mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GT-2845: Storing original program bytes in the program database.
This commit is contained in:
parent
d95fd43762
commit
0792417979
73 changed files with 7129 additions and 2575 deletions
|
@ -0,0 +1,194 @@
|
|||
/* ###
|
||||
* 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.database.mem;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.model.mem.MemoryBlockStub;
|
||||
|
||||
public class ByteSourceRangeListTest extends AbstractGenericTest {
|
||||
private AddressSpace space = new GenericAddressSpace("test", 64, AddressSpace.TYPE_RAM, 0);
|
||||
private MemoryBlock block = new MemoryBlockStub();
|
||||
|
||||
@Test
|
||||
public void testConstructor() {
|
||||
ByteSourceRange range1 = new ByteSourceRange(block, addr(0), 0x10, 1, 0x50);
|
||||
|
||||
ByteSourceRangeList list1 = new ByteSourceRangeList(range1);
|
||||
ByteSourceRangeList list2 = new ByteSourceRangeList();
|
||||
list2.add(range1);
|
||||
|
||||
assertTrue(list1.equals(list2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdd() {
|
||||
ByteSourceRange range1 = new ByteSourceRange(block, addr(0), 0x10, 1, 0x50);
|
||||
ByteSourceRange range2 = new ByteSourceRange(block, addr(0x100), 0x10, 2, 0x50);
|
||||
ByteSourceRangeList list1 = new ByteSourceRangeList(range1);
|
||||
ByteSourceRangeList list2 = new ByteSourceRangeList(range2);
|
||||
list1.add(list2);
|
||||
assertEquals(2, list1.getRangeCount());
|
||||
assertEquals(range1, list1.get(0));
|
||||
assertEquals(range2, list1.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEmpty() {
|
||||
ByteSourceRange range1 = new ByteSourceRange(block, addr(0), 0x10, 1, 0x50);
|
||||
ByteSourceRangeList list1 = new ByteSourceRangeList();
|
||||
|
||||
assertTrue(list1.isEmpty());
|
||||
list1.add(range1);
|
||||
assertFalse(list1.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddNullRange() {
|
||||
ByteSourceRange range = null;
|
||||
ByteSourceRangeList list1 = new ByteSourceRangeList();
|
||||
list1.add(range);
|
||||
assertTrue(list1.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterator() {
|
||||
ByteSourceRange range1 = new ByteSourceRange(block, addr(0), 0x10, 1, 0x50);
|
||||
ByteSourceRange range2 = new ByteSourceRange(block, addr(0x100), 0x10, 2, 0x50);
|
||||
ByteSourceRangeList list1 = new ByteSourceRangeList(range1);
|
||||
list1.add(range2);
|
||||
|
||||
Iterator<ByteSourceRange> it = list1.iterator();
|
||||
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals(range1, it.next());
|
||||
assertTrue(it.hasNext());
|
||||
assertEquals(range2, it.next());
|
||||
assertFalse(it.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntersectSimple() {
|
||||
ByteSourceRangeList list1 = new ByteSourceRangeList();
|
||||
list1.add(new ByteSourceRange(block, addr(0), 0x100, 1, 0));
|
||||
|
||||
ByteSourceRangeList list2 = new ByteSourceRangeList();
|
||||
list2.add(new ByteSourceRange(block, addr(0x100), 0x100, 1, 0x10));
|
||||
|
||||
// note that list1.intersect(list2) is not equal to list2.intersect(list1).
|
||||
// The byte sources are the same but the corresponding real addresses are calling
|
||||
// objects byte sources.
|
||||
|
||||
ByteSourceRangeList result = list1.intersect(list2);
|
||||
assertEquals(1, result.getRangeCount());
|
||||
ByteSourceRange range = result.get(0);
|
||||
|
||||
assertEquals(0xf0, range.getSize());
|
||||
assertEquals(0x10, range.getOffset());
|
||||
assertEquals(block, range.getMemoryBlock());
|
||||
assertEquals(1, range.getSourceId());
|
||||
assertEquals(addr(0x10), range.getStart());
|
||||
assertEquals(addr(0xff), range.getEnd());
|
||||
|
||||
// now intersect from list2 perspective
|
||||
result = list2.intersect(list1);
|
||||
assertEquals(1, result.getRangeCount());
|
||||
range = result.get(0);
|
||||
|
||||
assertEquals(0xf0, range.getSize());
|
||||
assertEquals(0x10, range.getOffset());
|
||||
assertEquals(block, range.getMemoryBlock());
|
||||
assertEquals(1, range.getSourceId());
|
||||
|
||||
assertEquals(addr(0x100), range.getStart());
|
||||
assertEquals(addr(0x1ef), range.getEnd());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOverlappingBlocks() {
|
||||
ByteSourceRange range = new ByteSourceRange(block, addr(0), 0x100, 1, 0x00);
|
||||
MemoryBlock block1 = new MemoryBlockStub();
|
||||
ByteSourceRange range1 = new ByteSourceRange(block1, addr(0x100), 0x100, 2, 0x00);
|
||||
|
||||
// create a byte source overlap with the first block
|
||||
MemoryBlock block2 = new MemoryBlockStub();
|
||||
ByteSourceRange range2 = new ByteSourceRange(block2, addr(0x200), 0x100, 1, 0x50);
|
||||
|
||||
ByteSourceRangeList list = new ByteSourceRangeList();
|
||||
list.add(range);
|
||||
list.add(range1);
|
||||
list.add(range2);
|
||||
|
||||
Set<MemoryBlock> overlappingBlocks = list.getOverlappingBlocks();
|
||||
assertEquals(2, overlappingBlocks.size());
|
||||
assertTrue(overlappingBlocks.contains(block));
|
||||
assertTrue(overlappingBlocks.contains(block2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOverlappingBlocksBlocksWhereBlocksAreAdjacentButDontOverlap() {
|
||||
ByteSourceRange range = new ByteSourceRange(block, addr(0), 0x100, 1, 0x00);
|
||||
MemoryBlock block1 = new MemoryBlockStub();
|
||||
ByteSourceRange range1 = new ByteSourceRange(block1, addr(0x100), 0x100, 2, 0x00);
|
||||
|
||||
// create a byte source overlap with the first block
|
||||
MemoryBlock block2 = new MemoryBlockStub();
|
||||
ByteSourceRange range2 = new ByteSourceRange(block2, addr(0x200), 0x100, 1, 0x100);
|
||||
|
||||
ByteSourceRangeList list = new ByteSourceRangeList();
|
||||
list.add(range);
|
||||
list.add(range1);
|
||||
list.add(range2);
|
||||
|
||||
Set<MemoryBlock> overlappingBlocks = list.getOverlappingBlocks();
|
||||
assertEquals(0, overlappingBlocks.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOverlappingBlocksBlocksWhereBlocksOverlapByExactlyOneByte() {
|
||||
ByteSourceRange range = new ByteSourceRange(block, addr(0), 0x100, 1, 0x00);
|
||||
MemoryBlock block1 = new MemoryBlockStub();
|
||||
ByteSourceRange range1 = new ByteSourceRange(block1, addr(0x100), 0x100, 2, 0x00);
|
||||
|
||||
// create a byte source overlap with the first block
|
||||
MemoryBlock block2 = new MemoryBlockStub();
|
||||
ByteSourceRange range2 = new ByteSourceRange(block2, addr(0x200), 0x100, 1, 0xff);
|
||||
|
||||
ByteSourceRangeList list = new ByteSourceRangeList();
|
||||
list.add(range);
|
||||
list.add(range1);
|
||||
list.add(range2);
|
||||
|
||||
Set<MemoryBlock> overlappingBlocks = list.getOverlappingBlocks();
|
||||
assertEquals(2, overlappingBlocks.size());
|
||||
assertTrue(overlappingBlocks.contains(block));
|
||||
assertTrue(overlappingBlocks.contains(block2));
|
||||
}
|
||||
|
||||
private Address addr(long value) {
|
||||
return space.getAddress(value);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
/* ###
|
||||
* 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.database.mem;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.model.mem.MemoryBlockStub;
|
||||
|
||||
public class ByteSourceRangeTest extends AbstractGenericTest {
|
||||
private AddressSpace space = new GenericAddressSpace("test", 64, AddressSpace.TYPE_RAM, 0);
|
||||
private MemoryBlock block = new MemoryBlockStub();
|
||||
@Test
|
||||
public void testIntersectNotSameSource() {
|
||||
ByteSourceRange range1 = new ByteSourceRange(block, addr(0), 0x10, 1, 0x50);
|
||||
ByteSourceRange range2 = new ByteSourceRange(block, addr(0x100), 0x10, 2, 0x50);
|
||||
assertNull(range1.intersect(range2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntersectOneRangeSimpleOverlap() {
|
||||
ByteSourceRange range1 = new ByteSourceRange(block, addr(0), 0x20, 1, 0x50);
|
||||
ByteSourceRange range2 = new ByteSourceRange(block, addr(0x100), 0x20, 1, 0x60);
|
||||
|
||||
ByteSourceRange intersect = range1.intersect(range2);
|
||||
assertNotNull(intersect);
|
||||
assertEquals(addr(0x10), intersect.getStart());
|
||||
assertEquals(addr(0x1f), intersect.getEnd());
|
||||
assertEquals(0x10, intersect.getSize());
|
||||
assertEquals(1, intersect.getSourceId());
|
||||
assertEquals(0x60, intersect.getOffset());
|
||||
|
||||
intersect = range2.intersect(range1);
|
||||
assertNotNull(intersect);
|
||||
assertEquals(addr(0x100), intersect.getStart());
|
||||
assertEquals(addr(0x10f), intersect.getEnd());
|
||||
assertEquals(0x10, intersect.getSize());
|
||||
assertEquals(1, intersect.getSourceId());
|
||||
assertEquals(0x60, intersect.getOffset());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntersectOneRangeButsAgainsAnother() {
|
||||
ByteSourceRange range1 = new ByteSourceRange(block, addr(0), 0x20, 1, 0x50);
|
||||
ByteSourceRange range2 = new ByteSourceRange(block, addr(0x100), 0x20, 2, 0x70);
|
||||
|
||||
assertNull(range1.intersect(range2));
|
||||
assertNull(range2.intersect(range1));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testIntersectOneRangeCompletelyInAnother() {
|
||||
ByteSourceRange range1 = new ByteSourceRange(block, addr(0), 0x10, 1, 0x50);
|
||||
ByteSourceRange range2 = new ByteSourceRange(block, addr(0x100), 0x30, 1, 0x40);
|
||||
|
||||
ByteSourceRange intersect = range1.intersect(range2);
|
||||
assertNotNull(intersect);
|
||||
assertEquals(addr(0), intersect.getStart());
|
||||
assertEquals(addr(0xf), intersect.getEnd());
|
||||
assertEquals(0x10, intersect.getSize());
|
||||
assertEquals(1, intersect.getSourceId());
|
||||
assertEquals(0x50, intersect.getOffset());
|
||||
|
||||
intersect = range2.intersect(range1);
|
||||
assertNotNull(intersect);
|
||||
assertEquals(addr(0x110), intersect.getStart());
|
||||
assertEquals(addr(0x11f), intersect.getEnd());
|
||||
assertEquals(0x10, intersect.getSize());
|
||||
assertEquals(1, intersect.getSourceId());
|
||||
assertEquals(0x50, intersect.getOffset());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBitMappedIntersect() {
|
||||
ByteSourceRange range1 = new ByteSourceRange(block, addr(0), 0x10, 1, 0x50);
|
||||
ByteSourceRange range2 = new BitMappedByteSourceRange(block, addr(0x100), 1, 0x55, 2);
|
||||
|
||||
ByteSourceRange intersect = range1.intersect(range2);
|
||||
assertNotNull(intersect);
|
||||
assertEquals(addr(5), intersect.getStart());
|
||||
assertEquals(addr(6), intersect.getEnd());
|
||||
assertEquals(2, intersect.getSize());
|
||||
assertEquals(1, intersect.getSourceId());
|
||||
assertEquals(0x55, intersect.getOffset());
|
||||
|
||||
intersect = range2.intersect(range1);
|
||||
assertNotNull(intersect);
|
||||
assertEquals(addr(0x100), intersect.getStart());
|
||||
assertEquals(addr(0x10f), intersect.getEnd());
|
||||
assertEquals(2, intersect.getSize());
|
||||
assertEquals(1, intersect.getSourceId());
|
||||
assertEquals(0x55, intersect.getOffset());
|
||||
|
||||
}
|
||||
|
||||
private Address addr(long value) {
|
||||
return space.getAddress(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,249 @@
|
|||
/* ###
|
||||
* 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.database.mem;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
import db.*;
|
||||
import db.buffers.BufferFile;
|
||||
import generic.jar.ResourceFile;
|
||||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.framework.store.db.PrivateDatabase;
|
||||
import ghidra.program.database.ProgramDB;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.util.DefaultLanguageService;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class FileBytesTest extends AbstractGenericTest {
|
||||
|
||||
private static final int MAX_BUFFER_SIZE_FOR_TESTING = 200;
|
||||
private Program program;
|
||||
private Memory mem;
|
||||
private int transactionID;
|
||||
|
||||
public FileBytesTest() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStoreAndRetrieveFileBytes() throws IOException {
|
||||
int dataSize = MAX_BUFFER_SIZE_FOR_TESTING / 2;
|
||||
FileBytes fileBytes = createFileBytes("testFile", dataSize);
|
||||
|
||||
byte[] outBytes = new byte[200];
|
||||
assertEquals("testFile", fileBytes.getFilename());
|
||||
assertEquals(0L, fileBytes.getFileOffset());
|
||||
assertEquals(dataSize, fileBytes.getSize());
|
||||
int n = fileBytes.getOriginalBytes(0L, outBytes);
|
||||
assertEquals(dataSize, n);
|
||||
for (int i = 0; i < dataSize; i++) {
|
||||
assertEquals("Byte[" + i + "]", i, outBytes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetrieveAfterSavingAndReopeningProgram() throws Exception {
|
||||
int dataSize = MAX_BUFFER_SIZE_FOR_TESTING / 2;
|
||||
FileBytes fileBytes = createFileBytes("testFile", dataSize);
|
||||
|
||||
byte[] outBytes = new byte[200];
|
||||
|
||||
saveAndRestoreProgram();
|
||||
|
||||
List<FileBytes> list = program.getMemory().getAllFileBytes();
|
||||
fileBytes = list.get(0);
|
||||
|
||||
assertEquals("testFile", fileBytes.getFilename());
|
||||
assertEquals(0L, fileBytes.getFileOffset());
|
||||
assertEquals(dataSize, fileBytes.getSize());
|
||||
int n = fileBytes.getOriginalBytes(0L, outBytes);
|
||||
assertEquals(100, n);
|
||||
for (int i = 0; i < dataSize; i++) {
|
||||
assertEquals("Byte[" + i + "]", i, outBytes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequiresMultipleBuffers() throws Exception {
|
||||
int dataSize = MAX_BUFFER_SIZE_FOR_TESTING + MAX_BUFFER_SIZE_FOR_TESTING / 2;
|
||||
FileBytes fileBytes = createFileBytes("testFile", dataSize);
|
||||
|
||||
saveAndRestoreProgram();
|
||||
|
||||
byte[] outBytes = new byte[400];
|
||||
List<FileBytes> list = program.getMemory().getAllFileBytes();
|
||||
fileBytes = list.get(0);
|
||||
|
||||
assertEquals("testFile", fileBytes.getFilename());
|
||||
assertEquals(0L, fileBytes.getFileOffset());
|
||||
assertEquals(dataSize, fileBytes.getSize());
|
||||
int n = fileBytes.getOriginalBytes(0L, outBytes);
|
||||
assertEquals(dataSize, n);
|
||||
for (int i = 0; i < dataSize; i++) {
|
||||
assertEquals("Byte[" + i + "]", (byte) i, outBytes[i]);
|
||||
}
|
||||
DBBuffer[] buffers = (DBBuffer[]) getInstanceField("originalBuffers", fileBytes);
|
||||
assertEquals(2, buffers.length);
|
||||
assertEquals(MAX_BUFFER_SIZE_FOR_TESTING, buffers[0].length());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateMultipleFileBytes() throws Exception {
|
||||
createFileBytes("file1", 10);
|
||||
createFileBytes("file2", 20);
|
||||
createFileBytes("file3", 30);
|
||||
|
||||
saveAndRestoreProgram();
|
||||
List<FileBytes> fileBytesList = mem.getAllFileBytes();
|
||||
assertEquals(3, fileBytesList.size());
|
||||
assertEquals("file1", fileBytesList.get(0).getFilename());
|
||||
assertEquals(10, fileBytesList.get(0).getSize());
|
||||
assertEquals("file2", fileBytesList.get(1).getFilename());
|
||||
assertEquals(20, fileBytesList.get(1).getSize());
|
||||
assertEquals("file3", fileBytesList.get(2).getFilename());
|
||||
assertEquals(30, fileBytesList.get(2).getSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteFileBytesDescriptors() throws Exception {
|
||||
createFileBytes("file1", 10);
|
||||
createFileBytes("file2", 20);
|
||||
createFileBytes("file3", 30);
|
||||
|
||||
saveAndRestoreProgram();
|
||||
List<FileBytes> fileBytes = mem.getAllFileBytes();
|
||||
|
||||
mem.deleteFileBytes(fileBytes.get(1));
|
||||
|
||||
saveAndRestoreProgram();
|
||||
List<FileBytes> fileBytesList = mem.getAllFileBytes();
|
||||
assertEquals(2, fileBytesList.size());
|
||||
assertEquals("file1", fileBytesList.get(0).getFilename());
|
||||
assertEquals(10, fileBytesList.get(0).getSize());
|
||||
assertEquals("file3", fileBytesList.get(1).getFilename());
|
||||
assertEquals(30, fileBytesList.get(1).getSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetByte() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes("file1", 10);
|
||||
assertEquals(5, fileBytes.getOriginalByte(5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLayeredByte() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes("file1", 10);
|
||||
incrementFileBytes(fileBytes, 0, 10);
|
||||
|
||||
// check that the layered bytes are changed, but you can still get the originals
|
||||
for (int i = 0; i < 10; i++) {
|
||||
assertEquals(i, fileBytes.getOriginalByte(i));
|
||||
assertEquals(i + 1, fileBytes.getModifiedByte(i));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void incrementFileBytes(FileBytes fileBytes, int offset, int n) throws IOException {
|
||||
for (int i = offset; i < offset + n; i++) {
|
||||
fileBytes.putByte(i, (byte) (fileBytes.getModifiedByte(i) + 1));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLayeredBytes() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes("file1", 10);
|
||||
incrementFileBytes(fileBytes, 0, 10);
|
||||
|
||||
// check that the layered bytes are changed, but you can still get the originals
|
||||
byte[] original = new byte[10];
|
||||
byte[] modified = new byte[10];
|
||||
fileBytes.getOriginalBytes(0, original);
|
||||
fileBytes.getModifiedBytes(0, modified);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
assertEquals(i, original[i]);
|
||||
assertEquals(i + 1, modified[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private FileBytes createFileBytes(String name, int size) throws IOException {
|
||||
byte[] bytes = new byte[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
bytes[i] = (byte) i;
|
||||
}
|
||||
try (ByteArrayInputStream is = new ByteArrayInputStream(bytes)) {
|
||||
return mem.createFileBytes(name, 0, size, is);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveAndRestoreProgram() throws Exception {
|
||||
program.endTransaction(transactionID, true);
|
||||
PrivateDatabase privateDatabase = saveProgram(program);
|
||||
program = restoreProgram(privateDatabase);
|
||||
mem = program.getMemory();
|
||||
transactionID = program.startTransaction("test");
|
||||
}
|
||||
|
||||
private PrivateDatabase saveProgram(Program program) throws Exception {
|
||||
File dir = createTempDirectory("program");
|
||||
File dbDir = new File(dir, "program.db");
|
||||
|
||||
DBHandle dbh = ((ProgramDB) program).getDBHandle();
|
||||
BufferFile bfile = PrivateDatabase.createDatabase(dbDir, null, dbh.getBufferSize());
|
||||
dbh.saveAs(bfile, true, TaskMonitor.DUMMY);
|
||||
return new PrivateDatabase(dbDir);
|
||||
}
|
||||
|
||||
private Program restoreProgram(PrivateDatabase db) throws Exception {
|
||||
DBHandle dbh = db.open(TaskMonitor.DUMMY);
|
||||
return new ProgramDB(dbh, DBConstants.UPDATE, null, this);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
FileBytesAdapter.setMaxBufferSize(MAX_BUFFER_SIZE_FOR_TESTING);
|
||||
Language language = getLanguage("Toy:BE:64:default");
|
||||
CompilerSpec compilerSpec = language.getDefaultCompilerSpec();
|
||||
program = new ProgramDB("Test", language, compilerSpec, this);
|
||||
|
||||
mem = program.getMemory();
|
||||
transactionID = program.startTransaction("Test");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
program.endTransaction(transactionID, true);
|
||||
program.release(this);
|
||||
}
|
||||
|
||||
private Language getLanguage(String languageName) throws Exception {
|
||||
|
||||
ResourceFile ldefFile = Application.getModuleDataFile("Toy", "languages/toy.ldefs");
|
||||
if (ldefFile != null) {
|
||||
LanguageService languageService = DefaultLanguageService.getLanguageService(ldefFile);
|
||||
Language language = languageService.getLanguage(new LanguageID(languageName));
|
||||
return language;
|
||||
}
|
||||
throw new LanguageNotFoundException("Unsupported test language: " + languageName);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,857 @@
|
|||
/* ###
|
||||
* 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.database.mem;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
import db.DBConstants;
|
||||
import db.DBHandle;
|
||||
import generic.jar.ResourceFile;
|
||||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.program.database.ProgramDB;
|
||||
import ghidra.program.database.map.AddressMapDB;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.program.util.DefaultLanguageService;
|
||||
import ghidra.util.Lock;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class MemBlockDBTest extends AbstractGenericTest {
|
||||
private static final long MAX_SUB_BLOCK_SIZE = 16;
|
||||
private MemoryMapDB mem;
|
||||
private long txID;
|
||||
private DBHandle handle;
|
||||
private AddressFactory addressFactory;
|
||||
private ProgramDB program;
|
||||
private int ptxID;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
Language language = getLanguage("Toy:BE:64:default");
|
||||
CompilerSpec compilerSpec = language.getDefaultCompilerSpec();
|
||||
program = new ProgramDB("Test", language, compilerSpec, this);
|
||||
ptxID = program.startTransaction("test");
|
||||
|
||||
handle = new DBHandle();
|
||||
|
||||
txID = handle.startTransaction();
|
||||
|
||||
addressFactory = language.getAddressFactory();
|
||||
AddressMapDB addrMap = (AddressMapDB) program.getAddressMap();
|
||||
Lock lock = new Lock("Test");
|
||||
int openMode = DBConstants.CREATE;
|
||||
mem = new MemoryMapDB(handle, addrMap, openMode, true, lock);
|
||||
|
||||
MemoryMapDBAdapter adapter =
|
||||
new MemoryMapDBAdapterV3(handle, mem, MAX_SUB_BLOCK_SIZE, true);
|
||||
FileBytesAdapter fileBytesAdapter = new FileBytesAdapterV0(handle, mem, true);
|
||||
|
||||
mem.init(adapter, fileBytesAdapter);
|
||||
mem.setProgram(program);
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
program.endTransaction(ptxID, true);
|
||||
handle.endTransaction(txID, true);
|
||||
handle.close();
|
||||
program.release(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateInitializedBlock() throws Exception {
|
||||
MemoryBlock block =
|
||||
mem.createInitializedBlock("test", addr(0), 10, (byte) 1, TaskMonitor.DUMMY, false);
|
||||
|
||||
assertEquals(10, block.getSize());
|
||||
assertEquals("test", block.getName());
|
||||
assertEquals(addr(0), block.getStart());
|
||||
assertEquals(addr(9), block.getEnd());
|
||||
assertEquals(MemoryBlockType.DEFAULT, block.getType());
|
||||
assertEquals(true, block.isInitialized());
|
||||
assertEquals(false, block.isMapped());
|
||||
assertNull(block.getComment());
|
||||
assertNull(block.getSourceName());
|
||||
assertEquals(MemoryBlock.READ, block.getPermissions());
|
||||
|
||||
List<SourceInfo> sourceInfos = block.getSourceInfos();
|
||||
|
||||
assertEquals(1, sourceInfos.size());
|
||||
SourceInfo info = sourceInfos.get(0);
|
||||
assertEquals(10, info.getLength());
|
||||
assertEquals(addr(0), info.getMinAddress());
|
||||
assertEquals(addr(9), info.getMaxAddress());
|
||||
for (int i = 0; i < 10; i++) {
|
||||
assertEquals(1, block.getByte(addr(i)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateUninitializedBlock() throws Exception {
|
||||
MemoryBlock block = mem.createUninitializedBlock("test", addr(0), 10, false);
|
||||
|
||||
assertEquals(10, block.getSize());
|
||||
assertEquals("test", block.getName());
|
||||
assertEquals(addr(0), block.getStart());
|
||||
assertEquals(addr(9), block.getEnd());
|
||||
assertEquals(MemoryBlockType.DEFAULT, block.getType());
|
||||
List<SourceInfo> sourceInfos = block.getSourceInfos();
|
||||
assertEquals(1, sourceInfos.size());
|
||||
SourceInfo info = sourceInfos.get(0);
|
||||
assertEquals(10, info.getLength());
|
||||
assertEquals(addr(0), info.getMinAddress());
|
||||
assertEquals(addr(9), info.getMaxAddress());
|
||||
try {
|
||||
block.getByte(addr(0));
|
||||
fail("expected exception trying to read bytes on unitialized block");
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateUnitializedOverlayBlock() throws Exception {
|
||||
MemoryBlock block = mem.createUninitializedBlock("test", addr(0), 10, true);
|
||||
|
||||
assertEquals(10, block.getSize());
|
||||
assertEquals("test", block.getName());
|
||||
assertNotEquals(addr(0), block.getStart()); // block should be in overlay space
|
||||
assertEquals(0, block.getStart().getOffset());
|
||||
assertEquals(9, block.getEnd().getOffset());
|
||||
assertTrue(block.getStart().getAddressSpace().isOverlaySpace());
|
||||
assertEquals(MemoryBlockType.OVERLAY, block.getType());
|
||||
List<SourceInfo> sourceInfos = block.getSourceInfos();
|
||||
assertEquals(1, sourceInfos.size());
|
||||
SourceInfo info = sourceInfos.get(0);
|
||||
assertEquals(10, info.getLength());
|
||||
try {
|
||||
block.getByte(block.getStart());
|
||||
fail("expected exception trying to read bytes on unitialized block");
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateInitializedOverlayBlock() throws Exception {
|
||||
MemoryBlock block =
|
||||
mem.createInitializedBlock("test", addr(0), 10, (byte) 1, TaskMonitor.DUMMY, true);
|
||||
|
||||
assertEquals(10, block.getSize());
|
||||
assertEquals("test", block.getName());
|
||||
assertNotEquals(addr(0), block.getStart()); // block should be in overlay space
|
||||
assertEquals(0, block.getStart().getOffset());
|
||||
assertEquals(9, block.getEnd().getOffset());
|
||||
assertTrue(block.getStart().getAddressSpace().isOverlaySpace());
|
||||
assertEquals(MemoryBlockType.OVERLAY, block.getType());
|
||||
List<SourceInfo> sourceInfos = block.getSourceInfos();
|
||||
assertEquals(1, sourceInfos.size());
|
||||
SourceInfo info = sourceInfos.get(0);
|
||||
assertEquals(10, info.getLength());
|
||||
for (int i = 0; i < 10; i++) {
|
||||
assertEquals(1, block.getByte(block.getStart().add(i)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateByteMappedBlock() throws Exception {
|
||||
mem.createInitializedBlock("test1", addr(0), 50, (byte) 1, TaskMonitor.DUMMY, false);
|
||||
mem.createUninitializedBlock("test2", addr(50), 50, false);
|
||||
MemoryBlock block = mem.createByteMappedBlock("mapped", addr(1000), addr(40), 20);
|
||||
|
||||
assertEquals(20, block.getSize());
|
||||
assertEquals("mapped", block.getName());
|
||||
assertEquals(addr(1000), block.getStart());
|
||||
assertEquals(addr(1019), block.getEnd());
|
||||
assertEquals(MemoryBlockType.BYTE_MAPPED, block.getType());
|
||||
assertEquals(false, block.isInitialized());
|
||||
assertEquals(true, block.isMapped());
|
||||
assertNull(block.getComment());
|
||||
assertNull(block.getSourceName());
|
||||
assertEquals(MemoryBlock.READ, block.getPermissions());
|
||||
|
||||
List<SourceInfo> sourceInfos = block.getSourceInfos();
|
||||
|
||||
assertEquals(1, sourceInfos.size());
|
||||
SourceInfo info = sourceInfos.get(0);
|
||||
assertEquals(20, info.getLength());
|
||||
assertEquals(new AddressRangeImpl(addr(40), addr(59)), info.getMappedRange().get());
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
assertEquals(1, mem.getByte(block.getStart().add(i)));
|
||||
}
|
||||
try {
|
||||
mem.getByte(block.getStart().add(10));
|
||||
fail("expected exception trying to read bytes on mapped unitialized block");
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateBitMappedBlock() throws Exception {
|
||||
mem.createInitializedBlock("test1", addr(0), 50, (byte) 1, TaskMonitor.DUMMY, false);
|
||||
mem.createUninitializedBlock("test2", addr(50), 50, false);
|
||||
MemoryBlock block = mem.createBitMappedBlock("mapped", addr(1000), addr(49), 16);
|
||||
|
||||
assertEquals(16, block.getSize());
|
||||
assertEquals("mapped", block.getName());
|
||||
assertEquals(addr(1000), block.getStart());
|
||||
assertEquals(addr(1015), block.getEnd());
|
||||
assertEquals(MemoryBlockType.BIT_MAPPED, block.getType());
|
||||
assertEquals(false, block.isInitialized());
|
||||
assertEquals(true, block.isMapped());
|
||||
assertNull(block.getComment());
|
||||
assertNull(block.getSourceName());
|
||||
assertEquals(MemoryBlock.READ, block.getPermissions());
|
||||
|
||||
List<SourceInfo> sourceInfos = block.getSourceInfos();
|
||||
|
||||
assertEquals(1, sourceInfos.size());
|
||||
SourceInfo info = sourceInfos.get(0);
|
||||
assertEquals(16, info.getLength());
|
||||
assertEquals(new AddressRangeImpl(addr(49), addr(50)), info.getMappedRange().get());
|
||||
|
||||
assertEquals(1, mem.getByte(block.getStart()));
|
||||
for (int i = 1; i < 8; i++) {
|
||||
assertEquals(0, mem.getByte(block.getStart().add(i)));
|
||||
}
|
||||
try {
|
||||
mem.getByte(block.getStart().add(8));
|
||||
fail("expected exception trying to read bytes on mapped unitialized block");
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateFileBytesBlock() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
MemoryBlock block = mem.createInitializedBlock("test", addr(100), fileBytes, 10, 50, false);
|
||||
|
||||
assertEquals(50, block.getSize());
|
||||
assertEquals("test", block.getName());
|
||||
assertEquals(addr(100), block.getStart());
|
||||
assertEquals(addr(149), block.getEnd());
|
||||
assertEquals(MemoryBlockType.DEFAULT, block.getType());
|
||||
assertEquals(true, block.isInitialized());
|
||||
assertEquals(false, block.isMapped());
|
||||
assertNull(block.getComment());
|
||||
assertNull(block.getSourceName());
|
||||
assertEquals(MemoryBlock.READ, block.getPermissions());
|
||||
|
||||
List<SourceInfo> sourceInfos = block.getSourceInfos();
|
||||
|
||||
assertEquals(1, sourceInfos.size());
|
||||
SourceInfo info = sourceInfos.get(0);
|
||||
assertEquals(50, info.getLength());
|
||||
assertEquals(addr(100), info.getMinAddress());
|
||||
assertEquals(addr(149), info.getMaxAddress());
|
||||
|
||||
for (int i = 0; i < block.getSize(); i++) {
|
||||
assertEquals(i + 10, block.getByte(addr(100 + i)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateFileBytesBlockOutSideRange() throws Exception {
|
||||
byte[] bytes = new byte[256];
|
||||
FileBytes fileBytes = mem.createFileBytes("test", 0, 100, new ByteArrayInputStream(bytes));
|
||||
try {
|
||||
mem.createInitializedBlock("test", addr(100), fileBytes, 10, 100, false);
|
||||
fail(
|
||||
"Expected create filebytes block to fail because the offset+blockLength > fileBytesLength");
|
||||
}
|
||||
catch (IndexOutOfBoundsException e) {
|
||||
// expected
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializedBlockAcrossSubBlocks() throws Exception {
|
||||
mem.createInitializedBlock("test", addr(0), 100, (byte) 1, TaskMonitor.DUMMY, false);
|
||||
assertEquals(0x0101010101010101L, mem.getLong(addr(MAX_SUB_BLOCK_SIZE - 1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializedBlockAcrossMutlitipleSubBlocks() throws Exception {
|
||||
byte[] bytes = new byte[256];
|
||||
for (int i = 0; i < 256; i++) {
|
||||
bytes[i] = (byte) i;
|
||||
}
|
||||
mem.createInitializedBlock("test", addr(0), new ByteArrayInputStream(bytes), 256,
|
||||
TaskMonitor.DUMMY, false);
|
||||
byte[] b = new byte[100];
|
||||
assertEquals(100, mem.getBytes(addr(10), b));
|
||||
for (int i = 0; i < 100; i++) {
|
||||
assertEquals(i + 10, b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJoinFileBytes() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
MemoryBlock block1 = createFileBytesBlock(fileBytes, addr(10), 25, 10);
|
||||
MemoryBlock block2 = createFileBytesBlock(fileBytes, addr(20), 35, 10);
|
||||
MemoryBlock block = mem.join(block1, block2);
|
||||
assertEquals(1, mem.getBlocks().length);
|
||||
assertEquals(20, block.getSize());
|
||||
assertEquals(addr(10), block.getStart());
|
||||
List<SourceInfo> sourceInfos = block.getSourceInfos();
|
||||
assertEquals(1, sourceInfos.size());
|
||||
SourceInfo sourceInfo = sourceInfos.get(0);
|
||||
assertEquals(fileBytes, sourceInfo.getFileBytes().get());
|
||||
assertEquals(25, sourceInfo.getFileBytesOffset());
|
||||
byte[] bytes = new byte[30];
|
||||
assertEquals(20, block.getBytes(addr(10), bytes));
|
||||
for (int i = 0; i < 20; i++) {
|
||||
assertEquals(i + 25, bytes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJoinNonConsecutiveFileBytes() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
MemoryBlock block1 = createFileBytesBlock(fileBytes, addr(10), 25, 10);
|
||||
MemoryBlock block2 = createFileBytesBlock(fileBytes, addr(20), 70, 10);
|
||||
|
||||
MemoryBlock block = mem.join(block1, block2);
|
||||
assertEquals(1, mem.getBlocks().length);
|
||||
assertEquals(20, block.getSize());
|
||||
assertEquals(addr(10), block.getStart());
|
||||
List<SourceInfo> sourceInfos = block.getSourceInfos();
|
||||
assertEquals(2, sourceInfos.size());
|
||||
SourceInfo sourceInfo = sourceInfos.get(0);
|
||||
assertEquals(fileBytes, sourceInfo.getFileBytes().get());
|
||||
assertEquals(25, sourceInfo.getFileBytesOffset());
|
||||
assertEquals(10, sourceInfo.getLength());
|
||||
|
||||
sourceInfo = sourceInfos.get(1);
|
||||
assertEquals(fileBytes, sourceInfo.getFileBytes().get());
|
||||
assertEquals(70, sourceInfo.getFileBytesOffset());
|
||||
assertEquals(10, sourceInfo.getLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJoinFileBytesBlockAndBufferBlock() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
MemoryBlock block1 = createFileBytesBlock(fileBytes, addr(10), 25, 10);
|
||||
MemoryBlock block2 =
|
||||
mem.createInitializedBlock("test", addr(20), 10, (byte) 1, TaskMonitor.DUMMY, false);
|
||||
|
||||
MemoryBlock block = mem.join(block1, block2);
|
||||
assertEquals(1, mem.getBlocks().length);
|
||||
assertEquals(20, block.getSize());
|
||||
assertEquals(addr(10), block.getStart());
|
||||
List<SourceInfo> sourceInfos = block.getSourceInfos();
|
||||
assertEquals(2, sourceInfos.size());
|
||||
SourceInfo sourceInfo = sourceInfos.get(0);
|
||||
assertEquals(fileBytes, sourceInfo.getFileBytes().get());
|
||||
assertEquals(25, sourceInfo.getFileBytesOffset());
|
||||
assertEquals(10, sourceInfo.getLength());
|
||||
|
||||
SourceInfo sourceInfo2 = sourceInfos.get(1);
|
||||
assertEquals(10, sourceInfo2.getLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJoinBlocksFromDifferentFileBytes() throws Exception {
|
||||
FileBytes fileBytes1 = createFileBytes();
|
||||
FileBytes fileBytes2 = createFileBytes();
|
||||
MemoryBlock block1 = createFileBytesBlock(fileBytes1, addr(10), 25, 10);
|
||||
MemoryBlock block2 = createFileBytesBlock(fileBytes2, addr(20), 35, 10);
|
||||
|
||||
MemoryBlock block = mem.join(block1, block2);
|
||||
assertEquals(1, mem.getBlocks().length);
|
||||
assertEquals(20, block.getSize());
|
||||
assertEquals(addr(10), block.getStart());
|
||||
List<SourceInfo> sourceInfos = block.getSourceInfos();
|
||||
assertEquals(2, sourceInfos.size());
|
||||
|
||||
SourceInfo sourceInfo = sourceInfos.get(0);
|
||||
assertEquals(fileBytes1, sourceInfo.getFileBytes().get());
|
||||
assertEquals(25, sourceInfo.getFileBytesOffset());
|
||||
assertEquals(10, sourceInfo.getLength());
|
||||
|
||||
sourceInfo = sourceInfos.get(1);
|
||||
assertEquals(fileBytes2, sourceInfo.getFileBytes().get());
|
||||
assertEquals(35, sourceInfo.getFileBytesOffset());
|
||||
assertEquals(10, sourceInfo.getLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitFileBytes() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
MemoryBlock block1 = createFileBytesBlock(fileBytes, addr(10), 25, 50);
|
||||
mem.split(block1, addr(30));
|
||||
|
||||
MemoryBlock[] blocks = mem.getBlocks();
|
||||
assertEquals(2, blocks.length);
|
||||
|
||||
assertEquals(20, blocks[0].getSize());
|
||||
assertEquals(30, blocks[1].getSize());
|
||||
|
||||
assertEquals(addr(10), blocks[0].getStart());
|
||||
assertEquals(addr(30), blocks[1].getStart());
|
||||
|
||||
List<SourceInfo> sourceInfos = blocks[0].getSourceInfos();
|
||||
assertEquals(1, sourceInfos.size());
|
||||
SourceInfo sourceInfo = sourceInfos.get(0);
|
||||
assertEquals(fileBytes, sourceInfo.getFileBytes().get());
|
||||
assertEquals(25, sourceInfo.getFileBytesOffset());
|
||||
|
||||
sourceInfos = blocks[1].getSourceInfos();
|
||||
assertEquals(1, sourceInfos.size());
|
||||
sourceInfo = sourceInfos.get(0);
|
||||
assertEquals(fileBytes, sourceInfo.getFileBytes().get());
|
||||
assertEquals(45, sourceInfo.getFileBytesOffset());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteFileBytesBlock() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
MemoryBlock block1 = createFileBytesBlock(fileBytes, addr(10), 25, 50);
|
||||
mem.removeBlock(block1, TaskMonitor.DUMMY);
|
||||
assertEquals(0, mem.getBlocks().length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutByteToFileBytesBlockAndGetBothChangedAndOriginalValues() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
MemoryBlock block = createFileBytesBlock(fileBytes, addr(0), 0, 50);
|
||||
byte[] bytes = new byte[20];
|
||||
block.getBytes(addr(0), bytes);
|
||||
checkBytes(bytes, 0);
|
||||
block.getBytes(addr(20), bytes);
|
||||
checkBytes(bytes, 20);
|
||||
|
||||
block.putBytes(addr(0), bytes);
|
||||
block.getBytes(addr(0), bytes);
|
||||
checkBytes(bytes, 20);
|
||||
fileBytes.getOriginalBytes(0, bytes);
|
||||
checkBytes(bytes, 0);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitAndJoinUnitializedBlock() throws Exception {
|
||||
MemoryBlock block = mem.createUninitializedBlock("test", addr(0), 40, false);
|
||||
mem.split(block, addr(10));
|
||||
MemoryBlock[] blocks = mem.getBlocks();
|
||||
assertEquals(2, blocks.length);
|
||||
assertEquals(addr(0), blocks[0].getStart());
|
||||
assertEquals(addr(10), blocks[1].getStart());
|
||||
assertEquals(10, blocks[0].getSize());
|
||||
assertEquals(30, blocks[1].getSize());
|
||||
assertTrue(!blocks[0].isInitialized());
|
||||
assertTrue(!blocks[1].isInitialized());
|
||||
|
||||
mem.join(blocks[0], blocks[1]);
|
||||
blocks = mem.getBlocks();
|
||||
assertEquals(1, blocks.length);
|
||||
assertEquals(addr(0), blocks[0].getStart());
|
||||
assertEquals(40, blocks[0].getSize());
|
||||
List<SourceInfo> sourceInfos = blocks[0].getSourceInfos();
|
||||
assertEquals(1, sourceInfos.size()); // make sure the sub blocks were merged
|
||||
}
|
||||
|
||||
private void checkBytes(byte[] bytes, int startingValue) {
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
assertEquals(startingValue + i, bytes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutBytesToFileBytesBlockAndGetBothChangedAndOriginalValues() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
MemoryBlock block = createFileBytesBlock(fileBytes, addr(0), 0, 50);
|
||||
assertEquals(0, block.getByte(addr(0)));
|
||||
block.putByte(addr(0), (byte) 55);
|
||||
assertEquals(55, block.getByte(addr(0)));
|
||||
assertEquals(0, fileBytes.getOriginalByte(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitOnSubBlockBoundary() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
MemoryBlock block1 = createFileBytesBlock(fileBytes, addr(0), 0, 10);
|
||||
MemoryBlock block2 = createFileBytesBlock(fileBytes, addr(10), 30, 10);
|
||||
mem.join(block1, block2);
|
||||
MemoryBlock[] blocks = mem.getBlocks();
|
||||
assertEquals(1, blocks.length);
|
||||
mem.split(blocks[0], addr(10));
|
||||
blocks = mem.getBlocks();
|
||||
assertEquals(2, blocks.length);
|
||||
assertEquals(1, blocks[0].getSourceInfos().size());
|
||||
assertEquals(1, blocks[1].getSourceInfos().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testByteMappedGetPutByte() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
MemoryBlock block1 = createFileBytesBlock(fileBytes, addr(0), 0, 10);
|
||||
MemoryBlock mappedBlock = mem.createByteMappedBlock("mapped", addr(100), addr(0), 20);
|
||||
assertEquals(5, mappedBlock.getByte(addr(105)));
|
||||
assertEquals(5, block1.getByte(addr(5)));
|
||||
mappedBlock.putByte(addr(105), (byte) 87);
|
||||
assertEquals(87, block1.getByte(addr(5)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testByteMappedGetPutBytes() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
MemoryBlock block1 = createFileBytesBlock(fileBytes, addr(0), 0, 50);
|
||||
MemoryBlock mappedBlock = mem.createByteMappedBlock("mapped", addr(100), addr(0), 20);
|
||||
byte[] bytes = new byte[10];
|
||||
mappedBlock.getBytes(addr(100), bytes);
|
||||
checkBytes(bytes, 0);
|
||||
|
||||
mappedBlock.putBytes(addr(105), bytes);
|
||||
block1.getBytes(addr(5), bytes);
|
||||
checkBytes(bytes, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testByteMappedJoin() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
createFileBytesBlock(fileBytes, addr(0), 0, 50);
|
||||
MemoryBlock mappedBlock1 = mem.createByteMappedBlock("mapped1", addr(100), addr(0), 10);
|
||||
MemoryBlock mappedBlock2 = mem.createByteMappedBlock("mapped2", addr(110), addr(10), 10);
|
||||
try {
|
||||
mem.join(mappedBlock1, mappedBlock2);
|
||||
fail("Expected exception when joining byte mapped blocks");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testByteMappedSplit() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
createFileBytesBlock(fileBytes, addr(0), 0, 50);
|
||||
MemoryBlock mappedBlock1 = mem.createByteMappedBlock("mapped1", addr(100), addr(0), 20);
|
||||
mem.split(mappedBlock1, addr(110));
|
||||
MemoryBlock[] blocks = mem.getBlocks();
|
||||
assertEquals(3, blocks.length);
|
||||
assertEquals(addr(110), blocks[2].getStart());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBitMappedGetPutByte() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
MemoryBlock block = createFileBytesBlock(fileBytes, addr(0), 0, 50);
|
||||
MemoryBlock mappedBlock = mem.createBitMappedBlock("mapped1", addr(100), addr(0), 20);
|
||||
|
||||
assertEquals(0, mappedBlock.getByte(addr(100)));
|
||||
assertEquals(0, mappedBlock.getByte(addr(101)));
|
||||
assertEquals(0, mappedBlock.getByte(addr(114)));
|
||||
assertEquals(1, mappedBlock.getByte(addr(108)));
|
||||
assertEquals(0, mappedBlock.getByte(addr(116)));
|
||||
|
||||
mappedBlock.putByte(addr(100), (byte) 4);
|
||||
assertEquals(1, block.getByte(addr(0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBitMappedGetPutBytes() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
MemoryBlock block = createFileBytesBlock(fileBytes, addr(0), 0, 50);
|
||||
MemoryBlock mappedBlock = mem.createBitMappedBlock("mapped1", addr(100), addr(0), 50);
|
||||
|
||||
byte[] bytes = new byte[8];
|
||||
|
||||
mappedBlock.getBytes(addr(108), bytes);
|
||||
assertEquals(1, bytes[0]);
|
||||
for (int i = 1; i < 8; i++) {
|
||||
assertEquals(0, bytes[i]);
|
||||
}
|
||||
for (int i = 0; i < 8; i++) {
|
||||
bytes[i] = 1;
|
||||
}
|
||||
mappedBlock.putBytes(addr(100), bytes);
|
||||
assertEquals(-1, block.getByte(addr(0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBitMappedJoin() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
createFileBytesBlock(fileBytes, addr(0), 0, 50);
|
||||
MemoryBlock mappedBlock1 = mem.createBitMappedBlock("mapped1", addr(100), addr(0), 16);
|
||||
MemoryBlock mappedBlock2 = mem.createBitMappedBlock("mapped2", addr(116), addr(2), 16);
|
||||
try {
|
||||
mem.join(mappedBlock1, mappedBlock2);
|
||||
fail("Expected exception when joining bit mapped blocks");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBitMappedSplit() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
createFileBytesBlock(fileBytes, addr(0), 0, 50);
|
||||
MemoryBlock mappedBlock1 = mem.createBitMappedBlock("mapped1", addr(100), addr(0), 16);
|
||||
try {
|
||||
mem.split(mappedBlock1, addr(108));
|
||||
fail("Expected exception when joining bit mapped blocks");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetByteSourceSetForFileBytesBlock() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
MemoryBlockDB block = (MemoryBlockDB) createFileBytesBlock(fileBytes, addr(0), 10, 50);
|
||||
|
||||
ByteSourceRangeList ranges = block.getByteSourceRangeList(addr(5), 10);
|
||||
|
||||
// we expect to get a single range ByteSourceSet pointing into the filebytes at offset
|
||||
// 15 (10 because block was created at filebytes:10 and 5 because we start at the 5th byte
|
||||
// in the block)
|
||||
|
||||
assertEquals(1, ranges.getRangeCount());
|
||||
assertEquals(10, ranges.get(0).getSize());
|
||||
assertEquals(5, ranges.get(0).getStart().getOffset());
|
||||
assertEquals(14, ranges.get(0).getEnd().getOffset());
|
||||
assertEquals(fileBytes.getId(), ranges.get(0).getSourceId());
|
||||
assertEquals(15, ranges.get(0).getOffset());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetByteSourceSetForBufferBlock() throws Exception {
|
||||
MemoryBlockDB block = (MemoryBlockDB) mem.createInitializedBlock("test", addr(0), 30,
|
||||
(byte) 1, TaskMonitor.DUMMY, false);
|
||||
|
||||
ByteSourceRangeList ranges = block.getByteSourceRangeList(addr(10), 10);
|
||||
|
||||
// We expect to get to ranges because we made the buffer size small (16) so when we
|
||||
// created a 30 size block, it had to make two separate sub blocks each with its own
|
||||
// DBBuffer. The first range should contain the first 6 bytes of the requested range
|
||||
// and the second buffer should contain the last 4 bytes of request range.
|
||||
|
||||
assertEquals(2, ranges.getRangeCount()); // we have two sublocks so two distinct ranges
|
||||
assertEquals(10, ranges.get(0).getSize() + ranges.get(1).getSize());
|
||||
|
||||
|
||||
ByteSourceRange range = ranges.get(0);
|
||||
assertEquals(10, range.getStart().getOffset());
|
||||
assertEquals(15, range.getEnd().getOffset());
|
||||
assertEquals(6, range.getSize());
|
||||
assertEquals(10, range.getOffset());
|
||||
|
||||
range = ranges.get(1);
|
||||
assertEquals(16, range.getStart().getOffset());
|
||||
assertEquals(19, range.getEnd().getOffset());
|
||||
assertEquals(4, range.getSize());
|
||||
assertEquals(0, range.getOffset());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetByteSourceForUndefinedBlock() throws Exception {
|
||||
MemoryBlockDB block =
|
||||
(MemoryBlockDB) mem.createUninitializedBlock("test", addr(0), 30, false);
|
||||
ByteSourceRangeList ranges = block.getByteSourceRangeList(addr(10), 10);
|
||||
// undefined blocks have no source bytes
|
||||
assertTrue(ranges.isEmpty());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetByteSourceForByteMappedBlock() throws Exception {
|
||||
mem.createInitializedBlock("test1", addr(0), 15, (byte) 1, TaskMonitor.DUMMY, false);
|
||||
mem.createUninitializedBlock("test2", addr(15), 20, false);
|
||||
mem.createInitializedBlock("test3", addr(35), 15, (byte) 1, TaskMonitor.DUMMY, false);
|
||||
MemoryBlockDB block =
|
||||
(MemoryBlockDB) mem.createByteMappedBlock("mapped", addr(1000), addr(5), 40);
|
||||
|
||||
ByteSourceRangeList ranges = block.getByteSourceRangeList(addr(1005), 30);
|
||||
|
||||
// Uninitialized blocks don't contribute, so we should have 10 address (5 from first and last blocks each).
|
||||
assertEquals(2, ranges.getRangeCount());
|
||||
assertEquals(10, ranges.get(0).getSize() + ranges.get(1).getSize());
|
||||
|
||||
ByteSourceRange range = ranges.get(0);
|
||||
assertEquals(addr(1005), range.getStart());
|
||||
assertEquals(addr(1009), range.getEnd());
|
||||
assertEquals(5, range.getSize());
|
||||
assertEquals(10, range.getOffset());
|
||||
|
||||
range = ranges.get(1);
|
||||
assertEquals(addr(1030), range.getStart());
|
||||
assertEquals(addr(1034), range.getEnd());
|
||||
assertEquals(5, range.getSize());
|
||||
assertEquals(0, range.getOffset());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetByteSourceForBitMappedBlock() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
createFileBytesBlock(fileBytes, addr(0), 0, 50);
|
||||
|
||||
MemoryBlockDB block =
|
||||
(MemoryBlockDB) mem.createBitMappedBlock("mapped", addr(0x1000), addr(5), 0x14);
|
||||
|
||||
ByteSourceRangeList ranges = block.getByteSourceRangeList(addr(0x1000), 0x14);
|
||||
|
||||
assertEquals(1, ranges.getRangeCount());
|
||||
assertEquals(3, ranges.get(0).getSize());
|
||||
|
||||
ByteSourceRange range = ranges.get(0);
|
||||
assertEquals(addr(0x1000), range.getStart());
|
||||
assertEquals(addr(0x1017), range.getEnd());
|
||||
assertEquals(3, range.getSize());
|
||||
assertEquals(5, range.getOffset());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetByteSourceForBitMappedBlockOffcutStart() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
createFileBytesBlock(fileBytes, addr(0), 0, 50);
|
||||
|
||||
MemoryBlockDB block =
|
||||
(MemoryBlockDB) mem.createBitMappedBlock("mapped", addr(0x1000), addr(5), 0x14);
|
||||
|
||||
ByteSourceRangeList ranges = block.getByteSourceRangeList(addr(0x1005), 8);
|
||||
|
||||
assertEquals(1, ranges.getRangeCount());
|
||||
assertEquals(2, ranges.get(0).getSize());
|
||||
|
||||
ByteSourceRange range = ranges.get(0);
|
||||
assertEquals(addr(0x1000), range.getStart());
|
||||
assertEquals(addr(0x100f), range.getEnd());
|
||||
assertEquals(2, range.getSize());
|
||||
assertEquals(5, range.getOffset());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetByteSourceForBitMappedBlockOffcutStartNotAtStart() throws Exception {
|
||||
FileBytes fileBytes = createFileBytes();
|
||||
createFileBytesBlock(fileBytes, addr(0), 0, 50);
|
||||
|
||||
MemoryBlockDB block =
|
||||
(MemoryBlockDB) mem.createBitMappedBlock("mapped", addr(0x1000), addr(5), 0x44);
|
||||
|
||||
ByteSourceRangeList ranges = block.getByteSourceRangeList(addr(0x1015), 8);
|
||||
|
||||
assertEquals(1, ranges.getRangeCount());
|
||||
assertEquals(2, ranges.get(0).getSize());
|
||||
|
||||
ByteSourceRange range = ranges.get(0);
|
||||
assertEquals(addr(0x1010), range.getStart());
|
||||
assertEquals(addr(0x101f), range.getEnd());
|
||||
assertEquals(2, range.getSize());
|
||||
assertEquals(7, range.getOffset());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetByteSourceForBitMappedBlock2() throws Exception {
|
||||
mem.createInitializedBlock("test1", addr(0), 4, (byte) 1, TaskMonitor.DUMMY, false);
|
||||
mem.createUninitializedBlock("test2", addr(0x4), 4, false);
|
||||
mem.createInitializedBlock("test3", addr(0x8), 4, (byte) 1, TaskMonitor.DUMMY, false);
|
||||
MemoryBlockDB block =
|
||||
(MemoryBlockDB) mem.createBitMappedBlock("mapped", addr(0x1000), addr(2), 0x40);
|
||||
|
||||
ByteSourceRangeList ranges = block.getByteSourceRangeList(addr(0x1008), 0x30);
|
||||
|
||||
assertEquals(2, ranges.getRangeCount());
|
||||
|
||||
ByteSourceRange range = ranges.get(0);
|
||||
assertEquals(addr(0x1008), range.getStart());
|
||||
assertEquals(addr(0x100f), range.getEnd());
|
||||
assertEquals(1, range.getSize());
|
||||
assertEquals(3, range.getOffset());
|
||||
|
||||
range = ranges.get(1);
|
||||
assertEquals(addr(0x1030), range.getStart());
|
||||
assertEquals(addr(0x1037), range.getEnd());
|
||||
assertEquals(1, range.getSize());
|
||||
assertEquals(0, range.getOffset());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetByteSourceForBitMappedBlock2Offcut() throws Exception {
|
||||
mem.createInitializedBlock("test1", addr(0), 4, (byte) 1, TaskMonitor.DUMMY, false);
|
||||
mem.createUninitializedBlock("test2", addr(0x4), 4, false);
|
||||
mem.createInitializedBlock("test3", addr(0x8), 4, (byte) 1, TaskMonitor.DUMMY, false);
|
||||
MemoryBlockDB block =
|
||||
(MemoryBlockDB) mem.createBitMappedBlock("mapped", addr(0x1000), addr(2), 0x40);
|
||||
|
||||
ByteSourceRangeList ranges = block.getByteSourceRangeList(addr(0x1006), 0x34);
|
||||
|
||||
assertEquals(2, ranges.getRangeCount());
|
||||
|
||||
ByteSourceRange range = ranges.get(0);
|
||||
assertEquals(addr(0x1000), range.getStart());
|
||||
assertEquals(addr(0x100f), range.getEnd());
|
||||
assertEquals(2, range.getSize());
|
||||
assertEquals(2, range.getOffset());
|
||||
|
||||
range = ranges.get(1);
|
||||
assertEquals(addr(0x1030), range.getStart());
|
||||
assertEquals(addr(0x103f), range.getEnd());
|
||||
assertEquals(2, range.getSize());
|
||||
assertEquals(0, range.getOffset());
|
||||
}
|
||||
private MemoryBlock createFileBytesBlock(FileBytes fileBytes, Address addr, int offset,
|
||||
int length) throws Exception {
|
||||
return mem.createInitializedBlock("test" + addr.toString(), addr, fileBytes, offset, length,
|
||||
false);
|
||||
}
|
||||
|
||||
private FileBytes createFileBytes() throws IOException {
|
||||
byte[] bytes = new byte[256];
|
||||
for (int i = 0; i < 256; i++) {
|
||||
bytes[i] = (byte) i;
|
||||
}
|
||||
FileBytes fileBytes = mem.createFileBytes("test", 0, 100, new ByteArrayInputStream(bytes));
|
||||
return fileBytes;
|
||||
}
|
||||
|
||||
private Address addr(long offset) {
|
||||
return addressFactory.getDefaultAddressSpace().getAddress(offset);
|
||||
}
|
||||
|
||||
private Language getLanguage(String languageName) throws Exception {
|
||||
|
||||
ResourceFile ldefFile = Application.getModuleDataFile("Toy", "languages/toy.ldefs");
|
||||
if (ldefFile != null) {
|
||||
LanguageService languageService = DefaultLanguageService.getLanguageService(ldefFile);
|
||||
Language language = languageService.getLanguage(new LanguageID(languageName));
|
||||
return language;
|
||||
}
|
||||
throw new LanguageNotFoundException("Unsupported test language: " + languageName);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue