diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/ProgramEmulationUtils.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/ProgramEmulationUtils.java
index 9f9c9f4e01..aa16cb8c4d 100644
--- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/ProgramEmulationUtils.java
+++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/emulation/ProgramEmulationUtils.java
@@ -104,7 +104,7 @@ public class ProgramEmulationUtils {
*/
public static Set getRegionFlags(MemoryBlock block) {
Set result = EnumSet.noneOf(TraceMemoryFlag.class);
- int mask = block.getPermissions();
+ int mask = block.getFlags();
if ((mask & MemoryBlock.READ) != 0) {
result.add(TraceMemoryFlag.READ);
}
diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewMemoryRegionBlock.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewMemoryRegionBlock.java
index 4fcc08b297..69486012e9 100644
--- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewMemoryRegionBlock.java
+++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewMemoryRegionBlock.java
@@ -18,6 +18,8 @@ package ghidra.trace.database.program;
import java.io.InputStream;
import java.math.BigInteger;
+import javax.help.UnsupportedOperationException;
+
import ghidra.framework.store.LockException;
import ghidra.program.model.address.*;
import ghidra.trace.database.memory.DBTraceMemorySpace;
@@ -57,7 +59,7 @@ public class DBTraceProgramViewMemoryRegionBlock extends AbstractDBTraceProgramV
}
@Override
- public int getPermissions() {
+ public int getFlags() {
int bits = 0;
for (TraceMemoryFlag flag : region.getFlags()) {
bits |= flag.getBits();
@@ -145,4 +147,15 @@ public class DBTraceProgramViewMemoryRegionBlock extends AbstractDBTraceProgramV
public void setVolatile(boolean v) {
region.setVolatile(v);
}
+
+ @Override
+ public boolean isArtificial() {
+ // By definition, any region present on target is non-artificial
+ return false;
+ }
+
+ @Override
+ public void setArtificial(boolean a) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewMemorySpaceBlock.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewMemorySpaceBlock.java
index 4012121576..d38679eea6 100644
--- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewMemorySpaceBlock.java
+++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewMemorySpaceBlock.java
@@ -50,7 +50,7 @@ public class DBTraceProgramViewMemorySpaceBlock extends AbstractDBTraceProgramVi
}
@Override
- public int getPermissions() {
+ public int getFlags() {
return MemoryBlock.READ | MemoryBlock.WRITE | MemoryBlock.EXECUTE;
}
@@ -119,6 +119,16 @@ public class DBTraceProgramViewMemorySpaceBlock extends AbstractDBTraceProgramVi
throw new UnsupportedOperationException();
}
+ @Override
+ public boolean isArtificial() {
+ return false;
+ }
+
+ @Override
+ public void setArtificial(boolean a) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public String getSourceName() {
return "Trace"; // TODO: What does this method actually do?
diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewRegisterMemoryBlock.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewRegisterMemoryBlock.java
index d0e67cdff7..975509feef 100644
--- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewRegisterMemoryBlock.java
+++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/program/DBTraceProgramViewRegisterMemoryBlock.java
@@ -116,7 +116,7 @@ public class DBTraceProgramViewRegisterMemoryBlock implements MemoryBlock {
}
@Override
- public int getPermissions() {
+ public int getFlags() {
return MemoryBlock.READ | MemoryBlock.WRITE;
}
@@ -220,6 +220,16 @@ public class DBTraceProgramViewRegisterMemoryBlock implements MemoryBlock {
throw new UnsupportedOperationException();
}
+ @Override
+ public boolean isArtificial() {
+ return false;
+ }
+
+ @Override
+ public void setArtificial(boolean a) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public String getSourceName() {
return "Trace"; // TODO: What does this method actually do?
diff --git a/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/Memory_Map.htm b/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/Memory_Map.htm
index af5d704f95..fdfb1e15c0 100644
--- a/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/Memory_Map.htm
+++ b/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/Memory_Map.htm
@@ -62,26 +62,11 @@
Overlay - Each of the above memory block types may
optionally be created as an Overlay block. One or more memory blocks may be defined
- within the same overlay address space.
-
-
- An overlay memory block may be created in two ways:
- *
- * - Specifying a {@code start} address within an existing overlay address space
- * ({@code overlay} parameter is ignored), or
- * - Specifying a {@code start} address within a physical memory address space and passing
- * {@code overlay=true}. This use case will force the creation of a new unique overlay
- * address space.
- *
-
-
-
- If this option is selected, the block is created in a new
- overlay address space. Overlay blocks can serve various
- purposes where a memory range may contain different data/code or map to different areas of memory
- at any given point in time or processor state. Note that
- overlay blocks are fixed and may not be moved, split, merged or expanded. In addition, Overlays
- do not relocate with image base changes and have significant limitations in conjunction with
+ within the same overlay address space where the Overlayed Space is reflected in the memory map table.
+ Overlay blocks can serve various
+ purposes where a memory range may contain different data/code at any given point in time
+ or processor state. Note that Overlay blocks
+ do not relocate with image base changes and have some limitations in conjunction with
decompilation and analysis.
To view the Memory Map, select Window
@@ -123,6 +108,9 @@
X * - Indicates execute permission.
Volatile * - Indicates a region of volatile I/O Memory.
+
+ Artificial * - Indicates an artificial memory block which has been fabricated to
+ facilitate analysis.
Overlayed Space - If the block is an overlay block this column indicates the name
of the overlayed physical memory space. This field will be empty for non-overlay blocks.
@@ -200,6 +188,13 @@
The volatile setting of a memory block can be changed by left-clicking on the
checkbox.
+
+ Change Artificial Setting
+
+
+ The artificial setting of a memory block can be changed by left-clicking on the
+ checkbox.
+
Initialize Memory Block
@@ -266,7 +261,11 @@
Execute - Sets the execute permission.
- Volatile - Marks this block as volatile I/O memory.
+ Volatile - Marks a block as volatile I/O memory.
+
+ Artificial - Marks a memory block as artificial. This may be useful when a
+ block is required to facilitate analysis but does not exist in the same form within a
+ running/loaded process state.
Overlay - Creates the block as an overlay block. An overlay memory block may be
created in two ways:
diff --git a/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/images/AddMappedBlock.png b/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/images/AddMappedBlock.png
index 4d198fc7f7..a5fd31ff6f 100644
Binary files a/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/images/AddMappedBlock.png and b/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/images/AddMappedBlock.png differ
diff --git a/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/images/AddMemoryBlock.png b/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/images/AddMemoryBlock.png
index 0812e81550..ac077c9b3a 100644
Binary files a/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/images/AddMemoryBlock.png and b/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/images/AddMemoryBlock.png differ
diff --git a/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/images/MemoryMap.png b/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/images/MemoryMap.png
index e1614e91a3..df5b6e8c05 100644
Binary files a/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/images/MemoryMap.png and b/Ghidra/Features/Base/src/main/help/help/topics/MemoryMapPlugin/images/MemoryMap.png differ
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AbstractAddMemoryBlockCmd.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AbstractAddMemoryBlockCmd.java
index ef7d8aecef..d98b702b44 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AbstractAddMemoryBlockCmd.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/memory/AbstractAddMemoryBlockCmd.java
@@ -28,7 +28,7 @@ import ghidra.util.exception.*;
/**
* Base command class for adding memory blocks.
*/
-abstract class AbstractAddMemoryBlockCmd implements Command {
+public abstract class AbstractAddMemoryBlockCmd implements Command {
protected String message;
protected final String name;
protected final String comment;
@@ -42,6 +42,8 @@ abstract class AbstractAddMemoryBlockCmd implements Command {
protected final boolean isVolatile;
protected final boolean isOverlay;
+ private boolean isArtificial = false;
+
AbstractAddMemoryBlockCmd(String name, String comment, String source, Address start,
long length, boolean read, boolean write, boolean execute, boolean isVolatile,
boolean isOverlay) {
@@ -57,6 +59,15 @@ abstract class AbstractAddMemoryBlockCmd implements Command {
this.isOverlay = isOverlay;
}
+ /**
+ * Prior to command execution the block's artificial attribute state may be specified
+ * and will be applied to the new memory block.
+ * @param a block artificial attribute state
+ */
+ public void setArtificial(boolean a) {
+ isArtificial = a;
+ }
+
@Override
public String getStatusMsg() {
return message;
@@ -67,9 +78,8 @@ abstract class AbstractAddMemoryBlockCmd implements Command {
return "Add Memory Block";
}
- protected abstract MemoryBlock createMemoryBlock(Memory memory)
- throws LockException, MemoryConflictException, AddressOverflowException,
- CancelledException;
+ protected abstract MemoryBlock createMemoryBlock(Memory memory) throws LockException,
+ MemoryConflictException, AddressOverflowException, CancelledException;
@Override
public boolean applyTo(DomainObject obj) {
@@ -82,6 +92,7 @@ abstract class AbstractAddMemoryBlockCmd implements Command {
block.setWrite(write);
block.setExecute(execute);
block.setVolatile(isVolatile);
+ block.setArtificial(isArtificial);
block.setSourceName(source);
renameFragment(program, block.getStart());
return true;
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/memory/MemoryMergeManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/memory/MemoryMergeManager.java
index af5feab5a3..3f61909112 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/memory/MemoryMergeManager.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/memory/MemoryMergeManager.java
@@ -196,7 +196,7 @@ public class MemoryMergeManager implements MergeResolver {
if (isNameConflict(i)) {
conflictList.add(new ConflictInfo(i, true, false, false));
}
- if (isPermissionConflict(i)) {
+ if (isFlagsConflict(i)) {
conflictList.add(new ConflictInfo(i, false, true, false));
}
if (isCommentConflict(i)) {
@@ -233,7 +233,8 @@ public class MemoryMergeManager implements MergeResolver {
String myName = myBlocks[index].getName();
String origName = origBlocks[index].getName();
- if (!myName.equals(origName) && !latestName.equals(origName) && !myName.equals(latestName)) {
+ if (!myName.equals(origName) && !latestName.equals(origName) &&
+ !myName.equals(latestName)) {
return true;
}
return false;
@@ -244,13 +245,12 @@ public class MemoryMergeManager implements MergeResolver {
* LATEST and MY programs.
* @param index block index
*/
- private boolean isPermissionConflict(int index) {
- int latestPermissions = latestBlocks[index].getPermissions();
- int myPermissions = myBlocks[index].getPermissions();
- int origPermissions = origBlocks[index].getPermissions();
+ private boolean isFlagsConflict(int index) {
+ int latestFlags = latestBlocks[index].getFlags();
+ int myFlags = myBlocks[index].getFlags();
+ int origFlags = origBlocks[index].getFlags();
- if (myPermissions != origPermissions && latestPermissions != origPermissions &&
- myPermissions != latestPermissions) {
+ if (myFlags != origFlags && latestFlags != origFlags && myFlags != latestFlags) {
return true;
}
return false;
@@ -363,27 +363,21 @@ public class MemoryMergeManager implements MergeResolver {
if (info.nameConflict) {
title = "Resolve Name Conflict";
- latestStr =
- "Use Block name '" + latestBlocks[info.index].getName() + "' (" +
- MergeConstants.LATEST_TITLE + ")";
- myStr =
- "Use Block name '" + getUniqueBlockName(myBlocks[info.index].getName()) + "' (" +
- MergeConstants.MY_TITLE + ")";
- origStr =
- "Use Block name '" + origBlocks[info.index].getName() + "' (" +
- MergeConstants.ORIGINAL_TITLE + ")";
+ latestStr = "Use Block name '" + latestBlocks[info.index].getName() + "' (" +
+ MergeConstants.LATEST_TITLE + ")";
+ myStr = "Use Block name '" + getUniqueBlockName(myBlocks[info.index].getName()) +
+ "' (" + MergeConstants.MY_TITLE + ")";
+ origStr = "Use Block name '" + origBlocks[info.index].getName() + "' (" +
+ MergeConstants.ORIGINAL_TITLE + ")";
}
else if (info.permissionConflict) {
- title = "Resolve Permissions Conflict";
- latestStr =
- "Use '" + getPermissionString(latestBlocks[info.index]) + "' (" +
- MergeConstants.LATEST_TITLE + ")";
- myStr =
- "Use '" + getPermissionString(myBlocks[info.index]) + "' (" +
- MergeConstants.MY_TITLE + ")";
- origStr =
- "Use '" + getPermissionString(origBlocks[info.index]) + "' (" +
- MergeConstants.ORIGINAL_TITLE + ")";
+ title = "Resolve Flags Conflict";
+ latestStr = "Use '" + getFlagsString(latestBlocks[info.index]) + "' (" +
+ MergeConstants.LATEST_TITLE + ")";
+ myStr = "Use '" + getFlagsString(myBlocks[info.index]) + "' (" +
+ MergeConstants.MY_TITLE + ")";
+ origStr = "Use '" + getFlagsString(origBlocks[info.index]) + "' (" +
+ MergeConstants.ORIGINAL_TITLE + ")";
}
else {
// comment conflict
@@ -393,7 +387,8 @@ public class MemoryMergeManager implements MergeResolver {
myStr = myBlocks[info.index].getComment();
origStr = origBlocks[info.index].getComment();
}
- if ((memoryDetailChoice == ASK_USER) && conflictOption == ASK_USER && mergeManager != null) {
+ if ((memoryDetailChoice == ASK_USER) && conflictOption == ASK_USER &&
+ mergeManager != null) {
title = title + " (Block index " + info.index + ")";
showMergePanel(panelID, title, latestStr, myStr, origStr);
}
@@ -428,6 +423,7 @@ public class MemoryMergeManager implements MergeResolver {
resultBlocks[info.index].setWrite(sourceBlock.isWrite());
resultBlocks[info.index].setExecute(sourceBlock.isExecute());
resultBlocks[info.index].setVolatile(sourceBlock.isVolatile());
+ resultBlocks[info.index].setArtificial(sourceBlock.isArtificial());
}
else {
resultBlocks[info.index].setComment(sourceBlock.getComment());
@@ -456,8 +452,8 @@ public class MemoryMergeManager implements MergeResolver {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
}
mergeManager.setApplyEnabled(false);
- mergeManager.showComponent(mergePanel, "MemoryMerge", new HelpLocation(
- HelpTopics.REPOSITORY, "MemoryConflict"));
+ mergeManager.showComponent(mergePanel, "MemoryMerge",
+ new HelpLocation(HelpTopics.REPOSITORY, "MemoryConflict"));
// block until the user either cancels or hits the "Apply" button
// on the merge dialog...
// when the "Apply" button is hit, get the user's selection
@@ -465,7 +461,7 @@ public class MemoryMergeManager implements MergeResolver {
}
- private String getPermissionString(MemoryBlock block) {
+ private String getFlagsString(MemoryBlock block) {
StringBuffer sb = new StringBuffer();
sb.append("Read = ");
sb.append(block.isExecute());
@@ -478,6 +474,9 @@ public class MemoryMergeManager implements MergeResolver {
sb.append(", ");
sb.append("Volatile = ");
sb.append(block.isVolatile());
+ sb.append(", ");
+ sb.append("Artificial = ");
+ sb.append(block.isArtificial());
return sb.toString();
}
@@ -501,7 +500,7 @@ public class MemoryMergeManager implements MergeResolver {
}
}
}
- if (!isPermissionConflict(index)) {
+ if (!isFlagsConflict(index)) {
boolean permission = myBlocks[index].isRead();
if (permission != origBlocks[index].isRead()) {
resultBlocks[index].setRead(permission);
@@ -534,6 +533,14 @@ public class MemoryMergeManager implements MergeResolver {
progressUpdated = true;
}
}
+ permission = myBlocks[index].isArtificial();
+ if (permission != origBlocks[index].isArtificial()) {
+ resultBlocks[index].setArtificial(permission);
+ if (!progressUpdated) {
+ currentMonitor.setProgress(++progressIndex);
+ progressUpdated = true;
+ }
+ }
}
if (!isCommentConflict(index)) {
String myComment = myBlocks[index].getComment();
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/GolangSymbolAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/GolangSymbolAnalyzer.java
index 03aa973861..032ae5d25c 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/GolangSymbolAnalyzer.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/GolangSymbolAnalyzer.java
@@ -136,7 +136,8 @@ public class GolangSymbolAnalyzer extends AbstractAnalyzer {
}
if (analyzerOptions.propagateRtti) {
- Msg.info(this, "Golang symbol analyzer: scheduling RTTI propagation after reference analysis");
+ Msg.info(this,
+ "Golang symbol analyzer: scheduling RTTI propagation after reference analysis");
aam.schedule(new PropagateRttiBackgroundCommand(goBinary),
AnalysisPriority.REFERENCE_ANALYSIS.after().priority());
}
@@ -408,6 +409,7 @@ public class GolangSymbolAnalyzer extends AbstractAnalyzer {
MemoryBlockUtils.createUninitializedBlock(program, false, "ARTIFICAL_GOLANG_CONTEXT",
mbStart, len, "Artifical memory block created to hold golang context data types",
null, true, true, false, null);
+ newMB.setArtificial(true);
return newMB.getStart();
}
@@ -567,8 +569,8 @@ public class GolangSymbolAnalyzer extends AbstractAnalyzer {
}
record CallSiteInfo(Reference ref, Function callingFunc, Function calledFunc,
- Register register,
- java.util.function.Function returnTypeMapper) {}
+ Register register, java.util.function.Function returnTypeMapper) {
+ }
private GoRttiMapper goBinary;
private MarkupSession markupSession;
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/AddressTableAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/AddressTableAnalyzer.java
index 1647641938..d7fa17101c 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/AddressTableAnalyzer.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/AddressTableAnalyzer.java
@@ -107,10 +107,10 @@ public class AddressTableAnalyzer extends AbstractAnalyzer {
processorHasLowBitCode = PseudoDisassembler.hasLowBitCodeModeInAddrValues(program);
// don't align based on instruction start rules, data is important too.
// if do this, will miss, runs of ptrs to data/code/data/code/....
- // ptrAlignment = program.getLanguage().getInstructionAlignment();
- // if (processorHasLowBitCode) {
- // ptrAlignment = 1;
- // }
+ // ptrAlignment = program.getLanguage().getInstructionAlignment();
+ // if (processorHasLowBitCode) {
+ // ptrAlignment = 1;
+ // }
return (addrSize == 32 || addrSize == 64);
}
@@ -164,8 +164,9 @@ public class AddressTableAnalyzer extends AbstractAnalyzer {
continue;
}
- Bookmark bookmark = program.getBookmarkManager().getBookmark(
- tableEntry.getTopAddress(), BookmarkType.ANALYSIS, "Address Table");
+ Bookmark bookmark = program.getBookmarkManager()
+ .getBookmark(tableEntry.getTopAddress(), BookmarkType.ANALYSIS,
+ "Address Table");
// nothing to see here, already done.
if (!ignoreBookmarks && bookmark != null) {
@@ -186,9 +187,10 @@ public class AddressTableAnalyzer extends AbstractAnalyzer {
// put info bookmark in
if (createBookmarksEnabled) {
- program.getBookmarkManager().setBookmark(tableEntry.getTopAddress(),
- BookmarkType.ANALYSIS, "Address Table",
- "Address table[" + tableEntry.getNumberAddressEntries() + "] created");
+ program.getBookmarkManager()
+ .setBookmark(tableEntry.getTopAddress(), BookmarkType.ANALYSIS,
+ "Address Table", "Address table[" +
+ tableEntry.getNumberAddressEntries() + "] created");
}
// if all are valid code, disassemble
@@ -268,8 +270,7 @@ public class AddressTableAnalyzer extends AbstractAnalyzer {
//
AddressSet badBlocks = new AddressSet();
for (MemoryBlock memoryBlock : blocks) {
- if (memoryBlock.isWrite() || memoryBlock.isRead() || memoryBlock.isExecute() ||
- memoryBlock.isVolatile()) {
+ if (memoryBlock.isWrite() || memoryBlock.isRead() || memoryBlock.isExecute()) {
continue;
}
@@ -339,15 +340,16 @@ public class AddressTableAnalyzer extends AbstractAnalyzer {
AddressIterator addrIter = addrSet.getAddresses(true);
long maxBytes = addrSet.getNumAddresses();
-
- MemoryBufferImpl buffer = new MemoryBufferImpl(memory, addrSet.getMinAddress(), (int) (maxBytes > 1024 ? 1024 : maxBytes));
+
+ MemoryBufferImpl buffer = new MemoryBufferImpl(memory, addrSet.getMinAddress(),
+ (int) (maxBytes > 1024 ? 1024 : maxBytes));
while (addrIter.hasNext()) {
Address start = addrIter.next();
// skip over anything that smells like a unicode string
//
- int strLen = getWStrLen(buffer, start, (int)(maxBytes / 2));
+ int strLen = getWStrLen(buffer, start, (int) (maxBytes / 2));
if (strLen > 4) {
int numBytes = strLen * 2;
addrIter = skipBytes(addrIter, addrSet, start, numBytes);
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/AddBlockDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/AddBlockDialog.java
index 78aba20b5b..b34c472ac2 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/AddBlockDialog.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/AddBlockDialog.java
@@ -65,6 +65,7 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
private JCheckBox writeCB;
private JCheckBox executeCB;
private JCheckBox volatileCB;
+ private JCheckBox artificialCB;
private JCheckBox overlayCB;
private RegisterField initialValueField;
private JLabel initialValueLabel;
@@ -108,6 +109,7 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
writeCB.setSelected(model.isWrite());
executeCB.setSelected(model.isExecute());
volatileCB.setSelected(model.isVolatile());
+ artificialCB.setSelected(model.isArtificial());
overlayCB.setSelected(model.isOverlay());
}
@@ -169,6 +171,11 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
volatileCB.setSelected(model.isVolatile());
volatileCB.addActionListener(e -> model.setVolatile(volatileCB.isSelected()));
+ artificialCB = new GCheckBox("Artificial");
+ artificialCB.setName("Artificial");
+ artificialCB.setSelected(model.isArtificial());
+ artificialCB.addActionListener(e -> model.setArtificial(artificialCB.isSelected()));
+
overlayCB = new GCheckBox("Overlay");
overlayCB.setName("Overlay");
overlayCB.setSelected(model.isOverlay());
@@ -180,6 +187,7 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
panel.add(writeCB);
panel.add(executeCB);
panel.add(volatileCB);
+ panel.add(artificialCB);
panel.add(overlayCB);
return panel;
@@ -320,6 +328,7 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
writeCB.setSelected(model.isWrite());
executeCB.setSelected(model.isExecute());
volatileCB.setSelected(model.isVolatile());
+ artificialCB.setSelected(model.isArtificial());
overlayCB.setSelected(model.isOverlay());
setOkEnabled(false);
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/AddBlockModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/AddBlockModel.java
index 469e8f1376..ecb9be0f45 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/AddBlockModel.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/AddBlockModel.java
@@ -18,7 +18,6 @@ package ghidra.app.plugin.core.memory;
import javax.swing.event.ChangeListener;
import ghidra.app.cmd.memory.*;
-import ghidra.framework.cmd.Command;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.database.mem.ByteMappingScheme;
import ghidra.program.database.mem.FileBytes;
@@ -55,6 +54,7 @@ class AddBlockModel {
private boolean isWrite;
private boolean isExecute;
private boolean isVolatile;
+ private boolean isArtificial;
private InitializedType initializedType;
private String comment;
private FileBytes fileBytes;
@@ -125,6 +125,7 @@ class AddBlockModel {
isExecute = false;
isVolatile = false;
isOverlay = false;
+ isArtificial = false;
schemeDestByteCount = blockType == MemoryBlockType.BIT_MAPPED ? 8 : 1;
schemeSrcByteCount = 1;
initializedType = InitializedType.UNINITIALIZED;
@@ -148,6 +149,10 @@ class AddBlockModel {
this.isVolatile = b;
}
+ void setArtificial(boolean b) {
+ this.isArtificial = b;
+ }
+
void setOverlay(boolean b) {
this.isOverlay = b;
validateInfo();
@@ -226,6 +231,10 @@ class AddBlockModel {
return isVolatile;
}
+ boolean isArtificial() {
+ return isArtificial;
+ }
+
boolean isOverlay() {
return isOverlay;
}
@@ -240,7 +249,8 @@ class AddBlockModel {
if (!isValid) {
return false;
}
- Command cmd = createAddBlockCommand();
+ AbstractAddMemoryBlockCmd cmd = createAddBlockCommand();
+ cmd.setArtificial(isArtificial);
if (!tool.execute(cmd, program)) {
message = cmd.getStatusMsg();
return false;
@@ -248,7 +258,7 @@ class AddBlockModel {
return true;
}
- Command createAddBlockCommand() {
+ AbstractAddMemoryBlockCmd createAddBlockCommand() {
String source = "";
switch (blockType) {
case BIT_MAPPED:
@@ -267,7 +277,7 @@ class AddBlockModel {
}
}
- private Command createNonMappedMemoryBlock(String source) {
+ private AbstractAddMemoryBlockCmd createNonMappedMemoryBlock(String source) {
switch (initializedType) {
case INITIALIZED_FROM_FILE_BYTES:
return new AddFileBytesMemoryBlockCmd(blockName, comment, source, startAddr, length,
@@ -293,8 +303,8 @@ class AddBlockModel {
private void validateInfo() {
message = "";
isValid = hasValidName() && hasValidStartAddress() && hasValidLength() &&
- hasNoMemoryConflicts() && hasMappedAddressIfNeeded() &&
- hasInitialValueIfNeeded() && hasFileBytesInfoIfNeeded() && isOverlayIfOtherSpace();
+ hasNoMemoryConflicts() && hasMappedAddressIfNeeded() && hasInitialValueIfNeeded() &&
+ hasFileBytesInfoIfNeeded() && isOverlayIfOtherSpace();
}
private boolean hasFileBytesInfoIfNeeded() {
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapManager.java
index 48f38bdf99..6d7f18c136 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapManager.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapManager.java
@@ -363,6 +363,7 @@ class MemoryMapManager {
newBlock.setWrite(bigBlock.isWrite());
newBlock.setExecute(bigBlock.isExecute());
newBlock.setVolatile(bigBlock.isVolatile());
+ newBlock.setArtificial(bigBlock.isArtificial());
newBlock.setSourceName("Resized Memory Block");
}
else {
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 4190477859..5bed0d0691 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
@@ -51,12 +51,13 @@ class MemoryMapModel extends AbstractSortedTableModel implements Pr
final static byte WRITE = 5;
final static byte EXECUTE = 6;
final static byte VOLATILE = 7;
- final static byte OVERLAY = 8;
- final static byte BLOCK_TYPE = 9;
- final static byte INIT = 10;
- final static byte BYTE_SOURCE = 11;
- final static byte SOURCE = 12;
- final static byte COMMENT = 13;
+ final static byte ARTIFICIAL = 8;
+ final static byte OVERLAY = 9;
+ final static byte BLOCK_TYPE = 10;
+ final static byte INIT = 11;
+ final static byte BYTE_SOURCE = 12;
+ final static byte SOURCE = 13;
+ final static byte COMMENT = 14;
final static String NAME_COL = "Name";
final static String START_COL = "Start";
@@ -66,6 +67,7 @@ class MemoryMapModel extends AbstractSortedTableModel implements Pr
final static String WRITE_COL = "W";
final static String EXECUTE_COL = "X";
final static String VOLATILE_COL = "Volatile";
+ final static String ARTIFICIAL_COL = "Artificial";
final static String OVERLAY_COL = "Overlayed Space";
final static String BLOCK_TYPE_COL = "Type";
final static String INIT_COL = "Initialized";
@@ -80,9 +82,9 @@ class MemoryMapModel extends AbstractSortedTableModel implements Pr
private List memList;
private MemoryMapProvider provider;
- private final static String COLUMN_NAMES[] =
- { NAME_COL, START_COL, END_COL, LENGTH_COL, READ_COL, WRITE_COL, EXECUTE_COL, VOLATILE_COL,
- OVERLAY_COL, BLOCK_TYPE_COL, INIT_COL, BYTE_SOURCE_COL, SOURCE_COL, COMMENT_COL };
+ private final static String COLUMN_NAMES[] = { NAME_COL, START_COL, END_COL, LENGTH_COL,
+ READ_COL, WRITE_COL, EXECUTE_COL, VOLATILE_COL, ARTIFICIAL_COL, OVERLAY_COL, BLOCK_TYPE_COL,
+ INIT_COL, BYTE_SOURCE_COL, SOURCE_COL, COMMENT_COL };
MemoryMapModel(MemoryMapProvider provider, Program program) {
super(START);
@@ -124,7 +126,7 @@ class MemoryMapModel extends AbstractSortedTableModel implements Pr
@Override
public boolean isSortable(int columnIndex) {
if (columnIndex == READ || columnIndex == WRITE || columnIndex == EXECUTE ||
- columnIndex == VOLATILE || columnIndex == INIT) {
+ columnIndex == VOLATILE || columnIndex == ARTIFICIAL || columnIndex == INIT) {
return false;
}
return true;
@@ -163,7 +165,7 @@ class MemoryMapModel extends AbstractSortedTableModel implements Pr
@Override
public Class> getColumnClass(int columnIndex) {
if (columnIndex == READ || columnIndex == WRITE || columnIndex == EXECUTE ||
- columnIndex == VOLATILE || columnIndex == INIT) {
+ columnIndex == VOLATILE || columnIndex == ARTIFICIAL || columnIndex == INIT) {
return Boolean.class;
}
return String.class;
@@ -178,6 +180,8 @@ class MemoryMapModel extends AbstractSortedTableModel implements Pr
case WRITE:
case EXECUTE:
case VOLATILE:
+ case ARTIFICIAL:
+ return true;
case COMMENT:
return true;
case INIT:
@@ -267,6 +271,14 @@ class MemoryMapModel extends AbstractSortedTableModel implements Pr
});
break;
}
+ case ARTIFICIAL: {
+ program.withTransaction("Set Artificial State", () -> {
+ boolean value = ((Boolean) aValue).booleanValue();
+ block.setArtificial(value);
+ provider.setStatusText("");
+ });
+ break;
+ }
case INIT:
MemoryBlockType blockType = block.getType();
if (blockType == MemoryBlockType.BIT_MAPPED ||
@@ -428,6 +440,8 @@ class MemoryMapModel extends AbstractSortedTableModel implements Pr
return block.isExecute() ? Boolean.TRUE : Boolean.FALSE;
case VOLATILE:
return block.isVolatile() ? Boolean.TRUE : Boolean.FALSE;
+ case ARTIFICIAL:
+ return block.isArtificial() ? Boolean.TRUE : Boolean.FALSE;
case OVERLAY:
return getOverlayBaseSpaceName(block);
case INIT:
@@ -554,29 +568,21 @@ class MemoryMapModel extends AbstractSortedTableModel implements Pr
case LENGTH:
return (int) (b1.getSize() - b2.getSize());
case READ:
- int b1r = (b1.isRead() ? 1 : -1);
- int b2r = (b2.isRead() ? 1 : -1);
- return (b1r - b2r);
+ return Boolean.compare(b1.isRead(), b2.isRead());
case WRITE:
- int b1w = (b1.isWrite() ? 1 : -1);
- int b2w = (b2.isWrite() ? 1 : -1);
- return (b1w - b2w);
+ return Boolean.compare(b1.isWrite(), b2.isWrite());
case EXECUTE:
- int b1x = (b1.isExecute() ? 1 : -1);
- int b2x = (b2.isExecute() ? 1 : -1);
- return (b1x - b2x);
+ return Boolean.compare(b1.isExecute(), b2.isExecute());
case VOLATILE:
- int b1v = (b1.isVolatile() ? 1 : -1);
- int b2v = (b2.isVolatile() ? 1 : -1);
- return (b1v - b2v);
+ return Boolean.compare(b1.isVolatile(), b2.isVolatile());
+ case ARTIFICIAL:
+ return Boolean.compare(b1.isArtificial(), b2.isArtificial());
case OVERLAY:
String ov1 = getOverlayBaseSpaceName(b1);
String ov2 = getOverlayBaseSpaceName(b2);
return ov1.compareTo(ov2);
case INIT:
- int b1init = (b1.isInitialized() ? 1 : -1);
- int b2init = (b2.isInitialized() ? 1 : -1);
- return (b1init - b2init);
+ return Boolean.compare(b1.isInitialized(), b2.isInitialized());
//case BYTE_SOURCE: - handled by default comparator
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java
index d10b3c4dfd..6004315da1 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java
@@ -480,6 +480,13 @@ class MemoryMapProvider extends ComponentProviderAdapter {
column.setResizable(false);
}
+ column = table.getColumn(MemoryMapModel.ARTIFICIAL_COL);
+ if (column != null) {
+ column.setMaxWidth(65);
+ column.setMinWidth(65);
+ column.setResizable(false);
+ }
+
column = table.getColumn(MemoryMapModel.BLOCK_TYPE_COL);
if (column != null) {
column.setMinWidth(25);
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/string/StringsAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/string/StringsAnalyzer.java
index 59f5ca18fe..e386f33e77 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/string/StringsAnalyzer.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/string/StringsAnalyzer.java
@@ -109,6 +109,7 @@ public class StringsAnalyzer extends AbstractAnalyzer {
public static enum Alignment {
ALIGN_1(1), ALIGN_2(2), ALIGN_4(4);
+
private int alignment;
Alignment(int alignment) {
@@ -349,7 +350,10 @@ public class StringsAnalyzer extends AbstractAnalyzer {
AddressSet addresses = new AddressSet();
for (MemoryBlock memBlock : blocks) {
- if (memBlock.getPermissions() > 0) {
+ if (!memBlock.isLoaded()) {
+ continue;
+ }
+ if (memBlock.isWrite() || memBlock.isRead() || memBlock.isExecute()) {
addresses = addresses.union(new AddressSet(memBlock.getStart(), memBlock.getEnd()));
}
}
@@ -581,14 +585,15 @@ public class StringsAnalyzer extends AbstractAnalyzer {
modelName = options.getString(MODELFILE_OPTION_NAME, MODEL_DEFAULT_NAME);
setTrigramFileName(modelName);
- minStringLength = options.getEnum(MINIMUM_STRING_LENGTH_OPTION_NAME,
- MINIMUM_STRING_LENGTH_DEFAULT_VALUE).getMinLength();
+ minStringLength =
+ options.getEnum(MINIMUM_STRING_LENGTH_OPTION_NAME, MINIMUM_STRING_LENGTH_DEFAULT_VALUE)
+ .getMinLength();
requireNullEnd = options.getBoolean(REQUIRE_NULL_TERMINATION_OPTION_NAME,
REQUIRE_NULL_TERMINATION_DEFAULT_VALUE);
- startAlignment = options.getEnum(START_ALIGNMENT_OPTION_NAME,
- START_ALIGNMENT_DEFAULT_VALUE).getAlignment();
+ startAlignment = options.getEnum(START_ALIGNMENT_OPTION_NAME, START_ALIGNMENT_DEFAULT_VALUE)
+ .getAlignment();
setStringEndAlignment(
options.getInt(END_ALIGNMENT_OPTION_NAME, END_ALIGNMENT_DEFAULT_VALUE));
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/ThreadEnvironmentBlock.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/ThreadEnvironmentBlock.java
index 1eda299cb0..c2d97eabe4 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/ThreadEnvironmentBlock.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/ThreadEnvironmentBlock.java
@@ -706,9 +706,9 @@ public class ThreadEnvironmentBlock {
* @throws CodeUnitInsertionException for problems laying down the structure on the block
* @throws InvalidInputException for problems with the symbol name attached to the TEB
*/
- public void createBlockAndStructure() throws MemoryConflictException, LockException,
- IllegalArgumentException, AddressOverflowException, CodeUnitInsertionException,
- InvalidInputException {
+ public void createBlockAndStructure()
+ throws MemoryConflictException, LockException, IllegalArgumentException,
+ AddressOverflowException, CodeUnitInsertionException, InvalidInputException {
Memory memory = program.getMemory();
MemoryBlock block = memory.getBlock(BLOCK_NAME);
if (block != null) {
@@ -722,6 +722,7 @@ public class ThreadEnvironmentBlock {
block = memory.createUninitializedBlock(BLOCK_NAME, tebAddress, blockSize, false);
}
block.setWrite(true);
+ block.setArtificial(true);
LayDownStructure laydown = new LayDownStructure(is64Bit);
create(laydown);
if (is64Bit) {
@@ -806,6 +807,7 @@ public class ThreadEnvironmentBlock {
null, false);
}
block1.setWrite(true);
+ block1.setArtificial(true);
LayDownFlat laydown = new LayDownFlat(program, tebAddress, is64Bit);
create(laydown);
Data data = program.getListing().getDataAt(tebAddress.add(is64Bit ? 0x30 : 0x18));
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/CoffLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/CoffLoader.java
index d2841d8189..ea251ffcff 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/CoffLoader.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/CoffLoader.java
@@ -349,6 +349,9 @@ public class CoffLoader extends AbstractLibrarySupportLoader {
// assume any value in external is writable.
block.setWrite(true);
+ // Mark block as an artificial fabrication
+ block.setArtificial(true);
+
Address current = externalAddressStart;
while (current.compareTo(externalAddress) < 0) {
createUndefined(program.getListing(), program.getMemory(), current,
@@ -745,8 +748,8 @@ public class CoffLoader extends AbstractLibrarySupportLoader {
}
}
- private void handleRelocationError(Program program, Address address,
- Short relocationType, String message, Exception causeToReport) {
+ private void handleRelocationError(Program program, Address address, Short relocationType,
+ String message, Exception causeToReport) {
String bookmarkMessage =
String.format("Failed to apply COFF Relocation type 0x%x: %s", relocationType, message);
program.getBookmarkManager()
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java
index 186a116582..ddbdd50868 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java
@@ -1546,6 +1546,10 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
// assume any value in external is writable.
block.setWrite(true);
+
+ // Mark block as an artificial fabrication
+ block.setArtificial(true);
+
block.setSourceName(BLOCK_SOURCE_NAME);
block.setComment(
"NOTE: This block is artificial and allows ELF Relocations to work correctly");
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java
index 5561843494..3ea9c5c61f 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java
@@ -105,8 +105,8 @@ public class MachoProgramBuilder {
*/
public static void buildProgram(Program program, ByteProvider provider, FileBytes fileBytes,
MessageLog log, TaskMonitor monitor) throws Exception {
- MachoProgramBuilder machoProgramBuilder = new MachoProgramBuilder(program, provider,
- fileBytes, log, monitor);
+ MachoProgramBuilder machoProgramBuilder =
+ new MachoProgramBuilder(program, provider, fileBytes, log, monitor);
machoProgramBuilder.build();
}
@@ -154,7 +154,7 @@ public class MachoProgramBuilder {
fixupProgramTree(null); // should be done last to account for new memory blocks
setCompiler();
}
-
+
/**
* Sets the image base
*
@@ -339,8 +339,7 @@ public class MachoProgramBuilder {
* @param suffix An optional suffix that will get appended to tree segment and segment nodes
* @throws Exception if there was a problem fixing up the Program Tree
*/
- protected void fixupProgramTree(String suffix)
- throws Exception {
+ protected void fixupProgramTree(String suffix) throws Exception {
if (suffix == null) {
suffix = "";
}
@@ -399,7 +398,7 @@ public class MachoProgramBuilder {
section.getSectionName() + suffix));
sectionFragment.move(sectionStart, sectionEnd);
}
-
+
// If the sections fully filled the segment, we can remove the now-empty segment
if (segmentFragment.isEmpty()) {
segmentModule.removeChild(segmentFragment.getName());
@@ -456,7 +455,7 @@ public class MachoProgramBuilder {
log.appendMsg("Unable to determine entry point.");
}
}
-
+
protected boolean processExports(MachHeader header) throws Exception {
monitor.setMessage("Processing exports...");
@@ -501,7 +500,7 @@ public class MachoProgramBuilder {
}
return !exports.isEmpty();
- }
+ }
protected void processNewExport(Address baseAddr, ExportEntry export, String name)
throws AddressOutOfBoundsException, Exception {
@@ -680,6 +679,10 @@ public class MachoProgramBuilder {
start, undefinedSymbols.size() * machoHeader.getAddressSize(), false);
// assume any value in external is writable.
block.setWrite(true);
+
+ // Mark block as an artificial fabrication
+ block.setArtificial(true);
+
block.setSourceName(BLOCK_SOURCE_NAME);
block.setComment(
"NOTE: This block is artificial and is used to make relocations work correctly");
@@ -792,14 +795,15 @@ public class MachoProgramBuilder {
}
}
- private void processBindings(BindingTable bindingTable, List libraryPaths) throws Exception {
+ private void processBindings(BindingTable bindingTable, List libraryPaths)
+ throws Exception {
DataConverter converter = DataConverter.getInstance(program.getLanguage().isBigEndian());
SymbolTable symbolTable = program.getSymbolTable();
List bindings = bindingTable.getBindings();
List threadedBindings = bindingTable.getThreadedBindings();
List segments = machoHeader.getAllSegments();
-
+
if (threadedBindings != null) {
DyldChainedFixups dyldChainedFixups =
new DyldChainedFixups(program, machoHeader, libraryPaths, log, monitor);
@@ -834,7 +838,7 @@ public class MachoProgramBuilder {
Address addr =
space.getAddress(segments.get(binding.getSegmentIndex()).getVMaddress() +
binding.getSegmentOffset());
-
+
fixupExternalLibrary(binding.getLibraryOrdinal(), symbol, libraryPaths);
boolean success = false;
@@ -1103,16 +1107,16 @@ public class MachoProgramBuilder {
}
/**
- * Processes the section relocations from all {@link Section}s.
- *
- * @throws CancelledException if the operation was cancelled.
- */
- protected void processSectionRelocations() throws CancelledException {
- monitor.setMessage("Processing section relocations...");
+ * Processes the section relocations from all {@link Section}s.
+ *
+ * @throws CancelledException if the operation was cancelled.
+ */
+ protected void processSectionRelocations() throws CancelledException {
+ monitor.setMessage("Processing section relocations...");
LinkedHashMap relocationMap = new LinkedHashMap<>();
- for (Section section : machoHeader.getAllSections()) {
- monitor.checkCancelled();
+ for (Section section : machoHeader.getAllSections()) {
+ monitor.checkCancelled();
MemoryBlock sectionMemoryBlock = getMemoryBlock(section);
if (sectionMemoryBlock == null) {
@@ -1124,54 +1128,54 @@ public class MachoProgramBuilder {
}
for (RelocationInfo relocationInfo : section.getRelocations()) {
- monitor.checkCancelled();
+ monitor.checkCancelled();
Address address = sectionMemoryBlock.getStart().add(relocationInfo.getAddress());
relocationMap.put(relocationInfo, address);
}
}
- performRelocations(relocationMap);
+ performRelocations(relocationMap);
}
/**
- * Processes the external relocations from all {@link DynamicSymbolTableCommand}s.
- *
- * @throws CancelledException if the operation was cancelled.
- */
- protected void processExternalRelocations() throws CancelledException {
+ * Processes the external relocations from all {@link DynamicSymbolTableCommand}s.
+ *
+ * @throws CancelledException if the operation was cancelled.
+ */
+ protected void processExternalRelocations() throws CancelledException {
monitor.setMessage("Processing external relocations...");
LinkedHashMap relocationMap = new LinkedHashMap<>();
- for (DynamicSymbolTableCommand cmd : machoHeader
- .getLoadCommands(DynamicSymbolTableCommand.class)) {
- monitor.checkCancelled();
- for (RelocationInfo relocationInfo : cmd.getExternalRelocations()) {
- monitor.checkCancelled();
- relocationMap.put(relocationInfo, space.getAddress(relocationInfo.getAddress()));
- }
- }
- performRelocations(relocationMap);
+ for (DynamicSymbolTableCommand cmd : machoHeader
+ .getLoadCommands(DynamicSymbolTableCommand.class)) {
+ monitor.checkCancelled();
+ for (RelocationInfo relocationInfo : cmd.getExternalRelocations()) {
+ monitor.checkCancelled();
+ relocationMap.put(relocationInfo, space.getAddress(relocationInfo.getAddress()));
+ }
+ }
+ performRelocations(relocationMap);
}
/**
- * Processes the local relocations from all {@link DynamicSymbolTableCommand}s.
- *
- * @throws CancelledException if the operation was cancelled.
- */
- protected void processLocalRelocations() throws CancelledException {
+ * Processes the local relocations from all {@link DynamicSymbolTableCommand}s.
+ *
+ * @throws CancelledException if the operation was cancelled.
+ */
+ protected void processLocalRelocations() throws CancelledException {
monitor.setMessage("Processing local relocations...");
LinkedHashMap relocationMap = new LinkedHashMap<>();
- for (DynamicSymbolTableCommand cmd : machoHeader
- .getLoadCommands(DynamicSymbolTableCommand.class)) {
- monitor.checkCancelled();
- for (RelocationInfo relocationInfo : cmd.getLocalRelocations()) {
- monitor.checkCancelled();
- relocationMap.put(relocationInfo, space.getAddress(relocationInfo.getAddress()));
- }
- }
- performRelocations(relocationMap);
+ for (DynamicSymbolTableCommand cmd : machoHeader
+ .getLoadCommands(DynamicSymbolTableCommand.class)) {
+ monitor.checkCancelled();
+ for (RelocationInfo relocationInfo : cmd.getLocalRelocations()) {
+ monitor.checkCancelled();
+ relocationMap.put(relocationInfo, space.getAddress(relocationInfo.getAddress()));
+ }
+ }
+ performRelocations(relocationMap);
}
protected List processLibraries() throws Exception {
@@ -1215,7 +1219,7 @@ public class MachoProgramBuilder {
if (program.getSymbolTable().getLibrarySymbol(Library.UNKNOWN) == null) {
program.getSymbolTable().createExternalLibrary(Library.UNKNOWN, SourceType.IMPORTED);
}
-
+
return libraryPaths;
}
@@ -1257,23 +1261,23 @@ public class MachoProgramBuilder {
* @throws CancelledException if the operation was cancelled.
*/
private void performRelocations(LinkedHashMap relocationMap)
- throws CancelledException {
+ throws CancelledException {
if (relocationMap.isEmpty()) {
return;
}
- MachoRelocationHandler handler = MachoRelocationHandlerFactory.getHandler(machoHeader);
+ MachoRelocationHandler handler = MachoRelocationHandlerFactory.getHandler(machoHeader);
if (handler == null) {
log.appendMsg(String.format("No relocation handler for machine type 0x%x",
machoHeader.getCpuType()));
}
- Iterator iter = relocationMap.keySet().iterator();
- while (iter.hasNext()) {
- RelocationInfo relocationInfo = iter.next();
- Address address = relocationMap.get(relocationInfo);
- MachoRelocation relocation = null;
+ Iterator iter = relocationMap.keySet().iterator();
+ while (iter.hasNext()) {
+ RelocationInfo relocationInfo = iter.next();
+ Address address = relocationMap.get(relocationInfo);
+ MachoRelocation relocation = null;
RelocationResult result = RelocationResult.FAILURE;
if (handler != null) {
@@ -1281,7 +1285,7 @@ public class MachoProgramBuilder {
? new MachoRelocation(program, machoHeader, address, relocationInfo,
iter.next())
: new MachoRelocation(program, machoHeader, address, relocationInfo);
- try {
+ try {
result = handler.relocate(relocation);
if (result.status() == Status.UNSUPPORTED) {
@@ -1291,9 +1295,9 @@ public class MachoProgramBuilder {
}
}
catch (MemoryAccessException e) {
- handleRelocationError(address, String.format(
+ handleRelocationError(address, String.format(
"Relocation failure at address %s: error accessing memory.", address));
- }
+ }
catch (RelocationException e) {
handleRelocationError(address, String.format(
"Relocation failure at address %s: %s", address, e.getMessage()));
@@ -1306,18 +1310,19 @@ public class MachoProgramBuilder {
msg = String.format("Relocation failure at address %s: %s", address, msg);
handleRelocationError(address, msg);
Msg.error(this, msg, e);
- }
+ }
}
program.getRelocationTable()
.add(address, result.status(), relocationInfo.getType(),
- new long[] { relocationInfo.getValue(),
- relocationInfo.getLength(), relocationInfo.isPcRelocated() ? 1 : 0,
- relocationInfo.isExternal() ? 1 : 0, relocationInfo.isScattered() ? 1 : 0 },
+ new long[] { relocationInfo.getValue(), relocationInfo.getLength(),
+ relocationInfo.isPcRelocated() ? 1 : 0,
+ relocationInfo.isExternal() ? 1 : 0,
+ relocationInfo.isScattered() ? 1 : 0 },
result.byteLength(),
relocation != null ? relocation.getTargetDescription() : null);
}
}
-
+
/**
* Marks up {@link LoadCommand} dadta
*
@@ -1338,10 +1343,10 @@ public class MachoProgramBuilder {
* @param message The error message
*/
private void handleRelocationError(Address address, String message) {
- program.getBookmarkManager()
- .setBookmark(address, BookmarkType.ERROR, "Relocations", message);
- log.appendMsg(message);
- }
+ program.getBookmarkManager()
+ .setBookmark(address, BookmarkType.ERROR, "Relocations", message);
+ log.appendMsg(message);
+ }
private void addLibrary(String library) {
library = library.replaceAll(" ", "_");
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/NeLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/NeLoader.java
index a0a38f7e53..1c20444cba 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/NeLoader.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/NeLoader.java
@@ -256,8 +256,8 @@ public class NeLoader extends AbstractOrdinalSupportLoader {
}
MemoryBlock block;
if (length > 0) {
- block = MemoryBlockUtils.createInitializedBlock(program, false,
- name, addr, fileBytes, offset, length, "", "", r, w, x, log);
+ block = MemoryBlockUtils.createInitializedBlock(program, false, name, addr,
+ fileBytes, offset, length, "", "", r, w, x, log);
if (length < minalloc) {
// Things actually rely on the block being padded out with real 0's, so we
// must expand it
@@ -354,8 +354,7 @@ public class NeLoader extends AbstractOrdinalSupportLoader {
int length = resource.getFileLengthShifted();
if (length > 0) {
MemoryBlockUtils.createInitializedBlock(program, false, "Rsrc" + (id++),
- addr, fileBytes, offset, length, "", "", true,
- false, false, log);
+ addr, fileBytes, offset, length, "", "", true, false, false, log);
}
}
catch (AddressOverflowException e) {
@@ -445,8 +444,12 @@ public class NeLoader extends AbstractOrdinalSupportLoader {
String comment = "";
String source = "";
// This isn't a real block, just place holder addresses, so don't create an initialized block
- MemoryBlockUtils.createUninitializedBlock(program, false, MemoryBlock.EXTERNAL_BLOCK_NAME,
- addr, length, comment, source, true, false, false, log);
+ MemoryBlock block = MemoryBlockUtils.createUninitializedBlock(program, false,
+ MemoryBlock.EXTERNAL_BLOCK_NAME, addr, length, comment, source, true, false, false,
+ log);
+
+ // Mark block as an artificial fabrication
+ block.setArtificial(true);
for (int i = 0; i < names.length; ++i) {
String moduleName = names[i].getString();
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/OmfLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/OmfLoader.java
index b5d0fb9cfb..50c6ffd37d 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/OmfLoader.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/OmfLoader.java
@@ -204,7 +204,7 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
int method, index, locationType = -1;
locAddress = null;
- if(fixup.getDataBlock() == null) {
+ if (fixup.getDataBlock() == null) {
continue; // If no data block don't try to fixup
}
try {
@@ -613,6 +613,9 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
// assume any value in external is writable.
block.setWrite(true);
+ // Mark block as an artificial fabrication
+ block.setArtificial(true);
+
Address current = externalAddressStart;
while (current.compareTo(externalAddress) < 0) {
createUndefined(program.getListing(), program.getMemory(), current,
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 d41c30ae83..eb5ea454b8 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
@@ -52,8 +52,7 @@ class MemoryMapXmlMgr {
///////////////////////////////////////////////////////////////////////////////////////
void read(XmlPullParser parser, boolean overwriteConflicts, TaskMonitor monitor,
- String directory)
- throws SAXParseException, FileNotFoundException, CancelledException {
+ String directory) throws SAXParseException, FileNotFoundException, CancelledException {
XmlElement element = parser.next();
element = parser.next();
@@ -71,8 +70,7 @@ class MemoryMapXmlMgr {
}
private void processMemoryBlock(XmlElement memorySectionElement, XmlPullParser parser,
- String directory, Program program, TaskMonitor monitor)
- throws FileNotFoundException {
+ String directory, Program program, TaskMonitor monitor) throws FileNotFoundException {
String name = memorySectionElement.getAttribute("NAME");
String addrStr = memorySectionElement.getAttribute("START_ADDR");
@@ -91,6 +89,9 @@ class MemoryMapXmlMgr {
String volatility = memorySectionElement.getAttribute("VOLATILE");
boolean isVolatile = "y".equals(volatility);
+ String artificial = memorySectionElement.getAttribute("ARTIFICIAL");
+ boolean isArtificial = "y".equals(artificial);
+
String comment = memorySectionElement.getAttribute("COMMENT");
try {
@@ -124,12 +125,12 @@ class MemoryMapXmlMgr {
element = parser.peek();//get next start of contents or end of section
}
if (overlayName != null) {
- MemoryBlock block =
- MemoryBlockUtils.createInitializedBlock(program, true, overlayName, addr,
- new ByteArrayInputStream(bytes),
- bytes.length, comment, null, r, w, x, log, monitor);
+ MemoryBlock block = MemoryBlockUtils.createInitializedBlock(program, true,
+ overlayName, addr, new ByteArrayInputStream(bytes), bytes.length, comment,
+ null, r, w, x, log, monitor);
if (block != null) {
block.setVolatile(isVolatile);
+ block.setArtificial(isArtificial);
if (!name.equals(overlayName)) {
block.setName(name);
}
@@ -138,8 +139,8 @@ class MemoryMapXmlMgr {
else {
MemoryBlock block = MemoryBlockUtils.createInitializedBlock(program, false,
- name, addr, new ByteArrayInputStream(bytes), bytes.length, comment, null,
- r, w, x, log, monitor);
+ name, addr, new ByteArrayInputStream(bytes), bytes.length, comment, null, r,
+ w, x, log, monitor);
if (block != null) {
block.setVolatile(isVolatile);
}
@@ -297,6 +298,10 @@ class MemoryMapXmlMgr {
attrs.addAttribute("VOLATILE", true);
}
+ if (block.isArtificial()) {
+ attrs.addAttribute("ARTIFICIAL", true);
+ }
+
writer.startElement("MEMORY_SECTION", attrs);
if (block.getType() == MemoryBlockType.BIT_MAPPED) {
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/MemoryBlockDiff.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/MemoryBlockDiff.java
index 3d3e925928..6a2ffaa530 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/MemoryBlockDiff.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/MemoryBlockDiff.java
@@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
- * REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,7 +22,8 @@ import ghidra.util.SystemUtilities;
* MemoryBlockDiff
determines the types of differences between two memory blocks.
*/
public class MemoryBlockDiff {
-
+
+ //@formatter:off
public static final int NAME = 0x001;
public static final int START_ADDRESS = 0x002;
public static final int END_ADDRESS = 0x004;
@@ -32,16 +32,18 @@ public class MemoryBlockDiff {
public static final int WRITE = 0x020;
public static final int EXECUTE = 0x040;
public static final int VOLATILE = 0x080;
- public static final int TYPE = 0x100;
- public static final int INIT = 0x200;
- public static final int SOURCE = 0x400;
- public static final int COMMENT = 0x800;
- public static final int ALL = 0xFFF;
-
+ public static final int ARTIFICIAL = 0x100;
+ public static final int TYPE = 0x200;
+ public static final int INIT = 0x400;
+ public static final int SOURCE = 0x800;
+ public static final int COMMENT = 0x1000;
+ public static final int ALL = 0x1FFF;
+ //@formatter:on
+
private MemoryBlock block1;
private MemoryBlock block2;
private int diffFlags;
-
+
/**
* Constructor. MemoryBlockDiff
determines the types of differences
* between two memory blocks.
@@ -57,139 +59,149 @@ public class MemoryBlockDiff {
MemoryBlock getBlock1() {
return block1;
}
-
+
MemoryBlock getBlock2() {
return block2;
}
-
+
/**
* Returns true if the memory block names differ.
*/
public boolean isNameDifferent() {
return (diffFlags & NAME) != 0;
}
-
+
/**
* Returns true if the start addresses of the memory blocks differ.
*/
public boolean isStartAddressDifferent() {
return (diffFlags & START_ADDRESS) != 0;
}
-
+
/**
* Returns true if the end addresses of the memory blocks differ.
*/
public boolean isEndAddressDifferent() {
return (diffFlags & END_ADDRESS) != 0;
}
-
+
/**
* Returns true if the sizes of the memory blocks differ.
*/
public boolean isSizeDifferent() {
return (diffFlags & SIZE) != 0;
}
-
+
/**
* Returns true if the memory blocks Read flags differ.
*/
public boolean isReadDifferent() {
return (diffFlags & READ) != 0;
}
-
+
/**
* Returns true if the memory blocks Write flags differ.
*/
public boolean isWriteDifferent() {
return (diffFlags & WRITE) != 0;
}
-
+
/**
* Returns true if the memory blocks Execute flags differ.
*/
public boolean isExecDifferent() {
return (diffFlags & EXECUTE) != 0;
}
-
+
/**
* Returns true if the memory blocks Volatile flags differ.
*/
public boolean isVolatileDifferent() {
return (diffFlags & VOLATILE) != 0;
}
-
+
+ /**
+ * Returns true if the memory blocks Artificial flags differ.
+ */
+ public boolean isArtificialDifferent() {
+ return (diffFlags & ARTIFICIAL) != 0;
+ }
+
/**
* Returns true if the type for the memory blocks differ.
*/
public boolean isTypeDifferent() {
return (diffFlags & TYPE) != 0;
}
-
+
/**
* Returns true if the initialization of the memory blocks isn't the same.
*/
public boolean isInitDifferent() {
return (diffFlags & INIT) != 0;
}
-
+
/**
* Returns true if the source for the memory blocks differ.
*/
public boolean isSourceDifferent() {
return (diffFlags & SOURCE) != 0;
}
-
+
/**
* Returns true if the comments on the memory blocks differ.
*/
public boolean isCommentDifferent() {
return (diffFlags & COMMENT) != 0;
}
-
+
/**
* Gets a string representation of the types of memory differences for this MemoryBlockDiff.
*/
public String getDifferencesAsString() {
StringBuffer buf = new StringBuffer();
- if((diffFlags & NAME) != 0) {
+ if ((diffFlags & NAME) != 0) {
buf.append("Name ");
}
- if((diffFlags & START_ADDRESS) != 0) {
+ if ((diffFlags & START_ADDRESS) != 0) {
buf.append("StartAddress ");
}
- if((diffFlags & END_ADDRESS) != 0) {
+ if ((diffFlags & END_ADDRESS) != 0) {
buf.append("EndAddress ");
}
- if((diffFlags & SIZE) != 0) {
+ if ((diffFlags & SIZE) != 0) {
buf.append("Size ");
}
- if((diffFlags & READ) != 0) {
+ if ((diffFlags & READ) != 0) {
buf.append("R ");
}
- if((diffFlags & WRITE) != 0) {
+ if ((diffFlags & WRITE) != 0) {
buf.append("W ");
}
- if((diffFlags & EXECUTE) != 0) {
+ if ((diffFlags & EXECUTE) != 0) {
buf.append("X ");
}
- if((diffFlags & VOLATILE) != 0) {
+ if ((diffFlags & VOLATILE) != 0) {
buf.append("Volatile ");
}
- if((diffFlags & TYPE) != 0) {
+ if ((diffFlags & ARTIFICIAL) != 0) {
+ buf.append("Artificial ");
+ }
+ if ((diffFlags & TYPE) != 0) {
buf.append("Type ");
}
- if((diffFlags & INIT) != 0) {
+ if ((diffFlags & INIT) != 0) {
buf.append("Initialized ");
}
- if((diffFlags & SOURCE) != 0) {
+ if ((diffFlags & SOURCE) != 0) {
buf.append("Source ");
}
- if((diffFlags & COMMENT) != 0) {
+ if ((diffFlags & COMMENT) != 0) {
buf.append("Comment ");
}
return buf.toString();
}
-
+
/**
* Gets an integer value that has bits set as flags indicating the types of differences
* that exist between the two memory blocks.
@@ -207,9 +219,9 @@ public class MemoryBlockDiff {
if (block2 == null) {
return ALL;
}
-
+
int flags = 0;
- if(!block1.getName().equals(block2.getName())) {
+ if (!block1.getName().equals(block2.getName())) {
flags |= NAME;
}
if (!block1.getStart().equals(block2.getStart())) {
@@ -233,6 +245,9 @@ public class MemoryBlockDiff {
if (block1.isVolatile() != block2.isVolatile()) {
flags |= VOLATILE;
}
+ if (block1.isArtificial() != block2.isArtificial()) {
+ flags |= ARTIFICIAL;
+ }
if (!block1.getType().equals(block2.getType())) {
flags |= TYPE;
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/MemoryDiff.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/MemoryDiff.java
index 99a007e792..8fab4d6b42 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/MemoryDiff.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/MemoryDiff.java
@@ -31,14 +31,14 @@ import ghidra.util.task.TaskMonitor;
* types of differences.
*/
public class MemoryDiff {
-
+
private Program program1;
private Program program2;
private Memory memory1;
private Memory memory2;
private AddressRange[] ranges;
private MemoryBlockDiff[] diffs;
-
+
/**
* Constructs an object for determining memory differences between two programs.
* @param p1 the first program
@@ -46,8 +46,7 @@ public class MemoryDiff {
* @throws ProgramConflictException if the program memory can't be compared because the programs
* are based on different languages.
*/
- public MemoryDiff(Program p1, Program p2)
- throws ProgramConflictException {
+ public MemoryDiff(Program p1, Program p2) throws ProgramConflictException {
program1 = p1;
program2 = p2;
memory1 = program1.getMemory();
@@ -55,7 +54,7 @@ public class MemoryDiff {
computeRanges();
computeDifferences();
}
-
+
/**
* Gets the first program that is part of this MemoryDiff.
* @return the first program
@@ -63,7 +62,7 @@ public class MemoryDiff {
public Program getProgram1() {
return program1;
}
-
+
/**
* Gets the second program that is part of this MemoryDiff.
* @return the second program
@@ -71,7 +70,7 @@ public class MemoryDiff {
public Program getProgram2() {
return program2;
}
-
+
/**
* Determines the address ranges that the two programs memories must be broken into for
* properly comparing the programs. Each of these address ranges will exist in the first
@@ -82,12 +81,12 @@ public class MemoryDiff {
ProgramMemoryComparator memComp = new ProgramMemoryComparator(program1, program2);
ArrayList rangeList = new ArrayList();
AddressRangeIterator rangeIter = memComp.getAddressRanges();
- while(rangeIter.hasNext()) {
+ while (rangeIter.hasNext()) {
rangeList.add(rangeIter.next());
}
ranges = rangeList.toArray(new AddressRange[rangeList.size()]);
}
-
+
/**
* Gets the number of address ranges that the two programs memories are broken into for
* comparing the programs.
@@ -96,7 +95,7 @@ public class MemoryDiff {
public int getNumRanges() {
return ranges.length;
}
-
+
/**
* Gets the address range as indicated by index. The index is zero based. Address ranges are
* in order from the minimum address to the maximum address range.
@@ -106,7 +105,7 @@ public class MemoryDiff {
public AddressRange getRange(int index) {
return ranges[index];
}
-
+
/**
* Gets the memory difference flags for the address range as indicated by index.
* @param index the index of the address range to get the difference flags for.
@@ -115,7 +114,7 @@ public class MemoryDiff {
public MemoryBlockDiff getDifferenceInfo(int index) {
return diffs[index];
}
-
+
/**
* Determines the memory differences and sets the flags for each associated address range.
*/
@@ -128,7 +127,7 @@ public class MemoryDiff {
diffs[i] = new MemoryBlockDiff(block1, block2);
}
}
-
+
/**
* Gets a string representation of the types of memory differences that exist for the memory
* block that contains the indicated address.
@@ -143,30 +142,30 @@ public class MemoryDiff {
MemoryBlockDiff info = getDifferenceInfo(index);
return info.getDifferencesAsString();
}
-
+
/**
* Gets the index of the address range containing the indicated address,
* if it is contained in the list;
- * otherwise, (-(insertion point) - 1).
+ * otherwise, (-(insertion point) - 1).
* @param address the address whose range we are interested in finding.
* @return the index of the address range.
*/
private int getAddressRangeIndex(Address address) {
int low = 0;
- int high = diffs.length-1;
-
+ int high = diffs.length - 1;
+
while (low <= high) {
- int mid = (low + high) >> 1;
- AddressRange range = ranges[mid];
- if (range.contains(address)) {
- return mid;
- }
- else if (address.compareTo(range.getMinAddress()) < 0) {
- high = mid - 1;
- }
- else {
- low = mid + 1;
- }
+ int mid = (low + high) >> 1;
+ AddressRange range = ranges[mid];
+ if (range.contains(address)) {
+ return mid;
+ }
+ else if (address.compareTo(range.getMinAddress()) < 0) {
+ high = mid - 1;
+ }
+ else {
+ low = mid + 1;
+ }
}
return -(low + 1); // not found.
}
@@ -187,7 +186,7 @@ public class MemoryDiff {
}
return rangeDiffs.toArray(new AddressRange[rangeDiffs.size()]);
}
-
+
/**
* Determines whether the two memory blocks are the same.
* @param block1 the first program's memory block
@@ -201,7 +200,7 @@ public class MemoryDiff {
else if (block2 == null) {
return false;
}
- if(!block1.getName().equals(block2.getName())) {
+ if (!block1.getName().equals(block2.getName())) {
return false;
}
if (!block1.getStart().equals(block2.getStart())) {
@@ -213,7 +212,7 @@ public class MemoryDiff {
if (block1.getSize() != block2.getSize()) {
return false;
}
- if (block1.getPermissions() != block2.getPermissions()) {
+ if (block1.getFlags() != block2.getFlags()) {
return false;
}
if (!block1.getType().equals(block2.getType())) {
@@ -233,8 +232,7 @@ public class MemoryDiff {
}
return true;
}
-
-
+
public boolean merge(int row, int mergeFields, TaskMonitor monitor) {
if ((mergeFields & MemoryBlockDiff.ALL) == 0) {
return false;
@@ -246,8 +244,8 @@ public class MemoryDiff {
MemoryBlock block1 = blockDiff.getBlock1();
MemoryBlock block2 = blockDiff.getBlock2();
AddressRange range = ranges[row];
- if (shouldMerge(mergeFields, MemoryBlockDiff.START_ADDRESS)
- && blockDiff.isStartAddressDifferent()) {
+ if (shouldMerge(mergeFields, MemoryBlockDiff.START_ADDRESS) &&
+ blockDiff.isStartAddressDifferent()) {
if (block1 == null) {
// Add all or part of a block.
Address start2 = block2.getStart();
@@ -271,7 +269,7 @@ public class MemoryDiff {
return true;
}
catch (Exception e) {
- Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
+ Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
}
return false;
}
@@ -295,64 +293,63 @@ public class MemoryDiff {
memory1.removeBlock(blockToRemove, monitor);
}
return true;
- } catch (LockException e) {
- Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
- } catch (NotFoundException e) {
- Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
- } catch (AddressOutOfBoundsException e) {
- Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
- } catch (MemoryBlockException e) {
+ }
+ catch (LockException e) {
+ Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
+ }
+ catch (NotFoundException e) {
+ Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
+ }
+ catch (AddressOutOfBoundsException e) {
+ Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
+ }
+ catch (MemoryBlockException e) {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
}
return false;
}
}
- if (shouldMerge(mergeFields, MemoryBlockDiff.END_ADDRESS)
- && blockDiff.isEndAddressDifferent()) {
+ if (shouldMerge(mergeFields, MemoryBlockDiff.END_ADDRESS) &&
+ blockDiff.isEndAddressDifferent()) {
// TODO
}
- if (shouldMerge(mergeFields, MemoryBlockDiff.SIZE)
- && blockDiff.isSizeDifferent()) {
+ if (shouldMerge(mergeFields, MemoryBlockDiff.SIZE) && blockDiff.isSizeDifferent()) {
// TODO
}
- if (shouldMerge(mergeFields, MemoryBlockDiff.TYPE)
- && blockDiff.isTypeDifferent()) {
+ if (shouldMerge(mergeFields, MemoryBlockDiff.TYPE) && blockDiff.isTypeDifferent()) {
// TODO
}
- if (shouldMerge(mergeFields, MemoryBlockDiff.INIT)
- && blockDiff.isInitDifferent()) {
+ if (shouldMerge(mergeFields, MemoryBlockDiff.INIT) && blockDiff.isInitDifferent()) {
// TODO
}
- if (shouldMerge(mergeFields, MemoryBlockDiff.NAME)
- && blockDiff.isNameDifferent()) {
+ if (shouldMerge(mergeFields, MemoryBlockDiff.NAME) && blockDiff.isNameDifferent()) {
try {
block1.setName(block2.getName());
- } catch (LockException e) {
- Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
+ }
+ catch (LockException e) {
+ Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
}
}
- if (shouldMerge(mergeFields, MemoryBlockDiff.READ)
- && blockDiff.isReadDifferent()) {
+ if (shouldMerge(mergeFields, MemoryBlockDiff.READ) && blockDiff.isReadDifferent()) {
block1.setRead(block2.isRead());
}
- if (shouldMerge(mergeFields, MemoryBlockDiff.WRITE)
- && blockDiff.isWriteDifferent()) {
+ if (shouldMerge(mergeFields, MemoryBlockDiff.WRITE) && blockDiff.isWriteDifferent()) {
block1.setWrite(block2.isWrite());
}
- if (shouldMerge(mergeFields, MemoryBlockDiff.EXECUTE)
- && blockDiff.isExecDifferent()) {
+ if (shouldMerge(mergeFields, MemoryBlockDiff.EXECUTE) && blockDiff.isExecDifferent()) {
block1.setExecute(block2.isExecute());
}
- if (shouldMerge(mergeFields, MemoryBlockDiff.VOLATILE)
- && blockDiff.isVolatileDifferent()) {
+ if (shouldMerge(mergeFields, MemoryBlockDiff.VOLATILE) && blockDiff.isVolatileDifferent()) {
block1.setVolatile(block2.isVolatile());
}
- if (shouldMerge(mergeFields, MemoryBlockDiff.SOURCE)
- && blockDiff.isSourceDifferent()) {
+ if (shouldMerge(mergeFields, MemoryBlockDiff.ARTIFICIAL) &&
+ blockDiff.isArtificialDifferent()) {
+ block1.setArtificial(block2.isArtificial());
+ }
+ if (shouldMerge(mergeFields, MemoryBlockDiff.SOURCE) && blockDiff.isSourceDifferent()) {
block1.setSourceName(block2.getSourceName());
}
- if (shouldMerge(mergeFields, MemoryBlockDiff.COMMENT)
- && blockDiff.isCommentDifferent()) {
+ if (shouldMerge(mergeFields, MemoryBlockDiff.COMMENT) && blockDiff.isCommentDifferent()) {
block1.setComment(block2.getComment());
}
return true;
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/util/table/field/MemoryTypeProgramLocationBasedTableColumn.java b/Ghidra/Features/Base/src/main/java/ghidra/util/table/field/MemoryTypeProgramLocationBasedTableColumn.java
index 1aa42f8873..df76dc0fea 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/util/table/field/MemoryTypeProgramLocationBasedTableColumn.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/util/table/field/MemoryTypeProgramLocationBasedTableColumn.java
@@ -111,6 +111,7 @@ public class MemoryTypeProgramLocationBasedTableColumn
updateForWrite(block, buffy, tooltipBuffy);
updateForExecute(block, buffy, tooltipBuffy);
updateForVolatile(block, buffy, tooltipBuffy);
+ updateForArtificial(block, buffy, tooltipBuffy);
}
private void updateForVolatile(MemoryBlock block, StringBuilder buffy,
@@ -128,6 +129,21 @@ public class MemoryTypeProgramLocationBasedTableColumn
tooltipBuffy.append(HTMLUtilities.spaces(2)).append("Volatile
");
}
+ private void updateForArtificial(MemoryBlock block, StringBuilder buffy,
+ StringBuilder tooltipBuffy) {
+
+ if (block.isArtificial()) {
+ buffy.append("A");
+ tooltipBuffy.append("");
+ }
+ else {
+ buffy.append(HTMLUtilities.colorString(disabledColor, "A"));
+ tooltipBuffy.append("");
+ }
+
+ tooltipBuffy.append(HTMLUtilities.spaces(2)).append("Artificial
");
+ }
+
private void updateForExecute(MemoryBlock block, StringBuilder buffy,
StringBuilder tooltipBuffy) {
@@ -186,7 +202,7 @@ public class MemoryTypeProgramLocationBasedTableColumn
private class MemoryTypeComparator implements Comparator {
@Override
public int compare(MemoryBlock o1, MemoryBlock o2) {
- return o1.getPermissions() - o2.getPermissions();
+ return o1.getFlags() - o2.getFlags();
}
}
}
diff --git a/Ghidra/Features/Base/src/main/resources/PROGRAM.DTD b/Ghidra/Features/Base/src/main/resources/PROGRAM.DTD
index d7410bd633..c0e72decdf 100644
--- a/Ghidra/Features/Base/src/main/resources/PROGRAM.DTD
+++ b/Ghidra/Features/Base/src/main/resources/PROGRAM.DTD
@@ -66,6 +66,7 @@
+
diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/memory/MemoryMergeManagerTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/memory/MemoryMergeManagerTest.java
index c0ba76f89b..42546aef63 100644
--- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/memory/MemoryMergeManagerTest.java
+++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/memory/MemoryMergeManagerTest.java
@@ -219,7 +219,7 @@ public class MemoryMergeManagerTest extends AbstractMergeTest {
blocks[4].setRead(false);
blocks[4].setWrite(false);
blocks[4].setExecute(false);
-
+
try {
blocks[4].setName("special-debug");
}
@@ -269,6 +269,7 @@ public class MemoryMergeManagerTest extends AbstractMergeTest {
assertTrue(!blocks[4].isWrite());
assertTrue(!blocks[4].isExecute());
assertTrue(!blocks[4].isVolatile());
+ assertTrue(!blocks[4].isArtificial());
}
@Test
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 9c1a61dd28..7bbaa46fff 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
@@ -239,6 +239,12 @@ public class MemoryManagerTest extends AbstractGhidraHeadedIntegrationTest {
assertEquals("Hello", block1.getComment());
assertEquals(block1, mem.getBlock(addr(5)));
+ block1.setArtificial(false);
+ assertTrue(!block1.isArtificial());
+
+ block1.setArtificial(true);
+ assertTrue(block1.isArtificial());
+
block1.setVolatile(false);
assertTrue(!block1.isVolatile());
@@ -473,6 +479,7 @@ public class MemoryManagerTest extends AbstractGhidraHeadedIntegrationTest {
assertNotNull(newBlock);
assertEquals(block.getName() + ".copy", newBlock.getName());
assertEquals(addr(500), newBlock.getStart());
+ assertEquals(block.isArtificial(), newBlock.isArtificial());
assertEquals(block.isVolatile(), newBlock.isVolatile());
assertEquals(block.isExecute(), newBlock.isExecute());
assertEquals(block.isRead(), newBlock.isRead());
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 787e8be331..ddccdb0656 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
@@ -32,7 +32,7 @@ class MyTestMemoryBlock implements MemoryBlock {
}
@Override
- public int getPermissions() {
+ public int getFlags() {
throw new UnsupportedOperationException();
}
@@ -136,6 +136,16 @@ class MyTestMemoryBlock implements MemoryBlock {
throw new UnsupportedOperationException();
}
+ @Override
+ public boolean isArtificial() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setArtificial(boolean a) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public String getSourceName() {
throw new UnsupportedOperationException();
diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/export/mm/ExtMemoryMap.java b/Ghidra/Features/Sarif/src/main/java/sarif/export/mm/ExtMemoryMap.java
index 0abb9dcc4a..99fad1e725 100644
--- a/Ghidra/Features/Sarif/src/main/java/sarif/export/mm/ExtMemoryMap.java
+++ b/Ghidra/Features/Sarif/src/main/java/sarif/export/mm/ExtMemoryMap.java
@@ -30,10 +30,12 @@ public class ExtMemoryMap implements IsfObject {
String kind;
String comment;
boolean isVolatile;
+ boolean isArtificial;
String type;
String location;
- public ExtMemoryMap(AddressRange range, MemoryBlock block, MemoryMapBytesFile bf, boolean write) throws IOException {
+ public ExtMemoryMap(AddressRange range, MemoryBlock block, MemoryMapBytesFile bf, boolean write)
+ throws IOException {
String permissions = "";
if (block.isRead()) {
@@ -54,12 +56,17 @@ public class ExtMemoryMap implements IsfObject {
if (block.isVolatile()) {
isVolatile = true;
}
+ if (block.isArtificial()) {
+ isArtificial = true;
+ }
type = block.getType().name();
- if (block.getType() == MemoryBlockType.BIT_MAPPED || block.getType() == MemoryBlockType.BYTE_MAPPED) {
+ if (block.getType() == MemoryBlockType.BIT_MAPPED ||
+ block.getType() == MemoryBlockType.BYTE_MAPPED) {
// bit mapped blocks can only have one sub-block
MemoryBlockSourceInfo info = block.getSourceInfos().get(0);
location = info.getMappedRange().get().getMinAddress().toString();
- } else if (block.isInitialized() && write) {
+ }
+ else if (block.isInitialized() && write) {
location = bf.getFileName() + ":" + bf.getOffset();
bf.writeBytes(range);
}
diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/managers/MemoryMapSarifMgr.java b/Ghidra/Features/Sarif/src/main/java/sarif/managers/MemoryMapSarifMgr.java
index 3d136840d9..6d2368cfe4 100644
--- a/Ghidra/Features/Sarif/src/main/java/sarif/managers/MemoryMapSarifMgr.java
+++ b/Ghidra/Features/Sarif/src/main/java/sarif/managers/MemoryMapSarifMgr.java
@@ -68,26 +68,27 @@ public class MemoryMapSarifMgr extends SarifMgr {
////////////////////////////
@Override
- public boolean read(Map result, SarifProgramOptions options, TaskMonitor monitor)
- throws CancelledException {
+ public boolean read(Map result, SarifProgramOptions options,
+ TaskMonitor monitor) throws CancelledException {
try {
processMemoryBlock(result, programMgr.getDirectory(), program, monitor);
return true;
- } catch (FileNotFoundException | AddressOverflowException e) {
+ }
+ catch (FileNotFoundException | AddressOverflowException e) {
log.appendException(e);
}
return false;
}
- private void processMemoryBlock(Map result, String directory, Program program, TaskMonitor monitor)
- throws FileNotFoundException, AddressOverflowException {
+ private void processMemoryBlock(Map result, String directory, Program program,
+ TaskMonitor monitor) throws FileNotFoundException, AddressOverflowException {
String name = (String) result.get("name");
AddressSet set = SarifUtils.getLocations(result, program, null);
Address blockAddress = set.getMinAddress();
if (set.getNumAddressRanges() != 1) {
- throw new RuntimeException(
- "Unexpected number of ranges for block @ " + blockAddress + ": " + set.getNumAddressRanges());
+ throw new RuntimeException("Unexpected number of ranges for block @ " + blockAddress +
+ ": " + set.getNumAddressRanges());
}
int length = (int) set.getMaxAddress().subtract(blockAddress) + 1;
@@ -100,6 +101,7 @@ public class MemoryMapSarifMgr extends SarifMgr {
boolean x = permissions.indexOf("x") >= 0;
boolean isVolatile = (boolean) result.get("isVolatile");
+ boolean isArtificial = (boolean) result.get("isArtificial");
String comment = (String) result.get("comment");
String type = (String) result.get("type");
@@ -110,33 +112,41 @@ public class MemoryMapSarifMgr extends SarifMgr {
MemoryBlock block = null;
if (type.equals("DEFAULT")) {
if (loc == null) {
- block = MemoryBlockUtils.createUninitializedBlock(program, false, name, blockAddress, length,
- comment, null, r, w, x, log);
- } else {
+ block = MemoryBlockUtils.createUninitializedBlock(program, false, name,
+ blockAddress, length, comment, null, r, w, x, log);
+ }
+ else {
String[] split = loc.split(":");
String fileName = split[0];
int fileOffset = Integer.parseInt(split[1]);
byte[] bytes = setData(directory, fileName, fileOffset, length, log);
- block = MemoryBlockUtils.createInitializedBlock(program, false, name, blockAddress,
- new ByteArrayInputStream(bytes), bytes.length, comment, null, r, w, x, log, monitor);
+ block = MemoryBlockUtils.createInitializedBlock(program, false, name,
+ blockAddress, new ByteArrayInputStream(bytes), bytes.length, comment, null,
+ r, w, x, log, monitor);
}
- } else if (type.equals("BIT_MAPPED")) {
+ }
+ else if (type.equals("BIT_MAPPED")) {
Address sourceAddr = factory.getAddress(loc);
- block = MemoryBlockUtils.createBitMappedBlock(program, name, blockAddress, sourceAddr, length, comment,
- comment, r, w, x, false, log);
- } else if (type.equals("BYTE_MAPPED")) {
+ block = MemoryBlockUtils.createBitMappedBlock(program, name, blockAddress,
+ sourceAddr, length, comment, comment, r, w, x, false, log);
+ }
+ else if (type.equals("BYTE_MAPPED")) {
Address sourceAddr = factory.getAddress(loc);
- block = MemoryBlockUtils.createByteMappedBlock(program, name, blockAddress, sourceAddr, length, comment,
- comment, r, w, x, false, log);
- } else {
+ block = MemoryBlockUtils.createByteMappedBlock(program, name, blockAddress,
+ sourceAddr, length, comment, comment, r, w, x, false, log);
+ }
+ else {
throw new RuntimeException("Unexpected type value - " + type);
}
if (block != null) {
block.setVolatile(isVolatile);
+ block.setArtificial(isArtificial);
}
- } catch (FileNotFoundException e) {
+ }
+ catch (FileNotFoundException e) {
throw e;
- } catch (Exception e) {
+ }
+ catch (Exception e) {
log.appendException(e);
}
}
@@ -160,7 +170,8 @@ public class MemoryMapSarifMgr extends SarifMgr {
}
pos += readLen;
}
- } catch (IndexOutOfBoundsException e) {
+ }
+ catch (IndexOutOfBoundsException e) {
log.appendMsg("Read exceeded array length " + length);
}
return bytes;
@@ -170,8 +181,8 @@ public class MemoryMapSarifMgr extends SarifMgr {
// SARIF WRITE CURRENT DTD //
/////////////////////////////
- void write(JsonArray results, AddressSetView addrs, TaskMonitor monitor, boolean isWriteContents, String filePath)
- throws IOException, CancelledException {
+ void write(JsonArray results, AddressSetView addrs, TaskMonitor monitor,
+ boolean isWriteContents, String filePath) throws IOException, CancelledException {
monitor.setMessage("Writing MEMORY MAP ...");
List> request = new ArrayList<>();
@@ -179,7 +190,8 @@ public class MemoryMapSarifMgr extends SarifMgr {
while (iter.hasNext()) {
monitor.checkCancelled();
AddressRange ranges = iter.next();
- RangeBlock rb = new RangeBlock(program.getAddressFactory(), program.getMemory(), ranges);
+ RangeBlock rb =
+ new RangeBlock(program.getAddressFactory(), program.getMemory(), ranges);
for (int i = 0; i < rb.getRanges().length; ++i) {
AddressRange range = rb.getRanges()[i];
MemoryBlock block = rb.getBlocks()[i];
@@ -190,16 +202,19 @@ public class MemoryMapSarifMgr extends SarifMgr {
try {
bf = isWriteContents ? new MemoryMapBytesFile(program, filePath) : null;
writeAsSARIF(request, bf, isWriteContents, results);
- } finally {
+ }
+ finally {
if (isWriteContents) {
bf.close();
}
}
}
- public static void writeAsSARIF(List> request, MemoryMapBytesFile bytes,
- boolean isWriteContents, JsonArray results) throws IOException {
- SarifMemoryMapWriter writer = new SarifMemoryMapWriter(request, null, bytes, isWriteContents);
+ public static void writeAsSARIF(List> request,
+ MemoryMapBytesFile bytes, boolean isWriteContents, JsonArray results)
+ throws IOException {
+ SarifMemoryMapWriter writer =
+ new SarifMemoryMapWriter(request, null, bytes, isWriteContents);
new TaskLauncher(new SarifWriterTask(SUBKEY, writer, results), null);
}
diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/validator/MemoryBlocksValidator.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/validator/MemoryBlocksValidator.java
index 7b760d9d61..ed69a3200c 100644
--- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/validator/MemoryBlocksValidator.java
+++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/validator/MemoryBlocksValidator.java
@@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
- * REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -69,13 +68,13 @@ public class MemoryBlocksValidator extends VTPreconditionValidator {
sourceProgram.getMemory().getBlock(destBlocks[i].getName());
if (matchingABlock != null) {
numMatchingNames++;
- int sourcePerm = matchingABlock.getPermissions();
- if (sourcePerm == destBlocks[i].getPermissions()) {
+ int sourceFlags = matchingABlock.getFlags();
+ if (sourceFlags == destBlocks[i].getFlags()) {
numMatches++;
}
else {
warnings.append("Block " + destProgName + ":" + blockName +
- " doesn't match permissions of " + sourceProgName + ":" + blockName + "\n");
+ " has different flags than " + sourceProgName + ":" + blockName + "\n");
status = ConditionStatus.Warning;
}
}
@@ -102,10 +101,12 @@ public class MemoryBlocksValidator extends VTPreconditionValidator {
}
}
if (numMatchingNames == numBlocksNeededForPerfectMatch) {
- warnings.append("\nSUMMARY: Number and names of blocks match but not all permissions match.");
+ warnings.append(
+ "\nSUMMARY: Number and names of blocks match but not all permissions match.");
}
else {
- warnings.append("\nSUMMARY: Number, names, and permissions of blocks do not all match");
+ warnings.append(
+ "\nSUMMARY: Number, names, and permissions of blocks do not all match");
}
}
return new ConditionResult(status, warnings.toString());
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/generic/MemoryBlockDefinition.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/generic/MemoryBlockDefinition.java
index 408335cbef..f7de363fb5 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/generic/MemoryBlockDefinition.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/generic/MemoryBlockDefinition.java
@@ -47,7 +47,7 @@ public class MemoryBlockDefinition {
private boolean readPermission = true;
private boolean writePermission = true;
private boolean executePermission = false;
- private boolean volatilePermission = false;
+ private boolean isVolatile = false;
/**
* Construct MemoryBlockDefinition
using a text-based specified.
@@ -107,7 +107,7 @@ public class MemoryBlockDefinition {
readPermission = mode.indexOf('r') >= 0;
writePermission = mode.indexOf('w') >= 0;
executePermission = mode.indexOf('x') >= 0;
- volatilePermission = mode.indexOf('v') >= 0;
+ isVolatile = mode.indexOf('v') >= 0;
}
try {
length = XmlUtilities.parseInt(lengthString);
@@ -186,7 +186,7 @@ public class MemoryBlockDefinition {
block.setRead(readPermission);
block.setWrite(writePermission);
block.setExecute(executePermission);
- block.setVolatile(volatilePermission);
+ block.setVolatile(isVolatile);
}
@Override
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 d3558209cc..722c4faa50 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
@@ -117,8 +117,8 @@ public class MemoryBlockDB implements MemoryBlock {
}
@Override
- public int getPermissions() {
- return record.getByteValue(MemoryMapDBAdapter.PERMISSIONS_COL);
+ public int getFlags() {
+ return record.getByteValue(MemoryMapDBAdapter.FLAGS_COL);
}
@Override
@@ -224,7 +224,7 @@ public class MemoryBlockDB implements MemoryBlock {
@Override
public boolean isRead() {
- return (record.getByteValue(MemoryMapDBAdapter.PERMISSIONS_COL) & READ) != 0;
+ return (record.getByteValue(MemoryMapDBAdapter.FLAGS_COL) & READ) != 0;
}
@Override
@@ -232,8 +232,9 @@ public class MemoryBlockDB implements MemoryBlock {
memMap.lock.acquire();
try {
checkValid();
- setPermissionBit(READ, r);
- memMap.fireBlockChanged(this);
+ if (setFlagBit(READ, r)) {
+ memMap.fireBlockChanged(this);
+ }
}
finally {
memMap.lock.release();
@@ -242,7 +243,7 @@ public class MemoryBlockDB implements MemoryBlock {
@Override
public boolean isWrite() {
- return (record.getByteValue(MemoryMapDBAdapter.PERMISSIONS_COL) & WRITE) != 0;
+ return (record.getByteValue(MemoryMapDBAdapter.FLAGS_COL) & WRITE) != 0;
}
@Override
@@ -250,8 +251,9 @@ public class MemoryBlockDB implements MemoryBlock {
memMap.lock.acquire();
try {
checkValid();
- setPermissionBit(WRITE, w);
- memMap.fireBlockChanged(this);
+ if (setFlagBit(WRITE, w)) {
+ memMap.fireBlockChanged(this);
+ }
}
finally {
memMap.lock.release();
@@ -260,7 +262,7 @@ public class MemoryBlockDB implements MemoryBlock {
@Override
public boolean isExecute() {
- return (record.getByteValue(MemoryMapDBAdapter.PERMISSIONS_COL) & EXECUTE) != 0;
+ return (record.getByteValue(MemoryMapDBAdapter.FLAGS_COL) & EXECUTE) != 0;
}
@Override
@@ -268,9 +270,10 @@ public class MemoryBlockDB implements MemoryBlock {
memMap.lock.acquire();
try {
checkValid();
- setPermissionBit(EXECUTE, x);
- memMap.blockExecuteChanged(this);
- memMap.fireBlockChanged(this);
+ if (setFlagBit(EXECUTE, x)) {
+ memMap.blockExecuteChanged(this);
+ memMap.fireBlockChanged(this);
+ }
}
finally {
memMap.lock.release();
@@ -282,11 +285,13 @@ public class MemoryBlockDB implements MemoryBlock {
memMap.lock.acquire();
try {
checkValid();
- setPermissionBit(READ, read);
- setPermissionBit(WRITE, write);
- setPermissionBit(EXECUTE, execute);
- memMap.blockExecuteChanged(this);
- memMap.fireBlockChanged(this);
+ boolean changed = setFlagBit(READ, read);
+ changed |= setFlagBit(WRITE, write);
+ changed |= setFlagBit(EXECUTE, execute);
+ if (changed) {
+ memMap.blockExecuteChanged(this);
+ memMap.fireBlockChanged(this);
+ }
}
finally {
memMap.lock.release();
@@ -295,7 +300,7 @@ public class MemoryBlockDB implements MemoryBlock {
@Override
public boolean isVolatile() {
- return (record.getByteValue(MemoryMapDBAdapter.PERMISSIONS_COL) & VOLATILE) != 0;
+ return (record.getByteValue(MemoryMapDBAdapter.FLAGS_COL) & VOLATILE) != 0;
}
@Override
@@ -303,8 +308,28 @@ public class MemoryBlockDB implements MemoryBlock {
memMap.lock.acquire();
try {
checkValid();
- setPermissionBit(VOLATILE, v);
- memMap.fireBlockChanged(this);
+ if (setFlagBit(VOLATILE, v)) {
+ memMap.fireBlockChanged(this);
+ }
+ }
+ finally {
+ memMap.lock.release();
+ }
+ }
+
+ @Override
+ public boolean isArtificial() {
+ return (record.getByteValue(MemoryMapDBAdapter.FLAGS_COL) & ARTIFICIAL) != 0;
+ }
+
+ @Override
+ public void setArtificial(boolean a) {
+ memMap.lock.acquire();
+ try {
+ checkValid();
+ if (setFlagBit(ARTIFICIAL, a)) {
+ memMap.fireBlockChanged(this);
+ }
}
finally {
memMap.lock.release();
@@ -430,21 +455,28 @@ public class MemoryBlockDB implements MemoryBlock {
}
}
- private void setPermissionBit(int permBitMask, boolean enable) {
- byte p = record.getByteValue(MemoryMapDBAdapter.PERMISSIONS_COL);
+ private boolean setFlagBit(int flagBitMask, boolean enable) {
+ byte p = record.getByteValue(MemoryMapDBAdapter.FLAGS_COL);
if (enable) {
- p |= permBitMask;
+ if ((p & flagBitMask) == flagBitMask) {
+ return false; // no change
+ }
+ p |= flagBitMask;
}
else {
- p &= ~permBitMask;
+ if ((p & flagBitMask) == 0) {
+ return false; // no change
+ }
+ p &= ~flagBitMask;
}
- record.setByteValue(MemoryMapDBAdapter.PERMISSIONS_COL, p);
+ record.setByteValue(MemoryMapDBAdapter.FLAGS_COL, p);
try {
adapter.updateBlockRecord(record);
}
catch (IOException e) {
memMap.dbError(e);
}
+ return true;
}
@Override
@@ -634,8 +666,7 @@ public class MemoryBlockDB implements MemoryBlock {
splitBlocks.addAll(subList);
subList.clear();
}
- return adapter.createBlock(getName() + ".split", addr, newLength, getPermissions(),
- splitBlocks);
+ return adapter.createBlock(getName() + ".split", addr, newLength, getFlags(), splitBlocks);
}
private int getIndexOfSubBlockToSplit(long offset) {
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 eebec0a423..6003b44fc9 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
@@ -901,7 +901,7 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
mappedAddr = info.getMappedRange().get().getMinAddress();
}
MemoryBlockDB newBlock = adapter.createBlock(block.getType(), name, start, length,
- mappedAddr, block.isInitialized(), block.getPermissions(), mappingScheme);
+ mappedAddr, block.isInitialized(), block.getFlags(), mappingScheme);
allAddrSet.add(newBlock.getStart(), newBlock.getEnd());
initializeBlocks();
fireBlockAdded(newBlock);
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 adaeabc237..9d46bfbcde 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
@@ -35,7 +35,7 @@ abstract class MemoryMapDBAdapter {
static final int NAME_COL = MemoryMapDBAdapterV3.V3_NAME_COL;
static final int COMMENTS_COL = MemoryMapDBAdapterV3.V3_COMMENTS_COL;
static final int SOURCE_COL = MemoryMapDBAdapterV3.V3_SOURCE_COL;
- static final int PERMISSIONS_COL = MemoryMapDBAdapterV3.V3_PERMISSIONS_COL;
+ static final int FLAGS_COL = MemoryMapDBAdapterV3.V3_FLAGS_COL;
static final int START_ADDR_COL = MemoryMapDBAdapterV3.V3_START_ADDR_COL;
static final int LENGTH_COL = MemoryMapDBAdapterV3.V3_LENGTH_COL;
static final int SEGMENT_COL = MemoryMapDBAdapterV3.V3_SEGMENT_COL;
@@ -130,7 +130,7 @@ abstract class MemoryMapDBAdapter {
if (block.isInitialized()) {
DBBuffer buf = block.getBuffer();
newBlock = newAdapter.createInitializedBlock(block.getName(), block.getStart(),
- buf, block.getPermissions());
+ buf, block.getFlags());
}
else {
Address mappedAddress = null;
@@ -141,7 +141,7 @@ abstract class MemoryMapDBAdapter {
}
newBlock =
newAdapter.createBlock(block.getType(), block.getName(), block.getStart(),
- block.getSize(), mappedAddress, false, block.getPermissions(), 0);
+ block.getSize(), mappedAddress, false, block.getFlags(), 0);
}
newBlock.setComment(block.getComment());
newBlock.setSourceName(block.getSourceName());
@@ -185,26 +185,26 @@ abstract class MemoryMapDBAdapter {
* @param startAddr the start address of the block.
* @param is data source or null for zero initialization
* @param length size of block
- * @param permissions the new block permissions
+ * @param flags the new block flags
* @return new memory block
- * @throws IOException
+ * @throws IOException if a database IO error occurs.
* @throws AddressOverflowException if block length is too large for the underlying space
*/
abstract MemoryBlockDB createInitializedBlock(String name, Address startAddr, InputStream is,
- long length, int permissions) throws AddressOverflowException, IOException;
+ long length, int flags) throws AddressOverflowException, IOException;
/**
* Creates a new initialized block object
* @param name the name of the block
* @param startAddr the start address of the block.
* @param buf the DBBuffer used to hold the bytes for the block.
- * @param permissions the new block permissions
+ * @param flags the new block flags
* @return new memory block
* @throws IOException if a database IO error occurs.
* @throws AddressOverflowException if block length is too large for the underlying space
*/
abstract MemoryBlockDB createInitializedBlock(String name, Address startAddr, DBBuffer buf,
- int permissions) throws AddressOverflowException, IOException;
+ int flags) throws AddressOverflowException, IOException;
/**
* Creates a new memory block that doesn't have associated bytes.
@@ -216,14 +216,14 @@ abstract class MemoryMapDBAdapter {
* the block. (used for bit/byte-mapped blocks only)
* @param initializeBytes if true, creates a database buffer for storing the
* bytes in the block (applies to initialized default blocks only)
- * @param permissions the new block permissions
+ * @param flags the new block flags
* @param encodedMappingScheme byte mapping scheme (used by byte-mapped blocks only)
* @return new memory block
* @throws IOException if a database IO error occurs.
* @throws AddressOverflowException if block length is too large for the underlying space
*/
abstract MemoryBlockDB createBlock(MemoryBlockType blockType, String name, Address startAddr,
- long length, Address mappedAddress, boolean initializeBytes, int permissions,
+ long length, Address mappedAddress, boolean initializeBytes, int flags,
int encodedMappingScheme) throws AddressOverflowException, IOException;
/**
@@ -289,13 +289,13 @@ abstract class MemoryMapDBAdapter {
* @param name the name of the block
* @param startAddress the start address of the block
* @param length the length of the block
- * @param permissions the permissions for the block
+ * @param flags the flags for the block
* @param splitBlocks the list of subBlock objects that make up this block
* @return the new MemoryBlock
* @throws IOException if a database error occurs
*/
protected abstract MemoryBlockDB createBlock(String name, Address startAddress, long length,
- int permissions, List splitBlocks) throws IOException;
+ int flags, List splitBlocks) throws IOException;
/**
* Creates a new memory block using a FileBytes
@@ -304,12 +304,12 @@ abstract class MemoryMapDBAdapter {
* @param length the length of the block
* @param fileBytes the {@link FileBytes} object that provides the bytes for this block
* @param offset the offset into the {@link FileBytes} object
- * @param permissions the permissions for the block
+ * @param flags the flags for the block
* @return the new MemoryBlock
* @throws IOException if a database error occurs
* @throws AddressOverflowException if block length is too large for the underlying space
*/
protected abstract MemoryBlockDB createFileBytesBlock(String name, Address startAddress,
- long length, FileBytes fileBytes, long offset, int permissions)
+ long length, FileBytes fileBytes, long offset, int flags)
throws IOException, AddressOverflowException;
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapterV0.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapterV0.java
index a34a7133f6..e7864cc245 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapterV0.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapterV0.java
@@ -106,15 +106,15 @@ class MemoryMapDBAdapterV0 extends MemoryMapDBAdapter {
RecordIterator it = table.iterator();
while (it.hasNext()) {
DBRecord rec = it.next();
- int permissions = 0;
+ int flags = 0;
if (rec.getBooleanValue(V0_IS_READ_COL)) {
- permissions |= MemoryBlock.READ;
+ flags |= MemoryBlock.READ;
}
if (rec.getBooleanValue(V0_IS_WRITE_COL)) {
- permissions |= MemoryBlock.WRITE;
+ flags |= MemoryBlock.WRITE;
}
if (rec.getBooleanValue(V0_IS_EXECUTE_COL)) {
- permissions |= MemoryBlock.EXECUTE;
+ flags |= MemoryBlock.EXECUTE;
}
Address start = addrFactory.oldGetAddressFromLong(rec.getLongValue(V0_START_ADDR_COL));
long startAddr = addrMap.getKey(start, false);
@@ -131,7 +131,7 @@ class MemoryMapDBAdapterV0 extends MemoryMapDBAdapter {
blockRecord.setString(NAME_COL, rec.getString(V0_NAME_COL));
blockRecord.setString(COMMENTS_COL, rec.getString(V0_COMMENTS_COL));
blockRecord.setString(SOURCE_COL, rec.getString(V0_SOURCE_NAME_COL));
- blockRecord.setByteValue(PERMISSIONS_COL, (byte) permissions);
+ blockRecord.setByteValue(FLAGS_COL, (byte) flags);
blockRecord.setLongValue(START_ADDR_COL, startAddr);
blockRecord.setLongValue(LENGTH_COL, length);
blockRecord.setIntValue(SEGMENT_COL, segment);
@@ -195,13 +195,13 @@ class MemoryMapDBAdapterV0 extends MemoryMapDBAdapter {
@Override
MemoryBlockDB createInitializedBlock(String name, Address startAddr, InputStream is,
- long length, int permissions) throws IOException {
+ long length, int flags) throws IOException {
throw new UnsupportedOperationException();
}
@Override
- MemoryBlockDB createInitializedBlock(String name, Address startAddr, DBBuffer buf,
- int permissions) throws IOException {
+ MemoryBlockDB createInitializedBlock(String name, Address startAddr, DBBuffer buf, int flags)
+ throws IOException {
throw new UnsupportedOperationException();
}
@@ -231,8 +231,7 @@ class MemoryMapDBAdapterV0 extends MemoryMapDBAdapter {
@Override
MemoryBlockDB createBlock(MemoryBlockType blockType, String name, Address startAddr,
- long length, Address overlayAddr, boolean initializeBytes, int permissions,
- int mappingScheme)
+ long length, Address overlayAddr, boolean initializeBytes, int flags, int mappingScheme)
throws IOException {
throw new UnsupportedOperationException();
}
@@ -267,14 +266,14 @@ class MemoryMapDBAdapterV0 extends MemoryMapDBAdapter {
}
@Override
- protected MemoryBlockDB createBlock(String name, Address addr, long length, int permissions,
+ protected MemoryBlockDB createBlock(String name, Address addr, long length, int flags,
List splitBlocks) {
throw new UnsupportedOperationException();
}
@Override
protected MemoryBlockDB createFileBytesBlock(String name, Address startAddress, long length,
- FileBytes fileBytes, long offset, int permissions)
+ FileBytes fileBytes, long offset, int flags)
throws IOException, AddressOverflowException {
throw new UnsupportedOperationException();
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapterV1.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapterV1.java
index 29e9bd54e9..8e4060a8cc 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapterV1.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapterV1.java
@@ -45,9 +45,6 @@ class MemoryMapDBAdapterV1 extends MemoryMapDBAdapterV0 {
// "Source Block ID","Segment"});
//
- /**
- * @param handle
- */
MemoryMapDBAdapterV1(DBHandle handle, MemoryMapDB memMap) throws VersionException, IOException {
super(handle, memMap, VERSION);
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapterV2.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapterV2.java
index 00ce73cdab..35b751a29f 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapterV2.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapterV2.java
@@ -63,7 +63,6 @@ class MemoryMapDBAdapterV2 extends MemoryMapDBAdapter {
// new String[] { "Name", "Comments", "Source Name", "Permissions", "Start Address",
// "Block Type", "Overlay Address", "Length", "Chain Buffer ID", "Segment" });
-
protected MemoryMapDBAdapterV2(DBHandle handle, MemoryMapDB memMap)
throws VersionException, IOException {
this.handle = handle;
@@ -86,7 +85,7 @@ class MemoryMapDBAdapterV2 extends MemoryMapDBAdapter {
RecordIterator it = table.iterator();
while (it.hasNext()) {
DBRecord rec = it.next();
- int permissions = rec.getByteValue(V2_PERMISSIONS_COL);
+ int flags = rec.getByteValue(V2_PERMISSIONS_COL);
long startAddr = rec.getLongValue(V2_START_ADDR_COL);
long length = rec.getLongValue(V2_LENGTH_COL);
@@ -99,7 +98,7 @@ class MemoryMapDBAdapterV2 extends MemoryMapDBAdapter {
blockRecord.setString(NAME_COL, rec.getString(V2_NAME_COL));
blockRecord.setString(COMMENTS_COL, rec.getString(V2_COMMENTS_COL));
blockRecord.setString(SOURCE_COL, rec.getString(V2_SOURCE_COL));
- blockRecord.setByteValue(PERMISSIONS_COL, (byte) permissions);
+ blockRecord.setByteValue(FLAGS_COL, (byte) flags);
blockRecord.setLongValue(START_ADDR_COL, startAddr);
blockRecord.setLongValue(LENGTH_COL, length);
blockRecord.setIntValue(SEGMENT_COL, segment);
@@ -149,22 +148,21 @@ class MemoryMapDBAdapterV2 extends MemoryMapDBAdapter {
}
@Override
- MemoryBlockDB createInitializedBlock(String name, Address startAddr, DBBuffer buf,
- int permissions) throws AddressOverflowException, IOException {
+ MemoryBlockDB createInitializedBlock(String name, Address startAddr, DBBuffer buf, int flags)
+ throws AddressOverflowException, IOException {
throw new UnsupportedOperationException();
}
@Override
MemoryBlockDB createInitializedBlock(String name, Address startAddr, InputStream is,
- long length, int permissions) throws AddressOverflowException, IOException {
+ long length, int flags) throws AddressOverflowException, IOException {
throw new UnsupportedOperationException();
}
@Override
MemoryBlockDB createBlock(MemoryBlockType blockType, String name, Address startAddr,
- long length, Address mappedAddress, boolean initializeBytes, int permissions,
- int mappingScheme)
- throws AddressOverflowException, IOException {
+ long length, Address mappedAddress, boolean initializeBytes, int flags,
+ int mappingScheme) throws AddressOverflowException, IOException {
throw new UnsupportedOperationException();
}
@@ -223,14 +221,14 @@ class MemoryMapDBAdapterV2 extends MemoryMapDBAdapter {
}
@Override
- protected MemoryBlockDB createBlock(String name, Address addr, long length, int permissions,
+ protected MemoryBlockDB createBlock(String name, Address addr, long length, int flags,
List splitBlocks) {
throw new UnsupportedOperationException();
}
@Override
protected MemoryBlockDB createFileBytesBlock(String name, Address startAddress, long length,
- FileBytes fileBytes, long offset, int permissions)
+ FileBytes fileBytes, long offset, int flags)
throws IOException, AddressOverflowException {
throw new UnsupportedOperationException();
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapterV3.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapterV3.java
index 7cacfc57d2..c20972a878 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapterV3.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapterV3.java
@@ -39,7 +39,7 @@ public class MemoryMapDBAdapterV3 extends MemoryMapDBAdapter {
static final int V3_NAME_COL = 0;
static final int V3_COMMENTS_COL = 1;
static final int V3_SOURCE_COL = 2;
- static final int V3_PERMISSIONS_COL = 3;
+ static final int V3_FLAGS_COL = 3;
static final int V3_START_ADDR_COL = 4;
static final int V3_LENGTH_COL = 5;
static final int V3_SEGMENT_COL = 6;
@@ -60,7 +60,7 @@ public class MemoryMapDBAdapterV3 extends MemoryMapDBAdapter {
static Schema V3_BLOCK_SCHEMA = new Schema(V3_VERSION, "Key",
new Field[] { StringField.INSTANCE, StringField.INSTANCE, StringField.INSTANCE,
ByteField.INSTANCE, LongField.INSTANCE, LongField.INSTANCE, IntField.INSTANCE },
- new String[] { "Name", "Comments", "Source Name", "Permissions", "Start Address", "Length",
+ new String[] { "Name", "Comments", "Source Name", "Flags", "Start Address", "Length",
"Segment" });
static Schema V3_SUB_BLOCK_SCHEMA = new Schema(V3_VERSION, "Key",
@@ -116,8 +116,8 @@ public class MemoryMapDBAdapterV3 extends MemoryMapDBAdapter {
void refreshMemory() throws IOException {
Map> subBlockMap = getSubBlockMap();
- Map blockMap = memoryBlocks.stream().collect(
- Collectors.toMap(MemoryBlockDB::getID, Function.identity()));
+ Map blockMap = memoryBlocks.stream()
+ .collect(Collectors.toMap(MemoryBlockDB::getID, Function.identity()));
List newBlocks = new ArrayList<>();
RecordIterator it = memBlockTable.iterator();
@@ -163,14 +163,14 @@ public class MemoryMapDBAdapterV3 extends MemoryMapDBAdapter {
@Override
MemoryBlockDB createInitializedBlock(String name, Address startAddr, InputStream is,
- long length, int permissions) throws AddressOverflowException, IOException {
+ long length, int flags) throws AddressOverflowException, IOException {
// TODO verify that it is necessary to pre-define all segments in the address map
updateAddressMapForAllAddresses(startAddr, length);
List subBlocks = new ArrayList<>();
try {
- DBRecord blockRecord = createMemoryBlockRecord(name, startAddr, length, permissions);
+ DBRecord blockRecord = createMemoryBlockRecord(name, startAddr, length, flags);
long key = blockRecord.getKey();
int numFullBlocks = (int) (length / maxSubBlockSize);
int lastSubBlockSize = (int) (length % maxSubBlockSize);
@@ -201,30 +201,30 @@ public class MemoryMapDBAdapterV3 extends MemoryMapDBAdapter {
@Override
MemoryBlockDB createBlock(MemoryBlockType blockType, String name, Address startAddr,
- long length, Address mappedAddress, boolean initializeBytes, int permissions,
+ long length, Address mappedAddress, boolean initializeBytes, int flags,
int encodedMappingScheme) throws AddressOverflowException, IOException {
if (blockType == MemoryBlockType.BIT_MAPPED) {
- return createBitMappedBlock(name, startAddr, length, mappedAddress, permissions);
+ return createBitMappedBlock(name, startAddr, length, mappedAddress, flags);
}
if (blockType == MemoryBlockType.BYTE_MAPPED) {
- return createByteMappedBlock(name, startAddr, length, mappedAddress, permissions,
+ return createByteMappedBlock(name, startAddr, length, mappedAddress, flags,
encodedMappingScheme);
}
// DEFAULT block type
if (initializeBytes) {
- return createInitializedBlock(name, startAddr, null, length, permissions);
+ return createInitializedBlock(name, startAddr, null, length, flags);
}
- return createUninitializedBlock(name, startAddr, length, permissions);
+ return createUninitializedBlock(name, startAddr, length, flags);
}
@Override
- MemoryBlockDB createInitializedBlock(String name, Address startAddr, DBBuffer buf,
- int permissions) throws AddressOverflowException, IOException {
+ MemoryBlockDB createInitializedBlock(String name, Address startAddr, DBBuffer buf, int flags)
+ throws AddressOverflowException, IOException {
updateAddressMapForAllAddresses(startAddr, buf.length());
List subBlocks = new ArrayList<>();
- DBRecord blockRecord = createMemoryBlockRecord(name, startAddr, buf.length(), permissions);
+ DBRecord blockRecord = createMemoryBlockRecord(name, startAddr, buf.length(), flags);
long key = blockRecord.getKey();
DBRecord subRecord =
@@ -239,11 +239,11 @@ public class MemoryMapDBAdapterV3 extends MemoryMapDBAdapter {
}
MemoryBlockDB createUninitializedBlock(String name, Address startAddress, long length,
- int permissions) throws IOException, AddressOverflowException {
+ int flags) throws IOException, AddressOverflowException {
updateAddressMapForAllAddresses(startAddress, length);
List subBlocks = new ArrayList<>();
- DBRecord blockRecord = createMemoryBlockRecord(name, startAddress, length, permissions);
+ DBRecord blockRecord = createMemoryBlockRecord(name, startAddress, length, flags);
long key = blockRecord.getKey();
DBRecord subRecord = createSubBlockRecord(key, 0, length, V3_SUB_TYPE_UNINITIALIZED, 0, 0);
@@ -256,9 +256,9 @@ public class MemoryMapDBAdapterV3 extends MemoryMapDBAdapter {
}
@Override
- protected MemoryBlockDB createBlock(String name, Address startAddress, long length,
- int permissions, List splitBlocks) throws IOException {
- DBRecord blockRecord = createMemoryBlockRecord(name, startAddress, length, permissions);
+ protected MemoryBlockDB createBlock(String name, Address startAddress, long length, int flags,
+ List splitBlocks) throws IOException {
+ DBRecord blockRecord = createMemoryBlockRecord(name, startAddress, length, flags);
long key = blockRecord.getKey();
long startingOffset = 0;
@@ -274,26 +274,26 @@ public class MemoryMapDBAdapterV3 extends MemoryMapDBAdapter {
}
MemoryBlockDB createBitMappedBlock(String name, Address startAddress, long length,
- Address mappedAddress, int permissions) throws IOException, AddressOverflowException {
+ Address mappedAddress, int flags) throws IOException, AddressOverflowException {
return createMappedBlock(V3_SUB_TYPE_BIT_MAPPED, name, startAddress, length, mappedAddress,
- permissions, 0);
+ flags, 0);
}
MemoryBlockDB createByteMappedBlock(String name, Address startAddress, long length,
- Address mappedAddress, int permissions, int mappingScheme)
+ Address mappedAddress, int flags, int mappingScheme)
throws IOException, AddressOverflowException {
return createMappedBlock(V3_SUB_TYPE_BYTE_MAPPED, name, startAddress, length, mappedAddress,
- permissions, mappingScheme);
+ flags, mappingScheme);
}
@Override
protected MemoryBlockDB createFileBytesBlock(String name, Address startAddress, long length,
- FileBytes fileBytes, long offset, int permissions)
+ FileBytes fileBytes, long offset, int flags)
throws IOException, AddressOverflowException {
updateAddressMapForAllAddresses(startAddress, length);
List subBlocks = new ArrayList<>();
- DBRecord blockRecord = createMemoryBlockRecord(name, startAddress, length, permissions);
+ DBRecord blockRecord = createMemoryBlockRecord(name, startAddress, length, flags);
long key = blockRecord.getKey();
DBRecord subRecord = createSubBlockRecord(key, 0, length, V3_SUB_TYPE_FILE_BYTES,
@@ -307,13 +307,12 @@ public class MemoryMapDBAdapterV3 extends MemoryMapDBAdapter {
}
private MemoryBlockDB createMappedBlock(byte type, String name, Address startAddress,
- long length, Address mappedAddress, int permissions,
- int mappingScheme)
+ long length, Address mappedAddress, int flags, int mappingScheme)
throws IOException, AddressOverflowException {
updateAddressMapForAllAddresses(startAddress, length);
List subBlocks = new ArrayList<>();
- DBRecord blockRecord = createMemoryBlockRecord(name, startAddress, length, permissions);
+ DBRecord blockRecord = createMemoryBlockRecord(name, startAddress, length, flags);
long key = blockRecord.getKey();
long encoded = addrMap.getKey(mappedAddress, true);
@@ -377,12 +376,12 @@ public class MemoryMapDBAdapterV3 extends MemoryMapDBAdapter {
}
private DBRecord createMemoryBlockRecord(String name, Address startAddr, long length,
- int permissions) {
+ int flags) {
DBRecord record = V3_BLOCK_SCHEMA.createRecord(memBlockTable.getKey());
record.setString(V3_NAME_COL, name);
record.setLongValue(V3_START_ADDR_COL, addrMap.getKey(startAddr, true));
record.setLongValue(V3_LENGTH_COL, length);
- record.setByteValue(V3_PERMISSIONS_COL, (byte) permissions);
+ record.setByteValue(V3_FLAGS_COL, (byte) flags);
record.setIntValue(V3_SEGMENT_COL, getSegment(startAddr));
return record;
}
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 946bbd6223..86033b0f93 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
@@ -46,17 +46,22 @@ public interface MemoryBlock extends Serializable, Comparable {
*/
public static final String EXTERNAL_BLOCK_NAME = "EXTERNAL";
- // Memory block permission bits
+ // Memory block flag bits
+ // NOTE: These are used by stored Flags with DB (8-bits) and
+ // should be changed other than to add values.
+ public static int ARTIFICIAL = 0x10;
public static int VOLATILE = 0x8;
public static int READ = 0x4;
public static int WRITE = 0x2;
public static int EXECUTE = 0x1;
/**
- * Returns block permissions as a bit mask. Permission bits defined as READ, WRITE, EXECUTE and
- * VOLATILE
+ * Returns block flags (i.e., permissions and attributes) as a bit mask.
+ * These bits defined as {@link #READ}, {@link #WRITE}, {@link #EXECUTE}, {@link #VOLATILE},
+ * {@link #ARTIFICIAL}.
+ * @return block flag bits
*/
- public int getPermissions();
+ public int getFlags();
/**
* Get memory data in the form of an InputStream. Null is returned for thos memory blocks which
@@ -107,6 +112,8 @@ public interface MemoryBlock extends Serializable, Comparable {
/**
* Get the name of this block
+ *
+ * @return block name
*/
public String getName();
@@ -122,6 +129,8 @@ public interface MemoryBlock extends Serializable, Comparable {
/**
* Get the comment associated with this block.
+ *
+ * @return block comment string
*/
public String getComment();
@@ -134,6 +143,8 @@ public interface MemoryBlock extends Serializable, Comparable {
/**
* Returns the value of the read property associated with this block
+ *
+ * @return true if enabled else false
*/
public boolean isRead();
@@ -146,6 +157,8 @@ public interface MemoryBlock extends Serializable, Comparable {
/**
* Returns the value of the write property associated with this block
+ *
+ * @return true if enabled else false
*/
public boolean isWrite();
@@ -158,6 +171,8 @@ public interface MemoryBlock extends Serializable, Comparable {
/**
* Returns the value of the execute property associated with this block
+ *
+ * @return true if enabled else false
*/
public boolean isExecute();
@@ -178,18 +193,41 @@ public interface MemoryBlock extends Serializable, Comparable {
public void setPermissions(boolean read, boolean write, boolean execute);
/**
- * Returns the value of the volatile property associated with this block. This attribute is
+ * Returns the volatile attribute state of this block. This attribute is
* generally associated with block of I/O regions of memory.
+ *
+ * @return true if enabled else false
*/
public boolean isVolatile();
/**
- * Sets the volatile property associated with this block.
+ * Sets the volatile attribute state associated of this block. This attribute is
+ * generally associated with block of I/O regions of memory.
*
- * @param v the value to set the volatile property to.
+ * @param v the volatile attribute state.
*/
public void setVolatile(boolean v);
+ /**
+ * Returns the artificial attribute state of this block. This attribute is
+ * generally associated with blocks which have been fabricated to facilitate
+ * analysis but do not exist in the same form within a running/loaded process
+ * state.
+ *
+ * @return true if enabled else false
+ */
+ public boolean isArtificial();
+
+ /**
+ * Sets the artificial attribute state associated with this block. This attribute is
+ * generally associated with blocks which have been fabricated to facilitate
+ * analysis but do not exist in the same form within a running/loaded process
+ * state.
+ *
+ * @param a the artificial attribute state.
+ */
+ public void setArtificial(boolean a);
+
/**
* Get the name of the source of this memory block.
*
@@ -208,6 +246,7 @@ public interface MemoryBlock extends Serializable, Comparable {
* Returns the byte at the given address in this block.
*
* @param addr the address.
+ * @return byte value from this block and specified address
* @throws MemoryAccessException if any of the requested bytes are uninitialized.
* @throws IllegalArgumentException if the Address is not in this block.
*/
@@ -246,6 +285,7 @@ public interface MemoryBlock extends Serializable, Comparable {
* Puts the given byte at the given address in this block.
*
* @param addr the address.
+ * @param b byte value
* @throws MemoryAccessException if the block is uninitialized
* @throws IllegalArgumentException if the Address is not in this 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 6be0695ec5..986840fc30 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
@@ -46,7 +46,7 @@ public class MemoryBlockStub implements MemoryBlock {
}
@Override
- public int getPermissions() {
+ public int getFlags() {
throw new UnsupportedOperationException();
}
@@ -150,6 +150,16 @@ public class MemoryBlockStub implements MemoryBlock {
throw new UnsupportedOperationException();
}
+ @Override
+ public boolean isArtificial() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setArtificial(boolean a) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public boolean isOverlay() {
return false;
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 f676677139..78bbaea4a9 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
@@ -92,7 +92,7 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(false, block.isMapped());
assertNull(block.getComment());
assertNull(block.getSourceName());
- assertEquals(MemoryBlock.READ, block.getPermissions());
+ assertEquals(MemoryBlock.READ, block.getFlags());
List sourceInfos = block.getSourceInfos();
@@ -192,7 +192,7 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(true, block.isMapped());
assertNull(block.getComment());
assertNull(block.getSourceName());
- assertEquals(MemoryBlock.READ, block.getPermissions());
+ assertEquals(MemoryBlock.READ, block.getFlags());
List sourceInfos = block.getSourceInfos();
@@ -228,7 +228,7 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(true, block.isMapped());
assertNull(block.getComment());
assertNull(block.getSourceName());
- assertEquals(MemoryBlock.READ, block.getPermissions());
+ assertEquals(MemoryBlock.READ, block.getFlags());
List sourceInfos = block.getSourceInfos();
@@ -264,7 +264,7 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(false, block.isMapped());
assertNull(block.getComment());
assertNull(block.getSourceName());
- assertEquals(MemoryBlock.READ, block.getPermissions());
+ assertEquals(MemoryBlock.READ, block.getFlags());
List sourceInfos = block.getSourceInfos();
diff --git a/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/relocation/MIPS_ElfRelocationContext.java b/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/relocation/MIPS_ElfRelocationContext.java
index ac88f85aa0..a7f4416720 100644
--- a/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/relocation/MIPS_ElfRelocationContext.java
+++ b/Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/relocation/MIPS_ElfRelocationContext.java
@@ -310,6 +310,10 @@ class MIPS_ElfRelocationContext extends ElfRelocationContext