185 lines
7.0 KiB
Java
185 lines
7.0 KiB
Java
// Script to export decompiled C code from Ghidra
|
|
// @category _Reman3
|
|
// @menupath Reman3.Decompile All
|
|
|
|
import java.io.File;
|
|
import java.io.PrintWriter;
|
|
import java.io.StringWriter;
|
|
import java.util.ArrayList;
|
|
import java.util.HashSet;
|
|
import java.util.Hashtable;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
import java.util.Arrays;
|
|
import java.util.Dictionary;
|
|
|
|
import ghidra.app.decompiler.ClangFieldToken;
|
|
import ghidra.app.decompiler.ClangLine;
|
|
import ghidra.app.decompiler.ClangSyntaxToken;
|
|
import ghidra.app.decompiler.ClangToken;
|
|
import ghidra.app.decompiler.DecompileResults;
|
|
import ghidra.app.decompiler.PrettyPrinter;
|
|
import ghidra.app.script.GhidraScript;
|
|
import ghidra.program.model.address.Address;
|
|
import ghidra.program.model.data.AbstractStringDataType;
|
|
import ghidra.program.model.data.Array;
|
|
import ghidra.program.model.data.ArrayDataType;
|
|
import ghidra.program.model.data.BitFieldDataType;
|
|
import ghidra.program.model.data.DataType;
|
|
import ghidra.program.model.data.DataTypeComponent;
|
|
import ghidra.program.model.data.DataTypeManager;
|
|
import ghidra.program.model.data.EnumDataType;
|
|
import ghidra.program.model.data.PointerDataType;
|
|
import ghidra.program.model.data.ProgramBasedDataTypeManager;
|
|
import ghidra.program.model.data.Structure;
|
|
import ghidra.program.model.data.TypedefDataType;
|
|
import ghidra.program.model.listing.Function;
|
|
import ghidra.program.model.listing.VariableStorage;
|
|
import ghidra.program.model.pcode.HighFunction;
|
|
import ghidra.program.model.pcode.HighSymbol;
|
|
import ghidra.program.model.pcode.PcodeOp;
|
|
import ghidra.program.model.pcode.Varnode;
|
|
import ghidra.program.model.symbol.Symbol;
|
|
import ghidra.util.task.TaskMonitor;
|
|
import re3lib.*;
|
|
|
|
public class Decompile extends GhidraScript {
|
|
|
|
|
|
// void headerGuardPre(PrintWriter writer, String tag) {
|
|
// writer.println("#ifndef GH_GENERATED_" + tag + "_H");
|
|
// writer.println("#define GH_GENERATED_" + tag + "_H");
|
|
// writer.println();
|
|
// }
|
|
|
|
// void headerGuardPost(PrintWriter writer, String tag) {
|
|
// writer.println("#endif // GH_GENERATED_" + tag + "_H");
|
|
// }
|
|
|
|
// void dumpGlobals(Hashtable<String, GlobalRec> globalSymbols) throws Exception {
|
|
// File globalSymbolsListH = new File(RecompileConfig.INSTANCE.outputDir, "gh_global.h");
|
|
// PrintWriter hwriter = new PrintWriter(globalSymbolsListH, "UTF-8");
|
|
// hwriter.println("// AUTO-GENERATED FILE ");
|
|
// headerGuardPre(hwriter, "GLOBALS");
|
|
// hwriter.println("#include <r3/binder/global.h>");
|
|
// hwriter.println();
|
|
|
|
// File globalSymbolsListC = new File(RecompileConfig.INSTANCE.outputDir, "gh_global.cxx");
|
|
// PrintWriter cwriter = new PrintWriter(globalSymbolsListC, "UTF-8");
|
|
// cwriter.println("// AUTO-GENERATED FILE ");
|
|
// cwriter.println("#include <r3/binder/global.h>");
|
|
// hwriter.println();
|
|
|
|
// for (GlobalRec sym : globalSymbols.values()) {
|
|
// HighSymbol highSym = sym.highSymbol;
|
|
// DataType dt = highSym.getDataType();
|
|
// String dataType = dt.getDisplayName();
|
|
// String sanitizedName = sanitizeFunctionName(highSym.getName());
|
|
// String name = highSym.getName();
|
|
// if (!sanitizedName.equals(name)) {
|
|
// println("Invalid global symbol name: " + name);
|
|
// name = sanitizedName;
|
|
// }
|
|
// Address addr = sym.address;
|
|
// // println("Symbol: " + symbol + " Addr: " + addr + " Size:" + symSize + " " +
|
|
// // storage.getSerializationString());
|
|
// try {
|
|
// String initBlk = " = ";
|
|
// boolean fullyDefinedType = false;
|
|
// if (dt instanceof AbstractStringDataType) {
|
|
// AbstractStringDataType sdt = (AbstractStringDataType) dt;
|
|
// dataType = "const char*";
|
|
// // String type
|
|
// initBlk += "\"" + escapeCString(readCString(addr, 2048)) + "\"";
|
|
// fullyDefinedType = true;
|
|
// } else if (dt instanceof PointerDataType) {
|
|
// PointerDataType pdt = (PointerDataType) dt;
|
|
// DataType baseType = pdt.getDataType();
|
|
// dataType = baseType.getDisplayName() + "*";
|
|
// initBlk += "(" + dataType + ")&GH_MEM(0x" + addr + ")";
|
|
// fullyDefinedType = true;
|
|
// }
|
|
// if (fullyDefinedType) {
|
|
// hwriter.println("extern " + dataType + " " + name + "; // " + addr);
|
|
// cwriter.println(dataType + " " + name + initBlk + "; // " + addr);
|
|
// } else {
|
|
// if (dt instanceof Array) {
|
|
// // println("Array: " + dt.getDisplayName() + " - " + addr + " - " +
|
|
// // dt.getClass().getSimpleName());
|
|
// Array adt = (Array) dt;
|
|
// DataType baseType = adt.getDataType();
|
|
// hwriter.println(
|
|
// "extern " + 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 + ");");
|
|
// }
|
|
// }
|
|
// } catch (Exception e) {
|
|
// println("Error processing global symbol: " + e);
|
|
// println("Symbol: " + highSym.getName() + " - " + addr + " - "
|
|
// + highSym.getHighFunction().getFunction().getName());
|
|
// }
|
|
// }
|
|
|
|
// headerGuardPost(hwriter, "GLOBALS");
|
|
// hwriter.close();
|
|
// cwriter.close();
|
|
// }
|
|
|
|
void decompileAll(List<Function> functions) throws Exception {
|
|
// Hashtable<String, GlobalRec> globalSymbols = new Hashtable<>();
|
|
|
|
// for (Function function : functions) {
|
|
// decompileFunction(globalSymbols, function);
|
|
// }
|
|
|
|
// dumpStructureTypes();
|
|
// dumpGlobals(globalSymbols);
|
|
}
|
|
|
|
@Override
|
|
public void run() throws Exception {
|
|
if (currentProgram == null) {
|
|
return;
|
|
}
|
|
|
|
RecompileConfig.INSTANCE = new RecompileConfig(this);
|
|
|
|
if (!new File(RecompileConfig.INSTANCE.outputDir).exists()) {
|
|
throw new Exception("Output directory does not exist: " + RecompileConfig.INSTANCE.outputDir);
|
|
}
|
|
|
|
// Make sure to create output folders
|
|
RecompileConfig.INSTANCE.dirDecompFix.mkdirs();
|
|
RecompileConfig.INSTANCE.dirDecompAuto.mkdirs();
|
|
RecompileConfig.INSTANCE.dirDecompRef.mkdirs();
|
|
|
|
// buildFunctionBlacklist();
|
|
|
|
List<Function> functions = new ArrayList<>();
|
|
|
|
Iterator<Function> functionsIt = currentProgram.getFunctionManager().getFunctions(true).iterator();
|
|
while (functionsIt.hasNext()) {
|
|
Function function = functionsIt.next();
|
|
// if (!shouldDecompileFunction(function)) {
|
|
// continue;
|
|
// }
|
|
|
|
functions.add(function);
|
|
}
|
|
|
|
decompileAll(functions);
|
|
}
|
|
|
|
String sanitizeFunctionName(String name) {
|
|
return name.replaceAll("[^a-zA-Z0-9_]", "_");
|
|
}
|
|
}
|