diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewSymbolTable.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewSymbolTable.java index e9320519c4..a9f4e2dfc2 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewSymbolTable.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewSymbolTable.java @@ -380,6 +380,11 @@ public class DBTraceProgramViewSymbolTable implements SymbolTable { })); } + @Override + public SymbolIterator scanSymbolsByName(String startName) { + return new SymbolIteratorAdapter(symbolManager.allSymbols().scanByName(startName)); + } + @Override public int getNumSymbols() { return symbolManager.allSymbols().size(true); diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/AbstractDBTraceSymbolSingleTypeView.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/AbstractDBTraceSymbolSingleTypeView.java index af12dd7ee6..efa32301cd 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/AbstractDBTraceSymbolSingleTypeView.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/AbstractDBTraceSymbolSingleTypeView.java @@ -88,6 +88,10 @@ public abstract class AbstractDBTraceSymbolSingleTypeView predicate.test(s.name)); } + public Iterator scanByName(String startName) { + return symbolsByName.tail(startName, true).values().iterator(); + } + public T getByKey(long key) { return store.getObjectAt(key); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceSymbolMultipleTypesView.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceSymbolMultipleTypesView.java index 3f04311d41..6fd825bf2f 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceSymbolMultipleTypesView.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceSymbolMultipleTypesView.java @@ -15,13 +15,14 @@ */ package ghidra.trace.database.symbol; -import java.util.Arrays; -import java.util.Collection; +import java.util.*; +import java.util.stream.Collectors; import com.google.common.collect.Collections2; import generic.CatenatedCollection; import ghidra.trace.model.symbol.*; +import ghidra.util.MergeSortingIterator; public class DBTraceSymbolMultipleTypesView implements TraceSymbolView { @@ -73,4 +74,11 @@ public class DBTraceSymbolMultipleTypesView return new CatenatedCollection<>( Collections2.transform(parts, p -> p.getWithMatchingName(glob, caseSensitive))); } + + @Override + public Iterator scanByName(String startName) { + List> iterators = + parts.stream().map(p -> p.scanByName(startName)).collect(Collectors.toList()); + return new MergeSortingIterator<>(iterators, Comparator.comparing(s -> s.getName())); + } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/symbol/TraceSymbolView.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/symbol/TraceSymbolView.java index b28eaaef94..63e4f19aea 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/symbol/TraceSymbolView.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/model/symbol/TraceSymbolView.java @@ -16,6 +16,7 @@ package ghidra.trace.model.symbol; import java.util.Collection; +import java.util.Iterator; public interface TraceSymbolView { @@ -55,4 +56,6 @@ public interface TraceSymbolView { * @return the collection of matching symbols */ Collection getWithMatchingName(String glob, boolean caseSensitive); + + Iterator scanByName(String startName); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/SymbolTablePlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/SymbolTablePlugin.java index c61214ee47..e383f49d4f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/SymbolTablePlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/SymbolTablePlugin.java @@ -722,7 +722,7 @@ public class SymbolTablePlugin extends Plugin implements DomainObjectListener { } } else if (toAddr.isMemoryAddress() && symProvider.isShowingDynamicSymbols()) { - long dynamicSymbolId = symbolTable.getDynamicSymbolID(reference.getToAddress()); + long dynamicSymbolId = symbolTable.getDynamicSymbolID(toAddr); symProvider.symbolRemoved(dynamicSymbolId); refProvider.symbolRemoved(dynamicSymbolId); } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/symbol/SymbolManagerTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/symbol/SymbolManagerTest.java index 9ed7486fba..10d1a3f0f2 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/symbol/SymbolManagerTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/symbol/SymbolManagerTest.java @@ -1265,6 +1265,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest { createExternalFunction("7"); createExternalLabel("8"); + // test restricted address range AddressSet set = new AddressSet(addr(0), addr(50)); set.addRange(addr(300), addr(350)); set.addRange(addr(500), addr(1000)); @@ -1275,22 +1276,48 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest { // External space before memory space Symbol s = it.next(); assertNotNull(s); - assertEquals("7", s.getName()); + assertEquals("Test::7", s.getName(true)); assertEquals(extAddr(1), s.getAddress()); s = it.next(); assertNotNull(s); - assertEquals("8", s.getName()); + assertEquals("Test::8", s.getName(true)); assertEquals(extAddr(2), s.getAddress()); s = it.next(); assertNotNull(s); + assertEquals("3", s.getName(true)); assertEquals(addr(300), s.getAddress()); s = it.next(); assertNotNull(s); + assertEquals("5", s.getName(true)); assertEquals(addr(500), s.getAddress()); assertTrue(!it.hasNext()); assertNull(it.next()); + + // test all memory/external + it = st.getPrimarySymbolIterator((AddressSetView) null, true); + + assertTrue(it.hasNext()); + s = it.next(); + assertNotNull(s); + assertEquals("Test::7", s.getName(true)); + + assertTrue(it.hasNext()); + s = it.next(); + assertNotNull(s); + assertEquals("Test::8", s.getName(true)); + + for (int i = 1; i <= 6; i++) { + assertTrue(it.hasNext()); + s = it.next(); + assertNotNull(s); + assertEquals(Integer.toString(i), s.getName(true)); + } + + assertTrue(!it.hasNext()); + assertNull(it.next()); + } @Test @@ -1433,12 +1460,31 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest { createLabel(addr(100), "1"); createLabel(addr(200), "2"); createLabel(addr(300), "3"); + Function extFunc = createExternalFunction("X"); + createExternalLabel("Y"); Function f1 = createFunction("A", addr(150)); Function f2 = createFunction("B", addr(250)); - SymbolIterator it = - st.getSymbols(new AddressSet(addr(0), addr(5000)), SymbolType.FUNCTION, true); + // test over constrained address set + AddressSet set = new AddressSet(addr(0), addr(200)); + set.addRange(AddressSpace.EXTERNAL_SPACE.getMinAddress(), + AddressSpace.EXTERNAL_SPACE.getMaxAddress()); + + SymbolIterator it = st.getSymbols(set, SymbolType.FUNCTION, true); + + assertTrue(it.hasNext()); + assertEquals(extFunc.getSymbol(), it.next()); + + assertTrue(it.hasNext()); + assertEquals(f1.getSymbol(), it.next()); + + assertFalse(it.hasNext()); + + it = st.getSymbols(null, SymbolType.FUNCTION, true); + + assertTrue(it.hasNext()); + assertEquals(extFunc.getSymbol(), it.next()); assertTrue(it.hasNext()); assertEquals(f1.getSymbol(), it.next()); @@ -2440,11 +2486,11 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest { .getSymbol(); } - private Symbol createExternalFunction(String name) + private Function createExternalFunction(String name) throws InvalidInputException, DuplicateNameException { ExternalManager externalManager = program.getExternalManager(); return externalManager.addExtFunction("Test", name, null, SourceType.USER_DEFINED) - .getSymbol(); + .getFunction(); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/assembler/sleigh/symbol/AssemblyNumericSymbols.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/assembler/sleigh/symbol/AssemblyNumericSymbols.java index b39e098cce..08b44706a5 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/assembler/sleigh/symbol/AssemblyNumericSymbols.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/assembler/sleigh/symbol/AssemblyNumericSymbols.java @@ -16,7 +16,9 @@ package ghidra.app.plugin.assembler.sleigh.symbol; import java.util.*; -import java.util.stream.Collectors; +import java.util.Map.Entry; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSpace; @@ -30,8 +32,7 @@ import ghidra.program.model.symbol.*; * A context to hold various symbols offered to the assembler, usable where numbers are expected. */ public final class AssemblyNumericSymbols { - public static final AssemblyNumericSymbols EMPTY = - new AssemblyNumericSymbols(Map.of(), Map.of(), Map.of()); + public static final AssemblyNumericSymbols EMPTY = new AssemblyNumericSymbols(); /** * Collect labels derived from memory-mapped registers in a language @@ -42,7 +43,8 @@ public final class AssemblyNumericSymbols { * @param labels the destination map * @param language the language */ - private static void collectLanguageLabels(Map> labels, Language language) { + private static NavigableMap> collectLanguageLabels(Language language) { + NavigableMap> labels = new TreeMap<>(); for (Register reg : language.getRegisters()) { // TODO/HACK: There ought to be a better mechanism describing suitable symbolic // substitutions for a given operand. @@ -50,42 +52,25 @@ public final class AssemblyNumericSymbols { labels.computeIfAbsent(reg.getName(), n -> new HashSet<>()).add(reg.getAddress()); } } + return labels; } - /** - * Collect labels from the program's database - * - * @param labels the destination map - * @param program the source program - */ - private static void collectProgramLabels(Map> labels, Program program) { - final SymbolIterator it = program.getSymbolTable().getAllSymbols(true); - while (it.hasNext()) { - Symbol sym = it.next(); - SymbolType symbolType = sym.getSymbolType(); - if (symbolType == SymbolType.LABEL) { - if (sym.isExternal()) { - continue; - } - labels.computeIfAbsent(sym.getName(), n -> new HashSet<>()).add(sym.getAddress()); - } - else if (symbolType == SymbolType.FUNCTION) { - if (!sym.getAddress().isExternalAddress()) { - labels.computeIfAbsent(sym.getName(), n -> new HashSet<>()) - .add(sym.getAddress()); - } - Function function = (Function) sym.getObject(); - Address[] thunks = function.getFunctionThunkAddresses(true); - if (thunks != null) { - for (Address t : thunks) { - if (!t.isExternalAddress()) { - labels.computeIfAbsent(sym.getName(), n -> new HashSet<>()).add(t); - } - } - } - } - // Ignore other symbol types + private static Stream
streamAddresses(Symbol sym) { + SymbolType symbolType = sym.getSymbolType(); + if (symbolType == SymbolType.LABEL) { + return Stream.of(sym.getAddress()); } + if (symbolType == SymbolType.FUNCTION) { + Function function = (Function) sym.getObject(); + Address[] thunks = function.getFunctionThunkAddresses(true); + return thunks == null ? Stream.of(sym.getAddress()) + : Stream.concat(Stream.of(sym.getAddress()), Stream.of(thunks)); + } + return Stream.of(); + } + + private static Stream
streamNonExternalAddresses(Symbol sym) { + return streamAddresses(sym).filter(a -> !a.isExternalAddress()); } /** @@ -94,13 +79,15 @@ public final class AssemblyNumericSymbols { * @param equates the destination map * @param programthe source program */ - private static void collectProgramEquates(Map> equates, Program program) { + private static NavigableMap> collectProgramEquates(Program program) { + NavigableMap> equates = new TreeMap<>(); final Iterator it = program.getEquateTable().getEquates(); while (it.hasNext()) { Equate eq = it.next(); // Thought is: If that's what the user sees, then that's what the user will type! equates.computeIfAbsent(eq.getDisplayName(), n -> new HashSet<>()).add(eq.getValue()); } + return equates; } /** @@ -110,84 +97,60 @@ public final class AssemblyNumericSymbols { * @return the symbols */ public static AssemblyNumericSymbols fromLanguage(Language language) { - Map> labels = new HashMap<>(); - collectLanguageLabels(labels, language); - return forMaps(Map.of(), labels); + return new AssemblyNumericSymbols(language); } /** * Get symbols from a program (and its language) * - *

- * TODO: It might be nice to cache these and use a listener to keep the maps up to date. Will - * depend on interactive performance. - * * @param program the program * @return the symbols */ public static AssemblyNumericSymbols fromProgram(Program program) { - Map> equates = new HashMap<>(); - Map> labels = new HashMap<>(); - collectLanguageLabels(labels, program.getLanguage()); - collectProgramLabels(labels, program); - collectProgramEquates(equates, program); - return forMaps(equates, labels); + return new AssemblyNumericSymbols(program); } - /** - * Get symbols for the given equate and label maps - * - * @param equates the equates - * @param labels the labels - * @return the symbols - */ - public static AssemblyNumericSymbols forMaps(Map> equates, - Map> labels) { - return new AssemblyNumericSymbols(Map.copyOf(equates), Map.copyOf(labels), - groupBySpace(labels)); + public final NavigableMap> programEquates; + public final NavigableMap> languageLabels; + private final Program program; + + private AssemblyNumericSymbols() { + this.program = null; + this.programEquates = new TreeMap<>(); + this.languageLabels = new TreeMap<>(); } - private static Map>> groupBySpace( - Map> labels) { - Map>> result = new HashMap<>(); - for (Map.Entry> entry : labels.entrySet()) { - for (Address addr : entry.getValue()) { - result.computeIfAbsent(addr.getAddressSpace(), as -> new HashMap<>()) - .computeIfAbsent(entry.getKey(), k -> new TreeSet<>()) - .add(addr); - } - } - return Collections.unmodifiableMap(result); + private AssemblyNumericSymbols(Language language) { + this.program = null; + this.programEquates = new TreeMap<>(); + this.languageLabels = collectLanguageLabels(language); } - private final NavigableSet all = new TreeSet<>(); - public final Map> equates; - public final Map> labels; - public final Map>> labelsBySpace; - - private AssemblyNumericSymbols(Map> equates, Map> labels, - Map>> labelsBySpace) { - this.equates = equates; - this.labels = labels; - this.labelsBySpace = labelsBySpace; - all.addAll(equates.keySet()); - all.addAll(labels.keySet()); + private AssemblyNumericSymbols(Program program) { + this.program = program; + this.programEquates = collectProgramEquates(program); + this.languageLabels = collectLanguageLabels(program.getLanguage()); } /** * Choose any symbol with the given name * *

- * This will check equates first, then labels. If an equate is found, its value is returned. If - * a label is found, its addressable word offset is returned. + * This will order equates first, then program labels, then language labels. For addresses, the + * value is its addressable word offset. * * @param name the name * @return the value, or null */ public Set chooseAll(String name) { Set result = new TreeSet<>(); - result.addAll(equates.getOrDefault(name, Set.of())); - for (Address address : labels.getOrDefault(name, Set.of())) { + result.addAll(programEquates.getOrDefault(name, Set.of())); + if (program != null) { + StreamSupport.stream(program.getSymbolTable().getSymbols(name).spliterator(), false) + .flatMap(sym -> streamNonExternalAddresses(sym)) + .forEach(a -> result.add(a.getAddressableWordOffset())); + } + for (Address address : languageLabels.getOrDefault(name, Set.of())) { result.add(address.getAddressableWordOffset()); } return result; @@ -201,11 +164,20 @@ public final class AssemblyNumericSymbols { * @return the addressable word offset of the found label, or null */ public Set chooseBySpace(String name, AddressSpace space) { - return labelsBySpace.getOrDefault(space, Map.of()) - .getOrDefault(name, Set.of()) - .stream() - .map(a -> a.getAddressableWordOffset()) - .collect(Collectors.toSet()); + Set result = new TreeSet<>(); + if (program != null) { + StreamSupport.stream(program.getSymbolTable().getSymbols(name).spliterator(), false) + .flatMap(sym -> streamAddresses(sym)) + .filter(a -> a.getAddressSpace() == space) + .forEach(a -> result.add(a.getAddressableWordOffset())); + } + for (Address address : languageLabels.getOrDefault(name, Set.of())) { + if (address.getAddressSpace() != space) { + continue; + } + result.add(address.getAddressableWordOffset()); + } + return result; } /** @@ -228,23 +200,59 @@ public final class AssemblyNumericSymbols { return chooseBySpace(name, space); } - private Collection suggestFrom(String got, Collection keys, int max, - boolean sorted) { - Set result = new HashSet<>(); + private void suggestFrom(List result, String got, NavigableSet keys, int max) { int count = 0; - for (String label : keys) { - if (count >= max) { - break; - } - if (label.startsWith(got)) { - result.add(label); - count++; - } - else if (sorted) { - break; + for (String k : keys.tailSet(got)) { + if (count >= max || !k.startsWith(got)) { + return; } + result.add(k); + count++; + } + } + + private void suggestFromBySpace(List result, String got, + NavigableMap> labels, int max, AddressSpace space) { + int count = 0; + for (Entry> ent : labels.entrySet()) { + if (count >= max || !ent.getKey().startsWith(got)) { + return; + } + if (!ent.getValue().stream().anyMatch(a -> a.getAddressSpace() == space)) { + continue; + } + result.add(ent.getKey()); + count++; + } + } + + private void suggestFromProgramAny(List result, String got, int max) { + int count = 0; + for (Symbol s : program.getSymbolTable().scanSymbolsByName(got)) { + if (count >= max || !s.getName().startsWith(got)) { + return; + } + if (streamNonExternalAddresses(s).findAny().isEmpty()) { + continue; + } + result.add(s.getName()); + count++; + } + } + + private void suggestFromProgramBySpace(List result, String got, int max, + AddressSpace space) { + int count = 0; + for (Symbol s : program.getSymbolTable().scanSymbolsByName(got)) { + if (count >= max || !s.getName().startsWith(got)) { + return; + } + if (!streamAddresses(s).anyMatch(a -> a.getAddressSpace() == space)) { + continue; + } + result.add(s.getName()); + count++; } - return result; } /** @@ -255,7 +263,18 @@ public final class AssemblyNumericSymbols { * @return the collection of symbol names */ public Collection suggestAny(String got, int max) { - return suggestFrom(got, all.tailSet(got), max, true); + List result = new ArrayList<>(); + suggestFrom(result, got, languageLabels.navigableKeySet(), max); + if (program == null) { + return result; + } + suggestFrom(result, got, programEquates.navigableKeySet(), max); + suggestFromProgramAny(result, got, max); + Collections.sort(result); + if (result.size() > max) { + return result.subList(0, max); + } + return result; } /** @@ -267,12 +286,17 @@ public final class AssemblyNumericSymbols { * @return the collection of symbol names */ public Collection suggestBySpace(String got, AddressSpace space, int max) { - Map> forSpace = labelsBySpace.get(space); - if (forSpace == null) { - return Set.of(); + List result = new ArrayList<>(); + suggestFromBySpace(result, got, languageLabels, max, space); + if (program == null) { + return result; } - // TODO: Should I sort these, perhaps lazily, to speed search? - return suggestFrom(got, forSpace.keySet(), max, false); + suggestFromProgramBySpace(result, got, max, space); + Collections.sort(result); + if (result.size() > max) { + return result.subList(0, max); + } + return result; } /** diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/ReferenceDBManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/ReferenceDBManager.java index d26cda1bb2..c649c8620b 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/ReferenceDBManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/ReferenceDBManager.java @@ -1572,8 +1572,9 @@ public class ReferenceDBManager implements ReferenceManager, ManagerDB, ErrorHan * Create a memory reference to the given address to mark it as * an external entry point. * @param toAddr the address at which to make an external entry point + * @throws IllegalArgumentException if a non-memory address is specified */ - public void addExternalEntryPointRef(Address toAddr) { + public void addExternalEntryPointRef(Address toAddr) throws IllegalArgumentException { if (!toAddr.isMemoryAddress()) { throw new IllegalArgumentException("Entry point address must be memory address"); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapter.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapter.java index f64799b909..47031f68ba 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapter.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapter.java @@ -366,6 +366,16 @@ abstract class SymbolDatabaseAdapter { */ abstract RecordIterator getSymbolsByName(String name) throws IOException; + /** + * Scan symbols lexicographically by name starting from the given name + *

+ * This only includes memory-based stored symbols. + * + * @param startName the starting name to search + * @throws IOException if a database io error occurs + */ + abstract RecordIterator scanSymbolsByName(String startName) throws IOException; + /** * Get all symbols contained in the given {@link Namespace} that have the given name * @param name the symbol name diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV0.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV0.java index f5826bfad5..bdd04bc046 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV0.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV0.java @@ -255,6 +255,13 @@ class SymbolDatabaseAdapterV0 extends SymbolDatabaseAdapter { symbolTable.indexIterator(V0_SYMBOL_NAME_COL, val, val, true)); } + @Override + RecordIterator scanSymbolsByName(String startName) throws IOException { + StringField val = new StringField(startName); + return new V0ConvertedRecordIterator( + symbolTable.indexIterator(V0_SYMBOL_NAME_COL, val, null, true)); + } + private class V0ConvertedRecordIterator implements RecordIterator { private RecordIterator symIter; diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV1.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV1.java index 25ad0d7ccd..57602640a9 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV1.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV1.java @@ -254,6 +254,13 @@ class SymbolDatabaseAdapterV1 extends SymbolDatabaseAdapter { symbolTable.indexIterator(V1_SYMBOL_NAME_COL, field, field, true)); } + @Override + RecordIterator scanSymbolsByName(String startName) throws IOException { + StringField val = new StringField(startName); + return new V1ConvertedRecordIterator( + symbolTable.indexIterator(V1_SYMBOL_NAME_COL, val, null, true)); + } + private class V1ConvertedRecordIterator extends ConvertedRecordIterator { V1ConvertedRecordIterator(RecordIterator originalIterator) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV2.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV2.java index e6f249b2c7..57acdb89e6 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV2.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV2.java @@ -229,6 +229,13 @@ class SymbolDatabaseAdapterV2 extends SymbolDatabaseAdapter { return new V2ConvertedRecordIterator(it); } + @Override + RecordIterator scanSymbolsByName(String startName) throws IOException { + StringField field = new StringField(startName); + RecordIterator it = symbolTable.indexIterator(SYMBOL_NAME_COL, field, null, true); + return new V2ConvertedRecordIterator(it); + } + @Override Address getMaxSymbolAddress(AddressSpace space) throws IOException { if (space.isMemorySpace()) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV3.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV3.java index 633f622ae1..dc69a5c0e1 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV3.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV3.java @@ -264,6 +264,12 @@ class SymbolDatabaseAdapterV3 extends SymbolDatabaseAdapter { return symbolTable.indexIterator(SYMBOL_NAME_COL, field, field, true); } + @Override + RecordIterator scanSymbolsByName(String startName) throws IOException { + StringField field = new StringField(startName); + return symbolTable.indexIterator(SYMBOL_NAME_COL, field, null, true); + } + @Override RecordIterator getSymbolsByNameAndNamespace(String name, long id) throws IOException { // create a range of hash fields for all symbols with this name and namespace id over all diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolManager.java index ee31fac974..37d86430f9 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolManager.java @@ -77,6 +77,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { /** * Creates a new Symbol manager. + * * @param handle the database handler * @param addrMap the address map. * @param openMode the open mode. @@ -125,6 +126,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { /** * Find previously defined variable storage address + * * @param storage variable storage * @return previously defined variable storage address or null if not found * @throws IOException if there is database exception @@ -136,7 +138,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { @Override public void setProgram(ProgramDB program) { this.program = program; - refManager = (ReferenceDBManager) program.getReferenceManager(); + refManager = program.getReferenceManager(); namespaceMgr = program.getNamespaceManager(); variableStorageMgr.setProgram(program); } @@ -177,17 +179,18 @@ public class SymbolManager implements SymbolTable, ManagerDB { /** * Check for and upgrade old namespace symbol addresses which included a namespace ID. - * Start at end since Namespace-0 will not result in an OldGenericNamespaceAddress. - * Namespace-0 external symbols do not need to be upgraded since this is effectively - * where all the moved external addresses will be placed. - * The triggering of this upgrade relies on the addition of the VariableManager which - * trigger an upgrade. + *

+ * Start at end since Namespace-0 will not result in an OldGenericNamespaceAddress. Namespace-0 + * external symbols do not need to be upgraded since this is effectively where all the moved + * external addresses will be placed. The triggering of this upgrade relies on the addition of + * the VariableManager which trigger an upgrade. + * * @param monitor the task monitor */ private boolean upgradeOldNamespaceAddresses(TaskMonitor monitor) throws IOException, CancelledException { - ReferenceDBManager refMgr = (ReferenceDBManager) program.getReferenceManager(); + ReferenceDBManager refMgr = program.getReferenceManager(); Address nextExtAddr = getNextExternalSymbolAddress(); @@ -236,7 +239,9 @@ public class SymbolManager implements SymbolTable, ManagerDB { /** * Upgrade old stack and register variable symbol address to variable addresses. + *

* Also force associated references to be updated to new variable addresses. + * * @param monitor the task monitor * @throws IOException if there is database exception * @throws CancelledException if the operation is cancelled @@ -292,8 +297,10 @@ public class SymbolManager implements SymbolTable, ManagerDB { /** * No more sharing the same variable address for multiple variable symbols. - * Must split these up. Only reference to variable addresses should be the - * symbol address - reference refer to physical/stack addresses, and symbolIDs. + *

+ * Must split these up. Only reference to variable addresses should be the symbol address - + * reference refer to physical/stack addresses, and symbolIDs. + * * @param monitor the task monitor * @throws CancelledException if the operation is cancelled */ @@ -394,6 +401,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { /** * Add old local symbols + * * @throws IOException if there is database exception * @throws CancelledException if the operation is cancelled */ @@ -442,6 +450,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { /** * Save off old local symbols whose upgrade needs to be deferred until after function manager * upgrade has been completed. + * * @param tmpHandle scratch pad database handle * @param symbolID local symbol ID * @param oldAddr old address value from symbol table @@ -628,7 +637,6 @@ public class SymbolManager implements SymbolTable, ManagerDB { return false; } } - //refManager.symbolRemoved(sym); return sym.delete(); } finally { @@ -661,6 +669,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { /** * Removes the symbol directly + * * @param sym the symbol to remove. * @return true if the symbol was removed, false otherwise. */ @@ -1144,6 +1153,21 @@ public class SymbolManager implements SymbolTable, ManagerDB { return null; } + @Override + public SymbolIterator scanSymbolsByName(String startName) { + lock.acquire(); + try { + return new SymbolNameScanningIterator(startName); + } + catch (IOException e) { + program.dbError(e); + } + finally { + lock.release(); + } + return null; + } + @Override public Symbol getPrimarySymbol(Address addr) { if (!addr.isMemoryAddress() && !addr.isExternalAddress()) { @@ -1201,6 +1225,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { /** * Returns the maximum symbol address within the specified address space. + * * @param space address space * @return maximum symbol address within space or null if none are found. */ @@ -1216,6 +1241,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { /** * Returns the next available external symbol address + * * @return the address */ public Address getNextExternalSymbolAddress() { @@ -1228,14 +1254,18 @@ public class SymbolManager implements SymbolTable, ManagerDB { } @Override - public SymbolIterator getPrimarySymbolIterator(Address startAddr, boolean forward) { + public SymbolIterator getPrimarySymbolIterator(Address startAddr, boolean forward) + throws IllegalArgumentException { + if (!startAddr.isMemoryAddress()) { + throw new IllegalArgumentException("Invalid memory address: " + startAddr); + } return getPrimarySymbolIterator( program.getAddressFactory().getAddressSet(startAddr, program.getMaxAddress()), forward); } @Override public SymbolIterator getPrimarySymbolIterator(AddressSetView set, boolean forward) { - if (set.isEmpty()) { + if (set != null && set.isEmpty()) { return SymbolIterator.EMPTY_ITERATOR; } try { @@ -1250,7 +1280,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { @Override public SymbolIterator getSymbols(AddressSetView set, SymbolType type, boolean forward) { - if (set.isEmpty()) { + if (set != null && set.isEmpty()) { return SymbolIterator.EMPTY_ITERATOR; } Query query = @@ -1264,7 +1294,11 @@ public class SymbolManager implements SymbolTable, ManagerDB { } @Override - public SymbolIterator getSymbolIterator(Address startAddr, boolean forward) { + public SymbolIterator getSymbolIterator(Address startAddr, boolean forward) + throws IllegalArgumentException { + if (!startAddr.isMemoryAddress()) { + throw new IllegalArgumentException("Invalid memory address: " + startAddr); + } RecordIterator it; try { it = adapter.getSymbolsByAddress(startAddr, forward); @@ -1315,7 +1349,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { } @Override - public void addExternalEntryPoint(Address addr) { + public void addExternalEntryPoint(Address addr) throws IllegalArgumentException { refManager.addExternalEntryPointRef(addr); } @@ -1394,10 +1428,12 @@ public class SymbolManager implements SymbolTable, ManagerDB { } /** - * Move symbol. Only symbol address is changed. - * References must be moved separately. - * @param oldAddr the old symbol address - * @param newAddr the new symbol address + * Move symbol. + *

+ * Only symbol address is changed. References must be moved separately. + * + * @param oldAddr the old symbol memory address + * @param newAddr the new symbol memory address */ public void moveSymbolsAt(Address oldAddr, Address newAddr) { lock.acquire(); @@ -1422,6 +1458,9 @@ public class SymbolManager implements SymbolTable, ManagerDB { // Unique dynamic symbol ID produced from a dynamic symbol address map which has a // high-order bit set to avoid potential conflict with stored symbol ID's which are // assigned starting at 0. + if (!addr.isMemoryAddress()) { + throw new IllegalArgumentException("Invalid memory address: " + addr); + } return dynamicSymbolAddressMap.getKey(addr); } @@ -1450,16 +1489,17 @@ public class SymbolManager implements SymbolTable, ManagerDB { } FunctionManagerDB getFunctionManager() { - return (FunctionManagerDB) program.getFunctionManager(); + return program.getFunctionManager(); } ExternalManagerDB getExternalManager() { - return (ExternalManagerDB) program.getExternalManager(); + return program.getExternalManager(); } /** * Called by the NamespaceManager when a namespace is removed; remove all symbols that have the * given namespace ID. + * * @param namespaceID ID of namespace being removed */ public void namespaceRemoved(long namespaceID) { @@ -1849,11 +1889,11 @@ public class SymbolManager implements SymbolTable, ManagerDB { } } - private class SymbolNameRecordIterator implements SymbolIterator { + private abstract class AbstractSymbolNameRecordIterator implements SymbolIterator { private RecordIterator it; - SymbolNameRecordIterator(String name) throws IOException { - this.it = adapter.getSymbolsByName(name); + AbstractSymbolNameRecordIterator(RecordIterator it) { + this.it = it; } @Override @@ -1891,6 +1931,18 @@ public class SymbolManager implements SymbolTable, ManagerDB { } } + private class SymbolNameRecordIterator extends AbstractSymbolNameRecordIterator { + SymbolNameRecordIterator(String name) throws IOException { + super(adapter.getSymbolsByName(name)); + } + } + + private class SymbolNameScanningIterator extends AbstractSymbolNameRecordIterator { + public SymbolNameScanningIterator(String startName) throws IOException { + super(adapter.scanSymbolsByName(startName)); + } + } + private class ExternalSymbolNameRecordIterator implements SymbolIterator { private RecordIterator it; @@ -2302,6 +2354,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { /** * Checks to make sure there is a single valid primary symbol at each address + * * @param set the set of addresses that may have to be fixed up */ private void fixupPrimarySymbols(Set

set) { @@ -2342,9 +2395,12 @@ public class SymbolManager implements SymbolTable, ManagerDB { } /** - * Checks if the givens symbols from the same address have exactly one primary symbol amongst them + * Checks if the givens symbols from the same address have exactly one primary symbol amongst + * them + * * @param symbols the array of symbols at a an address - * @return true if there is exactly one primary symbol at the address (also true if no symbols at address) + * @return true if there is exactly one primary symbol at the address (also true if no symbols + * at address) */ private boolean hasValidPrimary(Symbol[] symbols) { if (symbols.length == 0) { @@ -2496,8 +2552,11 @@ public class SymbolManager implements SymbolTable, ManagerDB { } /** - * Creates variable symbols. Note this is not a method defined in the Symbol Table interface. - * It is intended to be used by Ghidra program internals. + * Creates variable symbols. + *

+ * Note this is not a method defined in the Symbol Table interface. It is intended to be used by + * Ghidra program internals. + * * @param name the name of the variable * @param function the function that contains the variable. * @param type the type of the variable (can only be PARAMETER or LOCAL_VAR) @@ -2649,6 +2708,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { /** * Create a Library symbol with the specified name and optional pathname + * * @param name library name * @param pathname project file path (may be null) * @param source symbol source @@ -2664,6 +2724,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { /** * Create a Class symbol with the specified name and parent + * * @param name class name * @param parent parent namespace (may be null for global namespace) * @param source symbol source @@ -2680,6 +2741,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { /** * Create a simple Namespace symbol with the specified name and parent + * * @param name class name * @param parent parent namespace (may be null for global namespace) * @param source symbol source @@ -2730,11 +2792,14 @@ public class SymbolManager implements SymbolTable, ManagerDB { } /** - * Internal method for creating label symbols. If identical memory symbol already exists - * it will be returned. + * Internal method for creating label symbols. + *

+ * If identical memory symbol already exists it will be returned. + * * @param addr the address for the new symbol (memory or external) * @param name the name of the new symbol - * @param namespace the namespace for the new symbol (null may be specified for global namespace) + * @param namespace the namespace for the new symbol (null may be specified for global + * namespace) * @param source the SourceType of the new symbol * @param stringData special use depending on the symbol type and whether or not it is external * @return the new symbol @@ -2771,14 +2836,14 @@ public class SymbolManager implements SymbolTable, ManagerDB { makePrimary = (primary == null); } else if (addr.isExternalAddress()) { - // only one symbol per external address is allowed + // TODO: remove support for external symbol creation from this method (see GP-3045) Symbol primary = getPrimarySymbol(addr); - if (primary != null) { + if (primary != null) { // only one symbol per external address is allowed throw new IllegalArgumentException("external address already used"); } } else { - throw new IllegalArgumentException("bad label address"); + throw new IllegalArgumentException("Invalid memory address: " + addr); } return doCreateSymbol(name, addr, namespace, SymbolType.LABEL, stringData, null, null, @@ -2794,7 +2859,8 @@ public class SymbolManager implements SymbolTable, ManagerDB { * * @param addr the address for the new symbol * @param name the name of the new symbol - * @param namespace the namespace for the new symbol (null may be specified for global namespace) + * @param namespace the namespace for the new symbol (null may be specified for global + * namespace) * @param source the SourceType of the new symbol * @param stringData special use depending on the symbol type and whether or not it is external. * @return the new symbol @@ -2866,9 +2932,11 @@ public class SymbolManager implements SymbolTable, ManagerDB { } /** - * Finds the appropriate symbol to promote when function is created. And by promote, we really - * mean find the symbol that needs to be deleted before creating the function symbol. If the - * found symbol is not dynamic, the function symbol will assume its name and namespace. + * Finds the appropriate symbol to promote when function is created. + *

+ * And by promote, we really mean find the symbol that needs to be deleted before creating the + * function symbol. If the found symbol is not dynamic, the function symbol will assume its name + * and namespace. */ private Symbol findSymbolToPromote(Symbol matching, Symbol primary, SourceType source) { // if the function is default, then the primary will be promoted diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolTable.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolTable.java index 3c97f23937..2bf13eec85 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolTable.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolTable.java @@ -17,6 +17,7 @@ package ghidra.program.model.symbol; import java.util.*; +import ghidra.program.database.symbol.*; import ghidra.program.model.address.*; import ghidra.program.model.listing.*; import ghidra.util.exception.DuplicateNameException; @@ -24,342 +25,398 @@ import ghidra.util.exception.InvalidInputException; /** * A SymbolTable manages the Symbols defined in a program. - *
- * A Symbol is an association between an Address, - * a String name. In addition, symbols may have one or more - * References. - *
- * A Reference is a 4-tuple of a source address, destination address, type, - * and either a mnemonic or operand index - *
- * Any address in a program can have more than one symbol associated to it. - * At any given time, one and only one symbol will be designated as the primary. - *
- * A symbol can be either global or local. Local symbols belong to some namespace other than - * the global namespace. - *
+ *

+ * A Symbol is an association between an Address, a String name. In addition, symbols may have one + * or more References. + *

+ * A Reference is a 4-tuple of a source address, destination address, type, and either a mnemonic or + * operand index. + *

+ * Any address in a program can have more than one symbol associated to it. At any given time, one + * and only one symbol will be designated as the primary. + *

+ * A symbol can be either global or local. Local symbols belong to some namespace other than the + * global namespace. + *

* Label and Function symbols do not have to have unique names with a namespace. All other symbols - * must be unique within a namespace and be unique with all other symbols that must be unique. - * In other words you can have a several functions named "foo" and several labels named "foo" - * in the same namespace. But you can't have a class named "foo" and a namespace named "foo". - * But you can have a class named "foo" and and many functions and labels named "foo" all - * in the same namespace. - *
- * A symbol can also be designated as dynamic. Which means the name is - * generated on-the-fly by the system based on its context. + * must be unique within a namespace and be unique with all other symbols that must be unique. In + * other words, you can have several functions named "foo" and several labels named "foo" in the + * same namespace. But you can't have a class named "foo" and a namespace named "foo". But you can + * have a class named "foo" and many functions and labels named "foo" all in the same namespace. + *

+ * A symbol can also be designated as dynamic. Which means the name is generated on-the-fly by the + * system based on its context. */ public interface SymbolTable { /** - * Create a label symbol with the given name associated to the given - * Address. The symbol will be global and be of type SymbolType.CODE. Label - * Symbols do not have to have unique names. - * If this is the first symbol defined for the address it becomes - * the primary. - * @param addr the address at which to create a symbol - * @param name the name of the symbol. - * @param source the source of this symbol - *
Some symbol types, such as function symbols, can set the source to Symbol.DEFAULT. - * @return new code or function symbol - * @throws InvalidInputException thrown if names contains white space, is zero length, or is - * null for non-default source. - * @throws IllegalArgumentException if you try to set the source to DEFAULT for a symbol type - * that doesn't allow it, or an improper addr is specified + * Create a label symbol with the given name in the global namespace and associated to the + * given memory address. (see {@link Address#isMemoryAddress()}). + *

+ * The new symbol will be of type {@link SymbolType#LABEL} or {@link SymbolType#FUNCTION} if a + * default function symbol currently exists at the address. If a default function symbol exists + * at the specified address the function symbol will be renamed and returned. Label and function + * symbols do not need to be unique across multiple addresses. However, if a global symbol at + * the specified address already has the specified name it will be returned without changing the + * source type. If this is the first non-dynamic symbol defined for the address it becomes the + * primary symbol. + * + * @param addr the memory address at which to create a symbol + * @param name the name of the symbol + * @param source the source of this symbol. In general, a source of {@link SourceType#DEFAULT} + * should never be specified using this method. + * @return new labe or function symbol + * @throws InvalidInputException if name contains white space, is zero length, or is null for + * non-default source + * @throws IllegalArgumentException if {@link SourceType#DEFAULT} is improperly specified, or + * a non-memory address. */ public Symbol createLabel(Address addr, String name, SourceType source) throws InvalidInputException; /** - * Create a label symbol with the given name associated to the given - * Address and namespace. The symbol will be of type SymbolType.CODE. - * If this is the first symbol defined for the address it becomes - * the primary symbol. If a symbol with that name already exists at the - * address, it will be returned instead with its namespace changed to the new - * namespace unless the new symbol is in the global space, in which case the namespace - * will remain as is. + * Create a label symbol with the given name and namespace associated to the given memory + * address. (see {@link Address#isMemoryAddress()}). + *

+ * The new symbol will be of type {@link SymbolType#LABEL} or {@link SymbolType#FUNCTION} if a + * default function symbol currently exists at the address. If a default function symbol exists + * at the specified address the function symbol will be renamed and returned. Label and function + * symbols do not need to be unique across multiple addresses or namespaces. However, if a + * symbol at the specified address already has the specified name and namespace it will be + * returned without changing the source type. If this is the first non-dynamic symbol defined + * for the address it becomes the primary symbol. + * * @param addr the address at which to create a symbol - * @param name the name of the symbol. - * @param namespace the namespace of the symbol. - * @param source the source of this symbol - *
Some symbol types, such as function symbols, can set the source to Symbol.DEFAULT. - * @return new code or function symbol - * @throws InvalidInputException thrown if names contains white space, is zero length, or is - * null for non-default source. Also thrown if invalid parentNamespace is specified. - * @throws IllegalArgumentException if you try to set the source to DEFAULT for a symbol type - * that doesn't allow it, specify an improper addr, or specify a namespace which does not - * correspond to this symbol table's program. + * @param name the name of the symbol + * @param namespace the parent namespace of the symbol, or null for the global namespace. + * @param source the source of this symbol. In general, a source of {@link SourceType#DEFAULT} + * should never be specified using this method. + * @return new label or function symbol + * @throws InvalidInputException if name contains white space, is zero length, or is null for + * non-default source. Also thrown if invalid parent namespace is specified. + * @throws IllegalArgumentException if {@link SourceType#DEFAULT} is improperly specified, or + * a non-memory address, or if the given parent namespace is from a different + * program than that of this symbol table. */ public Symbol createLabel(Address addr, String name, Namespace namespace, SourceType source) throws InvalidInputException; /** - * Removes the specified symbol from the symbol table. If removing any non-function - * symbol the behavior will be the same as invoking {@link Symbol#delete()} on the - * symbol. Use of this method for non-function symbols is discouraged. + * Removes the specified symbol from the symbol table. *

- * WARNING! If removing a function symbol the behavior differs from directly - * invoking {@link Symbol#delete()} on the function symbol. + * If removing any non-function symbol, the behavior will be the same as invoking + * {@link Symbol#delete()} on the symbol. Use of this method for non-function symbols is + * discouraged. *

- * When removing a function symbol this method has the following behavior: + * WARNING! If removing a function symbol, the behavior differs from directly invoking + * {@link Symbol#delete()} on the function symbol. When removing a function symbol this method + * has the following behavior: *

    - *
  • If the function is a default symbol (e.g., FUN_12345678) this method - * has no affect and will return null
  • - *
  • otherwise if another label exists at the function entry point, that - * label will be removed and the function will be renamed with that labels name
  • - *
  • If no other labels exist at the function entry, the function will - * be renamed to the default function name
  • + *
  • If the function is a default symbol (e.g., FUN_12345678) this method has no effect and + * will return false.
  • + *
  • If no other labels exist at the function entry, the function will be renamed to the + * default function name.
  • + *
  • If another label does exist at the function entry point, that label will be removed, and + * the function will be renamed to that label's name.
  • *
- * Any reference bound to a symbol removed will loose that - * symbol specific binding. + *

+ * Any reference bound to a removed symbol will lose that symbol specific binding. * * @param sym the symbol to be removed. - * @return false, if removal of the symbol fails + * @return true if a symbol is removed, false if not or in case of failure */ public boolean removeSymbolSpecial(Symbol sym); /** * Get the symbol for the given symbol ID. - * @param symbolID the id of the symbol to be retrieved. - * @return null if there is no symbol with the given ID. + * + * @param symbolID the id of the symbol to be retrieved + * @return null if there is no symbol with the given ID */ public Symbol getSymbol(long symbolID); /** * Get the symbol with the given name, address, and namespace. - *

+ *

* Note that for a symbol to be uniquely specified, all these parameters are required. Any - * method that queries for symbols using just one or two of these parameters will return a list - * of symbols. This method will not return a default thunk (i.e., thunk function symbol with + * method that queries for symbols using just one or two of these parameters will return only + * the first match. + *

+ * NOTE: This method will not return a default thunk (i.e., thunk function symbol with * default source type) since it mirrors the name and parent namespace of the function it * thunks. * * @param name the name of the symbol to retrieve * @param addr the address of the symbol to retrieve - * @param namespace the namespace of the symbol to retrieve. May be null which indicates global - * namespace. + * @param namespace the namespace of the symbol to retrieve. May be null which indicates the + * global namespace. * @return the symbol which matches the specified criteria or null if not found - * @throws IllegalArgumentException amespace which does not correspond to this - * symbol table's program. + * @throws IllegalArgumentException if the given parent namespace is from a different program + * than that of this symbol table * @see #getGlobalSymbol(String, Address) for a convenience method if the namespace is the - * global namespace. + * global namespace. */ public Symbol getSymbol(String name, Address addr, Namespace namespace); /** - * Get the global symbol with the given name and address. Note that this results in a single - * Symbol because of an additional restriction that allows only one symbol with a given name - * at the same address and namespace (in this case the global namespace). - * - *

This is just a convenience method for {@link #getSymbol(String, Address, Namespace)} where + * Get the global symbol with the given name and address. + *

+ * Note that this results in a single Symbol because of an additional restriction that allows + * only one symbol with a given name at the same address and namespace (in this case the global + * namespace). + *

+ * This is just a convenience method for {@link #getSymbol(String, Address, Namespace)} where * the namespace is the global namespace. - * - *

NOTE: This method will not return a default thunk (i.e., thunk function symbol with + *

+ * NOTE: This method will not return a default thunk (i.e., thunk function symbol with * default source type) since it mirrors the name and parent namespace of the function it * thunks. * * @param name the name of the symbol to retrieve * @param addr the address of the symbol to retrieve * @return the symbol which matches the specified criteria in the global namespace or null if - * not found - * @see #getSymbol(String, Address, Namespace) + * not found + * @see #getSymbol(String, Address, Namespace) */ public Symbol getGlobalSymbol(String name, Address addr); /** - * Returns a list of all global symbols with the given name. + * Get a list of all global symbols with the given name. Matches against dynamic label symbols + * will be included. + *

+ * NOTE: This method will not return default thunks (i.e., thunk function symbol with + * default source type). * - *

NOTE: This method will not return default thunks (i.e., - * thunk function symbol with default source type).

- * - * @param name the name of the symbols to retrieve. - * @return a list of all global symbols with the given name. + * @param name the name of the symbols to retrieve + * @return a list of all global symbols with the given name */ public List getGlobalSymbols(String name); /** - * Returns all the label or function symbols that have the given name in the given namespace. + * Get all the label or function symbols that have the given name in the given parent namespace. + * If the global namespace is specified matches against dynamic label symbols will be included. + *

+ * NOTE: If a function namespace is specified default parameter and local variable names + * will be included. If an external library or namespace is specified default external + * label/function symbols will be included. + *

+ * NOTE: This method will not return a default thunk (i.e., thunk function symbol with + * default source type) since it mirrors the name and parent namespace of the function it + * thunks. * - *

NOTE: This method will not return a default thunk (i.e., thunk function symbol with default source type) - * since it mirrors the name and parent namespace of the function it thunks.

- * - * @param name the name of the symbols to search for. - * @param namespace the namespace to search. If null, then the global namespace is assumed. - * @return a list of all the label or function symbols with the given name in the given namespace. - * @throws IllegalArgumentException amespace which does not correspond to this - * symbol table's program. + * @param name the name of the symbols to search for + * @param namespace the namespace to search. If null, then the global namespace is assumed. + * @return a list of all the label or function symbols with the given name in the given parent + * namespace + * @throws IllegalArgumentException if the given parent namespace is from a different program + * than that of this symbol table */ public List getLabelOrFunctionSymbols(String name, Namespace namespace); /** - * Returns a generic namespace symbol with the given name in the given namespace. - * @param name the name of the namespace symbol to retrieve. - * @param namespace the namespace containing the symbol to retrieve. - * @return a generic namespace symbol with the given name in the given namespace. - * @throws IllegalArgumentException amespace which does not correspond to this - * symbol table's program. + * Get a generic namespace symbol with the given name in the given parent namespace + * + * @param name the name of the namespace symbol to retrieve + * @param namespace the namespace containing the symbol to retrieve + * @return the symbol, or null + * @throws IllegalArgumentException if the given parent namespace is from a different program + * than that of this symbol table */ public Symbol getNamespaceSymbol(String name, Namespace namespace); /** - * Returns the library symbol with the given name. - * @param name the name of the library symbol to retrieve. - * @return the library symbol with the given name. + * Get the library symbol with the given name + * + * @param name the name of the library symbol to retrieve + * @return the library symbol with the given name */ public Symbol getLibrarySymbol(String name); /** - * Returns the class symbol with the given name in the given namespace. - * @param name the name of the class. - * @param namespace the namespace to search for the class. - * @return the class symbol with the given name in the given namespace. - * @throws IllegalArgumentException amespace which does not correspond to this - * symbol table's program. + * Get the class symbol with the given name in the given namespace + * + * @param name the name of the class + * @param namespace the parent namespace to search for the class + * @return the class symbol with the given name in the given namespace + * @throws IllegalArgumentException if the given parent namespace is from a different program + * than that of this symbol table */ public Symbol getClassSymbol(String name, Namespace namespace); /** - * Returns the parameter symbol with the given name in the given namespace. - * @param name the name of the parameter. - * @param namespace the namespace (function) to search for the class. - * @return the parameter symbol with the given name in the given namespace. - * @throws IllegalArgumentException amespace which does not correspond to this - * symbol table's program. + * Get the parameter symbol with the given name in the given namespace + * + * @param name the name of the parameter + * @param namespace the namespace (function) to search for the class + * @return the parameter symbol with the given name in the given namespace + * @throws IllegalArgumentException if the given parent namespace is from a different program + * than that of this symbol table */ public Symbol getParameterSymbol(String name, Namespace namespace); /** - * Returns the local variable symbol with the given name in the given namespace. - * @param name the name of the local variable. - * @param namespace the namespace (function) to search for the class. - * @return the local variable symbol with the given name in the given namespace. - * @throws IllegalArgumentException amespace which does not correspond to this - * symbol table's program. + * Get the local variable symbol with the given name in the given namespace + * + * @param name the name of the local variable + * @param namespace the parent namespace (function) to search for the local variable + * @return the local variable symbol with the given name in the given namespace + * @throws IllegalArgumentException if the given parent namespace is from a different program + * than that of this symbol table */ public Symbol getLocalVariableSymbol(String name, Namespace namespace); /** - * Returns a list of all symbols with the given name in the given namespace. + * Get a list of all symbols with the given name in the given parent namespace. If the global + * namespace is specified matches against dynamic label symbols will be included. + *

+ * NOTE: If a function namespace is specified default parameter and local variable names + * will be included. If an external library or namespace is specified default external + * label/function symbols will be included. + *

+ * NOTE: The resulting iterator will not return default thunks (i.e., thunk function + * symbol with default source type). * - *

NOTE: The resulting iterator will not return default thunks (i.e., - * thunk function symbol with default source type).

- * - * @param name the name of the symbols to retrieve. - * @param namespace the namespace to search for symbols. - * @return all symbols which satisfy specified criteria - * @throws IllegalArgumentException amespace which does not correspond to this - * symbol table's program. + * @param name the name of the symbols to retrieve + * @param namespace the namespace to search for symbols + * @return a list of symbols which satisfy specified criteria + * @throws IllegalArgumentException if the given parent namespace is from a different program + * than that of this symbol table */ public List getSymbols(String name, Namespace namespace); /** - * Returns a symbol that is either a parameter or local variable. There can be only - * one because these symbol types have a unique name requirement. - * @param name the name of the variable. - * @param function the function to search. - * @return a parameter or local variable symbol with the given name. + * Get a symbol that is either a parameter or local variable. + *

+ * There can be only one because these symbol types have a unique name requirement. + * + * @param name the name of the variable + * @param function the function to search + * @return a parameter or local variable symbol with the given name */ public Symbol getVariableSymbol(String name, Function function); /** - * Returns the namespace with the given name in the given parent namespace. The namespace - * returned can be either a generic namespace or a class or library. It does not include - * functions. - * @param name the name of the namespace to be retrieved. - * @param namespace the parent namespace of the namespace to be retrieved. - * @return the namespace with the given name in the given parent namespace. - * @throws IllegalArgumentException amespace which does not correspond to this - * symbol table's program. + * Get the namespace with the given name in the given parent namespace. + *

+ * The returned namespace can be a generic namespace ({@link SymbolType#NAMESPACE}, + * {@link NamespaceSymbol}), class ({@link SymbolType#CLASS}, {@link ClassSymbol}),or + * library ({@link SymbolType#LIBRARY}, {@link LibrarySymbol}), but not a function. + *

+ * There can be only one because these symbol types have a unique name + * requirement within their parent namespace. + * + * @param name the name of the namespace to be retrieved + * @param namespace the parent namespace of the namespace to be retrieved + * @return the namespace with the given name in the given parent namespace + * @throws IllegalArgumentException if the given parent namespace is from a different program + * than that of this symbol table */ public Namespace getNamespace(String name, Namespace namespace); /** - * Returns all the symbols with the given name. + * Get all the symbols with the given name + *

+ * NOTE: The resulting iterator will not return default thunks (i.e., thunk function + * symbol with default source type). It will also not work for default local variables and + * parameters. * - *

NOTE: The resulting iterator will not return default thunks (i.e., - * thunk function symbol with default source type). It will also not work for default - * local variables and parameters.

- * - * @param name the name of symbols to search for. - * - * @return array of symbols with the given name + * @param name the name of symbols to search for + * @return an iterator over symbols with the given name */ public SymbolIterator getSymbols(String name); /** - * Returns an iterator over all symbols, including Dynamic symbols if - * includeDynamicSymbols is true. - * @param includeDynamicSymbols if true, the iterator will include dynamicSymbols - * @return symbol iterator + * Get all of the symbols, optionally including dynamic symbols + * + * @param includeDynamicSymbols if true, the iterator will include dynamic symbols + * @return an iterator over the symbols */ public SymbolIterator getAllSymbols(boolean includeDynamicSymbols); /** - * Returns the symbol that this reference is associated with. - * @param ref the reference to find the associated symbol for. - * @return referenced symbol + * Get the symbol that a given reference associates + * + * @param ref the reference for the associated symbol + * @return the associated symbol */ public Symbol getSymbol(Reference ref); /** - * Returns the primary symbol at the specified - * address. This method will always return null if the address specified - * is neither a Memory address nor an External address. - * @param addr the address at which to retrieve the primary symbol - * - * @return symbol, or null if no symbol at that address + * Get the primary label or function symbol at the given address + *

+ * This method will return null if the address specified is neither a memory address nor an + * external address. + * + * @param addr the address of the symbol + * @return the symbol, or null if no symbol is at the address */ public Symbol getPrimarySymbol(Address addr); /** - * Returns all the symbols at the given address. When addr is a memory address - * 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. + * Get all the symbols at the given address. This method will include a dynamic memory symbol + * if one exists at the specified address. + *

+ * For a memory address the primary symbol will be returned at array index 0. WARNING! + * Use of this method with non-memory addresses is discouraged. Example: Variable + * address could be used multiple times by many functions. + *

+ * NOTE: unless all the symbols are needed at once, and a dynamic symbol can be ignored, + * consider using {@link #getSymbolsAsIterator(Address)} instead. + * + * @param addr the address of the symbols + * @return an array, possibly empty, of the symbols at the given 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. + * Get an iterator over the symbols at the given address. Any dynamic symbol at the address + * will be excluded. + *

+ * 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 + * @param addr the address of the symbols + * @return an iterator over 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. - * @return all symbols at specified address + * Get an array of defined symbols at the given address (i.e., those with database record). + * Any dynamic memory symbol at the address will be excluded. + *

+ * WARNING! + * Use of this method with non-memory addresses is discouraged. Example: Variable + * address could be used multiple times by many functions. + *

+ * NOTE: unless all the symbols are needed at once, consider using + * {@link #getSymbolsAsIterator(Address)} instead. + * + * @param addr the address of the symbols + * @return an array, possibly empty, of the symbols */ public Symbol[] getUserSymbols(Address addr); /** - * Returns an iterator over all the symbols in the given namespace + * Get an iterator over all the symbols in the given namespace + *

+ * NOTE: The resulting iterator will not return default thunks (i.e., thunk function + * symbol with default source type). * - *

NOTE: The resulting iterator will not return default thunks (i.e., - * thunk function symbol with default source type).

- * - * @param namespace the namespace to search for symbols. - * @return symbol iterator - * @throws IllegalArgumentException amespace which does not correspond to this - * symbol table's program. + * @param namespace the namespace to search for symbols + * @return an iterator over the symbols + * @throws IllegalArgumentException if the given parent namespace is from a different program + * than that of this symbol table */ public SymbolIterator getSymbols(Namespace namespace); /** - * Returns an iterator over all the symbols in the given namespace - * - *

NOTE: This method will not return a default thunk (i.e., - * thunk function symbol with default source type).

+ * Get an iterator over all the symbols in the given namespace + *

+ * NOTE: The resulting iterator will not return default thunks (i.e., thunk function + * symbol with default source type). * * @param namespaceID the namespace ID to search for symbols. * @return symbol iterator @@ -367,203 +424,277 @@ public interface SymbolTable { public SymbolIterator getSymbols(long namespaceID); /** - * Return true if there exists a symbol at the given address. + * Check if there exists any symbol at the given address + * * @param addr address to check for an existing symbol * @return true if any symbol exists */ public boolean hasSymbol(Address addr); /** - * Get the unique symbol ID for a dynamic symbol associated with the specified addr. - * The generation of this symbol ID does not reflect the presence of a dynamic symbol - * at the specified addr. This symbol ID should not be permanently stored since the encoding - * may change between software releases. - * @param addr dynamic symbol address + * Get the unique symbol ID for a dynamic symbol at the specified address + *

+ * Having a dynamic symbol ID does not imply that a dynamic symbol actually exists. Rather, this + * just gives the ID that a dynamic symbol at that address would have, should it ever exist. + *

+ * NOTE: This symbol ID should not be permanently stored since the encoding may change + * between software releases. + * + * @param addr the dynamic symbol memory address * @return unique symbol ID + * @throws IllegalArgumentException if a non-memory address is specified */ public long getDynamicSymbolID(Address addr); /** - * Returns a an iterator over all symbols that match the given search string. + * Get an iterator over all symbols that match the given query + *

+ * NOTE: The iterator is in the forward direction only and will not return default thunks + * (i.e., thunk function symbol with default source type). * - *

NOTE: The iterator is in the forward direction only and will not return default thunk - * functions. The resulting iterator will not return default thunks (i.e., - * thunk function symbol with default source type). - * - * @param searchStr the string to search for (may contain * to match any sequence - * or ? to match a single char) - * @param caseSensitive flag to determine if the search is case sensitive or not. + * @param searchStr the query, which may contain * to match any sequence or ? to match a single + * char + * @param caseSensitive flag to specify whether the search is case sensitive * @return symbol iterator */ public SymbolIterator getSymbolIterator(String searchStr, boolean caseSensitive); /** - * Returns all the symbols of the given type within the given address set. - * @param set the address set in which to look for symbols of the given type (required). - * @param type the SymbolType to look for. - * @param forward the direction within the addressSet to search + * Get all the symbols of the given type within the given address set. + *

+ * NOTE: All external symbols will be omiitted unless the full + * {@link AddressSpace#EXTERNAL_SPACE} range is included within the specified address set + * or a null addressSet is specified. All global dynamic label symbols will be omitted. + * + * @param addressSet the address set containing the symbols. A null value may be specified + * to include all memory and external primary symbols. + * @param type the type of the symbols + * @param forward the direction of the iterator, by address * @return symbol iterator */ - public SymbolIterator getSymbols(AddressSetView set, SymbolType type, boolean forward); + public SymbolIterator getSymbols(AddressSetView addressSet, SymbolType type, boolean forward); /** - * Returns the total number of symbols in the table. + * Scan symbols lexicographically by name + *

+ * If a symbol with the given start name does not exist, the iterator will start at the first + * symbol following it. This includes only symbols whose addresses are in memory. In particular, + * it excludes external symbols and dynamic symbols, i.e., those generated as a reference + * destination. + * + * @param startName the starting point + * @return an iterator over the symbols in lexicographical order + */ + public SymbolIterator scanSymbolsByName(String startName); + + /** + * Get the total number of symbols in the table + * * @return total number of symbols */ public int getNumSymbols(); /** - * Get iterator over all label symbols. Labels are defined on memory locations. + * Get all label symbols + *

+ * Labels are defined on memory locations. + * * @return symbol iterator */ public SymbolIterator getSymbolIterator(); /** - * Returns an iterator over all defined symbols in no particular order. + * Get all defined symbols in no particular order. All global dynamic memory labels will be + * excluded. + * * @return symbol iterator */ public SymbolIterator getDefinedSymbols(); /** - * Returns the external symbol with the given name. - * @param name the name of the symbol to be retrieved. - * @return symbol, or null if no external symbol has that name + * Get the external symbol with the given name. The first occurance of the named symbol found + * within any external namespace will be returned. If all matching symbols need to be + * considered the {@link #getExternalSymbols(String)} should be used. + * + * @param name the name of the symbol + * @return the symbol, or null if no external symbol has that name */ public Symbol getExternalSymbol(String name); /** - * Returns all the external symbols with the given name. - * @param name the name of symbols to search for. - * - * @return array of external symbols with the given name + * Get all the external symbols with the given name + * + * @param name the name of symbols + * @return an iterator over the symbols */ public SymbolIterator getExternalSymbols(String name); /** - * Returns an iterator over all defined external symbols in no particular order. + * Get all defined external symbols in no particular order + * * @return symbol iterator */ public SymbolIterator getExternalSymbols(); /** - * Returns an iterator over all symbols. - * @param forward true means the iterator is in the forward direction + * Get all the symbols defined with program memory. + *

+ * NOTE: The returned symbols will not include any external symbols defined within the + * {@link AddressSpace#EXTERNAL_SPACE}. In addition, all global dynamic label symbols will + * be omitted. + * + * @param forward the direction of the iterator, by address * @return symbol iterator */ public SymbolIterator getSymbolIterator(boolean forward); /** - * Get iterator over all symbols starting at - * the specified startAddr - * @param startAddr the address at which to begin the iteration. + * Get all the symbols starting at the specified memory address. + *

+ * NOTE: The returned symbols will not include any external symbols defined within the + * {@link AddressSpace#EXTERNAL_SPACE}. In addition, all global dynamic label symbols will + * be omitted. + * + * @param startAddr the starting address * @param forward true means the iterator is in the forward direction * @return symbol iterator + * @throws IllegalArgumentException if startAddr is not a memory address */ public SymbolIterator getSymbolIterator(Address startAddr, boolean forward); /** - * Get iterator over all primary symbols. + * Get all primary label and function symbols defined within program memory address. + * Iteration may span multiple memory spaces. + *

+ * NOTE: The returned symbols will not include any external symbols defined within the + * {@link AddressSpace#EXTERNAL_SPACE}. In addition, all global dynamic label symbols will + * be omitted. + * * @param forward true means the iterator is in the forward direction * @return symbol iterator */ public SymbolIterator getPrimarySymbolIterator(boolean forward); /** - * Get iterator over only primary symbols starting at - * the specified startAddr - * @param startAddr the address at which to begin the iteration. + * Get all primary label and function symbols starting at the specified memory address through + * to the program's maximum memory address. Iteration may span multiple memory spaces. + *

+ * NOTE: The returned symbols will not include any external symbols defined within the + * {@link AddressSpace#EXTERNAL_SPACE}. In addition, all global dynamic label symbols will + * be omitted. + * + * @param startAddr the starting memory address * @param forward true means the iterator is in the forward direction * @return symbol iterator + * @throws IllegalArgumentException if a non-memory address is specified */ public SymbolIterator getPrimarySymbolIterator(Address startAddr, boolean forward); /** - * Get an iterator over symbols at addresses in the given addressSet - * @param asv the set of address over which to iterate symbols (required). + * Get primary label and function symbols within the given address set. + *

+ * NOTE: All external symbols will be omiitted unless the full + * {@link AddressSpace#EXTERNAL_SPACE} range is included within the specified address set + * or a null addressSet is specified. All global dynamic label symbols will be omitted. + * + * @param addressSet the set of address containing the symbols. A null value may be specified + * to include all memory and external primary symbols. * @param forward true means the iterator is in the forward direction * @return symbol iterator */ - public SymbolIterator getPrimarySymbolIterator(AddressSetView asv, boolean forward); + public SymbolIterator getPrimarySymbolIterator(AddressSetView addressSet, boolean forward); /** - * Sets the given address to be an external entry point. - * @param addr the address to set as an external entry point. + * Add a memory address to the external entry points. + * + * @param addr the memory address to add + * @throws IllegalArgumentException if a non-memory is specified */ public void addExternalEntryPoint(Address addr); /** - * Removes the given address as an external entry point. - * @param addr the address to remove as an external entry point. + * Remove an address from the external entry points + * + * @param addr the address to remove */ public void removeExternalEntryPoint(Address addr); /** - * Returns true if the given address has been set as an external entry point. - * @param addr address to test for external entry point. - * @return true if specified address has been marked as an entry point, else false + * Check if the given address is an external entry point + * + * @param addr address to check + * @return true if specified address has been marked as an entry point, otherwise false */ public boolean isExternalEntryPoint(Address addr); /** - * Get forward/back iterator over addresses that are entry points. + * Get the external entry points (addresses) + * * @return entry-point address iterator */ public AddressIterator getExternalEntryPointIterator(); /** - * Get the label history objects for the given address. The history - * object records changes made to labels at some address. + * Get the label history for the given address + *

+ * Each entry records a change made to the labels at the given address + * * @param addr address of the label change * @return array of history objects */ public LabelHistory[] getLabelHistory(Address addr); /** - * Get an iterator over all the label history objects. - * @return label history iterator + * Get the complete label history of the program + * + * @return an iterator over history entries */ public Iterator getLabelHistory(); /** - * Return true if there is a history of label changes at the given address. - * @param addr the address to check for symbol history. - * @return true if label history exists for specified address, else false + * Check if there is a history of label changes at the given address + * + * @param addr the address to check + * @return true if a label history exists for specified address, otherwise false */ public boolean hasLabelHistory(Address addr); /** - * Returns the lowest level Namespace within which the specified address is contained. - * @param addr the address for which to finds its enclosing namespace. - * @return namespace which contains specified address + * Get the deepest namespace containing the given address + * + * @param addr the address contained in the namespace + * @return the deepest namespace which contains the address */ public Namespace getNamespace(Address addr); /** - * Returns all Class Namespaces defined within the program in an arbitrary ordering. - * @return iterator of {@link GhidraClass} + * Get all class namespaces defined within the program, in no particular order + * + * @return an iterator over the classes */ public Iterator getClassNamespaces(); /** - * Create a class namespace in the given parent namespace. - * @param parent parent namespace (may be null for global namespace) - * @param name name of the namespace + * Create a class namespace in the given parent namespace + * + * @param parent the parent namespace, or null for the global namespace + * @param name the name of the namespace * @param source the source of this class namespace's symbol - * @return new class namespace - * @throws DuplicateNameException thrown if another non function or label symbol exists with - * the given name + * @return the new class namespace + * @throws DuplicateNameException thrown if another non function or label symbol exists with the + * given name * @throws InvalidInputException throw if the name has invalid characters or is null - * @throws IllegalArgumentException if you try to set the source to 'Symbol.DEFAULT' - * or specify a parent Namespace which does not correspond to this symbol table's program. + * @throws IllegalArgumentException if the given parent namespace is from a different program + * than that of this symbol table or if source is {@link SourceType#DEFAULT} */ public GhidraClass createClass(Namespace parent, String name, SourceType source) throws DuplicateNameException, InvalidInputException; /** - * Returns an iterator over all symbols that have the given symbol as its parent. - * - *

NOTE: The resulting iterator will not return default thunks (i.e., thunk function symbol - * with default source type). + * Get all symbols that have the given parent symbol + *

+ * NOTE: The resulting iterator will not return default thunks (i.e., thunk function + * symbol with default source type) or global dynamic label symbols. * * @param parentSymbol the parent symbol * @return symbol iterator @@ -571,59 +702,61 @@ public interface SymbolTable { public SymbolIterator getChildren(Symbol parentSymbol); /** - * Creates a Library namespace with the given name. - * @param name the name of the new Library namespace + * Create a library namespace with the given name + * + * @param name the name of the new library namespace * @param source the source of this external library's symbol - * @return the new Library namespace. - * @throws InvalidInputException if the name is invalid. - * @throws IllegalArgumentException if you try to set the source to 'Symbol.DEFAULT'. - * @throws DuplicateNameException thrown if another non function or label - * symbol exists with the given name + * @return the new library namespace + * @throws InvalidInputException if the name is invalid + * @throws IllegalArgumentException if you try to set the source to {@link SourceType#DEFAULT} + * @throws DuplicateNameException thrown if another non function or label symbol exists with the + * given name */ public Library createExternalLibrary(String name, SourceType source) throws DuplicateNameException, InvalidInputException; /** - * Creates a new namespace. - * @param parent the parent namespace for the new namespace (may be null for global namespace) + * Create a new namespace + * + * @param parent the parent of the new namespace, or null for the global namespace * @param name the name of the new namespace * @param source the source of this namespace's symbol - * @return the new Namespace object. - * @throws DuplicateNameException thrown if another non function or label symbol - * exists with the given name - * @throws InvalidInputException if the name is invalid. - * @throws IllegalArgumentException if you try to set the source to 'Symbol.DEFAULT' - * or specify a parent Namespace which does not correspond to this symbol table's program. + * @return the new namespace + * @throws DuplicateNameException if another non function or label symbol exists with the given + * name + * @throws InvalidInputException if the name is invalid + * @throws IllegalArgumentException if the given parent namespace is from a different program + * than that of this symbol table or if source is {@link SourceType#DEFAULT} */ public Namespace createNameSpace(Namespace parent, String name, SourceType source) throws DuplicateNameException, InvalidInputException; /** - * Converts the given namespace to a class namespace + * Convert the given namespace to a class namespace * * @param namespace the namespace to convert * @return the new class - * @throws IllegalArgumentException if the given parent namespace is from a different program - * than that of this symbol table * @throws ConcurrentModificationException if the given parent namespace has been deleted - * @throws IllegalArgumentException namespace does not correspond to this symbol table's program - * or namespace not allowed (e.g., global or library namespace). + * @throws IllegalArgumentException if the given parent namespace is from a different program + * than that of this symbol table or the namespace not allowed (e.g., global or + * library namespace). */ public GhidraClass convertNamespaceToClass(Namespace namespace); /** - * Gets an existing namespace with the given name in the given parent. If no namespace exists, - * then one will be created. + * Get or create the namespace with the given name in the given parent + *

+ * If the namespace does not already exists, then it will be created. * * @param parent the parent namespace * @param name the namespace name - * @param source the source type for the namespace if one is created + * @param source the source type for the namespace if it is created * @return the namespace - * @throws DuplicateNameException thrown if another non function or label symbol exists with - * the given name + * @throws DuplicateNameException if another non function or label symbol exists with the given + * name * @throws InvalidInputException if the name is invalid * @throws IllegalArgumentException if the given parent namespace is from a different program - * than that of this symbol table + * than that of this symbol table * @throws ConcurrentModificationException if the given parent namespace has been deleted */ public Namespace getOrCreateNameSpace(Namespace parent, String name, SourceType source) diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolUtilities.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolUtilities.java index 21305c61d6..c901a0df90 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolUtilities.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolUtilities.java @@ -17,6 +17,7 @@ package ghidra.program.model.symbol; import java.util.*; import java.util.function.Consumer; +import java.util.stream.Stream; import ghidra.program.model.address.*; import ghidra.program.model.data.*; @@ -85,7 +86,7 @@ public class SymbolUtilities { DEFAULT_DATA_PREFIX, DEFAULT_SYMBOL_PREFIX, DEFAULT_SUBROUTINE_PREFIX, DEFAULT_UNKNOWN_PREFIX, DEFAULT_EXTERNAL_ENTRY_PREFIX, DEFAULT_FUNCTION_PREFIX }; - private static List DYNAMIC_DATA_TYPE_PREFIXES = getDynamicDataTypePrefixes(); + private final static List DYNAMIC_DATA_TYPE_PREFIXES = getDynamicDataTypePrefixes(); /** * Any dynamic label will have an address with this minimum length or longer @@ -574,7 +575,7 @@ public class SymbolUtilities { */ public static Address parseDynamicName(AddressFactory factory, String name) { - // assume dynamic names will naver start with an underscore + // assume dynamic names will never start with an underscore if (name.startsWith(UNDERSCORE)) { return null; } @@ -591,7 +592,7 @@ public class SymbolUtilities { space = factory.getDefaultAddressSpace(); } - // Only consider address values which meet the meet the minimum padding behavior + // Only consider address values which meet the minimum padding behavior if (addressOffsetString.length() < MIN_LABEL_ADDRESS_DIGITS) { return null; } diff --git a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/symbol/StubSymbolTable.java b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/symbol/StubSymbolTable.java index 04df4daa01..07b6416bf7 100644 --- a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/symbol/StubSymbolTable.java +++ b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/symbol/StubSymbolTable.java @@ -172,6 +172,11 @@ public class StubSymbolTable implements SymbolTable { throw new UnsupportedOperationException(); } + @Override + public SymbolIterator scanSymbolsByName(String startName) { + throw new UnsupportedOperationException(); + } + @Override public int getNumSymbols() { throw new UnsupportedOperationException();