GP-6150 Improved AddressMapDB address use restriction to prevent invalid mixed use between programs.

This commit is contained in:
ghidra1
2025-12-02 15:09:48 -05:00
parent 863be7c97c
commit bed292716f
18 changed files with 267 additions and 152 deletions

View File

@@ -2159,6 +2159,10 @@ public class ProgramMerge {
monitor.setMessage("Replacing Function " + (count + 1) + " of " + totalAddresses +
"." + " Address = " + address.toString(true));
}
// Only use origin memory address
address = DiffUtility.getCompatibleMemoryAddress(address, originProgram);
if (isThunkFunction(address)) {
// Skip the thunk, but save it for processing during a second pass.
thunkSet.addRange(address, address);
@@ -2171,13 +2175,14 @@ public class ProgramMerge {
replaceThunks(thunkSet, monitor);
}
private void replaceThunks(AddressSet thunkSet, TaskMonitor monitor) throws CancelledException {
private void replaceThunks(AddressSet originThunkSet, TaskMonitor monitor)
throws CancelledException {
long granularity;
// Now that all the non-thunk functions have been processed, process the saved thunks.
long totalThunks = thunkSet.getNumAddresses();
long totalThunks = originThunkSet.getNumAddresses();
granularity = (totalThunks / PROGRESS_COUNTER_GRANULARITY) + 1;
monitor.initialize(totalThunks);
AddressIterator thunkIter = thunkSet.getAddresses(true);
AddressIterator thunkIter = originThunkSet.getAddresses(true);
for (int count = 0; thunkIter.hasNext(); count++) {
monitor.checkCancelled();
Address address = thunkIter.next();

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -259,7 +259,7 @@ class SymbolMerge {
* parent namespace path. The primary symbol will be get set to the symbol that was primary in
* the source program.
*
* @param address the program address where the symbols are being replaced.
* @param fromAddress the program address where the symbols are being replaced.
* This address should be derived from the "to" program.
* @param conflictSymbolIDMap maps the symbol IDs in the "from" program to the symbol IDs
* in the "to" program for any symbols (and their associated objects) that were created
@@ -267,33 +267,32 @@ class SymbolMerge {
* (key = "from" program's symbol ID; value = "to" program's symbol ID)
* @param monitor the task monitor for updating user progress and allowing cancelling.
*
* @return a map of symbols that were created as conflicts during the replace. These map symbols
* in the source program to a symbol with another name due to a duplicate symbol problem.
* (key = "from" program's symbol; value = "to" program's symbol)
*
* @throws CancelledException if the task monitor is cancelled.
* @throws DuplicateNameException if the name space can't be resolved due
* to a name conflict that can't be dealt with.
* @throws InvalidInputException
* the indicated address.
*/
void replaceSymbols(Address address, LongLongHashtable conflictSymbolIDMap, TaskMonitor monitor)
void replaceSymbols(Address fromAddress, LongLongHashtable conflictSymbolIDMap,
TaskMonitor monitor)
throws CancelledException, DuplicateNameException, InvalidInputException {
removeUniqueToSymbols(address, monitor);
replaceFunctionSymbol(address, address, conflictSymbolIDMap, monitor);
addFromSymbols(address, true, conflictSymbolIDMap, monitor);
Address toAddress = originToResultTranslator.getAddress(fromAddress);
replacePrimary(address, conflictSymbolIDMap);
removeUniqueToSymbols(toAddress, monitor);
replaceFunctionSymbol(fromAddress, toAddress, conflictSymbolIDMap, monitor);
addFromSymbols(fromAddress, true, conflictSymbolIDMap, monitor);
replacePrimary(fromAddress, conflictSymbolIDMap);
// Remove this address as an entry point if its not one in program2.
if (toSymbolTable.isExternalEntryPoint(address) &&
!fromSymbolTable.isExternalEntryPoint(address)) {
toSymbolTable.removeExternalEntryPoint(address);
if (toSymbolTable.isExternalEntryPoint(toAddress) &&
!fromSymbolTable.isExternalEntryPoint(fromAddress)) {
toSymbolTable.removeExternalEntryPoint(toAddress);
}
else if (fromSymbolTable.isExternalEntryPoint(address) &&
!toSymbolTable.isExternalEntryPoint(address)) {
toSymbolTable.addExternalEntryPoint(address);
else if (fromSymbolTable.isExternalEntryPoint(toAddress) &&
!toSymbolTable.isExternalEntryPoint(toAddress)) {
toSymbolTable.addExternalEntryPoint(toAddress);
}
}
@@ -304,15 +303,14 @@ class SymbolMerge {
* not be removed at the address even if it is different. Otherwise, the
* function would inadvertently get removed.
*
* @param address the program address where the symbols are being replaced.
* @param toAddress the program address where the symbols are being replaced.
* This address should be derived from the "to" program.
* @param monitor the task monitor for updating user progress and allowing cancelling.
*
* @throws CancelledException if the task monitor is cancelled.
*/
private void removeUniqueToSymbols(Address fromAddress, TaskMonitor monitor)
private void removeUniqueToSymbols(Address toAddress, TaskMonitor monitor)
throws CancelledException {
Address toAddress = originToResultTranslator.getAddress(fromAddress);
Symbol[] toSymbols = toSymbolTable.getUserSymbols(toAddress);
for (Symbol toSymbol : toSymbols) {
Symbol fromSymbol = SimpleDiffUtility.getSymbol(toSymbol, fromProgram);
@@ -349,10 +347,6 @@ class SymbolMerge {
* (key = "from" program's symbol ID; value = "to" program's symbol ID)
* @param monitor the task monitor for updating user progress and allowing cancelling.
*
* @return an array of <code>SymbolTranslators</code> for symbols that ended up with different
* pathnames in the destination program than they had in the source program. These map symbols
* in the source program to a symbol with another name due to a duplicate symbol problem.
*
* @throws CancelledException if the task monitor is canceled.
* @throws DuplicateNameException if a symbol couldn't be added due
* to a name conflict that can't be dealt with.
@@ -627,6 +621,7 @@ class SymbolMerge {
* @param setting indicates whether to replace or merge the symbols.
* @param replacePrimary true indicates that the primary symbol in the "to" program should be
* set to the same symbol as was primary in the "from" program.
* @param replaceFunction replace function if true
* @param conflictSymbolIDMap maps the symbol IDs in the "from" program to the symbol IDs
* in the "to" program for any symbols (and their associated objects) that were created
* with conflict names.
@@ -714,7 +709,6 @@ class SymbolMerge {
* with conflict names.
* (key = "from" program's symbol ID; value = "to" program's symbol ID)
* @param monitor the task monitor for notifying the user of this merge's progress.
* @return the symbol now at the address in the toSymbolTable.
*
* @throws CancelledException if user cancels via the monitor.
* @throws InvalidInputException if a symbol name from the second program isn't valid
@@ -743,16 +737,16 @@ class SymbolMerge {
/**
*
* @param address
* @param fromAddress
* This address should be derived from the "to" program.
* @param conflictSymbolIDMap maps the symbol IDs in the "from" program to the symbol IDs
* in the "to" program for any symbols (and their associated objects) that were created
* with conflict names.
* (key = "from" program's symbol ID; value = "to" program's symbol ID)
*/
private void replacePrimary(Address address, LongLongHashtable conflictSymbolIDMap) {
private void replacePrimary(Address fromAddress, LongLongHashtable conflictSymbolIDMap) {
// Set the primary symbol.
Symbol fromPrimary = fromSymbolTable.getPrimarySymbol(address);
Symbol fromPrimary = fromSymbolTable.getPrimarySymbol(fromAddress);
if (fromPrimary != null) {
Symbol newToPrimary = null;
try {

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -54,7 +54,7 @@ public class AddressRangeMapDBTest extends AbstractGhidraHeadedIntegrationTest
Language language = service.getLanguage(new LanguageID("sparc:BE:64:default"));
program = new ProgramDB("test", language, language.getDefaultCompilerSpec(), this);
MemoryMapDB memory = (MemoryMapDB) program.getMemory();
MemoryMapDB memory = program.getMemory();
addrMap = (AddressMap) getInstanceField("addrMap", memory);
space = program.getAddressFactory().getDefaultAddressSpace();
}
@@ -245,6 +245,72 @@ public class AddressRangeMapDBTest extends AbstractGhidraHeadedIntegrationTest
assertTrue(!iter.hasNext());
}
@Test
public void testAddressRangeIteratorWithImageBase() throws Exception {
AddressRangeMapDB map = new AddressRangeMapDB(program.getDBHandle(), addrMap,
new Lock("Test"), "TEST", this, LongField.INSTANCE, true);
int id = program.startTransaction("TEST");
try {
program.setImageBase(addr(0x0000001000L), true);
assertNull(map.getValue(addr(0x01000000000L)));
map.paintRange(addr(0x0000000000L), addr(0x0200001000L), ONE);
map.paintRange(addr(0x0100000000L), addr(0x0100001000L), TWO);
map.paintRange(addr(0x0080000000L), addr(0x0100000fffL), THREE);
map.clearRange(addr(0x0100000000L), addr(0x0100000010L));
map.clearRange(addr(0x01fffffff0L), addr(0x0200000010L));
// Force painted key range to cross wrap point
program.setImageBase(addr(0), true);
}
finally {
program.endTransaction(id, true);
}
// All address
AddressRangeIterator iter = map.getAddressRanges();
assertTrue(iter.hasNext());
assertEquals(new AddressRangeImpl(addr(0x0000000000L), addr(0x007fffefffL)), iter.next());
assertTrue(iter.hasNext());
assertEquals(new AddressRangeImpl(addr(0x007ffff000L), addr(0x00ffffefffL)), iter.next());
assertTrue(iter.hasNext());
assertEquals(new AddressRangeImpl(addr(0x0fffff011L), addr(0x0ffffffffL)), iter.next());
assertTrue(iter.hasNext());
assertEquals(new AddressRangeImpl(addr(0x0100000000L), addr(0x0100000000L)), iter.next());
assertTrue(iter.hasNext());
assertEquals(new AddressRangeImpl(addr(0x0100000001L), addr(0x01ffffefefL)), iter.next());
assertTrue(iter.hasNext());
assertEquals(new AddressRangeImpl(addr(0x01fffff011L), addr(0x0200000000L)), iter.next());
assertTrue(iter.hasNext());
assertEquals(new AddressRangeImpl(addr(0xfffffffffffff000L), addr(0xffffffffffffffffL)),
iter.next());
assertTrue(!iter.hasNext());
// Limited range of addresses starting at 0x0100000100
iter = map.getAddressRanges(addr(0x0100000100L));
assertTrue(iter.hasNext());
assertEquals(new AddressRangeImpl(addr(0x0100000100L), addr(0x01ffffefefL)), iter.next());
assertTrue(iter.hasNext());
assertEquals(new AddressRangeImpl(addr(0x01fffff011L), addr(0x0200000000L)), iter.next());
assertTrue(iter.hasNext());
assertEquals(new AddressRangeImpl(addr(0xfffffffffffff000L), addr(0xffffffffffffffffL)),
iter.next());
assertTrue(!iter.hasNext());
// Limited range of addresses from 0x0100000100 to 0x0200000100L
iter = map.getAddressRanges(addr(0x0100000100L), addr(0x0200000100L));
assertTrue(iter.hasNext());
assertEquals(new AddressRangeImpl(addr(0x0100000100L), addr(0x01ffffefefL)), iter.next());
assertTrue(iter.hasNext());
assertEquals(new AddressRangeImpl(addr(0x01fffff011L), addr(0x0200000000L)), iter.next());
assertTrue(!iter.hasNext());
}
@Test
public void testMove() {

View File

@@ -4402,8 +4402,8 @@ public class ProgramMerge2Test extends AbstractGhidraHeadedIntegrationTest {
AddressSet setToDiff = new AddressSet();
setToDiff.addRange(addr(p1, "SomeOverlay::01001630"),
addr(p1, "SomeOverlay::0100182f"));
setToDiff.addRange(addr(p2, "SomeOverlay::01001830"),
addr(p2, "SomeOverlay::0100192f"));
setToDiff.addRange(addr(p1, "SomeOverlay::01001830"),
addr(p1, "SomeOverlay::0100192f"));
setToDiff.addRange(addr(p1, "OtherOverlay::01001630"),
addr(p1, "OtherOverlay::0100192f"));
programMerge = new ProgramMergeManager(p1, p2, setToDiff);
@@ -4511,8 +4511,8 @@ public class ProgramMerge2Test extends AbstractGhidraHeadedIntegrationTest {
AddressSet setToDiff = new AddressSet();
setToDiff.addRange(addr(p1, "SomeOverlay::01001630"),
addr(p1, "SomeOverlay::0100182f"));
setToDiff.addRange(addr(p2, "SomeOverlay::01001830"),
addr(p2, "SomeOverlay::0100192f"));
setToDiff.addRange(addr(p1, "SomeOverlay::01001830"),
addr(p1, "SomeOverlay::0100192f"));
setToDiff.addRange(addr(p1, "OtherOverlay::01001630"),
addr(p1, "OtherOverlay::0100192f"));
programMerge = new ProgramMergeManager(p1, p2, setToDiff);
@@ -4617,8 +4617,8 @@ public class ProgramMerge2Test extends AbstractGhidraHeadedIntegrationTest {
AddressSet setToDiff = new AddressSet();
setToDiff.addRange(addr(p1, "SomeOverlay::01001630"),
addr(p1, "SomeOverlay::0100182f"));
setToDiff.addRange(addr(p2, "SomeOverlay::01001830"),
addr(p2, "SomeOverlay::0100192f"));
setToDiff.addRange(addr(p1, "SomeOverlay::01001830"),
addr(p1, "SomeOverlay::0100192f"));
setToDiff.addRange(addr(p1, "OtherOverlay::01001630"),
addr(p1, "OtherOverlay::0100192f"));
programMerge = new ProgramMergeManager(p1, p2, setToDiff);
@@ -4721,8 +4721,8 @@ public class ProgramMerge2Test extends AbstractGhidraHeadedIntegrationTest {
AddressSet setToDiff = new AddressSet();
setToDiff.addRange(addr(p1, "SomeOverlay::01001630"),
addr(p1, "SomeOverlay::0100182f"));
setToDiff.addRange(addr(p2, "SomeOverlay::01001830"),
addr(p2, "SomeOverlay::0100192f"));
setToDiff.addRange(addr(p1, "SomeOverlay::01001830"),
addr(p1, "SomeOverlay::0100192f"));
setToDiff.addRange(addr(p1, "OtherOverlay::01001630"),
addr(p1, "OtherOverlay::0100192f"));
programMerge = new ProgramMergeManager(p1, p2, setToDiff);

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -308,7 +308,7 @@ public abstract class AbstractVTMarkupItemTest extends AbstractGhidraHeadedInteg
// verify we cannot unapply before we have applied
//
List<VTMarkupItem> markupItems = new ArrayList<>();
Address destinationAddress = addr();
Address destinationAddress = addr(session.getDestinationProgram());
markupItem.setDefaultDestinationAddress(destinationAddress, TEST_ADDRESS_SOURCE);
markupItems.add(markupItem);

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -22,12 +22,19 @@ import java.util.List;
import ghidra.program.database.map.AddressMap;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program;
public class AddressMapTestDummy implements AddressMap {
private Program program;
public AddressMapTestDummy(Program p) {
program = p;
}
@Override
public Address decodeAddress(long value) {
return addr(value);
return addr(value, program);
}
@Override

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -30,36 +30,27 @@ public class DummyTestProgramCorrelator extends VTAbstractProgramCorrelator {
private String name = "DummyTestProgramCorrelator";
private int matchCount = 1;
public DummyTestProgramCorrelator() {
this(1);
}
public DummyTestProgramCorrelator(Program sourceProgram, AddressSetView sourceAddressSet,
Program destinationProgram, AddressSetView destinationAddressSet, ToolOptions options) {
super(sourceProgram, sourceAddressSet, destinationProgram, destinationAddressSet, options);
}
public DummyTestProgramCorrelator(Program sourceProgram, Program destinationProgram) {
super(sourceProgram, createAddressSet(), destinationProgram, createAddressSet(),
createOptions());
super(sourceProgram, createAddressSet(sourceProgram), destinationProgram,
createAddressSet(destinationProgram), createOptions());
}
public DummyTestProgramCorrelator(int matchCount) {
super(null, createAddressSet(), null, createAddressSet(), createOptions());
this.matchCount = matchCount;
}
private static AddressSet createAddressSet() {
private static AddressSet createAddressSet(Program p) {
AddressSet as = new AddressSet();
as.add(getRandomAddressRange());
as.add(getRandomAddressRange());
as.add(getRandomAddressRange());
as.add(getRandomAddressRange(p));
as.add(getRandomAddressRange(p));
as.add(getRandomAddressRange(p));
return as;
}
private static AddressRange getRandomAddressRange() {
Address addr1 = addr();
Address addr2 = addr();
private static AddressRange getRandomAddressRange(Program p) {
Address addr1 = addr(p);
Address addr2 = addr(p);
return new AddressRangeImpl(min(addr1, addr2), max(addr1, addr2));
}

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -789,16 +789,18 @@ public class VTAssociationDBTest extends VTBaseTestCase {
private VTMatchInfo createRandomMatchWithUnrelatedAssociation(VTMatchInfo info) {
Address sourceAddress = info.getSourceAddress();
Address destinationAddress = info.getDestinationAddress();
return createRandomMatch(otherAddr(sourceAddress), otherAddr(destinationAddress), db);
return createRandomMatch(otherAddr(sourceAddress, sourceProgram),
otherAddr(destinationAddress, destinationProgram), db);
}
private VTMatchInfo createRandomMatchWithConflictingDestinationAssociation(VTMatchInfo info) {
Address destinationAddress = info.getDestinationAddress();
return createRandomMatch(info.getSourceAddress(), otherAddr(destinationAddress), db);
return createRandomMatch(info.getSourceAddress(),
otherAddr(destinationAddress, destinationProgram), db);
}
private VTMatchInfo createRandomMatchWithConflictingSourceAssociation(VTMatchInfo mainMatch) {
return createRandomMatch(otherAddr(mainMatch.getSourceAddress()),
return createRandomMatch(otherAddr(mainMatch.getSourceAddress(), sourceProgram),
mainMatch.getDestinationAddress(), db);
}

View File

@@ -50,15 +50,14 @@ public abstract class VTBaseTestCase extends AbstractGenericTest {
}
};
private Program sourceProgram = new VTStubProgram(sourceDomainFile);
private Program destinationProgram = new VTStubProgram(destinationDomainFile);
protected final Program sourceProgram = new VTStubProgram(sourceDomainFile);
protected final Program destinationProgram = new VTStubProgram(destinationDomainFile);
private FunctionManager functionManager = new VTSTubFunctionManager();
private Listing listing = new VTStubListing();
private SymbolTable symbolTable = new VTStubSymbolTable();
private Memory memory = new VTStubMemory();
private AddressMap addressMap = new AddressMapTestDummy();
private static String[] randomTags = { "TAG1", "TAG2", "TAG3" };
private static GenericAddressSpace space =
new GenericAddressSpace("Test", 32, AddressSpace.TYPE_RAM, 3);
@@ -192,7 +191,12 @@ public abstract class VTBaseTestCase extends AbstractGenericTest {
private class VTStubProgram extends StubProgram {
private DomainFile domainFile;
private final DomainFile domainFile;
private final AddressSpace defaultSpace =
new GenericAddressSpace("Test", 32, AddressSpace.TYPE_RAM, 3);
private final AddressFactory addrFactory =
new DefaultAddressFactory(new AddressSpace[] { defaultSpace }, defaultSpace);
private final AddressMap addressMap = new AddressMapTestDummy(this);
VTStubProgram(DomainFile domainFile) {
this.domainFile = domainFile;
@@ -240,7 +244,7 @@ public abstract class VTBaseTestCase extends AbstractGenericTest {
@Override
public AddressFactory getAddressFactory() {
return null;
return addrFactory;
}
@Override

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -95,7 +95,7 @@ public class VTDomainObjectEventsTest extends VTBaseTestCase {
public void testEventsForAddingFirstMatchForAssociation() {
VTMatchSet matchSet = createMatchSet();
clearEvents();
VTMatchInfo match = VTTestUtils.createRandomMatch(null);
VTMatchInfo match = VTTestUtils.createRandomMatch(sourceProgram, destinationProgram);
matchSet.addMatch(match);
@@ -107,7 +107,7 @@ public class VTDomainObjectEventsTest extends VTBaseTestCase {
@Test
public void testEventsForAddingAdditionalMatchForAssociation() {
VTMatchSet matchSet = createMatchSet();
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(null);
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(sourceProgram, destinationProgram);
matchSet.addMatch(matchInfo);
clearEvents();
@@ -124,7 +124,7 @@ public class VTDomainObjectEventsTest extends VTBaseTestCase {
public void testEventsForRemovingLastMatchForAssociation() {
VTMatchSet manualMatchSet = db.getManualMatchSet();
clearEvents();
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(null);
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(sourceProgram, destinationProgram);
VTMatch match = manualMatchSet.addMatch(matchInfo);
clearEvents();
@@ -139,7 +139,7 @@ public class VTDomainObjectEventsTest extends VTBaseTestCase {
public void testEventsForDeletingLastMatchForAssociation() {
VTMatchSet manualMatchSet = db.getManualMatchSet();
clearEvents();
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(null);
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(sourceProgram, destinationProgram);
VTMatch match = manualMatchSet.addMatch(matchInfo);
clearEvents();
@@ -155,7 +155,7 @@ public class VTDomainObjectEventsTest extends VTBaseTestCase {
public void testEventsForRemovingNonLastMatchForAssociation() {
VTMatchSet manualMatchSet = db.getManualMatchSet();
clearEvents();
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(null);
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(sourceProgram, destinationProgram);
VTMatch match = manualMatchSet.addMatch(matchInfo);
clearEvents();
@@ -170,7 +170,7 @@ public class VTDomainObjectEventsTest extends VTBaseTestCase {
public void testEventsForDeletingNonLastMatchForAssociation() {
VTMatchSet manualMatchSet = db.getManualMatchSet();
clearEvents();
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(null);
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(sourceProgram, destinationProgram);
VTMatch match = manualMatchSet.addMatch(matchInfo);
clearEvents();
@@ -184,7 +184,7 @@ public class VTDomainObjectEventsTest extends VTBaseTestCase {
@Test
public void testEventsForRejectingMatch() throws VTAssociationStatusException {
VTMatchSet matchSet = createMatchSet();
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(null);
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(sourceProgram, destinationProgram);
VTMatch match = matchSet.addMatch(matchInfo);
clearEvents();
match.getAssociation().setRejected();
@@ -197,7 +197,7 @@ public class VTDomainObjectEventsTest extends VTBaseTestCase {
public void testAssociationStatusChangedEvent() throws Exception {
VTMatchSet manualMatchSet = db.getManualMatchSet();
clearEvents();
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(null);
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(sourceProgram, destinationProgram);
VTMatch match = manualMatchSet.addMatch(matchInfo);
clearEvents();
@@ -214,7 +214,7 @@ public class VTDomainObjectEventsTest extends VTBaseTestCase {
Msg.debug(this, "\tcalling clrearEvents()");
clearEvents();
Msg.debug(this, "\tcalling createRandomMatch()");
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(null);
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(sourceProgram, destinationProgram);
Msg.debug(this, "\tcalling addMatch()");
VTMatch match = manualMatchSet.addMatch(matchInfo);
Msg.debug(this, "\tcalling setAccepted()");
@@ -239,7 +239,7 @@ public class VTDomainObjectEventsTest extends VTBaseTestCase {
public void testMarkupStatusChangedEventWhenApplying() throws Exception {
VTMatchSet manualMatchSet = db.getManualMatchSet();
clearEvents();
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(null);
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(sourceProgram, destinationProgram);
VTMatch match = manualMatchSet.addMatch(matchInfo);
match.getAssociation().setAccepted();
VTMarkupItem markupItem = VTTestUtils.createRandomMarkupItemStub(match);
@@ -259,7 +259,7 @@ public class VTDomainObjectEventsTest extends VTBaseTestCase {
public void testMarkupStatusChangedEventWhenSettingStatus() throws Exception {
VTMatchSet manualMatchSet = db.getManualMatchSet();
clearEvents();
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(null);
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(sourceProgram, destinationProgram);
VTMatch match = manualMatchSet.addMatch(matchInfo);
match.getAssociation().setAccepted();
VTMarkupItem markupItem = VTTestUtils.createRandomMarkupItemStub(match);
@@ -295,7 +295,7 @@ public class VTDomainObjectEventsTest extends VTBaseTestCase {
public void testTagAppliedEvent() throws VTAssociationStatusException {
VTMatchTagDB tag = db.createMatchTag("TEST");
VTMatchSet manualMatchSet = db.getManualMatchSet();
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(null);
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(sourceProgram, destinationProgram);
VTMatch match = manualMatchSet.addMatch(matchInfo);
match.getAssociation().setAccepted();
clearEvents();
@@ -313,7 +313,7 @@ public class VTDomainObjectEventsTest extends VTBaseTestCase {
@Test
public void testEventsForVotes() {
VTMatchSet manualMatchSet = db.getManualMatchSet();
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(null);
VTMatchInfo matchInfo = VTTestUtils.createRandomMatch(sourceProgram, destinationProgram);
VTMatch match = manualMatchSet.addMatch(matchInfo);
clearEvents();
match.getAssociation().setVoteCount(4);

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -27,7 +27,8 @@ import ghidra.feature.vt.api.main.*;
import ghidra.feature.vt.api.markupitem.MarkupTypeTestStub;
import ghidra.feature.vt.api.markuptype.VTMarkupType;
import ghidra.feature.vt.api.markuptype.VTMarkupTypeFactory;
import ghidra.program.model.address.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.listing.Program;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
@@ -35,8 +36,6 @@ import ghidra.util.task.TaskMonitor;
public class VTTestUtils {
private static String[] randomTags = { "TAG1", "TAG2", "TAG3" };
private static GenericAddressSpace space =
new GenericAddressSpace("Test", 32, AddressSpace.TYPE_RAM, 3);
private VTTestUtils() {
// utility class
@@ -75,8 +74,8 @@ public class VTTestUtils {
return getRandomInt(0, Integer.MAX_VALUE);
}
public static Address addr() {
return addr(getRandomInt());
public static Address addr(Program p) {
return addr(getRandomInt(), p);
}
public static Address addr(String offset, Program p) {
@@ -84,14 +83,15 @@ public class VTTestUtils {
return addressFactory.getAddress(offset);
}
public static Address addr(long offset) {
return space.getAddress(offset);
public static Address addr(long offset, Program p) {
return p.getAddressFactory().getDefaultAddressSpace().getAddress(offset);
}
public static Address otherAddr(Address address) {
Address newAddress = addr();
while (newAddress.equals(address)) {
newAddress = addr();
public static Address otherAddr(Address addr, Program p) {
Address newAddress = addr(p);
long offset = addr.getOffset();
while (offset == newAddress.getOffset()) {
newAddress = addr(p);
}
return newAddress;
}
@@ -103,7 +103,19 @@ public class VTTestUtils {
* @return the match
*/
public static VTMatchInfo createRandomMatch(VTSession session) {
return createRandomMatch(addr(), addr(), session);
return createRandomMatch(addr(session.getSourceProgram()),
addr(session.getDestinationProgram()), session);
}
/**
* Create a random dummy match with a null VTSession.
* @param session the match set manager to use when creating a random tag or
* null if you don't want to create a random tag.
* @return the match
*/
public static VTMatchInfo createRandomMatch(Program sourceProgram,
Program destincationProgram) {
return createRandomMatch(addr(sourceProgram), addr(destincationProgram), null);
}
/**
@@ -184,7 +196,8 @@ public class VTTestUtils {
}
public static VTMatch createMatchSetWithOneMatch(VTSessionDB db) throws Exception {
return createMatchSetWithOneMatch(db, addr(), addr());
return createMatchSetWithOneMatch(db, addr(db.getSourceProgram()),
addr(db.getDestinationProgram()));
}
public static VTMatch createMatchSetWithOneMatch(VTSessionDB db, Address sourceAddress,

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -295,6 +295,48 @@ public class AddressMapDB implements AddressMap {
return encodeAbsolute(addr, create ? INDEX_CREATE : INDEX_MATCH);
}
private Address checkAddressSpace(Address addr) {
AddressSpace space = addr.getAddressSpace();
if (space.getType() == AddressSpace.TYPE_DELETED) {
return addr;
}
if (space.isStackSpace()) {
AddressSpace myStackSpace = addrFactory.getStackSpace();
if (!space.equals(myStackSpace)) {
// Stack AddressSpace differs from my program's stack
throw new IllegalArgumentException(
"Unknown stack address from a different Program: " + addr.toString(true));
}
}
else if (space.isMemorySpace()) {
AddressSpace mySpace = addrFactory.getAddressSpace(space.getSpaceID()); // fast lookup
if (space != mySpace) {
// AddressSpace instance is not from my program's AddressFactory -
// perform a lookup by name and allow use if matching space is found.
// Although mixing address space use between programs is not preferred we try to
// accomodate provided all address characterics match. An ID lookup is performed
// first since it is the fastest way to verify the address originated from our
// address factory, otherwise we must attempt to find the same address space
// by name and check all characteristics via the equals method. This assumes
// a HashMap lookup based on an integer key is faster than a string key lookup.
mySpace = addrFactory.getAddressSpace(space.getName());
// NOTE: overlay spaces from different programs will never be equal if their
// 'orderedKey' differ. This can occur if they get renamed.
if (!space.equals(mySpace)) {
throw new IllegalArgumentException(
"Unknown address from a different Program: " + addr.toString(true));
}
// Transform into my address to avoid map contamination
if (mySpace instanceof OverlayAddressSpace myOvSpace) {
return myOvSpace.getAddressInThisSpaceOnly(addr.getOffset());
}
return mySpace.getAddress(addr.getOffset());
}
}
return addr;
}
/**
* Get absolute key encoding for the specified address
* @param addr address
@@ -315,6 +357,7 @@ public class AddressMapDB implements AddressMap {
case AddressSpace.TYPE_CODE:
case AddressSpace.TYPE_DELETED:
case AddressSpace.TYPE_OTHER:
addr = checkAddressSpace(addr);
int baseIndex = getBaseAddressIndex(addr, false, indexOperation);
long offset;
if (baseIndex < 0) {
@@ -347,6 +390,7 @@ public class AddressMapDB implements AddressMap {
return REGISTER_ADDR_TYPE_LONG | (addr.getOffset() & ADDR_OFFSET_MASK);
case AddressSpace.TYPE_STACK:
addr = checkAddressSpace(addr);
return STACK_ADDR_TYPE_LONG | (addr.getOffset() & ADDR_OFFSET_MASK);
case AddressSpace.TYPE_EXTERNAL:
@@ -425,7 +469,6 @@ public class AddressMapDB implements AddressMap {
}
// A new address map entry is required
checkAddressSpace(addr.getAddressSpace());
int index = baseAddrs.length;
if (readOnly) {
// Create new base without modifying database
@@ -448,18 +491,6 @@ public class AddressMapDB implements AddressMap {
return index;
}
void checkAddressSpace(AddressSpace addrSpace) {
AddressSpace[] spaces = addrFactory.getPhysicalSpaces();
for (AddressSpace space : spaces) {
if (addrSpace.equals(space)) {
return;
}
}
if (addrSpace.getPhysicalSpace() != AddressSpace.OTHER_SPACE) { // not physical - but always exists in program
throw new IllegalArgumentException("Address space not found in program");
}
}
@Override
public synchronized Address decodeAddress(long value) {
return decodeAddress(value, true);
@@ -621,6 +652,7 @@ public class AddressMapDB implements AddressMap {
case AddressSpace.TYPE_CODE:
case AddressSpace.TYPE_DELETED:
case AddressSpace.TYPE_OTHER:
addr = checkAddressSpace(addr);
boolean normalize = !addrIsNormalized && isInDefaultAddressSpace(addr);
int baseIndex = getBaseAddressIndex(addr, normalize, indexOperation);
long offset;

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -75,7 +75,7 @@ class AddressMapDBAdapterV1 extends AddressMapDBAdapter {
if (segment != 0) {
spaceName += "_" + segment;
}
GenericAddressSpace sp = new GenericAddressSpace(deletedName, 32,
GenericAddressSpace sp = new GenericAddressSpace(deletedName, 64,
AddressSpace.TYPE_DELETED, (int) rec.getKey());
sp.setShowSpaceName(true);
space = sp;
@@ -156,8 +156,8 @@ class AddressMapDBAdapterV1 extends AddressMapDBAdapter {
Address[] newAddrs = new Address[addresses.length + 1];
System.arraycopy(addresses, 0, newAddrs, 0, addresses.length);
newAddrs[addresses.length] = addr.getAddressSpace().getAddressInThisSpaceOnly(
normalizedOffset & ~AddressMapDB.ADDR_OFFSET_MASK);
newAddrs[addresses.length] = addr.getAddressSpace()
.getAddressInThisSpaceOnly(normalizedOffset & ~AddressMapDB.ADDR_OFFSET_MASK);
addresses = newAddrs;
return addresses;

View File

@@ -16,8 +16,7 @@
package ghidra.program.database.symbol;
import java.io.IOException;
import java.util.Objects;
import java.util.Set;
import java.util.*;
import org.apache.commons.lang3.StringUtils;
@@ -185,13 +184,13 @@ abstract class SymbolDatabaseAdapter {
AddressMap oldAddrMap = addrMap.getOldAddressMap();
long nextKey = 1; // only used for V0 upgrade if a record with key 0 is encountered
long zeroIdRemap = -1; // only used for V0 upgrade if a record with key 0 is encountered
if (oldAdapter instanceof SymbolDatabaseAdapterV0) {
// V0 is so old that there is not enough info in the current record to create new
// records. So store the current info in a temp database table and complete the upgrade
// when SymbolManager.programReady() is called. The missing info can be retrieved from
// other managers in the program at that point.
nextKey =
zeroIdRemap =
((SymbolDatabaseAdapterV0) oldAdapter).extractLocalSymbols(tmpHandle, monitor);
}
@@ -205,8 +204,9 @@ abstract class SymbolDatabaseAdapter {
// We don't allow 0 keys starting with V1, set its key to next available
// which we got from the call to extractLocalSymbols() above
if (rec.getKey() == 0) {
rec.setKey(Math.max(1, nextKey));
if (zeroIdRemap > 0 && rec.getKey() == 0) {
// NOTE: V0 did not have concept of parent relationship
rec.setKey(zeroIdRemap);
}
tmpAdapter.updateSymbolRecord(rec);

View File

@@ -19,6 +19,7 @@ import java.io.IOException;
import java.util.Set;
import db.*;
import ghidra.framework.data.OpenMode;
import ghidra.program.database.map.AddressIndexPrimaryKeyIterator;
import ghidra.program.database.map.AddressMap;
import ghidra.program.database.util.EmptyRecordIterator;
@@ -78,7 +79,7 @@ class SymbolDatabaseAdapterV0 extends SymbolDatabaseAdapter {
* Stores local symbols information in a temporary database table because this version
* is so old, we don't have enough information in the record to upgrade during the normal
* upgrade time. So we store off the information and will complete this upgrade when
* {@link SymbolManager#programReady(int, int, TaskMonitor)} is called
* {@link SymbolManager#programReady(OpenMode, int, TaskMonitor)} is called
*
* @param handle handle to temporary database
* @param monitor the {@link TaskMonitor}

View File

@@ -155,8 +155,8 @@ public class SymbolManager implements SymbolTable, ManagerDB {
throws IOException, CancelledException {
if (openMode == OpenMode.UPGRADE) {
processOldLocalSymbols(monitor);
processOldExternalEntryPoints(monitor);
processOldLocalSymbols(monitor); // migrate from temp table from V0 adapter upgrade
processOldExternalEntryPoints(monitor); // migrates from obsolete table: External Entries
if (currentRevision < ProgramDB.ADDED_VARIABLE_STORAGE_MANAGER_VERSION) {
// Eliminated namespace encoding within External address encoding
@@ -165,8 +165,9 @@ public class SymbolManager implements SymbolTable, ManagerDB {
// Migrate all other OldNamespaceAddresses used for variable symbols
processOldVariableAddresses(monitor);
}
if (currentRevision < ProgramDB.EXTERNAL_FUNCTIONS_ADDED_VERSION) {
// SymbolType.EXTERNAL eliminated with program revision 17
// SymbolType.EXTERNAL eliminated with program revision 17 (switch to LABEL)
processOldExternalTypes(monitor);
}

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -637,7 +637,7 @@ abstract class AbstractAddressSpace implements AddressSpace {
@Override
public boolean isMemorySpace() {
return type == TYPE_RAM || type == TYPE_CODE || type == TYPE_OTHER;
return type == TYPE_RAM || type == TYPE_CODE || type == TYPE_OTHER || type == TYPE_DELETED;
}
@Override

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -53,18 +53,16 @@ public class AddressRangeImpl implements AddressRange, Serializable {
* maximum addresses are not comparable.
*/
public AddressRangeImpl(Address start, Address end) {
if (!start.getAddressSpace().equals(end.getAddressSpace())) {
throw new IllegalArgumentException("Start and end addresses are not in the same space.");
}
if (start.compareTo(end) < 0) {
minAddress = start;
maxAddress = end;
} else {
}
else {
// swap them if out of order
minAddress = end;
maxAddress = start;
}
AddressRange.checkValidRange(minAddress, maxAddress);
}
/**
@@ -120,8 +118,9 @@ public class AddressRangeImpl implements AddressRange, Serializable {
@Override
public BigInteger getBigLength() {
return maxAddress.getOffsetAsBigInteger().subtract(minAddress.getOffsetAsBigInteger()).add(
BigInteger.ONE);
return maxAddress.getOffsetAsBigInteger()
.subtract(minAddress.getOffsetAsBigInteger())
.add(BigInteger.ONE);
}
/**