Update readme and rename config java

This commit is contained in:
Guus Waals 2025-05-29 16:31:55 +08:00
parent d7de3deb59
commit fd7f151b3c
15 changed files with 127 additions and 77 deletions

View File

@ -150,16 +150,16 @@ public class Decompile extends GhidraScript {
return;
}
RecompileConfig.INSTANCE = new RecompileConfig(this);
RemanConfig.INSTANCE = new RemanConfig(this);
if (!new File(RecompileConfig.INSTANCE.outputDir).exists()) {
throw new Exception("Output directory does not exist: " + RecompileConfig.INSTANCE.outputDir);
if (!new File(RemanConfig.INSTANCE.outputDir).exists()) {
throw new Exception("Output directory does not exist: " + RemanConfig.INSTANCE.outputDir);
}
// Make sure to create output folders
RecompileConfig.INSTANCE.dirDecompFix.mkdirs();
RecompileConfig.INSTANCE.dirDecompAuto.mkdirs();
RecompileConfig.INSTANCE.dirDecompRef.mkdirs();
RemanConfig.INSTANCE.dirDecompFix.mkdirs();
RemanConfig.INSTANCE.dirDecompAuto.mkdirs();
RemanConfig.INSTANCE.dirDecompRef.mkdirs();
// buildFunctionBlacklist();

View File

@ -6,13 +6,13 @@ import ghidra.app.script.GhidraScript;
import ghidra.program.model.listing.Function;
import re3lib.FunctionDumper;
import re3lib.GlobalDumper;
import re3lib.RecompileConfig;
import re3lib.RemanConfig;
public class DumpCurrentFunction extends GhidraScript {
@Override
public void run() throws Exception {
RecompileConfig.INSTANCE = new RecompileConfig(this);
RecompileConfig.INSTANCE.createDirectories();
RemanConfig.INSTANCE = new RemanConfig(this);
RemanConfig.INSTANCE.createDirectories();
GlobalDumper globalDumper = new GlobalDumper(this);
globalDumper.loadGlobalManifest();
@ -26,7 +26,7 @@ public class DumpCurrentFunction extends GhidraScript {
}
if (functionDumper.createdFile)
RecompileConfig.INSTANCE.touchCMakeTimestamp();
RemanConfig.INSTANCE.touchCMakeTimestamp();
globalDumper.dumpGlobals();
globalDumper.saveGlobalManifest();

View File

@ -12,7 +12,7 @@ import ghidra.program.model.listing.Function;
import re3lib.FunctionDumper;
import re3lib.GlobalDumper;
import re3lib.PCallTracer;
import re3lib.RecompileConfig;
import re3lib.RemanConfig;
import re3lib.TypeDumper;
public class DumpCurrentFunctionN extends GhidraScript {
@ -43,8 +43,8 @@ public class DumpCurrentFunctionN extends GhidraScript {
@Override
public void run() throws Exception {
RecompileConfig.INSTANCE = new RecompileConfig(this);
RecompileConfig.INSTANCE.createDirectories();
RemanConfig.INSTANCE = new RemanConfig(this);
RemanConfig.INSTANCE.createDirectories();
GlobalDumper globalDumper = new GlobalDumper(this);
globalDumper.loadGlobalManifest();

View File

@ -10,14 +10,14 @@ import ghidra.program.model.listing.Function;
import re3lib.FunctionDumper;
import re3lib.GlobalDumper;
import re3lib.PCallTracer;
import re3lib.RecompileConfig;
import re3lib.RemanConfig;
import re3lib.TypeDumper;
public class DumpCurrentFunctionRecursive extends GhidraScript {
@Override
public void run() throws Exception {
RecompileConfig.INSTANCE = new RecompileConfig(this);
RecompileConfig.INSTANCE.createDirectories();
RemanConfig.INSTANCE = new RemanConfig(this);
RemanConfig.INSTANCE.createDirectories();
GlobalDumper globalDumper = new GlobalDumper(this);
globalDumper.loadGlobalManifest();
@ -65,7 +65,7 @@ public class DumpCurrentFunctionRecursive extends GhidraScript {
}
if (functionDumper.createdFile)
RecompileConfig.INSTANCE.touchCMakeTimestamp();
RemanConfig.INSTANCE.touchCMakeTimestamp();
globalDumper.dumpGlobals();
globalDumper.saveGlobalManifest();

View File

@ -7,7 +7,7 @@ import java.io.FileOutputStream;
import java.io.PrintWriter;
import ghidra.app.script.GhidraScript;
import ghidra.program.model.address.Address;
import re3lib.RecompileConfig;
import re3lib.RemanConfig;
public class ExportData extends GhidraScript {
@ -16,16 +16,16 @@ public class ExportData extends GhidraScript {
if (currentProgram == null) {
return;
}
RecompileConfig.INSTANCE = new RecompileConfig(this);
RemanConfig.INSTANCE = new RemanConfig(this);
String dataFile = new File(RecompileConfig.INSTANCE.outputDir, "gh_datasegment.bin").toString();
String headerFile = new File(RecompileConfig.INSTANCE.outputDir, "gh_datasegment.h").toString();
String dataFile = new File(RemanConfig.INSTANCE.outputDir, "gh_datasegment.bin").toString();
String headerFile = new File(RemanConfig.INSTANCE.outputDir, "gh_datasegment.h").toString();
FileOutputStream dataOutputStream = new FileOutputStream(dataFile);
PrintWriter headerWriter = new PrintWriter(headerFile, "UTF-8");
Address startAddr = RecompileConfig.INSTANCE.staticMemoryBlockStart;
Address endAddr = RecompileConfig.INSTANCE.staticMemoryBlockEnd;
Address startAddr = RemanConfig.INSTANCE.staticMemoryBlockStart;
Address endAddr = RemanConfig.INSTANCE.staticMemoryBlockEnd;
// Dump all the memory to the bin file
int numBytes = (int) endAddr.subtract(startAddr);

View File

@ -4,13 +4,13 @@
import ghidra.app.script.GhidraScript;
import re3lib.GlobalDumper;
import re3lib.RecompileConfig;
import re3lib.RemanConfig;
public class SanitizeGlobalSymbols extends GhidraScript {
@Override
public void run() throws Exception {
RecompileConfig.INSTANCE = new RecompileConfig(this);
RecompileConfig.INSTANCE.createDirectories();
RemanConfig.INSTANCE = new RemanConfig(this);
RemanConfig.INSTANCE.createDirectories();
GlobalDumper globalDumper = new GlobalDumper(this);
globalDumper.loadGlobalManifest();

View File

@ -3,21 +3,7 @@
// @importpackage org.sqlite
import ghidra.app.script.GhidraScript;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.StandAloneDataTypeManager;
import re3lib.RecompileConfig;
import java.io.File;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import re3lib.RemanConfig;
// SQLite imports
import java.sql.Connection;
@ -32,7 +18,7 @@ import org.sqlite.JDBC;
public class Test extends GhidraScript {
@Override
public void run() throws Exception {
RecompileConfig.INSTANCE = new RecompileConfig(this);
RemanConfig.INSTANCE = new RemanConfig(this);
java.sql.DriverManager.registerDriver(new JDBC());
@ -41,7 +27,7 @@ public class Test extends GhidraScript {
}
private void testSQLite() throws Exception {
String dbPath = "jdbc:sqlite:" + RecompileConfig.INSTANCE.outputDir + "/functions.db";
String dbPath = "jdbc:sqlite:" + RemanConfig.INSTANCE.outputDir + "/functions.db";
try (Connection conn = DriverManager.getConnection(dbPath)) {
println("Connected to SQLite database: " + dbPath);

View File

@ -38,7 +38,7 @@ public class FunctionDatabase {
private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
String addressString = (String) in.readObject();
if (addressString != null) {
address = RecompileConfig.INSTANCE.script.getCurrentProgram().getAddressFactory().getAddress(addressString);
address = RemanConfig.INSTANCE.script.getCurrentProgram().getAddressFactory().getAddress(addressString);
}
name = (String) in.readObject();
}
@ -63,7 +63,7 @@ public class FunctionDatabase {
private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
String addressString = (String) in.readObject();
if (addressString != null) {
address = RecompileConfig.INSTANCE.script.getCurrentProgram().getAddressFactory().getAddress(addressString);
address = RemanConfig.INSTANCE.script.getCurrentProgram().getAddressFactory().getAddress(addressString);
}
name = (String) in.readObject();
String fileString = (String) in.readObject();
@ -81,7 +81,7 @@ public class FunctionDatabase {
public FunctionDatabase(GhidraScript script) {
this.script = script;
file = new File(RecompileConfig.INSTANCE.outputDir, "functions.dat");
file = new File(RemanConfig.INSTANCE.outputDir, "functions.dat");
}
public void load() throws Exception {
@ -237,7 +237,7 @@ public class FunctionDatabase {
if (madeAnyChanges) {
// Update CMake timestamp
RecompileConfig.INSTANCE.touchCMakeTimestamp();
RemanConfig.INSTANCE.touchCMakeTimestamp();
globalDumper.dumpGlobals();
globalDumper.saveGlobalManifest();

View File

@ -58,7 +58,7 @@ public class FunctionDumper {
}
void initFunctionBlacklist() {
functionAddrBlackList = Utils.loadFunctionBlacklist(RecompileConfig.INSTANCE.functionBlacklistPath);
functionAddrBlackList = Utils.loadFunctionBlacklist(RemanConfig.INSTANCE.functionBlacklistPath);
// Build blacklist if not loaded
if (functionAddrBlackList == null) {
@ -99,7 +99,7 @@ public class FunctionDumper {
}
if (modified) {
Utils.saveFunctionBlacklist(functionAddrBlackList, RecompileConfig.INSTANCE.functionBlacklistPath);
Utils.saveFunctionBlacklist(functionAddrBlackList, RemanConfig.INSTANCE.functionBlacklistPath);
}
}
}
@ -107,14 +107,14 @@ public class FunctionDumper {
public static boolean isDumpedFix(Function function) {
String sanitizedFunctionName = Utils.sanitizeIdentifier(function.getName());
String fileName = sanitizedFunctionName + ".cxx";
File f0 = new File(RecompileConfig.INSTANCE.dirDecompFix, fileName);
File f0 = new File(RemanConfig.INSTANCE.dirDecompFix, fileName);
return f0.exists();
}
public static boolean isDumpedAuto(Function function) {
String sanitizedFunctionName = Utils.sanitizeIdentifier(function.getName());
String fileName = sanitizedFunctionName + ".cxx";
File f0 = new File(RecompileConfig.INSTANCE.dirDecompAuto, fileName);
File f0 = new File(RemanConfig.INSTANCE.dirDecompAuto, fileName);
return f0.exists();
}
@ -124,19 +124,19 @@ public class FunctionDumper {
String fileName = sanitizedFunctionName + ".cxx";
// Remove the stub file, since we now use the decompiled file
File stubFile = new File(RecompileConfig.INSTANCE.dirDecompStub, fileName);
File stubFile = new File(RemanConfig.INSTANCE.dirDecompStub, fileName);
if (stubFile.exists()) {
script.println("Removing function stub " + stubFile);
stubFile.delete();
createdFile = true;
}
File f0 = new File(RecompileConfig.INSTANCE.dirDecompFix, fileName);
File f0 = new File(RemanConfig.INSTANCE.dirDecompFix, fileName);
if (f0.exists()) {
script.println("Func " + function.getName() + " skipped (gh_fix)");
f0 = new File(RecompileConfig.INSTANCE.dirDecompRef, fileName);
f0 = new File(RemanConfig.INSTANCE.dirDecompRef, fileName);
} else {
f0 = new File(RecompileConfig.INSTANCE.dirDecompAuto, fileName);
f0 = new File(RemanConfig.INSTANCE.dirDecompAuto, fileName);
if (f0.exists()) {
f0.delete();
} else {
@ -148,7 +148,7 @@ public class FunctionDumper {
List<Function> externalFunctionCalls = new ArrayList<>();
DecompileResults decompRes = RecompileConfig.INSTANCE.decompCache.getOrInsert(function);
DecompileResults decompRes = RemanConfig.INSTANCE.decompCache.getOrInsert(function);
try (PrintWriter writer2 = new PrintWriter(f0, "UTF-8")) {
writer2.println("// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!! ");
writer2.println();
@ -291,15 +291,15 @@ public class FunctionDumper {
for (Function externalFunction : externalFunctionCalls) {
String sanitizedExtFunctionName = Utils.sanitizeIdentifier(externalFunction.getName());
fileName = sanitizedExtFunctionName + ".cxx";
File f2 = new File(RecompileConfig.INSTANCE.dirDecompFix, fileName);
File f3 = new File(RecompileConfig.INSTANCE.dirDecompAuto, fileName);
File f2 = new File(RemanConfig.INSTANCE.dirDecompFix, fileName);
File f3 = new File(RemanConfig.INSTANCE.dirDecompAuto, fileName);
if (f2.exists() || f3.exists()) {
// script.println("Skipping external function: " + externalFunction.getName() +
// " - " + externalFunction.getEntryPoint());
continue;
}
File f4 = new File(RecompileConfig.INSTANCE.dirDecompStub, fileName);
File f4 = new File(RemanConfig.INSTANCE.dirDecompStub, fileName);
script.println("Generating function stub for " + externalFunction.getName() + " => " + f4.toString());
try (PrintWriter writer2 = new PrintWriter(f4, "UTF-8")) {

View File

@ -25,7 +25,6 @@ import ghidra.program.model.data.DataType;
import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.data.DataTypePath;
import ghidra.program.model.data.PointerDataType;
import ghidra.program.model.data.Undefined;
import ghidra.program.model.listing.Data;
import ghidra.program.model.pcode.HighSymbol;
import ghidra.program.model.symbol.SourceType;
@ -53,7 +52,7 @@ public class GlobalDumper {
public GlobalDumper(GhidraScript script) {
this.script = script;
manifestFile = new File(RecompileConfig.INSTANCE.outputDir, "globals.txt");
manifestFile = new File(RemanConfig.INSTANCE.outputDir, "globals.txt");
}
public void removeGlobalManifest() {
@ -108,8 +107,8 @@ public class GlobalDumper {
}
public void addGlobal(Address addr, HighSymbol sym) throws Exception {
if (addr.compareTo(RecompileConfig.INSTANCE.staticMemoryBlockStart) < 0
|| addr.compareTo(RecompileConfig.INSTANCE.staticMemoryBlockEnd) > 0) {
if (addr.compareTo(RemanConfig.INSTANCE.staticMemoryBlockStart) < 0
|| addr.compareTo(RemanConfig.INSTANCE.staticMemoryBlockEnd) > 0) {
throw new Exception("Global address out of range: " + addr);
}
@ -162,14 +161,14 @@ public class GlobalDumper {
}
public void dumpGlobals() throws Exception {
File globalSymbolsListH = new File(RecompileConfig.INSTANCE.outputDir, "gh_global.h");
File globalSymbolsListH = new File(RemanConfig.INSTANCE.outputDir, "gh_global.h");
PrintWriter hwriter = new PrintWriter(globalSymbolsListH, "UTF-8");
hwriter.println("// AUTO-GENERATED FILE ");
Utils.headerGuardPre(hwriter, "GLOBALS");
hwriter.println("#include <r3/binders/global.h>");
hwriter.println();
File globalSymbolsListC = new File(RecompileConfig.INSTANCE.outputDir, "gh_global.cxx");
File globalSymbolsListC = new File(RemanConfig.INSTANCE.outputDir, "gh_global.cxx");
PrintWriter cwriter = new PrintWriter(globalSymbolsListC, "UTF-8");
cwriter.println("// AUTO-GENERATED FILE ");
cwriter.println("#include <r3/binders/global.h>");

View File

@ -42,7 +42,7 @@ public class PCallTracer {
Program program;
public PCallTracer() {
this.script = RecompileConfig.INSTANCE.script;
this.script = RemanConfig.INSTANCE.script;
this.program = this.script.getCurrentProgram();
// this.decomp = RecompileConfig.INSTANCE.decompCache;
}

View File

@ -10,7 +10,9 @@ import ghidra.program.flatapi.FlatProgramAPI;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
public class RecompileConfig {
// A general configuration for the reman project
// including all paths, specific addresses and stuff
public class RemanConfig {
private static final String RECOMPILE_PREFIX = "game_re";
// Version control project root
@ -24,6 +26,9 @@ public class RecompileConfig {
public final Address staticMemoryBlockStart;
public final Address staticMemoryBlockEnd;
// The path to the database file
public final File databasePath;
// The automatically decompiled files
public final File dirDecompAuto;
// The manually decompiled files (will not be overwritten by the auto
@ -48,9 +53,9 @@ public class RecompileConfig {
public final GhidraScript script;
public static RecompileConfig INSTANCE;
public static RemanConfig INSTANCE;
public RecompileConfig(GhidraScript script) {
public RemanConfig(GhidraScript script) {
staticMemoryBlockStart = script.getCurrentProgram().getAddressFactory().getAddress("00597000");
staticMemoryBlockEnd = script.getCurrentProgram().getAddressFactory().getAddress("00843fff");

View File

@ -25,15 +25,15 @@ public class TypeDumper {
public TypeDumper(GhidraScript script) {
this.script = script;
currentProgram = script.getCurrentProgram();
RecompileConfig.INSTANCE = new RecompileConfig(script);
RemanConfig.INSTANCE = new RemanConfig(script);
}
public void run() throws Exception {
ProgramBasedDataTypeManager dtm = currentProgram.getDataTypeManager();
HashSet<String> typeBlacklist = Utils.loadSimpleBlacklist(RecompileConfig.INSTANCE.typeBlacklistPath);
HashSet<String> typeBlacklist = Utils.loadSimpleBlacklist(RemanConfig.INSTANCE.typeBlacklistPath);
HashSet<String> categoryPathBlacklist = Utils
.loadSimpleBlacklist(RecompileConfig.INSTANCE.categoryPathBlacklistPath);
.loadSimpleBlacklist(RemanConfig.INSTANCE.categoryPathBlacklistPath);
if (typeBlacklist == null) {
script.println("Building struct blacklist from existing data types");
@ -45,7 +45,7 @@ public class TypeDumper {
typeBlacklist.add(dt.getDisplayName());
}
}
Utils.saveStructBlacklist(typeBlacklist, RecompileConfig.INSTANCE.typeBlacklistPath);
Utils.saveStructBlacklist(typeBlacklist, RemanConfig.INSTANCE.typeBlacklistPath);
}
List<DataType> filteredTypes = new ArrayList<>();
@ -92,7 +92,7 @@ public class TypeDumper {
}
}
try (PrintWriter writer = new PrintWriter(new File(RecompileConfig.INSTANCE.outputDir, "gh_types.h"),
try (PrintWriter writer = new PrintWriter(new File(RemanConfig.INSTANCE.outputDir, "gh_types.h"),
"UTF-8")) {
Utils.headerGuardPre(writer, "STRUCTS");
writer.println("// AUTO-GENERATED FILE ");

View File

@ -51,7 +51,7 @@ public class Utils {
}
public static HashSet<Address> loadFunctionBlacklist(String path) {
GhidraScript script = RecompileConfig.INSTANCE.script;
GhidraScript script = RemanConfig.INSTANCE.script;
HashSet<Address> fnBlacklist = new HashSet<>();
File blacklistFile = new File(path);
try (Scanner scanner = new Scanner(blacklistFile)) {
@ -60,7 +60,7 @@ public class Utils {
// Strip comment
String line1 = line.split("//")[0].trim();
// Deserialize address
Address addr = RecompileConfig.INSTANCE.currentProgram.getAddressFactory().getAddress(line1);
Address addr = RemanConfig.INSTANCE.currentProgram.getAddressFactory().getAddress(line1);
fnBlacklist.add(addr);
}
script.println("Loaded blacklist with " + fnBlacklist.size() + " entries");
@ -71,7 +71,7 @@ public class Utils {
}
public static void saveFunctionBlacklist(HashSet<Address> fnBlacklist, String path) {
GhidraScript script = RecompileConfig.INSTANCE.script;
GhidraScript script = RemanConfig.INSTANCE.script;
File blacklistFile = new File(path);
try (PrintWriter writer = new PrintWriter(blacklistFile)) {
for (Address addr : fnBlacklist) {

View File

@ -11,3 +11,63 @@ The decompile database is a sqlite database that contains a list of all files th
To generate the database from the current set of files, run the scan_sources script in the /game_re folder.
Make sure you have set up the tooling by running the /tooling/setup script.
## IDE Notes
This should work with the redhat java plugin for vscode, you however need to manually add the referenced libraries to the settings, like so:
```json
{
"java.project.referencedLibraries": [
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\Base\\lib\\Base.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\Decompiler\\lib\\Decompiler.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\BSim\\lib\\BSim.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\BSimFeatureVisualizer\\lib\\BSimFeatureVisualizer.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\Base\\lib\\Base.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\BytePatterns\\lib\\BytePatterns.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\ByteViewer\\lib\\ByteViewer.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\CodeCompare\\lib\\CodeCompare.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\DebugUtils\\lib\\DebugUtils.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\Decompiler\\lib\\Decompiler.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\DecompilerDependent\\lib\\DecompilerDependent.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\FileFormats\\lib\\FileFormats.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\FunctionGraph\\lib\\FunctionGraph.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\FunctionGraphDecompilerExtension\\lib\\FunctionGraphDecompilerExtension.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\FunctionID\\lib\\FunctionID.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\GhidraGo\\lib\\GhidraGo.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\GhidraServer\\lib\\GhidraServer.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\GnuDemangler\\lib\\GnuDemangler.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\GraphFunctionCalls\\lib\\GraphFunctionCalls.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\GraphServices\\lib\\GraphServices.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\MicrosoftCodeAnalyzer\\lib\\MicrosoftCodeAnalyzer.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\MicrosoftDemangler\\lib\\MicrosoftDemangler.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\MicrosoftDmang\\lib\\MicrosoftDmang.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\PDB\\lib\\PDB.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\ProgramDiff\\lib\\ProgramDiff.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\ProgramGraph\\lib\\ProgramGraph.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\Python\\lib\\Python.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\Recognizers\\lib\\Recognizers.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\Sarif\\lib\\Sarif.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\SourceCodeLookup\\lib\\SourceCodeLookup.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\SwiftDemangler\\lib\\SwiftDemangler.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\SystemEmulation\\lib\\SystemEmulation.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\VersionTracking\\lib\\VersionTracking.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\VersionTrackingBSim\\lib\\VersionTrackingBSim.jar",
"C:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Features\\WildcardAssembler\\lib\\WildcardAssembler.jar",
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\DB\\lib\\DB.jar",
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\Docking\\lib\\Docking.jar",
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\Emulation\\lib\\Emulation.jar",
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\FileSystem\\lib\\FileSystem.jar",
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\Generic\\lib\\Generic.jar",
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\Graph\\lib\\Graph.jar",
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\Gui\\lib\\Gui.jar",
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\Help\\lib\\Help.jar",
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\Project\\lib\\Project.jar",
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\Pty\\lib\\Pty.jar",
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\SoftwareModeling\\lib\\SoftwareModeling.jar",
"c:\\Projects\\ghidra_11.3.2_PUBLIC\\Ghidra\\Framework\\Utility\\lib\\Utility.jar",
"c:\\Projects\\R3\\java\\ghidra\\sqlite-jdbc-3.49.1.0.jar"
]
}
```