Merge remote-tracking branch 'origin/GP-4125_ghidra1_ArtificialBlockAttribute--SQUASHED'

This commit is contained in:
Ryan Kurtz 2024-03-07 08:50:41 -05:00
commit c3c34ebf10
48 changed files with 734 additions and 465 deletions

View File

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

View File

@ -18,6 +18,8 @@ package ghidra.trace.database.program;
import java.io.InputStream;
import java.math.BigInteger;
import javax.help.UnsupportedOperationException;
import ghidra.framework.store.LockException;
import ghidra.program.model.address.*;
import ghidra.trace.database.memory.DBTraceMemorySpace;
@ -57,7 +59,7 @@ public class DBTraceProgramViewMemoryRegionBlock extends AbstractDBTraceProgramV
}
@Override
public int getPermissions() {
public int getFlags() {
int bits = 0;
for (TraceMemoryFlag flag : region.getFlags()) {
bits |= flag.getBits();
@ -145,4 +147,15 @@ public class DBTraceProgramViewMemoryRegionBlock extends AbstractDBTraceProgramV
public void setVolatile(boolean v) {
region.setVolatile(v);
}
@Override
public boolean isArtificial() {
// By definition, any region present on target is non-artificial
return false;
}
@Override
public void setArtificial(boolean a) {
throw new UnsupportedOperationException();
}
}

View File

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

View File

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

View File

@ -62,26 +62,11 @@
<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
within the same overlay address space.
An overlay memory block may be created in two ways:
* <ul>
* <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
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
or processor state. &nbsp; Note that Overlay blocks
do not relocate with image base changes and have some limitations in conjunction with
decompilation and analysis.</P>
<P>To view the <I>Memory Map</I>, select <B>Window<IMG src="help/shared/arrow.gif" border="0">
@ -123,6 +108,9 @@
<P><I><B>X * -</B></I> Indicates execute permission.</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
of the overlayed physical memory space. This field will be empty for non-overlay blocks.</P>
@ -200,6 +188,13 @@
<P>The volatile setting of a memory block can be changed by left-clicking on the
checkbox.</P>
</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>
@ -266,7 +261,11 @@
<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
created in two ways:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -28,7 +28,7 @@ import ghidra.util.exception.*;
/**
* Base command class for adding memory blocks.
*/
abstract class AbstractAddMemoryBlockCmd implements Command {
public abstract class AbstractAddMemoryBlockCmd implements Command {
protected String message;
protected final String name;
protected final String comment;
@ -42,6 +42,8 @@ abstract class AbstractAddMemoryBlockCmd implements Command {
protected final boolean isVolatile;
protected final boolean isOverlay;
private boolean isArtificial = false;
AbstractAddMemoryBlockCmd(String name, String comment, String source, Address start,
long length, boolean read, boolean write, boolean execute, boolean isVolatile,
boolean isOverlay) {
@ -57,6 +59,15 @@ abstract class AbstractAddMemoryBlockCmd implements Command {
this.isOverlay = isOverlay;
}
/**
* Prior to command execution the block's artificial attribute state may be specified
* and will be applied to the new memory block.
* @param a block artificial attribute state
*/
public void setArtificial(boolean a) {
isArtificial = a;
}
@Override
public String getStatusMsg() {
return message;
@ -67,9 +78,8 @@ abstract class AbstractAddMemoryBlockCmd implements Command {
return "Add Memory Block";
}
protected abstract MemoryBlock createMemoryBlock(Memory memory)
throws LockException, MemoryConflictException, AddressOverflowException,
CancelledException;
protected abstract MemoryBlock createMemoryBlock(Memory memory) throws LockException,
MemoryConflictException, AddressOverflowException, CancelledException;
@Override
public boolean applyTo(DomainObject obj) {
@ -82,6 +92,7 @@ abstract class AbstractAddMemoryBlockCmd implements Command {
block.setWrite(write);
block.setExecute(execute);
block.setVolatile(isVolatile);
block.setArtificial(isArtificial);
block.setSourceName(source);
renameFragment(program, block.getStart());
return true;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -484,6 +484,13 @@ class MemoryMapProvider extends ComponentProviderAdapter {
column.setResizable(false);
}
column = table.getColumn(MemoryMapModel.ARTIFICIAL_COL);
if (column != null) {
column.setMaxWidth(65);
column.setMinWidth(65);
column.setResizable(false);
}
column = table.getColumn(MemoryMapModel.BLOCK_TYPE_COL);
if (column != null) {
column.setMinWidth(25);

View File

@ -109,6 +109,7 @@ public class StringsAnalyzer extends AbstractAnalyzer {
public static enum Alignment {
ALIGN_1(1), ALIGN_2(2), ALIGN_4(4);
private int alignment;
Alignment(int alignment) {
@ -349,7 +350,10 @@ public class StringsAnalyzer extends AbstractAnalyzer {
AddressSet addresses = new AddressSet();
for (MemoryBlock memBlock : blocks) {
if (memBlock.getPermissions() > 0) {
if (!memBlock.isLoaded()) {
continue;
}
if (memBlock.isWrite() || memBlock.isRead() || memBlock.isExecute()) {
addresses = addresses.union(new AddressSet(memBlock.getStart(), memBlock.getEnd()));
}
}
@ -581,14 +585,15 @@ public class StringsAnalyzer extends AbstractAnalyzer {
modelName = options.getString(MODELFILE_OPTION_NAME, MODEL_DEFAULT_NAME);
setTrigramFileName(modelName);
minStringLength = options.getEnum(MINIMUM_STRING_LENGTH_OPTION_NAME,
MINIMUM_STRING_LENGTH_DEFAULT_VALUE).getMinLength();
minStringLength =
options.getEnum(MINIMUM_STRING_LENGTH_OPTION_NAME, MINIMUM_STRING_LENGTH_DEFAULT_VALUE)
.getMinLength();
requireNullEnd = options.getBoolean(REQUIRE_NULL_TERMINATION_OPTION_NAME,
REQUIRE_NULL_TERMINATION_DEFAULT_VALUE);
startAlignment = options.getEnum(START_ALIGNMENT_OPTION_NAME,
START_ALIGNMENT_DEFAULT_VALUE).getAlignment();
startAlignment = options.getEnum(START_ALIGNMENT_OPTION_NAME, START_ALIGNMENT_DEFAULT_VALUE)
.getAlignment();
setStringEndAlignment(
options.getInt(END_ALIGNMENT_OPTION_NAME, END_ALIGNMENT_DEFAULT_VALUE));

View File

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

View File

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

View File

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

View File

@ -105,8 +105,8 @@ public class MachoProgramBuilder {
*/
public static void buildProgram(Program program, ByteProvider provider, FileBytes fileBytes,
MessageLog log, TaskMonitor monitor) throws Exception {
MachoProgramBuilder machoProgramBuilder = new MachoProgramBuilder(program, provider,
fileBytes, log, monitor);
MachoProgramBuilder machoProgramBuilder =
new MachoProgramBuilder(program, provider, fileBytes, log, monitor);
machoProgramBuilder.build();
}
@ -154,7 +154,7 @@ public class MachoProgramBuilder {
fixupProgramTree(null); // should be done last to account for new memory blocks
setCompiler();
}
/**
* Sets the image base
*
@ -339,8 +339,7 @@ public class MachoProgramBuilder {
* @param suffix An optional suffix that will get appended to tree segment and segment nodes
* @throws Exception if there was a problem fixing up the Program Tree
*/
protected void fixupProgramTree(String suffix)
throws Exception {
protected void fixupProgramTree(String suffix) throws Exception {
if (suffix == null) {
suffix = "";
}
@ -399,7 +398,7 @@ public class MachoProgramBuilder {
section.getSectionName() + suffix));
sectionFragment.move(sectionStart, sectionEnd);
}
// If the sections fully filled the segment, we can remove the now-empty segment
if (segmentFragment.isEmpty()) {
segmentModule.removeChild(segmentFragment.getName());
@ -456,7 +455,7 @@ public class MachoProgramBuilder {
log.appendMsg("Unable to determine entry point.");
}
}
protected boolean processExports(MachHeader header) throws Exception {
monitor.setMessage("Processing exports...");
@ -501,7 +500,7 @@ public class MachoProgramBuilder {
}
return !exports.isEmpty();
}
}
protected void processNewExport(Address baseAddr, ExportEntry export, String name)
throws AddressOutOfBoundsException, Exception {
@ -680,6 +679,10 @@ public class MachoProgramBuilder {
start, undefinedSymbols.size() * machoHeader.getAddressSize(), false);
// assume any value in external is writable.
block.setWrite(true);
// Mark block as an artificial fabrication
block.setArtificial(true);
block.setSourceName(BLOCK_SOURCE_NAME);
block.setComment(
"NOTE: This block is artificial and is used to make relocations work correctly");
@ -792,14 +795,15 @@ public class MachoProgramBuilder {
}
}
private void processBindings(BindingTable bindingTable, List<String> libraryPaths) throws Exception {
private void processBindings(BindingTable bindingTable, List<String> libraryPaths)
throws Exception {
DataConverter converter = DataConverter.getInstance(program.getLanguage().isBigEndian());
SymbolTable symbolTable = program.getSymbolTable();
List<Binding> bindings = bindingTable.getBindings();
List<Binding> threadedBindings = bindingTable.getThreadedBindings();
List<SegmentCommand> segments = machoHeader.getAllSegments();
if (threadedBindings != null) {
DyldChainedFixups dyldChainedFixups =
new DyldChainedFixups(program, machoHeader, libraryPaths, log, monitor);
@ -834,7 +838,7 @@ public class MachoProgramBuilder {
Address addr =
space.getAddress(segments.get(binding.getSegmentIndex()).getVMaddress() +
binding.getSegmentOffset());
fixupExternalLibrary(binding.getLibraryOrdinal(), symbol, libraryPaths);
boolean success = false;
@ -1103,16 +1107,16 @@ public class MachoProgramBuilder {
}
/**
* Processes the section relocations from all {@link Section}s.
*
* @throws CancelledException if the operation was cancelled.
*/
protected void processSectionRelocations() throws CancelledException {
monitor.setMessage("Processing section relocations...");
* Processes the section relocations from all {@link Section}s.
*
* @throws CancelledException if the operation was cancelled.
*/
protected void processSectionRelocations() throws CancelledException {
monitor.setMessage("Processing section relocations...");
LinkedHashMap<RelocationInfo, Address> relocationMap = new LinkedHashMap<>();
for (Section section : machoHeader.getAllSections()) {
monitor.checkCancelled();
for (Section section : machoHeader.getAllSections()) {
monitor.checkCancelled();
MemoryBlock sectionMemoryBlock = getMemoryBlock(section);
if (sectionMemoryBlock == null) {
@ -1124,54 +1128,54 @@ public class MachoProgramBuilder {
}
for (RelocationInfo relocationInfo : section.getRelocations()) {
monitor.checkCancelled();
monitor.checkCancelled();
Address address = sectionMemoryBlock.getStart().add(relocationInfo.getAddress());
relocationMap.put(relocationInfo, address);
}
}
performRelocations(relocationMap);
performRelocations(relocationMap);
}
/**
* Processes the external relocations from all {@link DynamicSymbolTableCommand}s.
*
* @throws CancelledException if the operation was cancelled.
*/
protected void processExternalRelocations() throws CancelledException {
* Processes the external relocations from all {@link DynamicSymbolTableCommand}s.
*
* @throws CancelledException if the operation was cancelled.
*/
protected void processExternalRelocations() throws CancelledException {
monitor.setMessage("Processing external relocations...");
LinkedHashMap<RelocationInfo, Address> relocationMap = new LinkedHashMap<>();
for (DynamicSymbolTableCommand cmd : machoHeader
.getLoadCommands(DynamicSymbolTableCommand.class)) {
monitor.checkCancelled();
for (RelocationInfo relocationInfo : cmd.getExternalRelocations()) {
monitor.checkCancelled();
relocationMap.put(relocationInfo, space.getAddress(relocationInfo.getAddress()));
}
}
performRelocations(relocationMap);
for (DynamicSymbolTableCommand cmd : machoHeader
.getLoadCommands(DynamicSymbolTableCommand.class)) {
monitor.checkCancelled();
for (RelocationInfo relocationInfo : cmd.getExternalRelocations()) {
monitor.checkCancelled();
relocationMap.put(relocationInfo, space.getAddress(relocationInfo.getAddress()));
}
}
performRelocations(relocationMap);
}
/**
* Processes the local relocations from all {@link DynamicSymbolTableCommand}s.
*
* @throws CancelledException if the operation was cancelled.
*/
protected void processLocalRelocations() throws CancelledException {
* Processes the local relocations from all {@link DynamicSymbolTableCommand}s.
*
* @throws CancelledException if the operation was cancelled.
*/
protected void processLocalRelocations() throws CancelledException {
monitor.setMessage("Processing local relocations...");
LinkedHashMap<RelocationInfo, Address> relocationMap = new LinkedHashMap<>();
for (DynamicSymbolTableCommand cmd : machoHeader
.getLoadCommands(DynamicSymbolTableCommand.class)) {
monitor.checkCancelled();
for (RelocationInfo relocationInfo : cmd.getLocalRelocations()) {
monitor.checkCancelled();
relocationMap.put(relocationInfo, space.getAddress(relocationInfo.getAddress()));
}
}
performRelocations(relocationMap);
for (DynamicSymbolTableCommand cmd : machoHeader
.getLoadCommands(DynamicSymbolTableCommand.class)) {
monitor.checkCancelled();
for (RelocationInfo relocationInfo : cmd.getLocalRelocations()) {
monitor.checkCancelled();
relocationMap.put(relocationInfo, space.getAddress(relocationInfo.getAddress()));
}
}
performRelocations(relocationMap);
}
protected List<String> processLibraries() throws Exception {
@ -1215,7 +1219,7 @@ public class MachoProgramBuilder {
if (program.getSymbolTable().getLibrarySymbol(Library.UNKNOWN) == null) {
program.getSymbolTable().createExternalLibrary(Library.UNKNOWN, SourceType.IMPORTED);
}
return libraryPaths;
}
@ -1257,23 +1261,23 @@ public class MachoProgramBuilder {
* @throws CancelledException if the operation was cancelled.
*/
private void performRelocations(LinkedHashMap<RelocationInfo, Address> relocationMap)
throws CancelledException {
throws CancelledException {
if (relocationMap.isEmpty()) {
return;
}
MachoRelocationHandler handler = MachoRelocationHandlerFactory.getHandler(machoHeader);
MachoRelocationHandler handler = MachoRelocationHandlerFactory.getHandler(machoHeader);
if (handler == null) {
log.appendMsg(String.format("No relocation handler for machine type 0x%x",
machoHeader.getCpuType()));
}
Iterator<RelocationInfo> iter = relocationMap.keySet().iterator();
while (iter.hasNext()) {
RelocationInfo relocationInfo = iter.next();
Address address = relocationMap.get(relocationInfo);
MachoRelocation relocation = null;
Iterator<RelocationInfo> iter = relocationMap.keySet().iterator();
while (iter.hasNext()) {
RelocationInfo relocationInfo = iter.next();
Address address = relocationMap.get(relocationInfo);
MachoRelocation relocation = null;
RelocationResult result = RelocationResult.FAILURE;
if (handler != null) {
@ -1281,7 +1285,7 @@ public class MachoProgramBuilder {
? new MachoRelocation(program, machoHeader, address, relocationInfo,
iter.next())
: new MachoRelocation(program, machoHeader, address, relocationInfo);
try {
try {
result = handler.relocate(relocation);
if (result.status() == Status.UNSUPPORTED) {
@ -1291,9 +1295,9 @@ public class MachoProgramBuilder {
}
}
catch (MemoryAccessException e) {
handleRelocationError(address, String.format(
handleRelocationError(address, String.format(
"Relocation failure at address %s: error accessing memory.", address));
}
}
catch (RelocationException e) {
handleRelocationError(address, String.format(
"Relocation failure at address %s: %s", address, e.getMessage()));
@ -1306,18 +1310,19 @@ public class MachoProgramBuilder {
msg = String.format("Relocation failure at address %s: %s", address, msg);
handleRelocationError(address, msg);
Msg.error(this, msg, e);
}
}
}
program.getRelocationTable()
.add(address, result.status(), relocationInfo.getType(),
new long[] { relocationInfo.getValue(),
relocationInfo.getLength(), relocationInfo.isPcRelocated() ? 1 : 0,
relocationInfo.isExternal() ? 1 : 0, relocationInfo.isScattered() ? 1 : 0 },
new long[] { relocationInfo.getValue(), relocationInfo.getLength(),
relocationInfo.isPcRelocated() ? 1 : 0,
relocationInfo.isExternal() ? 1 : 0,
relocationInfo.isScattered() ? 1 : 0 },
result.byteLength(),
relocation != null ? relocation.getTargetDescription() : null);
}
}
/**
* Marks up {@link LoadCommand} dadta
*
@ -1338,10 +1343,10 @@ public class MachoProgramBuilder {
* @param message The error message
*/
private void handleRelocationError(Address address, String message) {
program.getBookmarkManager()
.setBookmark(address, BookmarkType.ERROR, "Relocations", message);
log.appendMsg(message);
}
program.getBookmarkManager()
.setBookmark(address, BookmarkType.ERROR, "Relocations", message);
log.appendMsg(message);
}
private void addLibrary(String library) {
library = library.replaceAll(" ", "_");

View File

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

View File

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

View File

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

View File

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -23,7 +22,8 @@ import ghidra.util.SystemUtilities;
* <CODE>MemoryBlockDiff</CODE> determines the types of differences between two memory blocks.
*/
public class MemoryBlockDiff {
//@formatter:off
public static final int NAME = 0x001;
public static final int START_ADDRESS = 0x002;
public static final int END_ADDRESS = 0x004;
@ -32,16 +32,18 @@ public class MemoryBlockDiff {
public static final int WRITE = 0x020;
public static final int EXECUTE = 0x040;
public static final int VOLATILE = 0x080;
public static final int TYPE = 0x100;
public static final int INIT = 0x200;
public static final int SOURCE = 0x400;
public static final int COMMENT = 0x800;
public static final int ALL = 0xFFF;
public static final int ARTIFICIAL = 0x100;
public static final int TYPE = 0x200;
public static final int INIT = 0x400;
public static final int SOURCE = 0x800;
public static final int COMMENT = 0x1000;
public static final int ALL = 0x1FFF;
//@formatter:on
private MemoryBlock block1;
private MemoryBlock block2;
private int diffFlags;
/**
* Constructor. <CODE>MemoryBlockDiff</CODE> determines the types of differences
* between two memory blocks.
@ -57,139 +59,149 @@ public class MemoryBlockDiff {
MemoryBlock getBlock1() {
return block1;
}
MemoryBlock getBlock2() {
return block2;
}
/**
* Returns true if the memory block names differ.
*/
public boolean isNameDifferent() {
return (diffFlags & NAME) != 0;
}
/**
* Returns true if the start addresses of the memory blocks differ.
*/
public boolean isStartAddressDifferent() {
return (diffFlags & START_ADDRESS) != 0;
}
/**
* Returns true if the end addresses of the memory blocks differ.
*/
public boolean isEndAddressDifferent() {
return (diffFlags & END_ADDRESS) != 0;
}
/**
* Returns true if the sizes of the memory blocks differ.
*/
public boolean isSizeDifferent() {
return (diffFlags & SIZE) != 0;
}
/**
* Returns true if the memory blocks Read flags differ.
*/
public boolean isReadDifferent() {
return (diffFlags & READ) != 0;
}
/**
* Returns true if the memory blocks Write flags differ.
*/
public boolean isWriteDifferent() {
return (diffFlags & WRITE) != 0;
}
/**
* Returns true if the memory blocks Execute flags differ.
*/
public boolean isExecDifferent() {
return (diffFlags & EXECUTE) != 0;
}
/**
* Returns true if the memory blocks Volatile flags differ.
*/
public boolean isVolatileDifferent() {
return (diffFlags & VOLATILE) != 0;
}
/**
* Returns true if the memory blocks Artificial flags differ.
*/
public boolean isArtificialDifferent() {
return (diffFlags & ARTIFICIAL) != 0;
}
/**
* Returns true if the type for the memory blocks differ.
*/
public boolean isTypeDifferent() {
return (diffFlags & TYPE) != 0;
}
/**
* Returns true if the initialization of the memory blocks isn't the same.
*/
public boolean isInitDifferent() {
return (diffFlags & INIT) != 0;
}
/**
* Returns true if the source for the memory blocks differ.
*/
public boolean isSourceDifferent() {
return (diffFlags & SOURCE) != 0;
}
/**
* Returns true if the comments on the memory blocks differ.
*/
public boolean isCommentDifferent() {
return (diffFlags & COMMENT) != 0;
}
/**
* Gets a string representation of the types of memory differences for this MemoryBlockDiff.
*/
public String getDifferencesAsString() {
StringBuffer buf = new StringBuffer();
if((diffFlags & NAME) != 0) {
if ((diffFlags & NAME) != 0) {
buf.append("Name ");
}
if((diffFlags & START_ADDRESS) != 0) {
if ((diffFlags & START_ADDRESS) != 0) {
buf.append("StartAddress ");
}
if((diffFlags & END_ADDRESS) != 0) {
if ((diffFlags & END_ADDRESS) != 0) {
buf.append("EndAddress ");
}
if((diffFlags & SIZE) != 0) {
if ((diffFlags & SIZE) != 0) {
buf.append("Size ");
}
if((diffFlags & READ) != 0) {
if ((diffFlags & READ) != 0) {
buf.append("R ");
}
if((diffFlags & WRITE) != 0) {
if ((diffFlags & WRITE) != 0) {
buf.append("W ");
}
if((diffFlags & EXECUTE) != 0) {
if ((diffFlags & EXECUTE) != 0) {
buf.append("X ");
}
if((diffFlags & VOLATILE) != 0) {
if ((diffFlags & VOLATILE) != 0) {
buf.append("Volatile ");
}
if((diffFlags & TYPE) != 0) {
if ((diffFlags & ARTIFICIAL) != 0) {
buf.append("Artificial ");
}
if ((diffFlags & TYPE) != 0) {
buf.append("Type ");
}
if((diffFlags & INIT) != 0) {
if ((diffFlags & INIT) != 0) {
buf.append("Initialized ");
}
if((diffFlags & SOURCE) != 0) {
if ((diffFlags & SOURCE) != 0) {
buf.append("Source ");
}
if((diffFlags & COMMENT) != 0) {
if ((diffFlags & COMMENT) != 0) {
buf.append("Comment ");
}
return buf.toString();
}
/**
* Gets an integer value that has bits set as flags indicating the types of differences
* that exist between the two memory blocks.
@ -207,9 +219,9 @@ public class MemoryBlockDiff {
if (block2 == null) {
return ALL;
}
int flags = 0;
if(!block1.getName().equals(block2.getName())) {
if (!block1.getName().equals(block2.getName())) {
flags |= NAME;
}
if (!block1.getStart().equals(block2.getStart())) {
@ -233,6 +245,9 @@ public class MemoryBlockDiff {
if (block1.isVolatile() != block2.isVolatile()) {
flags |= VOLATILE;
}
if (block1.isArtificial() != block2.isArtificial()) {
flags |= ARTIFICIAL;
}
if (!block1.getType().equals(block2.getType())) {
flags |= TYPE;
}

View File

@ -31,14 +31,14 @@ import ghidra.util.task.TaskMonitor;
* types of differences.
*/
public class MemoryDiff {
private Program program1;
private Program program2;
private Memory memory1;
private Memory memory2;
private AddressRange[] ranges;
private MemoryBlockDiff[] diffs;
/**
* Constructs an object for determining memory differences between two programs.
* @param p1 the first program
@ -46,8 +46,7 @@ public class MemoryDiff {
* @throws ProgramConflictException if the program memory can't be compared because the programs
* are based on different languages.
*/
public MemoryDiff(Program p1, Program p2)
throws ProgramConflictException {
public MemoryDiff(Program p1, Program p2) throws ProgramConflictException {
program1 = p1;
program2 = p2;
memory1 = program1.getMemory();
@ -55,7 +54,7 @@ public class MemoryDiff {
computeRanges();
computeDifferences();
}
/**
* Gets the first program that is part of this MemoryDiff.
* @return the first program
@ -63,7 +62,7 @@ public class MemoryDiff {
public Program getProgram1() {
return program1;
}
/**
* Gets the second program that is part of this MemoryDiff.
* @return the second program
@ -71,7 +70,7 @@ public class MemoryDiff {
public Program getProgram2() {
return program2;
}
/**
* Determines the address ranges that the two programs memories must be broken into for
* properly comparing the programs. Each of these address ranges will exist in the first
@ -82,12 +81,12 @@ public class MemoryDiff {
ProgramMemoryComparator memComp = new ProgramMemoryComparator(program1, program2);
ArrayList<AddressRange> rangeList = new ArrayList<AddressRange>();
AddressRangeIterator rangeIter = memComp.getAddressRanges();
while(rangeIter.hasNext()) {
while (rangeIter.hasNext()) {
rangeList.add(rangeIter.next());
}
ranges = rangeList.toArray(new AddressRange[rangeList.size()]);
}
/**
* Gets the number of address ranges that the two programs memories are broken into for
* comparing the programs.
@ -96,7 +95,7 @@ public class MemoryDiff {
public int getNumRanges() {
return ranges.length;
}
/**
* Gets the address range as indicated by index. The index is zero based. Address ranges are
* in order from the minimum address to the maximum address range.
@ -106,7 +105,7 @@ public class MemoryDiff {
public AddressRange getRange(int index) {
return ranges[index];
}
/**
* Gets the memory difference flags for the address range as indicated by index.
* @param index the index of the address range to get the difference flags for.
@ -115,7 +114,7 @@ public class MemoryDiff {
public MemoryBlockDiff getDifferenceInfo(int index) {
return diffs[index];
}
/**
* Determines the memory differences and sets the flags for each associated address range.
*/
@ -128,7 +127,7 @@ public class MemoryDiff {
diffs[i] = new MemoryBlockDiff(block1, block2);
}
}
/**
* Gets a string representation of the types of memory differences that exist for the memory
* block that contains the indicated address.
@ -143,30 +142,30 @@ public class MemoryDiff {
MemoryBlockDiff info = getDifferenceInfo(index);
return info.getDifferencesAsString();
}
/**
* Gets the index of the address range containing the indicated address,
* if it is contained in the list;
* otherwise, <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.
* @return the index of the address range.
*/
private int getAddressRangeIndex(Address address) {
int low = 0;
int high = diffs.length-1;
int high = diffs.length - 1;
while (low <= high) {
int mid = (low + high) >> 1;
AddressRange range = ranges[mid];
if (range.contains(address)) {
return mid;
}
else if (address.compareTo(range.getMinAddress()) < 0) {
high = mid - 1;
}
else {
low = mid + 1;
}
int mid = (low + high) >> 1;
AddressRange range = ranges[mid];
if (range.contains(address)) {
return mid;
}
else if (address.compareTo(range.getMinAddress()) < 0) {
high = mid - 1;
}
else {
low = mid + 1;
}
}
return -(low + 1); // not found.
}
@ -187,7 +186,7 @@ public class MemoryDiff {
}
return rangeDiffs.toArray(new AddressRange[rangeDiffs.size()]);
}
/**
* Determines whether the two memory blocks are the same.
* @param block1 the first program's memory block
@ -201,7 +200,7 @@ public class MemoryDiff {
else if (block2 == null) {
return false;
}
if(!block1.getName().equals(block2.getName())) {
if (!block1.getName().equals(block2.getName())) {
return false;
}
if (!block1.getStart().equals(block2.getStart())) {
@ -213,7 +212,7 @@ public class MemoryDiff {
if (block1.getSize() != block2.getSize()) {
return false;
}
if (block1.getPermissions() != block2.getPermissions()) {
if (block1.getFlags() != block2.getFlags()) {
return false;
}
if (!block1.getType().equals(block2.getType())) {
@ -233,8 +232,7 @@ public class MemoryDiff {
}
return true;
}
public boolean merge(int row, int mergeFields, TaskMonitor monitor) {
if ((mergeFields & MemoryBlockDiff.ALL) == 0) {
return false;
@ -246,8 +244,8 @@ public class MemoryDiff {
MemoryBlock block1 = blockDiff.getBlock1();
MemoryBlock block2 = blockDiff.getBlock2();
AddressRange range = ranges[row];
if (shouldMerge(mergeFields, MemoryBlockDiff.START_ADDRESS)
&& blockDiff.isStartAddressDifferent()) {
if (shouldMerge(mergeFields, MemoryBlockDiff.START_ADDRESS) &&
blockDiff.isStartAddressDifferent()) {
if (block1 == null) {
// Add all or part of a block.
Address start2 = block2.getStart();
@ -271,7 +269,7 @@ public class MemoryDiff {
return true;
}
catch (Exception e) {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
}
return false;
}
@ -295,64 +293,63 @@ public class MemoryDiff {
memory1.removeBlock(blockToRemove, monitor);
}
return true;
} catch (LockException e) {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
} catch (NotFoundException e) {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
} catch (AddressOutOfBoundsException e) {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
} catch (MemoryBlockException e) {
}
catch (LockException e) {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
}
catch (NotFoundException e) {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
}
catch (AddressOutOfBoundsException e) {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
}
catch (MemoryBlockException e) {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
}
return false;
}
}
if (shouldMerge(mergeFields, MemoryBlockDiff.END_ADDRESS)
&& blockDiff.isEndAddressDifferent()) {
if (shouldMerge(mergeFields, MemoryBlockDiff.END_ADDRESS) &&
blockDiff.isEndAddressDifferent()) {
// TODO
}
if (shouldMerge(mergeFields, MemoryBlockDiff.SIZE)
&& blockDiff.isSizeDifferent()) {
if (shouldMerge(mergeFields, MemoryBlockDiff.SIZE) && blockDiff.isSizeDifferent()) {
// TODO
}
if (shouldMerge(mergeFields, MemoryBlockDiff.TYPE)
&& blockDiff.isTypeDifferent()) {
if (shouldMerge(mergeFields, MemoryBlockDiff.TYPE) && blockDiff.isTypeDifferent()) {
// TODO
}
if (shouldMerge(mergeFields, MemoryBlockDiff.INIT)
&& blockDiff.isInitDifferent()) {
if (shouldMerge(mergeFields, MemoryBlockDiff.INIT) && blockDiff.isInitDifferent()) {
// TODO
}
if (shouldMerge(mergeFields, MemoryBlockDiff.NAME)
&& blockDiff.isNameDifferent()) {
if (shouldMerge(mergeFields, MemoryBlockDiff.NAME) && blockDiff.isNameDifferent()) {
try {
block1.setName(block2.getName());
} catch (LockException e) {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
}
catch (LockException e) {
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
}
}
if (shouldMerge(mergeFields, MemoryBlockDiff.READ)
&& blockDiff.isReadDifferent()) {
if (shouldMerge(mergeFields, MemoryBlockDiff.READ) && blockDiff.isReadDifferent()) {
block1.setRead(block2.isRead());
}
if (shouldMerge(mergeFields, MemoryBlockDiff.WRITE)
&& blockDiff.isWriteDifferent()) {
if (shouldMerge(mergeFields, MemoryBlockDiff.WRITE) && blockDiff.isWriteDifferent()) {
block1.setWrite(block2.isWrite());
}
if (shouldMerge(mergeFields, MemoryBlockDiff.EXECUTE)
&& blockDiff.isExecDifferent()) {
if (shouldMerge(mergeFields, MemoryBlockDiff.EXECUTE) && blockDiff.isExecDifferent()) {
block1.setExecute(block2.isExecute());
}
if (shouldMerge(mergeFields, MemoryBlockDiff.VOLATILE)
&& blockDiff.isVolatileDifferent()) {
if (shouldMerge(mergeFields, MemoryBlockDiff.VOLATILE) && blockDiff.isVolatileDifferent()) {
block1.setVolatile(block2.isVolatile());
}
if (shouldMerge(mergeFields, MemoryBlockDiff.SOURCE)
&& blockDiff.isSourceDifferent()) {
if (shouldMerge(mergeFields, MemoryBlockDiff.ARTIFICIAL) &&
blockDiff.isArtificialDifferent()) {
block1.setArtificial(block2.isArtificial());
}
if (shouldMerge(mergeFields, MemoryBlockDiff.SOURCE) && blockDiff.isSourceDifferent()) {
block1.setSourceName(block2.getSourceName());
}
if (shouldMerge(mergeFields, MemoryBlockDiff.COMMENT)
&& blockDiff.isCommentDifferent()) {
if (shouldMerge(mergeFields, MemoryBlockDiff.COMMENT) && blockDiff.isCommentDifferent()) {
block1.setComment(block2.getComment());
}
return true;

View File

@ -111,6 +111,7 @@ public class MemoryTypeProgramLocationBasedTableColumn
updateForWrite(block, buffy, tooltipBuffy);
updateForExecute(block, buffy, tooltipBuffy);
updateForVolatile(block, buffy, tooltipBuffy);
updateForArtificial(block, buffy, tooltipBuffy);
}
private void updateForVolatile(MemoryBlock block, StringBuilder buffy,
@ -128,6 +129,21 @@ public class MemoryTypeProgramLocationBasedTableColumn
tooltipBuffy.append(HTMLUtilities.spaces(2)).append("Volatile<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,
StringBuilder tooltipBuffy) {
@ -186,7 +202,7 @@ public class MemoryTypeProgramLocationBasedTableColumn
private class MemoryTypeComparator implements Comparator<MemoryBlock> {
@Override
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 PERMISSIONS (r | w | x | rw | rx | wx | rwx) #IMPLIED>
<!ATTLIST MEMORY_SECTION VOLATILE (y | n) #IMPLIED>
<!ATTLIST MEMORY_SECTION ARTIFICIAL (y | n) #IMPLIED>
<!ATTLIST MEMORY_SECTION COMMENT CDATA #IMPLIED>
<!ELEMENT MEMORY_CONTENTS EMPTY>

View File

@ -219,7 +219,7 @@ public class MemoryMergeManagerTest extends AbstractMergeTest {
blocks[4].setRead(false);
blocks[4].setWrite(false);
blocks[4].setExecute(false);
try {
blocks[4].setName("special-debug");
}
@ -269,6 +269,7 @@ public class MemoryMergeManagerTest extends AbstractMergeTest {
assertTrue(!blocks[4].isWrite());
assertTrue(!blocks[4].isExecute());
assertTrue(!blocks[4].isVolatile());
assertTrue(!blocks[4].isArtificial());
}
@Test

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -46,17 +46,22 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
*/
public static final String EXTERNAL_BLOCK_NAME = "EXTERNAL";
// Memory block permission bits
// Memory block flag bits
// NOTE: These are used by stored Flags with DB (8-bits) and
// should be changed other than to add values.
public static int ARTIFICIAL = 0x10;
public static int VOLATILE = 0x8;
public static int READ = 0x4;
public static int WRITE = 0x2;
public static int EXECUTE = 0x1;
/**
* Returns block permissions as a bit mask. Permission bits defined as READ, WRITE, EXECUTE and
* VOLATILE
* Returns block flags (i.e., permissions and attributes) as a bit mask.
* These bits defined as {@link #READ}, {@link #WRITE}, {@link #EXECUTE}, {@link #VOLATILE},
* {@link #ARTIFICIAL}.
* @return block flag bits
*/
public int getPermissions();
public int getFlags();
/**
* Get memory data in the form of an InputStream. Null is returned for thos memory blocks which
@ -107,6 +112,8 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
/**
* Get the name of this block
*
* @return block name
*/
public String getName();
@ -122,6 +129,8 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
/**
* Get the comment associated with this block.
*
* @return block comment string
*/
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
*
* @return true if enabled else false
*/
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
*
* @return true if enabled else false
*/
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
*
* @return true if enabled else false
*/
public boolean isExecute();
@ -178,18 +193,41 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
public void setPermissions(boolean read, boolean write, boolean execute);
/**
* Returns the value of the volatile property associated with this block. This attribute is
* Returns the volatile attribute state of this block. This attribute is
* generally associated with block of I/O regions of memory.
*
* @return true if enabled else false
*/
public boolean isVolatile();
/**
* Sets the volatile property associated with this block.
* Sets the volatile attribute state associated of this block. This attribute is
* generally associated with block of I/O regions of memory.
*
* @param v the value to set the volatile property to.
* @param v the volatile attribute state.
*/
public void setVolatile(boolean v);
/**
* Returns the artificial attribute state of this block. This attribute is
* generally associated with blocks which have been fabricated to facilitate
* analysis but do not exist in the same form within a running/loaded process
* state.
*
* @return true if enabled else false
*/
public boolean isArtificial();
/**
* Sets the artificial attribute state associated with this block. This attribute is
* generally associated with blocks which have been fabricated to facilitate
* analysis but do not exist in the same form within a running/loaded process
* state.
*
* @param a the artificial attribute state.
*/
public void setArtificial(boolean a);
/**
* Get the name of the source of this memory block.
*
@ -208,6 +246,7 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
* Returns the byte at the given address in this block.
*
* @param addr the address.
* @return byte value from this block and specified address
* @throws MemoryAccessException if any of the requested bytes are uninitialized.
* @throws IllegalArgumentException if the Address is not in this block.
*/
@ -246,6 +285,7 @@ public interface MemoryBlock extends Serializable, Comparable<MemoryBlock> {
* Puts the given byte at the given address in this block.
*
* @param addr the address.
* @param b byte value
* @throws MemoryAccessException if the block is uninitialized
* @throws IllegalArgumentException if the Address is not in this block.
*/

View File

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

View File

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

View File

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

View File

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