mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-31 14:57:09 +08:00
GP-388 Adding feature to simplify the display names in the listing for symbol and datatype names that have complex template info in thier names
This commit is contained in:
+27
@@ -937,6 +937,33 @@
|
|||||||
"CodeBrowser.htm#Selection">Selection</A> color.</P>
|
"CodeBrowser.htm#Selection">Selection</A> color.</P>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H3><A name="Template_Display_Options"></A>Template Display Options</H3>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<P><B>Max Template Depth</B> - Sets the depth to display nested templates. A
|
||||||
|
depth of 0 completely simplifies the entire template, while a depth of 1 will
|
||||||
|
show 1 level of templates.For example, if the name was "foo<char,bar<int, dog<char>>",
|
||||||
|
a nesting depth of 0 would display "foo<>" and an nesting depth of 1 would display
|
||||||
|
"foo<char, bar<>>".
|
||||||
|
</P>
|
||||||
|
|
||||||
|
<P><B>Max Template Length</B> - This is the maximum length any template string will display.
|
||||||
|
If the template string exceeds this length, the middle part of the template will be replaced
|
||||||
|
with "..." to get the string down to the minimum length. For example, the string
|
||||||
|
"foo<abcdefghijklmnopqrstuvwxyz,0123456789>" would display something like "foo<abcd...6789>"
|
||||||
|
if the max length was set to 10. Note that this restriction is applied AFTER
|
||||||
|
any simplifications from the nesting depth.
|
||||||
|
</P>
|
||||||
|
|
||||||
|
<P><B>Min Template Length</B> - This is the minimum length of a template before template
|
||||||
|
simplification is applied. In other words, if the template string is less than this length,
|
||||||
|
then the template will not be simplified. This is done so that simple templates such as
|
||||||
|
"foo<char>" are not simplified to "foo<>", even if the template nesting depth is set to 0.
|
||||||
|
</P>
|
||||||
|
|
||||||
|
<P><B>Simplify Templated Names</B> - This turns the entire templating simplification feature
|
||||||
|
on or off. If this is off, none of the other option have any effect.</P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<H3><A name="XREFs_Field"></A>XREFs Field</H3>
|
<H3><A name="XREFs_Field"></A>XREFs Field</H3>
|
||||||
|
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import java.util.ArrayList;
|
|||||||
|
|
||||||
import generic.theme.GThemeDefaults.Colors.Messages;
|
import generic.theme.GThemeDefaults.Colors.Messages;
|
||||||
import ghidra.app.util.DisplayableEol;
|
import ghidra.app.util.DisplayableEol;
|
||||||
|
import ghidra.app.util.template.TemplateSimplifier;
|
||||||
import ghidra.framework.plugintool.ServiceProvider;
|
import ghidra.framework.plugintool.ServiceProvider;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSetView;
|
import ghidra.program.model.address.AddressSetView;
|
||||||
@@ -85,7 +86,8 @@ class ProgramTextWriter {
|
|||||||
writer.print("<HTML><BODY BGCOLOR=#ffffe0>");
|
writer.print("<HTML><BODY BGCOLOR=#ffffe0>");
|
||||||
writer.println("<FONT FACE=COURIER SIZE=3><STRONG><PRE>");
|
writer.println("<FONT FACE=COURIER SIZE=3><STRONG><PRE>");
|
||||||
}
|
}
|
||||||
|
TemplateSimplifier simplifier = new TemplateSimplifier();
|
||||||
|
simplifier.setEnabled(false);
|
||||||
CodeUnitFormatOptions formatOptions = new CodeUnitFormatOptions(
|
CodeUnitFormatOptions formatOptions = new CodeUnitFormatOptions(
|
||||||
options.isShowBlockNameInOperands() ? CodeUnitFormatOptions.ShowBlockName.NON_LOCAL
|
options.isShowBlockNameInOperands() ? CodeUnitFormatOptions.ShowBlockName.NON_LOCAL
|
||||||
: CodeUnitFormatOptions.ShowBlockName.NEVER,
|
: CodeUnitFormatOptions.ShowBlockName.NEVER,
|
||||||
@@ -95,7 +97,8 @@ class ProgramTextWriter {
|
|||||||
true, // include extended reference markup
|
true, // include extended reference markup
|
||||||
true, // include scalar adjustment
|
true, // include scalar adjustment
|
||||||
true, // include library names in namespace
|
true, // include library names in namespace
|
||||||
true // follow referenced pointers
|
true, // follow referenced pointers
|
||||||
|
simplifier // disabled simplifier
|
||||||
);
|
);
|
||||||
|
|
||||||
CodeUnitFormat cuFormat = new CodeUnitFormat(formatOptions);
|
CodeUnitFormat cuFormat = new CodeUnitFormat(formatOptions);
|
||||||
@@ -628,9 +631,9 @@ class ProgramTextWriter {
|
|||||||
if (options.isHTML()) {
|
if (options.isHTML()) {
|
||||||
Reference ref =
|
Reference ref =
|
||||||
cu.getProgram()
|
cu.getProgram()
|
||||||
.getReferenceManager()
|
.getReferenceManager()
|
||||||
.getPrimaryReferenceFrom(cuAddress,
|
.getPrimaryReferenceFrom(cuAddress,
|
||||||
i);
|
i);
|
||||||
addReferenceLinkedText(ref, opReps[i], true);
|
addReferenceLinkedText(ref, opReps[i], true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -0,0 +1,300 @@
|
|||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidra.app.util.template;
|
||||||
|
|
||||||
|
import ghidra.GhidraOptions;
|
||||||
|
import ghidra.framework.options.Options;
|
||||||
|
import ghidra.framework.options.ToolOptions;
|
||||||
|
import ghidra.util.HelpLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for simplify names with template data. This class can be used with tool options or
|
||||||
|
* as a stand alone configurable simplifier.
|
||||||
|
*/
|
||||||
|
public class TemplateSimplifier {
|
||||||
|
public static final String SUB_OPTION_NAME = "Templates";
|
||||||
|
|
||||||
|
public static final String SIMPLIFY_TEMPLATES_OPTION =
|
||||||
|
SUB_OPTION_NAME + ".Simplify Templated Names";
|
||||||
|
public static final String TEMPLATE_NESTING_DEPTH_OPTION =
|
||||||
|
SUB_OPTION_NAME + ".Max Template Depth";
|
||||||
|
public static final String MAX_TEMPLATE_LENGTH_OPTION =
|
||||||
|
SUB_OPTION_NAME + ".Max Template Length";
|
||||||
|
public static final String MIN_TEMPLATE_LENGTH_OPTION =
|
||||||
|
SUB_OPTION_NAME + ".Min Template Length";
|
||||||
|
|
||||||
|
public static final String SIMPLY_TEMPLATES_DESCRIPTION =
|
||||||
|
"Determines whether to diplay templated names in a simplified form.";
|
||||||
|
public static final String TEMPLATE_NESTING_DEPTH_DESCRIPTION =
|
||||||
|
"Maximum template depth to display when simplify templated names.";
|
||||||
|
public static final String MAX_TEMPLATE_LENGTH_DESCRIPTION =
|
||||||
|
"Maximum number of characters to display in a template before truncating the name in the middle.";
|
||||||
|
public static final String MIN_TEMPLATE_LENGTH_DESCRIPTION =
|
||||||
|
"Minumum size of template to be simplified";
|
||||||
|
|
||||||
|
private boolean doSimplify = true;
|
||||||
|
private int templateNestingDepth = 0;
|
||||||
|
private int maxTemplateLength = 20;
|
||||||
|
private int minTemplateLength = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor to use for a TemplateSimplifier that doesn't use values from ToolOptions
|
||||||
|
*/
|
||||||
|
public TemplateSimplifier() {
|
||||||
|
// constructs using standard simplifying options.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor to use for a TemplateSimplifier that operates using the current values in
|
||||||
|
* the tool options
|
||||||
|
* @param fieldOptions the "Listing Field" options
|
||||||
|
*/
|
||||||
|
public TemplateSimplifier(ToolOptions fieldOptions) {
|
||||||
|
checkForCorrectOptions(fieldOptions);
|
||||||
|
ensureRegistered(fieldOptions);
|
||||||
|
loadOptions(fieldOptions);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the template nesting depth to be simplified. A depth of 0 simplifies the entire
|
||||||
|
* template portion of the name (everything in between <>). A depth of 1 leaves one level of
|
||||||
|
* template information
|
||||||
|
* @param depth the nesting depth
|
||||||
|
*/
|
||||||
|
public void setNestingDepth(int depth) {
|
||||||
|
this.templateNestingDepth = depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the nesting depth for simplification
|
||||||
|
* @return the nesting depth for simplification
|
||||||
|
*/
|
||||||
|
public int getNestingDepth() {
|
||||||
|
return templateNestingDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the maximum length do display the template portion. If, after any nesting,
|
||||||
|
* simplification, the resulting template string is longer that the max length, the middle
|
||||||
|
* portion will be replaced with "..." to reduce the template string to the given max length.
|
||||||
|
* @param maxLength the max length of a template to display
|
||||||
|
*/
|
||||||
|
public void setMaxTemplateLength(int maxLength) {
|
||||||
|
this.maxTemplateLength = maxLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the maximum length that a template will display.
|
||||||
|
* @return the maximum length that a template will display
|
||||||
|
*/
|
||||||
|
public int getMaxTemplateLength() {
|
||||||
|
return maxTemplateLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets if this TemplateSimplifier is enabled. If disabled, the {@link #simplify(String)}
|
||||||
|
* method will return the input string.
|
||||||
|
* @param doSimplify true to do simplification, false to do nothing
|
||||||
|
*/
|
||||||
|
public void setEnabled(boolean doSimplify) {
|
||||||
|
this.doSimplify = doSimplify;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if this TemplateSimplifier is enabled.
|
||||||
|
* @return if this TemplateSimplifier is enabled
|
||||||
|
*/
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return doSimplify;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the minimum length for a template string to be simplified. In other words, template
|
||||||
|
* strings less than this length will not be changed.
|
||||||
|
* @param minLength the minimum length to simplify
|
||||||
|
*/
|
||||||
|
public void setMinimumTemplateLength(int minLength) {
|
||||||
|
this.minTemplateLength = minLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the minimum length of a template string that will be simplified.
|
||||||
|
* @return the minimum length of a template string that will be simplified.
|
||||||
|
*/
|
||||||
|
public int getMinimumTemplateLength() {
|
||||||
|
return minTemplateLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simplifies any template string in the given input base on the current simplification
|
||||||
|
* settings.
|
||||||
|
* @param input the input string to be simplified
|
||||||
|
* @return a simplified string
|
||||||
|
*/
|
||||||
|
public String simplify(String input) {
|
||||||
|
if (!doSimplify) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
return doSimplify(input, templateNestingDepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reloads the current simplification settings from the given field options
|
||||||
|
* @param fieldOptions the options to retrieve the simplification settings.
|
||||||
|
*/
|
||||||
|
public void reloadFromOptions(ToolOptions fieldOptions) {
|
||||||
|
checkForCorrectOptions(fieldOptions);
|
||||||
|
loadOptions(fieldOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification that options have changed
|
||||||
|
* @param options the options object that has changed values
|
||||||
|
* @param optionName the name of the options that changed
|
||||||
|
* @param oldValue the old value for the option that changed
|
||||||
|
* @param newValue the new value for the option that changed
|
||||||
|
* @return true if the option that changed was a template simplification option
|
||||||
|
*/
|
||||||
|
public boolean fieldOptionsChanged(Options options, String optionName, Object oldValue,
|
||||||
|
Object newValue) {
|
||||||
|
if (optionName.equals(SIMPLIFY_TEMPLATES_OPTION)) {
|
||||||
|
doSimplify = (Boolean) newValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (optionName.equals(TEMPLATE_NESTING_DEPTH_OPTION)) {
|
||||||
|
templateNestingDepth = (Integer) newValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (optionName.equals(MAX_TEMPLATE_LENGTH_OPTION)) {
|
||||||
|
maxTemplateLength = (Integer) newValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (optionName.equals(MIN_TEMPLATE_LENGTH_OPTION)) {
|
||||||
|
minTemplateLength = (Integer) newValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String doSimplify(String input, int depth) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
int pos = 0;
|
||||||
|
TemplateString ts;
|
||||||
|
while ((ts = findTemplateString(input, pos)) != null) {
|
||||||
|
builder.append(input.substring(pos, ts.start));
|
||||||
|
String template = ts.getTemplate();
|
||||||
|
if (depth == 0) {
|
||||||
|
builder.append("<");
|
||||||
|
if (template.length() <= minTemplateLength) {
|
||||||
|
builder.append(template);
|
||||||
|
}
|
||||||
|
builder.append(">");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
builder.append("<");
|
||||||
|
String simplifiedTemplate = doSimplify(template, depth - 1);
|
||||||
|
if (simplifiedTemplate.length() > maxTemplateLength) {
|
||||||
|
simplifiedTemplate = middleTruncate(template);
|
||||||
|
}
|
||||||
|
builder.append(simplifiedTemplate);
|
||||||
|
builder.append(">");
|
||||||
|
}
|
||||||
|
pos = ts.end + 1;
|
||||||
|
}
|
||||||
|
builder.append(input.substring(pos));
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String middleTruncate(String input) {
|
||||||
|
int partSize = maxTemplateLength / 2;
|
||||||
|
return input.substring(0, partSize) + "..." + input.substring(input.length() - partSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TemplateString findTemplateString(String input, int pos) {
|
||||||
|
for (int i = pos; i < input.length(); i++) {
|
||||||
|
char c = input.charAt(i);
|
||||||
|
if (c == '<') {
|
||||||
|
int end = findMatchingEnd(input, i + 1);
|
||||||
|
if (end > i) {
|
||||||
|
return new TemplateString(input, i, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int findMatchingEnd(String input, int start) {
|
||||||
|
int depth = 0;
|
||||||
|
for (int i = start; i < input.length(); i++) {
|
||||||
|
char c = input.charAt(i);
|
||||||
|
if (c == '>') {
|
||||||
|
if (depth == 0) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
depth--;
|
||||||
|
}
|
||||||
|
else if (c == '<') {
|
||||||
|
depth++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private record TemplateString(String input, int start, int end) {
|
||||||
|
String getTemplate() {
|
||||||
|
return input.substring(start + 1, end); // don't include the enclosing <> chars
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadOptions(ToolOptions options) {
|
||||||
|
doSimplify = options.getBoolean(SIMPLIFY_TEMPLATES_OPTION, doSimplify);
|
||||||
|
templateNestingDepth = options.getInt(TEMPLATE_NESTING_DEPTH_OPTION, templateNestingDepth);
|
||||||
|
maxTemplateLength = options.getInt(MAX_TEMPLATE_LENGTH_OPTION, maxTemplateLength);
|
||||||
|
minTemplateLength = options.getInt(MIN_TEMPLATE_LENGTH_OPTION, minTemplateLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkForCorrectOptions(ToolOptions fieldOptions) {
|
||||||
|
if (!GhidraOptions.CATEGORY_BROWSER_FIELDS.equals(fieldOptions.getName())) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Expected options named \"" + GhidraOptions.CATEGORY_BROWSER_FIELDS + "\", not \"" +
|
||||||
|
fieldOptions.getName() + "\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureRegistered(Options options) {
|
||||||
|
if (options.isRegistered(SIMPLIFY_TEMPLATES_OPTION)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HelpLocation help = new HelpLocation("CodeBrowserPlugin", "Template Display Options");
|
||||||
|
|
||||||
|
options.getOptions(SUB_OPTION_NAME).setOptionsHelpLocation(help);
|
||||||
|
|
||||||
|
options.registerOption(SIMPLIFY_TEMPLATES_OPTION, doSimplify, help,
|
||||||
|
SIMPLY_TEMPLATES_DESCRIPTION);
|
||||||
|
|
||||||
|
options.registerOption(TEMPLATE_NESTING_DEPTH_OPTION, templateNestingDepth, help,
|
||||||
|
TEMPLATE_NESTING_DEPTH_DESCRIPTION);
|
||||||
|
|
||||||
|
options.registerOption(MAX_TEMPLATE_LENGTH_OPTION, maxTemplateLength, help,
|
||||||
|
MAX_TEMPLATE_LENGTH_DESCRIPTION);
|
||||||
|
|
||||||
|
options.registerOption(MIN_TEMPLATE_LENGTH_OPTION, minTemplateLength, help,
|
||||||
|
MIN_TEMPLATE_LENGTH_DESCRIPTION);
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
-2
@@ -20,6 +20,7 @@ import javax.swing.event.ChangeEvent;
|
|||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
|
|
||||||
import ghidra.GhidraOptions;
|
import ghidra.GhidraOptions;
|
||||||
|
import ghidra.app.util.template.TemplateSimplifier;
|
||||||
import ghidra.framework.options.*;
|
import ghidra.framework.options.*;
|
||||||
import ghidra.program.model.listing.CodeUnitFormatOptions;
|
import ghidra.program.model.listing.CodeUnitFormatOptions;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
@@ -103,7 +104,7 @@ public class BrowserCodeUnitFormatOptions extends CodeUnitFormatOptions
|
|||||||
BrowserCodeUnitFormatOptions(ToolOptions fieldOptions, boolean autoUpdate) {
|
BrowserCodeUnitFormatOptions(ToolOptions fieldOptions, boolean autoUpdate) {
|
||||||
this.fieldOptions = fieldOptions;
|
this.fieldOptions = fieldOptions;
|
||||||
this.displayOptions = new OptionsBasedDataTypeDisplayOptions(fieldOptions);
|
this.displayOptions = new OptionsBasedDataTypeDisplayOptions(fieldOptions);
|
||||||
|
templateSimplifier = new TemplateSimplifier(fieldOptions);
|
||||||
boolean exists = fieldOptions.isRegistered(NAMESPACE_OPTIONS);
|
boolean exists = fieldOptions.isRegistered(NAMESPACE_OPTIONS);
|
||||||
|
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
@@ -144,7 +145,10 @@ public class BrowserCodeUnitFormatOptions extends CodeUnitFormatOptions
|
|||||||
@Override
|
@Override
|
||||||
public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
|
public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
|
||||||
Object newValue) {
|
Object newValue) {
|
||||||
if (optionName.equals(GhidraOptions.SHOW_BLOCK_NAME_OPTION) ||
|
if (templateSimplifier.fieldOptionsChanged(options, optionName, oldValue, newValue)) {
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
else if (optionName.equals(GhidraOptions.SHOW_BLOCK_NAME_OPTION) ||
|
||||||
optionName.equals(REGISTER_VARIABLE_MARKUP_OPTION) ||
|
optionName.equals(REGISTER_VARIABLE_MARKUP_OPTION) ||
|
||||||
optionName.equals(STACK_VARIABLE_MARKUP_OPTION) ||
|
optionName.equals(STACK_VARIABLE_MARKUP_OPTION) ||
|
||||||
optionName.equals(INFERRED_VARIABLE_MARKUP_OPTION) ||
|
optionName.equals(INFERRED_VARIABLE_MARKUP_OPTION) ||
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import java.math.BigInteger;
|
|||||||
import docking.widgets.fieldpanel.support.FieldLocation;
|
import docking.widgets.fieldpanel.support.FieldLocation;
|
||||||
import generic.theme.Gui;
|
import generic.theme.Gui;
|
||||||
import ghidra.app.util.HighlightProvider;
|
import ghidra.app.util.HighlightProvider;
|
||||||
|
import ghidra.app.util.template.TemplateSimplifier;
|
||||||
import ghidra.app.util.viewer.format.FieldFormatModel;
|
import ghidra.app.util.viewer.format.FieldFormatModel;
|
||||||
import ghidra.app.util.viewer.proxy.ProxyObj;
|
import ghidra.app.util.viewer.proxy.ProxyObj;
|
||||||
import ghidra.framework.options.Options;
|
import ghidra.framework.options.Options;
|
||||||
@@ -54,6 +55,7 @@ public abstract class FieldFactory implements ExtensionPoint {
|
|||||||
|
|
||||||
protected String colorOptionName;
|
protected String colorOptionName;
|
||||||
protected String styleOptionName;
|
protected String styleOptionName;
|
||||||
|
private TemplateSimplifier templateSimplifier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base constructor
|
* Base constructor
|
||||||
@@ -72,14 +74,14 @@ public abstract class FieldFactory implements ExtensionPoint {
|
|||||||
styleOptionName = name + " Style";
|
styleOptionName = name + " Style";
|
||||||
|
|
||||||
width = 100;
|
width = 100;
|
||||||
|
templateSimplifier = model.getFormatManager().getTemplateSimplifier();
|
||||||
initDisplayOptions(displayOptions);
|
initDisplayOptions(displayOptions);
|
||||||
initFieldOptions(fieldOptions);
|
initFieldOptions(fieldOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void initFieldOptions(Options fieldOptions) {
|
protected void initFieldOptions(Options fieldOptions) {
|
||||||
fieldOptions.getOptions(name)
|
fieldOptions.getOptions(name)
|
||||||
.setOptionsHelpLocation(new HelpLocation("CodeBrowserPlugin", name));
|
.setOptionsHelpLocation(new HelpLocation("CodeBrowserPlugin", name));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void initDisplayOptions(Options displayOptions) {
|
protected void initDisplayOptions(Options displayOptions) {
|
||||||
@@ -314,4 +316,8 @@ public abstract class FieldFactory implements ExtensionPoint {
|
|||||||
fontMetrics[i] = Toolkit.getDefaultToolkit().getFontMetrics(font);
|
fontMetrics[i] = Toolkit.getDefaultToolkit().getFontMetrics(font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected String simplifyTemplates(String input) {
|
||||||
|
return templateSimplifier.simplify(input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-10
@@ -59,7 +59,7 @@ public class FunctionSignatureFieldFactory extends FieldFactory {
|
|||||||
* @param fieldOptions the Options for field specific properties.
|
* @param fieldOptions the Options for field specific properties.
|
||||||
*/
|
*/
|
||||||
public FunctionSignatureFieldFactory(FieldFormatModel model, HighlightProvider hlProvider,
|
public FunctionSignatureFieldFactory(FieldFormatModel model, HighlightProvider hlProvider,
|
||||||
Options displayOptions, Options fieldOptions) {
|
ToolOptions displayOptions, ToolOptions fieldOptions) {
|
||||||
super(FIELD_NAME, model, hlProvider, displayOptions, fieldOptions);
|
super(FIELD_NAME, model, hlProvider, displayOptions, fieldOptions);
|
||||||
|
|
||||||
fieldOptions.registerOption(DISPLAY_NAMESPACE, false, null,
|
fieldOptions.registerOption(DISPLAY_NAMESPACE, false, null,
|
||||||
@@ -100,7 +100,7 @@ public class FunctionSignatureFieldFactory extends FieldFactory {
|
|||||||
elementIndex++;
|
elementIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// noreturn
|
// no return
|
||||||
if (function.hasNoReturn()) {
|
if (function.hasNoReturn()) {
|
||||||
as = new AttributedString(Function.NORETURN + " ", FunctionColors.RETURN_TYPE,
|
as = new AttributedString(Function.NORETURN + " ", FunctionColors.RETURN_TYPE,
|
||||||
getMetrics());
|
getMetrics());
|
||||||
@@ -110,7 +110,9 @@ public class FunctionSignatureFieldFactory extends FieldFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// return type
|
// return type
|
||||||
as = new AttributedString(function.getReturn().getFormalDataType().getDisplayName() + " ",
|
String returnTypeName = function.getReturn().getFormalDataType().getDisplayName();
|
||||||
|
returnTypeName = simplifyTemplates(returnTypeName);
|
||||||
|
as = new AttributedString(returnTypeName + " ",
|
||||||
FunctionColors.RETURN_TYPE, getMetrics());
|
FunctionColors.RETURN_TYPE, getMetrics());
|
||||||
textElements.add(new FunctionReturnTypeFieldElement(as, elementIndex, 0, startCol));
|
textElements.add(new FunctionReturnTypeFieldElement(as, elementIndex, 0, startCol));
|
||||||
startCol += as.length();
|
startCol += as.length();
|
||||||
@@ -126,14 +128,14 @@ public class FunctionSignatureFieldFactory extends FieldFactory {
|
|||||||
as = new AttributedString(callingConvention + " ", FunctionColors.RETURN_TYPE,
|
as = new AttributedString(callingConvention + " ", FunctionColors.RETURN_TYPE,
|
||||||
getMetrics());
|
getMetrics());
|
||||||
textElements
|
textElements
|
||||||
.add(new FunctionCallingConventionFieldElement(as, elementIndex, 0, startCol));
|
.add(new FunctionCallingConventionFieldElement(as, elementIndex, 0, startCol));
|
||||||
startCol += as.length();
|
startCol += as.length();
|
||||||
elementIndex++;
|
elementIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// function name
|
// function name
|
||||||
as = new AttributedString(function.getName(displayFunctionScope),
|
String functionName = simplifyTemplates(function.getName(displayFunctionScope));
|
||||||
getFunctionNameColor(function), getMetrics());
|
as = new AttributedString(functionName, getFunctionNameColor(function), getMetrics());
|
||||||
textElements.add(new FunctionNameFieldElement(as, elementIndex, 0, startCol));
|
textElements.add(new FunctionNameFieldElement(as, elementIndex, 0, startCol));
|
||||||
startCol += as.length();
|
startCol += as.length();
|
||||||
elementIndex++;
|
elementIndex++;
|
||||||
@@ -159,15 +161,15 @@ public class FunctionSignatureFieldFactory extends FieldFactory {
|
|||||||
Color pcolor =
|
Color pcolor =
|
||||||
params[i].isAutoParameter() ? FunctionColors.PARAM_AUTO : FunctionColors.PARAM;
|
params[i].isAutoParameter() ? FunctionColors.PARAM_AUTO : FunctionColors.PARAM;
|
||||||
|
|
||||||
String text = params[i].getFormalDataType().getDisplayName() + " ";
|
String dtName = simplifyTemplates(params[i].getFormalDataType().getDisplayName() + " ");
|
||||||
as = new AttributedString(text, pcolor, getMetrics());
|
as = new AttributedString(dtName, pcolor, getMetrics());
|
||||||
textElements.add(
|
textElements.add(
|
||||||
new FunctionParameterFieldElement(as, elementIndex, paramOffset, startCol, i));
|
new FunctionParameterFieldElement(as, elementIndex, paramOffset, startCol, i));
|
||||||
startCol += as.length();
|
startCol += as.length();
|
||||||
paramOffset += as.length();
|
paramOffset += as.length();
|
||||||
elementIndex++;
|
elementIndex++;
|
||||||
|
|
||||||
text = params[i].getName();
|
String text = params[i].getName();
|
||||||
as = new AttributedString(text, pcolor, getMetrics());
|
as = new AttributedString(text, pcolor, getMetrics());
|
||||||
textElements.add(
|
textElements.add(
|
||||||
new FunctionParameterNameFieldElement(as, elementIndex, paramOffset, startCol, i));
|
new FunctionParameterNameFieldElement(as, elementIndex, paramOffset, startCol, i));
|
||||||
@@ -381,7 +383,6 @@ public class FunctionSignatureFieldFactory extends FieldFactory {
|
|||||||
@Override
|
@Override
|
||||||
public void fieldOptionsChanged(Options options, String optionName, Object oldValue,
|
public void fieldOptionsChanged(Options options, String optionName, Object oldValue,
|
||||||
Object newValue) {
|
Object newValue) {
|
||||||
|
|
||||||
if (optionName.equals(DISPLAY_NAMESPACE)) {
|
if (optionName.equals(DISPLAY_NAMESPACE)) {
|
||||||
displayFunctionScope = ((Boolean) newValue).booleanValue();
|
displayFunctionScope = ((Boolean) newValue).booleanValue();
|
||||||
model.update();
|
model.update();
|
||||||
|
|||||||
+5
-6
@@ -250,27 +250,26 @@ public class LabelFieldFactory extends FieldFactory {
|
|||||||
private String checkLabelString(Symbol symbol, Program program) {
|
private String checkLabelString(Symbol symbol, Program program) {
|
||||||
|
|
||||||
if (!displayLocalNamespace && !displayNonLocalNamespace) {
|
if (!displayLocalNamespace && !displayNonLocalNamespace) {
|
||||||
return symbol.getName(); // no namespaces being shown
|
return simplifyTemplates(symbol.getName()); // no namespaces being shown
|
||||||
}
|
}
|
||||||
|
|
||||||
Namespace addressNamespace = program.getSymbolTable().getNamespace(symbol.getAddress());
|
Namespace addressNamespace = program.getSymbolTable().getNamespace(symbol.getAddress());
|
||||||
Namespace symbolNamespace = symbol.getParentNamespace();
|
Namespace symbolNamespace = symbol.getParentNamespace();
|
||||||
boolean isLocal = symbolNamespace.equals(addressNamespace);
|
boolean isLocal = symbolNamespace.equals(addressNamespace);
|
||||||
if (!isLocal) {
|
if (!isLocal) {
|
||||||
return symbol.getName(displayNonLocalNamespace);
|
return simplifyTemplates(symbol.getName(displayNonLocalNamespace));
|
||||||
}
|
}
|
||||||
|
|
||||||
// O.K., we ARE a local namespace, how to display it?
|
// O.K., we ARE a local namespace, how to display it?
|
||||||
if (!displayLocalNamespace) {
|
if (!displayLocalNamespace) {
|
||||||
return symbol.getName();
|
return simplifyTemplates(symbol.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// use the namespace name or a custom, user-defined value
|
// use the namespace name or a custom, user-defined value
|
||||||
if (useLocalPrefixOverride) {
|
if (useLocalPrefixOverride) {
|
||||||
return localPrefixText + symbol.getName(false);
|
return simplifyTemplates(localPrefixText + symbol.getName(false));
|
||||||
}
|
}
|
||||||
return symbol.getName(true);
|
return simplifyTemplates(symbol.getName(true));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Address> getOffcutReferenceAddress(CodeUnit cu) {
|
private List<Address> getOffcutReferenceAddress(CodeUnit cu) {
|
||||||
|
|||||||
+1
@@ -491,6 +491,7 @@ abstract class OperandFieldHelper extends FieldFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ColorStyleAttributes attributes = getOpAttributes(opElem, inst, opIndex);
|
ColorStyleAttributes attributes = getOpAttributes(opElem, inst, opIndex);
|
||||||
|
|
||||||
AttributedString as = new AttributedString(opElem.toString(), attributes.colorAttribute,
|
AttributedString as = new AttributedString(opElem.toString(), attributes.colorAttribute,
|
||||||
getMetrics(attributes.styleAttribute), underline, ListingColors.UNDERLINE);
|
getMetrics(attributes.styleAttribute), underline, ListingColors.UNDERLINE);
|
||||||
elements.add(new OperandFieldElement(as, opIndex, subOpIndex, characterOffset));
|
elements.add(new OperandFieldElement(as, opIndex, subOpIndex, characterOffset));
|
||||||
|
|||||||
+4
-4
@@ -25,7 +25,6 @@ import ghidra.app.util.HighlightProvider;
|
|||||||
import ghidra.app.util.viewer.format.FieldFormatModel;
|
import ghidra.app.util.viewer.format.FieldFormatModel;
|
||||||
import ghidra.app.util.viewer.proxy.FunctionProxy;
|
import ghidra.app.util.viewer.proxy.FunctionProxy;
|
||||||
import ghidra.app.util.viewer.proxy.ProxyObj;
|
import ghidra.app.util.viewer.proxy.ProxyObj;
|
||||||
import ghidra.framework.options.Options;
|
|
||||||
import ghidra.framework.options.ToolOptions;
|
import ghidra.framework.options.ToolOptions;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.program.model.listing.Library;
|
import ghidra.program.model.listing.Library;
|
||||||
@@ -56,7 +55,7 @@ public class ThunkedFunctionFieldFactory extends FieldFactory {
|
|||||||
* @param fieldOptions the Options for field specific properties.
|
* @param fieldOptions the Options for field specific properties.
|
||||||
*/
|
*/
|
||||||
public ThunkedFunctionFieldFactory(FieldFormatModel model, HighlightProvider hlProvider,
|
public ThunkedFunctionFieldFactory(FieldFormatModel model, HighlightProvider hlProvider,
|
||||||
ToolOptions displayOptions, Options fieldOptions) {
|
ToolOptions displayOptions, ToolOptions fieldOptions) {
|
||||||
super(FIELD_NAME, model, hlProvider, displayOptions, fieldOptions);
|
super(FIELD_NAME, model, hlProvider, displayOptions, fieldOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,8 +95,9 @@ public class ThunkedFunctionFieldFactory extends FieldFactory {
|
|||||||
as = new AttributedString("Thunked-Function: ", ListingColors.SEPARATOR, getMetrics());
|
as = new AttributedString("Thunked-Function: ", ListingColors.SEPARATOR, getMetrics());
|
||||||
textElements.add(new TextFieldElement(as, elementIndex++, 0));
|
textElements.add(new TextFieldElement(as, elementIndex++, 0));
|
||||||
|
|
||||||
as = new AttributedString(thunkedFunction.getName(true),
|
String functionName = simplifyTemplates(thunkedFunction.getName(true));
|
||||||
getThunkedFunctionNameColor(thunkedFunction), getMetrics());
|
as = new AttributedString(functionName, getThunkedFunctionNameColor(thunkedFunction),
|
||||||
|
getMetrics());
|
||||||
textElements.add(new TextFieldElement(as, elementIndex++, 0));
|
textElements.add(new TextFieldElement(as, elementIndex++, 0));
|
||||||
|
|
||||||
return ListingTextField.createSingleLineTextField(this, proxy,
|
return ListingTextField.createSingleLineTextField(this, proxy,
|
||||||
|
|||||||
+15
-9
@@ -23,7 +23,6 @@ import ghidra.app.util.HighlightProvider;
|
|||||||
import ghidra.app.util.viewer.format.FieldFormatModel;
|
import ghidra.app.util.viewer.format.FieldFormatModel;
|
||||||
import ghidra.app.util.viewer.proxy.ProxyObj;
|
import ghidra.app.util.viewer.proxy.ProxyObj;
|
||||||
import ghidra.app.util.viewer.proxy.VariableProxy;
|
import ghidra.app.util.viewer.proxy.VariableProxy;
|
||||||
import ghidra.framework.options.Options;
|
|
||||||
import ghidra.framework.options.ToolOptions;
|
import ghidra.framework.options.ToolOptions;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.listing.Parameter;
|
import ghidra.program.model.listing.Parameter;
|
||||||
@@ -52,7 +51,7 @@ public class VariableTypeFieldFactory extends AbstractVariableFieldFactory {
|
|||||||
* @param fieldOptions the Options for field specific properties.
|
* @param fieldOptions the Options for field specific properties.
|
||||||
*/
|
*/
|
||||||
private VariableTypeFieldFactory(FieldFormatModel model, HighlightProvider hlProvider,
|
private VariableTypeFieldFactory(FieldFormatModel model, HighlightProvider hlProvider,
|
||||||
Options displayOptions, Options fieldOptions) {
|
ToolOptions displayOptions, ToolOptions fieldOptions) {
|
||||||
super(FIELD_NAME, model, hlProvider, displayOptions, fieldOptions);
|
super(FIELD_NAME, model, hlProvider, displayOptions, fieldOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,24 +64,31 @@ public class VariableTypeFieldFactory extends AbstractVariableFieldFactory {
|
|||||||
if (!enabled || !(obj instanceof Variable)) {
|
if (!enabled || !(obj instanceof Variable)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Variable sv = (Variable) obj;
|
Variable variable = (Variable) obj;
|
||||||
|
|
||||||
DataType dt;
|
DataType dt;
|
||||||
if (sv instanceof Parameter) {
|
if (variable instanceof Parameter) {
|
||||||
dt = ((Parameter) sv).getFormalDataType();
|
dt = ((Parameter) variable).getFormalDataType();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dt = sv.getDataType();
|
dt = variable.getDataType();
|
||||||
}
|
}
|
||||||
String dtName = (dt != null) ? dt.getDisplayName() : null;
|
String dtName = getDataTypeName(dt);
|
||||||
|
|
||||||
AttributedString as =
|
AttributedString as =
|
||||||
new AttributedString((dtName != null) ? dtName : "", getColor(sv), getMetrics(sv));
|
new AttributedString(dtName, getColor(variable), getMetrics(variable));
|
||||||
FieldElement field = new TextFieldElement(as, 0, 0);
|
FieldElement field = new TextFieldElement(as, 0, 0);
|
||||||
return ListingTextField.createSingleLineTextField(this, proxy, field, startX + varWidth,
|
return ListingTextField.createSingleLineTextField(this, proxy, field, startX + varWidth,
|
||||||
width, hlProvider);
|
width, hlProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getDataTypeName(DataType dt) {
|
||||||
|
if (dt == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
String dtName = dt.getName();
|
||||||
|
return dtName == null ? "" : simplifyTemplates(dtName);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ghidra.app.util.viewer.field.FieldFactory#getProgramLocation(int, int, ghidra.app.util.viewer.field.ListingField)
|
* @see ghidra.app.util.viewer.field.FieldFactory#getProgramLocation(int, int, ghidra.app.util.viewer.field.ListingField)
|
||||||
*/
|
*/
|
||||||
|
|||||||
+25
-4
@@ -23,6 +23,7 @@ import org.jdom.Element;
|
|||||||
|
|
||||||
import docking.widgets.fieldpanel.support.Highlight;
|
import docking.widgets.fieldpanel.support.Highlight;
|
||||||
import ghidra.app.util.HighlightProvider;
|
import ghidra.app.util.HighlightProvider;
|
||||||
|
import ghidra.app.util.template.TemplateSimplifier;
|
||||||
import ghidra.app.util.viewer.field.*;
|
import ghidra.app.util.viewer.field.*;
|
||||||
import ghidra.framework.options.*;
|
import ghidra.framework.options.*;
|
||||||
import ghidra.framework.plugintool.ServiceProvider;
|
import ghidra.framework.plugintool.ServiceProvider;
|
||||||
@@ -67,6 +68,7 @@ public class FormatManager implements OptionsChangeListener {
|
|||||||
private ServiceProvider serviceProvider;
|
private ServiceProvider serviceProvider;
|
||||||
private int arrayValuesPerLine = 1;
|
private int arrayValuesPerLine = 1;
|
||||||
private boolean groupArrayElements = true;
|
private boolean groupArrayElements = true;
|
||||||
|
TemplateSimplifier templateSimplifier;
|
||||||
|
|
||||||
// NOTE: Unused custom format code was removed. The custom format code last existed in
|
// NOTE: Unused custom format code was removed. The custom format code last existed in
|
||||||
// commit #204e7892bf2f110ebb05ca4beee3fe5b397f88c9.
|
// commit #204e7892bf2f110ebb05ca4beee3fe5b397f88c9.
|
||||||
@@ -80,6 +82,7 @@ public class FormatManager implements OptionsChangeListener {
|
|||||||
public FormatManager(ToolOptions displayOptions, ToolOptions fieldOptions) {
|
public FormatManager(ToolOptions displayOptions, ToolOptions fieldOptions) {
|
||||||
this.fieldOptions = fieldOptions;
|
this.fieldOptions = fieldOptions;
|
||||||
this.displayOptions = displayOptions;
|
this.displayOptions = displayOptions;
|
||||||
|
this.templateSimplifier = new TemplateSimplifier(fieldOptions);
|
||||||
highlightProvider = new MultipleHighlighterProvider();
|
highlightProvider = new MultipleHighlighterProvider();
|
||||||
getFactorys();
|
getFactorys();
|
||||||
for (int i = 0; i < NUM_MODELS; i++) {
|
for (int i = 0; i < NUM_MODELS; i++) {
|
||||||
@@ -153,7 +156,7 @@ public class FormatManager implements OptionsChangeListener {
|
|||||||
/**
|
/**
|
||||||
* Adds a listener to be notified when a format changes.
|
* Adds a listener to be notified when a format changes.
|
||||||
*
|
*
|
||||||
* @param listener the listener to be added.
|
* @param listener the listener to be added
|
||||||
*/
|
*/
|
||||||
public void addFormatModelListener(FormatModelListener listener) {
|
public void addFormatModelListener(FormatModelListener listener) {
|
||||||
formatListeners.add(listener);
|
formatListeners.add(listener);
|
||||||
@@ -171,6 +174,7 @@ public class FormatManager implements OptionsChangeListener {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the total number of model in the format manager.
|
* Returns the total number of model in the format manager.
|
||||||
|
* @return the total number of model in the format manager
|
||||||
*/
|
*/
|
||||||
public int getNumModels() {
|
public int getNumModels() {
|
||||||
return NUM_MODELS;
|
return NUM_MODELS;
|
||||||
@@ -180,27 +184,31 @@ public class FormatManager implements OptionsChangeListener {
|
|||||||
* Returns the format model for the given index.
|
* Returns the format model for the given index.
|
||||||
*
|
*
|
||||||
* @param index the index of the format model to return.
|
* @param index the index of the format model to return.
|
||||||
|
* @return the format model for the given index
|
||||||
*/
|
*/
|
||||||
public FieldFormatModel getModel(int index) {
|
public FieldFormatModel getModel(int index) {
|
||||||
return models[index];
|
return models[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the format model for the address break (divider)
|
* Returns the format model for the address break (divider).
|
||||||
|
* @return the format model for the address break (divider)
|
||||||
*/
|
*/
|
||||||
public FieldFormatModel getDividerModel() {
|
public FieldFormatModel getDividerModel() {
|
||||||
return models[FieldFormatModel.DIVIDER];
|
return models[FieldFormatModel.DIVIDER];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the format model for the plate field
|
* Returns the format model for the plate field.
|
||||||
|
* @return the format model for the plate field
|
||||||
*/
|
*/
|
||||||
public FieldFormatModel getPlateFormat() {
|
public FieldFormatModel getPlateFormat() {
|
||||||
return models[FieldFormatModel.PLATE];
|
return models[FieldFormatModel.PLATE];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the format model for the function signature
|
* Returns the format model for the function signature.
|
||||||
|
* @return the format model for the function signature
|
||||||
*/
|
*/
|
||||||
public FieldFormatModel getFunctionFormat() {
|
public FieldFormatModel getFunctionFormat() {
|
||||||
return models[FieldFormatModel.FUNCTION];
|
return models[FieldFormatModel.FUNCTION];
|
||||||
@@ -208,6 +216,7 @@ public class FormatManager implements OptionsChangeListener {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the format model for the function variables.
|
* Returns the format model for the function variables.
|
||||||
|
* @return the format model for the function variables
|
||||||
*/
|
*/
|
||||||
public FieldFormatModel getFunctionVarFormat() {
|
public FieldFormatModel getFunctionVarFormat() {
|
||||||
return models[FieldFormatModel.FUNCTION_VARS];
|
return models[FieldFormatModel.FUNCTION_VARS];
|
||||||
@@ -215,6 +224,7 @@ public class FormatManager implements OptionsChangeListener {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the format model for a code unit.
|
* Returns the format model for a code unit.
|
||||||
|
* @return the format model for a code unit
|
||||||
*/
|
*/
|
||||||
public FieldFormatModel getCodeUnitFormat() {
|
public FieldFormatModel getCodeUnitFormat() {
|
||||||
return models[FieldFormatModel.INSTRUCTION_OR_DATA];
|
return models[FieldFormatModel.INSTRUCTION_OR_DATA];
|
||||||
@@ -261,6 +271,7 @@ public class FormatManager implements OptionsChangeListener {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Options used for display properties.
|
* Returns the Options used for display properties.
|
||||||
|
* @return the Options used for display properties.
|
||||||
*/
|
*/
|
||||||
public ToolOptions getDisplayOptions() {
|
public ToolOptions getDisplayOptions() {
|
||||||
return displayOptions;
|
return displayOptions;
|
||||||
@@ -268,11 +279,20 @@ public class FormatManager implements OptionsChangeListener {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Options used for field specific properties.
|
* Returns the Options used for field specific properties.
|
||||||
|
* @return the Options used for field specific properties
|
||||||
*/
|
*/
|
||||||
public ToolOptions getFieldOptions() {
|
public ToolOptions getFieldOptions() {
|
||||||
return fieldOptions;
|
return fieldOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the template simplifier.
|
||||||
|
* @return the template simplifier.
|
||||||
|
*/
|
||||||
|
public TemplateSimplifier getTemplateSimplifier() {
|
||||||
|
return templateSimplifier;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies listeners that the given model has changed.
|
* Notifies listeners that the given model has changed.
|
||||||
*
|
*
|
||||||
@@ -852,6 +872,7 @@ public class FormatManager implements OptionsChangeListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (options == fieldOptions) {
|
else if (options == fieldOptions) {
|
||||||
|
templateSimplifier.fieldOptionsChanged(options, name, oldValue, newValue);
|
||||||
for (int i = 0; i < NUM_MODELS; i++) {
|
for (int i = 0; i < NUM_MODELS; i++) {
|
||||||
models[i].fieldOptionsChanged(options, name, oldValue, newValue);
|
models[i].fieldOptionsChanged(options, name, oldValue, newValue);
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-14
@@ -322,17 +322,19 @@ public class CodeUnitFormat {
|
|||||||
}
|
}
|
||||||
else if (options.includeInferredVariableMarkup) {
|
else if (options.includeInferredVariableMarkup) {
|
||||||
boolean isRead = isRead(reg, instr);
|
boolean isRead = isRead(reg, instr);
|
||||||
Variable regVar = program.getFunctionManager().getReferencedVariable(
|
Variable regVar = program.getFunctionManager()
|
||||||
instr.getMinAddress(), reg.getAddress(), reg.getMinimumByteSize(), isRead);
|
.getReferencedVariable(
|
||||||
|
instr.getMinAddress(), reg.getAddress(), reg.getMinimumByteSize(), isRead);
|
||||||
if (regVar != null) {
|
if (regVar != null) {
|
||||||
// TODO: If register appears more than once, how can we distinguish read vs. write occurrence in operands
|
// TODO: If register appears more than once, how can we distinguish read vs. write occurrence in operands
|
||||||
if (isRead && isWritten(reg, instr) && !hasRegisterWriteReference(instr, reg) &&
|
if (isRead && isWritten(reg, instr) && !hasRegisterWriteReference(instr, reg) &&
|
||||||
instr.getRegister(opIndex) != null) {
|
instr.getRegister(opIndex) != null) {
|
||||||
// If register both read and written and there are no write references for this instruction
|
// If register both read and written and there are no write references for this instruction
|
||||||
// see if there is only one reference to choose from - if not we can't determine how to markup
|
// see if there is only one reference to choose from - if not we can't determine how to markup
|
||||||
Variable regWriteVar = program.getFunctionManager().getReferencedVariable(
|
Variable regWriteVar = program.getFunctionManager()
|
||||||
instr.getMinAddress(), reg.getAddress(), reg.getMinimumByteSize(),
|
.getReferencedVariable(
|
||||||
false);
|
instr.getMinAddress(), reg.getAddress(), reg.getMinimumByteSize(),
|
||||||
|
false);
|
||||||
if (regWriteVar != regVar) {
|
if (regWriteVar != regVar) {
|
||||||
continue; // TODO: tough case - not which operand is read vs. write!
|
continue; // TODO: tough case - not which operand is read vs. write!
|
||||||
}
|
}
|
||||||
@@ -630,8 +632,10 @@ public class CodeUnitFormat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Variable regVar =
|
Variable regVar =
|
||||||
instr.getProgram().getFunctionManager().getReferencedVariable(instr.getMinAddress(),
|
instr.getProgram()
|
||||||
associatedRegister.getAddress(), associatedRegister.getMinimumByteSize(), true);
|
.getFunctionManager()
|
||||||
|
.getReferencedVariable(instr.getMinAddress(),
|
||||||
|
associatedRegister.getAddress(), associatedRegister.getMinimumByteSize(), true);
|
||||||
if (regVar == null) {
|
if (regVar == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1151,8 +1155,10 @@ public class CodeUnitFormat {
|
|||||||
public String getReferenceRepresentationString(CodeUnit fromCodeUnit, Reference ref) {
|
public String getReferenceRepresentationString(CodeUnit fromCodeUnit, Reference ref) {
|
||||||
// NOTE: The isRead param is false since it really only pertains to register references which should
|
// NOTE: The isRead param is false since it really only pertains to register references which should
|
||||||
// generally only correspond to writes
|
// generally only correspond to writes
|
||||||
Variable refVar = fromCodeUnit.getProgram().getFunctionManager().getReferencedVariable(
|
Variable refVar = fromCodeUnit.getProgram()
|
||||||
fromCodeUnit.getMinAddress(), ref.getToAddress(), 0, false);
|
.getFunctionManager()
|
||||||
|
.getReferencedVariable(
|
||||||
|
fromCodeUnit.getMinAddress(), ref.getToAddress(), 0, false);
|
||||||
Object repObj = getReferenceRepresentation(fromCodeUnit, ref, refVar);
|
Object repObj = getReferenceRepresentation(fromCodeUnit, ref, refVar);
|
||||||
return repObj != null ? repObj.toString() : null;
|
return repObj != null ? repObj.toString() : null;
|
||||||
}
|
}
|
||||||
@@ -1367,7 +1373,13 @@ public class CodeUnitFormat {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
String name = symbol.getName();
|
String name = symbol.getName();
|
||||||
return addNamespace(program, symbol.getParentNamespace(), name, markupAddress);
|
String displayName =
|
||||||
|
addNamespace(program, symbol.getParentNamespace(), name, markupAddress);
|
||||||
|
return simplifyTemplate(displayName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String simplifyTemplate(String name) {
|
||||||
|
return options.simplifyTemplate(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isStringData(CodeUnit cu) {
|
private boolean isStringData(CodeUnit cu) {
|
||||||
@@ -1379,7 +1391,7 @@ public class CodeUnitFormat {
|
|||||||
|
|
||||||
private String getLabelStringForStringData(Data data, Symbol symbol) {
|
private String getLabelStringForStringData(Data data, Symbol symbol) {
|
||||||
if (!symbol.isDynamic()) {
|
if (!symbol.isDynamic()) {
|
||||||
return symbol.getName();
|
return options.simplifyTemplate(symbol.getName());
|
||||||
}
|
}
|
||||||
DataType dataType = data.getBaseDataType();
|
DataType dataType = data.getBaseDataType();
|
||||||
|
|
||||||
@@ -1440,7 +1452,7 @@ public class CodeUnitFormat {
|
|||||||
|
|
||||||
Symbol containingSymbol = program.getSymbolTable().getPrimarySymbol(instructionAddress);
|
Symbol containingSymbol = program.getSymbolTable().getPrimarySymbol(instructionAddress);
|
||||||
if (containingSymbol != null) {
|
if (containingSymbol != null) {
|
||||||
return containingSymbol.getName() + PLUS + diff;
|
return options.simplifyTemplate(containingSymbol.getName()) + PLUS + diff;
|
||||||
}
|
}
|
||||||
return getDefaultOffcutString(offsym, instruction, diff, false);
|
return getDefaultOffcutString(offsym, instruction, diff, false);
|
||||||
}
|
}
|
||||||
@@ -1464,10 +1476,11 @@ public class CodeUnitFormat {
|
|||||||
|
|
||||||
protected String getDefaultOffcutString(Symbol symbol, CodeUnit cu, long diff,
|
protected String getDefaultOffcutString(Symbol symbol, CodeUnit cu, long diff,
|
||||||
boolean decorate) {
|
boolean decorate) {
|
||||||
|
String name = options.simplifyTemplate(symbol.getName());
|
||||||
if (decorate) {
|
if (decorate) {
|
||||||
return symbol.getName() + ' ' + '(' + cu.getMinAddress() + PLUS + diff + ')';
|
return name + ' ' + '(' + cu.getMinAddress() + PLUS + diff + ')';
|
||||||
}
|
}
|
||||||
return symbol.getName();
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+10
-1
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.program.model.listing;
|
package ghidra.program.model.listing;
|
||||||
|
|
||||||
|
import ghidra.app.util.template.TemplateSimplifier;
|
||||||
import ghidra.program.model.data.DataTypeDisplayOptions;
|
import ghidra.program.model.data.DataTypeDisplayOptions;
|
||||||
|
|
||||||
public class CodeUnitFormatOptions {
|
public class CodeUnitFormatOptions {
|
||||||
@@ -80,9 +81,11 @@ public class CodeUnitFormatOptions {
|
|||||||
protected volatile boolean showOffcutInfo = true;
|
protected volatile boolean showOffcutInfo = true;
|
||||||
|
|
||||||
protected DataTypeDisplayOptions displayOptions = DataTypeDisplayOptions.DEFAULT;
|
protected DataTypeDisplayOptions displayOptions = DataTypeDisplayOptions.DEFAULT;
|
||||||
|
protected TemplateSimplifier templateSimplifier;
|
||||||
|
|
||||||
public CodeUnitFormatOptions() {
|
public CodeUnitFormatOptions() {
|
||||||
// use default options;
|
// use default options;
|
||||||
|
templateSimplifier = new TemplateSimplifier();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -93,6 +96,7 @@ public class CodeUnitFormatOptions {
|
|||||||
public CodeUnitFormatOptions(ShowBlockName showBlockName, ShowNamespace showNamespace) {
|
public CodeUnitFormatOptions(ShowBlockName showBlockName, ShowNamespace showNamespace) {
|
||||||
this.showBlockName = showBlockName;
|
this.showBlockName = showBlockName;
|
||||||
this.showNamespace = showNamespace;
|
this.showNamespace = showNamespace;
|
||||||
|
templateSimplifier = new TemplateSimplifier();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -119,7 +123,7 @@ public class CodeUnitFormatOptions {
|
|||||||
String localPrefixOverride, boolean doRegVariableMarkup, boolean doStackVariableMarkup,
|
String localPrefixOverride, boolean doRegVariableMarkup, boolean doStackVariableMarkup,
|
||||||
boolean includeInferredVariableMarkup, boolean alwaysShowPrimaryReference,
|
boolean includeInferredVariableMarkup, boolean alwaysShowPrimaryReference,
|
||||||
boolean includeScalarReferenceAdjustment, boolean showLibraryInNamespace,
|
boolean includeScalarReferenceAdjustment, boolean showLibraryInNamespace,
|
||||||
boolean followReferencedPointers) {
|
boolean followReferencedPointers, TemplateSimplifier templateSimplifier) {
|
||||||
this.showBlockName = showBlockName;
|
this.showBlockName = showBlockName;
|
||||||
this.showNamespace = showNamespace;
|
this.showNamespace = showNamespace;
|
||||||
this.showLibraryInNamespace = showLibraryInNamespace;
|
this.showLibraryInNamespace = showLibraryInNamespace;
|
||||||
@@ -130,6 +134,7 @@ public class CodeUnitFormatOptions {
|
|||||||
this.alwaysShowPrimaryReference = alwaysShowPrimaryReference;
|
this.alwaysShowPrimaryReference = alwaysShowPrimaryReference;
|
||||||
this.followReferencedPointers = followReferencedPointers;
|
this.followReferencedPointers = followReferencedPointers;
|
||||||
this.includeScalarReferenceAdjustment = includeScalarReferenceAdjustment;
|
this.includeScalarReferenceAdjustment = includeScalarReferenceAdjustment;
|
||||||
|
this.templateSimplifier = templateSimplifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -139,4 +144,8 @@ public class CodeUnitFormatOptions {
|
|||||||
public ShowBlockName getShowBlockNameOption() {
|
public ShowBlockName getShowBlockNameOption() {
|
||||||
return showBlockName;
|
return showBlockName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String simplifyTemplate(String name) {
|
||||||
|
return templateSimplifier.simplify(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+115
@@ -0,0 +1,115 @@
|
|||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidra.app.util.template;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import generic.test.AbstractGenericTest;
|
||||||
|
import ghidra.framework.options.ToolOptions;
|
||||||
|
|
||||||
|
public class TemplateSimplifierTest extends AbstractGenericTest {
|
||||||
|
|
||||||
|
private TemplateSimplifier simplifier = new TemplateSimplifier();
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
simplifier.setMinimumTemplateLength(0);
|
||||||
|
simplifier.setNestingDepth(0);
|
||||||
|
simplifier.setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSimplifyTemplates() {
|
||||||
|
assertEquals("bob<>", simplify("bob<hey>"));
|
||||||
|
assertEquals("bob<>", simplify("bob<foo<hey>>"));
|
||||||
|
assertEquals("bob<foo<>", simplify("bob<foo<bar>"));
|
||||||
|
assertEquals("bob<>", simplify("bob<foo<bar<hey>>>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSimplifyTemplatesDepth1() {
|
||||||
|
simplifier.setNestingDepth(1);
|
||||||
|
assertEquals("bob<hey>", simplify("bob<hey>"));
|
||||||
|
assertEquals("bob<foo<>>", simplify("bob<foo<hey>>"));
|
||||||
|
assertEquals("bob<foo<bar>", simplify("bob<foo<bar>"));
|
||||||
|
assertEquals("bob<foo<>>", simplify("bob<foo<bar<hey>>>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSimplifyTemplatesDepth2() {
|
||||||
|
simplifier.setNestingDepth(2);
|
||||||
|
assertEquals("bob<hey>", simplify("bob<hey>"));
|
||||||
|
assertEquals("bob<foo<hey>>", simplify("bob<foo<hey>>"));
|
||||||
|
assertEquals("bob<foo<bar>", simplify("bob<foo<bar>"));
|
||||||
|
assertEquals("bob<foo<bar<>>>", simplify("bob<foo<bar<hey>>>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStripTemplatesWithMaxSize() {
|
||||||
|
simplifier.setMaxTemplateLength(10);
|
||||||
|
simplifier.setNestingDepth(5);
|
||||||
|
assertEquals("bob<abcde...vwxyz>", simplify("bob<abcdefghijklmnopqrstuvwxyz>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStripTemplatesWithMaxSizeAndNestedTemplates() {
|
||||||
|
simplifier.setMaxTemplateLength(10);
|
||||||
|
simplifier.setNestingDepth(5);
|
||||||
|
assertEquals("bob<int, ...wxyz>>",
|
||||||
|
simplify("bob<int, foo<abcdefghijklmnopqrstuvwxyz>>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMinSizeToSimplify() {
|
||||||
|
simplifier.setMinimumTemplateLength(5);
|
||||||
|
assertEquals("bob<abcde>", simplify("bob<abcde>"));
|
||||||
|
assertEquals("bob<>", simplify("bob<abcdef>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOptionsGetRegistered() {
|
||||||
|
ToolOptions options = new ToolOptions("Listing Fields");
|
||||||
|
simplifier = new TemplateSimplifier(options);
|
||||||
|
|
||||||
|
assertTrue(options.isRegistered(TemplateSimplifier.SIMPLIFY_TEMPLATES_OPTION));
|
||||||
|
assertTrue(options.isRegistered(TemplateSimplifier.MAX_TEMPLATE_LENGTH_OPTION));
|
||||||
|
assertTrue(options.isRegistered(TemplateSimplifier.TEMPLATE_NESTING_DEPTH_OPTION));
|
||||||
|
assertTrue(options.isRegistered(TemplateSimplifier.MIN_TEMPLATE_LENGTH_OPTION));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadsOptions() {
|
||||||
|
ToolOptions options = new ToolOptions("Listing Fields");
|
||||||
|
options.setBoolean(TemplateSimplifier.SIMPLIFY_TEMPLATES_OPTION, false);
|
||||||
|
options.setInt(TemplateSimplifier.MAX_TEMPLATE_LENGTH_OPTION, 33);
|
||||||
|
options.setInt(TemplateSimplifier.TEMPLATE_NESTING_DEPTH_OPTION, 3);
|
||||||
|
options.setInt(TemplateSimplifier.MIN_TEMPLATE_LENGTH_OPTION, 7);
|
||||||
|
simplifier = new TemplateSimplifier(options);
|
||||||
|
|
||||||
|
assertEquals(false, simplifier.isEnabled());
|
||||||
|
assertEquals(33, simplifier.getMaxTemplateLength());
|
||||||
|
assertEquals(3, simplifier.getNestingDepth());
|
||||||
|
assertEquals(7, simplifier.getMinimumTemplateLength());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String simplify(String in) {
|
||||||
|
return simplifier.simplify(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user