Merge remote-tracking branch 'origin/patch'

This commit is contained in:
Ryan Kurtz 2019-11-15 08:55:08 -05:00
commit 05ee2c14b9
5 changed files with 134 additions and 35 deletions

View file

@ -84,9 +84,11 @@ public class SymbolTableCommand extends LoadCommand {
nlistList.add(NList.createNList(reader, is32bit)); nlistList.add(NList.createNList(reader, is32bit));
} }
// sort the entries by the index in the string table, so don't jump around reading // sort the entries by the index in the string table, so don't jump around reading
List<NList> sortedList = nlistList.stream().sorted( List<NList> sortedList = nlistList
(o1, o2) -> o1.getStringTableIndex() - o2.getStringTableIndex()).collect( .stream()
Collectors.toList()); .sorted((o1, o2) -> Integer.valueOf(o1.getStringTableIndex())
.compareTo(Integer.valueOf(o2.getStringTableIndex())))
.collect(Collectors.toList());
// initialize the NList strings from string table // initialize the NList strings from string table
long stringTableOffset = stroff; long stringTableOffset = stroff;

View file

@ -159,9 +159,11 @@ public class DyldCacheLocalSymbolsInfo implements StructConverter {
monitor.incrementProgress(1); monitor.incrementProgress(1);
} }
// sort the entries by the index in the string table, so don't jump around reading // sort the entries by the index in the string table, so don't jump around reading
List<NList> sortedList = nlistList.stream().sorted( List<NList> sortedList = nlistList
(o1, o2) -> o1.getStringTableIndex() - o2.getStringTableIndex()).collect( .stream()
Collectors.toList()); .sorted((o1, o2) -> Integer.valueOf(o1.getStringTableIndex())
.compareTo(Integer.valueOf(o2.getStringTableIndex())))
.collect(Collectors.toList());
// initialize the NList strings from string table // initialize the NList strings from string table
long stringTableOffset = startIndex + stringsOffset; long stringTableOffset = startIndex + stringsOffset;

View file

