mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-25 05:32:14 +00:00
Merge remote-tracking branch 'origin/GP-4125_ghidra1_ArtificialBlockAttribute--SQUASHED'
This commit is contained in:
commit
c3c34ebf10
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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?
|
||||
|
@ -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?
|
||||
|
@ -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. Overlay blocks can serve various
|
||||
purposes where a memory range may contain different data/code or map to different areas of memory
|
||||
at any given point in time or processor state. Note that
|
||||
overlay blocks are fixed and may not be moved, split, merged or expanded. In addition, Overlays
|
||||
do not relocate with image base changes and have significant limitations in conjunction with
|
||||
within the same overlay address space where the <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. 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 |
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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() {
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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()
|
||||
|
@ -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");
|
||||
|
@ -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(" ", "_");
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user