From 9c3ae59860b57630f5da946038d81b6b40e0f134 Mon Sep 17 00:00:00 2001 From: emteere <47253321+emteere@users.noreply.github.com> Date: Wed, 9 Oct 2019 08:19:14 -0400 Subject: [PATCH] GT-3223_emteere cache of block name to block lookup --- .../database/mem/MemoryManagerTest.java | 80 +++++++++++++++++-- .../program/database/mem/MemoryMapDB.java | 19 +++++ 2 files changed, 92 insertions(+), 7 deletions(-) diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/mem/MemoryManagerTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/mem/MemoryManagerTest.java index 20433a4ee7..d1aa6e5732 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/mem/MemoryManagerTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/mem/MemoryManagerTest.java @@ -15,20 +15,51 @@ */ 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 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.program.database.ProgramBuilder; import ghidra.program.database.ProgramDB; -import ghidra.program.model.address.*; -import ghidra.program.model.data.*; -import ghidra.program.model.listing.*; -import ghidra.program.model.mem.*; -import ghidra.program.model.symbol.*; +import ghidra.program.model.address.Address; +import ghidra.program.model.address.AddressOverflowException; +import ghidra.program.model.address.AddressRange; +import ghidra.program.model.address.AddressRangeImpl; +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.ToyProgramBuilder; import ghidra.util.task.TaskMonitor; @@ -315,6 +346,41 @@ public class MemoryManagerTest extends AbstractGhidraHeadedIntegrationTest { MemoryBlock block = mem.getBlock(addr(95)); 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 public void testSave() throws Exception { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDB.java index 394d6c4dfe..5769d32d01 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDB.java @@ -59,6 +59,10 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener { private AddressSet allInitializedAddrSet = new AddressSet(); private MemoryBlock lastBlock;// the last accessed block private LiveMemoryHandler liveMemory; + + // lazy hashmap of block names to blocks, must be reloaded if blocks are removed or added + private HashMap nameBlockMap = new HashMap(); + private static MemoryBlock NoBlock = new MemoryBlockStub(); // placeholder for no block, not given out Lock lock; private Set potentialOverlappingBlocks; @@ -182,6 +186,7 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener { lastBlock = null; blocks = newBlocks; addrMap.memoryMapChanged(this); + nameBlockMap = new HashMap<>(); } public void setLanguage(Language newLanguage) { @@ -302,11 +307,22 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener { */ @Override 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) { if (block.getName().equals(blockName)) { + nameBlockMap.put(blockName, block); return block; } } + + // store placeholder there is no memory block with that name + nameBlockMap.put(blockName, NoBlock); return null; } @@ -374,6 +390,9 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener { if (program != null) { program.setChanged(ChangeManager.DOCR_MEMORY_BLOCK_CHANGED, block, null); } + + // name could have changed + nameBlockMap = new HashMap<>(); } void fireBytesChanged(Address addr, int count) {