GP-6691 - Data Type Finder - Updated search results to include the field name if one is available. Added a new table column to show just the field name.

This commit is contained in:
dragonmacher
2026-05-01 17:39:14 -04:00
parent 7db1b83ff5
commit 0999e6b9a4
12 changed files with 109 additions and 97 deletions
@@ -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.
@@ -16,6 +16,7 @@
package ghidra.app.plugin.core.navigation.locationreferences;
import ghidra.program.database.symbol.FunctionSymbol;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.*;
@@ -67,7 +68,14 @@ public class FunctionDefinitionLocationDescriptor extends GenericDataTypeLocatio
continue;
}
accumulator.add(new LocationReference(symbol.getAddress()));
ProgramLocation location = symbol.getProgramLocation();
Address address = symbol.getAddress();
if (location != null) {
accumulator.add(new LocationReference(address, null, location));
}
else {
accumulator.add(new LocationReference(address));
}
}
}
@@ -38,6 +38,11 @@ public class LocationReference implements Comparable<LocationReference> {
private final SearchLocationContext context;
private final ProgramLocation location;
/**
* Optional field name.
*/
private String fieldName;
/**
* Optional reference object. Some clients do not have actual references.
*/
@@ -67,20 +72,25 @@ public class LocationReference implements Comparable<LocationReference> {
this.reference = reference;
}
LocationReference(Address locationOfUseAddress, String refType, boolean isOffcutReference) {
this(locationOfUseAddress, null, refType, EMPTY_CONTEXT, isOffcutReference);
LocationReference(Reference reference, boolean isOffcutReference, String fieldName) {
this(reference.getFromAddress(), null, getRefType(reference), EMPTY_CONTEXT,
isOffcutReference);
this.reference = reference;
this.fieldName = fieldName;
}
LocationReference(Address locationOfUseAddress) {
this(locationOfUseAddress, null, null, EMPTY_CONTEXT, false);
}
LocationReference(Address locationOfUseAddress, String context) {
LocationReference(Address locationOfUseAddress, SearchLocationContext context) {
this(locationOfUseAddress, null, null, SearchLocationContext.get(context), false);
}
LocationReference(Address locationOfUseAddress, SearchLocationContext context) {
LocationReference(Address locationOfUseAddress, SearchLocationContext context,
String fieldName) {
this(locationOfUseAddress, null, null, SearchLocationContext.get(context), false);
this.fieldName = fieldName;
}
LocationReference(Address locationOfUseAddress, String context, ProgramLocation location) {
@@ -150,6 +160,14 @@ public class LocationReference implements Comparable<LocationReference> {
return reference;
}
/**
* Returns the field name for this location reference or null if there is no field name.
* @return the field name; may be null
*/
public String getFieldName() {
return fieldName;
}
/**
* Returns true if this class has a {@link Reference} and that reference is not dynamic (i.e.,
* the reference exists in the database).
@@ -23,6 +23,7 @@ import org.apache.commons.lang3.StringUtils;
import docking.widgets.search.SearchLocationContext;
import docking.widgets.search.SearchLocationContextRenderer;
import docking.widgets.table.GTableCellRenderingData;
import docking.widgets.table.TableColumnDescriptor;
import ghidra.docking.settings.Settings;
import ghidra.framework.plugintool.ServiceProvider;
import ghidra.program.model.address.Address;
@@ -57,8 +58,14 @@ class LocationReferencesTableModel extends AddressBasedTableModel<LocationRefere
super("References", locationReferencesProvider.getTool(),
locationReferencesProvider.getProgram(), null, true);
this.provider = locationReferencesProvider;
}
addTableColumn(new ContextTableColumn());
@Override
protected TableColumnDescriptor<LocationReference> createTableColumnDescriptor() {
TableColumnDescriptor<LocationReference> descriptor = super.createTableColumnDescriptor();
descriptor.addVisibleColumn(new ContextColumn());
descriptor.addHiddenColumn(new FieldNameColumn());
return descriptor;
}
@Override
@@ -128,7 +135,7 @@ class LocationReferencesTableModel extends AddressBasedTableModel<LocationRefere
// Inner Classes
//==================================================================================================
private class ContextTableColumn
private class ContextColumn
extends AbstractProgramBasedDynamicTableColumn<LocationReference, LocationReference> {
private static final String OFFCUT_STRING = "<< OFFCUT >>";
@@ -262,7 +269,7 @@ class LocationReferencesTableModel extends AddressBasedTableModel<LocationRefere
}
SearchLocationContext context = rowObject.getContext();
return contextRenderer.renderHtmlContext(data, context);
return contextRenderer.renderHtmlContext(data, context, true);
}
@Override
@@ -279,4 +286,19 @@ class LocationReferencesTableModel extends AddressBasedTableModel<LocationRefere
}
private class FieldNameColumn
extends AbstractProgramBasedDynamicTableColumn<LocationReference, String> {
@Override
public String getColumnName() {
return "Field Name";
}
@Override
public String getValue(LocationReference rowObject, Settings settings,
Program data, ServiceProvider sp) throws IllegalArgumentException {
return rowObject.getFieldName();
}
}
}
@@ -330,7 +330,9 @@ public final class ReferenceUtils {
Consumer<DataTypeReference> callback = ref -> {
SearchLocationContext context = ref.getContext();
LocationReference locationReference = new LocationReference(ref.getAddress(), context);
String fieldName = ref.getFieldName();
LocationReference locationReference =
new LocationReference(ref.getAddress(), context, fieldName);
accumulator.add(locationReference);
};
@@ -1039,9 +1041,11 @@ public final class ReferenceUtils {
private static LocationReference createReferenceFromDefinedData(Data data,
FieldMatcher fieldMatcher) {
Address dataAddress = data.getMinAddress();
String pathName = data.getPathName();
if (fieldMatcher.isIgnored()) {
// no field to match; include the hit
return new LocationReference(dataAddress, data.getPathName());
SearchLocationContext context = SearchLocationContext.get(pathName);
return new LocationReference(dataAddress, context);
}
DataType dt = data.getDataType();
@@ -1052,8 +1056,11 @@ public final class ReferenceUtils {
}
DataType baseDt = getBaseDataType(data.getDataType());
String fieldName = fieldMatcher.getFieldName();
if (matchesEnumField(data, baseDt, fieldMatcher)) {
return new LocationReference(dataAddress, fieldMatcher.getDisplayText());
String text = fieldMatcher.getDisplayText();
SearchLocationContext context = SearchLocationContext.get(text);
return new LocationReference(dataAddress, context, fieldName);
}
DataTypeComponent component = getDataTypeComponent(baseDt, fieldMatcher);
@@ -1064,13 +1071,14 @@ public final class ReferenceUtils {
Address componentAddress;
try {
componentAddress = dataAddress.addNoWrap(component.getOffset());
return new LocationReference(componentAddress,
data.getPathName() + "." + fieldMatcher.getFieldName());
String text = pathName + "." + fieldName;
SearchLocationContext context = SearchLocationContext.get(text);
return new LocationReference(componentAddress, context, fieldName);
}
catch (AddressOverflowException e) {
// shouldn't happen
Msg.error(ReferenceUtils.class, "Unable to create address for sub-component of " +
data.getPathName() + " at " + dataAddress, e);
pathName + " at " + dataAddress, e);
}
return null;
}
@@ -1165,7 +1173,7 @@ public final class ReferenceUtils {
Consumer<LocationReference> consumer =
locationReference -> accumulator.add(locationReference);
Program program = data.getProgram();
accumulateDirectReferences(consumer, program, dataAddress);
accumulateDirectReferences(consumer, program, fieldMatcher, dataAddress);
Consumer<Reference> referenceConsumer = reference -> {
Address toAddress = reference.getToAddress();
@@ -1177,7 +1185,8 @@ public final class ReferenceUtils {
// have a field match; only add the reference if it is directly to the field
if (toAddress.equals(dataAddress)) {
accumulator.add(new LocationReference(reference, false));
String fieldName = fieldMatcher.getFieldName();
accumulator.add(new LocationReference(reference, false, fieldName));
}
};
accumulateOffcutReferences(referenceConsumer, data, monitor);
@@ -1264,8 +1273,8 @@ public final class ReferenceUtils {
ReferenceManager referenceManager = program.getReferenceManager();
Reference[] variableRefsTo = referenceManager.getReferencesTo(variable);
for (Reference ref : variableRefsTo) {
accumulator
.add(new LocationReference(ref, !ref.getToAddress().equals(variableAddress)));
Address toAddress = ref.getToAddress();
accumulator.add(new LocationReference(ref, !toAddress.equals(variableAddress)));
}
}
@@ -1348,12 +1357,18 @@ public final class ReferenceUtils {
private static void accumulateDirectReferences(Consumer<LocationReference> consumer,
Program program, Address address) {
accumulateDirectReferences(consumer, program, null, address);
}
private static void accumulateDirectReferences(Consumer<LocationReference> consumer,
Program program, FieldMatcher fieldMatcher, Address address) {
String fieldName = fieldMatcher != null ? fieldMatcher.getFieldName() : null;
boolean isOffcut = isOffcut(program, address);
ReferenceIterator iter = program.getReferenceManager().getReferencesTo(address);
while (iter.hasNext()) {
Reference ref = iter.next();
consumer.accept(new LocationReference(ref, isOffcut));
consumer.accept(new LocationReference(ref, isOffcut, fieldName));
}
}
@@ -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.
@@ -72,7 +72,7 @@ class XRefLocationDescriptor extends LocationDescriptor {
}
protected Address getXRefAddress(ProgramLocation location) {
return ((XRefFieldLocation) location).getRefAddress();
return location.getRefAddress();
}
protected String getLabelForLocation(ProgramLocation location) {
@@ -58,6 +58,10 @@ public class DataTypeReference {
return context;
}
public String getFieldName() {
return fieldName;
}
@Override
public String toString() {
String fieldNameText = fieldName == null ? "" : "\tfieldName: " + fieldName + "\n";