diff --git a/ghidra/ghidra_scripts/MSVC7Mangle.java b/ghidra/ghidra_scripts/MSVC7Mangle.java index 718ca2b..4657ef4 100644 --- a/ghidra/ghidra_scripts/MSVC7Mangle.java +++ b/ghidra/ghidra_scripts/MSVC7Mangle.java @@ -19,6 +19,7 @@ // @category Symbol import ghidra.app.script.GhidraScript; +import ghidra.program.flatapi.FlatProgramAPI; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSet; import ghidra.program.model.data.Array; @@ -53,6 +54,7 @@ import ghidra.program.model.data.WideCharDataType; import ghidra.program.model.listing.Data; import ghidra.program.model.listing.Function; import ghidra.program.model.listing.FunctionSignature; +import ghidra.program.model.listing.Instruction; import ghidra.program.model.symbol.Namespace; import ghidra.program.model.symbol.Reference; import ghidra.program.model.symbol.SourceType; @@ -74,16 +76,12 @@ public class MSVC7Mangle extends GhidraScript{ public void run() throws Exception { // Get selected ranges from arguments if invoked headless if (isRunningHeadless()) { - final String[] args = getScriptArgs(); final AddressSet addr = new AddressSet(); - for (int i = 0; i < args.length; i++) { - final String[] range = args[i].split("-"); - addr.add( - currentAddress.getAddress(range[0]), - currentAddress.getAddress(range[1]) - ); - } + Arrays.stream(getScriptArgs()).forEach(arg -> { + final String[] range = arg.split("-"); + addr.add(toAddr(range[0]), toAddr(range[1])); + }); setCurrentSelection(addr); } @@ -94,31 +92,62 @@ public class MSVC7Mangle extends GhidraScript{ while (iter.hasNext() && !monitor.isCancelled()) { final Symbol s = iter.next(); - // Skip if already mangled - if (s.getName().charAt(0) == '?') return; + mangle(s); - // Get mangled name - final String mangled = switch (s.getObject()) { - case Function f -> mangleFn (f); - case Data d -> mangleData(d, s.getName(true)); - default -> null; - }; - - // Apply new name - if (mangled != null) { - s.setName(mangled, SourceType.USER_DEFINED); - makeGlobal(s); + if ( + isRunningHeadless() && + s.getObject() instanceof Function f + ) { + // Also mangle everything referenced inside f + for ( + Instruction ins = getFirstInstruction(f); + ins != null && f.getBody().contains(ins.getAddress()); + ins = ins.getNext() + ) { + final Reference[] refs = ins.getReferencesFrom(); + for (int i = 0; i < refs.length; i++) { + final Symbol symbol = getSymbolAt(refs[i].getToAddress()); + if (symbol != null) mangle(symbol); + } + } } + } + } - // TODO: in headless mode, also mangle everything - // referenced by functions + private void mangle(final Symbol s) throws Exception { + /* Set the given symbol's name to its mangled version */ + // Skip if already mangled + if (s.getName().charAt(0) == '?') return; + + // Get mangled name + final String mangled = switch (s.getObject()) { + case Function f -> mangleFn (f); + case Data d -> mangleData(d, s.getName(true)); + default -> null; + }; + + // Apply new name + if (mangled != null) { + s.setName(mangled, SourceType.USER_DEFINED); + makeGlobal(s); + + if (s.getObject() instanceof Function f) { + // Also apply to target function if f is thunk + final Function thunked = f.getThunkedFunction(true); + if (thunked != null) { + final Symbol ts = thunked.getSymbol(); + ts.setName(mangled, SourceType.USER_DEFINED); + makeGlobal(ts); + } + } } } private String mangleFn(final Function f) throws Exception { /* Generate a mangled name for a function */ - // Special case for main() - if (f.getName(true).equals("main")) return "_main"; + // Special cases for main() + if (f.getName(true).equals("main" )) return "_main"; + if (f.getName(true).equals("___CxxFrameHandler")) return "___CxxFrameHandler"; final ArrayList dict = new ArrayList<>();