Merge branch 'GP-1525_ghidra1_ExternalFunctionPrimary' into Ghidra_10.1

This commit is contained in:
ghidra1 2021-11-23 21:44:26 -05:00
commit 5c82f87905
18 changed files with 553 additions and 433 deletions

View file

@ -160,6 +160,15 @@ public abstract class AbstractDBTraceProgramViewReferenceManager implements Refe
new AddressRangeImpl(fromAddr, fromAddr)); new AddressRangeImpl(fromAddr, fromAddr));
} }
@Override
public void removeAllReferencesTo(Address toAddr) {
if (refs(false) == null) {
return;
}
refs.clearReferencesTo(Range.closed(program.snap, program.snap),
new AddressRangeImpl(toAddr, toAddr));
}
@Override @Override
public Reference[] getReferencesTo(Variable var) { public Reference[] getReferencesTo(Variable var) {
return TODO(); return TODO();

View file

@ -266,6 +266,11 @@ public class DBTraceReferenceManager extends
Collections.emptyList()); Collections.emptyList());
} }
@Override
public void clearReferencesTo(Range<Long> span, AddressRange range) {
delegateDeleteV(range.getAddressSpace(), s -> s.clearReferencesTo(span, range));
}
@Override @Override
public AddressSetView getReferenceSources(Range<Long> span) { public AddressSetView getReferenceSources(Range<Long> span) {
return new UnionAddressSetView( return new UnionAddressSetView(

View file

@ -578,28 +578,26 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS
@Override @Override
public void clearReferencesFrom(Range<Long> span, AddressRange range) { public void clearReferencesFrom(Range<Long> span, AddressRange range) {
long startSnap = DBTraceUtils.lowerEndpoint(span); try (LockHold hold = manager.getTrace().lockWrite()) {
for (DBTraceReferenceEntry ref : referenceMapSpace.reduce( long startSnap = DBTraceUtils.lowerEndpoint(span);
TraceAddressSnapRangeQuery.intersecting(range, span)).values()) { for (DBTraceReferenceEntry ref : referenceMapSpace.reduce(
if (DBTraceUtils.lowerEndpoint(ref.getLifespan()) < startSnap) { TraceAddressSnapRangeQuery.intersecting(range, span)).values()) {
Range<Long> oldSpan = ref.getLifespan(); truncateOrDeleteEntry(ref, startSnap);
ref.setEndSnap(startSnap - 1);
trace.setChanged(new TraceChangeRecord<>(TraceReferenceChangeType.LIFESPAN_CHANGED,
this, ref.ref, oldSpan, ref.getLifespan()));
}
else {
ref.ref.delete();
} }
// TODO: Coalesce events? // TODO: Coalesce events?
} }
} }
protected DBTraceReference getRefForXRefEntry(DBTraceXRefEntry e) { protected DBTraceReferenceEntry getRefEntryForXRefEntry(DBTraceXRefEntry e) {
AddressSpace fromAddressSpace = AddressSpace fromAddressSpace =
baseLanguage.getAddressFactory().getAddressSpace(e.refSpaceId); baseLanguage.getAddressFactory().getAddressSpace(e.refSpaceId);
DBTraceReferenceSpace fromSpace = manager.getForSpace(fromAddressSpace, false); DBTraceReferenceSpace fromSpace = manager.getForSpace(fromAddressSpace, false);
assert fromSpace != null; assert fromSpace != null;
return fromSpace.referenceMapSpace.getDataByKey(e.refKey).ref; return fromSpace.referenceMapSpace.getDataByKey(e.refKey);
}
protected DBTraceReference getRefForXRefEntry(DBTraceXRefEntry e) {
return getRefEntryForXRefEntry(e).ref;
} }
@Override @Override
@ -617,6 +615,31 @@ public class DBTraceReferenceSpace implements DBTraceSpaceBased, TraceReferenceS
this::getRefForXRefEntry); this::getRefForXRefEntry);
} }
protected void truncateOrDeleteEntry(DBTraceReferenceEntry ref, long otherStartSnap) {
if (DBTraceUtils.lowerEndpoint(ref.getLifespan()) < otherStartSnap) {
Range<Long> oldSpan = ref.getLifespan();
ref.setEndSnap(otherStartSnap - 1);
trace.setChanged(new TraceChangeRecord<>(TraceReferenceChangeType.LIFESPAN_CHANGED,
this, ref.ref, oldSpan, ref.getLifespan()));
}
else {
ref.ref.delete();
}
}
@Override
public void clearReferencesTo(Range<Long> span, AddressRange range) {
try (LockHold hold = manager.getTrace().lockWrite()) {
long startSnap = DBTraceUtils.lowerEndpoint(span);
for (DBTraceXRefEntry xref : xrefMapSpace.reduce(
TraceAddressSnapRangeQuery.intersecting(range, span)).values()) {
DBTraceReferenceEntry ref = getRefEntryForXRefEntry(xref);
truncateOrDeleteEntry(ref, startSnap);
}
// TODO: Coalesce events?
}
}
@Override @Override
public AddressSetView getReferenceSources(Range<Long> span) { public AddressSetView getReferenceSources(Range<Long> span) {
return new DBTraceAddressSnapRangePropertyMapAddressSetView<>(space, lock, return new DBTraceAddressSnapRangePropertyMapAddressSetView<>(space, lock,

View file

@ -72,6 +72,8 @@ public interface TraceReferenceOperations {
Collection<? extends TraceReference> getReferencesTo(long snap, Address toAddress); Collection<? extends TraceReference> getReferencesTo(long snap, Address toAddress);
void clearReferencesTo(Range<Long> span, AddressRange range);
/** /**
* TODO: Document me * TODO: Document me
* *

View file

@ -461,6 +461,39 @@ public class DBTraceReferenceManagerTest extends AbstractGhidraHeadlessIntegrati
new HashSet<>(manager.getReferencesTo(0, b.addr(0x5000)))); new HashSet<>(manager.getReferencesTo(0, b.addr(0x5000))));
} }
@Test
public void testClearReferencesTo() {
DBTraceReference keptRef;
try (UndoableTransaction tid = b.startTransaction()) {
b.addMemoryReference(0, b.addr(0x4000), b.addr(0x5000), 3);
b.addOffsetReference(0, b.addr(0x4001), b.addr(0x5000), 20);
b.addShiftedReference(0, b.addr(0x4002), b.addr(0x5000), 1);
keptRef = b.addMemoryReference(0, b.addr(0x8000), b.addr(0x5001));
}
assertEquals(3, manager.getReferencesTo(0, b.addr(0x5000)).size());
assertEquals(1, manager.getReferencesTo(0, b.addr(0x5001)).size());
try (UndoableTransaction tid = b.startTransaction()) {
manager.clearReferencesTo(Range.atLeast(10L), b.range(0x4000, 0x5000));
}
assertEquals(3, manager.getReferencesTo(0, b.addr(0x5000)).size());
assertEquals(0, manager.getReferencesTo(10, b.addr(0x5000)).size());
assertEquals(Range.closed(0L, 9L),
manager.getReferencesTo(0, b.addr(0x5000)).iterator().next().getLifespan());
try (UndoableTransaction tid = b.startTransaction()) {
manager.clearReferencesTo(Range.atLeast(0L), b.range(0x4000, 0x5000));
}
assertEquals(0, manager.getReferencesTo(0, b.addr(0x5000)).size());
assertEquals(0, manager.getReferencesTo(-1, b.addr(0x5000)).size());
assertEquals(1, manager.getReferencesTo(0, b.addr(0x5001)).size());
assertEquals(keptRef, manager.getReferencesTo(0, b.addr(0x5001)).iterator().next());
assertEquals(Range.atLeast(0L), keptRef.getLifespan());
}
@Test @Test
public void testGetReferenceSourcesAndDestinations() { public void testGetReferenceSourcesAndDestinations() {
try (UndoableTransaction tid = b.startTransaction()) { try (UndoableTransaction tid = b.startTransaction()) {

View file

@ -1397,15 +1397,6 @@ public class SymbolMergeManagerNamespace1Test extends AbstractListingMergeManage
"The following namespaces were not removed", 4000); "The following namespaces were not removed", 4000);
waitForMergeCompletion(); waitForMergeCompletion();
SymbolTable symtab = resultProgram.getSymbolTable();
Namespace globalNS = resultProgram.getGlobalNamespace();
SymbolIterator iter = symtab.getSymbols(globalNS);
while (iter.hasNext()) {
Symbol s = iter.next();
if (s.getSymbolType().equals(SymbolType.NAMESPACE)) {
System.out.println("Namespace = " + s.getName(true));
}
}
Symbol firstNsSymbol = Symbol firstNsSymbol =
getUniqueSymbol(resultProgram, "FirstNamespace", resultProgram.getGlobalNamespace()); getUniqueSymbol(resultProgram, "FirstNamespace", resultProgram.getGlobalNamespace());
assertNotNull(firstNsSymbol); assertNotNull(firstNsSymbol);

View file

@ -26,6 +26,7 @@ import ghidra.app.cmd.disassemble.DisassembleCommand;
import ghidra.app.cmd.function.CreateFunctionCmd; import ghidra.app.cmd.function.CreateFunctionCmd;
import ghidra.program.database.ProgramBuilder; import ghidra.program.database.ProgramBuilder;
import ghidra.program.database.ProgramDB; import ghidra.program.database.ProgramDB;
import ghidra.program.database.function.OverlappingFunctionException;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
@ -83,24 +84,24 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testCreateSymbol() throws Exception { public void testCreateSymbol() throws Exception {
Symbol s = createSymbol(addr(100), "bob"); Symbol s = createLabel(addr(100), "bob");
assertNotNull(s); assertNotNull(s);
} }
@Test @Test
public void testCreateLocal() throws Exception { public void testCreateLocal() throws Exception {
Namespace scope = st.createNameSpace(null, "MyNamespace", SourceType.USER_DEFINED); Namespace scope = st.createNameSpace(null, "MyNamespace", SourceType.USER_DEFINED);
Symbol s = createSymbol(addr(0x200), "printf", scope); Symbol s = createLabel(addr(0x200), "printf", scope);
assertNotNull(s); assertNotNull(s);
} }
@Test @Test
public void testGetLocal() throws Exception { public void testGetLocal() throws Exception {
createSymbol(addr(100), "primary"); createLabel(addr(100), "primary");
createSymbol(addr(100), "fred"); createLabel(addr(100), "fred");
createSymbol(addr(100), "joe"); createLabel(addr(100), "joe");
Namespace scope = st.createNameSpace(null, "MyNamespace", SourceType.USER_DEFINED); Namespace scope = st.createNameSpace(null, "MyNamespace", SourceType.USER_DEFINED);
createSymbol(addr(200), "fred", scope); createLabel(addr(200), "fred", scope);
Symbol s = st.getSymbol("fred", addr(200), scope); Symbol s = st.getSymbol("fred", addr(200), scope);
assertNotNull(s); assertNotNull(s);
assertTrue(!s.isGlobal()); assertTrue(!s.isGlobal());
@ -109,17 +110,17 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testGetLocalSymbols() throws Exception { public void testGetLocalSymbols() throws Exception {
createSymbol(addr(100), "primary"); createLabel(addr(100), "primary");
createSymbol(addr(100), "fred"); createLabel(addr(100), "fred");
createSymbol(addr(100), "joe"); createLabel(addr(100), "joe");
Namespace scope = st.createNameSpace(null, "MyNamespace", SourceType.USER_DEFINED); Namespace scope = st.createNameSpace(null, "MyNamespace", SourceType.USER_DEFINED);
createSymbol(addr(100), "exit", scope); createLabel(addr(100), "exit", scope);
Namespace scope2 = st.createNameSpace(null, "MyNamespace2", SourceType.USER_DEFINED); Namespace scope2 = st.createNameSpace(null, "MyNamespace2", SourceType.USER_DEFINED);
createSymbol(addr(200), "exit", scope2); createLabel(addr(200), "exit", scope2);
createSymbol(addr(200), "printf"); createLabel(addr(200), "printf");
createSymbol(addr(256), "exit"); createLabel(addr(256), "exit");
SymbolIterator it = st.getSymbols("exit"); SymbolIterator it = st.getSymbols("exit");
int cnt = 0; int cnt = 0;
@ -133,23 +134,23 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testGetNumSymbols() throws Exception { public void testGetNumSymbols() throws Exception {
createSymbol(addr(100), "primary"); createLabel(addr(100), "primary");
createSymbol(addr(100), "fred"); createLabel(addr(100), "fred");
createSymbol(addr(100), "joe"); createLabel(addr(100), "joe");
Namespace scope = st.createNameSpace(null, "MyNamespace", SourceType.USER_DEFINED); Namespace scope = st.createNameSpace(null, "MyNamespace", SourceType.USER_DEFINED);
Namespace scope2 = st.createNameSpace(null, "MyNamespace2", SourceType.USER_DEFINED); Namespace scope2 = st.createNameSpace(null, "MyNamespace2", SourceType.USER_DEFINED);
createSymbol(addr(100), "exit", scope); createLabel(addr(100), "exit", scope);
createSymbol(addr(200), "exit", scope2); createLabel(addr(200), "exit", scope2);
createSymbol(addr(200), "printf"); createLabel(addr(200), "printf");
createSymbol(addr(256), "exit"); createLabel(addr(256), "exit");
assertEquals(9, st.getNumSymbols()); assertEquals(9, st.getNumSymbols());
} }
@Test @Test
public void testGetPrimarySymbol() throws Exception { public void testGetPrimarySymbol() throws Exception {
createSymbol(addr(100), "primary"); createLabel(addr(100), "primary");
createSymbol(addr(100), "fred"); createLabel(addr(100), "fred");
createSymbol(addr(100), "joe"); createLabel(addr(100), "joe");
Symbol s = st.getPrimarySymbol(addr(100)); Symbol s = st.getPrimarySymbol(addr(100));
assertNotNull(s); assertNotNull(s);
assertEquals("primary", s.getName()); assertEquals("primary", s.getName());
@ -157,20 +158,20 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testGetAllSymbols() throws Exception { public void testGetAllSymbols() throws Exception {
createSymbol(addr(100), "primary"); createLabel(addr(100), "primary");
createSymbol(addr(100), "fred"); createLabel(addr(100), "fred");
createSymbol(addr(100), "joe"); createLabel(addr(100), "joe");
Symbol[] syms = st.getSymbols(addr(100)); Symbol[] syms = st.getSymbols(addr(100));
assertEquals(3, syms.length); assertEquals(3, syms.length);
} }
@Test @Test
public void testGetByName() throws Exception { public void testGetByName() throws Exception {
createSymbol(addr(100), "primary"); createLabel(addr(100), "primary");
createSymbol(addr(100), "fred"); createLabel(addr(100), "fred");
createSymbol(addr(100), "joe"); createLabel(addr(100), "joe");
Namespace scope = st.createNameSpace(null, "MyNamespace", SourceType.USER_DEFINED); Namespace scope = st.createNameSpace(null, "MyNamespace", SourceType.USER_DEFINED);
createSymbol(addr(200), "fred", scope); createLabel(addr(200), "fred", scope);
Symbol s = getUniqueSymbol(program, "fred"); Symbol s = getUniqueSymbol(program, "fred");
assertNotNull(s); assertNotNull(s);
assertEquals("fred", s.getName()); assertEquals("fred", s.getName());
@ -187,11 +188,11 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testGetSymbolByAddress() throws Exception { public void testGetSymbolByAddress() throws Exception {
createSymbol(addr(100), "A"); createLabel(addr(100), "A");
createSymbol(addr(100), "fred"); createLabel(addr(100), "fred");
createSymbol(addr(100), "joe"); createLabel(addr(100), "joe");
Namespace scope = st.createNameSpace(null, "MyNamespace", SourceType.USER_DEFINED); Namespace scope = st.createNameSpace(null, "MyNamespace", SourceType.USER_DEFINED);
createSymbol(addr(200), "fred", scope); createLabel(addr(200), "fred", scope);
Symbol s = st.getSymbol("fred", addr(200), scope); Symbol s = st.getSymbol("fred", addr(200), scope);
assertNotNull(s); assertNotNull(s);
@ -203,11 +204,11 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testGetSymbolIteratorByAddress() throws Exception { public void testGetSymbolIteratorByAddress() throws Exception {
createSymbol(addr(100), "A"); createLabel(addr(100), "A");
createSymbol(addr(100), "fred"); createLabel(addr(100), "fred");
createSymbol(addr(100), "joe"); createLabel(addr(100), "joe");
Namespace scope = st.createNameSpace(null, "MyNamespace", SourceType.USER_DEFINED); Namespace scope = st.createNameSpace(null, "MyNamespace", SourceType.USER_DEFINED);
createSymbol(addr(200), "fred", scope); createLabel(addr(200), "fred", scope);
SymbolIterator it = st.getSymbolsAsIterator(addr(100)); SymbolIterator it = st.getSymbolsAsIterator(addr(100));
@ -225,7 +226,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testGetSymbolByReference() throws Exception { public void testGetSymbolByReference() throws Exception {
createSymbol(addr(256), "A"); createLabel(addr(256), "A");
refMgr.addMemoryReference(addr(512), addr(256), RefType.FLOW, SourceType.USER_DEFINED, -1); refMgr.addMemoryReference(addr(512), addr(256), RefType.FLOW, SourceType.USER_DEFINED, -1);
Reference ref = refMgr.getReference(addr(512), addr(256), -1); Reference ref = refMgr.getReference(addr(512), addr(256), -1);
Symbol s = st.getSymbol(ref); Symbol s = st.getSymbol(ref);
@ -366,7 +367,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
set.addRange(addr(100), addr(150)); set.addRange(addr(100), addr(150));
set.addRange(addr(300), addr(310)); set.addRange(addr(300), addr(310));
set.addRange(addr(320), addr(330)); set.addRange(addr(320), addr(330));
Function f = listing.createFunction("fredFunc", addr(102), set, SourceType.DEFAULT); Function f = listing.createFunction("fredFunc", addr(102), set, SourceType.DEFAULT); // name ignored
assertNotNull(f); assertNotNull(f);
String defaultName = "FUN_00000066"; String defaultName = "FUN_00000066";
@ -465,11 +466,11 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testRemoveSymbol() throws Exception { public void testRemoveSymbol() throws Exception {
createSymbol(addr(100), "primary"); createLabel(addr(100), "primary");
createSymbol(addr(100), "fred"); createLabel(addr(100), "fred");
createSymbol(addr(100), "joe"); createLabel(addr(100), "joe");
createSymbol(addr(100), "bob"); createLabel(addr(100), "bob");
createSymbol(addr(0x200), "A"); createLabel(addr(0x200), "A");
Symbol s = st.getPrimarySymbol(addr(100)); Symbol s = st.getPrimarySymbol(addr(100));
assertTrue(st.removeSymbolSpecial(s)); assertTrue(st.removeSymbolSpecial(s));
@ -486,7 +487,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
assertTrue(sym.isPrimary()); assertTrue(sym.isPrimary());
assertTrue(sym.getSource() == SourceType.DEFAULT); assertTrue(sym.getSource() == SourceType.DEFAULT);
Symbol s2 = createSymbol(addr(256), "TEST"); Symbol s2 = createLabel(addr(256), "TEST");
sym = st.getPrimarySymbol(addr(256)); sym = st.getPrimarySymbol(addr(256));
assertTrue(sym.isPrimary()); assertTrue(sym.isPrimary());
assertTrue(sym.getSource() != SourceType.DEFAULT); assertTrue(sym.getSource() != SourceType.DEFAULT);
@ -499,7 +500,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testRemoveSymbol3() throws Exception { public void testRemoveSymbol3() throws Exception {
// remove non-dynamic, primary symbol without refs // remove non-dynamic, primary symbol without refs
Symbol sym = createSymbol(addr(256), "TEST"); Symbol sym = createLabel(addr(256), "TEST");
assertTrue(sym.isPrimary()); assertTrue(sym.isPrimary());
assertTrue(sym.getSource() != SourceType.DEFAULT); assertTrue(sym.getSource() != SourceType.DEFAULT);
assertTrue(st.removeSymbolSpecial(sym)); assertTrue(st.removeSymbolSpecial(sym));
@ -507,9 +508,9 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testRemoveSymbol5() throws Exception { public void testRemoveSymbol5() throws Exception {
createSymbol(addr(256), "TEST1"); createLabel(addr(256), "TEST1");
Symbol sym2 = createSymbol(addr(256), "TEST2"); Symbol sym2 = createLabel(addr(256), "TEST2");
createSymbol(addr(256), "TEST3"); createLabel(addr(256), "TEST3");
assertTrue(st.removeSymbolSpecial(sym2)); assertTrue(st.removeSymbolSpecial(sym2));
Symbol[] symbols = st.getSymbols(addr(256)); Symbol[] symbols = st.getSymbols(addr(256));
assertEquals(2, symbols.length); assertEquals(2, symbols.length);
@ -521,9 +522,9 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testRemoveSymbol7() throws Exception { public void testRemoveSymbol7() throws Exception {
Symbol sym1 = createSymbol(addr(256), "TEST1"); Symbol sym1 = createLabel(addr(256), "TEST1");
Symbol sym2 = createSymbol(addr(256), "TEST2"); Symbol sym2 = createLabel(addr(256), "TEST2");
Reference ref = refMgr.addMemoryReference(addr(512), addr(256), RefType.FLOW, Reference ref = refMgr.addMemoryReference(addr(512), addr(256), RefType.FLOW,
SourceType.USER_DEFINED, -1); SourceType.USER_DEFINED, -1);
refMgr.setAssociation(sym2, ref); refMgr.setAssociation(sym2, ref);
@ -844,9 +845,9 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testPrimarySymbolBecomesNonPrimaryAfterFunctionCreated() throws Exception { public void testPrimarySymbolBecomesNonPrimaryAfterFunctionCreated() throws Exception {
Address addr = addr(256); Address addr = addr(256);
Symbol sym1 = createSymbol(addr, "TEST1"); Symbol sym1 = createLabel(addr, "TEST1");
Symbol sym2 = createSymbol(addr, "TEST2"); Symbol sym2 = createLabel(addr, "TEST2");
Symbol sym3 = createSymbol(addr, "TEST3"); Symbol sym3 = createLabel(addr, "TEST3");
assertEquals(sym1, st.getPrimarySymbol(addr)); assertEquals(sym1, st.getPrimarySymbol(addr));
@ -873,9 +874,9 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testPrimarySymbolGetsPromotedToFunction() throws Exception { public void testPrimarySymbolGetsPromotedToFunction() throws Exception {
Address addr = addr(256); Address addr = addr(256);
Symbol sym1 = createSymbol(addr, "TEST1"); Symbol sym1 = createLabel(addr, "TEST1");
Symbol sym2 = createSymbol(addr, "TEST2"); Symbol sym2 = createLabel(addr, "TEST2");
Symbol sym3 = createSymbol(addr, "TEST3"); Symbol sym3 = createLabel(addr, "TEST3");
assertEquals(sym1, st.getPrimarySymbol(addr)); assertEquals(sym1, st.getPrimarySymbol(addr));
@ -937,9 +938,9 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testRenameSymbol() throws Exception { public void testRenameSymbol() throws Exception {
Symbol s = createSymbol(addr(100), "primary"); Symbol s = createLabel(addr(100), "primary");
createSymbol(addr(100), "fred"); createLabel(addr(100), "fred");
createSymbol(addr(100), "joe"); createLabel(addr(100), "joe");
s.setName("printf", SourceType.USER_DEFINED); s.setName("printf", SourceType.USER_DEFINED);
assertEquals("printf", s.getName()); assertEquals("printf", s.getName());
@ -957,7 +958,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testRenameSymbol2() throws Exception { public void testRenameSymbol2() throws Exception {
// long names (>60) was a problem // long names (>60) was a problem
Symbol s = createSymbol(addr(100), Symbol s = createLabel(addr(100),
"aabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzABCDEFGH"); "aabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzABCDEFGH");
s.setName("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzABCDEFGH1", s.setName("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzABCDEFGH1",
@ -967,9 +968,9 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testSetPrimary() throws Exception { public void testSetPrimary() throws Exception {
Symbol s1 = createSymbol(addr(100), "primary"); Symbol s1 = createLabel(addr(100), "primary");
Symbol s2 = createSymbol(addr(100), "fred"); Symbol s2 = createLabel(addr(100), "fred");
createSymbol(addr(100), "joe"); createLabel(addr(100), "joe");
assertTrue(s1.isPrimary()); assertTrue(s1.isPrimary());
s2.setPrimary(); s2.setPrimary();
@ -980,9 +981,9 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testSetScope() throws Exception { public void testSetScope() throws Exception {
Symbol s1 = createSymbol(addr(100), "primary"); Symbol s1 = createLabel(addr(100), "primary");
Symbol s2 = createSymbol(addr(100), "fred"); Symbol s2 = createLabel(addr(100), "fred");
Symbol s3 = createSymbol(addr(100), "joe"); Symbol s3 = createLabel(addr(100), "joe");
Namespace scope = st.createNameSpace(null, "MyNamespace", SourceType.USER_DEFINED); Namespace scope = st.createNameSpace(null, "MyNamespace", SourceType.USER_DEFINED);
s2.setNamespace(scope); s2.setNamespace(scope);
@ -994,7 +995,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testExternalEntry() throws Exception { public void testExternalEntry() throws Exception {
createSymbol(addr(100), "A"); createLabel(addr(100), "A");
st.addExternalEntryPoint(addr(100)); st.addExternalEntryPoint(addr(100));
Symbol s = st.getPrimarySymbol(addr(100)); Symbol s = st.getPrimarySymbol(addr(100));
assertTrue(s.isExternalEntryPoint()); assertTrue(s.isExternalEntryPoint());
@ -1025,14 +1026,14 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testIsExternalEntry() throws Exception { public void testIsExternalEntry() throws Exception {
createSymbol(addr(100), "A"); createLabel(addr(100), "A");
st.addExternalEntryPoint(addr(100)); st.addExternalEntryPoint(addr(100));
assertTrue(st.isExternalEntryPoint(addr(100))); assertTrue(st.isExternalEntryPoint(addr(100)));
} }
@Test @Test
public void testAssociation() throws Exception { public void testAssociation() throws Exception {
Symbol sym2 = createSymbol(addr(256), "TEST2"); Symbol sym2 = createLabel(addr(256), "TEST2");
refMgr.addMemoryReference(addr(784), addr(256), RefType.FLOW, SourceType.USER_DEFINED, 2); refMgr.addMemoryReference(addr(784), addr(256), RefType.FLOW, SourceType.USER_DEFINED, 2);
Reference ref = refMgr.getReference(addr(784), addr(256), 2); Reference ref = refMgr.getReference(addr(784), addr(256), 2);
@ -1049,7 +1050,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testRemoveAssociation() throws Exception { public void testRemoveAssociation() throws Exception {
Symbol sym2 = createSymbol(addr(256), "TEST2"); Symbol sym2 = createLabel(addr(256), "TEST2");
refMgr.addMemoryReference(addr(784), addr(256), RefType.FLOW, SourceType.USER_DEFINED, 2); refMgr.addMemoryReference(addr(784), addr(256), RefType.FLOW, SourceType.USER_DEFINED, 2);
Reference ref = refMgr.getReference(addr(784), addr(256), 2); Reference ref = refMgr.getReference(addr(784), addr(256), 2);
refMgr.setAssociation(sym2, ref); refMgr.setAssociation(sym2, ref);
@ -1063,13 +1064,13 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testGetSymbolReferences() throws Exception { public void testGetSymbolReferences() throws Exception {
Symbol sym1 = createSymbol(addr(256), "TEST1"); Symbol sym1 = createLabel(addr(256), "TEST1");
refMgr.addMemoryReference(addr(512), addr(256), RefType.FLOW, SourceType.USER_DEFINED, 2); refMgr.addMemoryReference(addr(512), addr(256), RefType.FLOW, SourceType.USER_DEFINED, 2);
refMgr.addMemoryReference(addr(1024), addr(256), RefType.FLOW, SourceType.USER_DEFINED, 0); refMgr.addMemoryReference(addr(1024), addr(256), RefType.FLOW, SourceType.USER_DEFINED, 0);
refMgr.addMemoryReference(addr(1024), addr(256), RefType.FLOW, SourceType.USER_DEFINED, 1); refMgr.addMemoryReference(addr(1024), addr(256), RefType.FLOW, SourceType.USER_DEFINED, 1);
refMgr.addMemoryReference(addr(784), addr(256), RefType.FLOW, SourceType.USER_DEFINED, -1); refMgr.addMemoryReference(addr(784), addr(256), RefType.FLOW, SourceType.USER_DEFINED, -1);
Symbol sym2 = createSymbol(addr(256), "TEST2"); Symbol sym2 = createLabel(addr(256), "TEST2");
refMgr.addMemoryReference(addr(784), addr(256), RefType.FLOW, SourceType.USER_DEFINED, 2); refMgr.addMemoryReference(addr(784), addr(256), RefType.FLOW, SourceType.USER_DEFINED, 2);
Reference ref = refMgr.getReference(addr(784), addr(256), 2); Reference ref = refMgr.getReference(addr(784), addr(256), 2);
refMgr.setAssociation(sym2, ref); refMgr.setAssociation(sym2, ref);
@ -1114,21 +1115,21 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testSymbolSearcherIterator() throws Exception { public void testSymbolSearcherIterator() throws Exception {
createSymbol(addr(100), "Four"); createLabel(addr(100), "Four");
createSymbol(addr(100), "Five"); createLabel(addr(100), "Five");
createSymbol(addr(100), "Six"); createLabel(addr(100), "Six");
createSymbol(addr(100), "Seven"); createLabel(addr(100), "Seven");
createSymbol(addr(100), "Eight"); createLabel(addr(100), "Eight");
createSymbol(addr(100), "Nine"); createLabel(addr(100), "Nine");
createSymbol(addr(100), "Thirteen"); createLabel(addr(100), "Thirteen");
createSymbol(addr(200), "Fourteen"); createLabel(addr(200), "Fourteen");
createSymbol(addr(200), "Fifteen"); createLabel(addr(200), "Fifteen");
createSymbol(addr(200), "Sixteen"); createLabel(addr(200), "Sixteen");
createSymbol(addr(200), "Seventeen"); createLabel(addr(200), "Seventeen");
createSymbol(addr(300), "Eighteen"); createLabel(addr(300), "Eighteen");
createSymbol(addr(300), "Nineteen"); createLabel(addr(300), "Nineteen");
createSymbol(addr(300), "Sixty"); createLabel(addr(300), "Sixty");
createSymbol(addr(300), "Sixty-five"); createLabel(addr(300), "Sixty-five");
List<String> list = search("Six*", true); List<String> list = search("Six*", true);
assertContains(list, "Six", "Sixteen", "Sixty", "Sixty-five"); assertContains(list, "Six", "Sixteen", "Sixty", "Sixty-five");
@ -1146,18 +1147,18 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testSymbolSearcherIterator_WithSymbolNamesContainingWildcards() throws Exception { public void testSymbolSearcherIterator_WithSymbolNamesContainingWildcards() throws Exception {
createSymbols(addr(100), "Alpha", "alpha", "Albha", "Alzza", "Alibaba", "Alibabas"); createLabels(addr(100), "Alpha", "alpha", "Albha", "Alzza", "Alibaba", "Alibabas");
createSymbol(addr(100), "Bravo"); createLabel(addr(100), "Bravo");
createSymbol(addr(100), "Charlie"); createLabel(addr(100), "Charlie");
createSymbol(addr(200), "Delta"); createLabel(addr(200), "Delta");
createSymbols(addr(200), "echo", "echo!bang", "ECHO!bang", "!bangecho", "!bangECHO"); createLabels(addr(200), "echo", "echo!bang", "ECHO!bang", "!bangecho", "!bangECHO");
createSymbols(addr(300), "^FOXTROT-hyphen", "^foxtrot-hyphen"); createLabels(addr(300), "^FOXTROT-hyphen", "^foxtrot-hyphen");
createSymbol(addr(400), "golf,comma"); createLabel(addr(400), "golf,comma");
createSymbol(addr(500), "hotel_underscore"); createLabel(addr(500), "hotel_underscore");
createSymbol(addr(600), "india.dot.dollar$"); createLabel(addr(600), "india.dot.dollar$");
createSymbols(addr(700), "*juliet*", "*JULIET*"); createLabels(addr(700), "*juliet*", "*JULIET*");
createSymbols(addr(700), "kilo*star", "KILO*star"); createLabels(addr(700), "kilo*star", "KILO*star");
createSymbols(addr(800), "lima?questionmark", "LIMA?questionmark"); createLabels(addr(800), "lima?questionmark", "LIMA?questionmark");
boolean caseSensitive = true; boolean caseSensitive = true;
@ -1247,51 +1248,75 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testPrimarySymbolIteratorSet() throws Exception { public void testPrimarySymbolIteratorSet() throws Exception {
createSymbol(addr(100), "1"); createLabel(addr(100), "1");
createSymbol(addr(200), "2"); createLabel(addr(200), "2");
createSymbol(addr(200), "2a"); createLabel(addr(200), "2a");
createSymbol(addr(200), "2b"); createLabel(addr(200), "2b");
createSymbol(addr(200), "2c"); createLabel(addr(200), "2c");
createSymbol(addr(300), "3"); createLabel(addr(300), "3");
createSymbol(addr(300), "3a"); createLabel(addr(300), "3a");
createSymbol(addr(300), "3b"); createLabel(addr(300), "3b");
createSymbol(addr(300), "3c"); createLabel(addr(300), "3c");
createSymbol(addr(400), "4"); createLabel(addr(400), "4");
createSymbol(addr(500), "5"); createLabel(addr(500), "5");
createSymbol(addr(500), "5a"); createLabel(addr(500), "5a");
createFunction(addr(2000), "6");
createLabel(addr(2000), "6a");
createExternalFunction("7");
createExternalLabel("8");
AddressSet set = new AddressSet(addr(0), addr(50)); AddressSet set = new AddressSet(addr(0), addr(50));
set.addRange(addr(300), addr(350)); set.addRange(addr(300), addr(350));
set.addRange(addr(500), addr(1000)); set.addRange(addr(500), addr(1000));
set.addRange(AddressSpace.EXTERNAL_SPACE.getMinAddress(),
AddressSpace.EXTERNAL_SPACE.getMaxAddress());
SymbolIterator it = st.getPrimarySymbolIterator(set, true); SymbolIterator it = st.getPrimarySymbolIterator(set, true);
// External space before memory space
Symbol s = it.next(); Symbol s = it.next();
assertNotNull(s); assertNotNull(s);
assertEquals("7", s.getName());
assertEquals(extAddr(1), s.getAddress());
s = it.next();
assertNotNull(s);
assertEquals("8", s.getName());
assertEquals(extAddr(2), s.getAddress());
s = it.next();
assertNotNull(s);
assertEquals(addr(300), s.getAddress()); assertEquals(addr(300), s.getAddress());
s = it.next(); s = it.next();
assertNotNull(s); assertNotNull(s);
assertEquals(addr(500), s.getAddress()); assertEquals(addr(500), s.getAddress());
assertTrue(!it.hasNext()); assertTrue(!it.hasNext());
assertNull(it.next()); assertNull(it.next());
} }
@Test @Test
public void testPrimarySymbolIteratorSetBackwards() throws Exception { public void testPrimarySymbolIteratorSetBackwards() throws Exception {
createSymbol(addr(100), "1"); createLabel(addr(100), "1");
createSymbol(addr(200), "2"); createLabel(addr(200), "2");
createSymbol(addr(200), "2a"); createLabel(addr(200), "2a");
createSymbol(addr(200), "2b"); createLabel(addr(200), "2b");
createSymbol(addr(200), "2c"); createLabel(addr(200), "2c");
createSymbol(addr(300), "3"); createLabel(addr(300), "3");
createSymbol(addr(300), "3a"); createLabel(addr(300), "3a");
createSymbol(addr(300), "3b"); createLabel(addr(300), "3b");
createSymbol(addr(300), "3c"); createLabel(addr(300), "3c");
createSymbol(addr(400), "4"); createLabel(addr(400), "4");
createSymbol(addr(500), "5"); createLabel(addr(500), "5");
createSymbol(addr(500), "5a"); createLabel(addr(500), "5a");
createFunction(addr(2000), "6");
createLabel(addr(2000), "6a");
createExternalFunction("7");
createExternalLabel("8");
AddressSet set = new AddressSet(addr(0), addr(50)); AddressSet set = new AddressSet(addr(0), addr(50));
set.addRange(addr(300), addr(350)); set.addRange(addr(300), addr(350));
set.addRange(addr(500), addr(1000)); set.addRange(addr(500), addr(1000));
set.addRange(AddressSpace.EXTERNAL_SPACE.getMinAddress(),
AddressSpace.EXTERNAL_SPACE.getMaxAddress());
SymbolIterator it = st.getPrimarySymbolIterator(set, false); SymbolIterator it = st.getPrimarySymbolIterator(set, false);
Symbol s = it.next(); Symbol s = it.next();
@ -1302,23 +1327,34 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
assertNotNull(s); assertNotNull(s);
assertEquals(addr(300), s.getAddress()); assertEquals(addr(300), s.getAddress());
assertEquals("3", s.getName()); assertEquals("3", s.getName());
// External space after memory space
s = it.next();
assertNotNull(s);
assertEquals("8", s.getName());
assertEquals(extAddr(2), s.getAddress());
s = it.next();
assertNotNull(s);
assertEquals("7", s.getName());
assertEquals(extAddr(1), s.getAddress());
assertTrue(!it.hasNext()); assertTrue(!it.hasNext());
assertNull(it.next()); assertNull(it.next());
} }
@Test @Test
public void testSymbolIteratorBackwards() throws Exception { public void testSymbolIteratorBackwards() throws Exception {
createSymbol(addr(100), "1"); createLabel(addr(100), "1");
createSymbol(addr(200), "2"); createLabel(addr(200), "2");
createSymbol(addr(200), "2b"); createLabel(addr(200), "2b");
createSymbol(addr(200), "2c"); createLabel(addr(200), "2c");
createSymbol(addr(300), "3"); createLabel(addr(300), "3");
createSymbol(addr(300), "3a"); createLabel(addr(300), "3a");
createSymbol(addr(300), "3b"); createLabel(addr(300), "3b");
createSymbol(addr(300), "3c"); createLabel(addr(300), "3c");
createSymbol(addr(400), "4"); createLabel(addr(400), "4");
createSymbol(addr(500), "5"); createLabel(addr(500), "5");
createSymbol(addr(600), "6"); createLabel(addr(600), "6");
SymbolIterator it = st.getSymbolIterator(false); SymbolIterator it = st.getSymbolIterator(false);
assertTrue(it.hasNext()); assertTrue(it.hasNext());
@ -1336,18 +1372,18 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testPrimarySymbolIterator() throws Exception { public void testPrimarySymbolIterator() throws Exception {
createSymbol(addr(100), "1"); createLabel(addr(100), "1");
createSymbol(addr(200), "2"); createLabel(addr(200), "2");
createSymbol(addr(200), "2a"); createLabel(addr(200), "2a");
createSymbol(addr(200), "2b"); createLabel(addr(200), "2b");
createSymbol(addr(200), "2c"); createLabel(addr(200), "2c");
createSymbol(addr(300), "3"); createLabel(addr(300), "3");
createSymbol(addr(300), "3a"); createLabel(addr(300), "3a");
createSymbol(addr(300), "3b"); createLabel(addr(300), "3b");
createSymbol(addr(300), "3c"); createLabel(addr(300), "3c");
createSymbol(addr(400), "4"); createLabel(addr(400), "4");
createSymbol(addr(500), "5"); createLabel(addr(500), "5");
createSymbol(addr(500), "5a"); createLabel(addr(500), "5a");
SymbolIterator it = st.getPrimarySymbolIterator(true); SymbolIterator it = st.getPrimarySymbolIterator(true);
int count = 1; int count = 1;
@ -1361,18 +1397,18 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testPrimarySymbolIteratorBackwards() throws Exception { public void testPrimarySymbolIteratorBackwards() throws Exception {
createSymbol(addr(100), "1"); createLabel(addr(100), "1");
createSymbol(addr(200), "2"); createLabel(addr(200), "2");
createSymbol(addr(200), "2a"); createLabel(addr(200), "2a");
createSymbol(addr(200), "2b"); createLabel(addr(200), "2b");
createSymbol(addr(200), "2c"); createLabel(addr(200), "2c");
createSymbol(addr(300), "3"); createLabel(addr(300), "3");
createSymbol(addr(300), "3a"); createLabel(addr(300), "3a");
createSymbol(addr(300), "3b"); createLabel(addr(300), "3b");
createSymbol(addr(300), "3c"); createLabel(addr(300), "3c");
createSymbol(addr(400), "4"); createLabel(addr(400), "4");
createSymbol(addr(500), "5"); createLabel(addr(500), "5");
createSymbol(addr(500), "5a"); createLabel(addr(500), "5a");
SymbolIterator it = st.getPrimarySymbolIterator(false); SymbolIterator it = st.getPrimarySymbolIterator(false);
assertTrue(it.hasNext()); assertTrue(it.hasNext());
@ -1394,9 +1430,9 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testSymbolIteratorByType() throws Exception { public void testSymbolIteratorByType() throws Exception {
createSymbol(addr(100), "1"); createLabel(addr(100), "1");
createSymbol(addr(200), "2"); createLabel(addr(200), "2");
createSymbol(addr(300), "3"); createLabel(addr(300), "3");
Function f1 = createFunction("A", addr(150)); Function f1 = createFunction("A", addr(150));
Function f2 = createFunction("B", addr(250)); Function f2 = createFunction("B", addr(250));
@ -1415,9 +1451,9 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testSymbolIteratorByTypeBackward() throws Exception { public void testSymbolIteratorByTypeBackward() throws Exception {
createSymbol(addr(100), "1"); createLabel(addr(100), "1");
createSymbol(addr(200), "2"); createLabel(addr(200), "2");
createSymbol(addr(300), "3"); createLabel(addr(300), "3");
Function f1 = createFunction("A", addr(150)); Function f1 = createFunction("A", addr(150));
Function f2 = createFunction("B", addr(250)); Function f2 = createFunction("B", addr(250));
@ -1446,7 +1482,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
refMgr.addMemoryReference(addr(200), addr(356), RefType.CONDITIONAL_JUMP, refMgr.addMemoryReference(addr(200), addr(356), RefType.CONDITIONAL_JUMP,
SourceType.USER_DEFINED, 2); SourceType.USER_DEFINED, 2);
Reference ref = refMgr.getReference(addr(200), addr(356), 2); Reference ref = refMgr.getReference(addr(200), addr(356), 2);
createSymbol(addr(356), "printf"); createLabel(addr(356), "printf");
s = st.getSymbol(ref); s = st.getSymbol(ref);
assertNotNull(s); assertNotNull(s);
assertEquals("printf", s.getName()); assertEquals("printf", s.getName());
@ -1469,7 +1505,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
ref = refMgr.addMemoryReference(addr(200), addr(356), RefType.CONDITIONAL_JUMP, ref = refMgr.addMemoryReference(addr(200), addr(356), RefType.CONDITIONAL_JUMP,
SourceType.USER_DEFINED, 2); SourceType.USER_DEFINED, 2);
createSymbol(addr(356), "printf"); createLabel(addr(356), "printf");
s = st.getSymbol(ref); s = st.getSymbol(ref);
assertNotNull(s); assertNotNull(s);
assertEquals("printf", s.getName()); assertEquals("printf", s.getName());
@ -1485,7 +1521,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testCreateFunction() throws Exception { public void testCreateFunction() throws Exception {
Symbol s = createSymbol(addr(100), "fred"); Symbol s = createLabel(addr(100), "fred");
assertTrue(s.isPrimary()); assertTrue(s.isPrimary());
AddressSet set = new AddressSet(); AddressSet set = new AddressSet();
@ -1512,9 +1548,9 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testPromoteLabelToFunctionWithMultipleLabels() throws Exception { public void testPromoteLabelToFunctionWithMultipleLabels() throws Exception {
Symbol s = createSymbol(addr(100), "fred"); Symbol s = createLabel(addr(100), "fred");
assertTrue(s.isPrimary()); assertTrue(s.isPrimary());
Symbol s2 = createSymbol(addr(100), "joe"); Symbol s2 = createLabel(addr(100), "joe");
assertTrue(!s2.isPrimary()); assertTrue(!s2.isPrimary());
s2.setPrimary(); s2.setPrimary();
@ -1547,7 +1583,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testRemoveFunction() throws Exception { public void testRemoveFunction() throws Exception {
Symbol s = createSymbol(addr(100), "fred"); Symbol s = createLabel(addr(100), "fred");
assertFalse(s.isDeleted()); assertFalse(s.isDeleted());
AddressSet set = new AddressSet(); AddressSet set = new AddressSet();
@ -1596,7 +1632,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testAddExtEntryPoint() throws Exception { public void testAddExtEntryPoint() throws Exception {
Symbol s = createSymbol(addr(100), "extEntryPoint"); Symbol s = createLabel(addr(100), "extEntryPoint");
st.addExternalEntryPoint(addr(100)); st.addExternalEntryPoint(addr(100));
assertEquals("extEntryPoint", s.getName()); assertEquals("extEntryPoint", s.getName());
assertTrue(s.isExternalEntryPoint()); assertTrue(s.isExternalEntryPoint());
@ -1605,7 +1641,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testRemoveExtEntryPoint() throws Exception { public void testRemoveExtEntryPoint() throws Exception {
Symbol s = createSymbol(addr(100), "extEntryPoint"); Symbol s = createLabel(addr(100), "extEntryPoint");
st.addExternalEntryPoint(addr(100)); st.addExternalEntryPoint(addr(100));
assertEquals("extEntryPoint", s.getName()); assertEquals("extEntryPoint", s.getName());
assertTrue(s.isExternalEntryPoint()); assertTrue(s.isExternalEntryPoint());
@ -1617,9 +1653,9 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testGetAllSymbolsIncludingDynamic() throws Exception { public void testGetAllSymbolsIncludingDynamic() throws Exception {
createSymbol(addr(0x100), "aaaa"); createLabel(addr(0x100), "aaaa");
createSymbol(addr(0x200), "bbbb"); createLabel(addr(0x200), "bbbb");
createSymbol(addr(0x300), "cccc"); createLabel(addr(0x300), "cccc");
refMgr.addMemoryReference(addr(0x40), addr(0x050), RefType.FLOW, SourceType.USER_DEFINED, refMgr.addMemoryReference(addr(0x40), addr(0x050), RefType.FLOW, SourceType.USER_DEFINED,
-1); -1);
refMgr.addMemoryReference(addr(0x30), addr(0x150), RefType.FLOW, SourceType.USER_DEFINED, refMgr.addMemoryReference(addr(0x30), addr(0x150), RefType.FLOW, SourceType.USER_DEFINED,
@ -1648,9 +1684,9 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
String[] names = { "primary", "fred", "joe" }; String[] names = { "primary", "fred", "joe" };
Address address = addr(100); Address address = addr(100);
createSymbol(address, "primary"); createLabel(address, "primary");
createSymbol(address, "fred"); createLabel(address, "fred");
createSymbol(address, "joe"); createLabel(address, "joe");
LabelHistory[] h = st.getLabelHistory(address); LabelHistory[] h = st.getLabelHistory(address);
assertEquals(3, h.length); assertEquals(3, h.length);
@ -1672,9 +1708,9 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
Address address = addr(100); Address address = addr(100);
Symbol s1 = createSymbol(address, "primary"); Symbol s1 = createLabel(address, "primary");
Symbol s2 = createSymbol(address, "fred"); Symbol s2 = createLabel(address, "fred");
createSymbol(address, "joe"); createLabel(address, "joe");
// rename s1 to // rename s1 to
s1.setName("MyPrimary", SourceType.USER_DEFINED); s1.setName("MyPrimary", SourceType.USER_DEFINED);
@ -1683,7 +1719,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
st.removeSymbolSpecial(s2); st.removeSymbolSpecial(s2);
// create new symbol // create new symbol
createSymbol(addr(100), "bob"); createLabel(addr(100), "bob");
LabelHistory[] h = st.getLabelHistory(address); LabelHistory[] h = st.getLabelHistory(address);
assertEquals(6, h.length); assertEquals(6, h.length);
@ -1711,9 +1747,9 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
Address[] addrs = Address[] addrs =
{ address, address, address, address, address, address, addr(200), addr(200) }; { address, address, address, address, address, address, addr(200), addr(200) };
Symbol s1 = createSymbol(address, "primary"); Symbol s1 = createLabel(address, "primary");
Symbol s2 = createSymbol(address, "fred"); Symbol s2 = createLabel(address, "fred");
createSymbol(address, "joe"); createLabel(address, "joe");
// rename s1 to // rename s1 to
s1.setName("MyPrimary", SourceType.USER_DEFINED); s1.setName("MyPrimary", SourceType.USER_DEFINED);
@ -1722,10 +1758,10 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
st.removeSymbolSpecial(s2); st.removeSymbolSpecial(s2);
// create new symbol // create new symbol
createSymbol(addr(100), "bob"); createLabel(addr(100), "bob");
createSymbol(addr(200), "printf"); createLabel(addr(200), "printf");
createSymbol(addr(200), "fprintf"); createLabel(addr(200), "fprintf");
ArrayList<LabelHistory> list = new ArrayList<LabelHistory>(); ArrayList<LabelHistory> list = new ArrayList<LabelHistory>();
Iterator<LabelHistory> iter = st.getLabelHistory(); Iterator<LabelHistory> iter = st.getLabelHistory();
@ -1832,13 +1868,13 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testSetSymbolName() throws Exception { public void testSetSymbolName() throws Exception {
Symbol s = createSymbol(addr(0x100), "mysymbol"); Symbol s = createLabel(addr(0x100), "mysymbol");
Namespace s1 = st.createNameSpace(null, "MySpace1", SourceType.USER_DEFINED); Namespace s1 = st.createNameSpace(null, "MySpace1", SourceType.USER_DEFINED);
st.createNameSpace(s1, "subspace1", SourceType.USER_DEFINED); st.createNameSpace(s1, "subspace1", SourceType.USER_DEFINED);
st.createNameSpace(s1, "fred", SourceType.USER_DEFINED); st.createNameSpace(s1, "fred", SourceType.USER_DEFINED);
s.setName("fred", SourceType.USER_DEFINED); s.setName("fred", SourceType.USER_DEFINED);
createSymbol(addr(0x100), "fred", s1); createLabel(addr(0x100), "fred", s1);
Symbol[] symbols = st.getSymbols(addr(0x100)); Symbol[] symbols = st.getSymbols(addr(0x100));
assertEquals(2, symbols.length); assertEquals(2, symbols.length);
assertEquals("fred", symbols[0].getName()); assertEquals("fred", symbols[0].getName());
@ -2192,7 +2228,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testIsValidParentForCodeSymbol() throws Exception { public void testIsValidParentForCodeSymbol() throws Exception {
Namespace namespace = st.createNameSpace(null, "TestNameSpace", SourceType.USER_DEFINED); Namespace namespace = st.createNameSpace(null, "TestNameSpace", SourceType.USER_DEFINED);
Symbol s = createSymbol(addr(0x125), "printf", namespace); Symbol s = createLabel(addr(0x125), "printf", namespace);
Namespace subspace1 = st.createNameSpace(namespace, "MySpace1", SourceType.USER_DEFINED); Namespace subspace1 = st.createNameSpace(namespace, "MySpace1", SourceType.USER_DEFINED);
assertTrue(s.isValidParent(subspace1)); assertTrue(s.isValidParent(subspace1));
@ -2212,7 +2248,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testIsValidParentForFunction() throws Exception { public void testIsValidParentForFunction() throws Exception {
Namespace namespace = st.createNameSpace(null, "TestNameSpace", SourceType.USER_DEFINED); Namespace namespace = st.createNameSpace(null, "TestNameSpace", SourceType.USER_DEFINED);
createSymbol(addr(0x125), "printf", namespace); createLabel(addr(0x125), "printf", namespace);
Namespace subspace1 = st.createNameSpace(namespace, "MySpace1", SourceType.USER_DEFINED); Namespace subspace1 = st.createNameSpace(namespace, "MySpace1", SourceType.USER_DEFINED);
AddressSet set = new AddressSet(addr(0x100), addr(0x150)); AddressSet set = new AddressSet(addr(0x100), addr(0x150));
@ -2277,7 +2313,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
public void testClassParentScope() throws Exception { public void testClassParentScope() throws Exception {
Namespace scope = st.createClass(null, "TestClass", SourceType.USER_DEFINED); Namespace scope = st.createClass(null, "TestClass", SourceType.USER_DEFINED);
createSymbol(addr(0x200), "printf", scope); createLabel(addr(0x200), "printf", scope);
} }
@ -2293,7 +2329,7 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
Function extFunc = (Function) extSym.getObject(); Function extFunc = (Function) extSym.getObject();
try { try {
createSymbol(addr(0x200), "printf", extFunc); createLabel(addr(0x200), "printf", extFunc);
Assert.fail("should have gotten invalid input exception!"); Assert.fail("should have gotten invalid input exception!");
} }
catch (InvalidInputException e) { catch (InvalidInputException e) {
@ -2314,15 +2350,15 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
@Test @Test
public void testGetUniqueSymbol_OneSymbol() throws InvalidInputException { public void testGetUniqueSymbol_OneSymbol() throws InvalidInputException {
Symbol newBob = createSymbol(addr(1), "bob"); Symbol newBob = createLabel(addr(1), "bob");
Symbol s = getUniqueSymbol(program, "bob"); Symbol s = getUniqueSymbol(program, "bob");
assertEquals(newBob, s); assertEquals(newBob, s);
} }
@Test @Test
public void testGetUniqueSymbol_MultipleSymbols() throws InvalidInputException { public void testGetUniqueSymbol_MultipleSymbols() throws InvalidInputException {
createSymbol(addr(1), "bob"); createLabel(addr(1), "bob");
createSymbol(addr(2), "bob"); createLabel(addr(2), "bob");
Symbol s = getUniqueSymbol(program, "bob"); Symbol s = getUniqueSymbol(program, "bob");
assertNull(s); assertNull(s);
} }
@ -2353,20 +2389,45 @@ public class SymbolManagerTest extends AbstractGhidraHeadedIntegrationTest {
return space.getAddress(l); return space.getAddress(l);
} }
private Symbol createSymbol(Address addr, String name) throws InvalidInputException { private Address extAddr(long l) {
return AddressSpace.EXTERNAL_SPACE.getAddress(l);
}
private Symbol createLabel(Address addr, String name) throws InvalidInputException {
return st.createLabel(addr, name, SourceType.USER_DEFINED); return st.createLabel(addr, name, SourceType.USER_DEFINED);
} }
private void createSymbols(Address addr, String... names) throws InvalidInputException { private void createLabels(Address addr, String... names) throws InvalidInputException {
for (String name : names) { for (String name : names) {
st.createLabel(addr, name, SourceType.USER_DEFINED); st.createLabel(addr, name, SourceType.USER_DEFINED);
} }
} }
private Symbol createSymbol(Address addr, String name, Namespace namespace) private Symbol createLabel(Address addr, String name, Namespace namespace)
throws InvalidInputException { throws InvalidInputException {
return st.createLabel(addr, name, namespace, SourceType.USER_DEFINED); return st.createLabel(addr, name, namespace, SourceType.USER_DEFINED);
} }
private Symbol createFunction(Address addr, String name)
throws InvalidInputException, OverlappingFunctionException {
return program.getFunctionManager()
.createFunction(name, addr, new AddressSet(addr, addr), SourceType.USER_DEFINED)
.getSymbol();
}
private Symbol createExternalLabel(String name)
throws InvalidInputException, DuplicateNameException {
ExternalManager externalManager = program.getExternalManager();
return externalManager.addExtLocation("Test", name, null, SourceType.USER_DEFINED)
.getSymbol();
}
private Symbol createExternalFunction(String name)
throws InvalidInputException, DuplicateNameException {
ExternalManager externalManager = program.getExternalManager();
return externalManager.addExtFunction("Test", name, null, SourceType.USER_DEFINED)
.getSymbol();
}
} }

View file

@ -87,9 +87,6 @@ public class ExternalManagerDB implements ManagerDB, ExternalManager {
} }
} }
/**
* @see ghidra.program.database.ManagerDB#setProgram(ghidra.program.database.ProgramDB)
*/
@Override @Override
public void setProgram(ProgramDB program) { public void setProgram(ProgramDB program) {
this.program = program; this.program = program;
@ -98,9 +95,6 @@ public class ExternalManagerDB implements ManagerDB, ExternalManager {
scopeMgr = program.getNamespaceManager(); scopeMgr = program.getNamespaceManager();
} }
/**
* @see ghidra.program.database.ManagerDB#programReady(int, int, ghidra.util.task.TaskMonitor)
*/
@Override @Override
public void programReady(int openMode, int currentRevision, TaskMonitor monitor) public void programReady(int openMode, int currentRevision, TaskMonitor monitor)
throws IOException, CancelledException { throws IOException, CancelledException {
@ -185,26 +179,17 @@ public class ExternalManagerDB implements ManagerDB, ExternalManager {
return true; return true;
} }
/**
* @see ghidra.program.database.ManagerDB#invalidateCache(boolean)
*/
@Override @Override
public void invalidateCache(boolean all) throws IOException { public void invalidateCache(boolean all) throws IOException {
// nothing to do here // nothing to do here
} }
/**
* @see ghidra.program.database.ManagerDB#deleteAddressRange(ghidra.program.model.address.Address, ghidra.program.model.address.Address, ghidra.util.task.TaskMonitor)
*/
@Override @Override
public void deleteAddressRange(Address startAddr, Address endAddr, TaskMonitor monitor) public void deleteAddressRange(Address startAddr, Address endAddr, TaskMonitor monitor)
throws CancelledException { throws CancelledException {
// Has no affect on externals // Has no affect on externals
} }
/**
* @see ghidra.program.database.ManagerDB#moveAddressRange(ghidra.program.model.address.Address, ghidra.program.model.address.Address, long, ghidra.util.task.TaskMonitor)
*/
@Override @Override
public void moveAddressRange(Address fromAddr, Address toAddr, long length, TaskMonitor monitor) public void moveAddressRange(Address fromAddr, Address toAddr, long length, TaskMonitor monitor)
throws CancelledException { throws CancelledException {
@ -230,8 +215,7 @@ public class ExternalManagerDB implements ManagerDB, ExternalManager {
@Override @Override
public ExternalLocation addExtLocation(Namespace extParentNamespace, String extLabel, public ExternalLocation addExtLocation(Namespace extParentNamespace, String extLabel,
Address extAddr, SourceType sourceType) Address extAddr, SourceType sourceType) throws InvalidInputException {
throws InvalidInputException, DuplicateNameException {
lock.acquire(); lock.acquire();
try { try {
return addExtLocation(extParentNamespace, extLabel, extAddr, false, sourceType, true); return addExtLocation(extParentNamespace, extLabel, extAddr, false, sourceType, true);
@ -243,8 +227,7 @@ public class ExternalManagerDB implements ManagerDB, ExternalManager {
@Override @Override
public ExternalLocation addExtLocation(Namespace extParentNamespace, String extLabel, public ExternalLocation addExtLocation(Namespace extParentNamespace, String extLabel,
Address extAddr, SourceType sourceType, boolean reuseExisting) Address extAddr, SourceType sourceType, boolean reuseExisting) throws InvalidInputException {
throws InvalidInputException, DuplicateNameException {
lock.acquire(); lock.acquire();
try { try {
return addExtLocation(extParentNamespace, extLabel, extAddr, false, sourceType, return addExtLocation(extParentNamespace, extLabel, extAddr, false, sourceType,
@ -275,8 +258,7 @@ public class ExternalManagerDB implements ManagerDB, ExternalManager {
@Override @Override
public ExternalLocation addExtFunction(Namespace extParentNamespace, String extLabel, public ExternalLocation addExtFunction(Namespace extParentNamespace, String extLabel,
Address extAddr, SourceType sourceType) Address extAddr, SourceType sourceType) throws InvalidInputException {
throws InvalidInputException, DuplicateNameException {
lock.acquire(); lock.acquire();
try { try {
return addExtLocation(extParentNamespace, extLabel, extAddr, true, sourceType, true); return addExtLocation(extParentNamespace, extLabel, extAddr, true, sourceType, true);
@ -288,9 +270,7 @@ public class ExternalManagerDB implements ManagerDB, ExternalManager {
@Override @Override
public ExternalLocation addExtFunction(Namespace extNamespace, String extLabel, Address extAddr, public ExternalLocation addExtFunction(Namespace extNamespace, String extLabel, Address extAddr,
SourceType sourceType, boolean reuseExisting) SourceType sourceType, boolean reuseExisting) throws InvalidInputException {
throws InvalidInputException, DuplicateNameException {
lock.acquire(); lock.acquire();
try { try {
return addExtLocation(extNamespace, extLabel, extAddr, true, sourceType, reuseExisting); return addExtLocation(extNamespace, extLabel, extAddr, true, sourceType, reuseExisting);
@ -314,11 +294,18 @@ public class ExternalManagerDB implements ManagerDB, ExternalManager {
private ExternalLocation addExtLocation(Namespace extNamespace, String extLabel, private ExternalLocation addExtLocation(Namespace extNamespace, String extLabel,
Address extAddr, boolean isFunction, SourceType sourceType, boolean reuseExisting) Address extAddr, boolean isFunction, SourceType sourceType, boolean reuseExisting)
throws InvalidInputException, DuplicateNameException { throws InvalidInputException {
if (extNamespace == null) { if (extNamespace == null) {
extNamespace = getLibraryScope(Library.UNKNOWN); extNamespace = getLibraryScope(Library.UNKNOWN);
if (extNamespace == null) { if (extNamespace == null) {
extNamespace = addExternalLibraryName(Library.UNKNOWN, SourceType.ANALYSIS); try {
extNamespace = addExternalLibraryName(Library.UNKNOWN, SourceType.ANALYSIS);
}
catch (DuplicateNameException e) {
// TODO: really need to reserve the unknown namespace name
throw new InvalidInputException(
"Failed to establish " + Library.UNKNOWN + " library");
}
} }
} }
else if (!extNamespace.isExternal()) { else if (!extNamespace.isExternal()) {
@ -637,9 +624,6 @@ public class ExternalManagerDB implements ManagerDB, ExternalManager {
return symbolMgr; return symbolMgr;
} }
/**
* @see ghidra.program.model.symbol.ExternalManager#removeExternalLibrary(java.lang.String)
*/
@Override @Override
public boolean removeExternalLibrary(String name) { public boolean removeExternalLibrary(String name) {
lock.acquire(); lock.acquire();
@ -694,8 +678,7 @@ public class ExternalManagerDB implements ManagerDB, ExternalManager {
private Library addExternalName(String name, String pathname, SourceType source) private Library addExternalName(String name, String pathname, SourceType source)
throws DuplicateNameException, InvalidInputException { throws DuplicateNameException, InvalidInputException {
SymbolDB s = symbolMgr.createSpecialSymbol(Address.NO_ADDRESS, name, SymbolDB s = symbolMgr.createLibrarySymbol(name, pathname, source);
scopeMgr.getGlobalNamespace(), SymbolType.LIBRARY, null, null, pathname, source);
return (Library) s.getObject(); return (Library) s.getObject();
} }
@ -704,17 +687,11 @@ public class ExternalManagerDB implements ManagerDB, ExternalManager {
return s == null ? null : (Namespace) s.getObject(); return s == null ? null : (Namespace) s.getObject();
} }
/**
* @see ghidra.program.model.symbol.ExternalManager#contains(java.lang.String)
*/
@Override @Override
public boolean contains(String libraryName) { public boolean contains(String libraryName) {
return symbolMgr.getLibrarySymbol(libraryName) != null; return symbolMgr.getLibrarySymbol(libraryName) != null;
} }
/**
* @see ghidra.program.model.symbol.ExternalManager#getExternalLibraryNames()
*/
@Override @Override
public String[] getExternalLibraryNames() { public String[] getExternalLibraryNames() {
ArrayList<String> list = new ArrayList<>(); ArrayList<String> list = new ArrayList<>();
@ -735,9 +712,6 @@ public class ExternalManagerDB implements ManagerDB, ExternalManager {
return s != null ? (Library) s.getObject() : null; return s != null ? (Library) s.getObject() : null;
} }
/**
* @see ghidra.program.model.symbol.ExternalManager#getExternalLibraryPath(java.lang.String)
*/
@Override @Override
public String getExternalLibraryPath(String externalName) { public String getExternalLibraryPath(String externalName) {
SymbolDB s = (SymbolDB) symbolMgr.getLibrarySymbol(externalName); SymbolDB s = (SymbolDB) symbolMgr.getLibrarySymbol(externalName);
@ -799,7 +773,7 @@ public class ExternalManagerDB implements ManagerDB, ExternalManager {
try { try {
SymbolDB symbol = (SymbolDB) extLoc.getSymbol(); SymbolDB symbol = (SymbolDB) extLoc.getSymbol();
if (!(symbol instanceof CodeSymbol)) { if (!(symbol instanceof CodeSymbol)) {
return null; throw new IllegalStateException("Expected external code symbol");
} }
//long dtId = symbol.getSymbolData1(); //long dtId = symbol.getSymbolData1();
String extData = symbol.getSymbolStringData(); String extData = symbol.getSymbolStringData();
@ -813,18 +787,13 @@ public class ExternalManagerDB implements ManagerDB, ExternalManager {
return functionMgr.createExternalFunction(extAddr, name, namespace, extData, source); return functionMgr.createExternalFunction(extAddr, name, namespace, extData, source);
} }
catch (Exception e) { catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Unexpected exception", e); throw new RuntimeException("Unexpected exception", e);
} }
finally { finally {
lock.release(); lock.release();
} }
} }
/**
* @return
*/
AddressMap getAddressMap() { AddressMap getAddressMap() {
return addrMap; return addrMap;
} }
@ -834,9 +803,6 @@ public class ExternalManagerDB implements ManagerDB, ExternalManager {
return new ExternalLocationDBIterator(symbolMgr.getExternalSymbols(), memoryAddress); return new ExternalLocationDBIterator(symbolMgr.getExternalSymbols(), memoryAddress);
} }
/**
* @see ghidra.program.model.symbol.ExternalManager#getExternalLocations(java.lang.String)
*/
@Override @Override
public ExternalLocationIterator getExternalLocations(String externalName) { public ExternalLocationIterator getExternalLocations(String externalName) {
Namespace scope = getLibraryScope(externalName); Namespace scope = getLibraryScope(externalName);
@ -864,9 +830,6 @@ public class ExternalManagerDB implements ManagerDB, ExternalManager {
this.symIter = symIter; this.symIter = symIter;
} }
/**
* @see java.util.Iterator#remove()
*/
@Override @Override
public void remove() { public void remove() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
@ -888,9 +851,6 @@ public class ExternalManagerDB implements ManagerDB, ExternalManager {
return null; return null;
} }
/**
* @see ghidra.program.model.symbol.ExternalLocationIterator#hasNext()
*/
@Override @Override
public boolean hasNext() { public boolean hasNext() {
if (symIter != null) { if (symIter != null) {
@ -902,9 +862,6 @@ public class ExternalManagerDB implements ManagerDB, ExternalManager {
return nextExtLoc != null; return nextExtLoc != null;
} }
/**
* @see ghidra.program.model.symbol.ExternalLocationIterator#next()
*/
@Override @Override
public ExternalLocation next() { public ExternalLocation next() {
if (hasNext()) { if (hasNext()) {

View file

@ -272,23 +272,23 @@ public class FunctionManagerDB implements FunctionManager {
/** /**
* Transform an existing external symbol into an external function. * Transform an existing external symbol into an external function.
* This method should only be invoked by an ExternalSymbol * This method should only be invoked by an ExternalSymbol
* @param extSpaceAddr the external space address to use when creating this external. * @param extSpaceAddr the external space address to use when creating this external. Any
* other symbol using this address must first be deleted. Results are unpredictable if this is
* not done.
* @param name the external function name * @param name the external function name
* @param nameSpace the external function namespace * @param nameSpace the external function namespace
* @param extData the external data string to store additional info (see {@link ExternalLocationDB}) * @param extData the external data string to store additional info (see {@link ExternalLocationDB})
* @param source the source of this external. * @param source the source of this external.
* @return external function * @return external function
* @throws InvalidInputException if the name is invalid * @throws InvalidInputException if the name is invalid
* @throws DuplicateNameException if the name is an invalid duplicate
*/ */
public Function createExternalFunction(Address extSpaceAddr, String name, Namespace nameSpace, public Function createExternalFunction(Address extSpaceAddr, String name, Namespace nameSpace,
String extData, SourceType source) String extData, SourceType source)
throws DuplicateNameException, InvalidInputException { throws InvalidInputException {
lock.acquire(); lock.acquire();
try { try {
Symbol symbol =
Symbol symbol = symbolMgr.createSpecialSymbol(extSpaceAddr, name, nameSpace, symbolMgr.createFunctionSymbol(extSpaceAddr, name, nameSpace, source, extData);
SymbolType.FUNCTION, null, null, extData, source);
long returnDataTypeId = program.getDataTypeManager().getResolvedID(DataType.DEFAULT); long returnDataTypeId = program.getDataTypeManager().getResolvedID(DataType.DEFAULT);

View file

@ -1115,6 +1115,17 @@ public class ReferenceDBManager implements ReferenceManager, ManagerDB, ErrorHan
} }
@Override
public void removeAllReferencesTo(Address toAddr) {
try {
removeAllTo(toAddr);
}
catch (IOException e) {
program.dbError(e);
}
}
void removeReference(Address fromAddr, Address toAddr, int opIndex) { void removeReference(Address fromAddr, Address toAddr, int opIndex) {
lock.acquire(); lock.acquire();
try { try {

View file

@ -85,18 +85,22 @@ public class CodeSymbol extends SymbolDB {
@Override @Override
public boolean delete() { public boolean delete() {
if (isExternal()) { boolean keepReferences = !isExternal();
return delete(false); return delete(keepReferences);
}
return super.delete();
} }
/**
* Delete code/label symbol
* @param keepReferences if false all references to this symbols address will be removed,
* otherwise associated references will simply be disassociated following symbol removal
* (see {@link SymbolManager#doRemoveSymbol(SymbolDB)}.
* @return true if symbol successfully removed
*/
public boolean delete(boolean keepReferences) { public boolean delete(boolean keepReferences) {
lock.acquire(); lock.acquire();
try { try {
if (!keepReferences) { if (!keepReferences) {
// remove external references symbolMgr.getReferenceManager().removeAllReferencesTo(getAddress());
removeAllReferencesTo();
} }
return super.delete(); return super.delete();
} }

View file

@ -20,7 +20,6 @@ import java.util.List;
import db.DBRecord; import db.DBRecord;
import ghidra.program.database.DBObjectCache; import ghidra.program.database.DBObjectCache;
import ghidra.program.database.ProgramDB;
import ghidra.program.database.external.ExternalManagerDB; import ghidra.program.database.external.ExternalManagerDB;
import ghidra.program.database.function.FunctionManagerDB; import ghidra.program.database.function.FunctionManagerDB;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
@ -91,9 +90,6 @@ public class FunctionSymbol extends SymbolDB {
} }
} }
/**
* @see ghidra.program.model.symbol.Symbol#delete()
*/
@Override @Override
public boolean delete() { public boolean delete() {
lock.acquire(); lock.acquire();
@ -120,7 +116,8 @@ public class FunctionSymbol extends SymbolDB {
boolean restored = createLabelForDeletedFunctionName(address, symName, extData, boolean restored = createLabelForDeletedFunctionName(address, symName, extData,
namespace, source, pinned); namespace, source, pinned);
if (!restored && isExternal()) { if (!restored && isExternal()) {
removeAllReferencesTo(); // remove all associated external references if label not restored
symbolMgr.getReferenceManager().removeAllReferencesTo(getAddress());
} }
} }
return true; return true;
@ -138,34 +135,19 @@ public class FunctionSymbol extends SymbolDB {
*/ */
private boolean createLabelForDeletedFunctionName(Address entryPoint, String symName, private boolean createLabelForDeletedFunctionName(Address entryPoint, String symName,
String stringData, Namespace namespace, SourceType source, boolean pinned) { String stringData, Namespace namespace, SourceType source, boolean pinned) {
if (isExternal()) {
SymbolDB parent = (SymbolDB) namespace.getSymbol(); Symbol parentSymbol = namespace.getSymbol();
if (parent.isDeleting()) { if ((parentSymbol instanceof SymbolDB) && ((SymbolDB) parentSymbol).isDeleting()) {
return false; // don't recreate external // do not replace function with label if parent namespace is getting removed
} return false;
} }
try { try {
SymbolDB newSym; Symbol newSym =
try { symbolMgr.createCodeSymbol(entryPoint, symName, namespace, source, stringData);
newSym = symbolMgr.createSpecialSymbol(entryPoint, symName, namespace,
SymbolType.LABEL, null, null, stringData, source);
if (pinned) {
newSym.setPinned(true);
}
}
catch (InvalidInputException e) {
ProgramDB program = symbolMgr.getProgram();
newSym = (SymbolDB) symbolMgr.createLabel(entryPoint, symName,
program.getGlobalNamespace(), source);
}
newSym.setSymbolStringData(stringData);
newSym.setPrimary(); newSym.setPrimary();
return true; return true;
} }
catch (DuplicateNameException e) {
// This should't happen.
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
}
catch (InvalidInputException e) { catch (InvalidInputException e) {
// This shouldn't happen. // This shouldn't happen.
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e); Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
@ -173,17 +155,11 @@ public class FunctionSymbol extends SymbolDB {
return false; return false;
} }
/**
* @see ghidra.program.model.symbol.Symbol#getObject()
*/
@Override @Override
public Object getObject() { public Object getObject() {
return functionMgr.getFunction(key); return functionMgr.getFunction(key);
} }
/**
* @see ghidra.program.model.symbol.Symbol#isPrimary()
*/
@Override @Override
public boolean isPrimary() { public boolean isPrimary() {
return true; return true;
@ -204,9 +180,6 @@ public class FunctionSymbol extends SymbolDB {
} }
} }
/**
* @see ghidra.program.model.symbol.Symbol#getProgramLocation()
*/
@Override @Override
public ProgramLocation getProgramLocation() { public ProgramLocation getProgramLocation() {
lock.acquire(); lock.acquire();
@ -224,9 +197,6 @@ public class FunctionSymbol extends SymbolDB {
} }
} }
/**
* @see ghidra.program.model.symbol.Symbol#isValidParent(ghidra.program.model.symbol.Namespace)
*/
@Override @Override
public boolean isValidParent(Namespace parent) { public boolean isValidParent(Namespace parent) {
return SymbolType.FUNCTION.isValidParent(symbolMgr.getProgram(), parent, address, return SymbolType.FUNCTION.isValidParent(symbolMgr.getProgram(), parent, address,

View file

@ -855,15 +855,6 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
} }
} }
protected void removeAllReferencesTo() {
ReferenceManager refMgr = symbolMgr.getReferenceManager();
ReferenceIterator it = refMgr.getReferencesTo(address);
while (it.hasNext()) {
Reference ref = it.next();
refMgr.delete(ref);
}
}
public long getDataTypeId() { public long getDataTypeId() {
lock.acquire(); lock.acquire();
try { try {

View file

@ -2498,8 +2498,8 @@ public class SymbolManager implements SymbolTable, ManagerDB {
try { try {
source = adjustSourceTypeIfNecessary(name, type, source, storage); source = adjustSourceTypeIfNecessary(name, type, source, storage);
Address varAddr = variableStorageMgr.getVariableStorageAddress(storage, true); Address varAddr = variableStorageMgr.getVariableStorageAddress(storage, true);
return (VariableSymbolDB) createSpecialSymbol(varAddr, name, namespace, type, return (VariableSymbolDB) doCreateSpecialSymbol(varAddr, name, namespace, type, null,
null, Integer.valueOf(firstUseOffsetOrOrdinal), null, source); Integer.valueOf(firstUseOffsetOrOrdinal), null, source, true);
} }
catch (IOException e) { catch (IOException e) {
dbError(e); dbError(e);
@ -2525,29 +2525,21 @@ public class SymbolManager implements SymbolTable, ManagerDB {
@Override @Override
public GhidraClass createClass(Namespace parent, String name, SourceType source) public GhidraClass createClass(Namespace parent, String name, SourceType source)
throws DuplicateNameException, InvalidInputException { throws DuplicateNameException, InvalidInputException {
SymbolDB s = SymbolDB s = createClassSymbol(name, parent, source, true);
createSpecialSymbol(Address.NO_ADDRESS, name, parent, SymbolType.CLASS, null, null,
null, source);
return new GhidraClassDB(s, namespaceMgr); return new GhidraClassDB(s, namespaceMgr);
} }
@Override @Override
public Library createExternalLibrary(String name, SourceType source) public Library createExternalLibrary(String name, SourceType source)
throws DuplicateNameException, InvalidInputException { throws DuplicateNameException, InvalidInputException {
SymbolDB s = createLibrarySymbol(name, null, source);
SymbolDB s =
createSpecialSymbol(Address.NO_ADDRESS, name, null, SymbolType.LIBRARY, null, null,
null, source);
return new LibraryDB(s, namespaceMgr); return new LibraryDB(s, namespaceMgr);
} }
@Override @Override
public Namespace createNameSpace(Namespace parent, String name, SourceType source) public Namespace createNameSpace(Namespace parent, String name, SourceType source)
throws DuplicateNameException, InvalidInputException { throws DuplicateNameException, InvalidInputException {
SymbolDB s = createNamespaceSymbol(name, parent, source, true);
SymbolDB s =
createSpecialSymbol(Address.NO_ADDRESS, name, parent, SymbolType.NAMESPACE, null,
null, null, source);
return new NamespaceDB(s, namespaceMgr); return new NamespaceDB(s, namespaceMgr);
} }
@ -2569,10 +2561,8 @@ public class SymbolManager implements SymbolTable, ManagerDB {
// no duplicate check, since this class name will be set to that of the existing namespace // no duplicate check, since this class name will be set to that of the existing namespace
String tempName = "_temp_" + System.nanoTime(); String tempName = "_temp_" + System.nanoTime();
SymbolDB classSymbol = SymbolDB classSymbol = createClassSymbol(tempName, namespace.getParentNamespace(),
doCreateSpecialSymbol(Address.NO_ADDRESS, tempName, namespace.getParentNamespace(), originalSource, false /*check for duplicate */);
SymbolType.CLASS, null, null, null, originalSource,
false /*check for duplicate */);
GhidraClassDB classNamespace = new GhidraClassDB(classSymbol, namespaceMgr); GhidraClassDB classNamespace = new GhidraClassDB(classSymbol, namespaceMgr);
// move everything from old namespace into new class namespace // move everything from old namespace into new class namespace
@ -2646,11 +2636,9 @@ public class SymbolManager implements SymbolTable, ManagerDB {
// Note: We know there are no namespaces with the name; do we still have to check for // Note: We know there are no namespaces with the name; do we still have to check for
// duplicates? Assuming yes, as another symbol type may exist with this name. // duplicates? Assuming yes, as another symbol type may exist with this name.
SymbolDB s = SymbolDB s = createNamespaceSymbol(name, parent, source, true /*check for duplicates*/);
doCreateSpecialSymbol(Address.NO_ADDRESS, name, parent, SymbolType.NAMESPACE, null,
null, null, source, true /*check for duplicates*/);
return new NamespaceDB(s, namespaceMgr);
return new NamespaceDB(s, namespaceMgr);
} }
finally { finally {
lock.release(); lock.release();
@ -2658,36 +2646,55 @@ public class SymbolManager implements SymbolTable, ManagerDB {
} }
/** /**
* Creates a symbol, specifying all information for the record. This method is not on the * Create a Library symbol with the specified name and optional pathname
* public interface and is only intended for program API internal use. The user of this * @param name library name
* method must carefully provided exactly the information needed depending on the type of symbol * @param pathname project file path (may be null)
* being created. * @param source symbol source
* @param addr the address for the symbol * @return library symbol
* @param name the name of the symbol * @throws DuplicateNameException if library name conflicts with another symbol
* @param parent the namespace for the symbol * @throws InvalidInputException
* @param symbolType the type of the symbol
* @param dataTypeId the id for an associated datatype or null
* @param variableOffset this is the ordinal for params and firstUseOffset for locals
* @param stringData value whose meaning depends on the symbol type.
* @param source the SourceType for the new symbol
* @return the newly created symbol
* @throws DuplicateNameException if the symbol type must be unique and another already has that name
* in the given namespace.
* @throws InvalidInputException if the name contains any illegal characters (i.e. space)
*/ */
public SymbolDB createSpecialSymbol(Address addr, String name, Namespace parent, public SymbolDB createLibrarySymbol(String name, String pathname, SourceType source)
SymbolType symbolType, Long dataTypeId, Integer variableOffset, String stringData,
SourceType source)
throws DuplicateNameException, InvalidInputException { throws DuplicateNameException, InvalidInputException {
return doCreateSpecialSymbol(Address.NO_ADDRESS, name, null, SymbolType.LIBRARY, null, null,
pathname, source, true);
}
return doCreateSpecialSymbol(addr, name, parent, symbolType, stringData, dataTypeId, /**
variableOffset, source, true); * 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
* @param checkForDuplicates true if check for duplicate name conflict should be performed
* @return class symbol
* @throws DuplicateNameException if class name conflicts with another symbol
* @throws InvalidInputException
*/
SymbolDB createClassSymbol(String name, Namespace parent, SourceType source,
boolean checkForDuplicates) throws DuplicateNameException, InvalidInputException {
return doCreateSpecialSymbol(Address.NO_ADDRESS, name, parent, SymbolType.CLASS, null, null,
null, source, true);
}
/**
* 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
* @param checkForDuplicates true if check for duplicate name conflict should be performed
* @return namespace symbol
* @throws DuplicateNameException if namespace name conflicts with another symbol
* @throws InvalidInputException
*/
SymbolDB createNamespaceSymbol(String name, Namespace parent, SourceType source,
boolean checkForDuplicates) throws DuplicateNameException, InvalidInputException {
return doCreateSpecialSymbol(Address.NO_ADDRESS, name, parent, SymbolType.NAMESPACE, null,
null, null, source, true);
} }
private SymbolDB doCreateSpecialSymbol(Address addr, String name, Namespace parent, private SymbolDB doCreateSpecialSymbol(Address addr, String name, Namespace parent,
SymbolType symbolType, String stringData, Long dataTypeId, Integer variableOffset, SymbolType symbolType, Long dataTypeId, Integer variableOffset, String stringData,
SourceType source, SourceType source, boolean checkForDuplicates)
boolean checkForDuplicates)
throws DuplicateNameException, InvalidInputException { throws DuplicateNameException, InvalidInputException {
lock.acquire(); lock.acquire();
@ -2722,8 +2729,9 @@ public class SymbolManager implements SymbolTable, ManagerDB {
} }
/** /**
* Internal method for creating label symbols. * Internal method for creating label symbols. If identical memory symbol already exists
* @param addr the address for the new symbol * it will be returned.
* @param addr the address for the new symbol (memory or external)
* @param name the name of the new symbol * @param name the name of the new symbol
* @param namespace the namespace for the new symbol * @param namespace the namespace for the new symbol
* @param source the SourceType of the new symbol * @param source the SourceType of the new symbol
@ -2739,24 +2747,38 @@ public class SymbolManager implements SymbolTable, ManagerDB {
source = validateSource(source, name, addr, SymbolType.LABEL); source = validateSource(source, name, addr, SymbolType.LABEL);
name = validateName(name, source); name = validateName(name, source);
Symbol symbol = getSymbol(name, addr, namespace); boolean makePrimary = true;
if (symbol != null) { if (addr.isMemoryAddress()) {
return symbol;
}
// If there is a default named function, rename it to the new symbol name Symbol symbol = getSymbol(name, addr, namespace);
Symbol functionSymbol = tryUpdatingDefaultFunction(addr, name, namespace, source); if (symbol != null) {
if (functionSymbol != null) { return symbol;
return functionSymbol; }
}
// if there is a dynamic symbol, delete it and make the new symbol primary. // If there is a default named function, rename it to the new symbol name
Symbol primary = getPrimarySymbol(addr); Symbol functionSymbol = tryUpdatingDefaultFunction(addr, name, namespace, source);
if (primary != null && primary.isDynamic()) { if (functionSymbol != null) {
deleteDynamicSymbol(primary); return functionSymbol;
primary = null; }
// if there is a dynamic symbol, delete it and make the new symbol primary.
Symbol primary = getPrimarySymbol(addr);
if (primary != null && primary.isDynamic()) {
deleteDynamicSymbol(primary);
primary = null;
}
makePrimary = (primary == null);
}
else if (addr.isExternalAddress()) {
// only one symbol per external address is allowed
Symbol primary = getPrimarySymbol(addr);
if (primary != null) {
throw new IllegalArgumentException("external address already used");
}
}
else {
throw new IllegalArgumentException("bad label address");
} }
boolean makePrimary = primary == null;
return doCreateSymbol(name, addr, namespace, SymbolType.LABEL, stringData, null, null, return doCreateSymbol(name, addr, namespace, SymbolType.LABEL, stringData, null, null,
source, makePrimary); source, makePrimary);
@ -2784,6 +2806,27 @@ public class SymbolManager implements SymbolTable, ManagerDB {
source = validateSource(source, name, addr, SymbolType.FUNCTION); source = validateSource(source, name, addr, SymbolType.FUNCTION);
name = validateName(name, source); name = validateName(name, source);
if (addr.isMemoryAddress()) {
return doCreateMemoryFunctionSymbol(addr, name, namespace, source, stringData);
}
else if (addr.isExternalAddress()) {
// only one symbol per external address is allowed
Symbol primary = getPrimarySymbol(addr);
if (primary != null) {
throw new IllegalArgumentException("external address already used");
}
}
else {
throw new IllegalArgumentException("bad function address");
}
return doCreateSymbol(name, addr, namespace, SymbolType.FUNCTION, stringData, null, null,
source, true);
}
private Symbol doCreateMemoryFunctionSymbol(Address addr, String name, Namespace namespace,
SourceType source, String stringData) throws InvalidInputException {
// if there is already a FUNCTION symbol with that name and namespace here, just return it. // if there is already a FUNCTION symbol with that name and namespace here, just return it.
Symbol matching = getSymbol(name, addr, namespace); Symbol matching = getSymbol(name, addr, namespace);
if (matching != null && matching.getSymbolType() == SymbolType.FUNCTION) { if (matching != null && matching.getSymbolType() == SymbolType.FUNCTION) {

View file

@ -30,29 +30,31 @@ import ghidra.util.exception.InvalidInputException;
public interface ExternalManager { public interface ExternalManager {
/** /**
* Returns a list of all external names for which locations have been defined. * Returns an array of all external names for which locations have been defined.
* @return array of external names
*/ */
public String[] getExternalLibraryNames(); public String[] getExternalLibraryNames();
/** /**
* Get the Library which corresponds to the specified name * Get the Library which corresponds to the specified name
* @param name name of library * @param libraryName name of library
* @return library or null if not found * @return library or null if not found
*/ */
public Library getExternalLibrary(String name); public Library getExternalLibrary(String libraryName);
/** /**
* Removes external name if no associated ExternalLocation's exist * Removes external name if no associated ExternalLocation's exist
* @param name external name * @param libraryName external library name
* @return true if removed, false if unable to due to associated locations/references * @return true if removed, false if unable to due to associated locations/references
*/ */
public boolean removeExternalLibrary(String name); public boolean removeExternalLibrary(String libraryName);
/** /**
* Returns the file pathname associated with an external name. * Returns the file pathname associated with an external name.
* Null is returned if either the external name does not exist or * Null is returned if either the external name does not exist or
* a pathname has not been set. * a pathname has not been set.
* @param libraryName external name * @param libraryName external name
* @return project file pathname or null
*/ */
public String getExternalLibraryPath(String libraryName); public String getExternalLibraryPath(String libraryName);
@ -61,6 +63,7 @@ public interface ExternalManager {
* @param libraryName the name of the library to associate with a file. * @param libraryName the name of the library to associate with a file.
* @param pathname the path to the program to be associated with the library name. * @param pathname the path to the program to be associated with the library name.
* @param userDefined true if the external path is being specified by the user * @param userDefined true if the external path is being specified by the user
* @throws InvalidInputException
*/ */
public void setExternalPath(String libraryName, String pathname, boolean userDefined) public void setExternalPath(String libraryName, String pathname, boolean userDefined)
throws InvalidInputException; throws InvalidInputException;
@ -70,6 +73,8 @@ public interface ExternalManager {
* @param oldName the old name of the external library name. * @param oldName the old name of the external library name.
* @param newName the new name of the external library name. * @param newName the new name of the external library name.
* @param source the source of this external library * @param source the source of this external library
* @throws DuplicateNameException if another namespace has the same name
* @throws InvalidInputException
*/ */
public void updateExternalLibraryName(String oldName, String newName, SourceType source) public void updateExternalLibraryName(String oldName, String newName, SourceType source)
throws DuplicateNameException, InvalidInputException; throws DuplicateNameException, InvalidInputException;
@ -85,7 +90,7 @@ public interface ExternalManager {
/** /**
* Get an iterator over all external locations which have been associated to * Get an iterator over all external locations which have been associated to
* the specified memory address * the specified memory address
* @param memoryAddress * @param memoryAddress memory address
* @return external location iterator * @return external location iterator
*/ */
public ExternalLocationIterator getExternalLocations(Address memoryAddress); public ExternalLocationIterator getExternalLocations(Address memoryAddress);
@ -94,7 +99,9 @@ public interface ExternalManager {
* Get an external location. * Get an external location.
* @param libraryName the name of the library for which to get an external location * @param libraryName the name of the library for which to get an external location
* @param label the name of the external location. * @param label the name of the external location.
* @deprecated Use {@link #getExternalLocations(String, String)} instead * @return first matching external location
* @deprecated Use {@link #getExternalLocations(String, String)} or
* {@link #getUniqueExternalLocation(String, String)} since duplicate names may exist
*/ */
@Deprecated @Deprecated
public ExternalLocation getExternalLocation(String libraryName, String label); public ExternalLocation getExternalLocation(String libraryName, String label);
@ -103,7 +110,9 @@ public interface ExternalManager {
* Get an external location. * Get an external location.
* @param namespace the namespace containing the external label. * @param namespace the namespace containing the external label.
* @param label the name of the external location. * @param label the name of the external location.
* @deprecated Use {@link #getExternalLocations(Namespace, String)} * @return first matching external location
* @deprecated Use {@link #getExternalLocations(Namespace, String)} or
* {@link #getUniqueExternalLocation(Namespace, String)} since duplicate names may exist
*/ */
@Deprecated @Deprecated
public ExternalLocation getExternalLocation(Namespace namespace, String label); public ExternalLocation getExternalLocation(Namespace namespace, String label);
@ -156,25 +165,27 @@ public interface ExternalManager {
/** /**
* Adds a new external library name * Adds a new external library name
* @param name the new library name to add. * @param libraryName the new external library name to add.
* @param source the source of this external library * @param source the source of this external library
* @return library * @return library
* @throws InvalidInputException
* @throws DuplicateNameException if another non-Library namespace has the same name
*/ */
public Library addExternalLibraryName(String name, SourceType source) public Library addExternalLibraryName(String libraryName, SourceType source)
throws DuplicateNameException, InvalidInputException; throws InvalidInputException, DuplicateNameException;
/** /**
* Get or create an external location associated with an library/file named extName * Get or create an external location associated with an library/file named extName
* and the label within that file specified by extLabel * and the label within that file specified by extLabel
* @param extName the external name * @param libraryName the external library name
* @param extLabel the external label * @param extLabel the external label
* @param extAddr the external address * @param extAddr the external address
* @param sourceType the source type of this external library's symbol * @param sourceType the source type of this external library's symbol
* @return external location * @return external location
* @throws InvalidInputException * @throws InvalidInputException
* @throws DuplicateNameException * @throws DuplicateNameException if another non-Library namespace has the same name
*/ */
public ExternalLocation addExtLocation(String extName, String extLabel, Address extAddr, public ExternalLocation addExtLocation(String libraryName, String extLabel, Address extAddr,
SourceType sourceType) throws InvalidInputException, DuplicateNameException; SourceType sourceType) throws InvalidInputException, DuplicateNameException;
/** /**
@ -185,10 +196,9 @@ public interface ExternalManager {
* @param sourceType the source type of this external library's symbol * @param sourceType the source type of this external library's symbol
* @return external location * @return external location
* @throws InvalidInputException * @throws InvalidInputException
* @throws DuplicateNameException
*/ */
public ExternalLocation addExtLocation(Namespace extNamespace, String extLabel, Address extAddr, public ExternalLocation addExtLocation(Namespace extNamespace, String extLabel, Address extAddr,
SourceType sourceType) throws InvalidInputException, DuplicateNameException; SourceType sourceType) throws InvalidInputException;
/** /**
* Get or create an external location in the indicated parent namespace with the specified name. * Get or create an external location in the indicated parent namespace with the specified name.
@ -200,25 +210,24 @@ public interface ExternalManager {
* location instead of creating a new one. * location instead of creating a new one.
* @return external location * @return external location
* @throws InvalidInputException * @throws InvalidInputException
* @throws DuplicateNameException
*/ */
public ExternalLocation addExtLocation(Namespace extNamespace, String extLabel, Address extAddr, public ExternalLocation addExtLocation(Namespace extNamespace, String extLabel, Address extAddr,
SourceType sourceType, boolean reuseExisting) SourceType sourceType, boolean reuseExisting)
throws InvalidInputException, DuplicateNameException; throws InvalidInputException;
/** /**
* Get or create an external location associated with an library/file named extName * Get or create an external location associated with an library/file named extName
* and the label within that file specified by extLabel * and the label within that file specified by extLabel
* @param extName the external name * @param libraryName the external library name
* @param extLabel the external label * @param extLabel the external label
* @param extAddr the external address * @param extAddr the external address
* @param sourceType the source type of this external library's symbol * @param sourceType the source type of this external library's symbol
* @return external location * @return external location
* @throws InvalidInputException * @throws InvalidInputException
* @throws DuplicateNameException * @throws DuplicateNameException if another non-Library namespace has the same name
*/ */
public ExternalLocation addExtFunction(String extName, String extLabel, Address extAddr, public ExternalLocation addExtFunction(String libraryName, String extLabel, Address extAddr,
SourceType sourceType) throws DuplicateNameException, InvalidInputException; SourceType sourceType) throws InvalidInputException, DuplicateNameException;
/** /**
* Get or create an external function location associated with an library/file named extName * Get or create an external function location associated with an library/file named extName
@ -229,10 +238,9 @@ public interface ExternalManager {
* @param sourceType the source type of this external library's symbol * @param sourceType the source type of this external library's symbol
* @return external location * @return external location
* @throws InvalidInputException * @throws InvalidInputException
* @throws DuplicateNameException if another non-Library namespace has the same name
*/ */
public ExternalLocation addExtFunction(Namespace extNamespace, String extLabel, Address extAddr, public ExternalLocation addExtFunction(Namespace extNamespace, String extLabel, Address extAddr,
SourceType sourceType) throws InvalidInputException, DuplicateNameException; SourceType sourceType) throws InvalidInputException;
/** /**
* Get or create an external function location associated with an library/file named extName * Get or create an external function location associated with an library/file named extName
@ -245,10 +253,9 @@ public interface ExternalManager {
* address is not null and not used in an existing location. * address is not null and not used in an existing location.
* @return external location * @return external location
* @throws InvalidInputException * @throws InvalidInputException
* @throws DuplicateNameException if another non-Library namespace has the same name
*/ */
public ExternalLocation addExtFunction(Namespace extNamespace, String extLabel, Address extAddr, public ExternalLocation addExtFunction(Namespace extNamespace, String extLabel, Address extAddr,
SourceType sourceType, boolean reuseExisting) SourceType sourceType, boolean reuseExisting)
throws InvalidInputException, DuplicateNameException; throws InvalidInputException;
} }

View file

@ -173,6 +173,13 @@ public interface ReferenceManager {
*/ */
public void removeAllReferencesFrom(Address fromAddr); public void removeAllReferencesFrom(Address fromAddr);
/**
* Remove all stack, external, and memory references for the given
* to address.
* @param toAddr the address for which all references to should be removed.
*/
public void removeAllReferencesTo(Address toAddr);
/** /**
* Returns all references to the given variable. Only data references to storage * Returns all references to the given variable. Only data references to storage
* are considered. * are considered.

View file

@ -183,7 +183,8 @@ public interface Symbol {
throws DuplicateNameException, InvalidInputException, CircularDependencyException; throws DuplicateNameException, InvalidInputException, CircularDependencyException;
/** /**
* Delete the symbol and its associated resources. * Delete the symbol and its associated resources. Any references symbol associations
* will be discarded.
* @return true if successful * @return true if successful
*/ */
public boolean delete(); public boolean delete();

View file

@ -89,6 +89,11 @@ public class ReferenceManagerTestDouble implements ReferenceManager {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public void removeAllReferencesTo(Address toAddr) {
throw new UnsupportedOperationException();
}
@Override @Override
public Reference[] getReferencesTo(Variable var) { public Reference[] getReferencesTo(Variable var) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();