Added feature to show file offsets in address hover in listing

This commit is contained in:
ghidravore 2019-07-18 15:50:59 -04:00
parent 3eafdaae37
commit 57e2171dd4
24 changed files with 357 additions and 75 deletions

View file

@ -20,7 +20,7 @@ import java.util.Arrays;
import ghidra.pcode.error.LowlevelError;
import ghidra.pcode.memstate.MemoryFaultHandler;
import ghidra.pcode.memstate.MemoryPage;
import ghidra.program.database.mem.SourceInfo;
import ghidra.program.database.mem.MemoryBlockSourceInfo;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.*;
@ -48,7 +48,7 @@ public class ProgramLoadImage {
}
private AddressSetView addMappedInitializedMemory(MemoryBlock mappedBlock) {
SourceInfo sourceInfo = mappedBlock.getSourceInfos().get(0); // mapped block has exactly 1 mapped source
MemoryBlockSourceInfo sourceInfo = mappedBlock.getSourceInfos().get(0); // mapped block has exactly 1 mapped source
if (!sourceInfo.getMappedRange().isPresent()) {
throw new AssertException("Mapped block did not have mapped range!");
}

View file

@ -20,7 +20,7 @@ import java.util.Arrays;
import ghidra.pcode.error.LowlevelError;
import ghidra.pcode.memstate.MemoryFaultHandler;
import ghidra.pcode.memstate.MemoryPage;
import ghidra.program.database.mem.SourceInfo;
import ghidra.program.database.mem.MemoryBlockSourceInfo;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.*;
@ -52,7 +52,7 @@ public class ProgramMappedMemory {
private AddressSetView addMappedInitializedMemory(MemoryBlock mappedBlock) {
AddressSet modifiedSet = new AddressSet(initializedAddressSet);
SourceInfo sourceInfo = mappedBlock.getSourceInfos().get(0); // mapped block has exactly 1 mapped source
MemoryBlockSourceInfo sourceInfo = mappedBlock.getSourceInfos().get(0); // mapped block has exactly 1 mapped source
if (!sourceInfo.getMappedRange().isPresent()) {
throw new AssertException("Mapped block did not have mapped range!");
}

View file

@ -0,0 +1,138 @@
/* ###
* 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 java.io.IOException;
import java.util.List;
import java.util.Optional;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryBlock;
/**
* Provides information about the source of a byte value at an address including the file it
* came from, the offset into that file, and the original value of that byte.
*/
public class AddressSourceInfo {
private Address address;
private MemoryBlock block;
private FileBytes fileBytes;
private MemoryBlockSourceInfo sourceInfo;
private AddressSourceInfo mappedInfo;
private Memory memory;
public AddressSourceInfo(Memory memory, Address address, MemoryBlock block) {
this.memory = memory;
this.address = address;
this.block = block;
sourceInfo = getContainingInfo();
fileBytes = sourceInfo.getFileBytes().orElse(null);
}
/**
* Returns the address for which this object provides byte source information.
* @return the address for which this object provides byte source information.
*/
public Address getAddress() {
return address;
}
/**
* Returns the offset into the originally imported file that provided the byte value for the
* associated address or -1 if there is no source information for this location.
* @return the offset into the originally imported file that provided the byte value for the
* associated address.
*/
public long getFileOffset() {
if (mappedInfo != null) {
return mappedInfo.getFileOffset();
}
if (fileBytes != null) {
return sourceInfo.getFileBytesOffset(address) + fileBytes.getFileOffset();
}
return -1;
}
/**
* Returns the filename of the originally imported file that provided the byte value for the
* associated address or null if there is no source information for this location.
* @return the filename of the originally imported file that provided the byte value for the
* associated address or null if there is no source information for this location.
*/
public String getFileName() {
if (mappedInfo != null) {
return mappedInfo.getFileName();
}
if (fileBytes != null) {
return fileBytes.getFilename();
}
return null;
}
/**
* Returns the original byte value from the imported file that provided the byte value for the
* associated address or 0 if there is no source information for this location.
* @return the original byte value from the imported file that provided the byte value for the
* associated address or 0 if there is no source information for this location.
* @throws IOException if an io error occurs reading the program database.
*/
public byte getOriginalValue() throws IOException {
if (mappedInfo != null) {
return mappedInfo.getOriginalValue();
}
if (fileBytes != null) {
return fileBytes.getOriginalByte(getFileOffset());
}
return 0;
}
/**
* Returns the {@link MemoryBlockSourceInfo} for the region surround this info's location.
* @return the {@link MemoryBlockSourceInfo} for the region surround this info's location.
*/
public MemoryBlockSourceInfo getMemoryBlockSourceInfo() {
return sourceInfo;
}
private MemoryBlockSourceInfo getContainingInfo() {
List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
for (MemoryBlockSourceInfo info : sourceInfos) {
if (info.contains(address)) {
Optional<AddressRange> mappedRangeOptional = info.getMappedRange();
if (mappedRangeOptional.isPresent()) {
mappedInfo = getMappedSourceInfo(info, mappedRangeOptional.get());
}
return info;
}
}
return null;
}
private AddressSourceInfo getMappedSourceInfo(MemoryBlockSourceInfo info, AddressRange addressRange) {
Address mappedAddress =
addressRange.getMinAddress().add(address.subtract(info.getMinAddress()));
MemoryBlock mappedBlock = memory.getBlock(mappedAddress);
if (mappedBlock == null) {
return null;
}
return new AddressSourceInfo(memory, mappedAddress, mappedBlock);
}
}

View file

@ -113,11 +113,7 @@ class FileBytesSubMemoryBlock extends SubMemoryBlock {
protected String getDescription() {
String fileName = fileBytes.getFilename();
if (fileBytes.getFileOffset()> 0) {
fileName = "[" + fileName + " + 0x" + Long.toHexString(fileBytes.getFileOffset()) + "]";
}
String hexString = Long.toHexString(fileBytesOffset);
String hexString = Long.toHexString(fileBytesOffset + fileBytes.getFileOffset());
return "File: " + fileName + ": 0x" + hexString;
}

View file

@ -665,8 +665,8 @@ public class MemoryBlockDB implements MemoryBlock {
}
@Override
public List<SourceInfo> getSourceInfos() {
List<SourceInfo> infos = new ArrayList<>(subBlocks.size());
public List<MemoryBlockSourceInfo> getSourceInfos() {
List<MemoryBlockSourceInfo> infos = new ArrayList<>(subBlocks.size());
for (SubMemoryBlock subBlock : subBlocks) {
infos.add(subBlock.getSourceInfo(this));
}

View file

@ -24,12 +24,12 @@ import ghidra.program.model.mem.MemoryBlock;
/**
* Class for describing the source of bytes for a memory block.
*/
public class SourceInfo {
public class MemoryBlockSourceInfo {
final MemoryBlock block;
final SubMemoryBlock subBlock;
private final MemoryBlock block;
private final SubMemoryBlock subBlock;
SourceInfo(MemoryBlock block, SubMemoryBlock subBlock) {
MemoryBlockSourceInfo(MemoryBlock block, SubMemoryBlock subBlock) {
this.block = block;
this.subBlock = subBlock;
}
@ -97,6 +97,26 @@ public class SourceInfo {
return -1;
}
/**
* Returns the offset into the {@link FileBytes} object for the given address or
* -1 if this SourceInfo does not have an associated {@link FileBytes} or the address doesn't
* belong to this SourceInfo.
*
* @param address the address for which to get an offset into the {@link FileBytes} object.
* @return the offset into the {@link FileBytes} object for the given address.
*/
public long getFileBytesOffset(Address address) {
if (!contains(address)) {
return -1;
}
if (subBlock instanceof FileBytesSubMemoryBlock) {
long blockOffset = address.subtract(getMinAddress());
long subBlockOffset = blockOffset - subBlock.startingOffset;
return ((FileBytesSubMemoryBlock) subBlock).getFileBytesOffset() + subBlockOffset;
}
return -1;
}
/**
* Returns an {@link Optional} {@link AddressRange} for the mapped addresses if this is mapped
* memory block (bit mapped or byte mapped). Otherwise, the Optional is empty.
@ -114,4 +134,21 @@ public class SourceInfo {
}
return Optional.empty();
}
/**
* Returns the containing Memory Block
* @return the containing Memory Block
*/
public MemoryBlock getMemoryBlock() {
return block;
}
/**
* Returns true if this SourceInfo object applies to the given address;
* @param address the address to test if this is its SourceInfo
* @return true if this SourceInfo object applies to the given address;
*/
public boolean contains(Address address) {
return address.compareTo(getMinAddress()) >= 0 && address.compareTo(getMaxAddress()) <= 0;
}
}

View file

@ -662,7 +662,7 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
try {
Address overlayAddr = null;
if (block.isMapped()) {
SourceInfo info = block.getSourceInfos().get(0);
MemoryBlockSourceInfo info = block.getSourceInfos().get(0);
overlayAddr = info.getMappedRange().get().getMinAddress();
}
MemoryBlockDB newBlock =
@ -1838,9 +1838,9 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
*/
private AddressSet getMappedIntersection(MemoryBlock block, AddressSet set) {
AddressSet mappedIntersection = new AddressSet();
List<SourceInfo> sourceInfos = block.getSourceInfos();
List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
// mapped blocks can only ever have one sourceInfo
SourceInfo info = sourceInfos.get(0);
MemoryBlockSourceInfo info = sourceInfos.get(0);
AddressRange range = info.getMappedRange().get();
AddressSet resolvedIntersection = set.intersect(new AddressSet(range));
for (AddressRange resolvedRange : resolvedIntersection) {
@ -1855,7 +1855,7 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
private AddressRange getMappedRange(MemoryBlock mappedBlock, AddressRange resolvedRange) {
Address start, end;
SourceInfo info = mappedBlock.getSourceInfos().get(0);
MemoryBlockSourceInfo info = mappedBlock.getSourceInfos().get(0);
long startOffset =
resolvedRange.getMinAddress().subtract(info.getMappedRange().get().getMinAddress());
boolean isBitMapped = mappedBlock.getType() == MemoryBlockType.BIT_MAPPED;
@ -1989,6 +1989,14 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
return addrSet.findFirstAddressInCommon(set);
}
@Override
public AddressSourceInfo getAddressSourceInfo(Address address) {
MemoryBlock block = getBlock(address);
if (block != null) {
return new AddressSourceInfo(this, address, block);
}
return null;
}
private void checkBlockSize(long newBlockLength, boolean initialized) {
if (newBlockLength > MAX_BLOCK_SIZE) {
throw new IllegalStateException(
@ -2109,4 +2117,5 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
}
}
}
}

View file

@ -116,7 +116,7 @@ abstract class MemoryMapDBAdapter {
Address mappedAddress = null;
if (block.isMapped()) {
SourceInfo info = block.getSourceInfos().get(0);
MemoryBlockSourceInfo info = block.getSourceInfos().get(0);
mappedAddress = info.getMappedRange().get().getMinAddress();
}
newBlock =

View file

@ -189,12 +189,12 @@ abstract class SubMemoryBlock {
protected abstract MemoryBlockType getType();
/**
* Returns the {@link SourceInfo} object for this SubMemoryBlock
* Returns the {@link MemoryBlockSourceInfo} object for this SubMemoryBlock
* @param block the {@link MemoryBlock} that this block belongs to.
* @return the {@link SourceInfo} object for this SubMemoryBlock
* @return the {@link MemoryBlockSourceInfo} object for this SubMemoryBlock
*/
protected final SourceInfo getSourceInfo(MemoryBlock block) {
return new SourceInfo(block, this);
protected final MemoryBlockSourceInfo getSourceInfo(MemoryBlock block) {
return new MemoryBlockSourceInfo(block, this);
}
/**

View file

@ -20,6 +20,7 @@ import java.io.InputStream;
import java.util.List;
import ghidra.framework.store.LockException;
import ghidra.program.database.mem.AddressSourceInfo;
import ghidra.program.database.mem.FileBytes;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program;
@ -748,4 +749,11 @@ public interface Memory extends AddressSetView {
* @throws IOException if there was an error updating the database.
*/
public boolean deleteFileBytes(FileBytes fileBytes) throws IOException;
/**
* Returns information ({@link AddressSourceInfo}) about the byte source at the given address.
* @param address the address to query.
* @return information ({@link AddressSourceInfo}) about the byte source at the given address.
*/
public AddressSourceInfo getAddressSourceInfo(Address address);
}

View file

@ -20,7 +20,7 @@ import java.io.Serializable;
import java.util.List;
import ghidra.framework.store.LockException;
import ghidra.program.database.mem.SourceInfo;
import ghidra.program.database.mem.MemoryBlockSourceInfo;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.util.exception.DuplicateNameException;
@ -264,13 +264,13 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
public boolean isLoaded();
/**
* Returns a list of {@link SourceInfo} objects for this block. A block may consist of
* Returns a list of {@link MemoryBlockSourceInfo} objects for this block. A block may consist of
* multiple sequences of bytes from different sources. Each such source of bytes is described
* by its respective SourceInfo object. Blocks may have multiple sources after two or more
* memory blocks have been joined together and the underlying byte sources can't be joined.
* @return a list of SourceInfo objects, one for each different source of bytes in this block.
*/
public List<SourceInfo> getSourceInfos();
public List<MemoryBlockSourceInfo> getSourceInfos();
/**
* Determine if the specified address is contained within the reserved EXTERNAL block.

View file

@ -19,7 +19,7 @@ import java.io.InputStream;
import java.util.List;
import ghidra.framework.store.LockException;
import ghidra.program.database.mem.SourceInfo;
import ghidra.program.database.mem.MemoryBlockSourceInfo;
import ghidra.program.model.address.Address;
import ghidra.util.exception.DuplicateNameException;
@ -191,7 +191,7 @@ public class MemoryBlockStub implements MemoryBlock {
}
@Override
public List<SourceInfo> getSourceInfos() {
public List<MemoryBlockSourceInfo> getSourceInfos() {
throw new UnsupportedOperationException();
}

View file

@ -21,6 +21,7 @@ import java.util.Iterator;
import java.util.List;
import ghidra.framework.store.LockException;
import ghidra.program.database.mem.AddressSourceInfo;
import ghidra.program.database.mem.FileBytes;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program;
@ -489,4 +490,9 @@ public class MemoryStub implements Memory {
MemoryConflictException, AddressOverflowException {
throw new UnsupportedOperationException();
}
@Override
public AddressSourceInfo getAddressSourceInfo(Address address) {
throw new UnsupportedOperationException();
}
}

View file

@ -96,10 +96,10 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertNull(block.getSourceName());
assertEquals(MemoryBlock.READ, block.getPermissions());
List<SourceInfo> sourceInfos = block.getSourceInfos();
List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(1, sourceInfos.size());
SourceInfo info = sourceInfos.get(0);
MemoryBlockSourceInfo info = sourceInfos.get(0);
assertEquals(10, info.getLength());
assertEquals(addr(0), info.getMinAddress());
assertEquals(addr(9), info.getMaxAddress());
@ -117,9 +117,9 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(addr(0), block.getStart());
assertEquals(addr(9), block.getEnd());
assertEquals(MemoryBlockType.DEFAULT, block.getType());
List<SourceInfo> sourceInfos = block.getSourceInfos();
List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(1, sourceInfos.size());
SourceInfo info = sourceInfos.get(0);
MemoryBlockSourceInfo info = sourceInfos.get(0);
assertEquals(10, info.getLength());
assertEquals(addr(0), info.getMinAddress());
assertEquals(addr(9), info.getMaxAddress());
@ -143,9 +143,9 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(9, block.getEnd().getOffset());
assertTrue(block.getStart().getAddressSpace().isOverlaySpace());
assertEquals(MemoryBlockType.OVERLAY, block.getType());
List<SourceInfo> sourceInfos = block.getSourceInfos();
List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(1, sourceInfos.size());
SourceInfo info = sourceInfos.get(0);
MemoryBlockSourceInfo info = sourceInfos.get(0);
assertEquals(10, info.getLength());
try {
block.getByte(block.getStart());
@ -168,9 +168,9 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(9, block.getEnd().getOffset());
assertTrue(block.getStart().getAddressSpace().isOverlaySpace());
assertEquals(MemoryBlockType.OVERLAY, block.getType());
List<SourceInfo> sourceInfos = block.getSourceInfos();
List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(1, sourceInfos.size());
SourceInfo info = sourceInfos.get(0);
MemoryBlockSourceInfo info = sourceInfos.get(0);
assertEquals(10, info.getLength());
for (int i = 0; i < 10; i++) {
assertEquals(1, block.getByte(block.getStart().add(i)));
@ -194,10 +194,10 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertNull(block.getSourceName());
assertEquals(MemoryBlock.READ, block.getPermissions());
List<SourceInfo> sourceInfos = block.getSourceInfos();
List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(1, sourceInfos.size());
SourceInfo info = sourceInfos.get(0);
MemoryBlockSourceInfo info = sourceInfos.get(0);
assertEquals(20, info.getLength());
assertEquals(new AddressRangeImpl(addr(40), addr(59)), info.getMappedRange().get());
@ -230,10 +230,10 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertNull(block.getSourceName());
assertEquals(MemoryBlock.READ, block.getPermissions());
List<SourceInfo> sourceInfos = block.getSourceInfos();
List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(1, sourceInfos.size());
SourceInfo info = sourceInfos.get(0);
MemoryBlockSourceInfo info = sourceInfos.get(0);
assertEquals(16, info.getLength());
assertEquals(new AddressRangeImpl(addr(49), addr(50)), info.getMappedRange().get());
@ -266,10 +266,10 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertNull(block.getSourceName());
assertEquals(MemoryBlock.READ, block.getPermissions());
List<SourceInfo> sourceInfos = block.getSourceInfos();
List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(1, sourceInfos.size());
SourceInfo info = sourceInfos.get(0);
MemoryBlockSourceInfo info = sourceInfos.get(0);
assertEquals(50, info.getLength());
assertEquals(addr(100), info.getMinAddress());
assertEquals(addr(149), info.getMaxAddress());
@ -324,9 +324,9 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(1, mem.getBlocks().length);
assertEquals(20, block.getSize());
assertEquals(addr(10), block.getStart());
List<SourceInfo> sourceInfos = block.getSourceInfos();
List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(1, sourceInfos.size());
SourceInfo sourceInfo = sourceInfos.get(0);
MemoryBlockSourceInfo sourceInfo = sourceInfos.get(0);
assertEquals(fileBytes, sourceInfo.getFileBytes().get());
assertEquals(25, sourceInfo.getFileBytesOffset());
byte[] bytes = new byte[30];
@ -346,9 +346,9 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(1, mem.getBlocks().length);
assertEquals(20, block.getSize());
assertEquals(addr(10), block.getStart());
List<SourceInfo> sourceInfos = block.getSourceInfos();
List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(2, sourceInfos.size());
SourceInfo sourceInfo = sourceInfos.get(0);
MemoryBlockSourceInfo sourceInfo = sourceInfos.get(0);
assertEquals(fileBytes, sourceInfo.getFileBytes().get());
assertEquals(25, sourceInfo.getFileBytesOffset());
assertEquals(10, sourceInfo.getLength());
@ -370,14 +370,14 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(1, mem.getBlocks().length);
assertEquals(20, block.getSize());
assertEquals(addr(10), block.getStart());
List<SourceInfo> sourceInfos = block.getSourceInfos();
List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(2, sourceInfos.size());
SourceInfo sourceInfo = sourceInfos.get(0);
MemoryBlockSourceInfo sourceInfo = sourceInfos.get(0);
assertEquals(fileBytes, sourceInfo.getFileBytes().get());
assertEquals(25, sourceInfo.getFileBytesOffset());
assertEquals(10, sourceInfo.getLength());
SourceInfo sourceInfo2 = sourceInfos.get(1);
MemoryBlockSourceInfo sourceInfo2 = sourceInfos.get(1);
assertEquals(10, sourceInfo2.getLength());
}
@ -392,10 +392,10 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(1, mem.getBlocks().length);
assertEquals(20, block.getSize());
assertEquals(addr(10), block.getStart());
List<SourceInfo> sourceInfos = block.getSourceInfos();
List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(2, sourceInfos.size());
SourceInfo sourceInfo = sourceInfos.get(0);
MemoryBlockSourceInfo sourceInfo = sourceInfos.get(0);
assertEquals(fileBytes1, sourceInfo.getFileBytes().get());
assertEquals(25, sourceInfo.getFileBytesOffset());
assertEquals(10, sourceInfo.getLength());
@ -421,9 +421,9 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(addr(10), blocks[0].getStart());
assertEquals(addr(30), blocks[1].getStart());
List<SourceInfo> sourceInfos = blocks[0].getSourceInfos();
List<MemoryBlockSourceInfo> sourceInfos = blocks[0].getSourceInfos();
assertEquals(1, sourceInfos.size());
SourceInfo sourceInfo = sourceInfos.get(0);
MemoryBlockSourceInfo sourceInfo = sourceInfos.get(0);
assertEquals(fileBytes, sourceInfo.getFileBytes().get());
assertEquals(25, sourceInfo.getFileBytesOffset());
@ -479,7 +479,7 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(1, blocks.length);
assertEquals(addr(0), blocks[0].getStart());
assertEquals(40, blocks[0].getSize());
List<SourceInfo> sourceInfos = blocks[0].getSourceInfos();
List<MemoryBlockSourceInfo> sourceInfos = blocks[0].getSourceInfos();
assertEquals(1, sourceInfos.size()); // make sure the sub blocks were merged
}
@ -825,6 +825,63 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(2, range.getSize());
assertEquals(0, range.getOffset());
}
@Test
public void testAddressSourceInfoForFileBytesBlock() throws Exception {
FileBytes fileBytes = createFileBytes();
mem.createInitializedBlock("block", addr(100), fileBytes, 10, 50, false);
AddressSourceInfo info = mem.getAddressSourceInfo(addr(100));
assertEquals(addr(100), info.getAddress());
assertEquals("test", info.getFileName());
assertEquals(10, info.getFileOffset());
assertEquals(10, info.getOriginalValue());
info = mem.getAddressSourceInfo(addr(110));
assertEquals(addr(110), info.getAddress());
assertEquals("test", info.getFileName());
assertEquals(20, info.getFileOffset());
assertEquals(20, info.getOriginalValue());
}
@Test
public void testAddressSourceInfoForBufferBlock() throws Exception {
mem.createInitializedBlock("test", addr(0), 10, (byte) 1, TaskMonitor.DUMMY, false);
AddressSourceInfo info = mem.getAddressSourceInfo(addr(0));
assertEquals(addr(0), info.getAddress());
assertNull(info.getFileName());
assertEquals(-1, info.getFileOffset());
assertEquals(0, info.getOriginalValue());
}
@Test
public void testAddressSourceInfoForUnitialized() throws Exception {
mem.createUninitializedBlock("test", addr(0), 10, false);
AddressSourceInfo info = mem.getAddressSourceInfo(addr(0));
assertEquals(addr(0), info.getAddress());
assertNull(info.getFileName());
assertEquals(-1, info.getFileOffset());
assertEquals(0, info.getOriginalValue());
}
@Test
public void testAddressSourceInfoForMappedBlock() throws Exception {
FileBytes fileBytes = createFileBytes();
mem.createInitializedBlock("block", addr(0), fileBytes, 10, 50, false);
mem.createByteMappedBlock("mapped", addr(1000), addr(0), 20);
AddressSourceInfo info = mem.getAddressSourceInfo(addr(1000));
assertEquals(addr(1000), info.getAddress());
assertEquals("test", info.getFileName());
assertEquals(10, info.getFileOffset());
assertEquals(10, info.getOriginalValue());
}
private MemoryBlock createFileBytesBlock(FileBytes fileBytes, Address addr, int offset,
int length) throws Exception {
return mem.createInitializedBlock("test" + addr.toString(), addr, fileBytes, offset, length,