Compare commits

..

No commits in common. "0e84f9ab1f87006f816dcb42a077273c6e3a9fd7" and "e9b0c3c6bcaee5e89114a1099b555f7a9245f262" have entirely different histories.

2 changed files with 20 additions and 55 deletions

View file

@ -65,11 +65,8 @@ delink() {
export MSYS_NO_PATHCONV=1
"$1/support/analyzeHeadless$suffix" "$2" "$3"\
-readOnly\
-process default.xbe\
-noanalysis\
-scriptPath ghidra_scripts\
-preScript MSVC7Mangle.java $4\
-postScript DelinkProgram.java\
/exporter 'COFF relocatable object'\
$(printf "/include-range %s " $4)\

View file

@ -7,20 +7,17 @@
// permissive form (public, non-const, etc.).
//
// Special symbol names like "operator new" or "scalar deleting destructor"
// are given unique mangling. To properly mangle these, name them as they
// are given unique mangling. To properly demangle these, name them as they
// appear in objdiff, replacing spaces with underscores, e.g. "operator_new"
// and "`scalar_deleting_destructor'" (notice the ` and ').
//
// This script can be called in headless mode with the address ranges to mangle
// as arguments, e.g. 0x1234-0x5678. Any symbols referenced by functions being
// mangled will also be mangled in this mode (so that the references are
// correct if the mangling is done in preparation for exporting functions).
//
// @category Symbol
import ghidra.app.script.GhidraScript;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.listing.Data;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.FunctionSignature;
import ghidra.program.model.data.Array;
import ghidra.program.model.data.BooleanDataType;
import ghidra.program.model.data.CharDataType;
@ -41,7 +38,6 @@ import ghidra.program.model.data.StringDataInstance;
import ghidra.program.model.data.Structure;
import ghidra.program.model.data.TerminatedUnicodeDataType;
import ghidra.program.model.data.TypeDef;
import ghidra.program.model.data.Undefined;
import ghidra.program.model.data.Union;
import ghidra.program.model.data.UnsignedCharDataType;
import ghidra.program.model.data.UnsignedIntegerDataType;
@ -50,9 +46,6 @@ import ghidra.program.model.data.UnsignedLongLongDataType;
import ghidra.program.model.data.UnsignedShortDataType;
import ghidra.program.model.data.VoidDataType;
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.symbol.Namespace;
import ghidra.program.model.symbol.Reference;
import ghidra.program.model.symbol.SourceType;
@ -72,22 +65,6 @@ import java.util.zip.CRC32;
public class MSVC7Mangle extends GhidraScript{
@Override
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])
);
}
setCurrentSelection(addr);
}
final SymbolIterator iter = currentProgram.getSymbolTable()
.getPrimarySymbolIterator(currentSelection, true);
@ -109,9 +86,6 @@ public class MSVC7Mangle extends GhidraScript{
s.setName(mangled, SourceType.USER_DEFINED);
makeGlobal(s);
}
// TODO: in headless mode, also mangle everything
// referenced by functions
}
}
@ -264,29 +238,24 @@ public class MSVC7Mangle extends GhidraScript{
}
private boolean isVirtual(final Function f) {
/* Determine whether a method is virtual
We essentially check whether any references are from a vtable or a
scalar deleting destructor.
/* Attempt to determine whether a method is virtual
We essentially try to figure out if any references are from a vtable
by checking if they lie in non-executable memory, or from a scalar
deleting destructor.
*/
final Reference[] refs = getReferencesTo(f.getEntryPoint());
for (int i = 0; i < refs.length; i++) {
final Data data = getDataContaining (refs[i].getFromAddress());
final Function func = getFunctionContaining(refs[i].getFromAddress());
final Address addr = refs[i].getFromAddress();
final Optional<String> caller = Optional.ofNullable(getFunctionContaining(addr))
.map(x -> x.getName(false));
if (data != null) {
final String name = getSymbolAt(data.getRoot()
.getAddress()).getName(false);
if (
name.equals("`vftable'") ||
name.startsWith("??_7")
) return true;
} else if (func != null) {
final String name = func.getName(false);
if (
name.equals("`scalar_deleting_destructor'") ||
name.startsWith("??_G")
) return true;
}
if (
!getMemoryBlock(addr).isExecute() ||
caller.map(x -> x.equals("`scalar_deleting_destructor'"))
.orElse(false) ||
caller.map(x -> x.startsWith("??_G")) // From mangled name
.orElse(false)
) return true;
}
return false;
@ -336,7 +305,7 @@ public class MSVC7Mangle extends GhidraScript{
*/
if (t == null) throw new Exception (
"A data type was reported as null. Ensure that all " +
"data types in the code/data to mangle have been " +
"data types in the demangled code/data have been " +
"defined."
);
@ -367,8 +336,7 @@ public class MSVC7Mangle extends GhidraScript{
case Array a -> "PA" + mangleArrDims(a) + mangleType(arrType(a), dict);
case FunctionSignature f -> mangleFnType(f, dict);
case TypeDef d -> mangleType(d.getBaseDataType(), dict);
case DefaultDataType _ -> throw new Exception ("Encountered data marked \"undefined\". Ensure that all data types in the code/data to mangle have been defined.");
case Undefined _ -> throw new Exception ("Encountered data marked \"undefined\". Ensure that all data types in the code/data to mangle have been defined.");
case DefaultDataType _ -> throw new Exception ("Encountered data marked \"undefined\". All data types must be defined.");
default -> throw new Exception ("Unknown type \"" + t.getClass().getName() + "\"");
};
}