Merge remote-tracking branch 'origin/GP-6123_Dan_fixtTaintRegColumn'

This commit is contained in:
Ryan Kurtz
2026-01-20 04:41:56 -05:00
3 changed files with 159 additions and 78 deletions

View File

@@ -35,6 +35,7 @@ import docking.*;
import docking.action.*;
import docking.action.builder.ActionBuilder;
import docking.actions.PopupActionProvider;
import docking.widgets.AbstractGCellRenderer;
import docking.widgets.table.*;
import docking.widgets.table.ColumnSortState.SortDirection;
import docking.widgets.table.DefaultEnumeratedColumnTableModel.EnumeratedTableColumn;
@@ -411,28 +412,32 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
}
}
public static void applyStateColors(AbstractGCellRenderer renderer,
GTableCellRenderingData data, Predicate<RegisterRow> isChanged) {
RegisterRow row = (RegisterRow) data.getRowObject();
if (!row.isKnown()) {
if (data.isSelected()) {
renderer.setForeground(COLOR_FOREGROUND_STALE_SEL);
}
else {
renderer.setForeground(COLOR_FOREGROUND_STALE);
}
}
else if (isChanged.test(row)) {
if (data.isSelected()) {
renderer.setForeground(COLOR_FOREGROUND_CHANGED_SEL);
}
else {
renderer.setForeground(COLOR_FOREGROUND_CHANGED);
}
}
}
static class RegisterValueCellRenderer extends HexDefaultGColumnRenderer<BigInteger> {
@Override
public final Component getTableCellRendererComponent(GTableCellRenderingData data) {
super.getTableCellRendererComponent(data);
setFont(getFixedWidthFont());
RegisterRow row = (RegisterRow) data.getRowObject();
if (!row.isKnown()) {
if (data.isSelected()) {
setForeground(COLOR_FOREGROUND_STALE_SEL);
}
else {
setForeground(COLOR_FOREGROUND_STALE);
}
}
else if (row.isChanged()) {
if (data.isSelected()) {
setForeground(COLOR_FOREGROUND_CHANGED_SEL);
}
else {
setForeground(COLOR_FOREGROUND_CHANGED);
}
}
applyStateColors(this, data, RegisterRow::isChanged);
return this;
}
}
@@ -1055,7 +1060,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
if (previous.getThread() == null || current.getThread() == null) {
return false;
}
if (previous.getPlatform().getLanguage() != current.getPlatform().getLanguage()) {
if (previous.getLanguage() != current.getLanguage()) {
return false;
}
if (!isRegisterKnown(register)) {
@@ -1328,6 +1333,10 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
return current;
}
public DebuggerCoordinates getPrevious() {
return previous;
}
private void reportError(String title, String message, Throwable ex) {
plugin.getTool().setStatusInfo(message + ": " + ex.getMessage());
if (title != null) {

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -211,4 +211,13 @@ public class RegisterRow {
public DebuggerCoordinates getCurrent() {
return provider.getCurrent();
}
/**
* Get the table's previous coordinates (for change indication)
*
* @return the coordinates
*/
public DebuggerCoordinates getPrevious() {
return provider.getPrevious();
}
}

View File

@@ -15,20 +15,22 @@
*/
package ghidra.taint.gui.field;
import docking.widgets.table.AbstractDynamicTableColumn;
import docking.widgets.table.DynamicTableColumn;
import ghidra.app.plugin.core.debug.gui.register.DebuggerRegisterColumnFactory;
import ghidra.app.plugin.core.debug.gui.register.RegisterRow;
import java.awt.Component;
import java.util.Objects;
import docking.widgets.table.*;
import ghidra.app.plugin.core.debug.gui.register.*;
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
import ghidra.docking.settings.Settings;
import ghidra.framework.plugintool.ServiceProvider;
import ghidra.pcode.emu.taint.state.TaintPieceHandler;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.Register;
import ghidra.trace.model.Trace;
import ghidra.trace.model.property.TracePropertyMap;
import ghidra.trace.model.property.TracePropertyMapSpace;
import ghidra.trace.model.thread.TraceThread;
import ghidra.util.table.column.AbstractGColumnRenderer;
import ghidra.util.table.column.GColumnRenderer;
/**
* A factory for the "Taint" column in the "Registers" panel
@@ -38,60 +40,121 @@ import ghidra.trace.model.property.TracePropertyMapSpace;
* screen.
*/
public class TaintDebuggerRegisterColumnFactory implements DebuggerRegisterColumnFactory {
private static TracePropertyMapSpace<String> getTaintSpace(DebuggerCoordinates coords,
Register register) {
TracePropertyMap<String> taintMap =
coords.getTrace().getAddressPropertyManager().getPropertyMap(PROP_NAME, String.class);
if (taintMap == null) {
return null;
}
AddressSpace addressSpace = register.getAddressSpace();
if (addressSpace.isRegisterSpace()) {
return taintMap.getPropertyMapRegisterSpace(coords.getThread(),
coords.getFrame(), false);
}
return taintMap.getPropertyMapSpace(addressSpace, false);
}
private static String getTaintValue(DebuggerCoordinates coords,
TracePropertyMapSpace<String> taintSpace, Register register) {
// Cheat the deserialization/reserialization here
AddressRange range = coords.getPlatform()
.getConventionalRegisterRange(taintSpace.getAddressSpace(), register);
StringBuffer vec = new StringBuffer();
for (Address addr : range) {
vec.append('[');
String taint = taintSpace.get(coords.getViewSnap(), addr);
vec.append(taint == null ? "" : taint);
vec.append(']');
}
return vec.toString();
}
private static String getTaintValue(DebuggerCoordinates coords, RegisterRow row) {
TraceThread thread = coords.getThread();
if (thread == null) {
return null;
}
Register register = row.getRegister();
TracePropertyMapSpace<String> taintSpace = getTaintSpace(coords, register);
if (taintSpace == null) {
return null;
}
return getTaintValue(coords, taintSpace, register);
}
private static class TaintDebuggerRegisterCellRenderer extends AbstractGColumnRenderer<String> {
@Override
public Component getTableCellRendererComponent(GTableCellRenderingData data) {
super.getTableCellRendererComponent(data);
DebuggerRegistersProvider.applyStateColors(this, data, this::isChanged);
return this;
}
@Override
public String getFilterString(String t, Settings settings) {
return t;
}
private boolean isChanged(RegisterRow row) {
if (row.getPrevious().getThread() == null || row.getCurrent().getThread() == null) {
return false;
}
if (row.getPrevious().getLanguage() != row.getCurrent().getLanguage()) {
return false;
}
if (!row.isKnown()) {
return false;
}
Register register = row.getRegister();
TracePropertyMapSpace<String> curTaintSpace =
getTaintSpace(row.getCurrent(), register);
if (curTaintSpace == null) {
return false; // unlikely
}
TracePropertyMapSpace<String> prevTaintSpace =
getTaintSpace(row.getPrevious(), register);
if (prevTaintSpace == null) {
return false;
}
String curTaintValue = getTaintValue(row.getCurrent(), curTaintSpace, register);
String prevTaintValue = getTaintValue(row.getPrevious(), prevTaintSpace, register);
return !Objects.equals(curTaintValue, prevTaintValue);
}
}
private static final TaintDebuggerRegisterCellRenderer RENDERER =
new TaintDebuggerRegisterCellRenderer();
private static class TaintDebuggerRegisterColumn
extends AbstractDynamicTableColumn<RegisterRow, String, Void> {
@Override
public String getColumnName() {
return COL_NAME;
}
@Override
public GColumnRenderer<String> getColumnRenderer() {
return RENDERER;
}
@Override
public String getValue(RegisterRow rowObject, Settings settings, Void dataSource,
ServiceProvider serviceProvider) throws IllegalArgumentException {
String value = getTaintValue(rowObject.getCurrent(), rowObject);
return value == null ? "" : value;
}
}
protected static final String PROP_NAME = TaintPieceHandler.NAME;
public static final String COL_NAME = "Taint";
@Override
public DynamicTableColumn<RegisterRow, ?, ?> create() {
return new AbstractDynamicTableColumn<RegisterRow, String, Void>() {
@Override
public String getColumnName() {
return COL_NAME;
}
@Override
public String getValue(RegisterRow rowObject, Settings settings, Void dataSource,
ServiceProvider serviceProvider) throws IllegalArgumentException {
DebuggerCoordinates current = rowObject.getCurrent();
Trace trace = current.getTrace();
if (trace == null) {
return "";
}
TracePropertyMap<String> taintMap = current.getTrace()
.getAddressPropertyManager()
.getPropertyMap(PROP_NAME, String.class);
if (taintMap == null) {
return "";
}
Register register = rowObject.getRegister();
TracePropertyMapSpace<String> taintSpace;
AddressSpace addressSpace = register.getAddressSpace();
if (addressSpace.isRegisterSpace()) {
taintSpace = taintMap.getPropertyMapRegisterSpace(current.getThread(),
current.getFrame(), false);
}
else {
taintSpace = taintMap.getPropertyMapSpace(addressSpace, false);
}
if (taintSpace == null) {
return "";
}
// Cheat the deserialization/reserialization here
StringBuffer vec = new StringBuffer();
int count = register.getNumBytes();
Address start = register.getAddress();
for (int i = 0; i < count; i++) {
vec.append('[');
String taint = taintSpace.get(current.getViewSnap(), start.addWrap(i));
vec.append(taint == null ? "" : taint);
vec.append(']');
}
return vec.toString();
}
};
return new TaintDebuggerRegisterColumn();
}
}