mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-07 09:11:15 -09:00
GP-6148 Changed the byteviewer to display values that cross memory block boundaries in a different color(gray)
This commit is contained in:
@@ -57,7 +57,6 @@ import ghidra.framework.plugintool.annotation.AutoConfigStateField;
|
||||
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.program.util.ProgramSelection;
|
||||
@@ -325,8 +324,8 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
|
||||
* Override where edits are allowed and direct sets through the control service.
|
||||
*/
|
||||
class TargetByteBlock extends MemoryByteBlock {
|
||||
protected TargetByteBlock(Program program, Memory memory, MemoryBlock block) {
|
||||
super(program, memory, block);
|
||||
protected TargetByteBlock(Program program, MemoryBlock block) {
|
||||
super(program, block);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -390,8 +389,8 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MemoryByteBlock newMemoryByteBlock(Memory memory, MemoryBlock memBlock) {
|
||||
return new TargetByteBlock(program, memory, memBlock);
|
||||
protected MemoryByteBlock newMemoryByteBlock(MemoryBlock memBlock) {
|
||||
return new TargetByteBlock(program, memBlock);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -6,6 +6,7 @@ color.bg.byteviewer.highlight.middle.mouse = color.bg.highlight
|
||||
|
||||
color.fg.byteviewer.separator = color.palette.blue
|
||||
color.fg.byteviewer.changed = red
|
||||
color.fg.byteviewer.boundary.crossing = gray
|
||||
|
||||
color.cursor.byteviewer.focused.edit = color.palette.red
|
||||
color.cursor.byteviewer.unfocused.edit = color.palette.pink
|
||||
|
||||
@@ -21,6 +21,20 @@
|
||||
<img src="help/shared/arrow.gif" border="0"> <b>Bytes: ...</b> menu.</p>
|
||||
|
||||
<p>The following paragraphs describe the Byte Viewer.</p>
|
||||
|
||||
<h2>Boundaries</h2>
|
||||
<p>The Byte Viewer creates boundaries between memory blocks. Whenever a memory block
|
||||
boundary is encountered, the Byte Viewer will display a line of dots to indicate the
|
||||
transition to a new memory block. Since the Byte Viewer shows multiple addresses on a line,
|
||||
the block may start or end at some position other than the start of the line. In this case
|
||||
any value positions on a line that are not part of the current block are blank.</p>
|
||||
<p>One special
|
||||
case is when a multi-byte value spans adjacent memory blocks, the value that spans the
|
||||
blocks is shown with the block that it starts in. To indicate that the value spans blocks,
|
||||
it is displayed in a different color, which by default, is gray.</p>
|
||||
<p>Also, note that when a block starts somewhere other than the beginning of the line, the
|
||||
address shows the address of the first byte in the block, regardless of what position it
|
||||
starts at.</p>
|
||||
|
||||
<h2><a name="ToggleFormatAction"></a><a name="formats"></a>Data Formats</h2>
|
||||
<blockquote>
|
||||
|
||||
@@ -70,6 +70,7 @@ public abstract class ByteViewerComponentProvider extends ComponentProviderAdapt
|
||||
static final GColor BG_COLOR = new GColor("color.bg.byteviewer");
|
||||
static final GColor SEPARATOR_COLOR = new GColor("color.fg.byteviewer.separator");
|
||||
|
||||
static final GColor BOUNDARY_CROSSING_COLOR = new GColor("color.fg.byteviewer.boundary.crossing");
|
||||
static final GColor EDITED_TEXT_COLOR = new GColor("color.fg.byteviewer.changed");
|
||||
static final GColor CURSOR_COLOR_FOCUSED_EDIT = new GColor("color.cursor.byteviewer.focused.edit");
|
||||
static final GColor CURSOR_COLOR_UNFOCUSED_EDIT = new GColor("color.cursor.byteviewer.unfocused.edit");
|
||||
|
||||
@@ -119,12 +119,16 @@ class FieldFactory {
|
||||
// The following line is the same as the catch (ByteBlockAccessException) handler.
|
||||
return getByteField(readErrorStr, index);
|
||||
}
|
||||
|
||||
String str = model.getDataRepresentation(block, offset);
|
||||
ByteField bf = new ByteField(str, fm, startX, width, charWidth, false, fieldOffset,
|
||||
index, highlightFactory);
|
||||
if (blockSet.isChanged(block, offset, unitByteSize)) {
|
||||
bf.setForeground(ByteViewerComponentProvider.EDITED_TEXT_COLOR);
|
||||
}
|
||||
else if (crossesBlockBoundary(block, offset)) {
|
||||
bf.setForeground(ByteViewerComponentProvider.BOUNDARY_CROSSING_COLOR);
|
||||
}
|
||||
return bf;
|
||||
}
|
||||
catch (ByteBlockAccessException e) {
|
||||
@@ -139,6 +143,15 @@ class FieldFactory {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean crossesBlockBoundary(ByteBlock block, BigInteger offset) {
|
||||
int unitSize = model.getUnitByteSize();
|
||||
if (unitSize == 1) {
|
||||
return false;
|
||||
}
|
||||
BigInteger lastOffset = offset.add(BigInteger.valueOf(unitSize));
|
||||
return lastOffset.compareTo(block.getLength()) > 0;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
@@ -41,14 +41,26 @@ public class MemoryByteBlock implements ByteBlock {
|
||||
* @param memory memory from a program
|
||||
* @param block block from memory
|
||||
*/
|
||||
protected MemoryByteBlock(Program program, Memory memory, MemoryBlock block) {
|
||||
protected MemoryByteBlock(Program program, MemoryBlock block) {
|
||||
this.program = program;
|
||||
this.memory = memory;
|
||||
this.memory = program.getMemory();
|
||||
this.block = block;
|
||||
this.start = block.getStart();
|
||||
this.bigEndian = memory.isBigEndian();
|
||||
}
|
||||
|
||||
public Address getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public Address getEnd() {
|
||||
return block.getEnd();
|
||||
}
|
||||
|
||||
public boolean contains(Address address) {
|
||||
return block.contains(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the location representation for the given index.
|
||||
*
|
||||
@@ -377,4 +389,5 @@ public class MemoryByteBlock implements ByteBlock {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,10 +35,9 @@ import ghidra.util.NumericUtilities;
|
||||
*/
|
||||
public class ProgramByteBlockSet implements ByteBlockSet {
|
||||
|
||||
private MemoryBlock[] memBlocks;
|
||||
protected final Program program;
|
||||
private ByteBlockChangeManager bbcm;
|
||||
private ByteBlock[] blocks;
|
||||
private MemoryByteBlock[] blocks;
|
||||
private final ProgramByteViewerComponentProvider provider;
|
||||
|
||||
protected ProgramByteBlockSet(ProgramByteViewerComponentProvider provider, Program program,
|
||||
@@ -113,8 +112,8 @@ public class ProgramByteBlockSet implements ByteBlockSet {
|
||||
// Use entries that groups the relevant objects instead of co-indexed arrays
|
||||
// Though a nicety, it becomes necessary if indexing/sorting by start address
|
||||
for (int i = 0; i < blocks.length; i++) {
|
||||
Address blockStart = memBlocks[i].getStart();
|
||||
Address blockEnd = memBlocks[i].getEnd();
|
||||
Address blockStart = blocks[i].getStart();
|
||||
Address blockEnd = blocks[i].getEnd();
|
||||
AddressRange intersection =
|
||||
range.intersect(new AddressRangeImpl(blockStart, blockEnd));
|
||||
if (intersection != null) {
|
||||
@@ -210,7 +209,7 @@ public class ProgramByteBlockSet implements ByteBlockSet {
|
||||
}
|
||||
try {
|
||||
|
||||
Address addr = memBlocks[i].getStart();
|
||||
Address addr = blocks[i].getStart();
|
||||
return addr.addNoWrap(offset);
|
||||
|
||||
}
|
||||
@@ -233,12 +232,12 @@ public class ProgramByteBlockSet implements ByteBlockSet {
|
||||
}
|
||||
|
||||
for (int i = 0; i < blocks.length; i++) {
|
||||
if (!memBlocks[i].contains(address)) {
|
||||
if (!blocks[i].contains(address)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
long off = address.subtract(memBlocks[i].getStart());
|
||||
long off = address.subtract(blocks[i].getStart());
|
||||
BigInteger offset = NumericUtilities.unsignedLongToBigInteger(off);
|
||||
return new ByteBlockInfo(blocks[i], offset);
|
||||
}
|
||||
@@ -254,12 +253,12 @@ public class ProgramByteBlockSet implements ByteBlockSet {
|
||||
}
|
||||
|
||||
protected Address getBlockStart(int blockNumber) {
|
||||
return memBlocks[blockNumber].getStart();
|
||||
return blocks[blockNumber].getStart();
|
||||
}
|
||||
|
||||
protected int getByteBlockNumber(Address blockStartAddr) {
|
||||
for (int i = 0; i < memBlocks.length; i++) {
|
||||
if (memBlocks[i].getStart().compareTo(blockStartAddr) == 0) {
|
||||
for (int i = 0; i < blocks.length; i++) {
|
||||
if (blocks[i].getStart().compareTo(blockStartAddr) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@@ -282,15 +281,15 @@ public class ProgramByteBlockSet implements ByteBlockSet {
|
||||
|
||||
protected void newMemoryBlocks() {
|
||||
Memory memory = program.getMemory();
|
||||
memBlocks = memory.getBlocks();
|
||||
blocks = new ByteBlock[memBlocks.length];
|
||||
MemoryBlock[] memBlocks = memory.getBlocks();
|
||||
blocks = new MemoryByteBlock[memBlocks.length];
|
||||
for (int i = 0; i < memBlocks.length; i++) {
|
||||
blocks[i] = newMemoryByteBlock(memory, memBlocks[i]);
|
||||
blocks[i] = newMemoryByteBlock(memBlocks[i]);
|
||||
}
|
||||
}
|
||||
|
||||
protected MemoryByteBlock newMemoryByteBlock(Memory memory, MemoryBlock memBlock) {
|
||||
return new MemoryByteBlock(program, memory, memBlock);
|
||||
protected MemoryByteBlock newMemoryByteBlock(MemoryBlock memBlock) {
|
||||
return new MemoryByteBlock(program, memBlock);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user