@ -296,7 +296,6 @@ public class MemoryManagerTest extends AbstractGhidraHeadedIntegrationTest {
block2.setSourceName("Test"); block2.setSourceName("Test");
assertEquals("Test", block2.getSourceName()); assertEquals("Test", block2.getSourceName());
} }
@Test @Test
@ -398,6 +397,90 @@ public class MemoryManagerTest extends AbstractGhidraHeadedIntegrationTest {
transactionID = program.startTransaction("Test"); transactionID = program.startTransaction("Test");
} }
@Test
public void testMemoryMapExecuteSet() throws Exception {
AddressSetView executeSet = mem.getExecuteSet();
assertTrue(executeSet.isEmpty());
MemoryBlock block1 = createBlock("Test1", addr(100), 100);
executeSet = mem.getExecuteSet();
assertTrue(executeSet.isEmpty());
MemoryBlock block2 = createBlock("Test2", addr(300), 100);
executeSet = mem.getExecuteSet();
assertTrue(executeSet.isEmpty());
MemoryBlock block = mem.getBlock("Test1");
executeSet = mem.getExecuteSet();
assertTrue(executeSet.isEmpty());
block.setExecute(false);
executeSet = mem.getExecuteSet();
assertTrue(executeSet.isEmpty());
block.setExecute(true);
executeSet = mem.getExecuteSet();
assertTrue(executeSet.isEmpty() != true);
Address start = block.getStart();
Address end = block.getEnd();
assertTrue(executeSet.contains(start,end));
// non-existent block
block = mem.getBlock("NoExist");
assertNull(block);
program.endTransaction(transactionID, true);
transactionID = program.startTransaction("Test");
// now exists
mem.getBlock("Test1").setName("NoExist");
// Test1 no longer exists
block = mem.getBlock("NoExist");
executeSet = mem.getExecuteSet();
start = block.getStart();
end = block.getEnd();
// should be same block
assertTrue(executeSet.contains(start,end));
block.setExecute(false);
executeSet = mem.getExecuteSet();
assertTrue(executeSet.contains(start,end) == false);
block2.setExecute(true);
Address start2 = block2.getStart();
Address end2 = block2.getEnd();
mem.removeBlock(block2, new TaskMonitorAdapter());
program.endTransaction(transactionID, true);
program.undo();
transactionID = program.startTransaction("Test");
// should be execute set on block2, deleted, then undone
executeSet = mem.getExecuteSet();
assertTrue(executeSet.contains(start2,end2) == false);
// undid set execute block should now be contained
block = mem.getBlock("Test1");
start = block.getStart();
end = block.getEnd();
executeSet = mem.getExecuteSet();
assertTrue(executeSet.contains(start,end));
mem.split(block, addr(150));
block = mem.getBlock("Test1");
executeSet = mem.getExecuteSet();
assertTrue(executeSet.isEmpty() != true);
assertTrue(executeSet.contains(block.getStart(), block.getEnd()));
// remove block that was split, should still be executable memory
start = block.getStart();
end = block.getEnd();
mem.removeBlock(block, new TaskMonitorAdapter());
executeSet = mem.getExecuteSet();
assertTrue(executeSet.isEmpty() != true);
assertTrue(executeSet.contains(start, end) == false);
}
@Test @Test
public void testSave() throws Exception { public void testSave() throws Exception {
MemoryBlock block1 = createBlock("Test1", addr(0), 100); MemoryBlock block1 = createBlock("Test1", addr(0), 100);

View file

@ -95,8 +95,6 @@ public class PseudoDisassembler {
private boolean respectExecuteFlag = false; private boolean respectExecuteFlag = false;
private AddressSetView executeSet;
/** /**
* Create a pseudo disassembler for the given program. * Create a pseudo disassembler for the given program.
*/ */
@ -111,18 +109,6 @@ public class PseudoDisassembler {
this.programContext = program.getProgramContext(); this.programContext = program.getProgramContext();
} }
/**
* @return cached addressSet of executable memory blocks
*/
private AddressSetView getExecuteSet() {
if (executeSet != null) {
return executeSet;
}
executeSet = memory.getExecuteSet();
return executeSet;
}
/** /**
* Set the maximum number of instructions to check * Set the maximum number of instructions to check
@ -617,6 +603,7 @@ public class PseudoDisassembler {
boolean allowExistingInstructions, boolean mustTerminate) { boolean allowExistingInstructions, boolean mustTerminate) {
AddressSet body = new AddressSet(); AddressSet body = new AddressSet();
AddressSet instrStarts = new AddressSet(); AddressSet instrStarts = new AddressSet();
AddressSetView execSet = memory.getExecuteSet();
if (hasLowBitCodeModeInAddrValues(program)) { if (hasLowBitCodeModeInAddrValues(program)) {
entryPoint = setTargeContextForDisassembly(procContext, entryPoint); entryPoint = setTargeContextForDisassembly(procContext, entryPoint);
@ -801,7 +788,6 @@ public class PseudoDisassembler {
} }
} }
// if respecting execute flag on memory, test to make sure we did flow into non-execute memory // if respecting execute flag on memory, test to make sure we did flow into non-execute memory
AddressSetView execSet = getExecuteSet();
if (respectExecuteFlag && !execSet.isEmpty() && !execSet.contains(flows[j])) { if (respectExecuteFlag && !execSet.isEmpty() && !execSet.contains(flows[j])) {
if (!flows[j].isExternalAddress()) { if (!flows[j].isExternalAddress()) {
MemoryBlock block = memory.getBlock(flows[j]); MemoryBlock block = memory.getBlock(flows[j]);
@ -902,8 +888,8 @@ public class PseudoDisassembler {
} }
// check that body does not wander into non-executable memory // check that body does not wander into non-executable memory
AddressSetView execSet = getExecuteSet(); AddressSetView execSet = memory.getExecuteSet();
if (respectExecuteFlag && !execSet.isEmpty() && !body.subtract(execSet).isEmpty()) { if (respectExecuteFlag && !execSet.isEmpty() && !execSet.contains(body)) {
return false; return false;
} }
@ -914,8 +900,9 @@ public class PseudoDisassembler {
return false; return false;
} }
boolean canHaveOffcutEntry = hasLowBitCodeModeInAddrValues(program);
AddressSet strictlyBody = body.subtract(starts); AddressSet strictlyBody = body.subtract(starts);
if (hasLowBitCodeModeInAddrValues(program)) { if (canHaveOffcutEntry) {
strictlyBody.deleteRange(entry, entry.add(1)); strictlyBody.deleteRange(entry, entry.add(1));
} }
AddressIterator addrIter = AddressIterator addrIter =

View file

@ -57,11 +57,13 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
private AddressSet addrSet = new AddressSet(); private AddressSet addrSet = new AddressSet();
private AddressSet initializedLoadedAddrSet = new AddressSet(); private AddressSet initializedLoadedAddrSet = new AddressSet();
private AddressSet allInitializedAddrSet = new AddressSet(); private AddressSet allInitializedAddrSet = new AddressSet();
private AddressSetView executeSet = null;
private MemoryBlock lastBlock;// the last accessed block private MemoryBlock lastBlock;// the last accessed block
private LiveMemoryHandler liveMemory; private LiveMemoryHandler liveMemory;
// lazy hashmap of block names to blocks, must be reloaded if blocks are removed or added // lazy hashmap of block names to blocks, must be reloaded if blocks are removed or added
private HashMap<String,MemoryBlock> nameBlockMap = new HashMap<String, MemoryBlock>(); private HashMap<String, MemoryBlock> nameBlockMap = new HashMap<String, MemoryBlock>();
private final static MemoryBlock NoBlock = new MemoryBlockStub(); // placeholder for no block, not given out private final static MemoryBlock NoBlock = new MemoryBlockStub(); // placeholder for no block, not given out
Lock lock; Lock lock;
@ -187,6 +189,7 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
blocks = newBlocks; blocks = newBlocks;
addrMap.memoryMapChanged(this); addrMap.memoryMapChanged(this);
nameBlockMap = new HashMap<>(); nameBlockMap = new HashMap<>();
executeSet = null;
} }
public void setLanguage(Language newLanguage) { public void setLanguage(Language newLanguage) {
@ -248,7 +251,7 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
@Override @Override
public AddressSetView getAllInitializedAddressSet() { public AddressSetView getAllInitializedAddressSet() {
return allInitializedAddrSet; return new AddressSetViewAdapter(allInitializedAddrSet);
} }
/** /**
@ -259,7 +262,7 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
if (liveMemory != null) { if (liveMemory != null) {
return this;//all memory is initialized! return this;//all memory is initialized!
} }
return initializedLoadedAddrSet; return new AddressSetViewAdapter(initializedLoadedAddrSet);
} }
void checkMemoryWrite(MemoryBlockDB block, Address start, long length) void checkMemoryWrite(MemoryBlockDB block, Address start, long length)
@ -393,9 +396,12 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
if (program != null) { if (program != null) {
program.setChanged(ChangeManager.DOCR_MEMORY_BLOCK_CHANGED, block, null); program.setChanged(ChangeManager.DOCR_MEMORY_BLOCK_CHANGED, block, null);
} }
// name could have changed // name could have changed
nameBlockMap = new HashMap<>(); nameBlockMap = new HashMap<>();
// don't regenerate now, do lazily later if needed
executeSet = null;
} }
void fireBytesChanged(Address addr, int count) { void fireBytesChanged(Address addr, int count) {
@ -1972,15 +1978,34 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
*/ */
@Override @Override
public AddressSetView getExecuteSet() { public AddressSetView getExecuteSet() {
AddressSet set = new AddressSet(); AddressSetView set = executeSet;
for (MemoryBlock block : blocks) {
if (block.isExecute()) { if (set == null) {
set.addRange(block.getStart(), block.getEnd()); set = computeExecuteSet();
}
} }
return set; return set;
} }
/**
* @return executable address set
*/
private AddressSetView computeExecuteSet() {
lock.acquire();
try {
AddressSet set = new AddressSet();
for (MemoryBlock block : blocks) {
if (block.isExecute()) {
set.addRange(block.getStart(), block.getEnd());
}
}
executeSet = new AddressSetViewAdapter(set);
return executeSet;
}
finally {
lock.release();
}
}
@Override @Override
public void memoryChanged(Address addr, int size) { public void memoryChanged(Address addr, int size) {
fireBytesChanged(addr, size); fireBytesChanged(addr, size);