mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-10 05:39:36 +08:00
Merge remote-tracking branch 'origin/GP-809_ghidra1_DemangledThunks--SQUASHED' into patch
This commit is contained in:
+39
-9
@@ -18,8 +18,7 @@ package ghidra.app.plugin.core.analysis;
|
||||
import ghidra.app.services.*;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
@@ -41,6 +40,9 @@ import ghidra.util.task.TaskMonitor;
|
||||
*/
|
||||
public abstract class AbstractDemanglerAnalyzer extends AbstractAnalyzer {
|
||||
|
||||
private static final AddressSetView EXTERNAL_SET = new AddressSet(
|
||||
AddressSpace.EXTERNAL_SPACE.getMinAddress(), AddressSpace.EXTERNAL_SPACE.getMaxAddress());
|
||||
|
||||
public AbstractDemanglerAnalyzer(String name, String description) {
|
||||
super(name, description, AnalyzerType.BYTE_ANALYZER);
|
||||
setPriority(AnalysisPriority.DATA_TYPE_PROPOGATION.before().before().before());
|
||||
@@ -59,6 +61,8 @@ public abstract class AbstractDemanglerAnalyzer extends AbstractAnalyzer {
|
||||
|
||||
try {
|
||||
monitor.setIndeterminate(true);
|
||||
// NOTE: demangling of Externals may lose mangled name if original
|
||||
// imported name has already been assigned to the External symbol (e.g., ordinal based name)
|
||||
return doAdded(program, set, monitor, log);
|
||||
}
|
||||
finally {
|
||||
@@ -75,18 +79,42 @@ public abstract class AbstractDemanglerAnalyzer extends AbstractAnalyzer {
|
||||
log.appendMsg(getName(), "Invalid demangler options--cannot demangle");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Demangle external symbols after memory symbols.
|
||||
// This is done to compensate for cases where the mangled name on externals may be lost
|
||||
// after demangling when an alternate Ordinal symbol exists. The external mangled
|
||||
// name is helpful in preserving thunk relationships when a mangled symbols have been
|
||||
// placed on a thunk. It is assumed that analyzer is presented with entire
|
||||
// EXTERNAL space in set (all or none).
|
||||
boolean demangleExternals = set.contains(EXTERNAL_SET.getMinAddress());
|
||||
if (demangleExternals) {
|
||||
set = set.subtract(EXTERNAL_SET);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
String baseMonitorMessage = monitor.getMessage();
|
||||
int memorySymbolCount =
|
||||
demangleSymbols(program, set, 0, baseMonitorMessage, options, log, monitor);
|
||||
if (demangleExternals) {
|
||||
// process external symbols last
|
||||
demangleSymbols(program, EXTERNAL_SET, memorySymbolCount, baseMonitorMessage, options,
|
||||
log, monitor);
|
||||
}
|
||||
|
||||
String defaultMessage = monitor.getMessage();
|
||||
return true;
|
||||
}
|
||||
|
||||
private int demangleSymbols(Program program, AddressSetView set, int initialCount,
|
||||
String baseMonitorMessage, DemanglerOptions options, MessageLog log,
|
||||
TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
int count = initialCount;
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
SymbolIterator it = symbolTable.getPrimarySymbolIterator(set, true);
|
||||
while (it.hasNext()) {
|
||||
monitor.checkCanceled();
|
||||
|
||||
if (++count % 100 == 0) {
|
||||
monitor.setMessage(defaultMessage + " - " + count + " symbols");
|
||||
monitor.setMessage(baseMonitorMessage + " - " + count + " symbols");
|
||||
}
|
||||
|
||||
Symbol symbol = it.next();
|
||||
@@ -101,8 +129,7 @@ public abstract class AbstractDemanglerAnalyzer extends AbstractAnalyzer {
|
||||
apply(program, address, demangled, options, log, monitor);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,10 +179,13 @@ public abstract class AbstractDemanglerAnalyzer extends AbstractAnalyzer {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Someone has already added arguments or return to the function signature
|
||||
// Someone has already added arguments or return to the function signature.
|
||||
// Treatment of thunks must be handled later since thunk relationship may
|
||||
// need to be broken
|
||||
if (symbol.getSymbolType() == SymbolType.FUNCTION) {
|
||||
Function function = (Function) symbol.getObject();
|
||||
if (function.getSignatureSource().isHigherPriorityThan(SourceType.ANALYSIS)) {
|
||||
if (!function.isThunk() &&
|
||||
function.getSignatureSource().isHigherPriorityThan(SourceType.ANALYSIS)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+76
-5
@@ -349,14 +349,26 @@ public class DemangledFunction extends DemangledObject {
|
||||
|
||||
Function function = createFunction(program, address, options.doDisassembly(), monitor);
|
||||
if (function == null) {
|
||||
// no function whose signature we need to update
|
||||
// NOTE: this does not make much sense
|
||||
// renameExistingSymbol(program, address, symbolTable);
|
||||
// maybeCreateUndefined(program, address);
|
||||
// No function whose signature we need to update
|
||||
return false;
|
||||
}
|
||||
|
||||
//if existing function signature is user defined - add demangled label only
|
||||
if (function.isThunk()) {
|
||||
// If thunked function has same mangled name we can discard our
|
||||
// symbol if no other symbols at this address (i.e., rely entirely on
|
||||
// thunked function).
|
||||
// NOTE: mangled name on external may be lost once it is demangled.
|
||||
if (shouldThunkBePreserved(function)) {
|
||||
// Preserve thunk and remove mangled symbol. Allow to proceed normally by returning true.
|
||||
function.getSymbol().setName(null, SourceType.DEFAULT);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Break thunk relationship and continue applying demangle function below
|
||||
function.setThunkedFunction(null);
|
||||
}
|
||||
|
||||
// If existing function signature is user defined - add demangled label only
|
||||
boolean makePrimary = (function.getSignatureSource() != SourceType.USER_DEFINED);
|
||||
|
||||
Symbol demangledSymbol =
|
||||
@@ -395,6 +407,65 @@ public class DemangledFunction extends DemangledObject {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if existing thunk relationship should be preserved and mangled symbol
|
||||
* discarded. This is the case when the thunk function mangled name matches
|
||||
* the thunked function since we want to avoid duplicate symbol names.
|
||||
* @param thunkFunction thunk function with a mangled symbol which is currently
|
||||
* being demangled.
|
||||
* @return true if thunk should be preserved and mangled symbol discarded, otherwise
|
||||
* false if thunk relationship should be eliminated and demangled function information
|
||||
* should be applied as normal.
|
||||
*/
|
||||
private boolean shouldThunkBePreserved(Function thunkFunction) {
|
||||
Program program = thunkFunction.getProgram();
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
if (thunkFunction.getSymbol().isExternalEntryPoint()) {
|
||||
return false; // entry point should retain its own symbol
|
||||
}
|
||||
Symbol[] symbols = symbolTable.getSymbols(thunkFunction.getEntryPoint());
|
||||
if (symbols.length > 1) {
|
||||
return false; // too many symbols present to preserve thunk
|
||||
}
|
||||
// NOTE: order of demangling unknown - thunked function may, or may not, have
|
||||
// already been demangled
|
||||
Function thunkedFunction = thunkFunction.getThunkedFunction(true);
|
||||
if (mangled.equals(thunkedFunction.getName())) {
|
||||
// thunked function has matching mangled name
|
||||
return true;
|
||||
}
|
||||
if (thunkedFunction.isExternal()) {
|
||||
if (thunkedFunction.getParentNamespace() instanceof Library) {
|
||||
// Thunked function does not have mangled name, if it did it would have
|
||||
// matched name check above or now reside in a different namespace
|
||||
return false;
|
||||
}
|
||||
// assume external contained with specific namespace
|
||||
ExternalLocation externalLocation =
|
||||
program.getExternalManager().getExternalLocation(thunkedFunction.getSymbol());
|
||||
String originalImportedName = externalLocation.getOriginalImportedName();
|
||||
if (originalImportedName == null) {
|
||||
// assume external manually manipulated without use of mangled name
|
||||
return false;
|
||||
}
|
||||
if (mangled.equals(externalLocation.getOriginalImportedName())) {
|
||||
// matching mangled name also resides at thunked function location
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: carefully compare signature in absense of matching mangled name
|
||||
return false;
|
||||
}
|
||||
|
||||
if (symbolTable.getSymbol(mangled, thunkedFunction.getEntryPoint(),
|
||||
program.getGlobalNamespace()) != null) {
|
||||
// matching mangled name also resides at thunked function location
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasVarArgs() {
|
||||
if (parameters.isEmpty()) {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user