diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramMerge.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramMerge.java index c1c0fafe3d..11fed712fa 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramMerge.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramMerge.java @@ -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(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolMerge.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolMerge.java index 9fa9ce637a..6259f96911 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolMerge.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolMerge.java @@ -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 SymbolTranslators 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 { diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/map/AddressRangeMapDBTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/map/AddressRangeMapDBTest.java index 8153dd0df3..c3187839fc 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/map/AddressRangeMapDBTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/map/AddressRangeMapDBTest.java @@ -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() { diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/util/ProgramMerge2Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/util/ProgramMerge2Test.java index 1ce97f5713..eab4b52846 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/util/ProgramMerge2Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/util/ProgramMerge2Test.java @@ -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); diff --git a/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/api/markupitem/AbstractVTMarkupItemTest.java b/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/api/markupitem/AbstractVTMarkupItemTest.java index 134ebc103c..2c677ff726 100644 --- a/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/api/markupitem/AbstractVTMarkupItemTest.java +++ b/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/api/markupitem/AbstractVTMarkupItemTest.java @@ -339,7 +339,7 @@ public abstract class AbstractVTMarkupItemTest extends AbstractGhidraHeadedInteg // verify we cannot unapply before we have applied // List markupItems = new ArrayList<>(); - Address destinationAddress = addr(); + Address destinationAddress = addr(session.getDestinationProgram()); markupItem.setDefaultDestinationAddress(destinationAddress, TEST_ADDRESS_SOURCE); markupItems.add(markupItem); diff --git a/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/AddressMapTestDummy.java b/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/AddressMapTestDummy.java index 4fdbd53d3b..bf2b1861c2 100644 --- a/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/AddressMapTestDummy.java +++ b/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/AddressMapTestDummy.java @@ -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 diff --git a/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/DummyTestProgramCorrelator.java b/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/DummyTestProgramCorrelator.java index dc3d3ed2e4..34b3fb48ec 100644 --- a/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/DummyTestProgramCorrelator.java +++ b/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/DummyTestProgramCorrelator.java @@ -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)); } diff --git a/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/VTAssociationDBTest.java b/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/VTAssociationDBTest.java index 737a9f9973..4c08da6e0e 100644 --- a/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/VTAssociationDBTest.java +++ b/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/VTAssociationDBTest.java @@ -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); } diff --git a/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/VTBaseTestCase.java b/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/VTBaseTestCase.java index 337de9be54..2151d1515b 100644 --- a/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/VTBaseTestCase.java +++ b/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/VTBaseTestCase.java @@ -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 diff --git a/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/VTDomainObjectEventsTest.java b/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/VTDomainObjectEventsTest.java index fe2af6475c..4c2ca49756 100644 --- a/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/VTDomainObjectEventsTest.java +++ b/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/VTDomainObjectEventsTest.java @@ -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); diff --git a/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/VTTestUtils.java b/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/VTTestUtils.java index 132e5fe0ca..873fa2abb1 100644 --- a/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/VTTestUtils.java +++ b/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/VTTestUtils.java @@ -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, diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressMapDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressMapDB.java index ec17ed2877..d883256bce 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressMapDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressMapDB.java @@ -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; diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressMapDBAdapterV1.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressMapDBAdapterV1.java index ba498e76a5..f82592aaf4 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressMapDBAdapterV1.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressMapDBAdapterV1.java @@ -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; diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapter.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapter.java index b9e831da77..4f14e7c5a7 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapter.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapter.java @@ -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); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV0.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV0.java index 42de8a41d4..bd61333d08 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV0.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolDatabaseAdapterV0.java @@ -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} diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolManager.java index 6d83b8145f..6275670096 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/SymbolManager.java @@ -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); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AbstractAddressSpace.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AbstractAddressSpace.java index cd41cd2e36..ba4fe55969 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AbstractAddressSpace.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AbstractAddressSpace.java @@ -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 diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressRangeImpl.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressRangeImpl.java index e58123c0b8..42c8175b61 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressRangeImpl.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressRangeImpl.java @@ -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); } /**