GT-3223_emteere cache of block name to block lookup

This commit is contained in:
emteere 2019-10-09 08:19:14 -04:00
parent ded1fbbeb4
commit 9c3ae59860
2 changed files with 92 additions and 7 deletions

View file

@ -15,20 +15,51 @@
*/ */
package ghidra.program.database.mem; package ghidra.program.database.mem;
import static org.junit.Assert.*; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.Iterator; import java.util.Iterator;
import org.junit.*; import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import ghidra.app.plugin.core.memory.UninitializedBlockCmd; import ghidra.app.plugin.core.memory.UninitializedBlockCmd;
import ghidra.program.database.ProgramBuilder; import ghidra.program.database.ProgramBuilder;
import ghidra.program.database.ProgramDB; import ghidra.program.database.ProgramDB;
import ghidra.program.model.address.*; import ghidra.program.model.address.Address;
import ghidra.program.model.data.*; import ghidra.program.model.address.AddressOverflowException;
import ghidra.program.model.listing.*; import ghidra.program.model.address.AddressRange;
import ghidra.program.model.mem.*; import ghidra.program.model.address.AddressRangeImpl;
import ghidra.program.model.symbol.*; import ghidra.program.model.address.AddressSet;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.data.ArrayDataType;
import ghidra.program.model.data.ByteDataType;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.PointerDataType;
import ghidra.program.model.listing.Data;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.Listing;
import ghidra.program.model.listing.ProgramFragment;
import ghidra.program.model.listing.ProgramModule;
import ghidra.program.model.mem.LiveMemoryHandler;
import ghidra.program.model.mem.LiveMemoryListener;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.model.mem.MemoryBlockException;
import ghidra.program.model.mem.MemoryBlockSourceInfo;
import ghidra.program.model.mem.MemoryBlockStub;
import ghidra.program.model.mem.MemoryBlockType;
import ghidra.program.model.mem.MemoryConflictException;
import ghidra.program.model.symbol.Reference;
import ghidra.program.model.symbol.ReferenceManager;
import ghidra.program.model.symbol.SourceType;
import ghidra.test.AbstractGhidraHeadedIntegrationTest; import ghidra.test.AbstractGhidraHeadedIntegrationTest;
import ghidra.test.ToyProgramBuilder; import ghidra.test.ToyProgramBuilder;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
@ -315,6 +346,41 @@ public class MemoryManagerTest extends AbstractGhidraHeadedIntegrationTest {
MemoryBlock block = mem.getBlock(addr(95)); MemoryBlock block = mem.getBlock(addr(95));
assertEquals(newBlock, block); assertEquals(newBlock, block);
} }
@Test
public void testGetBlockByName() throws Exception {
MemoryBlock block1 = createBlock("Test1", addr(100), 100);
MemoryBlock block2 = createBlock("Test2", addr(300), 100);
MemoryBlock block = mem.getBlock("Test1");
assertEquals("Test1", block.getName());
assertEquals("get same block", block, block1);
mem.split(block, addr(150));
block = mem.getBlock("Test1");
assertEquals("Test1", block.getName());
assertEquals(50, block.getSize());
// non-existent block
block = mem.getBlock("NoExist");
assertNull(block);
// now exists
mem.getBlock("Test1").setName("NoExist");
block = mem.getBlock("NoExist");
assertEquals("NoExist", block.getName());
mem.removeBlock(block, new TaskMonitorAdapter());
block = mem.getBlock("NoExist");
assertNull("block should be deleted", block);
block = mem.getBlock("Test1");
assertNull("block deleted", block);
block = mem.getBlock("Test2");
assertEquals("Test2", block.getName());
}
@Test @Test
public void testSave() throws Exception { public void testSave() throws Exception {

View file

@ -59,6 +59,10 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
private AddressSet allInitializedAddrSet = new AddressSet(); private AddressSet allInitializedAddrSet = new AddressSet();
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
private HashMap<String,MemoryBlock> nameBlockMap = new HashMap<String, MemoryBlock>();
private static MemoryBlock NoBlock = new MemoryBlockStub(); // placeholder for no block, not given out
Lock lock; Lock lock;
private Set<MemoryBlock> potentialOverlappingBlocks; private Set<MemoryBlock> potentialOverlappingBlocks;
@ -182,6 +186,7 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
lastBlock = null; lastBlock = null;
blocks = newBlocks; blocks = newBlocks;
addrMap.memoryMapChanged(this); addrMap.memoryMapChanged(this);
nameBlockMap = new HashMap<>();
} }
public void setLanguage(Language newLanguage) { public void setLanguage(Language newLanguage) {
@ -302,11 +307,22 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
*/ */
@Override @Override
public synchronized MemoryBlock getBlock(String blockName) { public synchronized MemoryBlock getBlock(String blockName) {
// find block that might have been cached from previous call
MemoryBlock memoryBlock = nameBlockMap.get(blockName);
if (memoryBlock == NoBlock) {
// found placeholder, have searched and found nothing before
return null;
}
for (MemoryBlock block : blocks) { for (MemoryBlock block : blocks) {
if (block.getName().equals(blockName)) { if (block.getName().equals(blockName)) {
nameBlockMap.put(blockName, block);
return block; return block;
} }
} }
// store placeholder there is no memory block with that name
nameBlockMap.put(blockName, NoBlock);
return null; return null;
} }
@ -374,6 +390,9 @@ 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
nameBlockMap = new HashMap<>();
} }
void fireBytesChanged(Address addr, int count) { void fireBytesChanged(Address addr, int count) {