WIP
This commit is contained in:
parent
3e469475c9
commit
7090abf5a2
|
@ -0,0 +1,107 @@
|
|||
// Decompile selected function recursively (until a given number of new functions is reached)
|
||||
// @category _Reman3
|
||||
// @menupath Reman3.Dump N Functions
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.pcodeCPort.address.Address;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import re3lib.FunctionDumper;
|
||||
import re3lib.GlobalDumper;
|
||||
import re3lib.PCallTracer;
|
||||
import re3lib.RecompileConfig;
|
||||
import re3lib.TypeDumper;
|
||||
|
||||
public class DumpCurrentFunctionN extends GhidraScript {
|
||||
final int NumFunctions = 8;
|
||||
|
||||
class Entry {
|
||||
Function function;
|
||||
}
|
||||
class QueueEntry {
|
||||
Function function;
|
||||
List<Function> callees;
|
||||
}
|
||||
|
||||
HashSet<Address> visited = new HashSet<>();
|
||||
|
||||
QueueEntry enter(Function function) {
|
||||
if (visited.contains(function.getEntryPoint()))
|
||||
return null;
|
||||
|
||||
visited.add(function.getEntryPoint());
|
||||
|
||||
QueueEntry entry = new QueueEntry();
|
||||
entry.function = function;
|
||||
|
||||
function.getCalledFunctions(monitor);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
RecompileConfig.INSTANCE = new RecompileConfig(this);
|
||||
RecompileConfig.INSTANCE.createDirectories();
|
||||
|
||||
GlobalDumper globalDumper = new GlobalDumper(this);
|
||||
globalDumper.loadGlobalManifest();
|
||||
|
||||
FunctionDumper functionDumper = new FunctionDumper(this, globalDumper);
|
||||
|
||||
// PCallTracer tracer = new PCallTracer();
|
||||
// tracer.setBlacklist(functionDumper.functionAddrBlackList);
|
||||
// tracer.traceCalls(getFunctionContaining(currentAddress));
|
||||
|
||||
List<Address> queue = new ArrayList<>();
|
||||
|
||||
List<Function> functionsToDump = new ArrayList<>();
|
||||
List<Function> functionsToDumpNew = new ArrayList<>();
|
||||
for (Function func : tracer.out) {
|
||||
if (FunctionDumper.isDumpedFix(func))
|
||||
continue;
|
||||
|
||||
println("Dump: " + func.getName());
|
||||
functionsToDump.add(func);
|
||||
|
||||
if (!FunctionDumper.isDumpedAuto(func))
|
||||
functionsToDumpNew.add(func);
|
||||
}
|
||||
|
||||
if (!functionsToDump.isEmpty()) {
|
||||
String newOpt = "Only new (" + functionsToDumpNew.size() + ")";
|
||||
String okOpt = "Yes (" + functionsToDump.size() + ")";
|
||||
String choice = askChoice("Confirmation", "About to generate " + functionsToDump.size() + " functions ("
|
||||
+ functionsToDumpNew.size() + " new), continue?",
|
||||
new ArrayList<String>() {
|
||||
{
|
||||
add(okOpt);
|
||||
add(newOpt);
|
||||
add("No");
|
||||
}
|
||||
}, okOpt);
|
||||
if (choice == okOpt) {
|
||||
} else if (choice == newOpt) {
|
||||
functionsToDump = functionsToDumpNew;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Function func : functionsToDump) {
|
||||
functionDumper.dump(func);
|
||||
}
|
||||
|
||||
if (functionDumper.createdFile)
|
||||
RecompileConfig.INSTANCE.touchCMakeTimestamp();
|
||||
|
||||
globalDumper.dumpGlobals();
|
||||
globalDumper.saveGlobalManifest();
|
||||
}
|
||||
|
||||
// Dump types
|
||||
TypeDumper dumper = new TypeDumper(this);
|
||||
dumper.run();
|
||||
}
|
||||
}
|
|
@ -4,15 +4,22 @@ import java.util.ArrayList;
|
|||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import ghidra.app.decompiler.DecompileResults;
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.program.model.listing.FunctionManager;
|
||||
import ghidra.program.model.listing.Instruction;
|
||||
import ghidra.program.model.listing.InstructionIterator;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.pcode.HighFunction;
|
||||
import ghidra.program.model.pcode.PcodeOp;
|
||||
import ghidra.program.model.pcode.PcodeOpAST;
|
||||
import ghidra.program.model.pcode.Varnode;
|
||||
import ghidra.program.model.symbol.Reference;
|
||||
|
||||
public class PCallTracer {
|
||||
public class QueueItem {
|
||||
|
@ -30,38 +37,139 @@ public class PCallTracer {
|
|||
List<QueueItem> queue = new ArrayList<>();
|
||||
HashSet<Address> visited = new HashSet<>();
|
||||
|
||||
DecompileCache decomp;
|
||||
// DecompileCache decomp;
|
||||
GhidraScript script;
|
||||
Program program;
|
||||
|
||||
public PCallTracer() {
|
||||
this.script = RecompileConfig.INSTANCE.script;
|
||||
this.decomp = RecompileConfig.INSTANCE.decompCache;
|
||||
this.program = this.script.getCurrentProgram();
|
||||
// this.decomp = RecompileConfig.INSTANCE.decompCache;
|
||||
}
|
||||
|
||||
public void setBlacklist(HashSet<Address> blacklist) {
|
||||
this.visited = new HashSet<>(blacklist);
|
||||
}
|
||||
|
||||
void visit(HighFunction highFunction, int depth) {
|
||||
Iterator<PcodeOpAST> opIter = highFunction.getPcodeOps();
|
||||
while (opIter.hasNext()) {
|
||||
PcodeOpAST op = opIter.next();
|
||||
if (op.getOpcode() == PcodeOp.CALL) {
|
||||
Varnode target = op.getInput(0);
|
||||
if (target.isAddress()) {
|
||||
Address callAddr = target.getAddress();
|
||||
Function calledFunction = script.getFunctionAt(callAddr);
|
||||
if (calledFunction == null) {
|
||||
script.println("PCallTracer, called function not found: " + op.toString() + " - "
|
||||
+ highFunction.getFunction().getName());
|
||||
continue;
|
||||
}
|
||||
if (!visited.contains(calledFunction.getEntryPoint())) {
|
||||
queue.add(new QueueItem(calledFunction, depth + 1));
|
||||
}
|
||||
// public List<Address> getReferenceFromAddresses(Address address) {
|
||||
// Reference[] referencesFrom = script.getReferencesFrom(address);
|
||||
|
||||
// // get only the address references at the given address (ie no stack refs,
|
||||
// ...)
|
||||
// List<Address> refFromAddresses = new ArrayList<Address>();
|
||||
// for (Reference referenceFrom : referencesFrom) {
|
||||
// if (referenceFrom.isMemoryReference()) {
|
||||
// refFromAddresses.add(referenceFrom.getToAddress());
|
||||
// }
|
||||
// }
|
||||
|
||||
// return refFromAddresses;
|
||||
// }
|
||||
|
||||
public Function getReferencedFunction(Address address, boolean getThunkedFunction) {
|
||||
Reference[] referencesFrom = script.getReferencesFrom(address);
|
||||
|
||||
if (referencesFrom.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (Reference referenceFrom : referencesFrom) {
|
||||
Address referencedAddress = referenceFrom.getToAddress();
|
||||
if (referencedAddress == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Function function = script.getFunctionAt(referencedAddress);
|
||||
|
||||
if (function == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!getThunkedFunction) {
|
||||
return function;
|
||||
}
|
||||
|
||||
if (function.isThunk()) {
|
||||
function = function.getThunkedFunction(true);
|
||||
}
|
||||
return function;
|
||||
}
|
||||
|
||||
return null;
|
||||
// List<Address> referencesFrom = getReferenceFromAddresses(address);
|
||||
// if (referencesFrom.size() != 1) {
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// Address functionAddress = referencesFrom.get(0);
|
||||
|
||||
// Register lowBitCodeMode = program.getRegister("LowBitCodeMode");
|
||||
// if (lowBitCodeMode != null) {
|
||||
// long longValue = functionAddress.getOffset();
|
||||
// longValue = longValue & ~0x1;
|
||||
// functionAddress = functionAddress.getNewAddress(longValue);
|
||||
// }
|
||||
|
||||
// Function function = script.getFunctionAt(functionAddress);
|
||||
// if (function == null) {
|
||||
// // try to create function
|
||||
// function = script.createFunction(functionAddress, null);
|
||||
// if (function == null) {
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // if function is a thunk, get the thunked function
|
||||
// if (function.isThunk()) {
|
||||
// Function thunkedFunction = function.getThunkedFunction(true);
|
||||
// function = thunkedFunction;
|
||||
// }
|
||||
|
||||
// return function;
|
||||
}
|
||||
|
||||
void visitInstructions(Function function, int depth) {
|
||||
Set<Function> calledFunctions = new HashSet<Function>();
|
||||
|
||||
InstructionIterator instructions = script.getCurrentProgram()
|
||||
.getListing()
|
||||
.getInstructions(function.getBody(), true);
|
||||
while (instructions.hasNext()) {
|
||||
Instruction instruction = instructions.next();
|
||||
if (instruction.getFlowType().isCall()) {
|
||||
|
||||
FunctionManager functionManager = script.getCurrentProgram().getFunctionManager();
|
||||
Function calledFunction = getReferencedFunction(instruction.getMinAddress(), true);
|
||||
if (calledFunction == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!visited.contains(calledFunction.getEntryPoint())) {
|
||||
queue.add(new QueueItem(calledFunction, depth + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Iterator<PcodeOpAST> opIter = highFunction.getPcodeOps();
|
||||
// while (opIter.hasNext()) {
|
||||
// PcodeOpAST op = opIter.next();
|
||||
// if (op.getOpcode() == PcodeOp.CALL) {
|
||||
// Varnode target = op.getInput(0);
|
||||
// if (target.isAddress()) {
|
||||
// Address callAddr = target.getAddress();
|
||||
// Function calledFunction = script.getFunctionAt(callAddr);
|
||||
// if (calledFunction == null) {
|
||||
// script.println("PCallTracer, called function not found: " + op.toString() + "
|
||||
// - "
|
||||
// + highFunction.getFunction().getName());
|
||||
// continue;
|
||||
// }
|
||||
// if (!visited.contains(calledFunction.getEntryPoint())) {
|
||||
// queue.add(new QueueItem(calledFunction, depth + 1));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
void visit(Function function, int depth) {
|
||||
|
@ -70,8 +178,8 @@ public class PCallTracer {
|
|||
if (trace) {
|
||||
script.println("PCallTracer, visiting " + function.getName() + " (depth:" + depth + ")");
|
||||
}
|
||||
DecompileResults decompRes = decomp.getOrInsert(function);
|
||||
visit(decompRes.getHighFunction(), depth);
|
||||
// DecompileResults decompRes = decomp.getOrInsert(function);
|
||||
visitInstructions(function, depth);
|
||||
out.add(function);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue