GP-4125 Added memory block artificial attribute flag

This commit is contained in:
ghidra1 2024-03-06 16:53:12 -05:00
parent ddf4d15327
commit ae475f743b
48 changed files with 734 additions and 465 deletions

View file

@ -104,7 +104,7 @@ public class ProgramEmulationUtils {
*/ */
public static Set<TraceMemoryFlag> getRegionFlags(MemoryBlock block) { public static Set<TraceMemoryFlag> getRegionFlags(MemoryBlock block) {
Set<TraceMemoryFlag> result = EnumSet.noneOf(TraceMemoryFlag.class); Set<TraceMemoryFlag> result = EnumSet.noneOf(TraceMemoryFlag.class);
int mask = block.getPermissions(); int mask = block.getFlags();
if ((mask & MemoryBlock.READ) != 0) { if ((mask & MemoryBlock.READ) != 0) {
result.add(TraceMemoryFlag.READ); result.add(TraceMemoryFlag.READ);
} }

View file

@ -18,6 +18,8 @@ package ghidra.trace.database.program;
import java.io.InputStream; import java.io.InputStream;
import java.math.BigInteger; import java.math.BigInteger;
import javax.help.UnsupportedOperationException;
import ghidra.framework.store.LockException; import ghidra.framework.store.LockException;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.trace.database.memory.DBTraceMemorySpace; import ghidra.trace.database.memory.DBTraceMemorySpace;
@ -57,7 +59,7 @@ public class DBTraceProgramViewMemoryRegionBlock extends AbstractDBTraceProgramV
} }
@Override @Override
public int getPermissions() { public int getFlags() {
int bits = 0; int bits = 0;
for (TraceMemoryFlag flag : region.getFlags()) { for (TraceMemoryFlag flag : region.getFlags()) {
bits |= flag.getBits(); bits |= flag.getBits();
@ -145,4 +147,15 @@ public class DBTraceProgramViewMemoryRegionBlock extends AbstractDBTraceProgramV
public void setVolatile(boolean v) { public void setVolatile(boolean v) {
region.setVolatile(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();
}
} }

View file

@ -50,7 +50,7 @@ public class DBTraceProgramViewMemorySpaceBlock extends AbstractDBTraceProgramVi
} }
@Override @Override
public int getPermissions() { public int getFlags() {
return MemoryBlock.READ | MemoryBlock.WRITE | MemoryBlock.EXECUTE; return MemoryBlock.READ | MemoryBlock.WRITE | MemoryBlock.EXECUTE;
} }
@ -119,6 +119,16 @@ public class DBTraceProgramViewMemorySpaceBlock extends AbstractDBTraceProgramVi
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public boolean isArtificial() {
return false;
}
@Override
public void setArtificial(boolean a) {
throw new UnsupportedOperationException();
}
@Override @Override
public String getSourceName() { public String getSourceName() {
return "Trace"; // TODO: What does this method actually do? return "Trace"; // TODO: What does this method actually do?

View file

@ -116,7 +116,7 @@ public class DBTraceProgramViewRegisterMemoryBlock implements MemoryBlock {
} }
@Override @Override
public int getPermissions() { public int getFlags() {
return MemoryBlock.READ | MemoryBlock.WRITE; return MemoryBlock.READ | MemoryBlock.WRITE;
} }
@ -220,6 +220,16 @@ public class DBTraceProgramViewRegisterMemoryBlock implements MemoryBlock {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public boolean isArtificial() {
return false;
}
@Override
public void setArtificial(boolean a) {
throw new UnsupportedOperationException();
}
@Override @Override
public String getSourceName() { public String getSourceName() {
return "Trace"; // TODO: What does this method actually do? return "Trace"; // TODO: What does this method actually do?

View file

@ -62,26 +62,11 @@
<P><A name="OverlayType"></A><B>Overlay</B> - Each of the above memory block types may <P><A name="OverlayType"></A><B>Overlay</B> - Each of the above memory block types may
optionally be created as an <I>Overlay</I> block. One or more memory blocks may be defined optionally be created as an <I>Overlay</I> block. One or more memory blocks may be defined
within the same overlay address space. within the same overlay address space where the <B>Overlayed Space</B> 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
An overlay memory block may be created in two ways: or processor state. &nbsp; Note that Overlay blocks
* <ul> do not relocate with image base changes and have some limitations in conjunction with
* <li>Specifying a {@code start} address within an existing overlay address space
* ({@code overlay} parameter is ignored), or</li>
* <li>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.</li>
* </ul>
If this option is selected, the block is created in a new
overlay address space.&nbsp; 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. &nbsp; Note that
overlay blocks are fixed and may not be moved, split, merged or expanded.&nbsp; In addition, Overlays
do not relocate with image base changes and have significant limitations in conjunction with
decompilation and analysis.</P> decompilation and analysis.</P>
<P>To view the <I>Memory Map</I>, select <B>Window<IMG src="help/shared/arrow.gif" border="0"> <P>To view the <I>Memory Map</I>, select <B>Window<IMG src="help/shared/arrow.gif" border="0">
@ -124,6 +109,9 @@
<P><B>Volatile * </B> - Indicates a region of volatile I/O Memory.</P> <P><B>Volatile * </B> - Indicates a region of volatile I/O Memory.</P>
<P><B>Artificial * </B> - Indicates an artificial memory block which has been fabricated to
facilitate analysis.</P>
<P><I><B>Overlayed Space -</B></I> If the block is an overlay block this column indicates the name <P><I><B>Overlayed Space -</B></I> 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.</P> of the overlayed physical memory space. This field will be empty for non-overlay blocks.</P>
@ -201,6 +189,13 @@
checkbox.</P> checkbox.</P>
</BLOCKQUOTE> </BLOCKQUOTE>
<H3>Change Artificial Setting</H3>
<BLOCKQUOTE>
<P>The artificial setting of a memory block can be changed by left-clicking on the
checkbox.</P>
</BLOCKQUOTE>
<H3>Initialize Memory Block</H3> <H3>Initialize Memory Block</H3>
<BLOCKQUOTE> <BLOCKQUOTE>
@ -266,7 +261,11 @@
<P><B><I>Execute</I></B> - Sets the execute permission.</P> <P><B><I>Execute</I></B> - Sets the execute permission.</P>
<P><B>Volatile</B> - Marks this block as volatile I/O memory.</P> <P><B>Volatile</B> - Marks a block as volatile I/O memory.</P>
<P><B>Artificial</B> - 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.</P>
<P><B>Overlay</B> - Creates the block as an overlay block. An overlay memory block may be <P><B>Overlay</B> - Creates the block as an overlay block. An overlay memory block may be
created in two ways: created in two ways:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Before After
Before After

View file

@ -28,7 +28,7 @@ import ghidra.util.exception.*;
/** /**
* Base command class for adding memory blocks. * Base command class for adding memory blocks.
*/ */
abstract class AbstractAddMemoryBlockCmd implements Command { public abstract class AbstractAddMemoryBlockCmd implements Command {
protected String message; protected String message;
protected final String name; protected final String name;
protected final String comment; protected final String comment;
@ -42,6 +42,8 @@ abstract class AbstractAddMemoryBlockCmd implements Command {
protected final boolean isVolatile; protected final boolean isVolatile;
protected final boolean isOverlay; protected final boolean isOverlay;
private boolean isArtificial = false;
AbstractAddMemoryBlockCmd(String name, String comment, String source, Address start, AbstractAddMemoryBlockCmd(String name, String comment, String source, Address start,
long length, boolean read, boolean write, boolean execute, boolean isVolatile, long length, boolean read, boolean write, boolean execute, boolean isVolatile,
boolean isOverlay) { boolean isOverlay) {
@ -57,6 +59,15 @@ abstract class AbstractAddMemoryBlockCmd implements Command {
this.isOverlay = isOverlay; 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 @Override
public String getStatusMsg() { public String getStatusMsg() {
return message; return message;
@ -67,9 +78,8 @@ abstract class AbstractAddMemoryBlockCmd implements Command {
return "Add Memory Block"; return "Add Memory Block";
} }
protected abstract MemoryBlock createMemoryBlock(Memory memory) protected abstract MemoryBlock createMemoryBlock(Memory memory) throws LockException,
throws LockException, MemoryConflictException, AddressOverflowException, MemoryConflictException, AddressOverflowException, CancelledException;
CancelledException;
@Override @Override
public boolean applyTo(DomainObject obj) { public boolean applyTo(DomainObject obj) {
@ -82,6 +92,7 @@ abstract class AbstractAddMemoryBlockCmd implements Command {
block.setWrite(write); block.setWrite(write);
block.setExecute(execute); block.setExecute(execute);
block.setVolatile(isVolatile); block.setVolatile(isVolatile);
block.setArtificial(isArtificial);
block.setSourceName(source); block.setSourceName(source);
renameFragment(program, block.getStart()); renameFragment(program, block.getStart());
return true; return true;

View file

@ -196,7 +196,7 @@ public class MemoryMergeManager implements MergeResolver {
if (isNameConflict(i)) { if (isNameConflict(i)) {
conflictList.add(new ConflictInfo(i, true, false, false)); conflictList.add(new ConflictInfo(i, true, false, false));
} }
if (isPermissionConflict(i)) { if (isFlagsConflict(i)) {
conflictList.add(new ConflictInfo(i, false, true, false)); conflictList.add(new ConflictInfo(i, false, true, false));
} }
if (isCommentConflict(i)) { if (isCommentConflict(i)) {
@ -233,7 +233,8 @@ public class MemoryMergeManager implements MergeResolver {
String myName = myBlocks[index].getName(); String myName = myBlocks[index].getName();
String origName = origBlocks[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 true;
} }
return false; return false;
@ -244,13 +245,12 @@ public class MemoryMergeManager implements MergeResolver {
* LATEST and MY programs. * LATEST and MY programs.
* @param index block index * @param index block index
*/ */
private boolean isPermissionConflict(int index) { private boolean isFlagsConflict(int index) {
int latestPermissions = latestBlocks[index].getPermissions(); int latestFlags = latestBlocks[index].getFlags();
int myPermissions = myBlocks[index].getPermissions(); int myFlags = myBlocks[index].getFlags();
int origPermissions = origBlocks[index].getPermissions(); int origFlags = origBlocks[index].getFlags();
if (myPermissions != origPermissions && latestPermissions != origPermissions && if (myFlags != origFlags && latestFlags != origFlags && myFlags != latestFlags) {
myPermissions != latestPermissions) {
return true; return true;
} }
return false; return false;
@ -363,27 +363,21 @@ public class MemoryMergeManager implements MergeResolver {
if (info.nameConflict) { if (info.nameConflict) {
title = "Resolve Name Conflict"; title = "Resolve Name Conflict";
latestStr = latestStr = "Use Block name '" + latestBlocks[info.index].getName() + "' (" +
"Use Block name '" + latestBlocks[info.index].getName() + "' (" + MergeConstants.LATEST_TITLE + ")";
MergeConstants.LATEST_TITLE + ")"; myStr = "Use Block name '" + getUniqueBlockName(myBlocks[info.index].getName()) +
myStr = "' (" + MergeConstants.MY_TITLE + ")";
"Use Block name '" + getUniqueBlockName(myBlocks[info.index].getName()) + "' (" + origStr = "Use Block name '" + origBlocks[info.index].getName() + "' (" +
MergeConstants.MY_TITLE + ")"; MergeConstants.ORIGINAL_TITLE + ")";
origStr =
"Use Block name '" + origBlocks[info.index].getName() + "' (" +
MergeConstants.ORIGINAL_TITLE + ")";
} }
else if (info.permissionConflict) { else if (info.permissionConflict) {
title = "Resolve Permissions Conflict"; title = "Resolve Flags Conflict";
latestStr = latestStr = "Use '" + getFlagsString(latestBlocks[info.index]) + "' (" +
"Use '" + getPermissionString(latestBlocks[info.index]) + "' (" + MergeConstants.LATEST_TITLE + ")";
MergeConstants.LATEST_TITLE + ")"; myStr = "Use '" + getFlagsString(myBlocks[info.index]) + "' (" +
myStr = MergeConstants.MY_TITLE + ")";
"Use '" + getPermissionString(myBlocks[info.index]) + "' (" + origStr = "Use '" + getFlagsString(origBlocks[info.index]) + "' (" +
MergeConstants.MY_TITLE + ")"; MergeConstants.ORIGINAL_TITLE + ")";
origStr =
"Use '" + getPermissionString(origBlocks[info.index]) + "' (" +
MergeConstants.ORIGINAL_TITLE + ")";
} }
else { else {
// comment conflict // comment conflict
@ -393,7 +387,8 @@ public class MemoryMergeManager implements MergeResolver {
myStr = myBlocks[info.index].getComment(); myStr = myBlocks[info.index].getComment();
origStr = origBlocks[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 + ")"; title = title + " (Block index " + info.index + ")";
showMergePanel(panelID, title, latestStr, myStr, origStr); showMergePanel(panelID, title, latestStr, myStr, origStr);
} }
@ -428,6 +423,7 @@ public class MemoryMergeManager implements MergeResolver {
resultBlocks[info.index].setWrite(sourceBlock.isWrite()); resultBlocks[info.index].setWrite(sourceBlock.isWrite());
resultBlocks[info.index].setExecute(sourceBlock.isExecute()); resultBlocks[info.index].setExecute(sourceBlock.isExecute());
resultBlocks[info.index].setVolatile(sourceBlock.isVolatile()); resultBlocks[info.index].setVolatile(sourceBlock.isVolatile());
resultBlocks[info.index].setArtificial(sourceBlock.isArtificial());
} }
else { else {
resultBlocks[info.index].setComment(sourceBlock.getComment()); resultBlocks[info.index].setComment(sourceBlock.getComment());
@ -456,8 +452,8 @@ public class MemoryMergeManager implements MergeResolver {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e); Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
} }
mergeManager.setApplyEnabled(false); mergeManager.setApplyEnabled(false);
mergeManager.showComponent(mergePanel, "MemoryMerge", new HelpLocation( mergeManager.showComponent(mergePanel, "MemoryMerge",
HelpTopics.REPOSITORY, "MemoryConflict")); new HelpLocation(HelpTopics.REPOSITORY, "MemoryConflict"));
// block until the user either cancels or hits the "Apply" button // block until the user either cancels or hits the "Apply" button
// on the merge dialog... // on the merge dialog...
// when the "Apply" button is hit, get the user's selection // 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(); StringBuffer sb = new StringBuffer();
sb.append("Read = "); sb.append("Read = ");
sb.append(block.isExecute()); sb.append(block.isExecute());
@ -478,6 +474,9 @@ public class MemoryMergeManager implements MergeResolver {
sb.append(", "); sb.append(", ");
sb.append("Volatile = "); sb.append("Volatile = ");
sb.append(block.isVolatile()); sb.append(block.isVolatile());
sb.append(", ");
sb.append("Artificial = ");
sb.append(block.isArtificial());
return sb.toString(); return sb.toString();
} }
@ -501,7 +500,7 @@ public class MemoryMergeManager implements MergeResolver {
} }
} }
} }
if (!isPermissionConflict(index)) { if (!isFlagsConflict(index)) {
boolean permission = myBlocks[index].isRead(); boolean permission = myBlocks[index].isRead();
if (permission != origBlocks[index].isRead()) { if (permission != origBlocks[index].isRead()) {
resultBlocks[index].setRead(permission); resultBlocks[index].setRead(permission);
@ -534,6 +533,14 @@ public class MemoryMergeManager implements MergeResolver {
progressUpdated = true; 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)) { if (!isCommentConflict(index)) {
String myComment = myBlocks[index].getComment(); String myComment = myBlocks[index].getComment();

View file

@ -136,7 +136,8 @@ public class GolangSymbolAnalyzer extends AbstractAnalyzer {
} }
if (analyzerOptions.propagateRtti) { 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), aam.schedule(new PropagateRttiBackgroundCommand(goBinary),
AnalysisPriority.REFERENCE_ANALYSIS.after().priority()); AnalysisPriority.REFERENCE_ANALYSIS.after().priority());
} }
@ -408,6 +409,7 @@ public class GolangSymbolAnalyzer extends AbstractAnalyzer {
MemoryBlockUtils.createUninitializedBlock(program, false, "ARTIFICAL_GOLANG_CONTEXT", MemoryBlockUtils.createUninitializedBlock(program, false, "ARTIFICAL_GOLANG_CONTEXT",
mbStart, len, "Artifical memory block created to hold golang context data types", mbStart, len, "Artifical memory block created to hold golang context data types",
null, true, true, false, null); null, true, true, false, null);
newMB.setArtificial(true);
return newMB.getStart(); return newMB.getStart();
} }
@ -567,8 +569,8 @@ public class GolangSymbolAnalyzer extends AbstractAnalyzer {
} }
record CallSiteInfo(Reference ref, Function callingFunc, Function calledFunc, record CallSiteInfo(Reference ref, Function callingFunc, Function calledFunc,
Register register, Register register, java.util.function.Function<GoType, DataType> returnTypeMapper) {
java.util.function.Function<GoType, DataType> returnTypeMapper) {} }
private GoRttiMapper goBinary; private GoRttiMapper goBinary;
private MarkupSession markupSession; private MarkupSession markupSession;

View file

@ -107,10 +107,10 @@ public class AddressTableAnalyzer extends AbstractAnalyzer {
processorHasLowBitCode = PseudoDisassembler.hasLowBitCodeModeInAddrValues(program); processorHasLowBitCode = PseudoDisassembler.hasLowBitCodeModeInAddrValues(program);
// don't align based on instruction start rules, data is important too. // 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/.... // if do this, will miss, runs of ptrs to data/code/data/code/....
// ptrAlignment = program.getLanguage().getInstructionAlignment(); // ptrAlignment = program.getLanguage().getInstructionAlignment();
// if (processorHasLowBitCode) { // if (processorHasLowBitCode) {
// ptrAlignment = 1; // ptrAlignment = 1;
// } // }
return (addrSize == 32 || addrSize == 64); return (addrSize == 32 || addrSize == 64);
} }
@ -164,8 +164,9 @@ public class AddressTableAnalyzer extends AbstractAnalyzer {
continue; continue;
} }
Bookmark bookmark = program.getBookmarkManager().getBookmark( Bookmark bookmark = program.getBookmarkManager()
tableEntry.getTopAddress(), BookmarkType.ANALYSIS, "Address Table"); .getBookmark(tableEntry.getTopAddress(), BookmarkType.ANALYSIS,
"Address Table");
// nothing to see here, already done. // nothing to see here, already done.
if (!ignoreBookmarks && bookmark != null) { if (!ignoreBookmarks && bookmark != null) {
@ -186,9 +187,10 @@ public class AddressTableAnalyzer extends AbstractAnalyzer {
// put info bookmark in // put info bookmark in
if (createBookmarksEnabled) { if (createBookmarksEnabled) {
program.getBookmarkManager().setBookmark(tableEntry.getTopAddress(), program.getBookmarkManager()
BookmarkType.ANALYSIS, "Address Table", .setBookmark(tableEntry.getTopAddress(), BookmarkType.ANALYSIS,
"Address table[" + tableEntry.getNumberAddressEntries() + "] created"); "Address Table", "Address table[" +
tableEntry.getNumberAddressEntries() + "] created");
} }
// if all are valid code, disassemble // if all are valid code, disassemble
@ -268,8 +270,7 @@ public class AddressTableAnalyzer extends AbstractAnalyzer {
// //
AddressSet badBlocks = new AddressSet(); AddressSet badBlocks = new AddressSet();
for (MemoryBlock memoryBlock : blocks) { for (MemoryBlock memoryBlock : blocks) {
if (memoryBlock.isWrite() || memoryBlock.isRead() || memoryBlock.isExecute() || if (memoryBlock.isWrite() || memoryBlock.isRead() || memoryBlock.isExecute()) {
memoryBlock.isVolatile()) {
continue; continue;
} }
@ -340,14 +341,15 @@ public class AddressTableAnalyzer extends AbstractAnalyzer {
AddressIterator addrIter = addrSet.getAddresses(true); AddressIterator addrIter = addrSet.getAddresses(true);
long maxBytes = addrSet.getNumAddresses(); 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()) { while (addrIter.hasNext()) {
Address start = addrIter.next(); Address start = addrIter.next();
// skip over anything that smells like a unicode string // 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) { if (strLen > 4) {
int numBytes = strLen * 2; int numBytes = strLen * 2;
addrIter = skipBytes(addrIter, addrSet, start, numBytes); addrIter = skipBytes(addrIter, addrSet, start, numBytes);

View file

@ -65,6 +65,7 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
private JCheckBox writeCB; private JCheckBox writeCB;
private JCheckBox executeCB; private JCheckBox executeCB;
private JCheckBox volatileCB; private JCheckBox volatileCB;
private JCheckBox artificialCB;
private JCheckBox overlayCB; private JCheckBox overlayCB;
private RegisterField initialValueField; private RegisterField initialValueField;
private JLabel initialValueLabel; private JLabel initialValueLabel;
@ -108,6 +109,7 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
writeCB.setSelected(model.isWrite()); writeCB.setSelected(model.isWrite());
executeCB.setSelected(model.isExecute()); executeCB.setSelected(model.isExecute());
volatileCB.setSelected(model.isVolatile()); volatileCB.setSelected(model.isVolatile());
artificialCB.setSelected(model.isArtificial());
overlayCB.setSelected(model.isOverlay()); overlayCB.setSelected(model.isOverlay());
} }
@ -169,6 +171,11 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
volatileCB.setSelected(model.isVolatile()); volatileCB.setSelected(model.isVolatile());
volatileCB.addActionListener(e -> model.setVolatile(volatileCB.isSelected())); 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 = new GCheckBox("Overlay");
overlayCB.setName("Overlay"); overlayCB.setName("Overlay");
overlayCB.setSelected(model.isOverlay()); overlayCB.setSelected(model.isOverlay());
@ -180,6 +187,7 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
panel.add(writeCB); panel.add(writeCB);
panel.add(executeCB); panel.add(executeCB);
panel.add(volatileCB); panel.add(volatileCB);
panel.add(artificialCB);
panel.add(overlayCB); panel.add(overlayCB);
return panel; return panel;
@ -320,6 +328,7 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
writeCB.setSelected(model.isWrite()); writeCB.setSelected(model.isWrite());
executeCB.setSelected(model.isExecute()); executeCB.setSelected(model.isExecute());
volatileCB.setSelected(model.isVolatile()); volatileCB.setSelected(model.isVolatile());
artificialCB.setSelected(model.isArtificial());
overlayCB.setSelected(model.isOverlay()); overlayCB.setSelected(model.isOverlay());
setOkEnabled(false); setOkEnabled(false);

View file

@ -18,7 +18,6 @@ package ghidra.app.plugin.core.memory;
import javax.swing.event.ChangeListener; import javax.swing.event.ChangeListener;
import ghidra.app.cmd.memory.*; import ghidra.app.cmd.memory.*;
import ghidra.framework.cmd.Command;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.program.database.mem.ByteMappingScheme; import ghidra.program.database.mem.ByteMappingScheme;
import ghidra.program.database.mem.FileBytes; import ghidra.program.database.mem.FileBytes;
@ -55,6 +54,7 @@ class AddBlockModel {
private boolean isWrite; private boolean isWrite;
private boolean isExecute; private boolean isExecute;
private boolean isVolatile; private boolean isVolatile;
private boolean isArtificial;
private InitializedType initializedType; private InitializedType initializedType;
private String comment; private String comment;
private FileBytes fileBytes; private FileBytes fileBytes;
@ -125,6 +125,7 @@ class AddBlockModel {
isExecute = false; isExecute = false;
isVolatile = false; isVolatile = false;
isOverlay = false; isOverlay = false;
isArtificial = false;
schemeDestByteCount = blockType == MemoryBlockType.BIT_MAPPED ? 8 : 1; schemeDestByteCount = blockType == MemoryBlockType.BIT_MAPPED ? 8 : 1;
schemeSrcByteCount = 1; schemeSrcByteCount = 1;
initializedType = InitializedType.UNINITIALIZED; initializedType = InitializedType.UNINITIALIZED;
@ -148,6 +149,10 @@ class AddBlockModel {
this.isVolatile = b; this.isVolatile = b;
} }
void setArtificial(boolean b) {
this.isArtificial = b;
}
void setOverlay(boolean b) { void setOverlay(boolean b) {
this.isOverlay = b; this.isOverlay = b;
validateInfo(); validateInfo();
@ -226,6 +231,10 @@ class AddBlockModel {
return isVolatile; return isVolatile;
} }
boolean isArtificial() {
return isArtificial;
}
boolean isOverlay() { boolean isOverlay() {
return isOverlay; return isOverlay;
} }
@ -240,7 +249,8 @@ class AddBlockModel {
if (!isValid) { if (!isValid) {
return false; return false;
} }
Command cmd = createAddBlockCommand(); AbstractAddMemoryBlockCmd cmd = createAddBlockCommand();
cmd.setArtificial(isArtificial);
if (!tool.execute(cmd, program)) { if (!tool.execute(cmd, program)) {
message = cmd.getStatusMsg(); message = cmd.getStatusMsg();
return false; return false;
@ -248,7 +258,7 @@ class AddBlockModel {
return true; return true;
} }
Command createAddBlockCommand() { AbstractAddMemoryBlockCmd createAddBlockCommand() {
String source = ""; String source = "";
switch (blockType) { switch (blockType) {
case BIT_MAPPED: case BIT_MAPPED:
@ -267,7 +277,7 @@ class AddBlockModel {
} }
} }
private Command createNonMappedMemoryBlock(String source) { private AbstractAddMemoryBlockCmd createNonMappedMemoryBlock(String source) {
switch (initializedType) { switch (initializedType) {
case INITIALIZED_FROM_FILE_BYTES: case INITIALIZED_FROM_FILE_BYTES:
return new AddFileBytesMemoryBlockCmd(blockName, comment, source, startAddr, length, return new AddFileBytesMemoryBlockCmd(blockName, comment, source, startAddr, length,
@ -293,8 +303,8 @@ class AddBlockModel {
private void validateInfo() { private void validateInfo() {
message = ""; message = "";
isValid = hasValidName() && hasValidStartAddress() && hasValidLength() && isValid = hasValidName() && hasValidStartAddress() && hasValidLength() &&
hasNoMemoryConflicts() && hasMappedAddressIfNeeded() && hasNoMemoryConflicts() && hasMappedAddressIfNeeded() && hasInitialValueIfNeeded() &&
hasInitialValueIfNeeded() && hasFileBytesInfoIfNeeded() && isOverlayIfOtherSpace(); hasFileBytesInfoIfNeeded() && isOverlayIfOtherSpace();
} }
private boolean hasFileBytesInfoIfNeeded() { private boolean hasFileBytesInfoIfNeeded() {

View file

@ -363,6 +363,7 @@ class MemoryMapManager {
newBlock.setWrite(bigBlock.isWrite()); newBlock.setWrite(bigBlock.isWrite());
newBlock.setExecute(bigBlock.isExecute()); newBlock.setExecute(bigBlock.isExecute());
newBlock.setVolatile(bigBlock.isVolatile()); newBlock.setVolatile(bigBlock.isVolatile());
newBlock.setArtificial(bigBlock.isArtificial());
newBlock.setSourceName("Resized Memory Block"); newBlock.setSourceName("Resized Memory Block");
} }
else { else {

View file

@ -51,12 +51,13 @@ class MemoryMapModel extends AbstractSortedTableModel<MemoryBlock> implements Pr
final static byte WRITE = 5; final static byte WRITE = 5;
final static byte EXECUTE = 6; final static byte EXECUTE = 6;
final static byte VOLATILE = 7; final static byte VOLATILE = 7;
final static byte OVERLAY = 8; final static byte ARTIFICIAL = 8;
final static byte BLOCK_TYPE = 9; final static byte OVERLAY = 9;
final static byte INIT = 10; final static byte BLOCK_TYPE = 10;
final static byte BYTE_SOURCE = 11; final static byte INIT = 11;
final static byte SOURCE = 12; final static byte BYTE_SOURCE = 12;
final static byte COMMENT = 13; final static byte SOURCE = 13;
final static byte COMMENT = 14;
final static String NAME_COL = "Name"; final static String NAME_COL = "Name";
final static String START_COL = "Start"; final static String START_COL = "Start";
@ -66,6 +67,7 @@ class MemoryMapModel extends AbstractSortedTableModel<MemoryBlock> implements Pr
final static String WRITE_COL = "W"; final static String WRITE_COL = "W";
final static String EXECUTE_COL = "X"; final static String EXECUTE_COL = "X";
final static String VOLATILE_COL = "Volatile"; final static String VOLATILE_COL = "Volatile";
final static String ARTIFICIAL_COL = "Artificial";
final static String OVERLAY_COL = "Overlayed Space"; final static String OVERLAY_COL = "Overlayed Space";
final static String BLOCK_TYPE_COL = "Type"; final static String BLOCK_TYPE_COL = "Type";
final static String INIT_COL = "Initialized"; final static String INIT_COL = "Initialized";
@ -80,9 +82,9 @@ class MemoryMapModel extends AbstractSortedTableModel<MemoryBlock> implements Pr
private List<MemoryBlock> memList; private List<MemoryBlock> memList;
private MemoryMapProvider provider; private MemoryMapProvider provider;
private final static String COLUMN_NAMES[] = private final static String COLUMN_NAMES[] = { NAME_COL, START_COL, END_COL, LENGTH_COL,
{ NAME_COL, START_COL, END_COL, LENGTH_COL, READ_COL, WRITE_COL, EXECUTE_COL, VOLATILE_COL, READ_COL, WRITE_COL, EXECUTE_COL, VOLATILE_COL, ARTIFICIAL_COL, OVERLAY_COL, BLOCK_TYPE_COL,
OVERLAY_COL, BLOCK_TYPE_COL, INIT_COL, BYTE_SOURCE_COL, SOURCE_COL, COMMENT_COL }; INIT_COL, BYTE_SOURCE_COL, SOURCE_COL, COMMENT_COL };
MemoryMapModel(MemoryMapProvider provider, Program program) { MemoryMapModel(MemoryMapProvider provider, Program program) {
super(START); super(START);
@ -124,7 +126,7 @@ class MemoryMapModel extends AbstractSortedTableModel<MemoryBlock> implements Pr
@Override @Override
public boolean isSortable(int columnIndex) { public boolean isSortable(int columnIndex) {
if (columnIndex == READ || columnIndex == WRITE || columnIndex == EXECUTE || if (columnIndex == READ || columnIndex == WRITE || columnIndex == EXECUTE ||
columnIndex == VOLATILE || columnIndex == INIT) { columnIndex == VOLATILE || columnIndex == ARTIFICIAL || columnIndex == INIT) {
return false; return false;
} }
return true; return true;
@ -163,7 +165,7 @@ class MemoryMapModel extends AbstractSortedTableModel<MemoryBlock> implements Pr
@Override @Override
public Class<?> getColumnClass(int columnIndex) { public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == READ || columnIndex == WRITE || columnIndex == EXECUTE || if (columnIndex == READ || columnIndex == WRITE || columnIndex == EXECUTE ||
columnIndex == VOLATILE || columnIndex == INIT) { columnIndex == VOLATILE || columnIndex == ARTIFICIAL || columnIndex == INIT) {
return Boolean.class; return Boolean.class;
} }
return String.class; return String.class;
@ -178,6 +180,8 @@ class MemoryMapModel extends AbstractSortedTableModel<MemoryBlock> implements Pr
case WRITE: case WRITE:
case EXECUTE: case EXECUTE:
case VOLATILE: case VOLATILE:
case ARTIFICIAL:
return true;
case COMMENT: case COMMENT:
return true; return true;
case INIT: case INIT:
@ -267,6 +271,14 @@ class MemoryMapModel extends AbstractSortedTableModel<MemoryBlock> implements Pr
}); });
break; break;
} }
case ARTIFICIAL: {
program.withTransaction("Set Artificial State", () -> {
boolean value = ((Boolean) aValue).booleanValue();
block.setArtificial(value);
provider.setStatusText("");
});
break;
}
case INIT: case INIT:
MemoryBlockType blockType = block.getType(); MemoryBlockType blockType = block.getType();
if (blockType == MemoryBlockType.BIT_MAPPED || if (blockType == MemoryBlockType.BIT_MAPPED ||
@ -428,6 +440,8 @@ class MemoryMapModel extends AbstractSortedTableModel<MemoryBlock> implements Pr
return block.isExecute() ? Boolean.TRUE : Boolean.FALSE; return block.isExecute() ? Boolean.TRUE : Boolean.FALSE;
case VOLATILE: case VOLATILE:
return block.isVolatile() ? Boolean.TRUE : Boolean.FALSE; return block.isVolatile() ? Boolean.TRUE : Boolean.FALSE;
case ARTIFICIAL:
return block.isArtificial() ? Boolean.TRUE : Boolean.FALSE;
case OVERLAY: case OVERLAY:
return getOverlayBaseSpaceName(block); return getOverlayBaseSpaceName(block);
case INIT: case INIT:
@ -554,29 +568,21 @@ class MemoryMapModel extends AbstractSortedTableModel<MemoryBlock> implements Pr
case LENGTH: case LENGTH:
return (int) (b1.getSize() - b2.getSize()); return (int) (b1.getSize() - b2.getSize());
case READ: case READ:
int b1r = (b1.isRead() ? 1 : -1); return Boolean.compare(b1.isRead(), b2.isRead());
int b2r = (b2.isRead() ? 1 : -1);
return (b1r - b2r);
case WRITE: case WRITE:
int b1w = (b1.isWrite() ? 1 : -1); return Boolean.compare(b1.isWrite(), b2.isWrite());
int b2w = (b2.isWrite() ? 1 : -1);
return (b1w - b2w);
case EXECUTE: case EXECUTE:
int b1x = (b1.isExecute() ? 1 : -1); return Boolean.compare(b1.isExecute(), b2.isExecute());
int b2x = (b2.isExecute() ? 1 : -1);
return (b1x - b2x);
case VOLATILE: case VOLATILE:
int b1v = (b1.isVolatile() ? 1 : -1); return Boolean.compare(b1.isVolatile(), b2.isVolatile());
int b2v = (b2.isVolatile() ? 1 : -1); case ARTIFICIAL:
return (b1v - b2v); return Boolean.compare(b1.isArtificial(), b2.isArtificial());
case OVERLAY: case OVERLAY:
String ov1 = getOverlayBaseSpaceName(b1); String ov1 = getOverlayBaseSpaceName(b1);
String ov2 = getOverlayBaseSpaceName(b2); String ov2 = getOverlayBaseSpaceName(b2);
return ov1.compareTo(ov2); return ov1.compareTo(ov2);
case INIT: case INIT:
int b1init = (b1.isInitialized() ? 1 : -1); return Boolean.compare(b1.isInitialized(), b2.isInitialized());
int b2init = (b2.isInitialized() ? 1 : -1);
return (b1init - b2init);
//case BYTE_SOURCE: - handled by default comparator //case BYTE_SOURCE: - handled by default comparator

View file

@ -480,6 +480,13 @@ class MemoryMapProvider extends ComponentProviderAdapter {
column.setResizable(false); 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); column = table.getColumn(MemoryMapModel.BLOCK_TYPE_COL);
if (column != null) { if (column != null) {
column.setMinWidth(25); column.setMinWidth(25);

View file

@ -109,6 +109,7 @@ public class StringsAnalyzer extends AbstractAnalyzer {
public static enum Alignment { public static enum Alignment {
ALIGN_1(1), ALIGN_2(2), ALIGN_4(4); ALIGN_1(1), ALIGN_2(2), ALIGN_4(4);
private int alignment; private int alignment;
Alignment(int alignment) { Alignment(int alignment) {
@ -349,7 +350,10 @@ public class StringsAnalyzer extends AbstractAnalyzer {
AddressSet addresses = new AddressSet(); AddressSet addresses = new AddressSet();
for (MemoryBlock memBlock : blocks) { 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())); 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); modelName = options.getString(MODELFILE_OPTION_NAME, MODEL_DEFAULT_NAME);
setTrigramFileName(modelName); setTrigramFileName(modelName);
minStringLength = options.getEnum(MINIMUM_STRING_LENGTH_OPTION_NAME, minStringLength =
MINIMUM_STRING_LENGTH_DEFAULT_VALUE).getMinLength(); options.getEnum(MINIMUM_STRING_LENGTH_OPTION_NAME, MINIMUM_STRING_LENGTH_DEFAULT_VALUE)
.getMinLength();
requireNullEnd = options.getBoolean(REQUIRE_NULL_TERMINATION_OPTION_NAME, requireNullEnd = options.getBoolean(REQUIRE_NULL_TERMINATION_OPTION_NAME,
REQUIRE_NULL_TERMINATION_DEFAULT_VALUE); REQUIRE_NULL_TERMINATION_DEFAULT_VALUE);
startAlignment = options.getEnum(START_ALIGNMENT_OPTION_NAME, startAlignment = options.getEnum(START_ALIGNMENT_OPTION_NAME, START_ALIGNMENT_DEFAULT_VALUE)
START_ALIGNMENT_DEFAULT_VALUE).getAlignment(); .getAlignment();
setStringEndAlignment( setStringEndAlignment(
options.getInt(END_ALIGNMENT_OPTION_NAME, END_ALIGNMENT_DEFAULT_VALUE)); options.getInt(END_ALIGNMENT_OPTION_NAME, END_ALIGNMENT_DEFAULT_VALUE));

View file

@ -706,9 +706,9 @@ public class ThreadEnvironmentBlock {
* @throws CodeUnitInsertionException for problems laying down the structure on the block * @throws CodeUnitInsertionException for problems laying down the structure on the block
* @throws InvalidInputException for problems with the symbol name attached to the TEB * @throws InvalidInputException for problems with the symbol name attached to the TEB
*/ */
public void createBlockAndStructure() throws MemoryConflictException, LockException, public void createBlockAndStructure()
IllegalArgumentException, AddressOverflowException, CodeUnitInsertionException, throws MemoryConflictException, LockException, IllegalArgumentException,
InvalidInputException { AddressOverflowException, CodeUnitInsertionException, InvalidInputException {
Memory memory = program.getMemory(); Memory memory = program.getMemory();
MemoryBlock block = memory.getBlock(BLOCK_NAME); MemoryBlock block = memory.getBlock(BLOCK_NAME);
if (block != null) { if (block != null) {
@ -722,6 +722,7 @@ public class ThreadEnvironmentBlock {
block = memory.createUninitializedBlock(BLOCK_NAME, tebAddress, blockSize, false); block = memory.createUninitializedBlock(BLOCK_NAME, tebAddress, blockSize, false);
} }
block.setWrite(true); block.setWrite(true);
block.setArtificial(true);
LayDownStructure laydown = new LayDownStructure(is64Bit); LayDownStructure laydown = new LayDownStructure(is64Bit);
create(laydown); create(laydown);
if (is64Bit) { if (is64Bit) {
@ -806,6 +807,7 @@ public class ThreadEnvironmentBlock {
null, false); null, false);
} }
block1.setWrite(true); block1.setWrite(true);
block1.setArtificial(true);
LayDownFlat laydown = new LayDownFlat(program, tebAddress, is64Bit); LayDownFlat laydown = new LayDownFlat(program, tebAddress, is64Bit);
create(laydown); create(laydown);
Data data = program.getListing().getDataAt(tebAddress.add(is64Bit ? 0x30 : 0x18)); Data data = program.getListing().getDataAt(tebAddress.add(is64Bit ? 0x30 : 0x18));

View file

@ -349,6 +349,9 @@ public class CoffLoader extends AbstractLibrarySupportLoader {
// assume any value in external is writable. // assume any value in external is writable.
block.setWrite(true); block.setWrite(true);
// Mark block as an artificial fabrication
block.setArtificial(true);
Address current = externalAddressStart; Address current = externalAddressStart;
while (current.compareTo(externalAddress) < 0) { while (current.compareTo(externalAddress) < 0) {
createUndefined(program.getListing(), program.getMemory(), current, createUndefined(program.getListing(), program.getMemory(), current,
@ -745,8 +748,8 @@ public class CoffLoader extends AbstractLibrarySupportLoader {
} }
} }
private void handleRelocationError(Program program, Address address, private void handleRelocationError(Program program, Address address, Short relocationType,
Short relocationType, String message, Exception causeToReport) { String message, Exception causeToReport) {
String bookmarkMessage = String bookmarkMessage =
String.format("Failed to apply COFF Relocation type 0x%x: %s", relocationType, message); String.format("Failed to apply COFF Relocation type 0x%x: %s", relocationType, message);
program.getBookmarkManager() program.getBookmarkManager()

View file

@ -1546,6 +1546,10 @@ class ElfProgramBuilder extends MemorySectionResolver implements ElfLoadHelper {
// assume any value in external is writable. // assume any value in external is writable.
block.setWrite(true); block.setWrite(true);
// Mark block as an artificial fabrication
block.setArtificial(true);
block.setSourceName(BLOCK_SOURCE_NAME); block.setSourceName(BLOCK_SOURCE_NAME);
block.setComment( block.setComment(
"NOTE: This block is artificial and allows ELF Relocations to work correctly"); "NOTE: This block is artificial and allows ELF Relocations to work correctly");

View file

@ -105,8 +105,8 @@ public class MachoProgramBuilder {
*/ */
public static void buildProgram(Program program, ByteProvider provider, FileBytes fileBytes, public static void buildProgram(Program program, ByteProvider provider, FileBytes fileBytes,
MessageLog log, TaskMonitor monitor) throws Exception { MessageLog log, TaskMonitor monitor) throws Exception {
MachoProgramBuilder machoProgramBuilder = new MachoProgramBuilder(program, provider, MachoProgramBuilder machoProgramBuilder =
fileBytes, log, monitor); new MachoProgramBuilder(program, provider, fileBytes, log, monitor);
machoProgramBuilder.build(); machoProgramBuilder.build();
} }
@ -339,8 +339,7 @@ public class MachoProgramBuilder {
* @param suffix An optional suffix that will get appended to tree segment and segment nodes * @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 * @throws Exception if there was a problem fixing up the Program Tree
*/ */
protected void fixupProgramTree(String suffix) protected void fixupProgramTree(String suffix) throws Exception {
throws Exception {
if (suffix == null) { if (suffix == null) {
suffix = ""; suffix = "";
} }
@ -501,7 +500,7 @@ public class MachoProgramBuilder {
} }
return !exports.isEmpty(); return !exports.isEmpty();
} }
protected void processNewExport(Address baseAddr, ExportEntry export, String name) protected void processNewExport(Address baseAddr, ExportEntry export, String name)
throws AddressOutOfBoundsException, Exception { throws AddressOutOfBoundsException, Exception {
@ -680,6 +679,10 @@ public class MachoProgramBuilder {
start, undefinedSymbols.size() * machoHeader.getAddressSize(), false); start, undefinedSymbols.size() * machoHeader.getAddressSize(), false);
// assume any value in external is writable. // assume any value in external is writable.
block.setWrite(true); block.setWrite(true);
// Mark block as an artificial fabrication
block.setArtificial(true);
block.setSourceName(BLOCK_SOURCE_NAME); block.setSourceName(BLOCK_SOURCE_NAME);
block.setComment( block.setComment(
"NOTE: This block is artificial and is used to make relocations work correctly"); "NOTE: This block is artificial and is used to make relocations work correctly");
@ -792,7 +795,8 @@ public class MachoProgramBuilder {
} }
} }
private void processBindings(BindingTable bindingTable, List<String> libraryPaths) throws Exception { private void processBindings(BindingTable bindingTable, List<String> libraryPaths)
throws Exception {
DataConverter converter = DataConverter.getInstance(program.getLanguage().isBigEndian()); DataConverter converter = DataConverter.getInstance(program.getLanguage().isBigEndian());
SymbolTable symbolTable = program.getSymbolTable(); SymbolTable symbolTable = program.getSymbolTable();
@ -1103,16 +1107,16 @@ public class MachoProgramBuilder {
} }
/** /**
* Processes the section relocations from all {@link Section}s. * Processes the section relocations from all {@link Section}s.
* *
* @throws CancelledException if the operation was cancelled. * @throws CancelledException if the operation was cancelled.
*/ */
protected void processSectionRelocations() throws CancelledException { protected void processSectionRelocations() throws CancelledException {
monitor.setMessage("Processing section relocations..."); monitor.setMessage("Processing section relocations...");
LinkedHashMap<RelocationInfo, Address> relocationMap = new LinkedHashMap<>(); LinkedHashMap<RelocationInfo, Address> relocationMap = new LinkedHashMap<>();
for (Section section : machoHeader.getAllSections()) { for (Section section : machoHeader.getAllSections()) {
monitor.checkCancelled(); monitor.checkCancelled();
MemoryBlock sectionMemoryBlock = getMemoryBlock(section); MemoryBlock sectionMemoryBlock = getMemoryBlock(section);
if (sectionMemoryBlock == null) { if (sectionMemoryBlock == null) {
@ -1124,54 +1128,54 @@ public class MachoProgramBuilder {
} }
for (RelocationInfo relocationInfo : section.getRelocations()) { for (RelocationInfo relocationInfo : section.getRelocations()) {
monitor.checkCancelled(); monitor.checkCancelled();
Address address = sectionMemoryBlock.getStart().add(relocationInfo.getAddress()); Address address = sectionMemoryBlock.getStart().add(relocationInfo.getAddress());
relocationMap.put(relocationInfo, address); relocationMap.put(relocationInfo, address);
} }
} }
performRelocations(relocationMap); performRelocations(relocationMap);
} }
/** /**
* Processes the external relocations from all {@link DynamicSymbolTableCommand}s. * Processes the external relocations from all {@link DynamicSymbolTableCommand}s.
* *
* @throws CancelledException if the operation was cancelled. * @throws CancelledException if the operation was cancelled.
*/ */
protected void processExternalRelocations() throws CancelledException { protected void processExternalRelocations() throws CancelledException {
monitor.setMessage("Processing external relocations..."); monitor.setMessage("Processing external relocations...");
LinkedHashMap<RelocationInfo, Address> relocationMap = new LinkedHashMap<>(); LinkedHashMap<RelocationInfo, Address> relocationMap = new LinkedHashMap<>();
for (DynamicSymbolTableCommand cmd : machoHeader for (DynamicSymbolTableCommand cmd : machoHeader
.getLoadCommands(DynamicSymbolTableCommand.class)) { .getLoadCommands(DynamicSymbolTableCommand.class)) {
monitor.checkCancelled(); monitor.checkCancelled();
for (RelocationInfo relocationInfo : cmd.getExternalRelocations()) { for (RelocationInfo relocationInfo : cmd.getExternalRelocations()) {
monitor.checkCancelled(); monitor.checkCancelled();
relocationMap.put(relocationInfo, space.getAddress(relocationInfo.getAddress())); relocationMap.put(relocationInfo, space.getAddress(relocationInfo.getAddress()));
} }
} }
performRelocations(relocationMap); performRelocations(relocationMap);
} }
/** /**
* Processes the local relocations from all {@link DynamicSymbolTableCommand}s. * Processes the local relocations from all {@link DynamicSymbolTableCommand}s.
* *
* @throws CancelledException if the operation was cancelled. * @throws CancelledException if the operation was cancelled.
*/ */
protected void processLocalRelocations() throws CancelledException { protected void processLocalRelocations() throws CancelledException {
monitor.setMessage("Processing local relocations..."); monitor.setMessage("Processing local relocations...");
LinkedHashMap<RelocationInfo, Address> relocationMap = new LinkedHashMap<>(); LinkedHashMap<RelocationInfo, Address> relocationMap = new LinkedHashMap<>();
for (DynamicSymbolTableCommand cmd : machoHeader for (DynamicSymbolTableCommand cmd : machoHeader
.getLoadCommands(DynamicSymbolTableCommand.class)) { .getLoadCommands(DynamicSymbolTableCommand.class)) {
monitor.checkCancelled(); monitor.checkCancelled();
for (RelocationInfo relocationInfo : cmd.getLocalRelocations()) { for (RelocationInfo relocationInfo : cmd.getLocalRelocations()) {
monitor.checkCancelled(); monitor.checkCancelled();
relocationMap.put(relocationInfo, space.getAddress(relocationInfo.getAddress())); relocationMap.put(relocationInfo, space.getAddress(relocationInfo.getAddress()));
} }
} }
performRelocations(relocationMap); performRelocations(relocationMap);
} }
protected List<String> processLibraries() throws Exception { protected List<String> processLibraries() throws Exception {
@ -1257,23 +1261,23 @@ public class MachoProgramBuilder {
* @throws CancelledException if the operation was cancelled. * @throws CancelledException if the operation was cancelled.
*/ */
private void performRelocations(LinkedHashMap<RelocationInfo, Address> relocationMap) private void performRelocations(LinkedHashMap<RelocationInfo, Address> relocationMap)
throws CancelledException { throws CancelledException {
if (relocationMap.isEmpty()) { if (relocationMap.isEmpty()) {
return; return;
} }
MachoRelocationHandler handler = MachoRelocationHandlerFactory.getHandler(machoHeader); MachoRelocationHandler handler = MachoRelocationHandlerFactory.getHandler(machoHeader);
if (handler == null) { if (handler == null) {
log.appendMsg(String.format("No relocation handler for machine type 0x%x", log.appendMsg(String.format("No relocation handler for machine type 0x%x",
machoHeader.getCpuType())); machoHeader.getCpuType()));
} }
Iterator<RelocationInfo> iter = relocationMap.keySet().iterator(); Iterator<RelocationInfo> iter = relocationMap.keySet().iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
RelocationInfo relocationInfo = iter.next(); RelocationInfo relocationInfo = iter.next();
Address address = relocationMap.get(relocationInfo); Address address = relocationMap.get(relocationInfo);
MachoRelocation relocation = null; MachoRelocation relocation = null;
RelocationResult result = RelocationResult.FAILURE; RelocationResult result = RelocationResult.FAILURE;
if (handler != null) { if (handler != null) {
@ -1281,7 +1285,7 @@ public class MachoProgramBuilder {
? new MachoRelocation(program, machoHeader, address, relocationInfo, ? new MachoRelocation(program, machoHeader, address, relocationInfo,
iter.next()) iter.next())
: new MachoRelocation(program, machoHeader, address, relocationInfo); : new MachoRelocation(program, machoHeader, address, relocationInfo);
try { try {
result = handler.relocate(relocation); result = handler.relocate(relocation);
if (result.status() == Status.UNSUPPORTED) { if (result.status() == Status.UNSUPPORTED) {
@ -1291,9 +1295,9 @@ public class MachoProgramBuilder {
} }
} }
catch (MemoryAccessException e) { catch (MemoryAccessException e) {
handleRelocationError(address, String.format( handleRelocationError(address, String.format(
"Relocation failure at address %s: error accessing memory.", address)); "Relocation failure at address %s: error accessing memory.", address));
} }
catch (RelocationException e) { catch (RelocationException e) {
handleRelocationError(address, String.format( handleRelocationError(address, String.format(
"Relocation failure at address %s: %s", address, e.getMessage())); "Relocation failure at address %s: %s", address, e.getMessage()));
@ -1306,13 +1310,14 @@ public class MachoProgramBuilder {
msg = String.format("Relocation failure at address %s: %s", address, msg); msg = String.format("Relocation failure at address %s: %s", address, msg);
handleRelocationError(address, msg); handleRelocationError(address, msg);
Msg.error(this, msg, e); Msg.error(this, msg, e);
} }
} }
program.getRelocationTable() program.getRelocationTable()
.add(address, result.status(), relocationInfo.getType(), .add(address, result.status(), relocationInfo.getType(),
new long[] { relocationInfo.getValue(), new long[] { relocationInfo.getValue(), relocationInfo.getLength(),
relocationInfo.getLength(), relocationInfo.isPcRelocated() ? 1 : 0, relocationInfo.isPcRelocated() ? 1 : 0,
relocationInfo.isExternal() ? 1 : 0, relocationInfo.isScattered() ? 1 : 0 }, relocationInfo.isExternal() ? 1 : 0,
relocationInfo.isScattered() ? 1 : 0 },
result.byteLength(), result.byteLength(),
relocation != null ? relocation.getTargetDescription() : null); relocation != null ? relocation.getTargetDescription() : null);
} }
@ -1338,10 +1343,10 @@ public class MachoProgramBuilder {
* @param message The error message * @param message The error message
*/ */
private void handleRelocationError(Address address, String message) { private void handleRelocationError(Address address, String message) {
program.getBookmarkManager() program.getBookmarkManager()
.setBookmark(address, BookmarkType.ERROR, "Relocations", message); .setBookmark(address, BookmarkType.ERROR, "Relocations", message);
log.appendMsg(message); log.appendMsg(message);
} }
private void addLibrary(String library) { private void addLibrary(String library) {
library = library.replaceAll(" ", "_"); library = library.replaceAll(" ", "_");

View file

@ -256,8 +256,8 @@ public class NeLoader extends AbstractOrdinalSupportLoader {
} }
MemoryBlock block; MemoryBlock block;
if (length > 0) { if (length > 0) {
block = MemoryBlockUtils.createInitializedBlock(program, false, block = MemoryBlockUtils.createInitializedBlock(program, false, name, addr,
name, addr, fileBytes, offset, length, "", "", r, w, x, log); fileBytes, offset, length, "", "", r, w, x, log);
if (length < minalloc) { if (length < minalloc) {
// Things actually rely on the block being padded out with real 0's, so we // Things actually rely on the block being padded out with real 0's, so we
// must expand it // must expand it
@ -354,8 +354,7 @@ public class NeLoader extends AbstractOrdinalSupportLoader {
int length = resource.getFileLengthShifted(); int length = resource.getFileLengthShifted();
if (length > 0) { if (length > 0) {
MemoryBlockUtils.createInitializedBlock(program, false, "Rsrc" + (id++), MemoryBlockUtils.createInitializedBlock(program, false, "Rsrc" + (id++),
addr, fileBytes, offset, length, "", "", true, addr, fileBytes, offset, length, "", "", true, false, false, log);
false, false, log);
} }
} }
catch (AddressOverflowException e) { catch (AddressOverflowException e) {
@ -445,8 +444,12 @@ public class NeLoader extends AbstractOrdinalSupportLoader {
String comment = ""; String comment = "";
String source = ""; String source = "";
// This isn't a real block, just place holder addresses, so don't create an initialized block // 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, MemoryBlock block = MemoryBlockUtils.createUninitializedBlock(program, false,
addr, length, comment, source, true, false, false, log); 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) { for (int i = 0; i < names.length; ++i) {
String moduleName = names[i].getString(); String moduleName = names[i].getString();

View file

@ -204,7 +204,7 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
int method, index, locationType = -1; int method, index, locationType = -1;
locAddress = null; locAddress = null;
if(fixup.getDataBlock() == null) { if (fixup.getDataBlock() == null) {
continue; // If no data block don't try to fixup continue; // If no data block don't try to fixup
} }
try { try {
@ -613,6 +613,9 @@ public class OmfLoader extends AbstractProgramWrapperLoader {
// assume any value in external is writable. // assume any value in external is writable.
block.setWrite(true); block.setWrite(true);
// Mark block as an artificial fabrication
block.setArtificial(true);
Address current = externalAddressStart; Address current = externalAddressStart;
while (current.compareTo(externalAddress) < 0) { while (current.compareTo(externalAddress) < 0) {
createUndefined(program.getListing(), program.getMemory(), current, createUndefined(program.getListing(), program.getMemory(), current,

View file

@ -52,8 +52,7 @@ class MemoryMapXmlMgr {
/////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////
void read(XmlPullParser parser, boolean overwriteConflicts, TaskMonitor monitor, void read(XmlPullParser parser, boolean overwriteConflicts, TaskMonitor monitor,
String directory) String directory) throws SAXParseException, FileNotFoundException, CancelledException {
throws SAXParseException, FileNotFoundException, CancelledException {
XmlElement element = parser.next(); XmlElement element = parser.next();
element = parser.next(); element = parser.next();
@ -71,8 +70,7 @@ class MemoryMapXmlMgr {
} }
private void processMemoryBlock(XmlElement memorySectionElement, XmlPullParser parser, private void processMemoryBlock(XmlElement memorySectionElement, XmlPullParser parser,
String directory, Program program, TaskMonitor monitor) String directory, Program program, TaskMonitor monitor) throws FileNotFoundException {
throws FileNotFoundException {
String name = memorySectionElement.getAttribute("NAME"); String name = memorySectionElement.getAttribute("NAME");
String addrStr = memorySectionElement.getAttribute("START_ADDR"); String addrStr = memorySectionElement.getAttribute("START_ADDR");
@ -91,6 +89,9 @@ class MemoryMapXmlMgr {
String volatility = memorySectionElement.getAttribute("VOLATILE"); String volatility = memorySectionElement.getAttribute("VOLATILE");
boolean isVolatile = "y".equals(volatility); boolean isVolatile = "y".equals(volatility);
String artificial = memorySectionElement.getAttribute("ARTIFICIAL");
boolean isArtificial = "y".equals(artificial);
String comment = memorySectionElement.getAttribute("COMMENT"); String comment = memorySectionElement.getAttribute("COMMENT");
try { try {
@ -124,12 +125,12 @@ class MemoryMapXmlMgr {
element = parser.peek();//get next start of contents or end of section element = parser.peek();//get next start of contents or end of section
} }
if (overlayName != null) { if (overlayName != null) {
MemoryBlock block = MemoryBlock block = MemoryBlockUtils.createInitializedBlock(program, true,
MemoryBlockUtils.createInitializedBlock(program, true, overlayName, addr, overlayName, addr, new ByteArrayInputStream(bytes), bytes.length, comment,
new ByteArrayInputStream(bytes), null, r, w, x, log, monitor);
bytes.length, comment, null, r, w, x, log, monitor);
if (block != null) { if (block != null) {
block.setVolatile(isVolatile); block.setVolatile(isVolatile);
block.setArtificial(isArtificial);
if (!name.equals(overlayName)) { if (!name.equals(overlayName)) {
block.setName(name); block.setName(name);
} }
@ -138,8 +139,8 @@ class MemoryMapXmlMgr {
else { else {
MemoryBlock block = MemoryBlockUtils.createInitializedBlock(program, false, MemoryBlock block = MemoryBlockUtils.createInitializedBlock(program, false,
name, addr, new ByteArrayInputStream(bytes), bytes.length, comment, null, name, addr, new ByteArrayInputStream(bytes), bytes.length, comment, null, r,
r, w, x, log, monitor); w, x, log, monitor);
if (block != null) { if (block != null) {
block.setVolatile(isVolatile); block.setVolatile(isVolatile);
} }
@ -297,6 +298,10 @@ class MemoryMapXmlMgr {
attrs.addAttribute("VOLATILE", true); attrs.addAttribute("VOLATILE", true);
} }
if (block.isArtificial()) {
attrs.addAttribute("ARTIFICIAL", true);
}
writer.startElement("MEMORY_SECTION", attrs); writer.startElement("MEMORY_SECTION", attrs);
if (block.getType() == MemoryBlockType.BIT_MAPPED) { if (block.getType() == MemoryBlockType.BIT_MAPPED) {

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -24,6 +23,7 @@ import ghidra.util.SystemUtilities;
*/ */
public class MemoryBlockDiff { public class MemoryBlockDiff {
//@formatter:off
public static final int NAME = 0x001; public static final int NAME = 0x001;
public static final int START_ADDRESS = 0x002; public static final int START_ADDRESS = 0x002;
public static final int END_ADDRESS = 0x004; public static final int END_ADDRESS = 0x004;
@ -32,11 +32,13 @@ public class MemoryBlockDiff {
public static final int WRITE = 0x020; public static final int WRITE = 0x020;
public static final int EXECUTE = 0x040; public static final int EXECUTE = 0x040;
public static final int VOLATILE = 0x080; public static final int VOLATILE = 0x080;
public static final int TYPE = 0x100; public static final int ARTIFICIAL = 0x100;
public static final int INIT = 0x200; public static final int TYPE = 0x200;
public static final int SOURCE = 0x400; public static final int INIT = 0x400;
public static final int COMMENT = 0x800; public static final int SOURCE = 0x800;
public static final int ALL = 0xFFF; public static final int COMMENT = 0x1000;
public static final int ALL = 0x1FFF;
//@formatter:on
private MemoryBlock block1; private MemoryBlock block1;
private MemoryBlock block2; private MemoryBlock block2;
@ -118,6 +120,13 @@ public class MemoryBlockDiff {
return (diffFlags & VOLATILE) != 0; 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. * Returns true if the type for the memory blocks differ.
*/ */
@ -151,40 +160,43 @@ public class MemoryBlockDiff {
*/ */
public String getDifferencesAsString() { public String getDifferencesAsString() {
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
if((diffFlags & NAME) != 0) { if ((diffFlags & NAME) != 0) {
buf.append("Name "); buf.append("Name ");
} }
if((diffFlags & START_ADDRESS) != 0) { if ((diffFlags & START_ADDRESS) != 0) {
buf.append("StartAddress "); buf.append("StartAddress ");
} }
if((diffFlags & END_ADDRESS) != 0) { if ((diffFlags & END_ADDRESS) != 0) {
buf.append("EndAddress "); buf.append("EndAddress ");
} }
if((diffFlags & SIZE) != 0) { if ((diffFlags & SIZE) != 0) {
buf.append("Size "); buf.append("Size ");
} }
if((diffFlags & READ) != 0) { if ((diffFlags & READ) != 0) {
buf.append("R "); buf.append("R ");
} }
if((diffFlags & WRITE) != 0) { if ((diffFlags & WRITE) != 0) {
buf.append("W "); buf.append("W ");
} }
if((diffFlags & EXECUTE) != 0) { if ((diffFlags & EXECUTE) != 0) {
buf.append("X "); buf.append("X ");
} }
if((diffFlags & VOLATILE) != 0) { if ((diffFlags & VOLATILE) != 0) {
buf.append("Volatile "); buf.append("Volatile ");
} }
if((diffFlags & TYPE) != 0) { if ((diffFlags & ARTIFICIAL) != 0) {
buf.append("Artificial ");
}
if ((diffFlags & TYPE) != 0) {
buf.append("Type "); buf.append("Type ");
} }
if((diffFlags & INIT) != 0) { if ((diffFlags & INIT) != 0) {
buf.append("Initialized "); buf.append("Initialized ");
} }
if((diffFlags & SOURCE) != 0) { if ((diffFlags & SOURCE) != 0) {
buf.append("Source "); buf.append("Source ");
} }
if((diffFlags & COMMENT) != 0) { if ((diffFlags & COMMENT) != 0) {
buf.append("Comment "); buf.append("Comment ");
} }
return buf.toString(); return buf.toString();
@ -209,7 +221,7 @@ public class MemoryBlockDiff {
} }
int flags = 0; int flags = 0;
if(!block1.getName().equals(block2.getName())) { if (!block1.getName().equals(block2.getName())) {
flags |= NAME; flags |= NAME;
} }
if (!block1.getStart().equals(block2.getStart())) { if (!block1.getStart().equals(block2.getStart())) {
@ -233,6 +245,9 @@ public class MemoryBlockDiff {
if (block1.isVolatile() != block2.isVolatile()) { if (block1.isVolatile() != block2.isVolatile()) {
flags |= VOLATILE; flags |= VOLATILE;
} }
if (block1.isArtificial() != block2.isArtificial()) {
flags |= ARTIFICIAL;
}
if (!block1.getType().equals(block2.getType())) { if (!block1.getType().equals(block2.getType())) {
flags |= TYPE; flags |= TYPE;
} }

View file

@ -46,8 +46,7 @@ public class MemoryDiff {
* @throws ProgramConflictException if the program memory can't be compared because the programs * @throws ProgramConflictException if the program memory can't be compared because the programs
* are based on different languages. * are based on different languages.
*/ */
public MemoryDiff(Program p1, Program p2) public MemoryDiff(Program p1, Program p2) throws ProgramConflictException {
throws ProgramConflictException {
program1 = p1; program1 = p1;
program2 = p2; program2 = p2;
memory1 = program1.getMemory(); memory1 = program1.getMemory();
@ -82,7 +81,7 @@ public class MemoryDiff {
ProgramMemoryComparator memComp = new ProgramMemoryComparator(program1, program2); ProgramMemoryComparator memComp = new ProgramMemoryComparator(program1, program2);
ArrayList<AddressRange> rangeList = new ArrayList<AddressRange>(); ArrayList<AddressRange> rangeList = new ArrayList<AddressRange>();
AddressRangeIterator rangeIter = memComp.getAddressRanges(); AddressRangeIterator rangeIter = memComp.getAddressRanges();
while(rangeIter.hasNext()) { while (rangeIter.hasNext()) {
rangeList.add(rangeIter.next()); rangeList.add(rangeIter.next());
} }
ranges = rangeList.toArray(new AddressRange[rangeList.size()]); ranges = rangeList.toArray(new AddressRange[rangeList.size()]);
@ -147,26 +146,26 @@ public class MemoryDiff {
/** /**
* Gets the index of the address range containing the indicated address, * Gets the index of the address range containing the indicated address,
* if it is contained in the list; * if it is contained in the list;
* otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>. * otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.
* @param address the address whose range we are interested in finding. * @param address the address whose range we are interested in finding.
* @return the index of the address range. * @return the index of the address range.
*/ */
private int getAddressRangeIndex(Address address) { private int getAddressRangeIndex(Address address) {
int low = 0; int low = 0;
int high = diffs.length-1; int high = diffs.length - 1;
while (low <= high) { while (low <= high) {
int mid = (low + high) >> 1; int mid = (low + high) >> 1;
AddressRange range = ranges[mid]; AddressRange range = ranges[mid];
if (range.contains(address)) { if (range.contains(address)) {
return mid; return mid;
} }
else if (address.compareTo(range.getMinAddress()) < 0) { else if (address.compareTo(range.getMinAddress()) < 0) {
high = mid - 1; high = mid - 1;
} }
else { else {
low = mid + 1; low = mid + 1;
} }
} }
return -(low + 1); // not found. return -(low + 1); // not found.
} }
@ -201,7 +200,7 @@ public class MemoryDiff {
else if (block2 == null) { else if (block2 == null) {
return false; return false;
} }
if(!block1.getName().equals(block2.getName())) { if (!block1.getName().equals(block2.getName())) {
return false; return false;
} }
if (!block1.getStart().equals(block2.getStart())) { if (!block1.getStart().equals(block2.getStart())) {
@ -213,7 +212,7 @@ public class MemoryDiff {
if (block1.getSize() != block2.getSize()) { if (block1.getSize() != block2.getSize()) {
return false; return false;
} }
if (block1.getPermissions() != block2.getPermissions()) { if (block1.getFlags() != block2.getFlags()) {
return false; return false;
} }
if (!block1.getType().equals(block2.getType())) { if (!block1.getType().equals(block2.getType())) {
@ -234,7 +233,6 @@ public class MemoryDiff {
return true; return true;
} }
public boolean merge(int row, int mergeFields, TaskMonitor monitor) { public boolean merge(int row, int mergeFields, TaskMonitor monitor) {
if ((mergeFields & MemoryBlockDiff.ALL) == 0) { if ((mergeFields & MemoryBlockDiff.ALL) == 0) {
return false; return false;
@ -246,8 +244,8 @@ public class MemoryDiff {
MemoryBlock block1 = blockDiff.getBlock1(); MemoryBlock block1 = blockDiff.getBlock1();
MemoryBlock block2 = blockDiff.getBlock2(); MemoryBlock block2 = blockDiff.getBlock2();
AddressRange range = ranges[row]; AddressRange range = ranges[row];
if (shouldMerge(mergeFields, MemoryBlockDiff.START_ADDRESS) if (shouldMerge(mergeFields, MemoryBlockDiff.START_ADDRESS) &&
&& blockDiff.isStartAddressDifferent()) { blockDiff.isStartAddressDifferent()) {
if (block1 == null) { if (block1 == null) {
// Add all or part of a block. // Add all or part of a block.
Address start2 = block2.getStart(); Address start2 = block2.getStart();
@ -271,7 +269,7 @@ public class MemoryDiff {
return true; return true;
} }
catch (Exception e) { catch (Exception e) {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e); Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
} }
return false; return false;
} }
@ -295,64 +293,63 @@ public class MemoryDiff {
memory1.removeBlock(blockToRemove, monitor); memory1.removeBlock(blockToRemove, monitor);
} }
return true; return true;
} catch (LockException e) { }
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e); catch (LockException e) {
} catch (NotFoundException e) { Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e); }
} catch (AddressOutOfBoundsException e) { catch (NotFoundException e) {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e); Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
} catch (MemoryBlockException e) { }
catch (AddressOutOfBoundsException e) {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
}
catch (MemoryBlockException e) {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e); Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
} }
return false; return false;
} }
} }
if (shouldMerge(mergeFields, MemoryBlockDiff.END_ADDRESS) if (shouldMerge(mergeFields, MemoryBlockDiff.END_ADDRESS) &&
&& blockDiff.isEndAddressDifferent()) { blockDiff.isEndAddressDifferent()) {
// TODO // TODO
} }
if (shouldMerge(mergeFields, MemoryBlockDiff.SIZE) if (shouldMerge(mergeFields, MemoryBlockDiff.SIZE) && blockDiff.isSizeDifferent()) {
&& blockDiff.isSizeDifferent()) {
// TODO // TODO
} }
if (shouldMerge(mergeFields, MemoryBlockDiff.TYPE) if (shouldMerge(mergeFields, MemoryBlockDiff.TYPE) && blockDiff.isTypeDifferent()) {
&& blockDiff.isTypeDifferent()) {
// TODO // TODO
} }
if (shouldMerge(mergeFields, MemoryBlockDiff.INIT) if (shouldMerge(mergeFields, MemoryBlockDiff.INIT) && blockDiff.isInitDifferent()) {
&& blockDiff.isInitDifferent()) {
// TODO // TODO
} }
if (shouldMerge(mergeFields, MemoryBlockDiff.NAME) if (shouldMerge(mergeFields, MemoryBlockDiff.NAME) && blockDiff.isNameDifferent()) {
&& blockDiff.isNameDifferent()) {
try { try {
block1.setName(block2.getName()); 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) if (shouldMerge(mergeFields, MemoryBlockDiff.READ) && blockDiff.isReadDifferent()) {
&& blockDiff.isReadDifferent()) {
block1.setRead(block2.isRead()); block1.setRead(block2.isRead());
} }
if (shouldMerge(mergeFields, MemoryBlockDiff.WRITE) if (shouldMerge(mergeFields, MemoryBlockDiff.WRITE) && blockDiff.isWriteDifferent()) {
&& blockDiff.isWriteDifferent()) {
block1.setWrite(block2.isWrite()); block1.setWrite(block2.isWrite());
} }
if (shouldMerge(mergeFields, MemoryBlockDiff.EXECUTE) if (shouldMerge(mergeFields, MemoryBlockDiff.EXECUTE) && blockDiff.isExecDifferent()) {
&& blockDiff.isExecDifferent()) {
block1.setExecute(block2.isExecute()); block1.setExecute(block2.isExecute());
} }
if (shouldMerge(mergeFields, MemoryBlockDiff.VOLATILE) if (shouldMerge(mergeFields, MemoryBlockDiff.VOLATILE) && blockDiff.isVolatileDifferent()) {
&& blockDiff.isVolatileDifferent()) {
block1.setVolatile(block2.isVolatile()); block1.setVolatile(block2.isVolatile());
} }
if (shouldMerge(mergeFields, MemoryBlockDiff.SOURCE) if (shouldMerge(mergeFields, MemoryBlockDiff.ARTIFICIAL) &&
&& blockDiff.isSourceDifferent()) { blockDiff.isArtificialDifferent()) {
block1.setArtificial(block2.isArtificial());
}
if (shouldMerge(mergeFields, MemoryBlockDiff.SOURCE) && blockDiff.isSourceDifferent()) {
block1.setSourceName(block2.getSourceName()); block1.setSourceName(block2.getSourceName());
} }
if (shouldMerge(mergeFields, MemoryBlockDiff.COMMENT) if (shouldMerge(mergeFields, MemoryBlockDiff.COMMENT) && blockDiff.isCommentDifferent()) {
&& blockDiff.isCommentDifferent()) {
block1.setComment(block2.getComment()); block1.setComment(block2.getComment());
} }
return true; return true;

View file

@ -111,6 +111,7 @@ public class MemoryTypeProgramLocationBasedTableColumn
updateForWrite(block, buffy, tooltipBuffy); updateForWrite(block, buffy, tooltipBuffy);
updateForExecute(block, buffy, tooltipBuffy); updateForExecute(block, buffy, tooltipBuffy);
updateForVolatile(block, buffy, tooltipBuffy); updateForVolatile(block, buffy, tooltipBuffy);
updateForArtificial(block, buffy, tooltipBuffy);
} }
private void updateForVolatile(MemoryBlock block, StringBuilder buffy, private void updateForVolatile(MemoryBlock block, StringBuilder buffy,
@ -128,6 +129,21 @@ public class MemoryTypeProgramLocationBasedTableColumn
tooltipBuffy.append(HTMLUtilities.spaces(2)).append("Volatile<br>"); tooltipBuffy.append(HTMLUtilities.spaces(2)).append("Volatile<br>");
} }
private void updateForArtificial(MemoryBlock block, StringBuilder buffy,
StringBuilder tooltipBuffy) {
if (block.isArtificial()) {
buffy.append("<b>A</b>");
tooltipBuffy.append("<image src=\"" + onIcon.getUrl() + "\">");
}
else {
buffy.append(HTMLUtilities.colorString(disabledColor, "A"));
tooltipBuffy.append("<image src=\"" + offIcon.getUrl() + "\">");
}
tooltipBuffy.append(HTMLUtilities.spaces(2)).append("Artificial<br>");
}
private void updateForExecute(MemoryBlock block, StringBuilder buffy, private void updateForExecute(MemoryBlock block, StringBuilder buffy,
StringBuilder tooltipBuffy) { StringBuilder tooltipBuffy) {
@ -186,7 +202,7 @@ public class MemoryTypeProgramLocationBasedTableColumn
private class MemoryTypeComparator implements Comparator<MemoryBlock> { private class MemoryTypeComparator implements Comparator<MemoryBlock> {
@Override @Override
public int compare(MemoryBlock o1, MemoryBlock o2) { public int compare(MemoryBlock o1, MemoryBlock o2) {
return o1.getPermissions() - o2.getPermissions(); return o1.getFlags() - o2.getFlags();
} }
} }
} }

View file

@ -66,6 +66,7 @@
<!ATTLIST MEMORY_SECTION LENGTH CDATA #REQUIRED> <!ATTLIST MEMORY_SECTION LENGTH CDATA #REQUIRED>
<!ATTLIST MEMORY_SECTION PERMISSIONS (r | w | x | rw | rx | wx | rwx) #IMPLIED> <!ATTLIST MEMORY_SECTION PERMISSIONS (r | w | x | rw | rx | wx | rwx) #IMPLIED>
<!ATTLIST MEMORY_SECTION VOLATILE (y | n) #IMPLIED> <!ATTLIST MEMORY_SECTION VOLATILE (y | n) #IMPLIED>
<!ATTLIST MEMORY_SECTION ARTIFICIAL (y | n) #IMPLIED>
<!ATTLIST MEMORY_SECTION COMMENT CDATA #IMPLIED> <!ATTLIST MEMORY_SECTION COMMENT CDATA #IMPLIED>
<!ELEMENT MEMORY_CONTENTS EMPTY> <!ELEMENT MEMORY_CONTENTS EMPTY>

View file

@ -269,6 +269,7 @@ public class MemoryMergeManagerTest extends AbstractMergeTest {
assertTrue(!blocks[4].isWrite()); assertTrue(!blocks[4].isWrite());
assertTrue(!blocks[4].isExecute()); assertTrue(!blocks[4].isExecute());
assertTrue(!blocks[4].isVolatile()); assertTrue(!blocks[4].isVolatile());
assertTrue(!blocks[4].isArtificial());
} }
@Test @Test

View file

@ -239,6 +239,12 @@ public class MemoryManagerTest extends AbstractGhidraHeadedIntegrationTest {
assertEquals("Hello", block1.getComment()); assertEquals("Hello", block1.getComment());
assertEquals(block1, mem.getBlock(addr(5))); assertEquals(block1, mem.getBlock(addr(5)));
block1.setArtificial(false);
assertTrue(!block1.isArtificial());
block1.setArtificial(true);
assertTrue(block1.isArtificial());
block1.setVolatile(false); block1.setVolatile(false);
assertTrue(!block1.isVolatile()); assertTrue(!block1.isVolatile());
@ -473,6 +479,7 @@ public class MemoryManagerTest extends AbstractGhidraHeadedIntegrationTest {
assertNotNull(newBlock); assertNotNull(newBlock);
assertEquals(block.getName() + ".copy", newBlock.getName()); assertEquals(block.getName() + ".copy", newBlock.getName());
assertEquals(addr(500), newBlock.getStart()); assertEquals(addr(500), newBlock.getStart());
assertEquals(block.isArtificial(), newBlock.isArtificial());
assertEquals(block.isVolatile(), newBlock.isVolatile()); assertEquals(block.isVolatile(), newBlock.isVolatile());
assertEquals(block.isExecute(), newBlock.isExecute()); assertEquals(block.isExecute(), newBlock.isExecute());
assertEquals(block.isRead(), newBlock.isRead()); assertEquals(block.isRead(), newBlock.isRead());

View file

@ -32,7 +32,7 @@ class MyTestMemoryBlock implements MemoryBlock {
} }
@Override @Override
public int getPermissions() { public int getFlags() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -136,6 +136,16 @@ class MyTestMemoryBlock implements MemoryBlock {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public boolean isArtificial() {
throw new UnsupportedOperationException();
}
@Override
public void setArtificial(boolean a) {
throw new UnsupportedOperationException();
}
@Override @Override
public String getSourceName() { public String getSourceName() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();

View file

@ -30,10 +30,12 @@ public class ExtMemoryMap implements IsfObject {
String kind; String kind;
String comment; String comment;
boolean isVolatile; boolean isVolatile;
boolean isArtificial;
String type; String type;
String location; 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 = ""; String permissions = "";
if (block.isRead()) { if (block.isRead()) {
@ -54,12 +56,17 @@ public class ExtMemoryMap implements IsfObject {
if (block.isVolatile()) { if (block.isVolatile()) {
isVolatile = true; isVolatile = true;
} }
if (block.isArtificial()) {
isArtificial = true;
}
type = block.getType().name(); 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 // bit mapped blocks can only have one sub-block
MemoryBlockSourceInfo info = block.getSourceInfos().get(0); MemoryBlockSourceInfo info = block.getSourceInfos().get(0);
location = info.getMappedRange().get().getMinAddress().toString(); location = info.getMappedRange().get().getMinAddress().toString();
} else if (block.isInitialized() && write) { }
else if (block.isInitialized() && write) {
location = bf.getFileName() + ":" + bf.getOffset(); location = bf.getFileName() + ":" + bf.getOffset();
bf.writeBytes(range); bf.writeBytes(range);
} }

View file

@ -68,26 +68,27 @@ public class MemoryMapSarifMgr extends SarifMgr {
//////////////////////////// ////////////////////////////
@Override @Override
public boolean read(Map<String, Object> result, SarifProgramOptions options, TaskMonitor monitor) public boolean read(Map<String, Object> result, SarifProgramOptions options,
throws CancelledException { TaskMonitor monitor) throws CancelledException {
try { try {
processMemoryBlock(result, programMgr.getDirectory(), program, monitor); processMemoryBlock(result, programMgr.getDirectory(), program, monitor);
return true; return true;
} catch (FileNotFoundException | AddressOverflowException e) { }
catch (FileNotFoundException | AddressOverflowException e) {
log.appendException(e); log.appendException(e);
} }
return false; return false;
} }
private void processMemoryBlock(Map<String, Object> result, String directory, Program program, TaskMonitor monitor) private void processMemoryBlock(Map<String, Object> result, String directory, Program program,
throws FileNotFoundException, AddressOverflowException { TaskMonitor monitor) throws FileNotFoundException, AddressOverflowException {
String name = (String) result.get("name"); String name = (String) result.get("name");
AddressSet set = SarifUtils.getLocations(result, program, null); AddressSet set = SarifUtils.getLocations(result, program, null);
Address blockAddress = set.getMinAddress(); Address blockAddress = set.getMinAddress();
if (set.getNumAddressRanges() != 1) { if (set.getNumAddressRanges() != 1) {
throw new RuntimeException( throw new RuntimeException("Unexpected number of ranges for block @ " + blockAddress +
"Unexpected number of ranges for block @ " + blockAddress + ": " + set.getNumAddressRanges()); ": " + set.getNumAddressRanges());
} }
int length = (int) set.getMaxAddress().subtract(blockAddress) + 1; int length = (int) set.getMaxAddress().subtract(blockAddress) + 1;
@ -100,6 +101,7 @@ public class MemoryMapSarifMgr extends SarifMgr {
boolean x = permissions.indexOf("x") >= 0; boolean x = permissions.indexOf("x") >= 0;
boolean isVolatile = (boolean) result.get("isVolatile"); boolean isVolatile = (boolean) result.get("isVolatile");
boolean isArtificial = (boolean) result.get("isArtificial");
String comment = (String) result.get("comment"); String comment = (String) result.get("comment");
String type = (String) result.get("type"); String type = (String) result.get("type");
@ -110,33 +112,41 @@ public class MemoryMapSarifMgr extends SarifMgr {
MemoryBlock block = null; MemoryBlock block = null;
if (type.equals("DEFAULT")) { if (type.equals("DEFAULT")) {
if (loc == null) { if (loc == null) {
block = MemoryBlockUtils.createUninitializedBlock(program, false, name, blockAddress, length, block = MemoryBlockUtils.createUninitializedBlock(program, false, name,
comment, null, r, w, x, log); blockAddress, length, comment, null, r, w, x, log);
} else { }
else {
String[] split = loc.split(":"); String[] split = loc.split(":");
String fileName = split[0]; String fileName = split[0];
int fileOffset = Integer.parseInt(split[1]); int fileOffset = Integer.parseInt(split[1]);
byte[] bytes = setData(directory, fileName, fileOffset, length, log); byte[] bytes = setData(directory, fileName, fileOffset, length, log);
block = MemoryBlockUtils.createInitializedBlock(program, false, name, blockAddress, block = MemoryBlockUtils.createInitializedBlock(program, false, name,
new ByteArrayInputStream(bytes), bytes.length, comment, null, r, w, x, log, monitor); 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); Address sourceAddr = factory.getAddress(loc);
block = MemoryBlockUtils.createBitMappedBlock(program, name, blockAddress, sourceAddr, length, comment, block = MemoryBlockUtils.createBitMappedBlock(program, name, blockAddress,
comment, r, w, x, false, log); sourceAddr, length, comment, comment, r, w, x, false, log);
} else if (type.equals("BYTE_MAPPED")) { }
else if (type.equals("BYTE_MAPPED")) {
Address sourceAddr = factory.getAddress(loc); Address sourceAddr = factory.getAddress(loc);
block = MemoryBlockUtils.createByteMappedBlock(program, name, blockAddress, sourceAddr, length, comment, block = MemoryBlockUtils.createByteMappedBlock(program, name, blockAddress,
comment, r, w, x, false, log); sourceAddr, length, comment, comment, r, w, x, false, log);
} else { }
else {
throw new RuntimeException("Unexpected type value - " + type); throw new RuntimeException("Unexpected type value - " + type);
} }
if (block != null) { if (block != null) {
block.setVolatile(isVolatile); block.setVolatile(isVolatile);
block.setArtificial(isArtificial);
} }
} catch (FileNotFoundException e) { }
catch (FileNotFoundException e) {
throw e; throw e;
} catch (Exception e) { }
catch (Exception e) {
log.appendException(e); log.appendException(e);
} }
} }
@ -160,7 +170,8 @@ public class MemoryMapSarifMgr extends SarifMgr {
} }
pos += readLen; pos += readLen;
} }
} catch (IndexOutOfBoundsException e) { }
catch (IndexOutOfBoundsException e) {
log.appendMsg("Read exceeded array length " + length); log.appendMsg("Read exceeded array length " + length);
} }
return bytes; return bytes;
@ -170,8 +181,8 @@ public class MemoryMapSarifMgr extends SarifMgr {
// SARIF WRITE CURRENT DTD // // SARIF WRITE CURRENT DTD //
///////////////////////////// /////////////////////////////
void write(JsonArray results, AddressSetView addrs, TaskMonitor monitor, boolean isWriteContents, String filePath) void write(JsonArray results, AddressSetView addrs, TaskMonitor monitor,
throws IOException, CancelledException { boolean isWriteContents, String filePath) throws IOException, CancelledException {
monitor.setMessage("Writing MEMORY MAP ..."); monitor.setMessage("Writing MEMORY MAP ...");
List<Pair<AddressRange, MemoryBlock>> request = new ArrayList<>(); List<Pair<AddressRange, MemoryBlock>> request = new ArrayList<>();
@ -179,7 +190,8 @@ public class MemoryMapSarifMgr extends SarifMgr {
while (iter.hasNext()) { while (iter.hasNext()) {
monitor.checkCancelled(); monitor.checkCancelled();
AddressRange ranges = iter.next(); 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) { for (int i = 0; i < rb.getRanges().length; ++i) {
AddressRange range = rb.getRanges()[i]; AddressRange range = rb.getRanges()[i];
MemoryBlock block = rb.getBlocks()[i]; MemoryBlock block = rb.getBlocks()[i];
@ -190,16 +202,19 @@ public class MemoryMapSarifMgr extends SarifMgr {
try { try {
bf = isWriteContents ? new MemoryMapBytesFile(program, filePath) : null; bf = isWriteContents ? new MemoryMapBytesFile(program, filePath) : null;
writeAsSARIF(request, bf, isWriteContents, results); writeAsSARIF(request, bf, isWriteContents, results);
} finally { }
finally {
if (isWriteContents) { if (isWriteContents) {
bf.close(); bf.close();
} }
} }
} }
public static void writeAsSARIF(List<Pair<AddressRange, MemoryBlock>> request, MemoryMapBytesFile bytes, public static void writeAsSARIF(List<Pair<AddressRange, MemoryBlock>> request,
boolean isWriteContents, JsonArray results) throws IOException { MemoryMapBytesFile bytes, boolean isWriteContents, JsonArray results)
SarifMemoryMapWriter writer = new SarifMemoryMapWriter(request, null, bytes, isWriteContents); throws IOException {
SarifMemoryMapWriter writer =
new SarifMemoryMapWriter(request, null, bytes, isWriteContents);
new TaskLauncher(new SarifWriterTask(SUBKEY, writer, results), null); new TaskLauncher(new SarifWriterTask(SUBKEY, writer, results), null);
} }

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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()); sourceProgram.getMemory().getBlock(destBlocks[i].getName());
if (matchingABlock != null) { if (matchingABlock != null) {
numMatchingNames++; numMatchingNames++;
int sourcePerm = matchingABlock.getPermissions(); int sourceFlags = matchingABlock.getFlags();
if (sourcePerm == destBlocks[i].getPermissions()) { if (sourceFlags == destBlocks[i].getFlags()) {
numMatches++; numMatches++;
} }
else { else {
warnings.append("Block " + destProgName + ":" + blockName + warnings.append("Block " + destProgName + ":" + blockName +
" doesn't match permissions of " + sourceProgName + ":" + blockName + "\n"); " has different flags than " + sourceProgName + ":" + blockName + "\n");
status = ConditionStatus.Warning; status = ConditionStatus.Warning;
} }
} }
@ -102,10 +101,12 @@ public class MemoryBlocksValidator extends VTPreconditionValidator {
} }
} }
if (numMatchingNames == numBlocksNeededForPerfectMatch) { 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 { 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()); return new ConditionResult(status, warnings.toString());

View file

@ -47,7 +47,7 @@ public class MemoryBlockDefinition {
private boolean readPermission = true; private boolean readPermission = true;
private boolean writePermission = true; private boolean writePermission = true;
private boolean executePermission = false; private boolean executePermission = false;
private boolean volatilePermission = false; private boolean isVolatile = false;
/** /**
* Construct <code>MemoryBlockDefinition</code> using a text-based specified. * Construct <code>MemoryBlockDefinition</code> using a text-based specified.
@ -107,7 +107,7 @@ public class MemoryBlockDefinition {
readPermission = mode.indexOf('r') >= 0; readPermission = mode.indexOf('r') >= 0;
writePermission = mode.indexOf('w') >= 0; writePermission = mode.indexOf('w') >= 0;
executePermission = mode.indexOf('x') >= 0; executePermission = mode.indexOf('x') >= 0;
volatilePermission = mode.indexOf('v') >= 0; isVolatile = mode.indexOf('v') >= 0;
} }
try { try {
length = XmlUtilities.parseInt(lengthString); length = XmlUtilities.parseInt(lengthString);
@ -186,7 +186,7 @@ public class MemoryBlockDefinition {
block.setRead(readPermission); block.setRead(readPermission);
block.setWrite(writePermission); block.setWrite(writePermission);
block.setExecute(executePermission); block.setExecute(executePermission);
block.setVolatile(volatilePermission); block.setVolatile(isVolatile);
} }
@Override @Override

View file

@ -117,8 +117,8 @@ public class MemoryBlockDB implements MemoryBlock {
} }
@Override @Override
public int getPermissions() { public int getFlags() {
return record.getByteValue(MemoryMapDBAdapter.PERMISSIONS_COL); return record.getByteValue(MemoryMapDBAdapter.FLAGS_COL);
} }
@Override @Override
@ -224,7 +224,7 @@ public class MemoryBlockDB implements MemoryBlock {
@Override @Override
public boolean isRead() { public boolean isRead() {
return (record.getByteValue(MemoryMapDBAdapter.PERMISSIONS_COL) & READ) != 0; return (record.getByteValue(MemoryMapDBAdapter.FLAGS_COL) & READ) != 0;
} }
@Override @Override
@ -232,8 +232,9 @@ public class MemoryBlockDB implements MemoryBlock {
memMap.lock.acquire(); memMap.lock.acquire();
try { try {
checkValid(); checkValid();
setPermissionBit(READ, r); if (setFlagBit(READ, r)) {
memMap.fireBlockChanged(this); memMap.fireBlockChanged(this);
}
} }
finally { finally {
memMap.lock.release(); memMap.lock.release();
@ -242,7 +243,7 @@ public class MemoryBlockDB implements MemoryBlock {
@Override @Override
public boolean isWrite() { public boolean isWrite() {
return (record.getByteValue(MemoryMapDBAdapter.PERMISSIONS_COL) & WRITE) != 0; return (record.getByteValue(MemoryMapDBAdapter.FLAGS_COL) & WRITE) != 0;
} }
@Override @Override
@ -250,8 +251,9 @@ public class MemoryBlockDB implements MemoryBlock {
memMap.lock.acquire(); memMap.lock.acquire();
try { try {
checkValid(); checkValid();
setPermissionBit(WRITE, w); if (setFlagBit(WRITE, w)) {
memMap.fireBlockChanged(this); memMap.fireBlockChanged(this);
}
} }
finally { finally {
memMap.lock.release(); memMap.lock.release();
@ -260,7 +262,7 @@ public class MemoryBlockDB implements MemoryBlock {
@Override @Override
public boolean isExecute() { public boolean isExecute() {
return (record.getByteValue(MemoryMapDBAdapter.PERMISSIONS_COL) & EXECUTE) != 0; return (record.getByteValue(MemoryMapDBAdapter.FLAGS_COL) & EXECUTE) != 0;
} }
@Override @Override
@ -268,9 +270,10 @@ public class MemoryBlockDB implements MemoryBlock {
memMap.lock.acquire(); memMap.lock.acquire();
try { try {
checkValid(); checkValid();
setPermissionBit(EXECUTE, x); if (setFlagBit(EXECUTE, x)) {
memMap.blockExecuteChanged(this); memMap.blockExecuteChanged(this);
memMap.fireBlockChanged(this); memMap.fireBlockChanged(this);
}
} }
finally { finally {
memMap.lock.release(); memMap.lock.release();
@ -282,11 +285,13 @@ public class MemoryBlockDB implements MemoryBlock {
memMap.lock.acquire(); memMap.lock.acquire();
try { try {
checkValid(); checkValid();
setPermissionBit(READ, read); boolean changed = setFlagBit(READ, read);
setPermissionBit(WRITE, write); changed |= setFlagBit(WRITE, write);
setPermissionBit(EXECUTE, execute); changed |= setFlagBit(EXECUTE, execute);
memMap.blockExecuteChanged(this); if (changed) {
memMap.fireBlockChanged(this); memMap.blockExecuteChanged(this);
memMap.fireBlockChanged(this);
}
} }
finally { finally {
memMap.lock.release(); memMap.lock.release();
@ -295,7 +300,7 @@ public class MemoryBlockDB implements MemoryBlock {
@Override @Override
public boolean isVolatile() { public boolean isVolatile() {
return (record.getByteValue(MemoryMapDBAdapter.PERMISSIONS_COL) & VOLATILE) != 0; return (record.getByteValue(MemoryMapDBAdapter.FLAGS_COL) & VOLATILE) != 0;
} }
@Override @Override
@ -303,8 +308,28 @@ public class MemoryBlockDB implements MemoryBlock {
memMap.lock.acquire(); memMap.lock.acquire();
try { try {
checkValid(); checkValid();
setPermissionBit(VOLATILE, v); if (setFlagBit(VOLATILE, v)) {
memMap.fireBlockChanged(this); 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 { finally {
memMap.lock.release(); memMap.lock.release();
@ -430,21 +455,28 @@ public class MemoryBlockDB implements MemoryBlock {
} }
} }
private void setPermissionBit(int permBitMask, boolean enable) { private boolean setFlagBit(int flagBitMask, boolean enable) {
byte p = record.getByteValue(MemoryMapDBAdapter.PERMISSIONS_COL); byte p = record.getByteValue(MemoryMapDBAdapter.FLAGS_COL);
if (enable) { if (enable) {
p |= permBitMask; if ((p & flagBitMask) == flagBitMask) {
return false; // no change
}
p |= flagBitMask;
} }
else { 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 { try {
adapter.updateBlockRecord(record); adapter.updateBlockRecord(record);
} }
catch (IOException e) { catch (IOException e) {
memMap.dbError(e); memMap.dbError(e);
} }
return true;
} }
@Override @Override
@ -634,8 +666,7 @@ public class MemoryBlockDB implements MemoryBlock {
splitBlocks.addAll(subList); splitBlocks.addAll(subList);
subList.clear(); subList.clear();
} }
return adapter.createBlock(getName() + ".split", addr, newLength, getPermissions(), return adapter.createBlock(getName() + ".split", addr, newLength, getFlags(), splitBlocks);
splitBlocks);
} }
private int getIndexOfSubBlockToSplit(long offset) { private int getIndexOfSubBlockToSplit(long offset) {

View file

@ -901,7 +901,7 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
mappedAddr = info.getMappedRange().get().getMinAddress(); mappedAddr = info.getMappedRange().get().getMinAddress();
} }
MemoryBlockDB newBlock = adapter.createBlock(block.getType(), name, start, length, 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()); allAddrSet.add(newBlock.getStart(), newBlock.getEnd());
initializeBlocks(); initializeBlocks();
fireBlockAdded(newBlock); fireBlockAdded(newBlock);

View file

@ -35,7 +35,7 @@ abstract class MemoryMapDBAdapter {
static final int NAME_COL = MemoryMapDBAdapterV3.V3_NAME_COL; static final int NAME_COL = MemoryMapDBAdapterV3.V3_NAME_COL;
static final int COMMENTS_COL = MemoryMapDBAdapterV3.V3_COMMENTS_COL; static final int COMMENTS_COL = MemoryMapDBAdapterV3.V3_COMMENTS_COL;
static final int SOURCE_COL = MemoryMapDBAdapterV3.V3_SOURCE_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 START_ADDR_COL = MemoryMapDBAdapterV3.V3_START_ADDR_COL;
static final int LENGTH_COL = MemoryMapDBAdapterV3.V3_LENGTH_COL; static final int LENGTH_COL = MemoryMapDBAdapterV3.V3_LENGTH_COL;
static final int SEGMENT_COL = MemoryMapDBAdapterV3.V3_SEGMENT_COL; static final int SEGMENT_COL = MemoryMapDBAdapterV3.V3_SEGMENT_COL;
@ -130,7 +130,7 @@ abstract class MemoryMapDBAdapter {
if (block.isInitialized()) { if (block.isInitialized()) {
DBBuffer buf = block.getBuffer(); DBBuffer buf = block.getBuffer();
newBlock = newAdapter.createInitializedBlock(block.getName(), block.getStart(), newBlock = newAdapter.createInitializedBlock(block.getName(), block.getStart(),
buf, block.getPermissions()); buf, block.getFlags());
} }
else { else {
Address mappedAddress = null; Address mappedAddress = null;
@ -141,7 +141,7 @@ abstract class MemoryMapDBAdapter {
} }
newBlock = newBlock =
newAdapter.createBlock(block.getType(), block.getName(), block.getStart(), 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.setComment(block.getComment());
newBlock.setSourceName(block.getSourceName()); newBlock.setSourceName(block.getSourceName());
@ -185,26 +185,26 @@ abstract class MemoryMapDBAdapter {
* @param startAddr the start address of the block. * @param startAddr the start address of the block.
* @param is data source or null for zero initialization * @param is data source or null for zero initialization
* @param length size of block * @param length size of block
* @param permissions the new block permissions * @param flags the new block flags
* @return new memory block * @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 * @throws AddressOverflowException if block length is too large for the underlying space
*/ */
abstract MemoryBlockDB createInitializedBlock(String name, Address startAddr, InputStream is, 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 * Creates a new initialized block object
* @param name the name of the block * @param name the name of the block
* @param startAddr the start address of the block. * @param startAddr the start address of the block.
* @param buf the DBBuffer used to hold the bytes for 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 * @return new memory block
* @throws IOException if a database IO error occurs. * @throws IOException if a database IO error occurs.
* @throws AddressOverflowException if block length is too large for the underlying space * @throws AddressOverflowException if block length is too large for the underlying space
*/ */
abstract MemoryBlockDB createInitializedBlock(String name, Address startAddr, DBBuffer buf, 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. * 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) * the block. (used for bit/byte-mapped blocks only)
* @param initializeBytes if true, creates a database buffer for storing the * @param initializeBytes if true, creates a database buffer for storing the
* bytes in the block (applies to initialized default blocks only) * 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) * @param encodedMappingScheme byte mapping scheme (used by byte-mapped blocks only)
* @return new memory block * @return new memory block
* @throws IOException if a database IO error occurs. * @throws IOException if a database IO error occurs.
* @throws AddressOverflowException if block length is too large for the underlying space * @throws AddressOverflowException if block length is too large for the underlying space
*/ */
abstract MemoryBlockDB createBlock(MemoryBlockType blockType, String name, Address startAddr, 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; int encodedMappingScheme) throws AddressOverflowException, IOException;
/** /**
@ -289,13 +289,13 @@ abstract class MemoryMapDBAdapter {
* @param name the name of the block * @param name the name of the block
* @param startAddress the start address of the block * @param startAddress the start address of the block
* @param length the length 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 * @param splitBlocks the list of subBlock objects that make up this block
* @return the new MemoryBlock * @return the new MemoryBlock
* @throws IOException if a database error occurs * @throws IOException if a database error occurs
*/ */
protected abstract MemoryBlockDB createBlock(String name, Address startAddress, long length, protected abstract MemoryBlockDB createBlock(String name, Address startAddress, long length,
int permissions, List<SubMemoryBlock> splitBlocks) throws IOException; int flags, List<SubMemoryBlock> splitBlocks) throws IOException;
/** /**
* Creates a new memory block using a FileBytes * Creates a new memory block using a FileBytes
@ -304,12 +304,12 @@ abstract class MemoryMapDBAdapter {
* @param length the length of the block * @param length the length of the block
* @param fileBytes the {@link FileBytes} object that provides the bytes for this block * @param fileBytes the {@link FileBytes} object that provides the bytes for this block
* @param offset the offset into the {@link FileBytes} object * @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 * @return the new MemoryBlock
* @throws IOException if a database error occurs * @throws IOException if a database error occurs
* @throws AddressOverflowException if block length is too large for the underlying space * @throws AddressOverflowException if block length is too large for the underlying space
*/ */
protected abstract MemoryBlockDB createFileBytesBlock(String name, Address startAddress, 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; throws IOException, AddressOverflowException;
} }

View file

@ -106,15 +106,15 @@ class MemoryMapDBAdapterV0 extends MemoryMapDBAdapter {
RecordIterator it = table.iterator(); RecordIterator it = table.iterator();
while (it.hasNext()) { while (it.hasNext()) {
DBRecord rec = it.next(); DBRecord rec = it.next();
int permissions = 0; int flags = 0;
if (rec.getBooleanValue(V0_IS_READ_COL)) { if (rec.getBooleanValue(V0_IS_READ_COL)) {
permissions |= MemoryBlock.READ; flags |= MemoryBlock.READ;
} }
if (rec.getBooleanValue(V0_IS_WRITE_COL)) { if (rec.getBooleanValue(V0_IS_WRITE_COL)) {
permissions |= MemoryBlock.WRITE; flags |= MemoryBlock.WRITE;
} }
if (rec.getBooleanValue(V0_IS_EXECUTE_COL)) { if (rec.getBooleanValue(V0_IS_EXECUTE_COL)) {
permissions |= MemoryBlock.EXECUTE; flags |= MemoryBlock.EXECUTE;
} }
Address start = addrFactory.oldGetAddressFromLong(rec.getLongValue(V0_START_ADDR_COL)); Address start = addrFactory.oldGetAddressFromLong(rec.getLongValue(V0_START_ADDR_COL));
long startAddr = addrMap.getKey(start, false); 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(NAME_COL, rec.getString(V0_NAME_COL));
blockRecord.setString(COMMENTS_COL, rec.getString(V0_COMMENTS_COL)); blockRecord.setString(COMMENTS_COL, rec.getString(V0_COMMENTS_COL));
blockRecord.setString(SOURCE_COL, rec.getString(V0_SOURCE_NAME_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(START_ADDR_COL, startAddr);
blockRecord.setLongValue(LENGTH_COL, length); blockRecord.setLongValue(LENGTH_COL, length);
blockRecord.setIntValue(SEGMENT_COL, segment); blockRecord.setIntValue(SEGMENT_COL, segment);
@ -195,13 +195,13 @@ class MemoryMapDBAdapterV0 extends MemoryMapDBAdapter {
@Override @Override
MemoryBlockDB createInitializedBlock(String name, Address startAddr, InputStream is, MemoryBlockDB createInitializedBlock(String name, Address startAddr, InputStream is,
long length, int permissions) throws IOException { long length, int flags) throws IOException {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
MemoryBlockDB createInitializedBlock(String name, Address startAddr, DBBuffer buf, MemoryBlockDB createInitializedBlock(String name, Address startAddr, DBBuffer buf, int flags)
int permissions) throws IOException { throws IOException {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -231,8 +231,7 @@ class MemoryMapDBAdapterV0 extends MemoryMapDBAdapter {
@Override @Override
MemoryBlockDB createBlock(MemoryBlockType blockType, String name, Address startAddr, MemoryBlockDB createBlock(MemoryBlockType blockType, String name, Address startAddr,
long length, Address overlayAddr, boolean initializeBytes, int permissions, long length, Address overlayAddr, boolean initializeBytes, int flags, int mappingScheme)
int mappingScheme)
throws IOException { throws IOException {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -267,14 +266,14 @@ class MemoryMapDBAdapterV0 extends MemoryMapDBAdapter {
} }
@Override @Override
protected MemoryBlockDB createBlock(String name, Address addr, long length, int permissions, protected MemoryBlockDB createBlock(String name, Address addr, long length, int flags,
List<SubMemoryBlock> splitBlocks) { List<SubMemoryBlock> splitBlocks) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
protected MemoryBlockDB createFileBytesBlock(String name, Address startAddress, long length, protected MemoryBlockDB createFileBytesBlock(String name, Address startAddress, long length,
FileBytes fileBytes, long offset, int permissions) FileBytes fileBytes, long offset, int flags)
throws IOException, AddressOverflowException { throws IOException, AddressOverflowException {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View file

@ -45,9 +45,6 @@ class MemoryMapDBAdapterV1 extends MemoryMapDBAdapterV0 {
// "Source Block ID","Segment"}); // "Source Block ID","Segment"});
// //
/**
* @param handle
*/
MemoryMapDBAdapterV1(DBHandle handle, MemoryMapDB memMap) throws VersionException, IOException { MemoryMapDBAdapterV1(DBHandle handle, MemoryMapDB memMap) throws VersionException, IOException {
super(handle, memMap, VERSION); super(handle, memMap, VERSION);
} }

View file

@ -63,7 +63,6 @@ class MemoryMapDBAdapterV2 extends MemoryMapDBAdapter {
// new String[] { "Name", "Comments", "Source Name", "Permissions", "Start Address", // new String[] { "Name", "Comments", "Source Name", "Permissions", "Start Address",
// "Block Type", "Overlay Address", "Length", "Chain Buffer ID", "Segment" }); // "Block Type", "Overlay Address", "Length", "Chain Buffer ID", "Segment" });
protected MemoryMapDBAdapterV2(DBHandle handle, MemoryMapDB memMap) protected MemoryMapDBAdapterV2(DBHandle handle, MemoryMapDB memMap)
throws VersionException, IOException { throws VersionException, IOException {
this.handle = handle; this.handle = handle;
@ -86,7 +85,7 @@ class MemoryMapDBAdapterV2 extends MemoryMapDBAdapter {
RecordIterator it = table.iterator(); RecordIterator it = table.iterator();
while (it.hasNext()) { while (it.hasNext()) {
DBRecord rec = it.next(); 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 startAddr = rec.getLongValue(V2_START_ADDR_COL);
long length = rec.getLongValue(V2_LENGTH_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(NAME_COL, rec.getString(V2_NAME_COL));
blockRecord.setString(COMMENTS_COL, rec.getString(V2_COMMENTS_COL)); blockRecord.setString(COMMENTS_COL, rec.getString(V2_COMMENTS_COL));
blockRecord.setString(SOURCE_COL, rec.getString(V2_SOURCE_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(START_ADDR_COL, startAddr);
blockRecord.setLongValue(LENGTH_COL, length); blockRecord.setLongValue(LENGTH_COL, length);
blockRecord.setIntValue(SEGMENT_COL, segment); blockRecord.setIntValue(SEGMENT_COL, segment);
@ -149,22 +148,21 @@ class MemoryMapDBAdapterV2 extends MemoryMapDBAdapter {
} }
@Override @Override
MemoryBlockDB createInitializedBlock(String name, Address startAddr, DBBuffer buf, MemoryBlockDB createInitializedBlock(String name, Address startAddr, DBBuffer buf, int flags)
int permissions) throws AddressOverflowException, IOException { throws AddressOverflowException, IOException {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
MemoryBlockDB createInitializedBlock(String name, Address startAddr, InputStream is, 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(); throw new UnsupportedOperationException();
} }
@Override @Override
MemoryBlockDB createBlock(MemoryBlockType blockType, String name, Address startAddr, 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 mappingScheme) int mappingScheme) throws AddressOverflowException, IOException {
throws AddressOverflowException, IOException {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -223,14 +221,14 @@ class MemoryMapDBAdapterV2 extends MemoryMapDBAdapter {
} }
@Override @Override
protected MemoryBlockDB createBlock(String name, Address addr, long length, int permissions, protected MemoryBlockDB createBlock(String name, Address addr, long length, int flags,
List<SubMemoryBlock> splitBlocks) { List<SubMemoryBlock> splitBlocks) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
protected MemoryBlockDB createFileBytesBlock(String name, Address startAddress, long length, protected MemoryBlockDB createFileBytesBlock(String name, Address startAddress, long length,
FileBytes fileBytes, long offset, int permissions) FileBytes fileBytes, long offset, int flags)
throws IOException, AddressOverflowException { throws IOException, AddressOverflowException {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View file

@ -39,7 +39,7 @@ public class MemoryMapDBAdapterV3 extends MemoryMapDBAdapter {
static final int V3_NAME_COL = 0; static final int V3_NAME_COL = 0;
static final int V3_COMMENTS_COL = 1; static final int V3_COMMENTS_COL = 1;
static final int V3_SOURCE_COL = 2; 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_START_ADDR_COL = 4;
static final int V3_LENGTH_COL = 5; static final int V3_LENGTH_COL = 5;
static final int V3_SEGMENT_COL = 6; 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", static Schema V3_BLOCK_SCHEMA = new Schema(V3_VERSION, "Key",
new Field[] { StringField.INSTANCE, StringField.INSTANCE, StringField.INSTANCE, new Field[] { StringField.INSTANCE, StringField.INSTANCE, StringField.INSTANCE,
ByteField.INSTANCE, LongField.INSTANCE, LongField.INSTANCE, IntField.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" }); "Segment" });
static Schema V3_SUB_BLOCK_SCHEMA = new Schema(V3_VERSION, "Key", static Schema V3_SUB_BLOCK_SCHEMA = new Schema(V3_VERSION, "Key",
@ -116,8 +116,8 @@ public class MemoryMapDBAdapterV3 extends MemoryMapDBAdapter {
void refreshMemory() throws IOException { void refreshMemory() throws IOException {
Map<Long, List<SubMemoryBlock>> subBlockMap = getSubBlockMap(); Map<Long, List<SubMemoryBlock>> subBlockMap = getSubBlockMap();
Map<Long, MemoryBlockDB> blockMap = memoryBlocks.stream().collect( Map<Long, MemoryBlockDB> blockMap = memoryBlocks.stream()
Collectors.toMap(MemoryBlockDB::getID, Function.identity())); .collect(Collectors.toMap(MemoryBlockDB::getID, Function.identity()));
List<MemoryBlockDB> newBlocks = new ArrayList<>(); List<MemoryBlockDB> newBlocks = new ArrayList<>();
RecordIterator it = memBlockTable.iterator(); RecordIterator it = memBlockTable.iterator();
@ -163,14 +163,14 @@ public class MemoryMapDBAdapterV3 extends MemoryMapDBAdapter {
@Override @Override
MemoryBlockDB createInitializedBlock(String name, Address startAddr, InputStream is, 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 // TODO verify that it is necessary to pre-define all segments in the address map
updateAddressMapForAllAddresses(startAddr, length); updateAddressMapForAllAddresses(startAddr, length);
List<SubMemoryBlock> subBlocks = new ArrayList<>(); List<SubMemoryBlock> subBlocks = new ArrayList<>();
try { try {
DBRecord blockRecord = createMemoryBlockRecord(name, startAddr, length, permissions); DBRecord blockRecord = createMemoryBlockRecord(name, startAddr, length, flags);
long key = blockRecord.getKey(); long key = blockRecord.getKey();
int numFullBlocks = (int) (length / maxSubBlockSize); int numFullBlocks = (int) (length / maxSubBlockSize);
int lastSubBlockSize = (int) (length % maxSubBlockSize); int lastSubBlockSize = (int) (length % maxSubBlockSize);
@ -201,30 +201,30 @@ public class MemoryMapDBAdapterV3 extends MemoryMapDBAdapter {
@Override @Override
MemoryBlockDB createBlock(MemoryBlockType blockType, String name, Address startAddr, 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 { int encodedMappingScheme) throws AddressOverflowException, IOException {
if (blockType == MemoryBlockType.BIT_MAPPED) { if (blockType == MemoryBlockType.BIT_MAPPED) {
return createBitMappedBlock(name, startAddr, length, mappedAddress, permissions); return createBitMappedBlock(name, startAddr, length, mappedAddress, flags);
} }
if (blockType == MemoryBlockType.BYTE_MAPPED) { if (blockType == MemoryBlockType.BYTE_MAPPED) {
return createByteMappedBlock(name, startAddr, length, mappedAddress, permissions, return createByteMappedBlock(name, startAddr, length, mappedAddress, flags,
encodedMappingScheme); encodedMappingScheme);
} }
// DEFAULT block type // DEFAULT block type
if (initializeBytes) { 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 @Override
MemoryBlockDB createInitializedBlock(String name, Address startAddr, DBBuffer buf, MemoryBlockDB createInitializedBlock(String name, Address startAddr, DBBuffer buf, int flags)
int permissions) throws AddressOverflowException, IOException { throws AddressOverflowException, IOException {
updateAddressMapForAllAddresses(startAddr, buf.length()); updateAddressMapForAllAddresses(startAddr, buf.length());
List<SubMemoryBlock> subBlocks = new ArrayList<>(); List<SubMemoryBlock> subBlocks = new ArrayList<>();
DBRecord blockRecord = createMemoryBlockRecord(name, startAddr, buf.length(), permissions); DBRecord blockRecord = createMemoryBlockRecord(name, startAddr, buf.length(), flags);
long key = blockRecord.getKey(); long key = blockRecord.getKey();
DBRecord subRecord = DBRecord subRecord =
@ -239,11 +239,11 @@ public class MemoryMapDBAdapterV3 extends MemoryMapDBAdapter {
} }
MemoryBlockDB createUninitializedBlock(String name, Address startAddress, long length, MemoryBlockDB createUninitializedBlock(String name, Address startAddress, long length,
int permissions) throws IOException, AddressOverflowException { int flags) throws IOException, AddressOverflowException {
updateAddressMapForAllAddresses(startAddress, length); updateAddressMapForAllAddresses(startAddress, length);
List<SubMemoryBlock> subBlocks = new ArrayList<>(); List<SubMemoryBlock> subBlocks = new ArrayList<>();
DBRecord blockRecord = createMemoryBlockRecord(name, startAddress, length, permissions); DBRecord blockRecord = createMemoryBlockRecord(name, startAddress, length, flags);
long key = blockRecord.getKey(); long key = blockRecord.getKey();
DBRecord subRecord = createSubBlockRecord(key, 0, length, V3_SUB_TYPE_UNINITIALIZED, 0, 0); DBRecord subRecord = createSubBlockRecord(key, 0, length, V3_SUB_TYPE_UNINITIALIZED, 0, 0);
@ -256,9 +256,9 @@ public class MemoryMapDBAdapterV3 extends MemoryMapDBAdapter {
} }
@Override @Override
protected MemoryBlockDB createBlock(String name, Address startAddress, long length, protected MemoryBlockDB createBlock(String name, Address startAddress, long length, int flags,
int permissions, List<SubMemoryBlock> splitBlocks) throws IOException { List<SubMemoryBlock> splitBlocks) throws IOException {
DBRecord blockRecord = createMemoryBlockRecord(name, startAddress, length, permissions); DBRecord blockRecord = createMemoryBlockRecord(name, startAddress, length, flags);
long key = blockRecord.getKey(); long key = blockRecord.getKey();
long startingOffset = 0; long startingOffset = 0;
@ -274,26 +274,26 @@ public class MemoryMapDBAdapterV3 extends MemoryMapDBAdapter {
} }
MemoryBlockDB createBitMappedBlock(String name, Address startAddress, long length, 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, return createMappedBlock(V3_SUB_TYPE_BIT_MAPPED, name, startAddress, length, mappedAddress,
permissions, 0); flags, 0);
} }
MemoryBlockDB createByteMappedBlock(String name, Address startAddress, long length, MemoryBlockDB createByteMappedBlock(String name, Address startAddress, long length,
Address mappedAddress, int permissions, int mappingScheme) Address mappedAddress, int flags, int mappingScheme)
throws IOException, AddressOverflowException { throws IOException, AddressOverflowException {
return createMappedBlock(V3_SUB_TYPE_BYTE_MAPPED, name, startAddress, length, mappedAddress, return createMappedBlock(V3_SUB_TYPE_BYTE_MAPPED, name, startAddress, length, mappedAddress,
permissions, mappingScheme); flags, mappingScheme);
} }
@Override @Override
protected MemoryBlockDB createFileBytesBlock(String name, Address startAddress, long length, protected MemoryBlockDB createFileBytesBlock(String name, Address startAddress, long length,
FileBytes fileBytes, long offset, int permissions) FileBytes fileBytes, long offset, int flags)
throws IOException, AddressOverflowException { throws IOException, AddressOverflowException {
updateAddressMapForAllAddresses(startAddress, length); updateAddressMapForAllAddresses(startAddress, length);
List<SubMemoryBlock> subBlocks = new ArrayList<>(); List<SubMemoryBlock> subBlocks = new ArrayList<>();
DBRecord blockRecord = createMemoryBlockRecord(name, startAddress, length, permissions); DBRecord blockRecord = createMemoryBlockRecord(name, startAddress, length, flags);
long key = blockRecord.getKey(); long key = blockRecord.getKey();
DBRecord subRecord = createSubBlockRecord(key, 0, length, V3_SUB_TYPE_FILE_BYTES, 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, private MemoryBlockDB createMappedBlock(byte type, String name, Address startAddress,
long length, Address mappedAddress, int permissions, long length, Address mappedAddress, int flags, int mappingScheme)
int mappingScheme)
throws IOException, AddressOverflowException { throws IOException, AddressOverflowException {
updateAddressMapForAllAddresses(startAddress, length); updateAddressMapForAllAddresses(startAddress, length);
List<SubMemoryBlock> subBlocks = new ArrayList<>(); List<SubMemoryBlock> subBlocks = new ArrayList<>();
DBRecord blockRecord = createMemoryBlockRecord(name, startAddress, length, permissions); DBRecord blockRecord = createMemoryBlockRecord(name, startAddress, length, flags);
long key = blockRecord.getKey(); long key = blockRecord.getKey();
long encoded = addrMap.getKey(mappedAddress, true); long encoded = addrMap.getKey(mappedAddress, true);
@ -377,12 +376,12 @@ public class MemoryMapDBAdapterV3 extends MemoryMapDBAdapter {
} }
private DBRecord createMemoryBlockRecord(String name, Address startAddr, long length, private DBRecord createMemoryBlockRecord(String name, Address startAddr, long length,
int permissions) { int flags) {
DBRecord record = V3_BLOCK_SCHEMA.createRecord(memBlockTable.getKey()); DBRecord record = V3_BLOCK_SCHEMA.createRecord(memBlockTable.getKey());
record.setString(V3_NAME_COL, name); record.setString(V3_NAME_COL, name);
record.setLongValue(V3_START_ADDR_COL, addrMap.getKey(startAddr, true)); record.setLongValue(V3_START_ADDR_COL, addrMap.getKey(startAddr, true));
record.setLongValue(V3_LENGTH_COL, length); 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)); record.setIntValue(V3_SEGMENT_COL, getSegment(startAddr));
return record; return record;
} }

View file

@ -46,17 +46,22 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
*/ */
public static final String EXTERNAL_BLOCK_NAME = "EXTERNAL"; 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 VOLATILE = 0x8;
public static int READ = 0x4; public static int READ = 0x4;
public static int WRITE = 0x2; public static int WRITE = 0x2;
public static int EXECUTE = 0x1; public static int EXECUTE = 0x1;
/** /**
* Returns block permissions as a bit mask. Permission bits defined as READ, WRITE, EXECUTE and * Returns block flags (i.e., permissions and attributes) as a bit mask.
* VOLATILE * 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 * 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<MemoryBlock> {
/** /**
* Get the name of this block * Get the name of this block
*
* @return block name
*/ */
public String getName(); public String getName();
@ -122,6 +129,8 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
/** /**
* Get the comment associated with this block. * Get the comment associated with this block.
*
* @return block comment string
*/ */
public String getComment(); public String getComment();
@ -134,6 +143,8 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
/** /**
* Returns the value of the read property associated with this block * Returns the value of the read property associated with this block
*
* @return true if enabled else false
*/ */
public boolean isRead(); public boolean isRead();
@ -146,6 +157,8 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
/** /**
* Returns the value of the write property associated with this block * Returns the value of the write property associated with this block
*
* @return true if enabled else false
*/ */
public boolean isWrite(); public boolean isWrite();
@ -158,6 +171,8 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
/** /**
* Returns the value of the execute property associated with this block * Returns the value of the execute property associated with this block
*
* @return true if enabled else false
*/ */
public boolean isExecute(); public boolean isExecute();
@ -178,18 +193,41 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
public void setPermissions(boolean read, boolean write, boolean execute); 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. * generally associated with block of I/O regions of memory.
*
* @return true if enabled else false
*/ */
public boolean isVolatile(); 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); 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. * Get the name of the source of this memory block.
* *
@ -208,6 +246,7 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
* Returns the byte at the given address in this block. * Returns the byte at the given address in this block.
* *
* @param addr the address. * @param addr the address.
* @return byte value from this block and specified address
* @throws MemoryAccessException if any of the requested bytes are uninitialized. * @throws MemoryAccessException if any of the requested bytes are uninitialized.
* @throws IllegalArgumentException if the Address is not in this block. * @throws IllegalArgumentException if the Address is not in this block.
*/ */
@ -246,6 +285,7 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
* Puts the given byte at the given address in this block. * Puts the given byte at the given address in this block.
* *
* @param addr the address. * @param addr the address.
* @param b byte value
* @throws MemoryAccessException if the block is uninitialized * @throws MemoryAccessException if the block is uninitialized
* @throws IllegalArgumentException if the Address is not in this block. * @throws IllegalArgumentException if the Address is not in this block.
*/ */

View file

@ -46,7 +46,7 @@ public class MemoryBlockStub implements MemoryBlock {
} }
@Override @Override
public int getPermissions() { public int getFlags() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -150,6 +150,16 @@ public class MemoryBlockStub implements MemoryBlock {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public boolean isArtificial() {
throw new UnsupportedOperationException();
}
@Override
public void setArtificial(boolean a) {
throw new UnsupportedOperationException();
}
@Override @Override
public boolean isOverlay() { public boolean isOverlay() {
return false; return false;

View file

@ -92,7 +92,7 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(false, block.isMapped()); assertEquals(false, block.isMapped());
assertNull(block.getComment()); assertNull(block.getComment());
assertNull(block.getSourceName()); assertNull(block.getSourceName());
assertEquals(MemoryBlock.READ, block.getPermissions()); assertEquals(MemoryBlock.READ, block.getFlags());
List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos(); List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
@ -192,7 +192,7 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(true, block.isMapped()); assertEquals(true, block.isMapped());
assertNull(block.getComment()); assertNull(block.getComment());
assertNull(block.getSourceName()); assertNull(block.getSourceName());
assertEquals(MemoryBlock.READ, block.getPermissions()); assertEquals(MemoryBlock.READ, block.getFlags());
List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos(); List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
@ -228,7 +228,7 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(true, block.isMapped()); assertEquals(true, block.isMapped());
assertNull(block.getComment()); assertNull(block.getComment());
assertNull(block.getSourceName()); assertNull(block.getSourceName());
assertEquals(MemoryBlock.READ, block.getPermissions()); assertEquals(MemoryBlock.READ, block.getFlags());
List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos(); List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();
@ -264,7 +264,7 @@ public class MemBlockDBTest extends AbstractGenericTest {
assertEquals(false, block.isMapped()); assertEquals(false, block.isMapped());
assertNull(block.getComment()); assertNull(block.getComment());
assertNull(block.getSourceName()); assertNull(block.getSourceName());
assertEquals(MemoryBlock.READ, block.getPermissions()); assertEquals(MemoryBlock.READ, block.getFlags());
List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos(); List<MemoryBlockSourceInfo> sourceInfos = block.getSourceInfos();

View file

@ -310,6 +310,10 @@ class MIPS_ElfRelocationContext extends ElfRelocationContext<MIPS_ElfRelocationH
sectionGotAddress, size, sectionGotAddress, size,
"NOTE: This block is artificial and allows ELF Relocations to work correctly", "NOTE: This block is artificial and allows ELF Relocations to work correctly",
"Elf Loader", true, false, false, loadHelper.getLog()); "Elf Loader", true, false, false, loadHelper.getLog());
// Mark block as an artificial fabrication
block.setArtificial(true);
DataConverter converter = DataConverter converter =
program.getMemory().isBigEndian() ? BigEndianDataConverter.INSTANCE program.getMemory().isBigEndian() ? BigEndianDataConverter.INSTANCE
: LittleEndianDataConverter.INSTANCE; : LittleEndianDataConverter.INSTANCE;

View file

@ -259,6 +259,10 @@ class X86_64_ElfRelocationContext extends ElfRelocationContext<X86_64_ElfRelocat
ElfRelocationHandler.GOT_BLOCK_NAME, allocatedGotAddress, size, ElfRelocationHandler.GOT_BLOCK_NAME, allocatedGotAddress, size,
"NOTE: This block is artificial and allows ELF Relocations to work correctly", "NOTE: This block is artificial and allows ELF Relocations to work correctly",
"Elf Loader", true, false, false, loadHelper.getLog()); "Elf Loader", true, false, false, loadHelper.getLog());
// Mark block as an artificial fabrication
block.setArtificial(true);
DataConverter converter = DataConverter converter =
program.getMemory().isBigEndian() ? BigEndianDataConverter.INSTANCE program.getMemory().isBigEndian() ? BigEndianDataConverter.INSTANCE
: LittleEndianDataConverter.INSTANCE; : LittleEndianDataConverter.INSTANCE;