diff --git a/Ghidra/Features/Base/src/main/help/help/topics/CodeBrowserPlugin/CodeBrowser.htm b/Ghidra/Features/Base/src/main/help/help/topics/CodeBrowserPlugin/CodeBrowser.htm
index 90f7e50942..6fa568554e 100644
--- a/Ghidra/Features/Base/src/main/help/help/topics/CodeBrowserPlugin/CodeBrowser.htm
+++ b/Ghidra/Features/Base/src/main/help/help/topics/CodeBrowserPlugin/CodeBrowser.htm
@@ -465,7 +465,8 @@
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
a complex data (structure, array, etc.), the offset from the base of that data is
- shown.
+ 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
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/hover/ProgramAddressRelationshipListingHover.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/hover/ProgramAddressRelationshipListingHover.java
index a7f1a313ed..55c1bb5815 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/hover/ProgramAddressRelationshipListingHover.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/hover/ProgramAddressRelationshipListingHover.java
@@ -15,8 +15,7 @@
*/
package ghidra.app.plugin.core.codebrowser.hover;
-import static ghidra.util.HTMLUtilities.bold;
-import static ghidra.util.HTMLUtilities.italic;
+import static ghidra.util.HTMLUtilities.*;
import javax.swing.JComponent;
@@ -26,6 +25,7 @@ import ghidra.GhidraOptions;
import ghidra.app.plugin.core.hover.AbstractConfigurableHover;
import ghidra.framework.options.Options;
import ghidra.framework.plugintool.PluginTool;
+import ghidra.program.database.mem.AddressSourceInfo;
import ghidra.program.model.address.*;
import ghidra.program.model.data.Structure;
import ghidra.program.model.listing.*;
@@ -33,6 +33,7 @@ import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.util.AddressFieldLocation;
import ghidra.program.util.ProgramLocation;
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.
@@ -44,6 +45,7 @@ import ghidra.util.HTMLUtilities;
public class ProgramAddressRelationshipListingHover extends AbstractConfigurableHover
implements ListingHoverService {
+ private static final int MAX_FILENAME_SIZE = 40;
private static final String NAME = "Address Display";
private static final String DESCRIPTION =
"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);
addDataInfo(program, loc, sb);
+ addByteSourceInfo(program, loc, sb);
return createTooltipComponent(sb.toString());
}
@@ -139,6 +142,21 @@ public class ProgramAddressRelationshipListingHover extends AbstractConfigurable
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) {
Function function = program.getFunctionManager().getFunctionContaining(loc);
if (function != null) {
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapModel.java
index cc0bd55c68..97dc4ad512 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapModel.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapModel.java
@@ -33,7 +33,7 @@ import docking.widgets.table.AbstractSortedTableModel;
import ghidra.framework.model.DomainFile;
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.listing.Program;
import ghidra.program.model.mem.*;
@@ -504,7 +504,7 @@ class MemoryMapModel extends AbstractSortedTableModel {
case SOURCE:
if ((block.getType() == MemoryBlockType.BIT_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 block.getSourceName();
@@ -522,8 +522,8 @@ class MemoryMapModel extends AbstractSortedTableModel {
return null;
}
- private String getByteSourceDescription(List sourceInfos) {
- List limited = sourceInfos.size() < 5 ? sourceInfos : sourceInfos.subList(0, 4);
+ private String getByteSourceDescription(List sourceInfos) {
+ List limited = sourceInfos.size() < 5 ? sourceInfos : sourceInfos.subList(0, 4);
//@formatter:off
String description = limited
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/MemoryMapXmlMgr.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/MemoryMapXmlMgr.java
index db8e3c7ba2..376082419a 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/MemoryMapXmlMgr.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/MemoryMapXmlMgr.java
@@ -23,7 +23,7 @@ import org.xml.sax.SAXParseException;
import ghidra.app.util.MemoryBlockUtil;
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.listing.Program;
import ghidra.program.model.mem.*;
@@ -295,7 +295,7 @@ class MemoryMapXmlMgr {
if (block.getType() == MemoryBlockType.BIT_MAPPED) {
// 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",
info.getMappedRange().get().getMinAddress().toString());
writer.startElement("BIT_MAPPED", attrs);
@@ -303,7 +303,7 @@ class MemoryMapXmlMgr {
}
else if (block.getType() == MemoryBlockType.BYTE_MAPPED) {
// 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",
info.getMappedRange().get().getMinAddress().toString());
writer.startElement("BYTE_MAPPED", attrs);
diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/memory/MemoryMapProvider1Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/memory/MemoryMapProvider1Test.java
index fcbd105873..e27c884644 100644
--- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/memory/MemoryMapProvider1Test.java
+++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/memory/MemoryMapProvider1Test.java
@@ -35,7 +35,7 @@ import ghidra.app.plugin.core.gotoquery.GoToServicePlugin;
import ghidra.app.plugin.core.navigation.NavigationHistoryPlugin;
import ghidra.framework.plugintool.PluginTool;
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.listing.CodeUnit;
import ghidra.program.model.listing.Program;
@@ -560,7 +560,7 @@ public class MemoryMapProvider1Test extends AbstractGhidraHeadedIntegrationTest
for (MemoryBlock memBlock : blocks) {
if (memBlock.getSourceName().equals(sources[i]) &&
memBlock.getType() == MemoryBlockType.BIT_MAPPED) {
- SourceInfo info = memBlock.getSourceInfos().get(0);
+ MemoryBlockSourceInfo info = memBlock.getSourceInfos().get(0);
Address addr = info.getMappedRange().get().getMinAddress();
assertEquals(addr.toString(), model.getValueAt(i, MemoryMapModel.SOURCE));
@@ -605,7 +605,7 @@ public class MemoryMapProvider1Test extends AbstractGhidraHeadedIntegrationTest
for (MemoryBlock memBlock : blocks) {
if (memBlock.getSourceName().equals(sources[idx]) &&
memBlock.getType() == MemoryBlockType.BIT_MAPPED) {
- SourceInfo info = memBlock.getSourceInfos().get(0);
+ MemoryBlockSourceInfo info = memBlock.getSourceInfos().get(0);
Address addr = info.getMappedRange().get().getMinAddress();
assertEquals(addr.toString(), model.getValueAt(i, MemoryMapModel.SOURCE));
doAssert = false;
diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/mem/MemoryManagerTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/mem/MemoryManagerTest.java
index fba2b05b5f..20433a4ee7 100644
--- a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/mem/MemoryManagerTest.java
+++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/mem/MemoryManagerTest.java
@@ -879,7 +879,7 @@ public class MemoryManagerTest extends AbstractGhidraHeadedIntegrationTest {
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());
AddressSet expectedInitializedSet = new AddressSet();
expectedInitializedSet.add(addr(0), addr(0xfff));
@@ -895,7 +895,7 @@ public class MemoryManagerTest extends AbstractGhidraHeadedIntegrationTest {
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());
AddressSet expectedInitializedSet = new AddressSet();
expectedInitializedSet.add(addr(0), addr(0xfff));
diff --git a/Ghidra/Features/Base/src/test/java/ghidra/app/cmd/memory/AddMemoryBlockCmdTest.java b/Ghidra/Features/Base/src/test/java/ghidra/app/cmd/memory/AddMemoryBlockCmdTest.java
index 5d0c317194..bab3928e42 100644
--- a/Ghidra/Features/Base/src/test/java/ghidra/app/cmd/memory/AddMemoryBlockCmdTest.java
+++ b/Ghidra/Features/Base/src/test/java/ghidra/app/cmd/memory/AddMemoryBlockCmdTest.java
@@ -22,7 +22,7 @@ import org.junit.*;
import generic.test.AbstractGenericTest;
import ghidra.framework.cmd.Command;
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.listing.*;
import ghidra.program.model.mem.MemoryBlock;
@@ -110,7 +110,7 @@ public class AddMemoryBlockCmdTest extends AbstractGenericTest {
MemoryBlock block = x08.getMemory().getBlock(addr);
assertNotNull(block);
- SourceInfo info = block.getSourceInfos().get(0);
+ MemoryBlockSourceInfo info = block.getSourceInfos().get(0);
assertEquals(getX08Addr(0), info.getMappedRange().get().getMinAddress());
assertEquals(MemoryBlockType.BIT_MAPPED, block.getType());
}
@@ -124,7 +124,7 @@ public class AddMemoryBlockCmdTest extends AbstractGenericTest {
MemoryBlock block = x08.getMemory().getBlock(addr);
assertNotNull(block);
- SourceInfo info = block.getSourceInfos().get(0);
+ MemoryBlockSourceInfo info = block.getSourceInfos().get(0);
assertEquals(getX08Addr(0), info.getMappedRange().get().getMinAddress());
assertEquals(MemoryBlockType.BYTE_MAPPED, block.getType());
diff --git a/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/checksums/MyTestMemory.java b/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/checksums/MyTestMemory.java
index 93f955310f..047be6da11 100644
--- a/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/checksums/MyTestMemory.java
+++ b/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/checksums/MyTestMemory.java
@@ -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;
@@ -56,6 +57,11 @@ class MyTestMemory extends AddressSet implements Memory {
throw new UnsupportedOperationException();
}
+ @Override
+ public AddressSourceInfo getAddressSourceInfo(Address address) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public boolean isBigEndian() {
return false;
diff --git a/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/checksums/MyTestMemoryBlock.java b/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/checksums/MyTestMemoryBlock.java
index b771d75855..56cb91887a 100644
--- a/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/checksums/MyTestMemoryBlock.java
+++ b/Ghidra/Features/Base/src/test/java/ghidra/app/plugin/core/checksums/MyTestMemoryBlock.java
@@ -18,7 +18,7 @@ package ghidra.app.plugin.core.checksums;
import java.io.InputStream;
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.mem.*;
@@ -195,7 +195,7 @@ class MyTestMemoryBlock implements MemoryBlock {
}
@Override
- public List getSourceInfos() {
+ public List getSourceInfos() {
throw new UnsupportedOperationException();
}
}
diff --git a/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/MemoryTestDummy.java b/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/MemoryTestDummy.java
index f95a2077c8..dc4f8b3d22 100644
--- a/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/MemoryTestDummy.java
+++ b/Ghidra/Features/VersionTracking/src/test/java/ghidra/feature/vt/db/MemoryTestDummy.java
@@ -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;
@@ -348,4 +349,9 @@ public class MemoryTestDummy extends AddressSet implements Memory {
MemoryConflictException, AddressOverflowException {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public AddressSourceInfo getAddressSourceInfo(Address address) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/emulator/memory/ProgramLoadImage.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/emulator/memory/ProgramLoadImage.java
index 5fd89101d7..12c7d09314 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/emulator/memory/ProgramLoadImage.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/emulator/memory/ProgramLoadImage.java
@@ -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!");
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/emulator/memory/ProgramMappedMemory.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/emulator/memory/ProgramMappedMemory.java
index 2bf5f61cad..60268b20fc 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/emulator/memory/ProgramMappedMemory.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/emulator/memory/ProgramMappedMemory.java
@@ -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!");
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/AddressSourceInfo.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/AddressSourceInfo.java
new file mode 100644
index 0000000000..769084cfe5
--- /dev/null
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/AddressSourceInfo.java
@@ -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 sourceInfos = block.getSourceInfos();
+ for (MemoryBlockSourceInfo info : sourceInfos) {
+ if (info.contains(address)) {
+ Optional 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);
+ }
+}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/FileBytesSubMemoryBlock.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/FileBytesSubMemoryBlock.java
index b002ab232d..460a324be1 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/FileBytesSubMemoryBlock.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/FileBytesSubMemoryBlock.java
@@ -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;
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryBlockDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryBlockDB.java
index f039276723..bd0a8d82e4 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryBlockDB.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryBlockDB.java
@@ -665,8 +665,8 @@ public class MemoryBlockDB implements MemoryBlock {
}
@Override
- public List getSourceInfos() {
- List infos = new ArrayList<>(subBlocks.size());
+ public List getSourceInfos() {
+ List infos = new ArrayList<>(subBlocks.size());
for (SubMemoryBlock subBlock : subBlocks) {
infos.add(subBlock.getSourceInfo(this));
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/SourceInfo.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryBlockSourceInfo.java
similarity index 71%
rename from Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/SourceInfo.java
rename to Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryBlockSourceInfo.java
index 69b65f5003..6c63536d56 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/SourceInfo.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryBlockSourceInfo.java
@@ -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;
+ }
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDB.java
index 0e7d49dcb2..85e4e51a56 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDB.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDB.java
@@ -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 sourceInfos = block.getSourceInfos();
+ List 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 {
}
}
}
+
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapter.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapter.java
index 33aeb3d23b..f0cbc98124 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapter.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapter.java
@@ -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 =
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/SubMemoryBlock.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/SubMemoryBlock.java
index fba75aff6b..79a2a2c8c9 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/SubMemoryBlock.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/SubMemoryBlock.java
@@ -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);
}
/**
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/Memory.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/Memory.java
index 4e90438108..35b24ef806 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/Memory.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/Memory.java
@@ -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);
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/MemoryBlock.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/MemoryBlock.java
index 01712dcc92..49a867dea5 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/MemoryBlock.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/MemoryBlock.java
@@ -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 {
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 getSourceInfos();
+ public List getSourceInfos();
/**
* Determine if the specified address is contained within the reserved EXTERNAL block.
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/MemoryBlockStub.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/MemoryBlockStub.java
index 44a25e4f45..915e96a9ae 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/MemoryBlockStub.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/MemoryBlockStub.java
@@ -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 getSourceInfos() {
+ public List getSourceInfos() {
throw new UnsupportedOperationException();
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/MemoryStub.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/MemoryStub.java
index 3b600874d5..29d4ff9a1a 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/MemoryStub.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/mem/MemoryStub.java
@@ -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();
+ }
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/database/mem/MemBlockDBTest.java b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/database/mem/MemBlockDBTest.java
index cad62f4e7f..6ba898fd74 100644
--- a/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/database/mem/MemBlockDBTest.java
+++ b/Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/program/database/mem/MemBlockDBTest.java
@@ -96,10 +96,10 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertNull(block.getSourceName());
assertEquals(MemoryBlock.READ, block.getPermissions());
- List sourceInfos = block.getSourceInfos();
+ List 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 sourceInfos = block.getSourceInfos();
+ List 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 sourceInfos = block.getSourceInfos();
+ List 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 sourceInfos = block.getSourceInfos();
+ List 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 sourceInfos = block.getSourceInfos();
+ List 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 sourceInfos = block.getSourceInfos();
+ List 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 sourceInfos = block.getSourceInfos();
+ List 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 sourceInfos = block.getSourceInfos();
+ List 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 sourceInfos = block.getSourceInfos();
+ List 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 sourceInfos = block.getSourceInfos();
+ List 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 sourceInfos = block.getSourceInfos();
+ List 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 sourceInfos = blocks[0].getSourceInfos();
+ List 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 sourceInfos = blocks[0].getSourceInfos();
+ List 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,