fixing issues in memory sub-blocks

This commit is contained in:
ghidravore 2019-10-23 15:05:14 -04:00
parent 083b5f61cc
commit c73f0381d0
10 changed files with 137 additions and 89 deletions

View File

@ -45,13 +45,14 @@ class BitMappedSubMemoryBlock extends SubMemoryBlock {
}
@Override
public byte getByte(long offset) throws MemoryAccessException, IOException {
public byte getByte(long offsetInMemBlock) throws MemoryAccessException, IOException {
long offsetInSubBlock = offsetInMemBlock - subBlockOffset;
if (ioPending) {
throw new MemoryAccessException("Cyclic Access");
}
try {
ioPending = true;
return getBitOverlayByte(offset);
return getBitOverlayByte(offsetInSubBlock);
}
catch (AddressOverflowException e) {
throw new MemoryAccessException("No memory at address");
@ -62,21 +63,23 @@ class BitMappedSubMemoryBlock extends SubMemoryBlock {
}
public AddressRange getMappedRange() {
Address endMappedAddress = mappedAddress.add((length - 1) / 8);
Address endMappedAddress = mappedAddress.add((subBlockLength - 1) / 8);
return new AddressRangeImpl(mappedAddress, endMappedAddress);
}
@Override
public int getBytes(long offset, byte[] b, int off, int len)
public int getBytes(long offsetInMemBlock, byte[] b, int off, int len)
throws MemoryAccessException, IOException {
long offsetInSubBlock = offsetInMemBlock - subBlockOffset;
long available = subBlockLength - offsetInSubBlock;
len = (int) Math.min(len, available);
if (ioPending) {
new MemoryAccessException("Cyclic Access");
}
try {
ioPending = true;
len = (int) Math.min(len, length - offset);
for (int i = 0; i < len; i++) {
b[i + off] = getBitOverlayByte(offset++);
b[i + off] = getBitOverlayByte(offsetInMemBlock++);
}
return len;
}
@ -89,13 +92,15 @@ class BitMappedSubMemoryBlock extends SubMemoryBlock {
}
@Override
public void putByte(long offset, byte b) throws MemoryAccessException, IOException {
public void putByte(long offsetInMemBlock, byte b) throws MemoryAccessException, IOException {
long offsetInSubBlock = offsetInMemBlock - subBlockOffset;
try {
if (ioPending) {
new MemoryAccessException("Cyclic Access");
}
ioPending = true;
doPutByte(mappedAddress.addNoWrap(offset / 8), (int) (offset % 8), b);
doPutByte(mappedAddress.addNoWrap(offsetInSubBlock / 8), (int) (offsetInSubBlock % 8),
b);
}
catch (AddressOverflowException e) {
new MemoryAccessException("No memory at address");
@ -107,17 +112,20 @@ class BitMappedSubMemoryBlock extends SubMemoryBlock {
}
@Override
public int putBytes(long offset, byte[] b, int off, int len)
public int putBytes(long offsetInMemBlock, byte[] b, int off, int len)
throws MemoryAccessException, IOException {
long offsetInSubBlock = offsetInMemBlock - subBlockOffset;
long available = subBlockLength - offsetInSubBlock;
len = (int) Math.min(len, available);
try {
if (ioPending) {
new MemoryAccessException("Cyclic Access");
}
ioPending = true;
len = (int) Math.min(len, length - offset);
for (int i = 0; i < len; i++) {
doPutByte(mappedAddress.addNoWrap(offset / 8), (int) (offset % 8), b[off + i]);
offset++;
doPutByte(mappedAddress.addNoWrap(offsetInSubBlock / 8),
(int) (offsetInSubBlock % 8), b[off + i]);
offsetInSubBlock++;
}
return len;
}

View File

@ -41,26 +41,32 @@ class BufferSubMemoryBlock extends SubMemoryBlock {
}
@Override
public byte getByte(long offset) throws IOException {
return buf.getByte((int) (offset - startingOffset));
public byte getByte(long offsetInMemBlock) throws IOException {
long offsetInSubBlock = offsetInMemBlock - subBlockOffset;
return buf.getByte((int) offsetInSubBlock);
}
@Override
public int getBytes(long offset, byte[] b, int off, int len) throws IOException {
len = Math.min(len, (int) (length - (offset - startingOffset)));
buf.get((int) (offset - startingOffset), b, off, len);
public int getBytes(long offsetInMemBlock, byte[] b, int off, int len) throws IOException {
long offsetInSubBlock = offsetInMemBlock - subBlockOffset;
long available = subBlockLength - offsetInSubBlock;
len = (int) Math.min(len, available);
buf.get((int) offsetInSubBlock, b, off, len);
return len;
}
@Override
public void putByte(long offset, byte b) throws IOException {
buf.putByte((int) (offset - startingOffset), b);
public void putByte(long offsetInMemBlock, byte b) throws IOException {
long offsetInSubBlock = offsetInMemBlock - subBlockOffset;
buf.putByte((int) offsetInSubBlock, b);
}
@Override
public int putBytes(long offset, byte[] b, int off, int len) throws IOException {
len = Math.min(len, (int) (length - offset - startingOffset));
buf.put((int) (offset - startingOffset), b, off, len);
public int putBytes(long offsetInMemBlock, byte[] b, int off, int len) throws IOException {
long offsetInSubBlock = offsetInMemBlock - subBlockOffset;
long available = subBlockLength - offsetInSubBlock;
len = (int) Math.min(len, available);
buf.put((int) offsetInSubBlock, b, off, len);
return len;
}
@ -76,11 +82,11 @@ class BufferSubMemoryBlock extends SubMemoryBlock {
return false;
}
BufferSubMemoryBlock other = (BufferSubMemoryBlock) block;
if (other.length + length > Memory.GBYTE) {
if (other.subBlockLength + subBlockLength > Memory.GBYTE) {
return false;
}
buf.append(other.buf);
setLength(length + other.length);
setLength(subBlockLength + other.subBlockLength);
adapter.deleteSubBlock(other.record.getKey());
return true;
}
@ -97,10 +103,10 @@ class BufferSubMemoryBlock extends SubMemoryBlock {
@Override
protected SubMemoryBlock split(long memBlockOffset) throws IOException {
// convert from offset in block to offset in this sub block
int offset = (int) (memBlockOffset - startingOffset);
long newLength = length - offset;
length = offset;
record.setLongValue(MemoryMapDBAdapter.SUB_LENGTH_COL, length);
int offset = (int) (memBlockOffset - subBlockOffset);
long newLength = subBlockLength - offset;
subBlockLength = offset;
record.setLongValue(MemoryMapDBAdapter.SUB_LENGTH_COL, subBlockLength);
adapter.updateSubBlockRecord(record);
DBBuffer split = buf.split(offset);
@ -122,8 +128,7 @@ class BufferSubMemoryBlock extends SubMemoryBlock {
long size) {
long sourceId = -buf.getId(); // buffers use negative id values; FileBytes use positive id values.
ByteSourceRange bsRange =
new ByteSourceRange(block, start, size, sourceId, memBlockOffset - startingOffset);
new ByteSourceRange(block, start, size, sourceId, memBlockOffset - subBlockOffset);
return new ByteSourceRangeList(bsRange);
}
}

View File

@ -46,13 +46,14 @@ class ByteMappedSubMemoryBlock extends SubMemoryBlock {
}
@Override
public byte getByte(long offset) throws MemoryAccessException, IOException {
public byte getByte(long offsetInMemBlock) throws MemoryAccessException, IOException {
long offsetInSubBlock = offsetInMemBlock - subBlockOffset;
if (ioPending) {
new MemoryAccessException("Cyclic Access");
}
try {
ioPending = true;
return memMap.getByte(mappedAddress.addNoWrap(offset - startingOffset));
return memMap.getByte(mappedAddress.addNoWrap(offsetInSubBlock));
}
catch (AddressOverflowException e) {
throw new MemoryAccessException("No memory at address");
@ -63,15 +64,17 @@ class ByteMappedSubMemoryBlock extends SubMemoryBlock {
}
@Override
public int getBytes(long offset, byte[] b, int off, int len)
public int getBytes(long offsetInMemBlock, byte[] b, int off, int len)
throws MemoryAccessException, IOException {
long offsetInSubBlock = offsetInMemBlock - subBlockOffset;
long available = subBlockLength - offsetInSubBlock;
len = (int) Math.min(len, available);
if (ioPending) {
new MemoryAccessException("Cyclic Access");
}
try {
ioPending = true;
len = (int) Math.min(len, length - (offset - startingOffset));
return memMap.getBytes(mappedAddress.addNoWrap(offset), b, off, len);
return memMap.getBytes(mappedAddress.addNoWrap(offsetInSubBlock), b, off, len);
}
catch (AddressOverflowException e) {
throw new MemoryAccessException("No memory at address");
@ -82,13 +85,14 @@ class ByteMappedSubMemoryBlock extends SubMemoryBlock {
}
@Override
public void putByte(long offset, byte b) throws MemoryAccessException, IOException {
public void putByte(long offsetInMemBlock, byte b) throws MemoryAccessException, IOException {
long offsetInSubBlock = offsetInMemBlock - subBlockOffset;
try {
if (ioPending) {
new MemoryAccessException("Cyclic Access");
}
ioPending = true;
memMap.setByte(mappedAddress.addNoWrap(offset - startingOffset), b);
memMap.setByte(mappedAddress.addNoWrap(offsetInSubBlock), b);
}
catch (AddressOverflowException e) {
throw new MemoryAccessException("No memory at address");
@ -100,15 +104,18 @@ class ByteMappedSubMemoryBlock extends SubMemoryBlock {
}
@Override
public int putBytes(long offset, byte[] b, int off, int len)
public int putBytes(long offsetInMemBlock, byte[] b, int off, int len)
throws MemoryAccessException, IOException {
long offsetInSubBlock = offsetInMemBlock - subBlockOffset;
long available = subBlockLength - offsetInSubBlock;
len = (int) Math.min(len, available);
try {
if (ioPending) {
new MemoryAccessException("Cyclic Access");
}
ioPending = true;
len = (int) Math.min(len, length - (offset - startingOffset));
memMap.setBytes(mappedAddress.addNoWrap(offset - startingOffset), b, off, len);
memMap.setBytes(mappedAddress.addNoWrap(offsetInSubBlock), b, off,
len);
return len;
}
catch (AddressOverflowException e) {
@ -120,7 +127,7 @@ class ByteMappedSubMemoryBlock extends SubMemoryBlock {
}
public AddressRange getMappedRange() {
Address endMappedAddress = mappedAddress.add(length - 1);
Address endMappedAddress = mappedAddress.add(subBlockLength - 1);
return new AddressRangeImpl(mappedAddress, endMappedAddress);
}
@ -142,10 +149,10 @@ class ByteMappedSubMemoryBlock extends SubMemoryBlock {
@Override
protected SubMemoryBlock split(long memBlockOffset) throws IOException {
// convert from offset in block to offset in this sub block
int offset = (int) (memBlockOffset - startingOffset);
long newLength = length - offset;
length = offset;
record.setLongValue(MemoryMapDBAdapter.SUB_LENGTH_COL, length);
int offset = (int) (memBlockOffset - subBlockOffset);
long newLength = subBlockLength - offset;
subBlockLength = offset;
record.setLongValue(MemoryMapDBAdapter.SUB_LENGTH_COL, subBlockLength);
adapter.updateSubBlockRecord(record);
Address newAddr = mappedAddress.add(offset);
@ -167,7 +174,7 @@ class ByteMappedSubMemoryBlock extends SubMemoryBlock {
protected ByteSourceRangeList getByteSourceRangeList(MemoryBlock block, Address start,
long offset, long size) {
ByteSourceRangeList result = new ByteSourceRangeList();
long relativeOffset = offset - startingOffset;
long relativeOffset = offset - subBlockOffset;
Address startAddress = mappedAddress.add(relativeOffset);
Address endAddress = startAddress.add(size - 1);
List<MemoryBlockDB> blocks = memMap.getBlocks(startAddress, endAddress);

View File

@ -41,24 +41,31 @@ class FileBytesSubMemoryBlock extends SubMemoryBlock {
}
@Override
public byte getByte(long memBlockOffset) throws IOException {
return fileBytes.getModifiedByte(fileBytesOffset + memBlockOffset - startingOffset);
public byte getByte(long offsetInMemBlock) throws IOException {
long offsetInSubBlock = offsetInMemBlock - subBlockOffset;
return fileBytes.getModifiedByte(fileBytesOffset + offsetInSubBlock);
}
@Override
public int getBytes(long memBlockOffset, byte[] b, int off, int len) throws IOException {
return fileBytes.getModifiedBytes(fileBytesOffset + memBlockOffset - startingOffset, b, off,
len);
public int getBytes(long offsetInMemBlock, byte[] b, int off, int len) throws IOException {
long offsetInSubBlock = offsetInMemBlock - subBlockOffset;
long available = subBlockLength - offsetInSubBlock;
len = (int) Math.min(len, available);
return fileBytes.getModifiedBytes(fileBytesOffset + offsetInSubBlock, b, off, len);
}
@Override
public void putByte(long memBlockOffset, byte b) throws MemoryAccessException, IOException {
fileBytes.putByte(fileBytesOffset + memBlockOffset - startingOffset, b);
public void putByte(long offsetInMemBlock, byte b) throws MemoryAccessException, IOException {
long offsetInSubBlock = offsetInMemBlock - subBlockOffset;
fileBytes.putByte(fileBytesOffset + offsetInSubBlock, b);
}
@Override
public int putBytes(long memBlockOffset, byte[] b, int off, int len) throws IOException {
return fileBytes.putBytes(fileBytesOffset + memBlockOffset - startingOffset, b, off, len);
public int putBytes(long offsetInMemBlock, byte[] b, int off, int len) throws IOException {
long offsetInSubBlock = offsetInMemBlock - subBlockOffset;
long available = subBlockLength - offsetInSubBlock;
len = (int) Math.min(len, available);
return fileBytes.putBytes(fileBytesOffset + offsetInSubBlock, b, off, len);
}
@Override
@ -71,11 +78,11 @@ class FileBytesSubMemoryBlock extends SubMemoryBlock {
return false;
}
// are the two block consecutive in the fileBytes space?
if (other.fileBytesOffset != fileBytesOffset + length) {
if (other.fileBytesOffset != fileBytesOffset + subBlockLength) {
return false;
}
// ok we can join them
setLength(length + other.length);
setLength(subBlockLength + other.subBlockLength);
adapter.deleteSubBlock(other.record.getKey());
return true;
}
@ -96,10 +103,10 @@ class FileBytesSubMemoryBlock extends SubMemoryBlock {
@Override
protected SubMemoryBlock split(long memBlockOffset) throws IOException {
// convert from offset in block to offset in this sub block
int offset = (int) (memBlockOffset - startingOffset);
long newLength = length - offset;
length = offset;
record.setLongValue(MemoryMapDBAdapter.SUB_LENGTH_COL, length);
int offset = (int) (memBlockOffset - subBlockOffset);
long newLength = subBlockLength - offset;
subBlockLength = offset;
record.setLongValue(MemoryMapDBAdapter.SUB_LENGTH_COL, subBlockLength);
adapter.updateSubBlockRecord(record);
int fileBytesID = record.getIntValue(MemoryMapDBAdapter.SUB_SOURCE_ID_COL);
@ -128,9 +135,8 @@ class FileBytesSubMemoryBlock extends SubMemoryBlock {
long size) {
long sourceId = fileBytes.getId();
ByteSourceRange bsRange = new ByteSourceRange(block, start, size, sourceId,
fileBytesOffset + memBlockOffset - startingOffset);
fileBytesOffset + memBlockOffset - subBlockOffset);
return new ByteSourceRangeList(bsRange);
}
}

View File

@ -631,7 +631,7 @@ public class MemoryBlockDB implements MemoryBlock {
long startingOffset = 0;
for (SubMemoryBlock subBlock : subBlocks) {
subBlock.setParentIdAndStartingOffset(id, startingOffset);
startingOffset += subBlock.length;
startingOffset += subBlock.subBlockLength;
}
}
@ -692,7 +692,7 @@ public class MemoryBlockDB implements MemoryBlock {
size = Math.min(size, length - offset);
SubMemoryBlock subBlock = getSubBlock(offset);
long subSize = Math.min(size, subBlock.length - (offset - subBlock.getStartingOffset()));
long subSize = Math.min(size, subBlock.subBlockLength - (offset - subBlock.getStartingOffset()));
if (subSize == size) {
return subBlock.getByteSourceRangeList(this, address, offset, size);
}
@ -702,7 +702,7 @@ public class MemoryBlockDB implements MemoryBlock {
long total = subSize;
while (total < size) {
subBlock = getSubBlock(offset + total);
subSize = Math.min(size - total, subBlock.length);
subSize = Math.min(size - total, subBlock.subBlockLength);
start = address.add(total);
set.add(subBlock.getByteSourceRangeList(this, start, offset + total, subSize));
total += subSize;

View File

@ -40,7 +40,7 @@ class MemoryBlockSourceInfoDB implements MemoryBlockSourceInfo {
*/
@Override
public long getLength() {
return subBlock.length;
return subBlock.subBlockLength;
}
/**
@ -48,7 +48,7 @@ class MemoryBlockSourceInfoDB implements MemoryBlockSourceInfo {
*/
@Override
public Address getMinAddress() {
return block.getStart().add(subBlock.startingOffset);
return block.getStart().add(subBlock.subBlockOffset);
}
/**
@ -56,7 +56,7 @@ class MemoryBlockSourceInfoDB implements MemoryBlockSourceInfo {
*/
@Override
public Address getMaxAddress() {
return block.getStart().add(subBlock.startingOffset + subBlock.length - 1);
return block.getStart().add(subBlock.subBlockOffset + subBlock.subBlockLength - 1);
}
/**
@ -104,7 +104,7 @@ class MemoryBlockSourceInfoDB implements MemoryBlockSourceInfo {
public long getFileBytesOffset(Address address) {
if (subBlock instanceof FileBytesSubMemoryBlock && contains(address)) {
long blockOffset = address.subtract(getMinAddress());
long subBlockOffset = blockOffset - subBlock.startingOffset;
long subBlockOffset = blockOffset - subBlock.subBlockOffset;
return ((FileBytesSubMemoryBlock) subBlock).getFileBytesOffset() + subBlockOffset;
}
return -1;

View File

@ -249,7 +249,7 @@ public class MemoryMapDBAdapterV3 extends MemoryMapDBAdapter {
long startingOffset = 0;
for (SubMemoryBlock subMemoryBlock : splitBlocks) {
subMemoryBlock.setParentIdAndStartingOffset(key, startingOffset);
startingOffset += subMemoryBlock.length;
startingOffset += subMemoryBlock.subBlockLength;
}
memBlockTable.putRecord(blockRecord);

View File

@ -30,14 +30,14 @@ abstract class SubMemoryBlock implements Comparable<SubMemoryBlock> {
protected final MemoryMapDBAdapter adapter;
protected final Record record;
protected long length;
protected long startingOffset;
protected long subBlockLength;
protected long subBlockOffset;
protected SubMemoryBlock(MemoryMapDBAdapter adapter, Record record) {
this.adapter = adapter;
this.record = record;
this.startingOffset = record.getLongValue(MemoryMapDBAdapter.SUB_START_OFFSET_COL);
this.length = record.getLongValue(MemoryMapDBAdapter.SUB_LENGTH_COL);
this.subBlockOffset = record.getLongValue(MemoryMapDBAdapter.SUB_START_OFFSET_COL);
this.subBlockLength = record.getLongValue(MemoryMapDBAdapter.SUB_LENGTH_COL);
}
/**
@ -62,7 +62,7 @@ abstract class SubMemoryBlock implements Comparable<SubMemoryBlock> {
* @return the starting offset for this sub block.
*/
public final long getStartingOffset() {
return startingOffset;
return subBlockOffset;
}
/**
@ -70,7 +70,7 @@ abstract class SubMemoryBlock implements Comparable<SubMemoryBlock> {
* @return the length of this sub block
*/
public final long getLength() {
return length;
return subBlockLength;
}
/**
@ -80,7 +80,7 @@ abstract class SubMemoryBlock implements Comparable<SubMemoryBlock> {
* @return true if the offset is valid for this block
*/
public final boolean contains(long memBlockOffset) {
return memBlockOffset >= startingOffset && memBlockOffset < startingOffset + length;
return memBlockOffset >= subBlockOffset && memBlockOffset < subBlockOffset + subBlockLength;
}
/**
@ -158,7 +158,7 @@ abstract class SubMemoryBlock implements Comparable<SubMemoryBlock> {
* @throws IOException if a database error occurs
*/
protected void setLength(long length) throws IOException {
this.length = length;
this.subBlockLength = length;
record.setLongValue(MemoryMapDBAdapter.SUB_LENGTH_COL, length);
adapter.updateSubBlockRecord(record);
}
@ -216,7 +216,7 @@ abstract class SubMemoryBlock implements Comparable<SubMemoryBlock> {
* @throws IOException if a database error occurs.
*/
protected void setParentIdAndStartingOffset(long key, long startingOffset) throws IOException {
this.startingOffset = startingOffset;
this.subBlockOffset = startingOffset;
record.setLongValue(MemoryMapDBAdapter.SUB_PARENT_ID_COL, key);
record.setLongValue(MemoryMapDBAdapter.SUB_START_OFFSET_COL, startingOffset);
adapter.updateSubBlockRecord(record);

View File

@ -28,7 +28,7 @@ class UninitializedSubMemoryBlock extends SubMemoryBlock {
UninitializedSubMemoryBlock(MemoryMapDBAdapter adapter, Record record) {
super(adapter, record);
startingOffset = record.getLongValue(MemoryMapDBAdapter.SUB_START_OFFSET_COL);
subBlockOffset = record.getLongValue(MemoryMapDBAdapter.SUB_START_OFFSET_COL);
}
@Override
@ -38,10 +38,10 @@ class UninitializedSubMemoryBlock extends SubMemoryBlock {
@Override
public byte getByte(long offset) throws MemoryAccessException {
if (offset < startingOffset || offset >= startingOffset + length) {
if (offset < subBlockOffset || offset >= subBlockOffset + subBlockLength) {
throw new IllegalArgumentException(
"Offset " + offset + "is out of bounds. Should be in [" + startingOffset + "," +
(startingOffset + length - 1));
"Offset " + offset + "is out of bounds. Should be in [" + subBlockOffset + "," +
(subBlockOffset + subBlockLength - 1));
}
throw new MemoryAccessException("Attempted to read from uninitialized block");
}
@ -66,7 +66,7 @@ class UninitializedSubMemoryBlock extends SubMemoryBlock {
if (!(block instanceof UninitializedSubMemoryBlock)) {
return false;
}
setLength(length + block.length);
setLength(subBlockLength + block.subBlockLength);
adapter.deleteSubBlock(block.record.getKey());
return true;
}
@ -79,10 +79,10 @@ class UninitializedSubMemoryBlock extends SubMemoryBlock {
@Override
protected SubMemoryBlock split(long memBlockOffset) throws IOException {
// convert from offset in block to offset in this sub block
long offset = memBlockOffset - startingOffset;
long newLength = length - offset;
length = offset;
record.setLongValue(MemoryMapDBAdapter.SUB_LENGTH_COL, length);
long offset = memBlockOffset - subBlockOffset;
long newLength = subBlockLength - offset;
subBlockLength = offset;
record.setLongValue(MemoryMapDBAdapter.SUB_LENGTH_COL, subBlockLength);
adapter.updateSubBlockRecord(record);
Record newSubRecord = adapter.createSubBlockRecord(-1, 0, newLength,

View File

@ -18,6 +18,7 @@ package ghidra.program.database.mem;
import static org.junit.Assert.*;
import java.io.ByteArrayInputStream;
import java.util.Arrays;
import java.util.List;
import org.junit.*;
@ -315,6 +316,27 @@ public class MemBlockDBTest extends AbstractGenericTest {
}
}
@Test
public void testWriteBytesAcrossSubBlocks() throws Exception {
FileBytes fileBytes = createFileBytes();
MemoryBlock block1 = createFileBytesBlock(fileBytes, addr(10), 25, 10);
MemoryBlock block2 = createFileBytesBlock(fileBytes, addr(20), 50, 10);
mem.join(block1, block2);
byte[] bytes = createBytes(20);
mem.setBytes(addr(10), bytes);
byte[] readBytes = new byte[20];
mem.getBytes(addr(10), readBytes);
assertTrue(Arrays.equals(bytes, readBytes));
}
private byte[] createBytes(int size) {
byte[] bytes = new byte[size];
for (int i = 0; i < size; i++) {
bytes[i] = (byte) i;
}
return bytes;
}
@Test
public void testJoinFileBytes() throws Exception {
FileBytes fileBytes = createFileBytes();