Updated broken color usage for function references and parameter references

This commit is contained in:
dragonmacher
2025-07-10 17:09:20 -04:00
parent 894e65589a
commit c538b0def6
13 changed files with 669 additions and 290 deletions
@@ -40,7 +40,7 @@ color.fg.listing.comment.pre = color.palette.indigo
color.fg.listing.comment.offcut = color.fg.error
color.fg.listing.ref.bad = color.fg.error
color.fg.listing.ext.entrypoint = color.palette.magenta
color.fg.listing.ext.ref.resolved = color.palette.darkorange
color.fg.listing.ext.ref.resolved = color.palette.teal
color.fg.listing.ext.ref.unresolved = color.fg.listing.ref.bad
color.fg.listing.fieldname = color.fg
@@ -382,10 +382,10 @@ public class SymbolInspector implements OptionsChangeListener {
else if (isVariableSymbol(s)) {
if (s.getSymbolType() == SymbolType.PARAMETER) {
Function function = (Function) s.getParentNamespace();
return function.hasCustomVariableStorage() ? OptionsGui.PARAMETER_CUSTOM
: OptionsGui.PARAMETER_DYNAMIC;
return function.hasCustomVariableStorage() ? OptionsGui.FUN_PARAM_CUSTOM
: OptionsGui.FUN_PARAM_DYNAMIC;
}
return OptionsGui.VARIABLE;
return OptionsGui.FUN_VARIABLE;
}
else if (isPrimarySymbol(s)) {
return OptionsGui.LABELS_PRIMARY;
@@ -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.
@@ -81,9 +81,9 @@ public abstract class AbstractVariableFieldFactory extends FieldFactory {
parameterFieldOptions = new ParameterFieldOptions[2];
parameterFieldOptions[CUSTOM_PARAM_INDEX] =
new ParameterFieldOptions(OptionsGui.PARAMETER_CUSTOM);
new ParameterFieldOptions(OptionsGui.FUN_PARAM_CUSTOM);
parameterFieldOptions[DYNAMIC_PARAM_INDEX] =
new ParameterFieldOptions(OptionsGui.PARAMETER_DYNAMIC);
new ParameterFieldOptions(OptionsGui.FUN_PARAM_DYNAMIC);
for (int i = 0; i < 2; i++) {
parameterFieldOptions[i].style =
@@ -122,11 +122,16 @@ public abstract class AbstractVariableFieldFactory extends FieldFactory {
}
protected Color getColor(Variable var) {
if (var instanceof Parameter) {
if (var instanceof Parameter param) {
if (param.isAutoParameter()) {
return FunctionColors.PARAM_AUTO;
}
return var.getFunction().hasCustomVariableStorage() ? FunctionColors.PARAM_CUSTOM
: FunctionColors.PARAM_DYNAMIC;
}
return FunctionColors.PARAM;
return FunctionColors.VARIABLE;
}
protected FontMetrics getMetrics(Variable var) {
@@ -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.
@@ -45,7 +45,7 @@ public class VariableNameFieldFactory extends AbstractVariableFieldFactory {
/**
* Constructor
* @param model the model that the field belongs to.
* @param hsProvider the HightLightStringProvider.
* @param hlProvider the HightLightStringProvider.
* @param displayOptions the Options for display properties.
* @param fieldOptions the Options for field specific properties.
*/
@@ -72,9 +72,6 @@ public class VariableNameFieldFactory extends AbstractVariableFieldFactory {
width, hlProvider);
}
/**
* @see ghidra.app.util.viewer.field.FieldFactory#getProgramLocation(int, int, ghidra.app.util.viewer.field.ListingField)
*/
@Override
public ProgramLocation getProgramLocation(int row, int col, ListingField bf) {
ProxyObj<?> proxy = bf.getProxy();
@@ -88,9 +85,6 @@ public class VariableNameFieldFactory extends AbstractVariableFieldFactory {
return null;
}
/**
* @see ghidra.app.util.viewer.field.FieldFactory#getFieldLocation(ghidra.app.util.viewer.field.ListingField, BigInteger, int, ghidra.program.util.ProgramLocation)
*/
@Override
public FieldLocation getFieldLocation(ListingField bf, BigInteger index, int fieldNum,
ProgramLocation loc) {
@@ -111,9 +105,6 @@ public class VariableNameFieldFactory extends AbstractVariableFieldFactory {
return null;
}
/**
* @see ghidra.app.util.viewer.field.FieldFactory#acceptsType(int, java.lang.Class)
*/
@Override
public boolean acceptsType(int category, Class<?> proxyObjectClass) {
if (!Variable.class.isAssignableFrom(proxyObjectClass)) {
@@ -40,6 +40,7 @@ import generic.theme.GThemeDefaults.Colors.Palette;
import ghidra.GhidraOptions;
import ghidra.app.util.viewer.field.ListingColors;
import ghidra.app.util.viewer.field.ListingColors.*;
import ghidra.util.ColorUtils;
/**
* Class for displaying and manipulating field colors and fonts.
@@ -65,6 +66,9 @@ public class OptionsGui extends JPanel {
public static final ScreenElement FUN_CALL_FIXUP = new ScreenElement("Function Call-Fixup", FunctionColors.CALL_FIXUP);
public static final ScreenElement FUN_NAME = new ScreenElement("Function Name", FunctionColors.NAME);
public static final ScreenElement FUN_PARAMS = new ScreenElement("Function Parameters", FunctionColors.PARAM);
public static final ScreenElement FUN_PARAM_CUSTOM = new ScreenElement("Function Parameter, Custom Storage", FunctionColors.PARAM_CUSTOM);
public static final ScreenElement FUN_PARAM_DYNAMIC = new ScreenElement("Function Parameter, Dynamic Storage", FunctionColors.PARAM_DYNAMIC);
public static final ScreenElement FUN_VARIABLE = new ScreenElement("Function Variable", FunctionColors.VARIABLE);
public static final ScreenElement FUN_TAG = new ScreenElement("Function Tag", FunctionColors.TAG);
public static final ScreenElement FUN_AUTO_PARAMS = new ScreenElement("Function Auto-Parameters", FunctionColors.PARAM_AUTO);
public static final ScreenElement FUN_RET_TYPE = new ScreenElement("Function Return Type", FunctionColors.RETURN_TYPE);
@@ -73,7 +77,7 @@ public class OptionsGui extends JPanel {
public static final ScreenElement LABELS_LOCAL = new ScreenElement("Labels, Local", LabelColors.LOCAL);
public static final ScreenElement MNEMONIC = new ScreenElement("Mnemonic", MnemonicColors.NORMAL);
public static final ScreenElement MNEMONIC_OVERRIDE = new ScreenElement("Mnemonic, Override", MnemonicColors.OVERRIDE);
public static final ScreenElement MNEMONIC_UNIMPL = new ScreenElement("Unimplemented Mnemonic", MnemonicColors.UNIMPLEMENTED);
public static final ScreenElement MNEMONIC_UNIMPL = new ScreenElement("Mnemonic, Unimplemented ", MnemonicColors.UNIMPLEMENTED);
public static final ScreenElement FLOW_ARROW_ACTIVE = new ScreenElement("Flow Arrow, Active", FlowArrowColors.ACTIVE);
public static final ScreenElement FLOW_ARROW_NON_ACTIVE = new ScreenElement("Flow Arrow, Not Active", FlowArrowColors.INACTIVE);
public static final ScreenElement FLOW_ARROW_SELECTED = new ScreenElement("Flow Arrow, Selected", FlowArrowColors.SELECTED);
@@ -83,9 +87,7 @@ public class OptionsGui extends JPanel {
public static final ScreenElement COMMENT_POST = new ScreenElement("Comment, Post", "Post-Comment", CommentColors.POST);
public static final ScreenElement COMMENT_PRE = new ScreenElement("Comment, Pre", "Pre-Comment", CommentColors.PRE);
public static final ScreenElement SEPARATOR = new ScreenElement("Separator", ListingColors.SEPARATOR);
public static final ScreenElement VARIABLE = new ScreenElement("Variable", FunctionColors.VARIABLE);
public static final ScreenElement PARAMETER_CUSTOM = new ScreenElement("Parameter, Custom Storage", FunctionColors.PARAM_CUSTOM);
public static final ScreenElement PARAMETER_DYNAMIC = new ScreenElement("Parameter, Dynamic Storage", FunctionColors.PARAM_DYNAMIC);
public static final ScreenElement SEPARATOR_LINE = new ScreenElement("Separator Line", Colors.BACKGROUND);
public static final ScreenElement XREF = new ScreenElement("XRef", XrefColors.DEFAULT);
public static final ScreenElement XREF_OFFCUT = new ScreenElement("XRef, Offcut", XrefColors.OFFCUT);
public static final ScreenElement XREF_READ = new ScreenElement("XRef Read", XrefColors.READ);
@@ -98,19 +100,22 @@ public class OptionsGui extends JPanel {
public static final ScreenElement PCODE_RAW_VARNODE = new ScreenElement("P-code Raw Varnode", PcodeColors.VARNODE);
public static final ScreenElement PCODE_USEROP = new ScreenElement("P-code Userop", PcodeColors.USEROP);
static ScreenElement[] elements = {
ADDRESS,
BACKGROUND, BAD_REF_ADDR, BYTES,
COMMENT_AUTO, COMMENT_EOL, COMMENT_PLATE, COMMENT_POST, COMMENT_PRE, COMMENT_REPEATABLE,
COMMENT_REF_REPEAT, CONSTANT,
ENTRY_POINT, EXT_REF_RESOLVED, EXT_REF_UNRESOLVED,
FIELD_NAME, FLOW_ARROW_ACTIVE, FLOW_ARROW_NON_ACTIVE, FLOW_ARROW_SELECTED,
FUN_NAME, FUN_PARAMS, FUN_AUTO_PARAMS, FUN_PARAM_DYNAMIC, FUN_PARAM_CUSTOM, FUN_VARIABLE,
FUN_RET_TYPE, FUN_CALL_FIXUP, FUN_TAG,
LABELS_LOCAL, LABELS_NON_PRIMARY, LABELS_PRIMARY, LABELS_UNREFD,
MNEMONIC, MNEMONIC_OVERRIDE, MNEMONIC_UNIMPL,
PCODE_LINE_LABEL, PCODE_ADDR_SPACE, PCODE_RAW_VARNODE, PCODE_USEROP,
REGISTERS, SEPARATOR, UNDERLINE,
XREF, XREF_OFFCUT, XREF_READ, XREF_WRITE, XREF_OTHER };
//@formatter:on
static ScreenElement[] elements =
{ ADDRESS, BACKGROUND, BAD_REF_ADDR, BYTES, COMMENT_AUTO, COMMENT_EOL, COMMENT_PLATE,
COMMENT_POST, COMMENT_PRE, COMMENT_REPEATABLE, COMMENT_REF_REPEAT, CONSTANT,
ENTRY_POINT, EXT_REF_RESOLVED, EXT_REF_UNRESOLVED, FIELD_NAME, FLOW_ARROW_ACTIVE,
FLOW_ARROW_NON_ACTIVE, FLOW_ARROW_SELECTED, FUN_CALL_FIXUP, FUN_NAME, FUN_PARAMS,
FUN_AUTO_PARAMS, FUN_RET_TYPE, FUN_TAG, LABELS_LOCAL, LABELS_NON_PRIMARY,
LABELS_PRIMARY, LABELS_UNREFD, MNEMONIC, MNEMONIC_OVERRIDE, PARAMETER_CUSTOM,
PARAMETER_DYNAMIC, PCODE_LINE_LABEL, PCODE_ADDR_SPACE, PCODE_RAW_VARNODE, PCODE_USEROP,
REGISTERS, SEPARATOR, UNDERLINE, MNEMONIC_UNIMPL, VARIABLE, XREF, XREF_OFFCUT,
XREF_READ, XREF_WRITE, XREF_OTHER };
private Map<Integer, FontMetrics> metricsMap = new HashMap<>();
private JList<ScreenElement> namesList;
@@ -167,28 +172,31 @@ public class OptionsGui extends JPanel {
}
else {
setSelectedIndex(index);
setSelectedFieldElement(index);
}
});
setSelectedIndex(0);
colorChooser.getSelectionModel().addChangeListener(e -> {
Color c = colorChooser.getColor();
Color oldColor = elements[selectedIndex].getColor();
elements[selectedIndex].setColor(c);
colorPanel.setBackground(c);
genLayouts();
fieldPanel.setBackgroundColor(BACKGROUND.getColor());
enableApply();
if (!ColorUtils.hasSameRgb(oldColor, c)) {
enableApply();
}
});
ActionListener styleListener = e -> {
updateStyle();
genLayouts();
fieldPanel.setBackgroundColor(BACKGROUND.getColor());
enableApply();
};
ActionListener familyListener = e -> {
updateFonts();
genLayouts();
fieldPanel.setBackgroundColor(BACKGROUND.getColor());
enableApply();
};
@@ -217,7 +225,7 @@ public class OptionsGui extends JPanel {
}
/**
* callback for when the selected display field changes.
* Callback for when the selected display field changes.
*
* @param index the index in the JList of the selected field.
*/
@@ -243,6 +251,26 @@ public class OptionsGui extends JPanel {
}
}
private void setSelectedFieldElement(int index) {
ListModel<ScreenElement> model = namesList.getModel();
ScreenElement screenElement = model.getElementAt(index);
SimpleLayoutModel layoutModel = (SimpleLayoutModel) fieldPanel.getLayoutModel();
FieldSelection selection = layoutModel.getFieldSelection(screenElement);
if (selection == null) {
fieldPanel.clearSelection();
return;
}
FieldRange range = selection.getFieldRange(0);
FieldLocation loc = range.getStart();
fieldPanel.setCursorPosition(loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol());
fieldPanel.setSelection(selection);
fieldPanel.scrollTo(loc);
fieldPanel.center(loc);
}
public void setBaseFont(Font font) {
baseFont = font;
baseMetrics = getFontMetrics(font);
@@ -515,6 +543,8 @@ public class OptionsGui extends JPanel {
lb.add(".........", SEPARATOR);
list.add(lb.getLayout());
list.add(blankLine());
lb = new LayoutBuilder(1);
lb.add(" ", null);
lb.add("sprintf", LABELS_NON_PRIMARY);
@@ -557,6 +587,8 @@ public class OptionsGui extends JPanel {
lb.add(".........", SEPARATOR);
list.add(lb.getLayout());
list.add(blankLine());
lb = new LayoutBuilder(2);
lb.add(" ", null);
lb.add("LAB2000", LABELS_PRIMARY);
@@ -610,6 +642,9 @@ public class OptionsGui extends JPanel {
lb.add("33", CONSTANT);
list.add(lb.getLayout());
list.add(blankLine());
list.add(blankLine());
lb = new LayoutBuilder(1);
lb.add(" ", null);
lb.add("// This is a function comment", COMMENT_EOL);
@@ -639,30 +674,30 @@ public class OptionsGui extends JPanel {
lb = new LayoutBuilder(3);
lb.add(" ", null);
lb.add("12 ", PARAMETER_DYNAMIC);
lb.add("DWord ", PARAMETER_DYNAMIC);
lb.add("param_12 ", PARAMETER_DYNAMIC);
lb.add("12 ", FUN_PARAM_DYNAMIC);
lb.add("DWord ", FUN_PARAM_DYNAMIC);
lb.add("param_12 ", FUN_PARAM_DYNAMIC);
list.add(lb.getLayout());
lb = new LayoutBuilder(3);
lb.add(" ", null);
lb.add("8 ", PARAMETER_CUSTOM);
lb.add("DWord ", PARAMETER_CUSTOM);
lb.add("param_8 ", PARAMETER_CUSTOM);
lb.add("8 ", FUN_PARAM_CUSTOM);
lb.add("DWord ", FUN_PARAM_CUSTOM);
lb.add("param_8 ", FUN_PARAM_CUSTOM);
list.add(lb.getLayout());
lb = new LayoutBuilder(3);
lb.add(" ", null);
lb.add("4 ", PARAMETER_CUSTOM);
lb.add("Word ", PARAMETER_CUSTOM);
lb.add("param_4 ", PARAMETER_CUSTOM);
lb.add("4 ", FUN_PARAM_CUSTOM);
lb.add("Word ", FUN_PARAM_CUSTOM);
lb.add("param_4 ", FUN_PARAM_CUSTOM);
list.add(lb.getLayout());
lb = new LayoutBuilder(3);
lb.add(" ", null);
lb.add("-4 ", VARIABLE);
lb.add("Float ", VARIABLE);
lb.add("local_4 ", VARIABLE);
lb.add("-4 ", FUN_VARIABLE);
lb.add("Float ", FUN_VARIABLE);
lb.add("local_4 ", FUN_VARIABLE);
list.add(lb.getLayout());
lb = new LayoutBuilder(2);
@@ -689,8 +724,14 @@ public class OptionsGui extends JPanel {
}
}
private Layout blankLine() {
LayoutBuilder lb = new LayoutBuilder(1);
lb.add(" ", SEPARATOR_LINE);
return lb.getLayout();
}
/**
* updates the style of the field at the selected index.
* Updates the style of the field at the selected index.
*/
private void updateStyle() {
if (customCheckbox.isSelected()) {
@@ -839,12 +880,75 @@ public class OptionsGui extends JPanel {
return BigInteger.valueOf(layouts.length);
}
FieldSelection getFieldSelection(ScreenElement element) {
List<FieldRange> ranges = getAllRanges(element);
if (ranges.isEmpty()) {
return null;
}
FieldSelection selection = new FieldSelection();
for (FieldRange r : ranges) {
selection.addRange(r);
}
return selection;
}
// finds all places this element is used; consecutive fields will be combined
List<FieldRange> getAllRanges(ScreenElement element) {
List<FieldRange> ranges = new ArrayList<>();
for (int index = 0; index < layouts.length; index++) {
SingleRowLayout rowLayout = (SingleRowLayout) layouts[index];
getRangesForRow(rowLayout, element, index, ranges);
}
return ranges;
}
private void getRangesForRow(SingleRowLayout layout, ScreenElement element, int index,
List<FieldRange> ranges) {
FieldRange lastRange = null;
int n = layout.getNumFields();
for (int i = 0; i < n; i++) {
ScreenElementTextField field = (ScreenElementTextField) layout.getField(i);
ScreenElement fieldElement = field.getScreenElement();
String text = field.getText();
if (element != fieldElement) {
lastRange = null;
continue;
}
int start = 0;
if (lastRange == null) {
start = getNonWhitespaceStart(text);
}
lastRange = new FieldRange(
new FieldLocation(index, i, 0, start),
new FieldLocation(index, i, 0, start + text.trim().length()));
ranges.add(lastRange);
}
}
}
private int getNonWhitespaceStart(String text) {
int start = 0;
for (int j = 0; j < text.length(); j++) {
char c = text.charAt(j);
if (!Character.isWhitespace(c)) {
break;
}
start++;
}
return start;
}
/**
* Class to create the layouts for the preview panel.
*/
class LayoutBuilder {
private class LayoutBuilder {
private ClippingTextField[] fields;
int startPos;
int fieldNum;
@@ -1251,8 +1251,8 @@ public class CodeUnitFormat {
}
result = addBlockName(program, toAddress, result, refBlock, withBlockName);
LabelType labelType = (toSymbol != null && toSymbol.isExternal()) ? LabelString.EXTERNAL
: LabelString.CODE_LABEL;
LabelType labelType = (toSymbol != null && toSymbol.isExternal()) ? LabelType.EXTERNAL
: LabelType.CODE_LABEL;
LabelString label = new LabelString(result, labelType);
// Apply extended pointer markup if needed
@@ -1291,8 +1291,8 @@ public class CodeUnitFormat {
Symbol symbol = program.getSymbolTable().getSymbol(referencesFrom[0]);
if (symbol != null && !symbol.isDynamic()) {
String result = getSymbolLabelString(program, symbol, ref.getFromAddress());
return new LabelString(result,
symbol.isExternal() ? LabelString.EXTERNAL : LabelString.CODE_LABEL);
return new LabelString(result, symbol,
symbol.isExternal() ? LabelType.EXTERNAL : LabelType.CODE_LABEL);
}
return null;
}
@@ -12,6 +12,7 @@ color.fg.decompiler.type = color.palette.blue
color.fg.decompiler.parameter = color.palette.purple
color.fg.decompiler.global = color.palette.darkcyan
color.fg.decompiler.special = color.palette.crimson
color.fg.decompiler.external.function = color.palette.fuchsia
color.bg.decompiler.current.variable = color.palette.highlight.transparent.yellow
@@ -26,6 +26,7 @@ import docking.widgets.fieldpanel.field.*;
import docking.widgets.fieldpanel.listener.IndexMapper;
import docking.widgets.fieldpanel.listener.LayoutModelListener;
import docking.widgets.fieldpanel.support.*;
import generic.theme.GColor;
import ghidra.app.decompiler.*;
import ghidra.app.util.SymbolInspector;
import ghidra.app.util.viewer.field.CommentUtils;
@@ -41,6 +42,9 @@ import ghidra.util.UndefinedFunction;
*/
public class ClangLayoutController implements LayoutModel, LayoutModelListener {
private static GColor COLOR_EXTERNAL_FUNCTION =
new GColor("color.fg.decompiler.external.function");
private int maxWidth;
private int indentWidth;
private SymbolInspector symbolInspector;
@@ -202,22 +206,44 @@ public class ClangLayoutController implements LayoutModel, LayoutModelListener {
private Color getTokenColor(ClangToken token) {
Color tokenColor = syntaxColor[token.getSyntaxType()];
if (token instanceof ClangFuncNameToken clangFunctionToken) {
Program program = decompilerPanel.getProgram();
Function function = DecompilerUtils.getFunction(program, clangFunctionToken);
if (isValidFunction(function)) {
Symbol symbol = function.getSymbol();
tokenColor = symbolInspector.getColor(symbol);
return getFunctionColor(function);
}
}
Color tokenColor = syntaxColor[token.getSyntaxType()];
if (tokenColor != null) {
return tokenColor;
}
return syntaxColor[ClangToken.ERROR_COLOR];
}
private Color getFunctionColor(Function function) {
Symbol symbol = function.getSymbol();
// For now we have decided that any external function, linked or not, will be one color, as
// this makes it easy for the user to identify external function calls. Other functions will
// be colored according to the SymbolInspector. If we use the SymbolInspector for all
// colors, then some of the color values will be very close to some of the colors used by
// the Decompiler. For example, non-linked external functions default to red and linked
// external functions default to green.
if (function.isExternal()) {
return COLOR_EXTERNAL_FUNCTION;
}
if (function.isThunk()) {
Function thunkedFunction = function.getThunkedFunction(true);
if (thunkedFunction.isExternal()) {
return COLOR_EXTERNAL_FUNCTION;
}
}
return symbolInspector.getColor(symbol);
}
private boolean isValidFunction(Function f) {
return f != null && !(f instanceof UndefinedFunction);
}
@@ -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.
@@ -86,7 +86,7 @@ public class FieldLocation implements Comparable<FieldLocation> {
* @param index the index of the layout containing the location
* @param fieldNum the index of the field in the layout containing the location
* @param row the text row in the field containing the location.
* @param col the character position the row containing the location.
* @param col the character position in the row containing the location.
*/
public FieldLocation(int index, int fieldNum, int row, int col) {
this(BigInteger.valueOf(index), fieldNum, row, col);
@@ -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.
@@ -18,6 +18,8 @@ package ghidra.util;
import java.awt.Color;
import java.util.Comparator;
import generic.theme.GColor;
public class ColorUtils {
private static final int MAX_COLOR_VALUE = 255;
@@ -348,6 +350,26 @@ public class ColorUtils {
return new Color(red, green, blue, alpha);
}
/**
* Returns true if both colors are not null and have the same RGB value. This is useful to
* compare colors that may have different classes, such as {@link Color} and {@link GColor}.
*
* @param c1 the first color
* @param c2 the second color
* @return true if the colors have the same RGB value
*/
public static boolean hasSameRgb(Color c1, Color c2) {
int rgb1 = 0;
int rgb2 = 0;
if (c1 != null) {
rgb1 = c1.getRGB();
}
if (c2 != null) {
rgb2 = c2.getRGB();
}
return rgb1 == rgb2;
}
/**
* Blender of colors
*/
@@ -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.
@@ -15,27 +15,38 @@
*/
package ghidra.program.model.listing;
public class LabelString {
public enum LabelType { CODE_LABEL, VARIABLE, EXTERNAL }
import ghidra.program.model.symbol.Symbol;
public class LabelString {
public enum LabelType {
CODE_LABEL, VARIABLE, EXTERNAL
}
public static final LabelType CODE_LABEL = LabelType.CODE_LABEL;
public static final LabelType VARIABLE = LabelType.VARIABLE;
public static final LabelType EXTERNAL = LabelType.EXTERNAL;
private final String label;
private final LabelType type;
private Symbol symbol;
public LabelString(String label, LabelType type) {
this.label = label;
this.type = type;
}
public LabelString(String label, Symbol symbol, LabelType type) {
this.label = label;
this.symbol = symbol;
this.type = type;
}
public Symbol getSymbol() {
return symbol;
}
@Override
public String toString() {
return label;
}
public LabelType getLabelType() {
return type;
}
@@ -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.
@@ -15,12 +15,12 @@
*/
package ghidra.program.model.listing;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.lang.Register;
import ghidra.program.model.listing.LabelString.LabelType;
import ghidra.program.model.scalar.Scalar;
import ghidra.program.model.symbol.*;
import ghidra.util.SystemUtilities;
@@ -43,7 +43,7 @@ public class VariableOffset {
/**
* Constructor for an implied variable reference.
* @param variable function variable
* @param var function variable
* @param offset offset into variable
* @param indirect if true and variable data-type is a pointer, the offset
* is relative to underlying data-type of the pointer-type. This should generally be
@@ -51,8 +51,8 @@ public class VariableOffset {
* whereas it would be false for stack-references.
* @param dataAccess true if content of variable is being read and/or written
*/
public VariableOffset(Variable variable, long offset, boolean indirect, boolean dataAccess) {
this.variable = variable;
public VariableOffset(Variable var, long offset, boolean indirect, boolean dataAccess) {
this.variable = Objects.requireNonNull(var, "Variable reference not bound to a variable");
this.offset = offset;
this.indirect = indirect;
this.dataAccess = dataAccess;
@@ -65,20 +65,14 @@ public class VariableOffset {
*/
public VariableOffset(Reference ref, Variable var) {
indirect = false;
variable = var;
if (variable == null) {
throw new IllegalArgumentException("Variable reference not bound to a variable");
}
this.indirect = false;
this.variable = Objects.requireNonNull(var, "Variable reference not bound to a variable");
RefType rt = ref.getReferenceType();
dataAccess = rt.isRead() || rt.isWrite();
this.dataAccess = rt.isRead() || rt.isWrite();
if (ref instanceof StackReference && variable.isStackVariable()) {
offset = variable.getStackOffset();
offset = ((StackReference) ref).getStackOffset() - variable.getStackOffset();
this.offset = ((StackReference) ref).getStackOffset() - variable.getStackOffset();
}
}
/**
@@ -94,6 +88,7 @@ public class VariableOffset {
/**
* Sets the original replaced sub-operand Register.
* @param reg the register
*/
public void setReplacedElement(Register reg) {
replacedElement = reg;
@@ -107,9 +102,6 @@ public class VariableOffset {
return replacedElement;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuffer buf = new StringBuffer();
@@ -204,7 +196,7 @@ public class VariableOffset {
}
List<Object> list = new ArrayList<>();
list.add(new LabelString(name.toString(), LabelString.VARIABLE));
list.add(new LabelString(name.toString(), LabelType.VARIABLE));
if (absOffset != 0 || scalarAdjustment != 0) {
long adjustedOffset = (offset < 0 ? -absOffset : absOffset) + scalarAdjustment;