GT-3448_emteere_LargeDisPerf simple better byte buffering

This commit is contained in:
emteere 2020-01-30 14:07:27 +00:00
parent 2291b27356
commit cd650d0103
2 changed files with 230 additions and 2 deletions

View file

@ -456,6 +456,14 @@ public class Disassembler implements DisassemblerConflictHandler {
while (!todoSubset.isEmpty() && !monitor.isCancelled()) {
Address nextAddr = todoSubset.getMinAddress();
// Check if location is already on disassembly list
if (disassembledAddrs.contains(nextAddr)) {
AddressRange doneRange = disassembledAddrs.getRangeContaining(nextAddr);
todoSubset.delete(doneRange);
continue;
}
// must be aligned
if (nextAddr.getOffset() % alignment != 0) {
todoSubset.delete(nextAddr, nextAddr);
@ -921,8 +929,9 @@ public class Disassembler implements DisassemblerConflictHandler {
disassemblerContext.flowToAddress(addr);
MemBuffer instrMemBuffer = new WrappedMemBuffer(blockMemBuffer,
(int) addr.subtract(blockMemBuffer.getAddress()));
// TODO: An overall better caching of bytes for this block could be done instead
// the previous buffering done here was not doing any buffering
MemBuffer instrMemBuffer = new DumbMemBufferImpl(blockMemBuffer.getMemory(), addr);
adjustPreParseContext(instrMemBuffer);

View file

@ -0,0 +1,219 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.program.disassemble;
import static org.junit.Assert.*;
import org.junit.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryBlock;
import ghidra.test.AbstractGhidraHeadlessIntegrationTest;
import ghidra.test.ToyProgramBuilder;
import ghidra.util.task.TaskMonitorAdapter;
public class DisassemblerLargeSetTest extends AbstractGhidraHeadlessIntegrationTest {
private static final int MEMORY_SIZE = 1024 * 128;
private static final int CASESIZE = 12;
private static final long NUMCASES = MEMORY_SIZE / CASESIZE;
private static byte disBlock[] = { (byte) 0xf5, 0x0c, 0x03, 0x04, (byte) 0xf4, 0x00,
(byte) 0xdf, 0x34, (byte) 0xf4, 0x00, (byte) 0xf4, 0x00 };
private ToyProgramBuilder programBuilder;// Instructions are 2-byte aligned
private Program program;
private Disassembler disassembler;
private int txId;
@Before
public void setUp() throws Exception {
programBuilder = new ToyProgramBuilder("Test", true, true, null);
program = programBuilder.getProgram();
txId = program.startTransaction("Add Memory");// leave open until tearDown
programBuilder.createMemory(".text", "0", MEMORY_SIZE).setExecute(true);// initialized
// Fill memory
MemoryBlock block = programBuilder.getProgram().getMemory().getBlock(addr(0x0));
long numCases = MEMORY_SIZE / CASESIZE;
for (long i = 0; i < numCases; i++) {
block.putBytes(addr(i * CASESIZE), disBlock);
}
disassembler = new Disassembler(program, TaskMonitorAdapter.DUMMY_MONITOR, null);
}
@After
public void tearDown() throws Exception {
if (program != null) {
program.endTransaction(txId, true);
}
if (programBuilder != null) {
programBuilder.dispose();
}
}
private Address addr(long offset) {
return programBuilder.getAddress(offset);
}
private void verifyBookmarks(int cnt) {
assertEquals("unexpected bookmarks exist", cnt,
program.getBookmarkManager().getBookmarkCount());
}
@Test
public void testLargeDisjointPointsNoPredisassembledPoints() throws Exception {
// disassemble the threaded flow
AddressSet disassemble1 = disassembler.disassemble(addr(0x0), null, true);
AddressSet disLocs = new AddressSet();
for (long i = 0; i < NUMCASES; i++) {
disLocs.add(addr(i * CASESIZE));
}
assertTrue(disassemble1.contains(disLocs));
AddressSet disLocs2 = new AddressSet();
for (long i = 0; i < NUMCASES; i++) {
disLocs2.add(addr(i * CASESIZE + 6));
}
AddressSet disassemble2 = disassembler.disassemble(disLocs2, null, true);
assertTrue(disassemble2.contains(disLocs2));
verifyBookmarks(1);
}
@Test
public void testLargeDisjointPointsWithAlreadyDiassembledPoints() throws Exception {
// disassemble the threaded flow
AddressSet disassemble1 = disassembler.disassemble(addr(0x0), null, true);
AddressSet disLocs = new AddressSet();
for (long i = 0; i < NUMCASES; i++) {
disLocs.add(addr(i * CASESIZE));
}
assertTrue(disassemble1.contains(disLocs));
AddressSet disLocs2 = new AddressSet();
for (long i = 0; i < NUMCASES; i++) {
disLocs2.add(addr(i * CASESIZE));
disLocs2.add(addr(i * CASESIZE + 6));
}
AddressSet disassemble2 = disassembler.disassemble(disLocs2, null, true);
assertTrue(disassemble2.contains(disLocs2.subtract(disLocs)));
}
@Test
public void testLargeDisjointRange() throws Exception {
// disassemble the threaded flow
AddressSet disassemble1 = disassembler.disassemble(addr(0x0), null, true);
AddressSet disLocs = new AddressSet();
for (long i = 0; i < NUMCASES; i++) {
disLocs.add(addr(i * CASESIZE));
}
assertTrue(disassemble1.contains(disLocs));
AddressSet disLocs2 = new AddressSet();
for (long i = 0; i < NUMCASES; i++) {
disLocs2.add(addr(i * CASESIZE));
disLocs2.add(addr(i * CASESIZE + 6), addr(i * CASESIZE + 10));
}
AddressSet disassemble2 = disassembler.disassemble(disLocs2, null, true);
assertTrue(disassemble2.contains(disLocs2.subtract(disLocs)));
}
@Test
public void testLargeDisjointRangePartialOverlap() throws Exception {
// disassemble the threaded flow
AddressSet disassemble1 = disassembler.disassemble(addr(0x0), null, true);
AddressSet disLocs = new AddressSet();
for (long i = 0; i < NUMCASES; i++) {
disLocs.add(addr(i * CASESIZE));
}
assertTrue(disassemble1.contains(disLocs));
AddressSet disLocs2 = new AddressSet();
for (long i = 0; i < NUMCASES; i++) {
disLocs2.add(addr(i * CASESIZE));
disLocs2.add(addr(i * CASESIZE + 6), addr(i * CASESIZE + 11));
}
AddressSet disassemble2 = disassembler.disassemble(disLocs2, null, true);
assertTrue(disassemble2.contains(disLocs2.subtract(disLocs)));
}
@Test
public void testLargeDisjointRangeFullOverlap() throws Exception {
// disassemble the threaded flow
AddressSet disassemble1 = disassembler.disassemble(addr(0x0), null, true);
AddressSet disLocs = new AddressSet();
for (long i = 0; i < NUMCASES; i++) {
disLocs.add(addr(i * CASESIZE), addr(i * CASESIZE + 3));
}
assertTrue(disassemble1.contains(disLocs));
AddressSet disLocs2 = new AddressSet();
for (long i = 0; i < NUMCASES; i++) {
disLocs2.add(addr(i * CASESIZE), addr(i * CASESIZE + 3));
disLocs2.add(addr(i * CASESIZE + 6), addr(i * CASESIZE + 11));
}
AddressSet disassemble2 = disassembler.disassemble(disLocs2, null, true);
assertTrue(disassemble2.contains(disLocs2.subtract(disLocs)));
}
@Test
public void testSingleRange() throws Exception {
AddressSet disLocs2 = new AddressSet(addr(0x0), addr(CASESIZE * (NUMCASES)));
AddressSet disassemble2 = disassembler.disassemble(disLocs2, null, true);
assertTrue(disassemble2.contains(disLocs2));
}
@Test
public void testSingleRangeDisjoint() throws Exception {
// disassemble the threaded flow
AddressSet disassemble1 = disassembler.disassemble(addr(0x0), null, true);
AddressSet disLocs2 = new AddressSet(addr(0x0), addr(CASESIZE * (NUMCASES)));
AddressSet disassemble2 = disassembler.disassemble(disLocs2, null, true);
AddressSet disLocs = new AddressSet();
for (long i = 0; i < NUMCASES; i++) {
disLocs.add(addr(i * CASESIZE));
}
assertTrue(!disassemble2.contains(disLocs));
}
}