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

@ -465,7 +465,8 @@
relationship between the hovered address and the base of memory and the containing memory relationship between the hovered address and the base of memory and the containing memory
block. For addresses in functions, the function offset is also shown; for addresses within block. For addresses in functions, the function offset is also shown; for addresses within
a complex data (structure, array, etc.), the offset from the base of that data is a complex data (structure, array, etc.), the offset from the base of that data is
shown.</P> shown. Also, if the byte value for the address can be traced back to the original imported
file, then the filename and offset for that location is displayed</P>
</BLOCKQUOTE> </BLOCKQUOTE>
</BLOCKQUOTE><!-- Function Name Hover Section--> </BLOCKQUOTE><!-- Function Name Hover Section-->

View file

@ -15,8 +15,7 @@
*/ */
package ghidra.app.plugin.core.codebrowser.hover; package ghidra.app.plugin.core.codebrowser.hover;
import static ghidra.util.HTMLUtilities.bold; import static ghidra.util.HTMLUtilities.*;
import static ghidra.util.HTMLUtilities.italic;
import javax.swing.JComponent; import javax.swing.JComponent;
@ -26,6 +25,7 @@ import ghidra.GhidraOptions;
import ghidra.app.plugin.core.hover.AbstractConfigurableHover; import ghidra.app.plugin.core.hover.AbstractConfigurableHover;
import ghidra.framework.options.Options; import ghidra.framework.options.Options;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.program.database.mem.AddressSourceInfo;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.data.Structure; import ghidra.program.model.data.Structure;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
@ -33,6 +33,7 @@ import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.util.AddressFieldLocation; import ghidra.program.util.AddressFieldLocation;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.util.HTMLUtilities; import ghidra.util.HTMLUtilities;
import ghidra.util.StringUtilities;
/** /**
* A hover service to show tool tip text for hovering over a program address in the listing. * A hover service to show tool tip text for hovering over a program address in the listing.
@ -44,6 +45,7 @@ import ghidra.util.HTMLUtilities;
public class ProgramAddressRelationshipListingHover extends AbstractConfigurableHover public class ProgramAddressRelationshipListingHover extends AbstractConfigurableHover
implements ListingHoverService { implements ListingHoverService {
private static final int MAX_FILENAME_SIZE = 40;
private static final String NAME = "Address Display"; private static final String NAME = "Address Display";
private static final String DESCRIPTION = private static final String DESCRIPTION =
"Shows the relationship between the hovered address and the base of memory " + "Shows the relationship between the hovered address and the base of memory " +
@ -98,6 +100,7 @@ public class ProgramAddressRelationshipListingHover extends AbstractConfigurable
addFunctionInfo(program, loc, sb); addFunctionInfo(program, loc, sb);
addDataInfo(program, loc, sb); addDataInfo(program, loc, sb);
addByteSourceInfo(program, loc, sb);
return createTooltipComponent(sb.toString()); return createTooltipComponent(sb.toString());
} }
@ -139,6 +142,21 @@ public class ProgramAddressRelationshipListingHover extends AbstractConfigurable
appendTableRow(sb, dataDescr, name, dataOffset); appendTableRow(sb, dataDescr, name, dataOffset);
} }
private void addByteSourceInfo(Program program, Address loc, StringBuilder sb) {
AddressSourceInfo addressSourceInfo = program.getMemory().getAddressSourceInfo(loc);
if (addressSourceInfo == null) {
return;
}
if (addressSourceInfo.getFileName() == null) {
return;
}
String filename = StringUtilities.trim(addressSourceInfo.getFileName(), MAX_FILENAME_SIZE);
long fileOffset = addressSourceInfo.getFileOffset();
String dataDescr = "Byte Source Offset";
appendTableRow(sb, dataDescr, "File: " + filename, fileOffset);
}
private void addFunctionInfo(Program program, Address loc, StringBuilder sb) { private void addFunctionInfo(Program program, Address loc, StringBuilder sb) {
Function function = program.getFunctionManager().getFunctionContaining(loc); Function function = program.getFunctionManager().getFunctionContaining(loc);
if (function != null) { if (function != null) {

View file

@ -33,7 +33,7 @@ import docking.widgets.table.AbstractSortedTableModel;
import ghidra.framework.model.DomainFile; import ghidra.framework.model.DomainFile;
import ghidra.framework.store.LockException; import ghidra.framework.store.LockException;
import ghidra.program.database.mem.SourceInfo; import ghidra.program.database.mem.MemoryBlockSourceInfo;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.*; import ghidra.program.model.mem.*;
@ -504,7 +504,7 @@ class MemoryMapModel extends AbstractSortedTableModel<MemoryBlock> {
case SOURCE: case SOURCE:
if ((block.getType() == MemoryBlockType.BIT_MAPPED) || if ((block.getType() == MemoryBlockType.BIT_MAPPED) ||
(block.getType() == MemoryBlockType.BYTE_MAPPED)) { (block.getType() == MemoryBlockType.BYTE_MAPPED)) {
SourceInfo info = block.getSourceInfos().get(0); MemoryBlockSourceInfo info = block.getSourceInfos().get(0);
return info.getMappedRange().get().getMinAddress().toString(); return info.getMappedRange().get().getMinAddress().toString();
} }
return block.getSourceName(); return block.getSourceName();
@ -522,8 +522,8 @@ class MemoryMapModel extends AbstractSortedTableModel<MemoryBlock> {
return null; return null;
} }
private String getByteSourceDescription(List<SourceInfo> sourceInfos) { private String getByteSourceDescription(List<MemoryBlockSourceInfo> sourceInfos) {
List<SourceInfo> limited = sourceInfos.size() < 5 ? sourceInfos : sourceInfos.subList(0, 4); List<MemoryBlockSourceInfo> limited = sourceInfos.size() < 5 ? sourceInfos : sourceInfos.subList(0, 4);
//@formatter:off //@formatter:off
String description = limited String description = limited

View file

@ -23,7 +23,7 @@ import org.xml.sax.SAXParseException;
import ghidra.app.util.MemoryBlockUtil; import ghidra.app.util.MemoryBlockUtil;
import ghidra.app.util.importer.MessageLog; import ghidra.app.util.importer.MessageLog;
import ghidra.program.database.mem.SourceInfo; import ghidra.program.database.mem.MemoryBlockSourceInfo;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.*; import ghidra.program.model.mem.*;
@ -295,7 +295,7 @@ class MemoryMapXmlMgr {
if (block.getType() == MemoryBlockType.BIT_MAPPED) { if (block.getType() == MemoryBlockType.BIT_MAPPED) {
// bit mapped blocks can only have one sub-block // bit mapped blocks can only have one sub-block
SourceInfo info = block.getSourceInfos().get(0); MemoryBlockSourceInfo info = block.getSourceInfos().get(0);
attrs.addAttribute("SOURCE_ADDRESS", attrs.addAttribute("SOURCE_ADDRESS",
info.getMappedRange().get().getMinAddress().toString()); info.getMappedRange().get().getMinAddress().toString());
writer.startElement("BIT_MAPPED", attrs); writer.startElement("BIT_MAPPED", attrs);
@ -303,7 +303,7 @@ class MemoryMapXmlMgr {
} }
else if (block.getType() == MemoryBlockType.BYTE_MAPPED) { else if (block.getType() == MemoryBlockType.BYTE_MAPPED) {
// byte mapped blocks can only have one sub-block // byte mapped blocks can only have one sub-block
SourceInfo info = block.getSourceInfos().get(0); MemoryBlockSourceInfo info = block.getSourceInfos().get(0);
attrs.addAttribute("SOURCE_ADDRESS", attrs.addAttribute("SOURCE_ADDRESS",
info.getMappedRange().get().getMinAddress().toString()); info.getMappedRange().get().getMinAddress().toString());
writer.startElement("BYTE_MAPPED", attrs); writer.startElement("BYTE_MAPPED", attrs);

View file

@ -35,7 +35,7 @@ import ghidra.app.plugin.core.gotoquery.GoToServicePlugin;
import ghidra.app.plugin.core.navigation.NavigationHistoryPlugin; import ghidra.app.plugin.core.navigation.NavigationHistoryPlugin;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.program.database.ProgramBuilder; import ghidra.program.database.ProgramBuilder;
import ghidra.program.database.mem.SourceInfo; import ghidra.program.database.mem.MemoryBlockSourceInfo;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.listing.CodeUnit; import ghidra.program.model.listing.CodeUnit;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
@ -560,7 +560,7 @@ public class MemoryMapProvider1Test extends AbstractGhidraHeadedIntegrationTest
for (MemoryBlock memBlock : blocks) { for (MemoryBlock memBlock : blocks) {
if (memBlock.getSourceName().equals(sources[i]) && if (memBlock.getSourceName().equals(sources[i]) &&
memBlock.getType() == MemoryBlockType.BIT_MAPPED) { memBlock.getType() == MemoryBlockType.BIT_MAPPED) {
SourceInfo info = memBlock.getSourceInfos().get(0); MemoryBlockSourceInfo info = memBlock.getSourceInfos().get(0);
Address addr = info.getMappedRange().get().getMinAddress(); Address addr = info.getMappedRange().get().getMinAddress();
assertEquals(addr.toString(), model.getValueAt(i, MemoryMapModel.SOURCE)); assertEquals(addr.toString(), model.getValueAt(i, MemoryMapModel.SOURCE));
@ -605,7 +605,7 @@ public class MemoryMapProvider1Test extends AbstractGhidraHeadedIntegrationTest
for (MemoryBlock memBlock : blocks) { for (MemoryBlock memBlock : blocks) {
if (memBlock.getSourceName().equals(sources[idx]) && if (memBlock.getSourceName().equals(sources[idx]) &&
memBlock.getType() == MemoryBlockType.BIT_MAPPED) { memBlock.getType() == MemoryBlockType.BIT_MAPPED) {
SourceInfo info = memBlock.getSourceInfos().get(0); MemoryBlockSourceInfo info = memBlock.getSourceInfos().get(0);
Address addr = info.getMappedRange().get().getMinAddress(); Address addr = info.getMappedRange().get().getMinAddress();
assertEquals(addr.toString(), model.getValueAt(i, MemoryMapModel.SOURCE)); assertEquals(addr.toString(), model.getValueAt(i, MemoryMapModel.SOURCE));
doAssert = false; doAssert = false;

View file

@ -879,7 +879,7 @@ public class MemoryManagerTest extends AbstractGhidraHeadedIntegrationTest {
assertEquals(MemoryBlockType.BIT_MAPPED, bitBlock.getType()); assertEquals(MemoryBlockType.BIT_MAPPED, bitBlock.getType());
SourceInfo info = bitBlock.getSourceInfos().get(0); MemoryBlockSourceInfo info = bitBlock.getSourceInfos().get(0);
assertEquals(new AddressRangeImpl(addr(0xf00), addr(0x10ff)), info.getMappedRange().get()); assertEquals(new AddressRangeImpl(addr(0xf00), addr(0x10ff)), info.getMappedRange().get());
AddressSet expectedInitializedSet = new AddressSet(); AddressSet expectedInitializedSet = new AddressSet();
expectedInitializedSet.add(addr(0), addr(0xfff)); expectedInitializedSet.add(addr(0), addr(0xfff));
@ -895,7 +895,7 @@ public class MemoryManagerTest extends AbstractGhidraHeadedIntegrationTest {
assertEquals(MemoryBlockType.BYTE_MAPPED, byteBlock.getType()); assertEquals(MemoryBlockType.BYTE_MAPPED, byteBlock.getType());
SourceInfo info = byteBlock.getSourceInfos().get(0); MemoryBlockSourceInfo info = byteBlock.getSourceInfos().get(0);
assertEquals(new AddressRangeImpl(addr(0xf00), addr(0x10ff)), info.getMappedRange().get()); assertEquals(new AddressRangeImpl(addr(0xf00), addr(0x10ff)), info.getMappedRange().get());
AddressSet expectedInitializedSet = new AddressSet(); AddressSet expectedInitializedSet = new AddressSet();
expectedInitializedSet.add(addr(0), addr(0xfff)); expectedInitializedSet.add(addr(0), addr(0xfff));

View file

@ -22,7 +22,7 @@ import org.junit.*;
import generic.test.AbstractGenericTest; import generic.test.AbstractGenericTest;
import ghidra.framework.cmd.Command; import ghidra.framework.cmd.Command;
import ghidra.program.database.ProgramBuilder; import ghidra.program.database.ProgramBuilder;
import ghidra.program.database.mem.SourceInfo; import ghidra.program.database.mem.MemoryBlockSourceInfo;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.model.mem.MemoryBlock; import ghidra.program.model.mem.MemoryBlock;
@ -110,7 +110,7 @@ public class AddMemoryBlockCmdTest extends AbstractGenericTest {
MemoryBlock block = x08.getMemory().getBlock(addr); MemoryBlock block = x08.getMemory().getBlock(addr);
assertNotNull(block); assertNotNull(block);
SourceInfo info = block.getSourceInfos().get(0); MemoryBlockSourceInfo info = block.getSourceInfos().get(0);
assertEquals(getX08Addr(0), info.getMappedRange().get().getMinAddress()); assertEquals(getX08Addr(0), info.getMappedRange().get().getMinAddress());
assertEquals(MemoryBlockType.BIT_MAPPED, block.getType()); assertEquals(MemoryBlockType.BIT_MAPPED, block.getType());
} }
@ -124,7 +124,7 @@ public class AddMemoryBlockCmdTest extends AbstractGenericTest {
MemoryBlock block = x08.getMemory().getBlock(addr); MemoryBlock block = x08.getMemory().getBlock(addr);
assertNotNull(block); assertNotNull(block);
SourceInfo info = block.getSourceInfos().get(0); MemoryBlockSourceInfo info = block.getSourceInfos().get(0);
assertEquals(getX08Addr(0), info.getMappedRange().get().getMinAddress()); assertEquals(getX08Addr(0), info.getMappedRange().get().getMinAddress());
assertEquals(MemoryBlockType.BYTE_MAPPED, block.getType()); assertEquals(MemoryBlockType.BYTE_MAPPED, block.getType());

View file

@ -20,6 +20,7 @@ import java.io.InputStream;
import java.util.List; import java.util.List;
import ghidra.framework.store.LockException; import ghidra.framework.store.LockException;
import ghidra.program.database.mem.AddressSourceInfo;
import ghidra.program.database.mem.FileBytes; import ghidra.program.database.mem.FileBytes;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
@ -56,6 +57,11 @@ class MyTestMemory extends AddressSet implements Memory {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public AddressSourceInfo getAddressSourceInfo(Address address) {
throw new UnsupportedOperationException();
}
@Override @Override
public boolean isBigEndian() { public boolean isBigEndian() {
return false; return false;

View file

@ -18,7 +18,7 @@ package ghidra.app.plugin.core.checksums;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
import ghidra.program.database.mem.SourceInfo; import ghidra.program.database.mem.MemoryBlockSourceInfo;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.mem.*; import ghidra.program.model.mem.*;
@ -195,7 +195,7 @@ class MyTestMemoryBlock implements MemoryBlock {
} }
@Override @Override
public List<SourceInfo> getSourceInfos() { public List<MemoryBlockSourceInfo> getSourceInfos() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
} }

View file

@ -20,6 +20,7 @@ import java.io.InputStream;
import java.util.List; import java.util.List;
import ghidra.framework.store.LockException; import ghidra.framework.store.LockException;
import ghidra.program.database.mem.AddressSourceInfo;
import ghidra.program.database.mem.FileBytes; import ghidra.program.database.mem.FileBytes;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
@ -348,4 +349,9 @@ public class MemoryTestDummy extends AddressSet implements Memory {
MemoryConflictException, AddressOverflowException { MemoryConflictException, AddressOverflowException {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public AddressSourceInfo getAddressSourceInfo(Address address) {
throw new UnsupportedOperationException();
}
} }

View file

@ -20,7 +20,7 @@ import java.util.Arrays;
import ghidra.pcode.error.LowlevelError; import ghidra.pcode.error.LowlevelError;
import ghidra.pcode.memstate.MemoryFaultHandler; import ghidra.pcode.memstate.MemoryFaultHandler;
import ghidra.pcode.memstate.MemoryPage; 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.address.*;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.*; import ghidra.program.model.mem.*;
@ -48,7 +48,7 @@ public class ProgramLoadImage {
} }
private AddressSetView addMappedInitializedMemory(MemoryBlock mappedBlock) { 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()) { if (!sourceInfo.getMappedRange().isPresent()) {
throw new AssertException("Mapped block did not have mapped range!"); 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.error.LowlevelError;
import ghidra.pcode.memstate.MemoryFaultHandler; import ghidra.pcode.memstate.MemoryFaultHandler;
import ghidra.pcode.memstate.MemoryPage; 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.address.*;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.*; import ghidra.program.model.mem.*;
@ -52,7 +52,7 @@ public class ProgramMappedMemory {
private AddressSetView addMappedInitializedMemory(MemoryBlock mappedBlock) { private AddressSetView addMappedInitializedMemory(MemoryBlock mappedBlock) {
AddressSet modifiedSet = new AddressSet(initializedAddressSet); 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()) { if (!sourceInfo.getMappedRange().isPresent()) {
throw new AssertException("Mapped block did not have mapped range!"); 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() { protected String getDescription() {
String fileName = fileBytes.getFilename(); String fileName = fileBytes.getFilename();
if (fileBytes.getFileOffset()> 0) { String hexString = Long.toHexString(fileBytesOffset + fileBytes.getFileOffset());
fileName = "[" + fileName + " + 0x" + Long.toHexString(fileBytes.getFileOffset()) + "]";
}
String hexString = Long.toHexString(fileBytesOffset);
return "File: " + fileName + ": 0x" + hexString; return "File: " + fileName + ": 0x" + hexString;
} }

View file

@ -665,8 +665,8 @@ public class MemoryBlockDB implements MemoryBlock {
} }
@Override @Override
public List<SourceInfo> getSourceInfos() { public List<MemoryBlockSourceInfo> getSourceInfos() {
List<SourceInfo> infos = new ArrayList<>(subBlocks.size()); List<MemoryBlockSourceInfo> infos = new ArrayList<>(subBlocks.size());
for (SubMemoryBlock subBlock : subBlocks) { for (SubMemoryBlock subBlock : subBlocks) {
infos.add(subBlock.getSourceInfo(this)); 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. * Class for describing the source of bytes for a memory block.
*/ */
public class SourceInfo { public class MemoryBlockSourceInfo {
final MemoryBlock block; private final MemoryBlock block;
final SubMemoryBlock subBlock; private final SubMemoryBlock subBlock;
SourceInfo(MemoryBlock block, SubMemoryBlock subBlock) { MemoryBlockSourceInfo(MemoryBlock block, SubMemoryBlock subBlock) {
this.block = block; this.block = block;
this.subBlock = subBlock; this.subBlock = subBlock;
} }
@ -97,6 +97,26 @@ public class SourceInfo {
return -1; 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 * 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. * memory block (bit mapped or byte mapped). Otherwise, the Optional is empty.
@ -114,4 +134,21 @@ public class SourceInfo {
} }
return Optional.empty(); 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 { try {
Address overlayAddr = null; Address overlayAddr = null;
if (block.isMapped()) { if (block.isMapped()) {
SourceInfo info = block.getSourceInfos().get(0); MemoryBlockSourceInfo info = block.getSourceInfos().get(0);
overlayAddr = info.getMappedRange().get().getMinAddress(); overlayAddr = info.getMappedRange().get().getMinAddress();
} }
MemoryBlockDB newBlock = MemoryBlockDB newBlock =
@ -1838,9 +1838,9 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
*/ */
private AddressSet getMappedIntersection(MemoryBlock block, AddressSet set) { private AddressSet getMappedIntersection(MemoryBlock block, AddressSet set) {
AddressSet mappedIntersection = new AddressSet(); AddressSet mappedIntersection = new AddressSet();
List<SourceInfo> sourceInfos = block.getSourceInfos(); List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
// mapped blocks can only ever have one sourceInfo // mapped blocks can only ever have one sourceInfo
SourceInfo info = sourceInfos.get(0); MemoryBlockSourceInfo info = sourceInfos.get(0);
AddressRange range = info.getMappedRange().get(); AddressRange range = info.getMappedRange().get();
AddressSet resolvedIntersection = set.intersect(new AddressSet(range)); AddressSet resolvedIntersection = set.intersect(new AddressSet(range));
for (AddressRange resolvedRange : resolvedIntersection) { for (AddressRange resolvedRange : resolvedIntersection) {
@ -1855,7 +1855,7 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
private AddressRange getMappedRange(MemoryBlock mappedBlock, AddressRange resolvedRange) { private AddressRange getMappedRange(MemoryBlock mappedBlock, AddressRange resolvedRange) {
Address start, end; Address start, end;
SourceInfo info = mappedBlock.getSourceInfos().get(0); MemoryBlockSourceInfo info = mappedBlock.getSourceInfos().get(0);
long startOffset = long startOffset =
resolvedRange.getMinAddress().subtract(info.getMappedRange().get().getMinAddress()); resolvedRange.getMinAddress().subtract(info.getMappedRange().get().getMinAddress());
boolean isBitMapped = mappedBlock.getType() == MemoryBlockType.BIT_MAPPED; boolean isBitMapped = mappedBlock.getType() == MemoryBlockType.BIT_MAPPED;
@ -1989,6 +1989,14 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
return addrSet.findFirstAddressInCommon(set); 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) { private void checkBlockSize(long newBlockLength, boolean initialized) {
if (newBlockLength > MAX_BLOCK_SIZE) { if (newBlockLength > MAX_BLOCK_SIZE) {
throw new IllegalStateException( 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; Address mappedAddress = null;
if (block.isMapped()) { if (block.isMapped()) {
SourceInfo info = block.getSourceInfos().get(0); MemoryBlockSourceInfo info = block.getSourceInfos().get(0);
mappedAddress = info.getMappedRange().get().getMinAddress(); mappedAddress = info.getMappedRange().get().getMinAddress();
} }
newBlock = newBlock =

View file

@ -189,12 +189,12 @@ abstract class SubMemoryBlock {
protected abstract MemoryBlockType getType(); 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. * @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) { protected final MemoryBlockSourceInfo getSourceInfo(MemoryBlock block) {
return new SourceInfo(block, this); return new MemoryBlockSourceInfo(block, this);
} }
/** /**

View file

@ -20,6 +20,7 @@ import java.io.InputStream;
import java.util.List; import java.util.List;
import ghidra.framework.store.LockException; import ghidra.framework.store.LockException;
import ghidra.program.database.mem.AddressSourceInfo;
import ghidra.program.database.mem.FileBytes; import ghidra.program.database.mem.FileBytes;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program; 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. * @throws IOException if there was an error updating the database.
*/ */
public boolean deleteFileBytes(FileBytes fileBytes) throws IOException; 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 java.util.List;
import ghidra.framework.store.LockException; 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.address.Address;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
@ -264,13 +264,13 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
public boolean isLoaded(); 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 * 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 * 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. * 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. * @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. * 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 java.util.List;
import ghidra.framework.store.LockException; 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.address.Address;
import ghidra.util.exception.DuplicateNameException; import ghidra.util.exception.DuplicateNameException;
@ -191,7 +191,7 @@ public class MemoryBlockStub implements MemoryBlock {
} }
@Override @Override
public List<SourceInfo> getSourceInfos() { public List<MemoryBlockSourceInfo> getSourceInfos() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View file

@ -21,6 +21,7 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import ghidra.framework.store.LockException; import ghidra.framework.store.LockException;
import ghidra.program.database.mem.AddressSourceInfo;
import ghidra.program.database.mem.FileBytes; import ghidra.program.database.mem.FileBytes;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
@ -489,4 +490,9 @@ public class MemoryStub implements Memory {
MemoryConflictException, AddressOverflowException { MemoryConflictException, AddressOverflowException {
throw new UnsupportedOperationException(); 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()); assertNull(block.getSourceName());
assertEquals(MemoryBlock.READ, block.getPermissions()); assertEquals(MemoryBlock.READ, block.getPermissions());
List<SourceInfo> sourceInfos = block.getSourceInfos(); List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(1, sourceInfos.size()); assertEquals(1, sourceInfos.size());
SourceInfo info = sourceInfos.get(0); MemoryBlockSourceInfo info = sourceInfos.get(0);
assertEquals(10, info.getLength()); assertEquals(10, info.getLength());
assertEquals(addr(0), info.getMinAddress()); assertEquals(addr(0), info.getMinAddress());
assertEquals(addr(9), info.getMaxAddress()); assertEquals(addr(9), info.getMaxAddress());
@ -117,9 +117,9 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(addr(0), block.getStart()); assertEquals(addr(0), block.getStart());
assertEquals(addr(9), block.getEnd()); assertEquals(addr(9), block.getEnd());
assertEquals(MemoryBlockType.DEFAULT, block.getType()); assertEquals(MemoryBlockType.DEFAULT, block.getType());
List<SourceInfo> sourceInfos = block.getSourceInfos(); List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(1, sourceInfos.size()); assertEquals(1, sourceInfos.size());
SourceInfo info = sourceInfos.get(0); MemoryBlockSourceInfo info = sourceInfos.get(0);
assertEquals(10, info.getLength()); assertEquals(10, info.getLength());
assertEquals(addr(0), info.getMinAddress()); assertEquals(addr(0), info.getMinAddress());
assertEquals(addr(9), info.getMaxAddress()); assertEquals(addr(9), info.getMaxAddress());
@ -143,9 +143,9 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(9, block.getEnd().getOffset()); assertEquals(9, block.getEnd().getOffset());
assertTrue(block.getStart().getAddressSpace().isOverlaySpace()); assertTrue(block.getStart().getAddressSpace().isOverlaySpace());
assertEquals(MemoryBlockType.OVERLAY, block.getType()); assertEquals(MemoryBlockType.OVERLAY, block.getType());
List<SourceInfo> sourceInfos = block.getSourceInfos(); List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(1, sourceInfos.size()); assertEquals(1, sourceInfos.size());
SourceInfo info = sourceInfos.get(0); MemoryBlockSourceInfo info = sourceInfos.get(0);
assertEquals(10, info.getLength()); assertEquals(10, info.getLength());
try { try {
block.getByte(block.getStart()); block.getByte(block.getStart());
@ -168,9 +168,9 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(9, block.getEnd().getOffset()); assertEquals(9, block.getEnd().getOffset());
assertTrue(block.getStart().getAddressSpace().isOverlaySpace()); assertTrue(block.getStart().getAddressSpace().isOverlaySpace());
assertEquals(MemoryBlockType.OVERLAY, block.getType()); assertEquals(MemoryBlockType.OVERLAY, block.getType());
List<SourceInfo> sourceInfos = block.getSourceInfos(); List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(1, sourceInfos.size()); assertEquals(1, sourceInfos.size());
SourceInfo info = sourceInfos.get(0); MemoryBlockSourceInfo info = sourceInfos.get(0);
assertEquals(10, info.getLength()); assertEquals(10, info.getLength());
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
assertEquals(1, block.getByte(block.getStart().add(i))); assertEquals(1, block.getByte(block.getStart().add(i)));
@ -194,10 +194,10 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertNull(block.getSourceName()); assertNull(block.getSourceName());
assertEquals(MemoryBlock.READ, block.getPermissions()); assertEquals(MemoryBlock.READ, block.getPermissions());
List<SourceInfo> sourceInfos = block.getSourceInfos(); List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(1, sourceInfos.size()); assertEquals(1, sourceInfos.size());
SourceInfo info = sourceInfos.get(0); MemoryBlockSourceInfo info = sourceInfos.get(0);
assertEquals(20, info.getLength()); assertEquals(20, info.getLength());
assertEquals(new AddressRangeImpl(addr(40), addr(59)), info.getMappedRange().get()); assertEquals(new AddressRangeImpl(addr(40), addr(59)), info.getMappedRange().get());
@ -230,10 +230,10 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertNull(block.getSourceName()); assertNull(block.getSourceName());
assertEquals(MemoryBlock.READ, block.getPermissions()); assertEquals(MemoryBlock.READ, block.getPermissions());
List<SourceInfo> sourceInfos = block.getSourceInfos(); List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(1, sourceInfos.size()); assertEquals(1, sourceInfos.size());
SourceInfo info = sourceInfos.get(0); MemoryBlockSourceInfo info = sourceInfos.get(0);
assertEquals(16, info.getLength()); assertEquals(16, info.getLength());
assertEquals(new AddressRangeImpl(addr(49), addr(50)), info.getMappedRange().get()); assertEquals(new AddressRangeImpl(addr(49), addr(50)), info.getMappedRange().get());
@ -266,10 +266,10 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertNull(block.getSourceName()); assertNull(block.getSourceName());
assertEquals(MemoryBlock.READ, block.getPermissions()); assertEquals(MemoryBlock.READ, block.getPermissions());
List<SourceInfo> sourceInfos = block.getSourceInfos(); List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(1, sourceInfos.size()); assertEquals(1, sourceInfos.size());
SourceInfo info = sourceInfos.get(0); MemoryBlockSourceInfo info = sourceInfos.get(0);
assertEquals(50, info.getLength()); assertEquals(50, info.getLength());
assertEquals(addr(100), info.getMinAddress()); assertEquals(addr(100), info.getMinAddress());
assertEquals(addr(149), info.getMaxAddress()); assertEquals(addr(149), info.getMaxAddress());
@ -324,9 +324,9 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(1, mem.getBlocks().length); assertEquals(1, mem.getBlocks().length);
assertEquals(20, block.getSize()); assertEquals(20, block.getSize());
assertEquals(addr(10), block.getStart()); assertEquals(addr(10), block.getStart());
List<SourceInfo> sourceInfos = block.getSourceInfos(); List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(1, sourceInfos.size()); assertEquals(1, sourceInfos.size());
SourceInfo sourceInfo = sourceInfos.get(0); MemoryBlockSourceInfo sourceInfo = sourceInfos.get(0);
assertEquals(fileBytes, sourceInfo.getFileBytes().get()); assertEquals(fileBytes, sourceInfo.getFileBytes().get());
assertEquals(25, sourceInfo.getFileBytesOffset()); assertEquals(25, sourceInfo.getFileBytesOffset());
byte[] bytes = new byte[30]; byte[] bytes = new byte[30];
@ -346,9 +346,9 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(1, mem.getBlocks().length); assertEquals(1, mem.getBlocks().length);
assertEquals(20, block.getSize()); assertEquals(20, block.getSize());
assertEquals(addr(10), block.getStart()); assertEquals(addr(10), block.getStart());
List<SourceInfo> sourceInfos = block.getSourceInfos(); List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(2, sourceInfos.size()); assertEquals(2, sourceInfos.size());
SourceInfo sourceInfo = sourceInfos.get(0); MemoryBlockSourceInfo sourceInfo = sourceInfos.get(0);
assertEquals(fileBytes, sourceInfo.getFileBytes().get()); assertEquals(fileBytes, sourceInfo.getFileBytes().get());
assertEquals(25, sourceInfo.getFileBytesOffset()); assertEquals(25, sourceInfo.getFileBytesOffset());
assertEquals(10, sourceInfo.getLength()); assertEquals(10, sourceInfo.getLength());
@ -370,14 +370,14 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(1, mem.getBlocks().length); assertEquals(1, mem.getBlocks().length);
assertEquals(20, block.getSize()); assertEquals(20, block.getSize());
assertEquals(addr(10), block.getStart()); assertEquals(addr(10), block.getStart());
List<SourceInfo> sourceInfos = block.getSourceInfos(); List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(2, sourceInfos.size()); assertEquals(2, sourceInfos.size());
SourceInfo sourceInfo = sourceInfos.get(0); MemoryBlockSourceInfo sourceInfo = sourceInfos.get(0);
assertEquals(fileBytes, sourceInfo.getFileBytes().get()); assertEquals(fileBytes, sourceInfo.getFileBytes().get());
assertEquals(25, sourceInfo.getFileBytesOffset()); assertEquals(25, sourceInfo.getFileBytesOffset());
assertEquals(10, sourceInfo.getLength()); assertEquals(10, sourceInfo.getLength());
SourceInfo sourceInfo2 = sourceInfos.get(1); MemoryBlockSourceInfo sourceInfo2 = sourceInfos.get(1);
assertEquals(10, sourceInfo2.getLength()); assertEquals(10, sourceInfo2.getLength());
} }
@ -392,10 +392,10 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(1, mem.getBlocks().length); assertEquals(1, mem.getBlocks().length);
assertEquals(20, block.getSize()); assertEquals(20, block.getSize());
assertEquals(addr(10), block.getStart()); assertEquals(addr(10), block.getStart());
List<SourceInfo> sourceInfos = block.getSourceInfos(); List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
assertEquals(2, sourceInfos.size()); assertEquals(2, sourceInfos.size());
SourceInfo sourceInfo = sourceInfos.get(0); MemoryBlockSourceInfo sourceInfo = sourceInfos.get(0);
assertEquals(fileBytes1, sourceInfo.getFileBytes().get()); assertEquals(fileBytes1, sourceInfo.getFileBytes().get());
assertEquals(25, sourceInfo.getFileBytesOffset()); assertEquals(25, sourceInfo.getFileBytesOffset());
assertEquals(10, sourceInfo.getLength()); assertEquals(10, sourceInfo.getLength());
@ -421,9 +421,9 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(addr(10), blocks[0].getStart()); assertEquals(addr(10), blocks[0].getStart());
assertEquals(addr(30), blocks[1].getStart()); assertEquals(addr(30), blocks[1].getStart());
List<SourceInfo> sourceInfos = blocks[0].getSourceInfos(); List<MemoryBlockSourceInfo> sourceInfos = blocks[0].getSourceInfos();
assertEquals(1, sourceInfos.size()); assertEquals(1, sourceInfos.size());
SourceInfo sourceInfo = sourceInfos.get(0); MemoryBlockSourceInfo sourceInfo = sourceInfos.get(0);
assertEquals(fileBytes, sourceInfo.getFileBytes().get()); assertEquals(fileBytes, sourceInfo.getFileBytes().get());
assertEquals(25, sourceInfo.getFileBytesOffset()); assertEquals(25, sourceInfo.getFileBytesOffset());
@ -479,7 +479,7 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(1, blocks.length); assertEquals(1, blocks.length);
assertEquals(addr(0), blocks[0].getStart()); assertEquals(addr(0), blocks[0].getStart());
assertEquals(40, blocks[0].getSize()); 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 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(2, range.getSize());
assertEquals(0, range.getOffset()); 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, private MemoryBlock createFileBytesBlock(FileBytes fileBytes, Address addr, int offset,
int length) throws Exception { int length) throws Exception {
return mem.createInitializedBlock("test" + addr.toString(), addr, fileBytes, offset, length, return mem.createInitializedBlock("test" + addr.toString(), addr, fileBytes, offset, length,