mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
commit
a5e16b7237
10 changed files with 112 additions and 73 deletions
|
@ -57,7 +57,7 @@
|
|||
|
||||
<LI>Address - when evaluation succeeds, the address of the watch's value. This field is
|
||||
really only meaningful when the outermost operator of the expression is a memory dereference.
|
||||
Double-clicking a row will navigate the primary dynamic listing to this address, if
|
||||
Double-clicking this cell will navigate the primary dynamic listing to this address, if
|
||||
possible.</LI>
|
||||
|
||||
<LI>Value - the raw bytes of the watched buffer. If the expression is a register, then this
|
||||
|
@ -71,7 +71,9 @@
|
|||
possible.</LI>
|
||||
|
||||
<LI>Representation - the value of the watch as interpreted by the selected data type. This
|
||||
field is not yet user modifiable, even if the <B>Enable Edits</B> toggle is on.</LI>
|
||||
field is not yet user modifiable, even if the <B>Enable Edits</B> toggle is on. If the value
|
||||
is an address, i.e., Type is a pointer, then double-clicking this cell will navigate the
|
||||
primary dynamic listing, if possible.</LI>
|
||||
|
||||
<LI>Error - if an error occurs during compilation or evaluation of the expression, that error
|
||||
is rendered here. Double-clicking the row will display the stack trace. Note that errors
|
||||
|
|
|
@ -20,7 +20,6 @@ import java.awt.FontMetrics;
|
|||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import docking.widgets.fieldpanel.internal.LayoutBackgroundColorManager;
|
||||
import docking.widgets.fieldpanel.support.FieldSelection;
|
||||
|
@ -34,7 +33,6 @@ import ghidra.framework.options.AutoOptions;
|
|||
import ghidra.framework.options.annotation.AutoOptionConsumed;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.memory.TraceMemoryState;
|
||||
|
||||
public class DebuggerMemoryByteViewerComponent extends ByteViewerComponent
|
||||
|
@ -71,37 +69,45 @@ public class DebuggerMemoryByteViewerComponent extends ByteViewerComponent
|
|||
}
|
||||
Trace trace = coordinates.getTrace();
|
||||
// TODO: Mimic the listing's background, or factor into common
|
||||
long snap = coordinates.getSnap();
|
||||
long viewSnap = coordinates.getViewSnap();
|
||||
// TODO: Span out and cache?
|
||||
AddressSetView lineAddresses = translator.convertFieldToAddress(lineFieldSel);
|
||||
// Because UNKNOWN need not be explicitly recorded, compute it by subtracting others
|
||||
AddressSet unknown = new AddressSet(lineAddresses);
|
||||
for (AddressRange range : lineAddresses) {
|
||||
for (Entry<TraceAddressSnapRange, TraceMemoryState> entry : trace.getMemoryManager()
|
||||
.getStates(snap, range)) {
|
||||
if (entry.getValue() != TraceMemoryState.UNKNOWN) {
|
||||
unknown.delete(entry.getKey().getRange());
|
||||
}
|
||||
Color color = colorForState(entry.getValue());
|
||||
if (color == null) {
|
||||
continue;
|
||||
}
|
||||
// NOTE: Only TraceMemoryState.ERROR should reach here
|
||||
FieldSelection resultFieldSel =
|
||||
translator.convertAddressToField(entry.getKey().getRange());
|
||||
if (!resultFieldSel.isEmpty()) {
|
||||
selections.add(new ColoredFieldSelection(resultFieldSel, color));
|
||||
}
|
||||
AddressSet known = new AddressSet();
|
||||
AddressSet error = new AddressSet();
|
||||
|
||||
for (Address addr : lineAddresses.getAddresses(true)) {
|
||||
TraceMemoryState state =
|
||||
trace.getMemoryManager().getViewState(viewSnap, addr).getValue();
|
||||
switch (state) {
|
||||
case KNOWN:
|
||||
known.add(addr);
|
||||
break;
|
||||
case ERROR:
|
||||
error.add(addr);
|
||||
break;
|
||||
default:
|
||||
// Don't care
|
||||
}
|
||||
}
|
||||
if (unknownColor == null) {
|
||||
AddressSet unknown = new AddressSet(lineAddresses);
|
||||
unknown.delete(known);
|
||||
unknown.delete(error);
|
||||
|
||||
doAddSelections(unknownColor, unknown, translator, selections);
|
||||
doAddSelections(errorColor, error, translator, selections);
|
||||
}
|
||||
|
||||
protected void doAddSelections(Color color, AddressSetView set,
|
||||
SelectionTranslator translator, List<ColoredFieldSelection> selections) {
|
||||
if (color == null) {
|
||||
return;
|
||||
}
|
||||
for (AddressRange unk : unknown) {
|
||||
FieldSelection resultFieldSel = translator.convertAddressToField(unk);
|
||||
if (!resultFieldSel.isEmpty()) {
|
||||
selections.add(new ColoredFieldSelection(resultFieldSel, unknownColor));
|
||||
for (AddressRange rng : set) {
|
||||
FieldSelection resultFieldSel = translator.convertAddressToField(rng);
|
||||
if (resultFieldSel.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
selections.add(new ColoredFieldSelection(resultFieldSel, color));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -133,18 +139,6 @@ public class DebuggerMemoryByteViewerComponent extends ByteViewerComponent
|
|||
// NOTE: Cursor, being line-by-line, is done via background color model in super
|
||||
}
|
||||
|
||||
protected Color colorForState(TraceMemoryState state) {
|
||||
switch (state) {
|
||||
case ERROR:
|
||||
return errorColor;
|
||||
case KNOWN:
|
||||
return null;
|
||||
case UNKNOWN:
|
||||
return unknownColor;
|
||||
}
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LayoutBackgroundColorManager getLayoutSelectionMap(BigInteger layoutIndex) {
|
||||
Color backgroundColor = backgroundColorModel.getBackgroundColor(layoutIndex);
|
||||
|
|
|
@ -334,24 +334,7 @@ public class DebuggerWatchesProvider extends ComponentProviderAdapter {
|
|||
if (e.getClickCount() != 2 || e.getButton() != MouseEvent.BUTTON1) {
|
||||
return;
|
||||
}
|
||||
if (myActionContext == null) {
|
||||
return;
|
||||
}
|
||||
WatchRow row = myActionContext.getWatchRow();
|
||||
if (row == null) {
|
||||
return;
|
||||
}
|
||||
Throwable error = row.getError();
|
||||
if (error != null) {
|
||||
Msg.showError(this, getComponent(), "Evaluation error",
|
||||
"Could not evaluate watch", error);
|
||||
return;
|
||||
}
|
||||
Address address = myActionContext.getWatchRow().getAddress();
|
||||
if (listingService == null || address == null || !address.isMemoryAddress()) {
|
||||
return;
|
||||
}
|
||||
listingService.goTo(address, true);
|
||||
navigateToSelectedWatch();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -371,6 +354,44 @@ public class DebuggerWatchesProvider extends ComponentProviderAdapter {
|
|||
super.contextChanged();
|
||||
}
|
||||
|
||||
protected void navigateToSelectedWatch() {
|
||||
if (myActionContext == null) {
|
||||
return;
|
||||
}
|
||||
WatchRow row = myActionContext.getWatchRow();
|
||||
if (row == null) {
|
||||
return;
|
||||
}
|
||||
int modelCol = watchTable.convertColumnIndexToModel(watchTable.getSelectedColumn());
|
||||
Throwable error = row.getError(); // I don't care the selected column for errors
|
||||
if (error != null) {
|
||||
Msg.showError(this, getComponent(), "Evaluation error",
|
||||
"Could not evaluate watch", error);
|
||||
}
|
||||
else if (modelCol == WatchTableColumns.ADDRESS.ordinal()) {
|
||||
Address address = row.getAddress();
|
||||
if (address != null) {
|
||||
navigateToAddress(address);
|
||||
}
|
||||
}
|
||||
else if (modelCol == WatchTableColumns.REPR.ordinal()) {
|
||||
Object val = row.getValueObj();
|
||||
if (val instanceof Address) {
|
||||
navigateToAddress((Address) val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void navigateToAddress(Address address) {
|
||||
if (listingService == null) {
|
||||
return;
|
||||
}
|
||||
if (address.isMemoryAddress()) {
|
||||
listingService.goTo(address, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
protected void createActions() {
|
||||
actionEnableEdits = DebuggerResources.EnableEditsAction.builder(plugin)
|
||||
.enabledWhen(c -> current.getTrace() != null)
|
||||
|
|
|
@ -64,6 +64,7 @@ public class WatchRow {
|
|||
private byte[] value;
|
||||
private byte[] prevValue; // Value at previous coordinates
|
||||
private String valueString;
|
||||
private Object valueObj;
|
||||
private Throwable error = null;
|
||||
|
||||
public WatchRow(DebuggerWatchesProvider provider, String expression) {
|
||||
|
@ -77,6 +78,7 @@ public class WatchRow {
|
|||
reads = null;
|
||||
value = null;
|
||||
valueString = null;
|
||||
valueObj = null;
|
||||
}
|
||||
|
||||
protected void recompile() {
|
||||
|
@ -125,20 +127,29 @@ public class WatchRow {
|
|||
address = valueWithAddress.getRight();
|
||||
reads = executorWithAddress.getReads();
|
||||
|
||||
valueString = parseAsDataType();
|
||||
valueObj = parseAsDataTypeObj();
|
||||
valueString = parseAsDataTypeStr();
|
||||
}
|
||||
catch (Exception e) {
|
||||
error = e;
|
||||
}
|
||||
}
|
||||
|
||||
protected String parseAsDataType() {
|
||||
protected String parseAsDataTypeStr() {
|
||||
if (dataType == null || value == null) {
|
||||
return "";
|
||||
}
|
||||
MemBuffer buffer = new ByteMemBufferImpl(address, value, language.isBigEndian());
|
||||
return dataType.getRepresentation(buffer, SettingsImpl.NO_SETTINGS, value.length);
|
||||
}
|
||||
|
||||
protected Object parseAsDataTypeObj() {
|
||||
if (dataType == null || value == null) {
|
||||
return null;
|
||||
}
|
||||
MemBuffer buffer = new ByteMemBufferImpl(address, value, language.isBigEndian());
|
||||
return dataType.getValue(buffer, SettingsImpl.NO_SETTINGS, value.length);
|
||||
}
|
||||
|
||||
public static class ReadDepsTraceBytesPcodeExecutorState
|
||||
extends TraceBytesPcodeExecutorState {
|
||||
|
@ -299,7 +310,8 @@ public class WatchRow {
|
|||
public void setDataType(DataType dataType) {
|
||||
this.typePath = dataType == null ? null : dataType.getPathName();
|
||||
this.dataType = dataType;
|
||||
valueString = parseAsDataType();
|
||||
valueString = parseAsDataTypeStr();
|
||||
valueObj = parseAsDataTypeObj();
|
||||
provider.contextChanged();
|
||||
}
|
||||
|
||||
|
@ -357,6 +369,10 @@ public class WatchRow {
|
|||
return valueString;
|
||||
}
|
||||
|
||||
public Object getValueObj() {
|
||||
return valueObj;
|
||||
}
|
||||
|
||||
public boolean isValueEditable() {
|
||||
return address != null && provider.isEditsEnabled();
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ dependencies {
|
|||
runtimeOnly "org.slf4j:slf4j-nop:1.7.25"
|
||||
|
||||
// use this if you want slf4j log messages sent to log4j
|
||||
// runtimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:2.17.0"
|
||||
// runtimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:2.17.1"
|
||||
|
||||
compileOnly "junit:junit:4.12"
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ public class ObjectiveC2_Class implements StructConverter {
|
|||
AddressSpace space = _state.program.getAddressFactory().getDefaultAddressSpace();
|
||||
Address addr = space.getAddress(_index);
|
||||
Symbol symbol = _state.program.getSymbolTable().getPrimarySymbol(addr);
|
||||
if (symbol.getParentNamespace().getName().equals(SectionNames.SECT_GOT)) {
|
||||
if (symbol != null && symbol.getParentNamespace().getName().equals(SectionNames.SECT_GOT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,9 +37,15 @@ public class ObjectiveC2_Method extends ObjectiveC_Method {
|
|||
|
||||
if (isSmallList) {
|
||||
int nameOffset = (int)ObjectiveC1_Utilities.readNextIndex(reader, true);
|
||||
int namePtr = reader.readInt(_index + nameOffset);
|
||||
long imagebase = state.program.getImageBase().getOffset(); // When we support dyld_shared_cache, this base will likely have to change
|
||||
name = reader.readAsciiString(imagebase + namePtr);
|
||||
long namePtr;
|
||||
if (state.is32bit) {
|
||||
namePtr = reader.readInt(_index + nameOffset);
|
||||
}
|
||||
else {
|
||||
namePtr = reader.readLong(_index + nameOffset);
|
||||
}
|
||||
|
||||
name = reader.readAsciiString(namePtr);
|
||||
|
||||
int typesOffset = (int)ObjectiveC1_Utilities.readNextIndex(reader, true);
|
||||
types = reader.readAsciiString(_index + 4 + typesOffset);
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
MODULE FILE LICENSE: lib/cglib-nodep-2.2.jar Apache License 2.0
|
||||
MODULE FILE LICENSE: lib/guava-19.0.jar Apache License 2.0
|
||||
MODULE FILE LICENSE: lib/jdom-legacy-1.1.3.jar JDOM License
|
||||
MODULE FILE LICENSE: lib/log4j-api-2.17.0.jar Apache License 2.0
|
||||
MODULE FILE LICENSE: lib/log4j-core-2.17.0.jar Apache License 2.0
|
||||
MODULE FILE LICENSE: lib/log4j-api-2.17.1.jar Apache License 2.0
|
||||
MODULE FILE LICENSE: lib/log4j-core-2.17.1.jar Apache License 2.0
|
||||
MODULE FILE LICENSE: lib/commons-collections4-4.1.jar Apache License 2.0
|
||||
MODULE FILE LICENSE: lib/commons-lang3-3.9.jar Apache License 2.0
|
||||
MODULE FILE LICENSE: lib/commons-io-2.6.jar Apache License 2.0
|
||||
MODULE FILE LICENSE: lib/commons-text-1.6.jar Apache License 2.0
|
||||
MODULE FILE LICENSE: lib/gson-2.8.6.jar Apache License 2.0
|
||||
MODULE FILE LICENSE: lib/gson-2.8.9.jar Apache License 2.0
|
||||
MODULE FILE LICENSE: lib/bcpkix-jdk15on-1.69.jar Bouncy Castle License
|
||||
MODULE FILE LICENSE: lib/bcprov-jdk15on-1.69.jar Bouncy Castle License
|
||||
MODULE FILE LICENSE: lib/bcutil-jdk15on-1.69.jar Bouncy Castle License
|
||||
|
|
|
@ -29,13 +29,13 @@ dependencies {
|
|||
api "cglib:cglib-nodep:2.2"
|
||||
api "com.google.guava:guava:19.0"
|
||||
api "org.jdom:jdom-legacy:1.1.3"
|
||||
api "org.apache.logging.log4j:log4j-api:2.17.0"
|
||||
api "org.apache.logging.log4j:log4j-core:2.17.0"
|
||||
api "org.apache.logging.log4j:log4j-api:2.17.1"
|
||||
api "org.apache.logging.log4j:log4j-core:2.17.1"
|
||||
api "org.apache.commons:commons-collections4:4.1"
|
||||
api "org.apache.commons:commons-lang3:3.9"
|
||||
api "org.apache.commons:commons-text:1.6"
|
||||
api "commons-io:commons-io:2.6"
|
||||
api "com.google.code.gson:gson:2.8.6"
|
||||
api "com.google.code.gson:gson:2.8.9"
|
||||
api 'org.bouncycastle:bcpkix-jdk15on:1.69' // requires bcutil and bcprov
|
||||
api 'org.bouncycastle:bcprov-jdk15on:1.69'
|
||||
api 'org.bouncycastle:bcutil-jdk15on:1.69'
|
||||
|
|
|
@ -19,7 +19,7 @@ eclipse.project.name = '_JsonDoclet'
|
|||
apply plugin: 'java-library'
|
||||
|
||||
dependencies {
|
||||
api "com.google.code.gson:gson:2.8.6"
|
||||
api "com.google.code.gson:gson:2.8.9"
|
||||
}
|
||||
|
||||
rootProject.createJsondocs.dependsOn jar
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue