diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ConstantPropagationAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ConstantPropagationAnalyzer.java index b8368f46ad..64715c328c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ConstantPropagationAnalyzer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ConstantPropagationAnalyzer.java @@ -332,15 +332,13 @@ public class ConstantPropagationAnalyzer extends AbstractAnalyzer { if (resultSet != null) { // null sometimes when cancelled // set.getMinAddress() and start may not be in the same segment if (!start.equals(set.getMinAddress())) { - set = set.subtract(new AddressSet(set.getMinAddress(), start)); + set = AddressSetView.trimStart(set, start); } set = set.subtract(resultSet); } } } - - /** * Analyze a single location * diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/PseudoDisassembler.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/PseudoDisassembler.java index eecef33e33..926d2268f4 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/PseudoDisassembler.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/PseudoDisassembler.java @@ -19,39 +19,14 @@ import java.math.BigInteger; import java.util.ArrayList; import java.util.Iterator; -import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressIterator; -import ghidra.program.model.address.AddressOutOfBoundsException; -import ghidra.program.model.address.AddressOverflowException; -import ghidra.program.model.address.AddressSet; -import ghidra.program.model.address.AddressSetView; +import ghidra.program.model.address.*; import ghidra.program.model.data.DataType; import ghidra.program.model.data.PointerDataType; -import ghidra.program.model.lang.InstructionPrototype; -import ghidra.program.model.lang.InsufficientBytesException; -import ghidra.program.model.lang.Language; -import ghidra.program.model.lang.Register; -import ghidra.program.model.lang.RegisterValue; -import ghidra.program.model.lang.UnknownContextException; -import ghidra.program.model.lang.UnknownInstructionException; -import ghidra.program.model.listing.ContextChangeException; -import ghidra.program.model.listing.Data; -import ghidra.program.model.listing.Function; -import ghidra.program.model.listing.Instruction; -import ghidra.program.model.listing.Program; -import ghidra.program.model.listing.ProgramContext; -import ghidra.program.model.mem.ByteMemBufferImpl; -import ghidra.program.model.mem.DumbMemBufferImpl; -import ghidra.program.model.mem.MemBuffer; -import ghidra.program.model.mem.Memory; -import ghidra.program.model.mem.MemoryAccessException; -import ghidra.program.model.mem.MemoryBlock; +import ghidra.program.model.lang.*; +import ghidra.program.model.listing.*; +import ghidra.program.model.mem.*; import ghidra.program.model.pcode.PcodeOp; -import ghidra.program.model.symbol.FlowType; -import ghidra.program.model.symbol.RefType; -import ghidra.program.model.symbol.Reference; -import ghidra.program.model.symbol.Symbol; -import ghidra.program.model.symbol.SymbolType; +import ghidra.program.model.symbol.*; /** * PseudoDisassembler.java @@ -449,8 +424,8 @@ public class PseudoDisassembler { byte[] ptrbytes = new byte[pointerSize]; if (memory.getBytes(tempAddr, ptrbytes) == ptrbytes.length) { boolean allZero = true; - for (int i = 0; i < ptrbytes.length; i++) { - if (ptrbytes[i] != 0) { + for (byte ptrbyte : ptrbytes) { + if (ptrbyte != 0) { allZero = false; break; } @@ -776,23 +751,24 @@ public class PseudoDisassembler { } } if (flows != null && flows.length > 0) { - for (int j = 0; j < flows.length; j++) { + for (Address flow : flows) { // does this reference a valid function? if (program != null) { - Symbol[] syms = program.getSymbolTable().getSymbols(flows[j]); - for (int k = 0; k < syms.length; k++) { - if (syms[k].getSymbolType() == SymbolType.FUNCTION) { + Symbol[] syms = program.getSymbolTable().getSymbols(flow); + for (Symbol sym : syms) { + if (sym.getSymbolType() == SymbolType.FUNCTION) { didCallValidSubroutine = true; break; } } } // if respecting execute flag on memory, test to make sure we did flow into non-execute memory - if (respectExecuteFlag && !execSet.isEmpty() && !execSet.contains(flows[j])) { - if (!flows[j].isExternalAddress()) { - MemoryBlock block = memory.getBlock(flows[j]); + if (respectExecuteFlag && !execSet.isEmpty() && !execSet.contains(flow)) { + if (!flow.isExternalAddress()) { + MemoryBlock block = memory.getBlock(flow); // flowing into non-executable, but readable memory is bad - if (block != null && block.isRead()) { + if (block != null && block.isRead() && + !MemoryBlock.EXTERNAL_BLOCK_NAME.equals(block.getName())) { return false; } } @@ -872,8 +848,8 @@ public class PseudoDisassembler { */ private boolean isReallyReturn(Instruction instr) { PcodeOp[] pcode = instr.getPcode(); - for (int i = 0; i < pcode.length; i++) { - if (pcode[i].getOpcode() == PcodeOp.RETURN) { + for (PcodeOp element : pcode) { + if (element.getOpcode() == PcodeOp.RETURN) { return true; } } 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 2ede719a29..87200ae261 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 @@ -235,4 +235,57 @@ public interface AddressSetView extends Iterable { * @return the first address that is contained in this set and the given set. */ public Address findFirstAddressInCommon(AddressSetView set); + + /** + * Trim address set removing all addresses less-than-or-equal to specified + * address based upon {@link Address#compareTo(Address)} behavior. + * The address set may contain address ranges from multiple + * address spaces. + * @param set address set to be trimmed + * @param addr trim point. Only addresses greater than this address will be returned. + * @return trimmed address set view + */ + public static AddressSetView trimStart(AddressSetView set, Address addr) { + AddressSet trimmedSet = new AddressSet(); + AddressRangeIterator addressRanges = set.getAddressRanges(); + while (addressRanges.hasNext()) { + AddressRange range = addressRanges.next(); + Address rangeMin = range.getMinAddress(); + Address rangeMax = range.getMaxAddress(); + if (rangeMin.compareTo(addr) > 0) { + trimmedSet.add(range); + } + else if (rangeMax.compareTo(addr) > 0) { + trimmedSet.add(addr.next(), rangeMax); + + } + } + return trimmedSet; + } + + /** + * Trim address set removing all addresses greater-than-or-equal to specified + * address based upon {@link Address#compareTo(Address)} behavior. + * The address set may contain address ranges from multiple + * address spaces. + * @param set address set to be trimmed + * @param addr trim point. Only addresses less than this address will be returned. + * @return trimmed address set view + */ + public static AddressSetView trimEnd(AddressSetView set, Address addr) { + AddressSet trimmedSet = new AddressSet(); + AddressRangeIterator addressRanges = set.getAddressRanges(); + while (addressRanges.hasNext()) { + AddressRange range = addressRanges.next(); + Address rangeMin = range.getMinAddress(); + Address rangeMax = range.getMaxAddress(); + if (rangeMax.compareTo(addr) < 0) { + trimmedSet.add(range); + } + else if (rangeMin.compareTo(addr) < 0) { + trimmedSet.add(rangeMin, addr.previous()); + } + } + return trimmedSet; + } } diff --git a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/address/AddressSetTest.java b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/address/AddressSetTest.java index 80373f2ea7..e2d890a892 100644 --- a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/address/AddressSetTest.java +++ b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/model/address/AddressSetTest.java @@ -15,8 +15,7 @@ */ package ghidra.program.model.address; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import java.util.Iterator; @@ -807,6 +806,44 @@ public class AddressSetTest extends AbstractGenericTest { Assert.assertEquals(set, newSet); } + @Test + public void testTrimStart() { + AddressSet set = set(0x10, 0x20, 0x30, 0x40); + set.add(space2.getAddress(0x10), space2.getAddress(0x20)); + set.add(space2.getAddress(0x30), space2.getAddress(0x40)); + + AddressSetView trimSet = AddressSetView.trimStart(set, addr(0x15)); + + AddressSet expectedSet = set(0x16, 0x20, 0x30, 0x40); + expectedSet.add(space2.getAddress(0x10), space2.getAddress(0x20)); + expectedSet.add(space2.getAddress(0x30), space2.getAddress(0x40)); + assertEquals(expectedSet, trimSet); + + trimSet = AddressSetView.trimStart(set, space2.getAddress(0x15)); + + expectedSet = new AddressSet(space2.getAddress(0x16), space2.getAddress(0x20)); + expectedSet.add(space2.getAddress(0x30), space2.getAddress(0x40)); + assertEquals(expectedSet, trimSet); + } + + @Test + public void testTrimEnd() { + AddressSet set = set(0x10, 0x20, 0x30, 0x40); + set.add(space2.getAddress(0x10), space2.getAddress(0x20)); + set.add(space2.getAddress(0x30), space2.getAddress(0x40)); + + AddressSetView trimSet = AddressSetView.trimEnd(set, addr(0x15)); + + AddressSet expectedSet = set(0x10, 0x14); + assertEquals(expectedSet, trimSet); + + trimSet = AddressSetView.trimEnd(set, space2.getAddress(0x15)); + + expectedSet = set(0x10, 0x20, 0x30, 0x40); + expectedSet.add(space2.getAddress(0x10), space2.getAddress(0x14)); + assertEquals(expectedSet, trimSet); + } + // //// //// public void testSequentialInsertionSpeed() {