mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-10 08:28:17 +08:00
Merge remote-tracking branch 'origin/GP-1073_ghidravore_checking_uses_of_getSymbols_address--SQUASHED'
This commit is contained in:
+7
@@ -326,6 +326,13 @@ public class DBTraceProgramViewSymbolTable implements SymbolTable {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolIterator getSymbolsAsIterator(Address addr) {
|
||||
Symbol[] symbols = getSymbols(addr);
|
||||
List<Symbol> list = Arrays.asList(symbols);
|
||||
return new SymbolIteratorAdapter(list.iterator());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Symbol[] getUserSymbols(Address addr) {
|
||||
try (LockHold hold = program.trace.lockRead()) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,58 +25,49 @@ import ghidra.program.model.symbol.*;
|
||||
|
||||
public class AutoRenameLabelsScript extends GhidraScript {
|
||||
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
if (currentSelection == null || currentSelection.isEmpty()) {
|
||||
println("No selection exists.");
|
||||
return;
|
||||
}
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
if (currentSelection == null || currentSelection.isEmpty()) {
|
||||
println("No selection exists.");
|
||||
return;
|
||||
}
|
||||
|
||||
String base = askString("Auto Rename Labels", "Enter label base name:");
|
||||
if (base == null) {
|
||||
println("No base value entered.");
|
||||
return;
|
||||
}
|
||||
String base = askString("Auto Rename Labels", "Enter label base name:");
|
||||
if (base == null) {
|
||||
println("No base value entered.");
|
||||
return;
|
||||
}
|
||||
|
||||
int num = 1;
|
||||
int num = 1;
|
||||
|
||||
AddressSetView view = currentSelection;
|
||||
if ((view == null) || (view.isEmpty())) return;
|
||||
AddressSetView view = currentSelection;
|
||||
if ((view == null) || (view.isEmpty()))
|
||||
return;
|
||||
|
||||
// Obtain the symbol table and listing from program
|
||||
SymbolTable symbolTable = currentProgram.getSymbolTable();
|
||||
// Obtain the symbol table and listing from program
|
||||
SymbolTable symbolTable = currentProgram.getSymbolTable();
|
||||
|
||||
// Get the addresses in the set.
|
||||
AddressIterator it = view.getAddresses(true);
|
||||
|
||||
CompoundCmd cmd = new CompoundCmd("Auto Rename Labels");
|
||||
while(it.hasNext()) {
|
||||
Address address = it.next();
|
||||
Symbol[] symbols = symbolTable.getSymbols(address);
|
||||
Symbol defaultSymbol = getDynamicSymbol( symbols );
|
||||
if ( defaultSymbol != null ) {
|
||||
cmd.add(new RenameLabelCmd(address, null, base+num++, SourceType.USER_DEFINED));
|
||||
}
|
||||
}
|
||||
if (cmd.size() > 0) {
|
||||
if (!cmd.applyTo(currentProgram)) {
|
||||
String msg = cmd.getStatusMsg();
|
||||
if (msg != null && msg.length() > 0) {
|
||||
setToolStatusMessage(msg, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
println("No default labels found in selection.");
|
||||
}
|
||||
}
|
||||
// Get the addresses in the set.
|
||||
AddressIterator it = view.getAddresses(true);
|
||||
|
||||
private Symbol getDynamicSymbol( Symbol[] symbols ) {
|
||||
for (int i=0;i<symbols.length;i++) {
|
||||
if ( symbols[i].getSource() == SourceType.DEFAULT ) {
|
||||
return symbols[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
CompoundCmd cmd = new CompoundCmd("Auto Rename Labels");
|
||||
while (it.hasNext()) {
|
||||
Address address = it.next();
|
||||
Symbol primary = symbolTable.getPrimarySymbol(address);
|
||||
if (primary != null && primary.getSource() == SourceType.DEFAULT) {
|
||||
cmd.add(new RenameLabelCmd(address, null, base + num++, SourceType.USER_DEFINED));
|
||||
}
|
||||
}
|
||||
if (cmd.size() > 0) {
|
||||
if (!cmd.applyTo(currentProgram)) {
|
||||
String msg = cmd.getStatusMsg();
|
||||
if (msg != null && msg.length() > 0) {
|
||||
setToolStatusMessage(msg, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
println("No default labels found in selection.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public class GccRttiAnalysisScript extends GhidraScript {
|
||||
symbolTable = currentProgram.getSymbolTable();
|
||||
|
||||
globalNamespace = (GlobalNamespace) currentProgram.getGlobalNamespace();
|
||||
|
||||
|
||||
// create the path for the data type manager root/ClassDataTypes folder
|
||||
classDataTypesCategoryPath =
|
||||
createDataTypeCategoryPath(CategoryPath.ROOT, DTM_CLASS_DATA_FOLDER_NAME);
|
||||
@@ -201,7 +201,7 @@ public class GccRttiAnalysisScript extends GhidraScript {
|
||||
// find the three special vtables and replace the incorrectly made array with
|
||||
// data types found in vtable
|
||||
boolean continueProcessing = createSpecialVtables();
|
||||
if(!continueProcessing) {
|
||||
if (!continueProcessing) {
|
||||
return;
|
||||
}
|
||||
// find all typeinfo symbols and get their class namespace and create RecoveredClass object
|
||||
@@ -264,9 +264,11 @@ public class GccRttiAnalysisScript extends GhidraScript {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(class_type_info_vtable == null && si_class_type_info_vtable == null && vmi_class_type_info_vtable == null) {
|
||||
println("Since there are no class typeinfo tables this program does not appear to have RTTI.");
|
||||
|
||||
if (class_type_info_vtable == null && si_class_type_info_vtable == null &&
|
||||
vmi_class_type_info_vtable == null) {
|
||||
println(
|
||||
"Since there are no class typeinfo tables this program does not appear to have RTTI.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -378,7 +380,7 @@ public class GccRttiAnalysisScript extends GhidraScript {
|
||||
|
||||
// Except for the first one which should have a symbol, if there is a symbol at the
|
||||
// address, stop making longs because it there are no references into the vtable longs
|
||||
if (offset > 0 && symbolTable.getSymbols(address).length > 0) {
|
||||
if (offset > 0 && symbolTable.getPrimarySymbol(address) != null) {
|
||||
return numLongs;
|
||||
}
|
||||
|
||||
@@ -499,8 +501,11 @@ public class GccRttiAnalysisScript extends GhidraScript {
|
||||
private void setIsGcc() {
|
||||
|
||||
isGcc =
|
||||
currentProgram.getCompilerSpec().getCompilerSpecID().getIdAsString().equalsIgnoreCase(
|
||||
"gcc");
|
||||
currentProgram.getCompilerSpec()
|
||||
.getCompilerSpecID()
|
||||
.getIdAsString()
|
||||
.equalsIgnoreCase(
|
||||
"gcc");
|
||||
}
|
||||
|
||||
private void createTypeinfoStructs(List<Symbol> typeinfoSymbols) throws CancelledException {
|
||||
@@ -684,7 +689,6 @@ public class GccRttiAnalysisScript extends GhidraScript {
|
||||
*/
|
||||
private void processVtables() throws Exception {
|
||||
|
||||
|
||||
// find all vtable symbols
|
||||
List<Symbol> listOfVtableSymbols = getListOfSymbolsInAddressSet(
|
||||
currentProgram.getAddressFactory().getAddressSet(), VTABLE_LABEL, false);
|
||||
@@ -700,7 +704,6 @@ public class GccRttiAnalysisScript extends GhidraScript {
|
||||
|
||||
processVtable(vtableAddress, vtableNamespace, true);
|
||||
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -756,7 +759,6 @@ public class GccRttiAnalysisScript extends GhidraScript {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int numFunctionPointers = getNumFunctionPointers(vftableAddress, true, true);
|
||||
|
||||
// if at least one function pointer make vftable label - the createVftable method will
|
||||
@@ -791,7 +793,6 @@ public class GccRttiAnalysisScript extends GhidraScript {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check for an internal vtable and make a symbol there if there is one
|
||||
// will process them later
|
||||
Address possibleInternalVtableAddress =
|
||||
@@ -1160,7 +1161,6 @@ public class GccRttiAnalysisScript extends GhidraScript {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Address findNextTypeinfoRef(Address startAddress) {
|
||||
|
||||
int offset = 0;
|
||||
@@ -1275,4 +1275,3 @@ public class GccRttiAnalysisScript extends GhidraScript {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -970,10 +970,11 @@ public class OperandReferenceAnalyzer extends AbstractAnalyzer {
|
||||
return false;
|
||||
}
|
||||
|
||||
// See if the tested address is contained in memory
|
||||
// if the reference is not in memory or to a well known location, then don't create it
|
||||
// because we are not sure it is correct
|
||||
if (!memory.contains(testAddr)) {
|
||||
Symbol syms[] = program.getSymbolTable().getSymbols(testAddr);
|
||||
if (syms == null || syms.length == 0 || syms[0].getSource() == SourceType.DEFAULT) {
|
||||
Symbol symbol = program.getSymbolTable().getPrimarySymbol(testAddr);
|
||||
if (symbol == null || symbol.getSource() == SourceType.DEFAULT) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+26
-16
@@ -56,7 +56,7 @@ public class ScalarOperandAnalyzer extends AbstractAnalyzer {
|
||||
private static final int MAX_NEG_ENTRIES = 32;
|
||||
|
||||
private int alignment = 4;
|
||||
|
||||
|
||||
private TaskMonitor monitor;
|
||||
|
||||
public ScalarOperandAnalyzer() {
|
||||
@@ -78,7 +78,8 @@ public class ScalarOperandAnalyzer extends AbstractAnalyzer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean added(Program program, AddressSetView set, TaskMonitor taskMonitor, MessageLog log) {
|
||||
public boolean added(Program program, AddressSetView set, TaskMonitor taskMonitor,
|
||||
MessageLog log) {
|
||||
int count = 0;
|
||||
|
||||
monitor = taskMonitor;
|
||||
@@ -88,14 +89,15 @@ public class ScalarOperandAnalyzer extends AbstractAnalyzer {
|
||||
// Evaluate each operand
|
||||
//
|
||||
Listing listing = program.getListing();
|
||||
|
||||
|
||||
InstructionIterator iter = listing.getInstructions(set, true);
|
||||
while (iter.hasNext() && !monitor.isCancelled()) {
|
||||
Instruction instr = iter.next();
|
||||
monitor.setProgress(++count);
|
||||
checkOperands(program, instr);
|
||||
}
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
monitor = null; // get rid of the reference to it
|
||||
}
|
||||
|
||||
@@ -123,22 +125,26 @@ public class ScalarOperandAnalyzer extends AbstractAnalyzer {
|
||||
try {
|
||||
switch (scalar.bitLength()) {
|
||||
case 8:
|
||||
if (program.getMemory().getByte(addr) == scalar.getSignedValue()) {
|
||||
if (program.getMemory().getByte(addr) == scalar
|
||||
.getSignedValue()) {
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
if (program.getMemory().getShort(addr) == scalar.getSignedValue()) {
|
||||
if (program.getMemory().getShort(addr) == scalar
|
||||
.getSignedValue()) {
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
if (program.getMemory().getInt(addr) == scalar.getSignedValue()) {
|
||||
if (program.getMemory().getInt(addr) == scalar
|
||||
.getSignedValue()) {
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
case 64:
|
||||
if (program.getMemory().getLong(addr) == scalar.getSignedValue()) {
|
||||
if (program.getMemory().getLong(addr) == scalar
|
||||
.getSignedValue()) {
|
||||
found = true;
|
||||
}
|
||||
break;
|
||||
@@ -162,7 +168,8 @@ public class ScalarOperandAnalyzer extends AbstractAnalyzer {
|
||||
}
|
||||
|
||||
// check the address in this space first
|
||||
if (addReference(program, instr, i, instr.getMinAddress().getAddressSpace(), scalar)) {
|
||||
if (addReference(program, instr, i, instr.getMinAddress().getAddressSpace(),
|
||||
scalar)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -209,10 +216,11 @@ public class ScalarOperandAnalyzer extends AbstractAnalyzer {
|
||||
return false;
|
||||
}
|
||||
|
||||
//check that memory contains the target address
|
||||
// if the reference is not in memory or to a well known location, then don't create it
|
||||
// because we are not sure it is correct
|
||||
if (!program.getMemory().contains(addr)) {
|
||||
Symbol syms[] = program.getSymbolTable().getSymbols(addr);
|
||||
if (syms == null || syms.length == 0 || syms[0].getSource() == SourceType.DEFAULT) {
|
||||
Symbol symbol = program.getSymbolTable().getPrimarySymbol(addr);
|
||||
if (symbol == null || symbol.getSource() == SourceType.DEFAULT) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -284,8 +292,9 @@ public class ScalarOperandAnalyzer extends AbstractAnalyzer {
|
||||
AddressTable.MINIMUM_SAFE_ADDRESS, relocationGuideEnabled);
|
||||
if (table != null) {
|
||||
// add in an offcut reference
|
||||
program.getReferenceManager().addOffsetMemReference(refInstr.getMinAddress(), offAddr,
|
||||
-entryLen, RefType.DATA, SourceType.ANALYSIS, opIndex);
|
||||
program.getReferenceManager()
|
||||
.addOffsetMemReference(refInstr.getMinAddress(), offAddr,
|
||||
-entryLen, RefType.DATA, SourceType.ANALYSIS, opIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -321,8 +330,9 @@ public class ScalarOperandAnalyzer extends AbstractAnalyzer {
|
||||
offAddr = lastGoodTable.getTopAddress();
|
||||
|
||||
// add in an offcut reference
|
||||
program.getReferenceManager().addOffsetMemReference(instr.getMinAddress(), offAddr,
|
||||
(i + 3) * entryLen, RefType.DATA, SourceType.ANALYSIS, opIndex);
|
||||
program.getReferenceManager()
|
||||
.addOffsetMemReference(instr.getMinAddress(), offAddr,
|
||||
(i + 3) * entryLen, RefType.DATA, SourceType.ANALYSIS, opIndex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -121,7 +121,7 @@ public class OperandLabelDialog extends DialogComponentProvider {
|
||||
// the presentation at the call or jump instruction, it doesn't matter which symbol of the
|
||||
// same name you pick.
|
||||
private Symbol findSymbol(SymbolTable symTable, String currentLabel, Address symAddr) {
|
||||
Symbol[] symbols = symTable.getSymbols(symAddr);
|
||||
SymbolIterator symbols = symTable.getSymbolsAsIterator(symAddr);
|
||||
for (Symbol symbol : symbols) {
|
||||
if (symbol.getName(true).equals(currentLabel)) {
|
||||
return symbol;
|
||||
|
||||
+4
-3
@@ -153,8 +153,9 @@ public class MakeStringsTask extends ProgramTask {
|
||||
|
||||
if (paddingLength != 0) {
|
||||
try {
|
||||
program.getListing().createData(address.add(length), new AlignmentDataType(),
|
||||
paddingLength);
|
||||
program.getListing()
|
||||
.createData(address.add(length), new AlignmentDataType(),
|
||||
paddingLength);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// don't care that padding failed
|
||||
@@ -241,7 +242,7 @@ public class MakeStringsTask extends ProgramTask {
|
||||
|
||||
private boolean labelAlreadyExists(Address addr, String name) {
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
Symbol[] symbols = symbolTable.getSymbols(addr);
|
||||
SymbolIterator symbols = symbolTable.getSymbolsAsIterator(addr);
|
||||
for (Symbol symbol : symbols) {
|
||||
if (symbol.getName().equals(name)) {
|
||||
return true;
|
||||
|
||||
+1
-5
@@ -287,11 +287,7 @@ class SymbolTableModel extends AddressBasedTableModel<Symbol> {
|
||||
CompoundCmd cmd = new CompoundCmd("Delete symbol(s)");
|
||||
for (Symbol symbol : rowObjects) {
|
||||
if (symbol.isDynamic()) {
|
||||
Symbol[] symbols = symbolTable.getSymbols(symbol.getAddress());
|
||||
if (symbols.length == 1) {
|
||||
tool.setStatusInfo("Unable to delete symbol: " + symbol.getName());
|
||||
continue;//can't delete dynamic symbols...
|
||||
}
|
||||
continue;//can't delete dynamic symbols...
|
||||
}
|
||||
|
||||
deleteList.add(symbol);
|
||||
|
||||
@@ -370,11 +370,9 @@ public class AddEditDialog extends DialogComponentProvider {
|
||||
|
||||
private FunctionSymbol getFunctionSymbol(Address address) {
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
Symbol[] symbols = symbolTable.getSymbols(address);
|
||||
for (Symbol localSymbol : symbols) {
|
||||
if (localSymbol instanceof FunctionSymbol) {
|
||||
return (FunctionSymbol) localSymbol;
|
||||
}
|
||||
Symbol primary = symbolTable.getPrimarySymbol(address);
|
||||
if (primary instanceof FunctionSymbol) {
|
||||
return (FunctionSymbol) primary;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -395,10 +393,8 @@ public class AddEditDialog extends DialogComponentProvider {
|
||||
pinnedCheckBox.setEnabled(true);
|
||||
pinnedCheckBox.setSelected(false);
|
||||
|
||||
Symbol[] symbols = symbolTable.getSymbols(address);
|
||||
|
||||
FunctionSymbol functionSymbol = getFunctionSymbol(address);
|
||||
if (functionSymbol == null && symbols.length == 0) {
|
||||
Symbol primarySymbol = symbolTable.getPrimarySymbol(address);
|
||||
if (primarySymbol == null) {
|
||||
primaryCheckBox.setSelected(true);
|
||||
primaryCheckBox.setEnabled(false);
|
||||
}
|
||||
@@ -463,9 +459,8 @@ public class AddEditDialog extends DialogComponentProvider {
|
||||
nameBorder.setTitle("Enter Label:");
|
||||
entryPointCheckBox.setEnabled(true);
|
||||
entryPointCheckBox.setSelected(symbolTable.isExternalEntryPoint(addr));
|
||||
Symbol[] symbols = symbolTable.getSymbols(addr);
|
||||
primaryCheckBox.setSelected(s.isPrimary());
|
||||
primaryCheckBox.setEnabled(!s.isPrimary() && symbols.length > 1);
|
||||
primaryCheckBox.setEnabled(!s.isPrimary());
|
||||
pinnedCheckBox.setEnabled(true);
|
||||
pinnedCheckBox.setSelected(s.isPinned());
|
||||
namespaceChoices.setEnabled(true);
|
||||
|
||||
+6
-8
@@ -234,7 +234,7 @@ public class ElfDefaultGotPltMarkup {
|
||||
long symbolSearchSpacing; // nominal PLT entry size for computing maxSymbolSearchAddress
|
||||
|
||||
Address firstPltEntryAddr = null; // may be offcut within first PLT entry
|
||||
|
||||
|
||||
if (pltSpacing == 0) { // Entries have same original bytes which refer to PLT head
|
||||
Function pltHeadFunc = elfLoadHelper.createOneByteFunction(null, pltAddr1, false);
|
||||
if (pltHeadFunc.getSymbol().getSource() == SourceType.DEFAULT) {
|
||||
@@ -537,8 +537,9 @@ public class ElfDefaultGotPltMarkup {
|
||||
// Stop on first error but discard error bookmark since
|
||||
// some plt sections are partly empty and must rely
|
||||
// on normal flow disassembly during analysis
|
||||
prog.getBookmarkManager().removeBookmarks(set, BookmarkType.ERROR,
|
||||
Disassembler.ERROR_BOOKMARK_CATEGORY, monitor);
|
||||
prog.getBookmarkManager()
|
||||
.removeBookmarks(set, BookmarkType.ERROR,
|
||||
Disassembler.ERROR_BOOKMARK_CATEGORY, monitor);
|
||||
break;//we did not disassemble anything...
|
||||
}
|
||||
set.delete(disset);
|
||||
@@ -604,11 +605,8 @@ public class ElfDefaultGotPltMarkup {
|
||||
if (memory.contains(refAddr)) {
|
||||
return true;
|
||||
}
|
||||
Symbol syms[] = program.getSymbolTable().getSymbols(refAddr);
|
||||
if (syms != null && syms.length > 0 && syms[0].getSource() != SourceType.DEFAULT) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
Symbol primary = program.getSymbolTable().getPrimarySymbol(refAddr);
|
||||
return primary != null && primary.getSource() != SourceType.DEFAULT;
|
||||
}
|
||||
|
||||
private void removeMemRefs(Data data) {
|
||||
|
||||
@@ -1570,7 +1570,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find memory register with matching name (ignoring leading and trailing underscore chars).
|
||||
* @param elfSymbol ELF symbol
|
||||
@@ -1586,7 +1586,7 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
||||
}
|
||||
return regAddr;
|
||||
}
|
||||
|
||||
|
||||
private Address getMemoryRegister(String name, long value) {
|
||||
Register reg = program.getRegister(name);
|
||||
if (reg != null && reg.getAddress().isMemoryAddress()) {
|
||||
@@ -2360,9 +2360,9 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
|
||||
.addMemoryReference(valueData.getAddress(), refAddr, RefType.DATA,
|
||||
SourceType.ANALYSIS, 0);
|
||||
if (label != null) {
|
||||
// add label if a non-default label does not exist
|
||||
Symbol[] symbols = program.getSymbolTable().getSymbols(refAddr);
|
||||
if (symbols.length == 0 || symbols[0].getSource() == SourceType.DEFAULT) {
|
||||
// add label if no label exists of there is just a default label
|
||||
Symbol symbol = program.getSymbolTable().getPrimarySymbol(refAddr);
|
||||
if (symbol == null || symbol.getSource() == SourceType.DEFAULT) {
|
||||
createSymbol(refAddr, "_" + label, false, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1377,7 +1377,7 @@ public class FlatProgramAPI {
|
||||
*/
|
||||
@Deprecated
|
||||
public final Symbol getSymbolAt(Address address, String name) {
|
||||
Symbol[] symbols = currentProgram.getSymbolTable().getSymbols(address);
|
||||
SymbolIterator symbols = currentProgram.getSymbolTable().getSymbolsAsIterator(address);
|
||||
for (Symbol symbol : symbols) {
|
||||
if (symbol.getName().equals(name)) {
|
||||
return symbol;
|
||||
|
||||
+21
@@ -199,7 +199,28 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
assertTrue(!s.isGlobal());
|
||||
assertTrue(s.getSource() == SourceType.USER_DEFINED);
|
||||
assertTrue(s.isPrimary());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSymbolIteratorByAddress() throws Exception {
|
||||
createSymbol(addr(100), "A");
|
||||
createSymbol(addr(100), "fred");
|
||||
createSymbol(addr(100), "joe");
|
||||
Namespace scope = st.createNameSpace(null, "MyNamespace", SourceType.USER_DEFINED);
|
||||
createSymbol(addr(200), "fred", scope);
|
||||
|
||||
SymbolIterator it = st.getSymbolsAsIterator(addr(100));
|
||||
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals("A", it.next().getName());
|
||||
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals("fred", it.next().getName());
|
||||
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals("joe", it.next().getName());
|
||||
|
||||
assertFalse(it.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+20
-32
@@ -166,8 +166,9 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
byte[] gccBytes = { (byte) 0x47, (byte) 0x43, (byte) 0x43, (byte) 0x3a };
|
||||
byte[] maskBytes = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
|
||||
|
||||
Address found = program.getMemory().findBytes(commentBlock.getStart(),
|
||||
commentBlock.getEnd(), gccBytes, maskBytes, true, monitor);
|
||||
Address found = program.getMemory()
|
||||
.findBytes(commentBlock.getStart(),
|
||||
commentBlock.getEnd(), gccBytes, maskBytes, true, monitor);
|
||||
if (found == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -256,7 +257,6 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
|
||||
updateClassesWithParentsAndFlags(typeinfoSymbols);
|
||||
|
||||
|
||||
// update the vftable offset map
|
||||
Iterator<RecoveredClass> recoveredClassIterator = recoveredClasses.iterator();
|
||||
while (recoveredClassIterator.hasNext()) {
|
||||
@@ -417,7 +417,6 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
if (specialTypeinfoRef.equals(vmi_class_type_info) ||
|
||||
specialTypeinfoRef.equals(vmi_class_type_info_vtable)) {
|
||||
|
||||
|
||||
List<RecoveredClass> parents =
|
||||
addGccClassParentsFromVmiStruct(recoveredClass, typeinfoAddress);
|
||||
|
||||
@@ -493,7 +492,6 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
for (Address typeinfoRef : typeinfoReferencesNotInTypeinfoStructs) {
|
||||
monitor.checkCanceled();
|
||||
|
||||
|
||||
Address typeinfoAddress = extraUtils.getPointer(typeinfoRef);
|
||||
|
||||
if (typeinfoAddress == null) {
|
||||
@@ -524,14 +522,13 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
if (!typeinfoSymbol.getName().equals("typeinfo")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// check for construction table and make new namespace if so
|
||||
Namespace classNamespace = typeinfoSymbol.getParentNamespace();
|
||||
|
||||
|
||||
if (classNamespace.equals(globalNamespace)) {
|
||||
throw new Exception("typeinfo has global namespace " + typeinfoAddress);
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
Symbol vtableSymbol = symbolTable.createLabel(vtableAddress, VTABLE_LABEL,
|
||||
@@ -617,8 +614,6 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private Namespace createConstructionNamespace(Symbol vtableSymbol, Symbol vttSymbol)
|
||||
throws Exception {
|
||||
|
||||
@@ -635,7 +630,7 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
try {
|
||||
Namespace newNamespace =
|
||||
NamespaceUtils.createNamespaceHierarchy(name, vtableNamespace,
|
||||
program, SourceType.ANALYSIS);
|
||||
program, SourceType.ANALYSIS);
|
||||
return newNamespace;
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
@@ -722,7 +717,6 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
|
||||
Data dataContainingTypeinfoRef = prog.getListing().getDefinedDataContaining(addr);
|
||||
|
||||
|
||||
Instruction instructionContainingAddr =
|
||||
prog.getListing().getInstructionContaining(addr);
|
||||
|
||||
@@ -863,8 +857,9 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
|
||||
api.setPlateComment(vtableAddress, "construction vtable " + n +
|
||||
" for class " +
|
||||
vttSymbolBeforeConstructionVtable.getParentNamespace().getName(
|
||||
true));
|
||||
vttSymbolBeforeConstructionVtable.getParentNamespace()
|
||||
.getName(
|
||||
true));
|
||||
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
@@ -897,7 +892,7 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
}
|
||||
|
||||
int numFunctionPointers = getNumFunctionPointers(possibleVftableAddress, true, true);
|
||||
|
||||
|
||||
if (numFunctionPointers == 0) {
|
||||
// if not a vftable check for an internal vtable
|
||||
boolean isInternalVtable =
|
||||
@@ -1190,7 +1185,6 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1402,7 +1396,7 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
|
||||
// Except for the first one which should have a symbol, if there is a symbol at the
|
||||
// address, stop making longs because it there are no references into the vtable longs
|
||||
if (offset > 0 && symbolTable.getSymbols(address).length > 0) {
|
||||
if (offset > 0 && symbolTable.getPrimarySymbol(address) != null) {
|
||||
return numLongs;
|
||||
}
|
||||
|
||||
@@ -1489,33 +1483,34 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
// create a "no inheritance" struct here
|
||||
if (specialTypeinfoRef.equals(class_type_info) ||
|
||||
specialTypeinfoRef.equals(class_type_info_vtable)) {
|
||||
|
||||
|
||||
newStructure = applyTypeinfoStructure(classTypeInfoStructure, typeinfoAddress);
|
||||
}
|
||||
|
||||
// create a "single inheritance" struct here
|
||||
else if (specialTypeinfoRef.equals(si_class_type_info) ||
|
||||
specialTypeinfoRef.equals(si_class_type_info_vtable)) {
|
||||
|
||||
|
||||
newStructure = applyTypeinfoStructure(siClassTypeInfoStructure, typeinfoAddress);
|
||||
}
|
||||
|
||||
// create a "virtual multip inheritance" struct here
|
||||
else if (specialTypeinfoRef.equals(vmi_class_type_info) ||
|
||||
specialTypeinfoRef.equals(vmi_class_type_info_vtable)) {
|
||||
|
||||
|
||||
Structure vmiClassTypeinfoStructure =
|
||||
getOrCreateVmiTypeinfoStructure(typeinfoAddress, baseClassTypeInfoStructure);
|
||||
if (vmiClassTypeinfoStructure != null) {
|
||||
newStructure = applyTypeinfoStructure(vmiClassTypeinfoStructure, typeinfoAddress);
|
||||
newStructure =
|
||||
applyTypeinfoStructure(vmiClassTypeinfoStructure, typeinfoAddress);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (newStructure == null) {
|
||||
throw new Exception(
|
||||
"ERROR: Could not apply typeinfo structure to " + typeinfoAddress);
|
||||
}
|
||||
|
||||
|
||||
// check for existing symbol and if none, demangle the name and apply
|
||||
Symbol typeinfoSymbol = api.getSymbolAt(typeinfoAddress);
|
||||
if (typeinfoSymbol == null || typeinfoSymbol.getSource() == SourceType.DEFAULT) {
|
||||
@@ -1840,7 +1835,6 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
return specialTypeinfoRefs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method to call the various methods to determine whether the functions that make references to
|
||||
* the vftables are constructors, destructors, deleting destructors, clones, or vbase functions
|
||||
@@ -1985,7 +1979,6 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
DataType pointer = dataTypeManager.getPointer(null);
|
||||
DataType charPointer = dataTypeManager.getPointer(characterDT);
|
||||
|
||||
|
||||
vmiClassTypeInfoStructure.add(pointer, "classTypeinfoPtr", null);
|
||||
vmiClassTypeInfoStructure.add(charPointer, "typeinfoName", null);
|
||||
vmiClassTypeInfoStructure.add(unsignedIntDT, "flags", null);
|
||||
@@ -2011,7 +2004,6 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
private List<RecoveredClass> addGccClassParentsFromVmiStruct(RecoveredClass recoveredClass,
|
||||
Address typeinfoAddress) throws Exception {
|
||||
|
||||
|
||||
Structure vmiTypeinfoStructure = getTypeinfoStructure(typeinfoAddress);
|
||||
if (vmiTypeinfoStructure == null ||
|
||||
!vmiTypeinfoStructure.getName().contains(VMI_CLASS_TYPE_INFO_STRUCTURE)) {
|
||||
@@ -2150,8 +2142,6 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
|
||||
parentClass.setIsPublicClass(isPublic);
|
||||
|
||||
|
||||
|
||||
// from doc:
|
||||
//All but the lower 8 bits of __offset_flags are a signed offset. For a
|
||||
//non-virtual base, this is the offset in the object of the base subobject.
|
||||
@@ -2168,7 +2158,6 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
|
||||
continue;
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
@@ -2893,7 +2882,6 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!recoveredClass.hasVftable()) {
|
||||
createSimpleClassStructure(recoveredClass, null);
|
||||
// return in this case because if there is no vftable for a class the script cannot
|
||||
@@ -3018,7 +3006,6 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
" : structure should exist but doesn't.");
|
||||
}
|
||||
|
||||
|
||||
if (structUtils.canAdd(classStructureDataType, parentOffset,
|
||||
baseClassStructure.getLength(), monitor)) {
|
||||
classStructureDataType =
|
||||
@@ -3049,7 +3036,8 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer {
|
||||
|
||||
}
|
||||
|
||||
if (classStructureDataType.getNumComponents() == classStructureDataType.getNumDefinedComponents()) {
|
||||
if (classStructureDataType.getNumComponents() == classStructureDataType
|
||||
.getNumDefinedComponents()) {
|
||||
classStructureDataType.setPackingEnabled(true);
|
||||
}
|
||||
|
||||
|
||||
+16
-35
@@ -56,11 +56,9 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
||||
private static final String VFTABLE_META_PTR_LABEL = "vftable_meta_ptr";
|
||||
private static final String VFTABLE_LABEL = "vftable";
|
||||
|
||||
|
||||
private static final String CLASS_VTABLE_STRUCT_NAME = "_vbtable";
|
||||
private static final String CLASS_VTABLE_PTR_FIELD_EXT = "vftablePtr";
|
||||
|
||||
|
||||
private static final int CHD_MULTINH = 0x00000001; //Multiple inheritance
|
||||
private static final int CHD_VIRTINH = 0x00000002; //Virtual inheritance
|
||||
private static final int CHD_AMBIGUOUS = 0x00000004; //Multiple inheritance with repeated base classes
|
||||
@@ -91,7 +89,6 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isValidProgramType() {
|
||||
if (!isVisualStudioOrClangPe()) {
|
||||
@@ -100,7 +97,6 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void fixUpProgram() {
|
||||
|
||||
@@ -184,10 +180,8 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
||||
|
||||
determineParentClassInfoFromBaseClassArray(recoveredClasses);
|
||||
|
||||
|
||||
assignParentClassToVftables(recoveredClasses);
|
||||
|
||||
|
||||
// using all the information found above, create the class structures, add the constructor,
|
||||
// destructor, vfunctions to class which finds the appropriate class structure and assigns
|
||||
// to "this" param
|
||||
@@ -205,7 +199,7 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
||||
//println("Removing erroneous FID namespaces and corresponding class data types");
|
||||
removeEmptyClassesAndStructures();
|
||||
}
|
||||
|
||||
|
||||
return recoveredClasses;
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
@@ -219,14 +213,12 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
||||
|
||||
}
|
||||
|
||||
|
||||
private boolean isVisualStudioOrClangPe() {
|
||||
return program.getExecutableFormat().equals(PeLoader.PE_NAME) &&
|
||||
(program.getCompiler().equals(CompilerEnum.VisualStudio.toString()) ||
|
||||
program.getCompiler().equals(CompilerEnum.Clang.toString()));
|
||||
}
|
||||
|
||||
|
||||
private boolean hasTypeInfoVftable() throws CancelledException {
|
||||
|
||||
List<Symbol> vftableSymbols = getListOfVftableSymbols();
|
||||
@@ -474,8 +466,10 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
||||
Address baseClassDescriptorAddress = getReferencedAddress(address.add(i * 4));
|
||||
|
||||
Data baseClassDescriptor = extraUtils.getDataAt(baseClassDescriptorAddress);
|
||||
if (baseClassDescriptor == null || !baseClassDescriptor.getDataType().getName().equals(
|
||||
RTTI_BASE_CLASS_DESCRIPTOR_DATA_NAME)) {
|
||||
if (baseClassDescriptor == null || !baseClassDescriptor.getDataType()
|
||||
.getName()
|
||||
.equals(
|
||||
RTTI_BASE_CLASS_DESCRIPTOR_DATA_NAME)) {
|
||||
|
||||
int num1 = extraUtils.getInt(baseClassDescriptorAddress.add(8));
|
||||
int num2 = extraUtils.getInt(baseClassDescriptorAddress.add(12));
|
||||
@@ -563,8 +557,10 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
||||
Data classHierarchyStructure = extraUtils.getDataAt(classHierarchyDescriptorAddress);
|
||||
|
||||
if (classHierarchyStructure != null &&
|
||||
classHierarchyStructure.getDataType().getName().equals(
|
||||
RTTI_CLASS_HIERARCHY_DESCRIPTOR_DATA_NAME)) {
|
||||
classHierarchyStructure.getDataType()
|
||||
.getName()
|
||||
.equals(
|
||||
RTTI_CLASS_HIERARCHY_DESCRIPTOR_DATA_NAME)) {
|
||||
return classHierarchyDescriptorAddress;
|
||||
|
||||
}
|
||||
@@ -803,7 +799,7 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
||||
private Symbol getGivenSymbol(Address address, String name, Namespace namespace)
|
||||
throws CancelledException {
|
||||
|
||||
Symbol[] symbols = symbolTable.getSymbols(address);
|
||||
SymbolIterator symbols = symbolTable.getSymbolsAsIterator(address);
|
||||
for (Symbol sym : symbols) {
|
||||
monitor.checkCanceled();
|
||||
if (sym.getName().contains(name) && sym.getParentNamespace().equals(namespace)) {
|
||||
@@ -884,10 +880,6 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
||||
findFunctionsUsingAtexit();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Method to recover the class information for each vftable symbol on the list
|
||||
* * For each virtual function table:
|
||||
@@ -923,7 +915,7 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
||||
|
||||
if (classNamespace.getSymbol().getSymbolType() != SymbolType.CLASS) {
|
||||
classNamespace = promoteToClassNamespace(classNamespace);
|
||||
if(classNamespace.getSymbol().getSymbolType() != SymbolType.CLASS) {
|
||||
if (classNamespace.getSymbol().getSymbolType() != SymbolType.CLASS) {
|
||||
Msg.debug(this,
|
||||
classHierarchyDescriptorAddress.toString() + " Could not promote " +
|
||||
classNamespace.getName(true) + " to a class namespace.");
|
||||
@@ -963,11 +955,11 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
||||
List<RecoveredClass> classesWithVftablesInNamespace =
|
||||
recoverClassesFromVftables(vftableSymbolsInNamespace, false, false);
|
||||
if (classesWithVftablesInNamespace.size() == 0) {
|
||||
Msg.debug(this,"No class recovered for namespace " + classNamespace.getName());
|
||||
Msg.debug(this, "No class recovered for namespace " + classNamespace.getName());
|
||||
continue;
|
||||
}
|
||||
if (classesWithVftablesInNamespace.size() > 1) {
|
||||
Msg.debug(this,"Unexpected multiple classes recovered for namespace " +
|
||||
Msg.debug(this, "Unexpected multiple classes recovered for namespace " +
|
||||
classNamespace.getName());
|
||||
continue;
|
||||
}
|
||||
@@ -1372,7 +1364,6 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method to recover parent information, including class offsets, vbase structure and its offset and address if applicable, and whether
|
||||
* the parent is regularly or virtually inherited
|
||||
@@ -2142,14 +2133,6 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Method to call create and apply class structures method starting with top parent classes
|
||||
* and non-virtual classes then the children and their children until all classes are processed.
|
||||
@@ -2493,7 +2476,7 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
||||
|
||||
Structure recoveredClassDataStruct =
|
||||
createClassMemberDataStructure(recoveredClass,
|
||||
classStructureDataType, dataLen, dataOffset);
|
||||
classStructureDataType, dataLen, dataOffset);
|
||||
|
||||
if (recoveredClassDataStruct != null) {
|
||||
classStructureDataType = structUtils.addDataTypeToStructure(
|
||||
@@ -2502,7 +2485,8 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
||||
|
||||
}
|
||||
|
||||
if (classStructureDataType.getNumComponents() == classStructureDataType.getNumDefinedComponents()) {
|
||||
if (classStructureDataType.getNumComponents() == classStructureDataType
|
||||
.getNumDefinedComponents()) {
|
||||
classStructureDataType.setPackingEnabled(true);
|
||||
}
|
||||
|
||||
@@ -2590,7 +2574,6 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
||||
return classStructureDataType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method to apply the given class's vbtable structure
|
||||
* @param recoveredClass the given RecoveredClass object which, if applicable, contains the address and structure to apply
|
||||
@@ -2615,6 +2598,4 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
|
||||
recoveredClass.getClassNamespace().getName(true) + "::vbtable");
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -169,7 +169,6 @@ public class RecoveredClassUtils {
|
||||
decompilerUtils = new DecompilerScriptUtils(program, tool, monitor);
|
||||
structUtils = new EditStructureUtils();
|
||||
|
||||
|
||||
dataTypeManager = program.getDataTypeManager();
|
||||
symbolTable = program.getSymbolTable();
|
||||
|
||||
@@ -236,7 +235,7 @@ public class RecoveredClassUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<Address> getVftableReferences(Function function) {
|
||||
return functionToVftableRefsMap.get(function);
|
||||
}
|
||||
@@ -522,8 +521,6 @@ public class RecoveredClassUtils {
|
||||
return allInlinedDestructors;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Method to determine if referenced vftables are from the same class
|
||||
* @param vftableReferences list of vftable references
|
||||
@@ -907,7 +904,7 @@ public class RecoveredClassUtils {
|
||||
*/
|
||||
public Address getStoredVftableAddress(List<OffsetPcodeOpPair> storedPcodeOps)
|
||||
throws CancelledException {
|
||||
|
||||
|
||||
if (storedPcodeOps.size() > 0) {
|
||||
Iterator<OffsetPcodeOpPair> iterator = storedPcodeOps.iterator();
|
||||
// figure out if vftable is referenced
|
||||
@@ -1288,8 +1285,6 @@ public class RecoveredClassUtils {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Method to determine if the given possible ancestor is an ancestor of any of the listed classes
|
||||
* @param recoveredClasses List of classes
|
||||
@@ -2658,7 +2653,6 @@ public class RecoveredClassUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method to create a new recovered class object and add it to the namespaceToClassMap
|
||||
* @param namespace the namespace to put the new class in
|
||||
@@ -2724,7 +2718,7 @@ public class RecoveredClassUtils {
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// get only the functions from the ones that are not already processed structures
|
||||
// return null if not an unprocessed table
|
||||
List<Function> virtualFunctions = getFunctionsFromVftable(vftableAddress, vftableSymbol,
|
||||
@@ -2766,7 +2760,6 @@ public class RecoveredClassUtils {
|
||||
Map<Address, Function> vftableReferenceToFunctionMapping =
|
||||
createVftableReferenceToFunctionMapping(referencesToVftable);
|
||||
|
||||
|
||||
//vftableReferenceToFunctionMapping
|
||||
List<Function> possibleConstructorDestructorsForThisClass =
|
||||
findPossibleConstructorDestructors(vftableReferenceToFunctionMapping);
|
||||
@@ -2910,8 +2903,6 @@ public class RecoveredClassUtils {
|
||||
return cdFunctions;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Method to get functions from vftable
|
||||
* @param vftableAddress the address of the vftable
|
||||
@@ -3890,8 +3881,8 @@ public class RecoveredClassUtils {
|
||||
|
||||
String simpleName = extraUtils.removeTemplate(name);
|
||||
|
||||
Symbol[] symbols = symbolTable.getSymbols(address);
|
||||
for (Symbol symbol : symbols) {
|
||||
SymbolIterator it = symbolTable.getSymbolsAsIterator(address);
|
||||
for (Symbol symbol : it) {
|
||||
monitor.checkCanceled();
|
||||
|
||||
String simpleSymbolName = extraUtils.removeTemplate(symbol.getName());
|
||||
@@ -4541,7 +4532,7 @@ public class RecoveredClassUtils {
|
||||
if (nameField.contains("purecall")) {
|
||||
nameField = DEFAULT_VFUNCTION_PREFIX + vfunctionNumber;
|
||||
comment = recoveredClass.getName() + " pure " + comment;
|
||||
|
||||
|
||||
}
|
||||
|
||||
PointerDataType functionPointerDataType =
|
||||
@@ -4932,10 +4923,11 @@ public class RecoveredClassUtils {
|
||||
//TODO: remove after testing
|
||||
if (!classVftableRef.equals(otherWayRef)) {
|
||||
if (DEBUG) {
|
||||
Msg.debug(this,
|
||||
recoveredClass.getName() + " function " +
|
||||
functionContainingInline.getEntryPoint().toString() + " first ref: " +
|
||||
classVftableRef.toString() + " other way ref: " + otherWayRef.toString());
|
||||
Msg.debug(this,
|
||||
recoveredClass.getName() + " function " +
|
||||
functionContainingInline.getEntryPoint().toString() + " first ref: " +
|
||||
classVftableRef.toString() + " other way ref: " +
|
||||
otherWayRef.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5056,8 +5048,9 @@ public class RecoveredClassUtils {
|
||||
Function firstCalledFunction =
|
||||
extraUtils.getCalledFunctionByCallOrder(deletingDestructor, 1);
|
||||
if (firstCalledFunction == null ||
|
||||
!recoveredClass.getConstructorOrDestructorFunctions().contains(
|
||||
firstCalledFunction)) {
|
||||
!recoveredClass.getConstructorOrDestructorFunctions()
|
||||
.contains(
|
||||
firstCalledFunction)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -5201,11 +5194,14 @@ public class RecoveredClassUtils {
|
||||
return;
|
||||
}
|
||||
if (parentDestructorClasses.size() == 1) {
|
||||
if (!parentDestructorClasses.get(0).getDestructorList().contains(
|
||||
parentDestructor)) {
|
||||
if (!parentDestructorClasses.get(0)
|
||||
.getDestructorList()
|
||||
.contains(
|
||||
parentDestructor)) {
|
||||
addDestructorToClass(parentDestructorClasses.get(0), parentDestructor);
|
||||
parentDestructorClasses.get(0).removeIndeterminateConstructorOrDestructor(
|
||||
parentDestructor);
|
||||
parentDestructorClasses.get(0)
|
||||
.removeIndeterminateConstructorOrDestructor(
|
||||
parentDestructor);
|
||||
}
|
||||
}
|
||||
// if more than one parent class for this function then let either inline or multi-class
|
||||
@@ -5390,8 +5386,10 @@ public class RecoveredClassUtils {
|
||||
*/
|
||||
public boolean isClassOffsetToVftableMapComplete(RecoveredClass recoveredClass) {
|
||||
|
||||
if (recoveredClass.getClassOffsetToVftableMap().values().containsAll(
|
||||
recoveredClass.getVftableAddresses())) {
|
||||
if (recoveredClass.getClassOffsetToVftableMap()
|
||||
.values()
|
||||
.containsAll(
|
||||
recoveredClass.getVftableAddresses())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -5434,8 +5432,9 @@ public class RecoveredClassUtils {
|
||||
Function secondCalledFunction =
|
||||
extraUtils.getCalledFunctionByCallOrder(vFunction, 2);
|
||||
if (firstCalledFunction != null && secondCalledFunction != null &&
|
||||
!recoveredClass.getConstructorOrDestructorFunctions().contains(
|
||||
firstCalledFunction) &&
|
||||
!recoveredClass.getConstructorOrDestructorFunctions()
|
||||
.contains(
|
||||
firstCalledFunction) &&
|
||||
secondCalledFunction.equals(operator_delete) &&
|
||||
!getAllConstructorsAndDestructors().contains(vFunction)) {
|
||||
recoveredClass.addDeletingDestructor(vFunction);
|
||||
@@ -6903,7 +6902,6 @@ public class RecoveredClassUtils {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return changedItems;
|
||||
|
||||
}
|
||||
@@ -7419,12 +7417,12 @@ public class RecoveredClassUtils {
|
||||
|
||||
private Structure getParentClassStructure(Structure childClassStructure, String nameOfParent)
|
||||
throws CancelledException {
|
||||
|
||||
|
||||
DataTypeComponent[] components = childClassStructure.getComponents();
|
||||
for (DataTypeComponent component : components) {
|
||||
monitor.checkCanceled();
|
||||
DataType componentDataType = component.getDataType();
|
||||
if(componentDataType.getName().equals(nameOfParent)) {
|
||||
if (componentDataType.getName().equals(nameOfParent)) {
|
||||
return (Structure) componentDataType;
|
||||
}
|
||||
}
|
||||
@@ -7520,22 +7518,24 @@ public class RecoveredClassUtils {
|
||||
DataTypeComponent[] vfunctionComponents = vfunctionStructure.getComponents();
|
||||
for (DataTypeComponent vfunctionComponent : vfunctionComponents) {
|
||||
monitor.checkCanceled();
|
||||
Object changedItem = updateListingVfunctionSignature(data, vfunctionComponent, vftableAddress);
|
||||
if(changedItem != null && !changedItems.contains(changedItem)) {
|
||||
Object changedItem =
|
||||
updateListingVfunctionSignature(data, vfunctionComponent, vftableAddress);
|
||||
if (changedItem != null && !changedItems.contains(changedItem)) {
|
||||
changedItems.add(changedItem);
|
||||
|
||||
FunctionDefinition newFunctionDefinition = getComponentFunctionDefinition(vfunctionComponent);
|
||||
if(newFunctionDefinition == null) {
|
||||
FunctionDefinition newFunctionDefinition =
|
||||
getComponentFunctionDefinition(vfunctionComponent);
|
||||
if (newFunctionDefinition == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
List<Object> changedStructs =
|
||||
applyNewFunctionDefinitionToComponents(vfunctionComponent,
|
||||
newFunctionDefinition);
|
||||
applyNewFunctionDefinitionToComponents(vfunctionComponent,
|
||||
newFunctionDefinition);
|
||||
if (changedStructs.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
changedItems = updateList(changedItems, changedStructs);
|
||||
}
|
||||
}
|
||||
@@ -7604,7 +7604,6 @@ public class RecoveredClassUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
boolean changed = updateFunctionSignature(vfunction, newFunctionDefinition);
|
||||
if (changed) {
|
||||
return vfunction;
|
||||
|
||||
+10
-15
@@ -502,7 +502,7 @@ public class ObjectiveC2_DecompilerMessageAnalyzer extends AbstractAnalyzer {
|
||||
offset = ((Address) dataValue).getOffset();
|
||||
if (offset == address.getOffset()) {
|
||||
// Self-referencing pointer
|
||||
name = null;
|
||||
name = null;
|
||||
}
|
||||
else {
|
||||
name = getNameFromOffset(program, offset, input, isClass, isMethod);
|
||||
@@ -671,23 +671,18 @@ public class ObjectiveC2_DecompilerMessageAnalyzer extends AbstractAnalyzer {
|
||||
}
|
||||
|
||||
private String getLabelFromUndefinedData(Program program, Address address) {
|
||||
Symbol[] symbols = program.getSymbolTable().getSymbols(address);
|
||||
if (symbols.length == 0) {
|
||||
Symbol primary = program.getSymbolTable().getPrimarySymbol(address);
|
||||
if (primary == null) {
|
||||
return null;
|
||||
}
|
||||
for (Symbol symbol : symbols) {
|
||||
if (symbol.isPrimary()) {
|
||||
String symbolName = symbol.getName();
|
||||
if (symbolName.contains("_OBJC_CLASS_$_")) {
|
||||
symbolName = symbolName.substring("_OBJC_CLASS_$_".length());
|
||||
}
|
||||
else if (symbolName.contains("_objc_msgSend")) {
|
||||
return null;
|
||||
}
|
||||
return symbolName;
|
||||
}
|
||||
String symbolName = primary.getName();
|
||||
if (symbolName.contains("_OBJC_CLASS_$_")) {
|
||||
symbolName = symbolName.substring("_OBJC_CLASS_$_".length());
|
||||
}
|
||||
return null;
|
||||
else if (symbolName.contains("_objc_msgSend")) {
|
||||
return null;
|
||||
}
|
||||
return symbolName;
|
||||
}
|
||||
|
||||
private String getClassName(Program program, Address toAddress) {
|
||||
|
||||
+4
-8
@@ -764,14 +764,10 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
|
||||
SymbolTable symbolTable = currentProgram.getSymbolTable();
|
||||
AddressSetView vertexAddresses = destinationVertex.getAddresses();
|
||||
Address minAddress = vertexAddresses.getMinAddress();
|
||||
Symbol[] symbols = symbolTable.getSymbols(minAddress);
|
||||
if (symbols.length > 1) {
|
||||
return; // real user symbols
|
||||
}
|
||||
else if (symbols.length == 1) {
|
||||
if (!symbols[0].isDynamic()) {
|
||||
return; // real user symbol
|
||||
}
|
||||
|
||||
Symbol primary = symbolTable.getPrimarySymbol(minAddress);
|
||||
if (!primary.isDynamic()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ReferenceManager referenceManager = currentProgram.getReferenceManager();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+14
-27
@@ -278,7 +278,7 @@ public class ApplyFidEntriesCommand extends BackgroundCommand {
|
||||
private boolean hasUserOrImportedSymbols(Function function) {
|
||||
Program program = function.getProgram();
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
Symbol[] symbols = symbolTable.getSymbols(function.getEntryPoint());
|
||||
SymbolIterator symbols = symbolTable.getSymbolsAsIterator(function.getEntryPoint());
|
||||
for (Symbol symbol : symbols) {
|
||||
SourceType sourceType = symbol.getSource();
|
||||
if (sourceType == SourceType.USER_DEFINED || sourceType == SourceType.IMPORTED) {
|
||||
@@ -297,39 +297,26 @@ public class ApplyFidEntriesCommand extends BackgroundCommand {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a symbol of the given name and address, knowing there are multiple Symbols at the address.
|
||||
* If the symbol is primary, make another Symbol at the address primary before deleting
|
||||
* Delete a symbol of the given name at the given address.
|
||||
*
|
||||
* @param matchName is the given Symbol name
|
||||
* @param addr is the given Address
|
||||
* @param program is the Program
|
||||
* @return the number of Symbols remaining at the address
|
||||
*/
|
||||
private int deleteSymbol(String matchName, Address addr, Program program) {
|
||||
int numSymbols = 0;
|
||||
for (int i = 0; i < 2; ++i) { // Try to find non-primary matching Symbol at most twice
|
||||
Symbol[] symbols = program.getSymbolTable().getSymbols(addr);
|
||||
numSymbols = symbols.length;
|
||||
if (numSymbols <= 1) {
|
||||
Symbol[] symbols = program.getSymbolTable().getSymbols(addr);
|
||||
int numSymbols = symbols.length;
|
||||
if (numSymbols <= 1) {
|
||||
return numSymbols;
|
||||
}
|
||||
// find the matching symbol and delete it
|
||||
for (Symbol sym : symbols) {
|
||||
if (sym.getName().equals(matchName)) {
|
||||
sym.delete();
|
||||
numSymbols -= 1;
|
||||
break;
|
||||
}
|
||||
for (Symbol sym : symbols) { // Among Symbols at the Address
|
||||
if (sym.getName().equals(matchName)) { // Find one with matching name
|
||||
if (!sym.isPrimary()) { // If it is not primary
|
||||
sym.delete(); // delete it immediately
|
||||
numSymbols -= 1;
|
||||
break; // and we are done
|
||||
}
|
||||
Symbol otherSym = symbols[0];
|
||||
if (otherSym == sym) { // Otherwise find another Symbol, which must not be primary
|
||||
otherSym = symbols[1];
|
||||
}
|
||||
// Set the other symbol to primary
|
||||
SetLabelPrimaryCmd cmd = new SetLabelPrimaryCmd(addr, otherSym.getName(),
|
||||
otherSym.getParentNamespace());
|
||||
cmd.applyTo(program);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return numSymbols;
|
||||
}
|
||||
@@ -390,7 +377,7 @@ public class ApplyFidEntriesCommand extends BackgroundCommand {
|
||||
BookmarkManager bookmarkManager = function.getProgram().getBookmarkManager();
|
||||
bookmarkManager.setBookmark(addr, BookmarkType.ANALYSIS,
|
||||
FIDCONFLICT_BOOKMARK_CATEGORY,
|
||||
"Multiple likely matching functions");
|
||||
"Multiple likely matching functions");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-8
@@ -460,14 +460,9 @@ class FidServiceLibraryIngest {
|
||||
}
|
||||
|
||||
private static String grabSymbol(SymbolTable symbolTable, Address address) {
|
||||
Symbol[] symbols = symbolTable.getSymbols(address);
|
||||
if (symbols == null || symbols.length == 0) {
|
||||
return null;
|
||||
}
|
||||
for (Symbol symbol : symbols) {
|
||||
if (symbol.isPrimary()) {
|
||||
return symbol.getName();
|
||||
}
|
||||
Symbol primary = symbolTable.getPrimarySymbol(address);
|
||||
if (primary != null) {
|
||||
return primary.getName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -264,8 +264,10 @@ public class FixUpRttiAnalysisScript extends GhidraScript {
|
||||
Address baseClassDescriptorAddress = getReferencedAddress(address.add(i * 4));
|
||||
|
||||
Data baseClassDescriptor = getDataAt(baseClassDescriptorAddress);
|
||||
if (baseClassDescriptor == null || !baseClassDescriptor.getDataType().getName().equals(
|
||||
RTTI_BASE_CLASS_DESCRIPTOR_DATA_NAME)) {
|
||||
if (baseClassDescriptor == null || !baseClassDescriptor.getDataType()
|
||||
.getName()
|
||||
.equals(
|
||||
RTTI_BASE_CLASS_DESCRIPTOR_DATA_NAME)) {
|
||||
|
||||
int num1 = getInt(baseClassDescriptorAddress.add(8));
|
||||
int num2 = getInt(baseClassDescriptorAddress.add(12));
|
||||
@@ -352,8 +354,10 @@ public class FixUpRttiAnalysisScript extends GhidraScript {
|
||||
Data classHierarchyStructure = getDataAt(classHierarchyDescriptorAddress);
|
||||
|
||||
if (classHierarchyStructure != null &&
|
||||
classHierarchyStructure.getDataType().getName().equals(
|
||||
RTTI_CLASS_HIERARCHY_DESCRIPTOR_DATA_NAME)) {
|
||||
classHierarchyStructure.getDataType()
|
||||
.getName()
|
||||
.equals(
|
||||
RTTI_CLASS_HIERARCHY_DESCRIPTOR_DATA_NAME)) {
|
||||
return classHierarchyDescriptorAddress;
|
||||
|
||||
}
|
||||
@@ -588,7 +592,7 @@ public class FixUpRttiAnalysisScript extends GhidraScript {
|
||||
private Symbol getGivenSymbol(Address address, String name, Namespace namespace)
|
||||
throws CancelledException {
|
||||
|
||||
Symbol[] symbols = symbolTable.getSymbols(address);
|
||||
SymbolIterator symbols = symbolTable.getSymbolsAsIterator(address);
|
||||
for (Symbol sym : symbols) {
|
||||
monitor.checkCanceled();
|
||||
if (sym.getName().contains(name) && sym.getParentNamespace().equals(namespace)) {
|
||||
|
||||
+1
-1
@@ -278,7 +278,7 @@ public class EHDataTypeUtilities {
|
||||
dataTypeName = SymbolUtilities.replaceInvalidChars(dataTypeName, true);
|
||||
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
Symbol[] symbols = symbolTable.getSymbols(address);
|
||||
SymbolIterator symbols = symbolTable.getSymbolsAsIterator(address);
|
||||
for (Symbol symbol : symbols) {
|
||||
if (symbol.getName().contains(dataTypeName)) {
|
||||
return null; // Already have one with dataTypeName.
|
||||
|
||||
+17
-16
@@ -65,7 +65,7 @@ public class RttiUtil {
|
||||
*/
|
||||
static boolean createSymbolFromDemangledType(Program program, Address rttiAddress,
|
||||
TypeDescriptorModel typeDescriptorModel, String rttiSuffix) {
|
||||
|
||||
|
||||
rttiSuffix = SymbolUtilities.replaceInvalidChars(rttiSuffix, true);
|
||||
|
||||
// Get or create the namespace for this RTTI's type descriptor.
|
||||
@@ -97,7 +97,7 @@ public class RttiUtil {
|
||||
return false;
|
||||
}
|
||||
// Don't create it if a similar symbol already exists at the address of the data.
|
||||
Symbol[] symbols = symbolTable.getSymbols(rttiAddress);
|
||||
SymbolIterator symbols = symbolTable.getSymbolsAsIterator(rttiAddress);
|
||||
for (Symbol symbol : symbols) {
|
||||
String name = symbol.getName();
|
||||
if (name.contains(rttiSuffix)) {
|
||||
@@ -159,7 +159,7 @@ public class RttiUtil {
|
||||
}
|
||||
|
||||
// check in .text and .nep if either exists
|
||||
if ( textBlock != null || nepBlock != null) {
|
||||
if (textBlock != null || nepBlock != null) {
|
||||
MemoryBlock refedBlock = memory.getBlock(referencedAddress);
|
||||
boolean inTextBlock = ((textBlock != null) && textBlock.equals(refedBlock));
|
||||
boolean inNepBlock = ((nepBlock != null) && nepBlock.equals(refedBlock));
|
||||
@@ -168,12 +168,12 @@ public class RttiUtil {
|
||||
break; // Not pointing to good section.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// any references after the first one ends the table
|
||||
if (tableSize > 0 && referenceManager.hasReferencesTo(currentVfPointerAddress)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Function function = functionManager.getFunctionAt(referencedAddress);
|
||||
|
||||
if (function == null &&
|
||||
@@ -212,12 +212,12 @@ public class RttiUtil {
|
||||
boolean terminationRequest = false;
|
||||
Address commonVftableAddress = null;
|
||||
Program program;
|
||||
|
||||
|
||||
public CommonRTTIMatchCounter(Program program) {
|
||||
this.program = program;
|
||||
defaultPointerSize = program.getDefaultPointerSize();
|
||||
}
|
||||
|
||||
|
||||
public Address getinfoVfTable() {
|
||||
return commonVftableAddress;
|
||||
}
|
||||
@@ -249,10 +249,10 @@ public class RttiUtil {
|
||||
}
|
||||
matchingAddrCount = 0;
|
||||
}
|
||||
|
||||
|
||||
commonVftableAddress = possibleVftableAddress;
|
||||
matchingAddrCount++;
|
||||
|
||||
|
||||
if (matchingAddrCount > MIN_MATCHING_VFTABLE_PTRS) {
|
||||
// done finding good addresses have at Minimum matching number
|
||||
terminationRequest = true;
|
||||
@@ -261,7 +261,7 @@ public class RttiUtil {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method to figure out the type_info vftable address using pointed to value by all RTTI classes
|
||||
* @param program the current program
|
||||
@@ -293,7 +293,7 @@ public class RttiUtil {
|
||||
dataBlocks, set, monitor);
|
||||
infoVftableAddress = vfTableAddrChecker.getinfoVfTable();
|
||||
}
|
||||
|
||||
|
||||
// cache result of search
|
||||
vftableMap.put(program, infoVftableAddress);
|
||||
|
||||
@@ -308,18 +308,18 @@ public class RttiUtil {
|
||||
private static Address findTypeInfoVftableLabel(Program program) {
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
Namespace typeinfoNamespace =
|
||||
symbolTable.getNamespace(TYPE_INFO_NAMESPACE, program.getGlobalNamespace());
|
||||
symbolTable.getNamespace(TYPE_INFO_NAMESPACE, program.getGlobalNamespace());
|
||||
Symbol vftableSymbol =
|
||||
symbolTable.getLocalVariableSymbol("vftable", typeinfoNamespace);
|
||||
symbolTable.getLocalVariableSymbol("vftable", typeinfoNamespace);
|
||||
if (vftableSymbol != null) {
|
||||
return vftableSymbol.getAddress();
|
||||
}
|
||||
|
||||
|
||||
vftableSymbol = symbolTable.getLocalVariableSymbol("`vftable'", typeinfoNamespace);
|
||||
if (vftableSymbol != null) {
|
||||
return vftableSymbol.getAddress();
|
||||
}
|
||||
|
||||
|
||||
vftableSymbol = symbolTable.getLocalVariableSymbol("type_info", typeinfoNamespace);
|
||||
if (vftableSymbol != null) {
|
||||
return vftableSymbol.getAddress();
|
||||
@@ -358,7 +358,8 @@ public class RttiUtil {
|
||||
}
|
||||
|
||||
// check to see if symbol already exists both non-pdb and pdb versions
|
||||
Symbol vftableSymbol = symbolTable.getSymbol(TYPE_INFO_NAMESPACE, address, typeinfoNamespace);
|
||||
Symbol vftableSymbol =
|
||||
symbolTable.getSymbol(TYPE_INFO_NAMESPACE, address, typeinfoNamespace);
|
||||
if (vftableSymbol != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
+12
-5
@@ -57,6 +57,7 @@ public class BlockGraphTask extends Task {
|
||||
private ColorizingService colorizingService;
|
||||
|
||||
private final static String ENTRY_NEXUS_NAME = "Entry Points";
|
||||
private static final int MAX_SYMBOLS = 10;
|
||||
private CodeBlockModel blockModel;
|
||||
private AddressSetView selection;
|
||||
private ProgramLocation location;
|
||||
@@ -417,14 +418,20 @@ public class BlockGraphTask extends Task {
|
||||
}
|
||||
|
||||
private void addSymbolAttribute(AttributedVertex vertex, CodeBlock bb) {
|
||||
Symbol[] symbols = program.getSymbolTable().getSymbols(bb.getMinAddress());
|
||||
if (symbols.length != 0) {
|
||||
SymbolIterator it = program.getSymbolTable().getSymbolsAsIterator(bb.getMinAddress());
|
||||
int count = 0;
|
||||
if (it.hasNext()) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (int i = 0; i < symbols.length; i++) {
|
||||
if (i != 0) {
|
||||
for (Symbol symbol : it) {
|
||||
if (count != 0) {
|
||||
buf.append('\n');
|
||||
}
|
||||
buf.append(symbols[i].getName());
|
||||
// limit the number of symbols to include (there can be a ridiculous # of symbols)
|
||||
if (count++ > MAX_SYMBOLS) {
|
||||
buf.append("...");
|
||||
break;
|
||||
}
|
||||
buf.append(symbol.getName());
|
||||
}
|
||||
vertex.setAttribute(SYMBOLS_ATTRIBUTE, buf.toString());
|
||||
}
|
||||
|
||||
+1
-6
@@ -15,8 +15,7 @@
|
||||
*/
|
||||
package ghidra.feature.vt.api.markuptype;
|
||||
|
||||
import static ghidra.feature.vt.gui.util.VTOptionDefines.DEFAULT_OPTION_FOR_LABELS;
|
||||
import static ghidra.feature.vt.gui.util.VTOptionDefines.LABELS;
|
||||
import static ghidra.feature.vt.gui.util.VTOptionDefines.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -232,10 +231,6 @@ public class LabelMarkupType extends VTMarkupType {
|
||||
LabelMarkupUtils.removeAllLabels(getDestinationProgram(association),
|
||||
destinationAddress);
|
||||
}
|
||||
else if (replaceDefault) {
|
||||
LabelMarkupUtils.removeDefaultLabels(getDestinationProgram(association),
|
||||
destinationAddress);
|
||||
}
|
||||
|
||||
Program destinationProgram = getDestinationProgram(association);
|
||||
try {
|
||||
|
||||
+10
-27
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,31 +23,15 @@ import ghidra.program.model.symbol.SymbolTable;
|
||||
|
||||
public class LabelMarkupUtils {
|
||||
|
||||
public static void removeDefaultLabels( Program destinationProgram, Address address ) {
|
||||
SymbolTable symbolTable = destinationProgram.getSymbolTable();
|
||||
Symbol[] symbols = symbolTable.getSymbols( address );
|
||||
for ( Symbol symbol : symbols ) {
|
||||
if ( symbol instanceof FunctionSymbol ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !symbol.isDynamic() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
symbolTable.removeSymbolSpecial( symbol );
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeAllLabels( Program destinationProgram, Address address ) {
|
||||
SymbolTable symbolTable = destinationProgram.getSymbolTable();
|
||||
Symbol[] symbols = symbolTable.getSymbols( address );
|
||||
for ( Symbol symbol : symbols ) {
|
||||
if ( symbol instanceof FunctionSymbol ) {
|
||||
continue;
|
||||
}
|
||||
symbolTable.removeSymbolSpecial( symbol );
|
||||
}
|
||||
}
|
||||
public static void removeAllLabels(Program destinationProgram, Address address) {
|
||||
SymbolTable symbolTable = destinationProgram.getSymbolTable();
|
||||
Symbol[] symbols = symbolTable.getSymbols(address);
|
||||
for (Symbol symbol : symbols) {
|
||||
if (symbol instanceof FunctionSymbol) {
|
||||
continue;
|
||||
}
|
||||
symbolTable.removeSymbolSpecial(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -401,7 +401,7 @@ public class NamespaceUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
Symbol[] symbols = program.getSymbolTable().getSymbols(address);
|
||||
SymbolIterator symbols = program.getSymbolTable().getSymbolsAsIterator(address);
|
||||
for (Symbol symbol : symbols) {
|
||||
if (symbol.getSymbolType() == SymbolType.FUNCTION &&
|
||||
symbolPath.matchesPathOf(symbol)) {
|
||||
|
||||
+8
-8
@@ -757,16 +757,14 @@ public class PseudoDisassembler {
|
||||
for (Address flow : flows) {
|
||||
// does this reference a valid function?
|
||||
if (program != null) {
|
||||
Symbol[] syms = program.getSymbolTable().getSymbols(flow);
|
||||
for (Symbol sym : syms) {
|
||||
if (sym.getSymbolType() == SymbolType.FUNCTION) {
|
||||
didCallValidSubroutine = true;
|
||||
break;
|
||||
}
|
||||
Symbol primary = program.getSymbolTable().getPrimarySymbol(flow);
|
||||
if (primary.getSymbolType() == SymbolType.FUNCTION) {
|
||||
didCallValidSubroutine = true;
|
||||
}
|
||||
}
|
||||
// if respecting execute flag on memory, test to make sure we did flow into non-execute memory
|
||||
if (respectExecuteFlag && !execSet.isEmpty() && !execSet.contains(flow)) {
|
||||
if (respectExecuteFlag && !execSet.isEmpty() &&
|
||||
!execSet.contains(flow)) {
|
||||
if (!flow.isExternalAddress()) {
|
||||
MemoryBlock block = memory.getBlock(flow);
|
||||
// flowing into non-executable, but readable memory is bad
|
||||
@@ -782,7 +780,9 @@ public class PseudoDisassembler {
|
||||
target = newTarget;
|
||||
}
|
||||
}
|
||||
catch (InsufficientBytesException e) {
|
||||
catch (
|
||||
|
||||
InsufficientBytesException e) {
|
||||
return false;
|
||||
}
|
||||
catch (UnknownInstructionException e) {
|
||||
|
||||
+18
-4
@@ -270,16 +270,21 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
||||
try {
|
||||
checkIsValid();
|
||||
ReferenceManager rm = symbolMgr.getReferenceManager();
|
||||
ReferenceIterator iter = rm.getReferencesTo(address);
|
||||
boolean isPrimary = this.isPrimary();
|
||||
Symbol[] symbols = symbolMgr.getSymbols(address);
|
||||
if (symbols.length == 1) {
|
||||
|
||||
// if there is only one symbol, then all the references to this address count
|
||||
if (hasExactlyOneSymbolAtAddress(address)) {
|
||||
return rm.getReferenceCountTo(address);
|
||||
}
|
||||
|
||||
// search through references and see which ones apply specifically to this symbol
|
||||
ReferenceIterator iter = rm.getReferencesTo(address);
|
||||
int count = 0;
|
||||
boolean isPrimary = this.isPrimary();
|
||||
while (iter.hasNext()) {
|
||||
Reference ref = iter.next();
|
||||
long symbolID = ref.getSymbolID();
|
||||
// references refer to me if it matches my key or I'm primary and it doesn't
|
||||
// specify a specific symbol id
|
||||
if (symbolID == key || (isPrimary && symbolID < 0)) {
|
||||
count++;
|
||||
}
|
||||
@@ -291,6 +296,15 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasExactlyOneSymbolAtAddress(Address addr) {
|
||||
SymbolIterator it = symbolMgr.getSymbolsAsIterator(addr);
|
||||
if (!it.hasNext()) {
|
||||
return false;
|
||||
}
|
||||
it.next();
|
||||
return !it.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Reference[] getReferences(TaskMonitor monitor) {
|
||||
lock.acquire();
|
||||
|
||||
+26
-49
@@ -600,7 +600,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
||||
if (sym.getSymbolType() == SymbolType.FUNCTION) {
|
||||
Address addr = sym.getAddress();
|
||||
Function f = (Function) sym.getObject();
|
||||
Symbol nextPrimary = getNextPrimarySymbol(this, addr);
|
||||
Symbol nextPrimary = findFirstNonPrimarySymbol(addr);
|
||||
String name;
|
||||
Namespace parentNamespace;
|
||||
SourceType source;
|
||||
@@ -636,20 +636,14 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
||||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public boolean removeSymbol(Symbol sym) {
|
||||
// return removeSymbolSpecial(sym);
|
||||
// }
|
||||
|
||||
private Symbol getNextPrimarySymbol(SymbolManager sm, Address addr2) {
|
||||
Symbol[] symbols = sm.getSymbols(addr2);
|
||||
Symbol next = null;
|
||||
for (int i = symbols.length - 1; i >= 0; i--) {
|
||||
if (!symbols[i].isPrimary()) {
|
||||
return symbols[i]; // For now return the last non-primary found.
|
||||
private Symbol findFirstNonPrimarySymbol(Address address) {
|
||||
SymbolIterator it = getSymbolsAsIterator(address);
|
||||
for (Symbol symbol : it) {
|
||||
if (!symbol.isPrimary()) {
|
||||
return symbol; // return the first non-primary symbol we find
|
||||
}
|
||||
}
|
||||
return next;
|
||||
return null;
|
||||
}
|
||||
|
||||
void removeChildren(SymbolDB sym) {
|
||||
@@ -804,6 +798,21 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
||||
return false;
|
||||
}
|
||||
|
||||
public SymbolIterator getSymbolsAsIterator(Address addr) {
|
||||
lock.acquire();
|
||||
try {
|
||||
RecordIterator iterator = adapter.getSymbols(addr, addr, true);
|
||||
return new SymbolRecordIterator(iterator, true, true);
|
||||
}
|
||||
catch (IOException e) {
|
||||
program.dbError(e);
|
||||
}
|
||||
finally {
|
||||
lock.release();
|
||||
}
|
||||
return new SymbolRecordIterator(new EmptyRecordIterator(), true, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Symbol[] getSymbols(Address addr) {
|
||||
lock.acquire();
|
||||
@@ -932,14 +941,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
||||
|
||||
@Override
|
||||
public Symbol getGlobalSymbol(String name, Address addr) {
|
||||
Symbol[] symbols = getSymbols(addr);
|
||||
for (Symbol symbol : symbols) {
|
||||
// there can be only one global symbol with a name at an address
|
||||
if (symbol.getName().equals(name) && symbol.isGlobal()) {
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return getSymbol(name, addr, program.getGlobalNamespace());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1714,9 +1716,9 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
||||
|
||||
private void findNextDynamicSymbol() {
|
||||
while (addrIt.hasNext()) {
|
||||
Symbol[] symbols = getSymbols(addrIt.next());
|
||||
if (symbols.length == 1 && symbols[0].isDynamic()) {
|
||||
nextDynamicSymbol = symbols[0];
|
||||
Symbol symbol = getPrimarySymbol(addrIt.next());
|
||||
if (symbol != null && symbol.isDynamic()) {
|
||||
nextDynamicSymbol = symbol;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -3062,28 +3064,3 @@ public class SymbolManager implements SymbolTable, ManagerDB {
|
||||
return getFirstSymbol(name, namespace, s -> s.getSymbolType() == type);
|
||||
}
|
||||
}
|
||||
|
||||
class SymbolMatcher implements Predicate<Symbol> {
|
||||
|
||||
private String name;
|
||||
private Namespace namespace;
|
||||
private SymbolType type1;
|
||||
|
||||
public SymbolMatcher(String name, Namespace namespace, SymbolType type1) {
|
||||
this.name = name;
|
||||
this.namespace = namespace;
|
||||
this.type1 = type1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Symbol s) {
|
||||
if (!name.equals(s.getName())) {
|
||||
return false;
|
||||
}
|
||||
if (!namespace.equals(s.getParentNamespace())) {
|
||||
return false;
|
||||
}
|
||||
SymbolType type = s.getSymbolType();
|
||||
return type == type1;
|
||||
}
|
||||
}
|
||||
|
||||
+15
@@ -353,11 +353,26 @@ public interface SymbolTable {
|
||||
* the primary symbol will be returned in array slot 0.
|
||||
* WARNING! Use of this method with a Variable address is highly discouraged since
|
||||
* a single Variable address could be used multiple times by many functions.
|
||||
* Note that unless all the symbols are needed at once, you should consider using
|
||||
* the {@link #getSymbolsAsIterator(Address)} method instead.
|
||||
* @param addr the address at which to retrieve all symbols.
|
||||
* @return a zero-length array when no symbols are defined at address.
|
||||
* @see #getSymbolsAsIterator(Address)
|
||||
*/
|
||||
public Symbol[] getSymbols(Address addr);
|
||||
|
||||
/**
|
||||
* Returns a symbol iterator over all the symbols at the given address. Use this instead of
|
||||
* {@link #getSymbols(Address)} when you do not need to get all symbols, but rather are
|
||||
* searching for a particular symbol. This method prevents all symbols at the given address
|
||||
* from being loaded up front.
|
||||
*
|
||||
* @param addr the address at which to retrieve all symbols
|
||||
* @return an iterator over all the symbols at the given address
|
||||
* @see #getSymbols(Address)
|
||||
*/
|
||||
public SymbolIterator getSymbolsAsIterator(Address addr);
|
||||
|
||||
/**
|
||||
* Returns an array of all user defined symbols at the given address
|
||||
* @param addr the address at which to retrieve all user defined symbols.
|
||||
|
||||
+1
-1
@@ -1032,7 +1032,7 @@ public class SymbolUtilities {
|
||||
|
||||
if (namespace.isGlobal()) {
|
||||
// do not add global symbol if same name already exists at address
|
||||
for (Symbol s : program.getSymbolTable().getSymbols(address)) {
|
||||
for (Symbol s : program.getSymbolTable().getSymbolsAsIterator(address)) {
|
||||
if (name.equals(s.getName())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user