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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -18,6 +18,7 @@ package ghidra.program.database.mem;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.util.Arrays;
import java.util.List; import java.util.List;
import org.junit.*; 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 @Test
public void testJoinFileBytes() throws Exception { public void testJoinFileBytes() throws Exception {
FileBytes fileBytes = createFileBytes(); FileBytes fileBytes = createFileBytes();