diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ManagerDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ManagerDB.java index 65b47f389f..e406390b59 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ManagerDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/ManagerDB.java @@ -17,8 +17,7 @@ package ghidra.program.database; import java.io.IOException; -import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressOverflowException; +import ghidra.program.model.address.*; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; @@ -44,8 +43,8 @@ public interface ManagerDB { * @throws IOException if a database io error occurs. * @throws CancelledException if the user cancelled the operation via the task monitor. */ - void programReady(int openMode, int currentRevision, TaskMonitor monitor) throws IOException, - CancelledException; + void programReady(int openMode, int currentRevision, TaskMonitor monitor) + throws IOException, CancelledException; /** * Clears all data caches. @@ -59,6 +58,9 @@ public interface ManagerDB { /** * Delete all objects which have been applied to the address range startAddr to endAddr * and update the database accordingly. + * The specified start and end addresses must form a valid range within + * a single {@link AddressSpace}. + * * @param startAddr the first address in the range. * @param endAddr the last address in the range. * @param monitor the task monitor to use in any upgrade operations. @@ -69,6 +71,7 @@ public interface ManagerDB { /** * Move all objects within an address range to a new location. + * * @param fromAddr the first address of the range to be moved. * @param toAddr the address where to the range is to be moved. * @param length the number of addresses to move. diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/CodeManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/CodeManager.java index 44feb59f7d..a98fcae4d6 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/CodeManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/CodeManager.java @@ -724,6 +724,8 @@ public class CodeManager implements ErrorHandler, ManagerDB { public void deleteAddressRange(Address start, Address end, TaskMonitor monitor) throws CancelledException { + AddressRange.checkValidRange(start, end); + // Expand range to include any overlapping or delay-slotted instructions CodeUnit cu = getCodeUnitContaining(start); if (cu != null) { @@ -2194,11 +2196,14 @@ public class CodeManager implements ErrorHandler, ManagerDB { /** * Clears all comments in the given range (inclusive). + * The specified start and end addresses must form a valid range within + * a single {@link AddressSpace}. * * @param start the start address of the range to clear * @param end the end address of the range to clear */ public void clearComments(Address start, Address end) { + AddressRange.checkValidRange(start, end); lock.acquire(); try { try { @@ -2227,6 +2232,8 @@ public class CodeManager implements ErrorHandler, ManagerDB { /** * Clears the properties in the given range (inclusive). + * The specified start and end addresses must form a valid range within + * a single {@link AddressSpace}. * * @param start the start address of the range to clear * @param end the end address of the range to clear @@ -2289,6 +2296,9 @@ public class CodeManager implements ErrorHandler, ManagerDB { /** * Remove code units, symbols, equates, and references to code units in the given range * (inclusive). Comments and comment history will be retained. + * The specified start and end addresses must form a valid range within + * a single {@link AddressSpace}. + * * @param start the start address of the range to clear * @param end the end address of the range to clear * @param clearContext if true all context-register values will be cleared over range @@ -2297,6 +2307,7 @@ public class CodeManager implements ErrorHandler, ManagerDB { */ public void clearCodeUnits(Address start, Address end, boolean clearContext, TaskMonitor monitor) throws CancelledException { + AddressRange.checkValidRange(start, end); lock.acquire(); try { // Expand range to include any overlapping or delay-slotted instructions @@ -2336,10 +2347,10 @@ public class CodeManager implements ErrorHandler, ManagerDB { * @param monitor the task monitor */ public void clearAll(boolean clearContext, TaskMonitor monitor) { - Address minAddr = program.getMinAddress(); - Address maxAddr = program.getMaxAddress(); try { - clearCodeUnits(minAddr, maxAddr, clearContext, monitor); + for (AddressRange range : program.getMemory().getAddressRanges()) { + clearCodeUnits(range.getMinAddress(), range.getMaxAddress(), clearContext, monitor); + } } catch (CancelledException e) { // nothing to do @@ -2571,17 +2582,18 @@ public class CodeManager implements ErrorHandler, ManagerDB { } /** - * Check if any instruction intersects the specified address range + * Check if any instruction intersects the specified address range. + * The specified start and end addresses must form a valid range within + * a single {@link AddressSpace}. + * * @param start start of range * @param end end of range * @throws ContextChangeException if there is a context register change conflict */ public void checkContextWrite(Address start, Address end) throws ContextChangeException { + AddressRange.checkValidRange(start, end); lock.acquire(); try { - if (!start.getAddressSpace().equals(end.getAddressSpace())) { - throw new IllegalArgumentException(); - } if (!contextLockingEnabled || creatingInstruction || !program.getMemory().contains(start, end)) { return; diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProgramBasedDataTypeManagerDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProgramBasedDataTypeManagerDB.java index 7c2f4f4102..de86989b06 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProgramBasedDataTypeManagerDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProgramBasedDataTypeManagerDB.java @@ -22,8 +22,7 @@ import db.*; import db.util.ErrorHandler; import ghidra.docking.settings.SettingsDefinition; import ghidra.program.database.map.AddressMap; -import ghidra.program.model.address.Address; -import ghidra.program.model.address.KeyRange; +import ghidra.program.model.address.*; import ghidra.program.model.data.*; import ghidra.program.model.listing.Data; import ghidra.util.Lock; @@ -66,12 +65,12 @@ public abstract class ProgramBasedDataTypeManagerDB extends DataTypeManagerDB super(handle, addrMap, openMode, tablePrefix, errHandler, lock, monitor); } + @Override protected void initializeOtherAdapters(int openMode, TaskMonitor monitor) throws CancelledException, IOException, VersionException { if (addrMap != null) { - instanceSettingsAdapter = - SettingsDBAdapter.getAdapter(tablePrefix + INSTANCE_SETTINGS_TABLE_NAME, dbHandle, - openMode, addrMap, monitor); + instanceSettingsAdapter = SettingsDBAdapter.getAdapter( + tablePrefix + INSTANCE_SETTINGS_TABLE_NAME, dbHandle, openMode, addrMap, monitor); } } @@ -97,8 +96,7 @@ public abstract class ProgramBasedDataTypeManagerDB extends DataTypeManagerDB abstract protected void dataSettingChanged(Address address); @Override - public boolean isChangeAllowed(Data data, - SettingsDefinition settingsDefinition) { + public boolean isChangeAllowed(Data data, SettingsDefinition settingsDefinition) { if (settingsDefinition instanceof TypeDefSettingsDefinition) { return false; } @@ -261,9 +259,8 @@ public abstract class ProgramBasedDataTypeManagerDB extends DataTypeManagerDB monitor.checkCancelled(); DBRecord rec = iter.next(); // update address key (i.e., settings association ID) and re-introduce into table - Address addr = addrMap - .decodeAddress( - rec.getLongValue(SettingsDBAdapter.SETTINGS_ASSOCIATION_ID_COL)); + Address addr = addrMap.decodeAddress( + rec.getLongValue(SettingsDBAdapter.SETTINGS_ASSOCIATION_ID_COL)); long offset = addr.subtract(fromAddr); addr = toAddr.add(offset); rec.setLongValue(SettingsDBAdapter.SETTINGS_ASSOCIATION_ID_COL, @@ -410,6 +407,7 @@ public abstract class ProgramBasedDataTypeManagerDB extends DataTypeManagerDB if (instanceSettingsAdapter == null) { throw new UnsupportedOperationException(); } + AddressRange.checkValidRange(startAddr, endAddr); lock.acquire(); try { List addrKeyRanges = addrMap.getKeyRanges(startAddr, endAddr, false); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/module/TreeManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/module/TreeManager.java index 18e94259f3..21fe5c497a 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/module/TreeManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/module/TreeManager.java @@ -98,9 +98,7 @@ public class TreeManager implements ManagerDB { public void imageBaseChanged(boolean commit) { lock.acquire(); try { - Iterator iter = treeMap.values().iterator(); - while (iter.hasNext()) { - ModuleManager m = iter.next(); + for (ModuleManager m : treeMap.values()) { m.imageBaseChanged(commit); } } @@ -376,6 +374,7 @@ public class TreeManager implements ManagerDB { @Override public void deleteAddressRange(Address startAddr, Address endAddr, TaskMonitor monitor) throws CancelledException { + AddressRange.checkValidRange(startAddr, endAddr); lock.acquire(); try { Iterator keys = treeMap.keySet().iterator(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/properties/DBPropertyMapManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/properties/DBPropertyMapManager.java index c52f51210f..ef20b3662d 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/properties/DBPropertyMapManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/properties/DBPropertyMapManager.java @@ -28,6 +28,7 @@ import ghidra.program.database.ProgramDB; import ghidra.program.database.bookmark.OldBookmark; import ghidra.program.database.map.AddressMap; import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressRange; import ghidra.program.model.listing.BookmarkManager; import ghidra.program.model.util.*; import ghidra.program.util.ChangeManager; @@ -576,9 +577,7 @@ public class DBPropertyMapManager implements PropertyMapManager, ManagerDB { public void removeAll(Address addr) { lock.acquire(); try { - Iterator> iter = propertyMapCache.values().iterator(); - while (iter.hasNext()) { - PropertyMapDB pm = iter.next(); + for (PropertyMapDB pm : propertyMapCache.values()) { pm.remove(addr); } @@ -591,15 +590,13 @@ public class DBPropertyMapManager implements PropertyMapManager, ManagerDB { @Override public void removeAll(Address startAddr, Address endAddr, TaskMonitor monitor) throws CancelledException { + AddressRange.checkValidRange(startAddr, endAddr); lock.acquire(); try { - Iterator> iter = propertyMapCache.values().iterator(); - while (iter.hasNext()) { + for (PropertyMapDB pm : propertyMapCache.values()) { monitor.checkCancelled(); - PropertyMapDB pm = iter.next(); pm.removeRange(startAddr, endAddr); } - } finally { lock.release(); @@ -611,13 +608,10 @@ public class DBPropertyMapManager implements PropertyMapManager, ManagerDB { throws CancelledException { lock.acquire(); try { - Iterator> iter = propertyMapCache.values().iterator(); - while (iter.hasNext()) { + for (PropertyMapDB pm : propertyMapCache.values()) { monitor.checkCancelled(); - PropertyMapDB pm = iter.next(); pm.moveRange(fromAddr, fromAddr.add(length - 1), toAddr); } - } finally { lock.release(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/register/ProgramRegisterContextDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/register/ProgramRegisterContextDB.java index 37fd0b15ab..03ff77bbd3 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/register/ProgramRegisterContextDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/register/ProgramRegisterContextDB.java @@ -210,6 +210,7 @@ public class ProgramRegisterContextDB extends AbstractStoredProgramContext imple @Override public void deleteAddressRange(Address start, Address end, TaskMonitor monitor) { + AddressRange.checkValidRange(start, end); lock.acquire(); try { super.deleteAddressRange(start, end, monitor); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/EquateManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/EquateManager.java index b70ca77d7f..74ce4140b5 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/EquateManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/EquateManager.java @@ -312,6 +312,7 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB { @Override public void deleteAddressRange(Address startAddr, Address endAddr, TaskMonitor monitor) throws CancelledException { + AddressRange.checkValidRange(startAddr, endAddr); lock.acquire(); try { ArrayList list = new ArrayList<>(); 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 4c6f82e683..6ad246e5f9 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 @@ -2427,6 +2427,7 @@ public class SymbolManager implements SymbolTable, ManagerDB { @Override public void deleteAddressRange(Address startAddr, Address endAddr, TaskMonitor monitor) throws CancelledException { + AddressRange.checkValidRange(startAddr, endAddr); lock.acquire(); try { invalidateCache(true); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/util/AddressRangeMapDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/util/AddressRangeMapDB.java index 42d6a70530..069a677e6c 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/util/AddressRangeMapDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/util/AddressRangeMapDB.java @@ -214,13 +214,7 @@ public class AddressRangeMapDB implements DBListener { * @throws IllegalArgumentException if the end address is greater then the start address */ public void paintRange(Address startAddress, Address endAddress, Field value) { - if (!startAddress.hasSameAddressSpace(endAddress)) { - throw new IllegalArgumentException("Addresses must be in the same space!"); - } - if (startAddress.compareTo(endAddress) > 0) { - throw new IllegalArgumentException("Start address must be <= end address!"); - } - + AddressRange.checkValidRange(startAddress, endAddress); lock.acquire(); try { clearCache(); @@ -566,8 +560,7 @@ public class AddressRangeMapDB implements DBListener { record = getRecordAfter(address); if (record != null) { Address startAddress = getStartAddress(record); - if (startAddress.hasSameAddressSpace(address) && - startAddress.compareTo(address) > 0) { + if (startAddress.hasSameAddressSpace(address) && startAddress.compareTo(address) > 0) { gapEnd = startAddress.subtract(1); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressRange.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressRange.java index 934977f430..9574083408 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressRange.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressRange.java @@ -101,4 +101,25 @@ public interface AddressRange extends Comparable, Iterable
0) { - throw new IllegalArgumentException("Start address must be less than or equal to " + - "end address: Start " + start + " end = " + end); - } - - if (!start.getAddressSpace().equals(end.getAddressSpace())) { - throw new IllegalArgumentException( - "Start and end addresses must be in same address space! Start " + start + - " end = " + end); - } - } - private RedBlackEntry createRangeNode(Address start, Address end) { RedBlackEntry newEntry = rbTree.getOrCreateEntry(start); newEntry.setValue(end); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressSetView.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressSetView.java index 81aec8a393..218ae9ed91 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressSetView.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressSetView.java @@ -33,6 +33,8 @@ public interface AddressSetView extends Iterable { /** * Test if the given address range is contained in this set. + * The specified start and end addresses must form a valid range within + * a single {@link AddressSpace}. *

* @param start the first address in the range. * @param end the last address in the range. @@ -56,11 +58,19 @@ public interface AddressSetView extends Iterable { public boolean isEmpty(); /** + * Get the minimum address for this address set. + * NOTE: An {@link AddressRange} should generally not be formed using this address + * and {@link #getMaxAddress()} since it may span multiple {@link AddressSpace}s. + * * @return the minimum address for this set. Returns null if the set is empty. */ public Address getMinAddress(); /** + * Get the maximum address for this address set. + * NOTE: An {@link AddressRange} should generally not be formed using this address + * and {@link #getMaxAddress()} since it may span multiple {@link AddressSpace}s. + * * @return the maximum address for this set. Returns null if the set is empty. */ public Address getMaxAddress(); @@ -151,8 +161,9 @@ public interface AddressSetView extends Iterable { public boolean intersects(AddressSetView addrSet); /** - * Determine if the start and end range - * intersects with the specified address set. + * Determine if the start and end range intersects with the specified address set. + * The specified start and end addresses must form a valid range within + * a single {@link AddressSpace}. * @param start start of range * @param end end of range * @return true if the given range intersects this address set. @@ -171,6 +182,8 @@ public interface AddressSetView extends Iterable { /** * Computes the intersection of this address set with the given address range. * This method does not modify this address set. + * The specified start and end addresses must form a valid range within + * a single {@link AddressSpace}. * @param start start of range * @param end end of range * @return AddressSet a new address set that contains all addresses that are diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/Program.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/Program.java index 73411665f3..2fd7d0032a 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/Program.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/Program.java @@ -305,7 +305,10 @@ public interface Program extends DataTypeManagerDomainObject, ProgramArchitectur public ProgramContext getProgramContext(); /** - * get the program's minimum address. + * Get the program's minimum address. + * NOTE: An {@link AddressRange} should generally not be formed using this address + * and {@link #getMaxAddress()} since it may span multiple {@link AddressSpace}s. + * * @return the program's minimum address or null if no memory blocks * have been defined in the program. */ @@ -313,6 +316,9 @@ public interface Program extends DataTypeManagerDomainObject, ProgramArchitectur /** * Get the programs maximum address. + * NOTE: An {@link AddressRange} should generally not be formed using this address + * and {@link #getMinAddress()} since it may span multiple {@link AddressSpace}s. + * * @return the program's maximum address or null if no memory blocks * have been defined in the program. */ diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/util/PropertyMapManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/util/PropertyMapManager.java index c636e303ca..7684bdbccf 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/util/PropertyMapManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/util/PropertyMapManager.java @@ -18,6 +18,7 @@ package ghidra.program.model.util; import java.util.Iterator; import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressSpace; import ghidra.util.Saveable; import ghidra.util.exception.CancelledException; import ghidra.util.exception.DuplicateNameException; @@ -153,7 +154,10 @@ public interface PropertyMapManager { /** * Removes all properties in the given range from all user - * defined PropertyMaps. + * defined PropertyMaps. + * The specified start and end addresses must form a valid range within + * a single {@link AddressSpace}. + * * @param startAddr the first address in the range of addresses where * propertie values are to be removed. * @param endAddr the last address in the range of addresses where diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/RegisterValueStore.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/RegisterValueStore.java index c79fcbc919..a38510a3af 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/RegisterValueStore.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/RegisterValueStore.java @@ -152,9 +152,7 @@ public class RegisterValueStore { while (rangeIt.hasNext()) { list.add(rangeIt.next()); } - Iterator it = list.iterator(); - while (it.hasNext()) { - AddressRange indexRange = it.next(); + for (AddressRange indexRange : list) { Address rangeStart = indexRange.getMinAddress(); Address rangeEnd = indexRange.getMaxAddress(); if (rangeStart.compareTo(start) > 0) { @@ -194,6 +192,8 @@ public class RegisterValueStore { */ public void clearValue(Address start, Address end, Register register) { + AddressRange.checkValidRange(start, end); + flushWriteCache(); // if the mask is all on, then just clear any values that are stored in this range @@ -208,9 +208,7 @@ public class RegisterValueStore { while (rangeIt.hasNext()) { list.add(rangeIt.next()); } - Iterator it = list.iterator(); - while (it.hasNext()) { - AddressRange indexRange = it.next(); + for (AddressRange indexRange : list) { Address rangeStart = indexRange.getMinAddress(); Address rangeEnd = indexRange.getMaxAddress(); @@ -243,7 +241,7 @@ public class RegisterValueStore { if (bytes != null) { value = new RegisterValue(register, bytes); } - + synchronized (this) { if (rangeWriteCacheValue != null && address.compareTo(rangeWriteCacheMin) >= 0 && address.compareTo(rangeWriteCacheMax) <= 0) {