mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-19 16:40:38 -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.framework.plugintool.annotation.AutoServiceConsumed;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.mem.Memory;
|
|
||||||
import ghidra.program.model.mem.MemoryBlock;
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
import ghidra.program.util.ProgramLocation;
|
import ghidra.program.util.ProgramLocation;
|
||||||
import ghidra.program.util.ProgramSelection;
|
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.
|
* Override where edits are allowed and direct sets through the control service.
|
||||||
*/
|
*/
|
||||||
class TargetByteBlock extends MemoryByteBlock {
|
class TargetByteBlock extends MemoryByteBlock {
|
||||||
protected TargetByteBlock(Program program, Memory memory, MemoryBlock block) {
|
protected TargetByteBlock(Program program, MemoryBlock block) {
|
||||||
super(program, memory, block);
|
super(program, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -390,8 +389,8 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected MemoryByteBlock newMemoryByteBlock(Memory memory, MemoryBlock memBlock) {
|
protected MemoryByteBlock newMemoryByteBlock(MemoryBlock memBlock) {
|
||||||
return new TargetByteBlock(program, memory, memBlock);
|
return new TargetByteBlock(program, memBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ color.bg.byteviewer.highlight.middle.mouse = color.bg.highlight
|
|||||||
|
|
||||||
color.fg.byteviewer.separator = color.palette.blue
|
color.fg.byteviewer.separator = color.palette.blue
|
||||||
color.fg.byteviewer.changed = red
|
color.fg.byteviewer.changed = red
|
||||||
|
color.fg.byteviewer.boundary.crossing = gray
|
||||||
|
|
||||||
color.cursor.byteviewer.focused.edit = color.palette.red
|
color.cursor.byteviewer.focused.edit = color.palette.red
|
||||||
color.cursor.byteviewer.unfocused.edit = color.palette.pink
|
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>
|
<img src="help/shared/arrow.gif" border="0"> <b>Bytes: ...</b> menu.</p>
|
||||||
|
|
||||||
<p>The following paragraphs describe the Byte Viewer.</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>
|
<h2><a name="ToggleFormatAction"></a><a name="formats"></a>Data Formats</h2>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ public abstract class ByteViewerComponentProvider extends ComponentProviderAdapt
|
|||||||
static final GColor BG_COLOR = new GColor("color.bg.byteviewer");
|
static final GColor BG_COLOR = new GColor("color.bg.byteviewer");
|
||||||
static final GColor SEPARATOR_COLOR = new GColor("color.fg.byteviewer.separator");
|
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 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_FOCUSED_EDIT = new GColor("color.cursor.byteviewer.focused.edit");
|
||||||
static final GColor CURSOR_COLOR_UNFOCUSED_EDIT = new GColor("color.cursor.byteviewer.unfocused.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.
|
// The following line is the same as the catch (ByteBlockAccessException) handler.
|
||||||
return getByteField(readErrorStr, index);
|
return getByteField(readErrorStr, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
String str = model.getDataRepresentation(block, offset);
|
String str = model.getDataRepresentation(block, offset);
|
||||||
ByteField bf = new ByteField(str, fm, startX, width, charWidth, false, fieldOffset,
|
ByteField bf = new ByteField(str, fm, startX, width, charWidth, false, fieldOffset,
|
||||||
index, highlightFactory);
|
index, highlightFactory);
|
||||||
if (blockSet.isChanged(block, offset, unitByteSize)) {
|
if (blockSet.isChanged(block, offset, unitByteSize)) {
|
||||||
bf.setForeground(ByteViewerComponentProvider.EDITED_TEXT_COLOR);
|
bf.setForeground(ByteViewerComponentProvider.EDITED_TEXT_COLOR);
|
||||||
}
|
}
|
||||||
|
else if (crossesBlockBoundary(block, offset)) {
|
||||||
|
bf.setForeground(ByteViewerComponentProvider.BOUNDARY_CROSSING_COLOR);
|
||||||
|
}
|
||||||
return bf;
|
return bf;
|
||||||
}
|
}
|
||||||
catch (ByteBlockAccessException e) {
|
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() {
|
public int getWidth() {
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,14 +41,26 @@ public class MemoryByteBlock implements ByteBlock {
|
|||||||
* @param memory memory from a program
|
* @param memory memory from a program
|
||||||
* @param block block from memory
|
* @param block block from memory
|
||||||
*/
|
*/
|
||||||
protected MemoryByteBlock(Program program, Memory memory, MemoryBlock block) {
|
protected MemoryByteBlock(Program program, MemoryBlock block) {
|
||||||
this.program = program;
|
this.program = program;
|
||||||
this.memory = memory;
|
this.memory = program.getMemory();
|
||||||
this.block = block;
|
this.block = block;
|
||||||
this.start = block.getStart();
|
this.start = block.getStart();
|
||||||
this.bigEndian = memory.isBigEndian();
|
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.
|
* Get the location representation for the given index.
|
||||||
*
|
*
|
||||||
@@ -377,4 +389,5 @@ public class MemoryByteBlock implements ByteBlock {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,10 +35,9 @@ import ghidra.util.NumericUtilities;
|
|||||||
*/
|
*/
|
||||||
public class ProgramByteBlockSet implements ByteBlockSet {
|
public class ProgramByteBlockSet implements ByteBlockSet {
|
||||||
|
|
||||||
private MemoryBlock[] memBlocks;
|
|
||||||
protected final Program program;
|
protected final Program program;
|
||||||
private ByteBlockChangeManager bbcm;
|
private ByteBlockChangeManager bbcm;
|
||||||
private ByteBlock[] blocks;
|
private MemoryByteBlock[] blocks;
|
||||||
private final ProgramByteViewerComponentProvider provider;
|
private final ProgramByteViewerComponentProvider provider;
|
||||||
|
|
||||||
protected ProgramByteBlockSet(ProgramByteViewerComponentProvider provider, Program program,
|
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
|
// Use entries that groups the relevant objects instead of co-indexed arrays
|
||||||
// Though a nicety, it becomes necessary if indexing/sorting by start address
|
// Though a nicety, it becomes necessary if indexing/sorting by start address
|
||||||
for (int i = 0; i < blocks.length; i++) {
|
for (int i = 0; i < blocks.length; i++) {
|
||||||
Address blockStart = memBlocks[i].getStart();
|
Address blockStart = blocks[i].getStart();
|
||||||
Address blockEnd = memBlocks[i].getEnd();
|
Address blockEnd = blocks[i].getEnd();
|
||||||
AddressRange intersection =
|
AddressRange intersection =
|
||||||
range.intersect(new AddressRangeImpl(blockStart, blockEnd));
|
range.intersect(new AddressRangeImpl(blockStart, blockEnd));
|
||||||
if (intersection != null) {
|
if (intersection != null) {
|
||||||
@@ -210,7 +209,7 @@ public class ProgramByteBlockSet implements ByteBlockSet {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
||||||
Address addr = memBlocks[i].getStart();
|
Address addr = blocks[i].getStart();
|
||||||
return addr.addNoWrap(offset);
|
return addr.addNoWrap(offset);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -233,12 +232,12 @@ public class ProgramByteBlockSet implements ByteBlockSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < blocks.length; i++) {
|
for (int i = 0; i < blocks.length; i++) {
|
||||||
if (!memBlocks[i].contains(address)) {
|
if (!blocks[i].contains(address)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
long off = address.subtract(memBlocks[i].getStart());
|
long off = address.subtract(blocks[i].getStart());
|
||||||
BigInteger offset = NumericUtilities.unsignedLongToBigInteger(off);
|
BigInteger offset = NumericUtilities.unsignedLongToBigInteger(off);
|
||||||
return new ByteBlockInfo(blocks[i], offset);
|
return new ByteBlockInfo(blocks[i], offset);
|
||||||
}
|
}
|
||||||
@@ -254,12 +253,12 @@ public class ProgramByteBlockSet implements ByteBlockSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Address getBlockStart(int blockNumber) {
|
protected Address getBlockStart(int blockNumber) {
|
||||||
return memBlocks[blockNumber].getStart();
|
return blocks[blockNumber].getStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getByteBlockNumber(Address blockStartAddr) {
|
protected int getByteBlockNumber(Address blockStartAddr) {
|
||||||
for (int i = 0; i < memBlocks.length; i++) {
|
for (int i = 0; i < blocks.length; i++) {
|
||||||
if (memBlocks[i].getStart().compareTo(blockStartAddr) == 0) {
|
if (blocks[i].getStart().compareTo(blockStartAddr) == 0) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -282,15 +281,15 @@ public class ProgramByteBlockSet implements ByteBlockSet {
|
|||||||
|
|
||||||
protected void newMemoryBlocks() {
|
protected void newMemoryBlocks() {
|
||||||
Memory memory = program.getMemory();
|
Memory memory = program.getMemory();
|
||||||
memBlocks = memory.getBlocks();
|
MemoryBlock[] memBlocks = memory.getBlocks();
|
||||||
blocks = new ByteBlock[memBlocks.length];
|
blocks = new MemoryByteBlock[memBlocks.length];
|
||||||
for (int i = 0; i < memBlocks.length; i++) {
|
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) {
|
protected MemoryByteBlock newMemoryByteBlock(MemoryBlock memBlock) {
|
||||||
return new MemoryByteBlock(program, memory, memBlock);
|
return new MemoryByteBlock(program, memBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user