mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
GP-5146 fixed rttiUtil issue resulting from previous pdb anon fix. Main fix was to remove incorrect pdb secondary symbols causing rtti script to blow up. Also updated to remove known functions from other class possible const/dest lists. Also updated to remove ticks from pdb rtti instead of just removing the symbols and recreating. This fixed the missing _forParent symbols so also updated script to handle for parent case now that it is getting them.
This commit is contained in:
parent
0411db7e88
commit
8892384b71
3 changed files with 103 additions and 33 deletions
|
@ -120,7 +120,7 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
// They are either undefined bytes or code that is not in a function.
|
// They are either undefined bytes or code that is not in a function.
|
||||||
private static final boolean FIXUP_PROGRAM = true;
|
private static final boolean FIXUP_PROGRAM = true;
|
||||||
|
|
||||||
// bookmark all constructor/destructor functions figured out by this script
|
// bookmark all constructor/destructor functions recognized by script
|
||||||
private static final boolean BOOKMARK_FOUND_FUNCTIONS = true;
|
private static final boolean BOOKMARK_FOUND_FUNCTIONS = true;
|
||||||
|
|
||||||
// show a graph of class hierarchies after script is complete
|
// show a graph of class hierarchies after script is complete
|
||||||
|
@ -323,13 +323,10 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
getNumberOfConstructorsOrDestructors(recoveredClasses) +
|
getNumberOfConstructorsOrDestructors(recoveredClasses) +
|
||||||
" class member functions to assign.");
|
" class member functions to assign.");
|
||||||
|
|
||||||
if (!hasDebugSymbols) {
|
|
||||||
|
|
||||||
if (BOOKMARK_FOUND_FUNCTIONS) {
|
if (BOOKMARK_FOUND_FUNCTIONS) {
|
||||||
bookmarkFunctions(recoveredClasses);
|
bookmarkFunctions(recoveredClasses);
|
||||||
println("See Bookmark Manager for a list of functions by type.");
|
println("See Bookmark Manager for a list of functions by type.");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
callOptionalOutputMethods(recoveredClasses, out);
|
callOptionalOutputMethods(recoveredClasses, out);
|
||||||
|
|
||||||
|
@ -477,7 +474,8 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
//then this situation is not an issue - it indicates a copy relocation at the
|
//then this situation is not an issue - it indicates a copy relocation at the
|
||||||
//location of the special typeinfo vtable which is a use case that can be handled
|
//location of the special typeinfo vtable which is a use case that can be handled
|
||||||
Address address = r.getAddress();
|
Address address = r.getAddress();
|
||||||
Symbol symbolAtAddress = currentProgram.getSymbolTable().getSymbol(symbolName, address, currentProgram.getGlobalNamespace());
|
Symbol symbolAtAddress = currentProgram.getSymbolTable()
|
||||||
|
.getSymbol(symbolName, address, currentProgram.getGlobalNamespace());
|
||||||
if (symbolAtAddress != null) {
|
if (symbolAtAddress != null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -489,7 +487,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void analyzeProgramChanges(AddressSetView beforeChanges) throws Exception {
|
private void analyzeProgramChanges(AddressSetView beforeChanges) throws Exception {
|
||||||
|
|
||||||
AddressSetView addressSet = currentProgram.getChanges().getAddressSet();
|
AddressSetView addressSet = currentProgram.getChanges().getAddressSet();
|
||||||
|
|
|
@ -2562,7 +2562,11 @@ public class RecoveredClassHelper {
|
||||||
Function function = functionIterator.next();
|
Function function = functionIterator.next();
|
||||||
Namespace namespace = function.getParentNamespace();
|
Namespace namespace = function.getParentNamespace();
|
||||||
if (!namespace.equals(recoveredClass.getClassNamespace())) {
|
if (!namespace.equals(recoveredClass.getClassNamespace())) {
|
||||||
continue;
|
Symbol functionSymbol = function.getSymbol();
|
||||||
|
if (functionSymbol.getSource().equals(SourceType.IMPORTED)) {
|
||||||
|
functionIterator.remove(); // remove named functions belonging to other class
|
||||||
|
}
|
||||||
|
continue; // continue in either case to skip functions in other namespaces
|
||||||
}
|
}
|
||||||
String name = function.getName();
|
String name = function.getName();
|
||||||
if (name.equals(recoveredClass.getName())) {
|
if (name.equals(recoveredClass.getName())) {
|
||||||
|
@ -8465,7 +8469,8 @@ public class RecoveredClassHelper {
|
||||||
Symbol symbol = symbols.next();
|
Symbol symbol = symbols.next();
|
||||||
if (symbol.getName().equals("vftable") ||
|
if (symbol.getName().equals("vftable") ||
|
||||||
symbol.getName().substring(1).startsWith("vftable") ||
|
symbol.getName().substring(1).startsWith("vftable") ||
|
||||||
symbol.getName().contains("vftable_for_")) {
|
symbol.getName().contains("vftable_for_") ||
|
||||||
|
symbol.getName().contains("vftable{for")) {
|
||||||
vftableSymbols.add(symbol);
|
vftableSymbols.add(symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,8 @@ import ghidra.app.cmd.data.TypeDescriptorModel;
|
||||||
import ghidra.app.util.NamespaceUtils;
|
import ghidra.app.util.NamespaceUtils;
|
||||||
import ghidra.app.util.PseudoDisassembler;
|
import ghidra.app.util.PseudoDisassembler;
|
||||||
import ghidra.app.util.datatype.microsoft.MSDataTypeUtils;
|
import ghidra.app.util.datatype.microsoft.MSDataTypeUtils;
|
||||||
|
import ghidra.app.util.demangler.DemangledObject;
|
||||||
|
import ghidra.app.util.demangler.DemanglerUtil;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSetView;
|
import ghidra.program.model.address.AddressSetView;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
@ -73,29 +75,71 @@ public class RttiUtil {
|
||||||
|
|
||||||
SymbolTable symbolTable = program.getSymbolTable();
|
SymbolTable symbolTable = program.getSymbolTable();
|
||||||
|
|
||||||
// See if the symbol already exists for the RTTI data.
|
// See if the symbol already exists for the RTTI data
|
||||||
Symbol matchingSymbol = symbolTable.getSymbol(rttiSuffix, rttiAddress, classNamespace);
|
Symbol matchingSymbol = symbolTable.getSymbol(rttiSuffix, rttiAddress, classNamespace);
|
||||||
if (matchingSymbol != null) {
|
if (matchingSymbol != null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: This code was originally put here to skip applying labels the pdb put down if the
|
// check for similar symbol
|
||||||
// above check failed but symbols were similar. This check has been removed because of
|
DemangledObject matchingDemangledObject = null;
|
||||||
// cases where this check stopped the full namespace path from being created. The code is
|
SymbolIterator symbols = symbolTable.getSymbolsAsIterator(rttiAddress);
|
||||||
// here commented out because we might want to use this to do extra checking and possibly
|
for (Symbol symbol : symbols) {
|
||||||
// remove the similar symbol instead of leaving it as a secondary symbol.
|
String name = symbol.getName();
|
||||||
// Don't create it if a similar symbol already exists at the address of the data.
|
|
||||||
// SymbolIterator symbols = symbolTable.getSymbolsAsIterator(rttiAddress);
|
// if mangled get the matching demangled object if there is one and save for after loop
|
||||||
// for (Symbol symbol : symbols) {
|
// in case symbols are not demangled yet
|
||||||
// String name = symbol.getName();
|
DemangledObject demangledObject = DemanglerUtil.demangle(name);
|
||||||
// if (name.contains(rttiSuffix)) {
|
if (demangledObject != null && demangledObject.getName().contains(rttiSuffix)) {
|
||||||
// return false; // Similar symbol already exists.
|
matchingDemangledObject = demangledObject;
|
||||||
// }
|
continue;
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
// Similar symbol already exists - more checking/fixing needed
|
||||||
|
if (name.contains(rttiSuffix)) {
|
||||||
|
|
||||||
|
// check for differing namespace to correct pdb in rare cases
|
||||||
|
Namespace currentNamespace = symbol.getParentNamespace();
|
||||||
|
if (!currentNamespace.equals(classNamespace)) {
|
||||||
|
Msg.warn(program, "Removed incorrect pdb symbol: " + symbol.getName(true));
|
||||||
|
symbol.delete();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// if symbol contains the matching string and ticks, remove the ticks
|
||||||
|
if (replaceSymbolWithNoTicks(symbol)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it gets here then there were no demangled symbols that contained the rttisuffix
|
||||||
|
// indicating that the mangled matching symbol has not been demangled yet and needs to be
|
||||||
|
// demangled
|
||||||
|
if (matchingDemangledObject != null) {
|
||||||
|
|
||||||
|
String name = matchingDemangledObject.getName();
|
||||||
|
if (name.contains(rttiSuffix)) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Symbol symbol = symbolTable.createLabel(rttiAddress, name, classNamespace,
|
||||||
|
SourceType.IMPORTED);
|
||||||
|
// Set the symbol to be primary so that the demangler
|
||||||
|
// won't demangle again
|
||||||
|
symbol.setPrimary();
|
||||||
|
if (replaceSymbolWithNoTicks(symbol)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (InvalidInputException e) {
|
||||||
|
//fall through and make a symbol using the rttiSuffix string even though
|
||||||
|
// it might really be one with extra information
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if code gets here then no pdb info so have to make the symbol here
|
||||||
try {
|
try {
|
||||||
// Ignore imported mangled symbol because demangling would add tick marks into the name.
|
|
||||||
// The name created here is better. Set the symbol to be primary so that the demangler
|
|
||||||
// won't demangle.
|
|
||||||
Symbol symbol = symbolTable.createLabel(rttiAddress, rttiSuffix, classNamespace,
|
Symbol symbol = symbolTable.createLabel(rttiAddress, rttiSuffix, classNamespace,
|
||||||
SourceType.IMPORTED);
|
SourceType.IMPORTED);
|
||||||
symbol.setPrimary();
|
symbol.setPrimary();
|
||||||
|
@ -108,6 +152,30 @@ public class RttiUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to remove all ' and ` from symbol if it starts with `
|
||||||
|
* @param symbol the symbol
|
||||||
|
* @return true if the symbol has been replaced, false otherwise
|
||||||
|
*/
|
||||||
|
private static boolean replaceSymbolWithNoTicks(Symbol symbol) {
|
||||||
|
|
||||||
|
String name = symbol.getName();
|
||||||
|
if (name.startsWith("`")) {
|
||||||
|
name = name.replace("'", "").replace("`", "");
|
||||||
|
try {
|
||||||
|
symbol.setName(name, symbol.getSource());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (DuplicateNameException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (InvalidInputException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to promote the given namespace to a class namespace
|
* Method to promote the given namespace to a class namespace
|
||||||
* @param program the given program
|
* @param program the given program
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue