WIP Generate function stubs
This commit is contained in:
@@ -30,6 +30,8 @@ public class FunctionDumper {
|
||||
GlobalDumper globalDumper;
|
||||
HashSet<Address> functionAddrBlackList = new HashSet<>();
|
||||
|
||||
public boolean createdFile = false;
|
||||
|
||||
static final Pattern fieldAccessRegex = Pattern.compile("^_([0-9]+)_([0-9]+)_$");
|
||||
|
||||
public FunctionDumper(GhidraScript script, GlobalDumper globalDumper) {
|
||||
@@ -112,11 +114,15 @@ public class FunctionDumper {
|
||||
f0 = new File(RecompileConfig.INSTANCE.dirDecompAuto, fileName);
|
||||
if (f0.exists()) {
|
||||
f0.delete();
|
||||
} else {
|
||||
createdFile = true;
|
||||
}
|
||||
}
|
||||
|
||||
script.println("Processing " + function.getName() + " => " + f0.toString());
|
||||
|
||||
List<Function> externalFunctionCalls = new ArrayList<>();
|
||||
|
||||
DecompileResults decompRes = RecompileConfig.INSTANCE.decompCache.getOrInsert(function);
|
||||
try (PrintWriter writer2 = new PrintWriter(f0, "UTF-8")) {
|
||||
writer2.println("// AUTO-GENERATED FILE, MOVE TO 'gh_fix' FOLDER PREVENT OVERWRITING!!!!! ");
|
||||
@@ -213,6 +219,7 @@ public class FunctionDumper {
|
||||
headers.add("extern " + proto
|
||||
+ "; // " + calledFunction.getEntryPoint() + " // "
|
||||
+ calledFunction.getName());
|
||||
externalFunctionCalls.add(calledFunction);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -236,5 +243,39 @@ public class FunctionDumper {
|
||||
writer2.print(codeWriter.toString());
|
||||
writer2.println();
|
||||
}
|
||||
|
||||
// Possibly generate stubs for external functions
|
||||
for (Function externalFunction : externalFunctionCalls) {
|
||||
File f2 = new File(RecompileConfig.INSTANCE.dirDecompFix, fileName);
|
||||
File f3 = new File(RecompileConfig.INSTANCE.dirDecompAuto, fileName);
|
||||
if (f2.exists() || f3.exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
File f4 = new File(RecompileConfig.INSTANCE.dirDecompStub, fileName);
|
||||
script.println("Generating function stub for " + externalFunction.getName() + " => " + f4.toString());
|
||||
|
||||
try (PrintWriter writer2 = new PrintWriter(f4, "UTF-8")) {
|
||||
writer2.println("// AUTO-GENERATED FILE!!!!");
|
||||
writer2.println("// This function has yet to be decompiled using 'Dump Current Function' in ghidra");
|
||||
writer2.println("// with possible manualy fixes");
|
||||
writer2.println();
|
||||
writer2.println("#include <gh_auto_binder.h>");
|
||||
writer2.println("#include \"../gh_global.h\"");
|
||||
writer2.println("#include <stdexcept>");
|
||||
writer2.println();
|
||||
writer2.println("// " + externalFunction.getEntryPoint());
|
||||
writer2.println("// " + externalFunction.getName());
|
||||
writer2.println(externalFunction.getSignature().getPrototypeString(false) + " {");
|
||||
writer2.println(" // TODO: Implement this function");
|
||||
writer2
|
||||
.println(" throw std::runtime_error(\"Function not implemented: " + externalFunction.getName() + "\");");
|
||||
writer2.println("}");
|
||||
}
|
||||
|
||||
if (!f4.exists()) {
|
||||
createdFile = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@ import java.util.Map;
|
||||
|
||||
import javax.xml.datatype.DatatypeFactory;
|
||||
|
||||
import ghidra.app.cmd.label.AddLabelCmd;
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.app.services.DataTypeManagerService;
|
||||
import ghidra.program.model.address.Address;
|
||||
@@ -27,6 +28,8 @@ 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;
|
||||
import ghidra.program.model.symbol.Symbol;
|
||||
import ghidra.util.data.DataTypeParser;
|
||||
import ghidra.util.data.DataTypeParser.AllowedDataTypes;
|
||||
|
||||
@@ -181,8 +184,9 @@ public class GlobalDumper {
|
||||
initBlk += "(" + dataType + ")&GH_MEM(0x" + addr + ")";
|
||||
fullyDefinedType = true;
|
||||
}
|
||||
String linkagePrefix = "extern ";
|
||||
if (fullyDefinedType) {
|
||||
hwriter.println("extern " + dataType + " " + name + "; // " + addr);
|
||||
hwriter.println(linkagePrefix + dataType + " " + name + "; // " + addr);
|
||||
cwriter.println(dataType + " " + name + initBlk + "; // " + addr);
|
||||
} else {
|
||||
if (dt instanceof Array) {
|
||||
@@ -191,14 +195,14 @@ public class GlobalDumper {
|
||||
Array adt = (Array) dt;
|
||||
DataType baseType = adt.getDataType();
|
||||
hwriter.println(
|
||||
"extern " + baseType.getDisplayName() + "(&" + name + ")[" + adt.getNumElements() + "]; // " + addr);
|
||||
linkagePrefix + baseType.getDisplayName() + "(&" + name + ")[" + adt.getNumElements() + "]; // " + addr);
|
||||
cwriter.println(
|
||||
baseType.getDisplayName() + "(&" + name + ")[" + adt.getNumElements() + "] = *reinterpret_cast<"
|
||||
+ baseType.getDisplayName() + "(*)[" + adt.getNumElements() + "]>(GH_MEM(0x" + addr + "));");
|
||||
} else {
|
||||
String refTypeStr = dt.getDisplayName() + "&";
|
||||
hwriter.println("extern " + refTypeStr + " " + name + "; // " + addr);
|
||||
cwriter.println(dataType + " " + name + "= (" + refTypeStr + ") GH_MEM(0x" + addr + ");");
|
||||
hwriter.println(linkagePrefix + refTypeStr + " " + name + "; // " + addr);
|
||||
cwriter.println(refTypeStr + " " + name + "= (" + refTypeStr + ") GH_MEM(0x" + addr + ");");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@@ -233,4 +237,23 @@ public class GlobalDumper {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void sanitizeGlobalSymbols() {
|
||||
for (GlobalRec global : globalAddrs.values()) {
|
||||
String sanitizedName = Utils.sanitizeIdentifier(global.name);
|
||||
if (!sanitizedName.equals(global.name)) {
|
||||
Symbol symbol = script.getSymbolAt(global.address);
|
||||
if (symbol != null) {
|
||||
script.println("Renaming global symbol: " + global.name + " -> " + sanitizedName);
|
||||
AddLabelCmd cmd = new AddLabelCmd(global.address, sanitizedName,
|
||||
symbol.getParentNamespace(),
|
||||
SourceType.USER_DEFINED);
|
||||
if (!cmd.applyTo(script.getCurrentProgram())) {
|
||||
script.println("Error renaming symbol: " + cmd.getStatusMsg());
|
||||
}
|
||||
global.name = sanitizedName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package re3lib;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.jar.ResourceFile;
|
||||
import ghidra.app.decompiler.DecompInterface;
|
||||
@@ -27,10 +28,20 @@ public class RecompileConfig {
|
||||
// The manually decompiled files (will not be overwritten by the auto
|
||||
// decompiler)
|
||||
public final File dirDecompFix;
|
||||
// The automatically generated files get written here in case a gh_fix entry exists
|
||||
// The automatically generated files get written here in case a gh_fix entry
|
||||
// exists
|
||||
// usable for referencing the modified function against the auto-decompiled one
|
||||
public final File dirDecompRef;
|
||||
|
||||
// The path for generated function stubs, for yet-to-be-compiled functions
|
||||
// Usefully for testing a part of the recompiled code without linker errors
|
||||
public final File dirDecompStub;
|
||||
|
||||
// The CMake timestamp file, automatically touched sometimes to trigger a
|
||||
// reconfigure
|
||||
// mostly when adding new files to the project
|
||||
public final File cmakeTimestampFile;
|
||||
|
||||
public final Program currentProgram;
|
||||
public final DecompileCache decompCache;
|
||||
|
||||
@@ -54,6 +65,9 @@ public class RecompileConfig {
|
||||
dirDecompAuto = new File(outputDir, "gh_auto");
|
||||
dirDecompFix = new File(outputDir, "gh_fix");
|
||||
dirDecompRef = new File(outputDir, "gh_ref");
|
||||
dirDecompStub = new File(outputDir, "gh_stub");
|
||||
|
||||
cmakeTimestampFile = new File(outputDir, "gh_cmake_timestamp");
|
||||
|
||||
currentProgram = script.getCurrentProgram();
|
||||
|
||||
@@ -66,5 +80,16 @@ public class RecompileConfig {
|
||||
dirDecompAuto.mkdirs();
|
||||
dirDecompFix.mkdirs();
|
||||
dirDecompRef.mkdirs();
|
||||
dirDecompStub.mkdirs();
|
||||
}
|
||||
|
||||
public void touchCMakeTimestamp() {
|
||||
try {
|
||||
if (!cmakeTimestampFile.exists()) {
|
||||
cmakeTimestampFile.createNewFile();
|
||||
}
|
||||
cmakeTimestampFile.setLastModified(System.currentTimeMillis());
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user