diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/map/AddressKeyIteratorTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/map/AddressKeyIteratorTest.java index e6af93cbb0..aa0403e16f 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/map/AddressKeyIteratorTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/map/AddressKeyIteratorTest.java @@ -115,7 +115,7 @@ public class AddressKeyIteratorTest extends AbstractGhidraHeadedIntegrationTest @Test public void testIterator0() throws Exception { - AddressKeyIterator it = new AddressKeyIterator(); + AddressKeyIterator it = AddressKeyIterator.EMPTY_ITERATOR; assertTrue(!it.hasNext()); assertTrue(!it.hasPrevious()); try { @@ -123,12 +123,14 @@ public class AddressKeyIteratorTest extends AbstractGhidraHeadedIntegrationTest Assert.fail(); } catch (NoSuchElementException e) { + // expected } try { it.previous(); Assert.fail(); } catch (NoSuchElementException e) { + // expected } } 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 f4b2208b9e..f4a9215952 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 @@ -1174,6 +1174,9 @@ public class CodeManager implements ErrorHandler, ManagerDB { if (addrSetView == null) { addrSetView = program.getMemory(); } + else if (addrSetView.isEmpty()) { + return CodeUnitIterator.EMPTY_ITERATOR; + } if (property.equals(CodeUnit.COMMENT_PROPERTY)) { try { @@ -1219,7 +1222,8 @@ public class CodeManager implements ErrorHandler, ManagerDB { /** * Get a forward iterator over code units that have comments of the given type. * @param commentType comment type defined in CodeUnit - * @param set address set + * @param set address set (null for all defined memory) + * @return code unit iterator */ public CodeUnitIterator getCommentCodeUnitIterator(int commentType, AddressSetView set) { CodeUnitIterator it = getCodeUnitIterator(CodeUnit.COMMENT_PROPERTY, set, true); @@ -1229,10 +1233,15 @@ public class CodeManager implements ErrorHandler, ManagerDB { /** * Get a forward iterator over addresses that have comments of the given type. * @param commentType comment type defined in CodeUnit - * @param set address set + * @param set address set (null for all defined memory) + * @param forward true to iterate in the direction of increasing addresses. + * @return address iterator */ public AddressIterator getCommentAddressIterator(int commentType, AddressSetView set, boolean forward) { + if (set != null && set.isEmpty()) { + return AddressIterator.EMPTY_ITERATOR; + } try { AddressKeyIterator keyIter = commentAdapter.getKeys(set, forward); AddressIterator addrIter = @@ -1251,6 +1260,9 @@ public class CodeManager implements ErrorHandler, ManagerDB { * @param forward true to iterate in the direction of increasing addresses. */ public AddressIterator getCommentAddressIterator(AddressSetView addrSet, boolean forward) { + if (addrSet != null && addrSet.isEmpty()) { + return AddressIterator.EMPTY_ITERATOR; + } try { AddressKeyIterator keyIter = commentAdapter.getKeys(addrSet, forward); return new AddressKeyAddressIterator(keyIter, forward, addrMap, program); @@ -1632,6 +1644,9 @@ public class CodeManager implements ErrorHandler, ManagerDB { searchSet = new AddressSet( initializedMemoryOnly ? mem.getLoadedAndInitializedAddressSet() : mem); } + else if (set.isEmpty()) { + return set; + } else { searchSet = new AddressSet(set); searchSet = searchSet.intersect( @@ -1855,13 +1870,19 @@ public class CodeManager implements ErrorHandler, ManagerDB { * Returns the next undefined data whose min address falls within the address set * searching in the forward direction {@code (e.g., 0 -> 0xfff).} * - * @param set the address set to look within. + * @param set the address set to look within (required). * @param monitor the current monitor. * @return Data the first undefined data within the address set, or null if there is none. */ public Data getFirstUndefinedData(AddressSetView set, TaskMonitor monitor) { + if (set.isEmpty()) { + return null; + } Memory mem = program.getMemory(); set = mem.intersect(set); + if (set.isEmpty()) { + return null; + } int i = 0; CodeUnitIterator it = getCodeUnits(set, true); @@ -2172,8 +2193,7 @@ public class CodeManager implements ErrorHandler, ManagerDB { private boolean exceedsLimitOn64BitAddressSegments(List
longSegmentAddressList, Address toAddr) { long maskedOffset = toAddr.getOffset() & 0xffffffff00000000L; - for (int i = 0; i < longSegmentAddressList.size(); i++) { - Address address = longSegmentAddressList.get(i); + for (Address address : longSegmentAddressList) { long offset = address.getOffset(); if ((offset & 0xffffffff00000000L) == maskedOffset) { return false; @@ -2419,6 +2439,7 @@ public class CodeManager implements ErrorHandler, ManagerDB { * @param forward if true the iterator returns all codeUnits from the given * start address to the end of the program, otherwise it returns all codeUnits * from the given start address to the start of the program. + * @return code unit iterator */ public CodeUnitIterator getCodeUnits(Address start, boolean forward) { @@ -2439,6 +2460,10 @@ public class CodeManager implements ErrorHandler, ManagerDB { bounds = program.getAddressFactory().getAddressSet(min, start); } + AddressSet set = mem.intersect(bounds); + if (set.isEmpty()) { + return CodeUnitIterator.EMPTY_ITERATOR; + } return new CodeUnitRecordIterator(this, getInstructions(start, forward), getDefinedData(start, forward), mem.intersect(bounds), forward); } @@ -2447,10 +2472,15 @@ public class CodeManager implements ErrorHandler, ManagerDB { * Returns an iterator over all codeUnits in the given addressSet. The iterator * will go from the lowest address to the largest or from the largest to the * lowest depending on the forward parameter. + * @param set the memory address set over which code units should be iterated (required) * @param forward determines if the iterator goes from lowest address to highest * or the other way around. + * @return code unit iterator */ public CodeUnitIterator getCodeUnits(AddressSetView set, boolean forward) { + if (set.isEmpty()) { + return CodeUnitIterator.EMPTY_ITERATOR; + } return new CodeUnitRecordIterator(this, getInstructions(set, forward), getDefinedData(set, forward), set, forward); } @@ -2677,9 +2707,8 @@ public class CodeManager implements ErrorHandler, ManagerDB { } } } - for (int i = 0; i < addrs.size(); i++) { + for (Address addr : addrs) { monitor.checkCanceled(); - Address addr = addrs.get(i); clearCodeUnits(addr, addr, false, monitor); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/CodeUnitRecordIterator.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/CodeUnitRecordIterator.java index f0be23e6c9..f0c3916fdd 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/CodeUnitRecordIterator.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/CodeUnitRecordIterator.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +15,11 @@ */ package ghidra.program.database.code; +import java.util.Iterator; + import ghidra.program.model.address.*; import ghidra.program.model.listing.*; -import java.util.Iterator; - /** * Combines an Instruction iterator and Data iterator into a codeunit iterator */ @@ -42,7 +41,7 @@ class CodeUnitRecordIterator implements CodeUnitIterator { * @param codeMgr the code managaer * @param instIt the instruction iterator * @param dataIt the data iterator - * @param set the address set + * @param set the address set (required) * @param forward the iterator direction */ CodeUnitRecordIterator(CodeManager codeMgr, InstructionIterator instIt, DataIterator dataIt, diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/CommentsDBAdapter.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/CommentsDBAdapter.java index 52ec0066a9..6a444ab350 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/CommentsDBAdapter.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/CommentsDBAdapter.java @@ -235,7 +235,7 @@ abstract class CommentsDBAdapter { /** * Returns an address key iterator over the given address set in the given direction. - * @param addrSetView the set to iterator over. + * @param addrSetView the set to iterator over (null for all defined memory). * @param forward the direction to iterate. */ abstract AddressKeyIterator getKeys(AddressSetView set, boolean forward) throws IOException; diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressIndexKeyIterator.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressIndexKeyIterator.java index 1b4b1fe178..2654b2fa27 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressIndexKeyIterator.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressIndexKeyIterator.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,13 +15,12 @@ */ package ghidra.program.database.map; -import ghidra.program.model.address.*; - import java.io.IOException; import java.util.List; import java.util.NoSuchElementException; import db.*; +import ghidra.program.model.address.*; /** * Iterator of indexed fields that are addresses. The longs returned are the address longs. @@ -95,7 +93,7 @@ public class AddressIndexKeyIterator implements DBLongIterator { * @param addrMap the address map * @param absolute if true, only absolute memory address encodings are considered, otherwise * only standard/relocatable address encodings are considered. - * @param set the set of addresses to iterator over. + * @param set the set of addresses to iterator over or null for all addresses. * @param atStart if true, iterates forward, otherwise iterates backwards. * @throws IOException if a database io error occurs. */ @@ -192,6 +190,7 @@ public class AddressIndexKeyIterator implements DBLongIterator { /** * @see db.DBLongIterator#hasNext() */ + @Override public boolean hasNext() throws IOException { if (it == null) { return false; @@ -217,6 +216,7 @@ public class AddressIndexKeyIterator implements DBLongIterator { /** * @see db.DBLongIterator#hasPrevious() */ + @Override public boolean hasPrevious() throws IOException { if (it == null) { return false; @@ -242,6 +242,7 @@ public class AddressIndexKeyIterator implements DBLongIterator { /** * @see db.DBLongIterator#next() */ + @Override public long next() throws IOException { if (hasNext()) { return ((LongField) it.next()).getLongValue(); @@ -252,6 +253,7 @@ public class AddressIndexKeyIterator implements DBLongIterator { /** * @see db.DBLongIterator#previous() */ + @Override public long previous() throws IOException { if (hasPrevious()) { return ((LongField) it.previous()).getLongValue(); @@ -262,6 +264,7 @@ public class AddressIndexKeyIterator implements DBLongIterator { /** * @see db.DBLongIterator#delete() */ + @Override public boolean delete() throws IOException { if (it != null) { return it.delete(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressIndexPrimaryKeyIterator.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressIndexPrimaryKeyIterator.java index 6304f736f8..38fd096d83 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressIndexPrimaryKeyIterator.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressIndexPrimaryKeyIterator.java @@ -93,7 +93,7 @@ public class AddressIndexPrimaryKeyIterator implements DBFieldIterator { * @param addrMap the address map * @param absolute if true, only absolute memory address encodings are considered, otherwise * only standard/relocatable address encodings are considered. - * @param set the set of addresses to iterator over. + * @param set the set of addresses to iterator over or null for all addresses. * @param atStart if true, iterates forward, otherwise iterates backwards. * @throws IOException if a database io error occurs. */ diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressKeyAddressIterator.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressKeyAddressIterator.java index 6a61eddee4..e9f1227e25 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressKeyAddressIterator.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressKeyAddressIterator.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,15 +15,14 @@ */ package ghidra.program.database.map; -import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressIterator; - import java.io.IOException; import java.util.Iterator; import java.util.NoSuchElementException; import db.DBLongIterator; import db.util.ErrorHandler; +import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressIterator; /** * Converts an AddressKeyIterator or an addressKeyAddressIterator into an AddressIterator @@ -39,6 +37,7 @@ public class AddressKeyAddressIterator implements AddressIterator { /** * Constructor. * @param keyIter address key iterator, may be null. All long values must decode properly with the specified addrMap. + * @param forward true to iterate in the direction of increasing addresses. * @param addrMap address map * @param errHandler IO error handler (may be null) */ diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressKeyIterator.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressKeyIterator.java index 47678c2ad1..e58fad5acd 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressKeyIterator.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressKeyIterator.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,14 +15,13 @@ */ package ghidra.program.database.map; -import ghidra.program.model.address.*; - import java.io.IOException; import java.util.List; import java.util.NoSuchElementException; import db.DBLongIterator; import db.Table; +import ghidra.program.model.address.*; /** * Iterator of primary keys that are addresses. The longs returned are the address longs. @@ -31,6 +29,8 @@ import db.Table; public class AddressKeyIterator implements DBLongIterator { + public static final AddressKeyIterator EMPTY_ITERATOR = new AddressKeyIterator(); + private Table table; private List keyRangeList; @@ -40,7 +40,7 @@ public class AddressKeyIterator implements DBLongIterator { /** * Constructs an empty iterator. */ - public AddressKeyIterator() { + private AddressKeyIterator() { } /** @@ -96,7 +96,7 @@ public class AddressKeyIterator implements DBLongIterator { * Memory addresses encoded as Absolute are not included. * @param table the database table key by addresses * @param addrMap the address map - * @param set the address set to iterator over + * @param set the address set to iterator over (may be null for all defined memory) * @param startAddr the address at which to position the iterator, can be null. The exact * position of the iterator depends on the before parameter. * @param before positions the iterator before the start address,otherwise after @@ -115,7 +115,7 @@ public class AddressKeyIterator implements DBLongIterator { * @param addrMap the address map * @param absolute if true, only absolute memory address encodings are considered, otherwise * only standard/relocatable address encodings are considered. - * @param set the address set to iterator over + * @param set the address set to iterator over or null for all addresses. * @param startAddr the address at which to position the iterator, can be null. The exact * position of the iterator depends on the before parameter. * @param before positions the iterator before the start address,otherwise after @@ -180,6 +180,7 @@ public class AddressKeyIterator implements DBLongIterator { /** * @see db.DBLongIterator#hasNext() */ + @Override public boolean hasNext() throws IOException { if (it == null) { return false; @@ -203,6 +204,7 @@ public class AddressKeyIterator implements DBLongIterator { /** * @see db.DBLongIterator#hasPrevious() */ + @Override public boolean hasPrevious() throws IOException { if (it == null) { return false; @@ -226,6 +228,7 @@ public class AddressKeyIterator implements DBLongIterator { /** * @see db.DBLongIterator#next() */ + @Override public long next() throws IOException { if (hasNext()) { return it.next(); @@ -236,6 +239,7 @@ public class AddressKeyIterator implements DBLongIterator { /** * @see db.DBLongIterator#previous() */ + @Override public long previous() throws IOException { if (hasPrevious()) { return it.previous(); @@ -246,6 +250,7 @@ public class AddressKeyIterator implements DBLongIterator { /** * @see db.DBLongIterator#delete() */ + @Override public boolean delete() throws IOException { if (it != null) { return it.delete(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressKeyRecordIterator.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressKeyRecordIterator.java index ba8100b658..c3f319f0fc 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressKeyRecordIterator.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressKeyRecordIterator.java @@ -15,13 +15,12 @@ */ package ghidra.program.database.map; -import ghidra.program.model.address.*; - import java.io.IOException; import java.util.Iterator; import java.util.List; import db.*; +import ghidra.program.model.address.*; /** * Returns a RecordIterator over records that are address keyed. Various constructors allow @@ -116,7 +115,7 @@ public class AddressKeyRecordIterator implements RecordIterator { * @param addrMap the address map * @param absolute if true, only absolute memory address encodings are considered, otherwise * only standard/relocatable address encodings are considered. - * @param set the address set to iterate over. + * @param set the address set to iterate over or null for all addresses * @param startAddr the address at which to position the iterator. The iterator will be positioned * either before or after the start address depending on the before parameter. If this parameter * is null, then the iterator will start either before the min address or after the max address @@ -174,6 +173,7 @@ public class AddressKeyRecordIterator implements RecordIterator { /** * @see db.RecordIterator#hasNext() */ + @Override public boolean hasNext() throws IOException { if (it == null) { return false; @@ -197,6 +197,7 @@ public class AddressKeyRecordIterator implements RecordIterator { /** * @see db.RecordIterator#hasPrevious() */ + @Override public boolean hasPrevious() throws IOException { if (it == null) { return false; @@ -220,6 +221,7 @@ public class AddressKeyRecordIterator implements RecordIterator { /** * @see db.RecordIterator#next() */ + @Override public DBRecord next() throws IOException { if (hasNext()) { return it.next(); @@ -230,6 +232,7 @@ public class AddressKeyRecordIterator implements RecordIterator { /** * @see db.RecordIterator#previous() */ + @Override public DBRecord previous() throws IOException { if (hasPrevious()) { return it.previous(); @@ -240,6 +243,7 @@ public class AddressKeyRecordIterator implements RecordIterator { /** * @see db.RecordIterator#delete() */ + @Override public boolean delete() throws IOException { if (it != null) { return it.delete(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressMap.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressMap.java index 3f444c2c75..e2d1c143df 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressMap.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/AddressMap.java @@ -65,7 +65,7 @@ public interface AddressMap { /** * Search for addr within the "sorted" keyRangeList and return the index of the * keyRange which contains the specified addr. - * @param keyRangeList + * @param keyRangeList key range list to search * @param addr address or null * @return index of the keyRange within the keyRangeList which contains addr * if it is contained in the list; otherwise, (-(insertion point) - 1). @@ -100,7 +100,7 @@ public interface AddressMap { * Generates a properly ordered list of database key ranges for a * a specified address set. If absolute encodings are requested, * only memory addresses will be included. - * @param set address set or null for all real address. + * @param set address set or null for all addresses. May not be null if create is true. * @param create true if a new keys may be generated, otherwise returned * key-ranges will be limited to those already defined. * @return "sorted" list of KeyRange objects @@ -113,12 +113,14 @@ public interface AddressMap { * "absoluteEncoding" method. If the program's default address space is segmented (i.e., SegmentedAddressSpace). * the address returned will be always be normalized to defined segmented memory blocks if possible. * @param value the long value to convert to an address. + * @return address decoded from long */ public Address decodeAddress(long value); /** * Returns the address factory associated with this map. * Null may be returned if map not associated with a specific address factory. + * @return associated {@link AddressFactory} or null */ public AddressFactory getAddressFactory(); @@ -140,7 +142,7 @@ public interface AddressMap { * Generates a properly ordered list of database key ranges for a * a specified address set. If absolute encodings are requested, * only memory addresses will be included. - * @param set address set or null for all real address. + * @param set address set or null for all addresses. May not be null if create is true. * @param absolute if true, absolute key encodings are returned, otherwise * standard/relocatable address key encodings are returned. * @param create true if a new keys may be generated, otherwise returned diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/properties/PropertyMapDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/properties/PropertyMapDB.java index aaf6bff622..05715ab767 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/properties/PropertyMapDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/properties/PropertyMapDB.java @@ -434,7 +434,7 @@ public abstract class PropertyMapDB implements PropertyMap { /** * Get an iterator over the long address keys which contain a property value. - * @param set + * @param set addresses over which to iterate (null indicates all defined memory regions) * @param atStart true if the iterator should be positioned at the start * of the range * @return long address iterator. @@ -442,9 +442,8 @@ public abstract class PropertyMapDB implements PropertyMap { */ public AddressKeyIterator getAddressKeyIterator(AddressSetView set, boolean atStart) throws IOException { - - if (propertyTable == null) { - return new AddressKeyIterator(); + if (propertyTable == null || (set != null && set.isEmpty())) { + return AddressKeyIterator.EMPTY_ITERATOR; } if (atStart) { return new AddressKeyIterator(propertyTable, addrMap, set, set.getMinAddress(), true); @@ -463,7 +462,7 @@ public abstract class PropertyMapDB implements PropertyMap { throws IOException { if (propertyTable == null) { - return new AddressKeyIterator(); + return AddressKeyIterator.EMPTY_ITERATOR; } return new AddressKeyIterator(propertyTable, addrMap, start, before); } @@ -481,7 +480,7 @@ public abstract class PropertyMapDB implements PropertyMap { throws IOException { if (propertyTable == null) { - return new AddressKeyIterator(); + return AddressKeyIterator.EMPTY_ITERATOR; } if (atStart) { return new AddressKeyIterator(propertyTable, addrMap, start, end, start, true); @@ -561,8 +560,8 @@ public abstract class PropertyMapDB implements PropertyMap { */ @Override public AddressIterator getPropertyIterator(AddressSetView asv, boolean forward) { - if (propertyTable == null) { - return new EmptyAddressIterator(); + if (propertyTable == null || (asv != null && asv.isEmpty())) { + return AddressIterator.EMPTY_ITERATOR; } AddressKeyIterator keyIter = null; try { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/ReferenceDBManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/ReferenceDBManager.java index d773e80928..a8c5aba723 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/ReferenceDBManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/references/ReferenceDBManager.java @@ -946,6 +946,9 @@ public class ReferenceDBManager implements ReferenceManager, ManagerDB, ErrorHan @Override public AddressIterator getReferenceDestinationIterator(AddressSetView addrSet, boolean forward) { + if (addrSet != null && addrSet.isEmpty()) { + return AddressIterator.EMPTY_ITERATOR; + } try { return toAdapter.getToIterator(addrSet, forward); } @@ -973,6 +976,9 @@ public class ReferenceDBManager implements ReferenceManager, ManagerDB, ErrorHan @Override public AddressIterator getReferenceSourceIterator(AddressSetView addrSet, boolean forward) { + if (addrSet != null && addrSet.isEmpty()) { + return AddressIterator.EMPTY_ITERATOR; + } try { return fromAdapter.getFromIterator(addrSet, forward); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/AddressSetFilteredSymbolIterator.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/AddressSetFilteredSymbolIterator.java index f927a33cde..e4c2068d19 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/AddressSetFilteredSymbolIterator.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/symbol/AddressSetFilteredSymbolIterator.java @@ -44,7 +44,7 @@ class AddressSetFilteredSymbolIterator implements SymbolIterator { /** * Construct a new AddressSetFilteredSymbolIterator. * @param symbolMgr the symbol manager - * @param set the address set to iterator over. + * @param set the address set to iterator over (required). * @param query the query to use as a filter * @param forward the direction of the iterator. */ 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 9f946099fc..55307aafbe 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 @@ -1204,6 +1204,9 @@ public class SymbolManager implements SymbolTable, ManagerDB { @Override public SymbolIterator getPrimarySymbolIterator(AddressSetView set, boolean forward) { + if (set.isEmpty()) { + return SymbolIterator.EMPTY_ITERATOR; + } Query query1 = new FieldMatchQuery(SymbolDatabaseAdapter.SYMBOL_DATA2_COL, new IntField(1)); Query query2 = new FieldMatchQuery(SymbolDatabaseAdapter.SYMBOL_TYPE_COL, new ByteField(SymbolType.LABEL.getID())); @@ -1216,6 +1219,9 @@ public class SymbolManager implements SymbolTable, ManagerDB { @Override public SymbolIterator getSymbols(AddressSetView set, SymbolType type, boolean forward) { + if (set.isEmpty()) { + return SymbolIterator.EMPTY_ITERATOR; + } Query query = new FieldMatchQuery(SymbolDatabaseAdapter.SYMBOL_TYPE_COL, new ByteField(type.getID())); return new AddressSetFilteredSymbolIterator(this, set, query, forward); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressIterator.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressIterator.java index 9f25ec93e2..8755135097 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressIterator.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/address/AddressIterator.java @@ -16,6 +16,7 @@ package ghidra.program.model.address; import java.util.Iterator; +import java.util.NoSuchElementException; import util.CollectionUtils; @@ -30,20 +31,24 @@ import util.CollectionUtils; */ public interface AddressIterator extends Iterator
, Iterable
{ - /** - * Get the next address. - * - * @return the next address in the iteration. - */ - @Override - public Address next(); - /** - * Checks if there is a next address in the iteration. - * - * @return true if there is a next address. - */ - @Override - public boolean hasNext(); + public static final AddressIterator EMPTY_ITERATOR = new AddressIterator() { + + @Override + public boolean hasNext() { + return false; + } + + @Override + public Address next() { + throw new NoSuchElementException(); + } + + @Override + public Iterator
iterator() { + return this; + } + + }; } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/CodeUnitIterator.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/CodeUnitIterator.java index 685ee16b42..686f0b00a6 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/CodeUnitIterator.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/CodeUnitIterator.java @@ -26,14 +26,35 @@ import util.CollectionUtils; */ public interface CodeUnitIterator extends Iterator, Iterable { + public static final CodeUnitIterator EMPTY_ITERATOR = new CodeUnitIterator() { + + @Override + public boolean hasNext() { + return false; + } + + @Override + public CodeUnit next() { + return null; + } + + @Override + public Iterator iterator() { + return this; + } + + }; + /** - * Returns true if the iteration has more elements. + * Return true if there is a next CodeUnit. */ @Override public boolean hasNext(); /** - * Return the next code unit in the iteration. + * Get the next CodeUnit or null if no more CodeUnits. + *

NOTE: This deviates from the standard {@link Iterator} interface + * by returning null instead of throwing an exception. */ @Override public CodeUnit next(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/Listing.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/Listing.java index 2ae6a3253c..6d2e66f220 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/Listing.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/listing/Listing.java @@ -213,7 +213,7 @@ public interface Listing { * addresses are contained in the given address set will be returned by the * iterator. * - * @param addrSet the AddressRangeSet to iterate over. + * @param addrSet the AddressRangeSet to iterate over (required). * @param forward true means get iterator in forward direction * @return a CodeUnitIterator that is restricted to the give * AddressRangeSet. diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/ReferenceManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/ReferenceManager.java index 8b6026b19a..9af6c9d1dd 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/ReferenceManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/ReferenceManager.java @@ -288,7 +288,7 @@ public interface ReferenceManager { /** * Returns an iterator over all addresses that are the "From" address in a * reference, restricted by the given address set. - * @param addrSet the set of address to restrict the iterator. + * @param addrSet the set of address to restrict the iterator or null for all addresses. * @param forward true means to iterate in the forward direction */ public AddressIterator getReferenceSourceIterator(AddressSetView addrSet, boolean forward); @@ -304,7 +304,7 @@ public interface ReferenceManager { /** * Returns an iterator over all addresses that are the "To" address in a * memory reference, restricted by the given address set. - * @param addrSet the set of address to restrict the iterator. + * @param addrSet the set of address to restrict the iterator or null for all addresses. * @param forward true means to iterate in the forward direction */ public AddressIterator getReferenceDestinationIterator(AddressSetView addrSet, boolean forward); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolIterator.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolIterator.java index ab4ea9b8b8..f24454a74e 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolIterator.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolIterator.java @@ -25,13 +25,37 @@ import util.CollectionUtils; * @see CollectionUtils#asIterable */ public interface SymbolIterator extends Iterator, Iterable { + + public static final SymbolIterator EMPTY_ITERATOR = new SymbolIterator() { + + @Override + public Iterator iterator() { + return this; + } + + @Override + public Symbol next() { + return null; + } + + @Override + public boolean hasNext() { + return false; + } + }; + /** * Return true if there is a next symbol. */ + @Override public boolean hasNext(); /** - * Get the next symbol. + * Get the next symbol or null if no more symbols. + *

NOTE: This deviates from the standard {@link Iterator} interface + * by returning null instead of throwing an exception. */ + @Override public Symbol next(); + } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolTable.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolTable.java index 22fdfd0f20..c0553ce9cc 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolTable.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/symbol/SymbolTable.java @@ -420,7 +420,7 @@ public interface SymbolTable { /** * Returns all the symbols of the given type within the given address set. - * @param set the address set in which to look for symbols of the given type + * @param set the address set in which to look for symbols of the given type (required). * @param type the SymbolType to look for. * @param forward the direction within the addressSet to search * @return symbol iterator @@ -500,7 +500,7 @@ public interface SymbolTable { /** * Get an iterator over symbols at addresses in the given addressSet - * @param asv the set of address over which to iterate symbols. + * @param asv the set of address over which to iterate symbols (required). * @param forward true means the iterator is in the forward direction * @return symbol iterator */