GP-5085 Functionality for unifying the color of external function names across the listing and decompiler views.

This commit is contained in:
ghidravision
2024-12-06 14:31:06 +00:00
parent 16388dc261
commit 6ed50fa085
9 changed files with 77 additions and 39 deletions
@@ -87,6 +87,10 @@ public abstract class CodeComparisonPanel extends JPanel
// to avoid java's constructor ordering problem // to avoid java's constructor ordering problem
} }
public PluginTool getTool() {
return tool;
}
/** /**
* Displays a comparison of two ComparisonData objects * Displays a comparison of two ComparisonData objects
* *
@@ -317,10 +321,14 @@ public abstract class CodeComparisonPanel extends JPanel
// Set the MINIMUM_PANEL_WIDTH for the left and right panel to prevent the split pane's // Set the MINIMUM_PANEL_WIDTH for the left and right panel to prevent the split pane's
// divider from becoming locked (can't be moved) due to extra long title names. // divider from becoming locked (can't be moved) due to extra long title names.
titlePanels.get(LEFT).setMinimumSize( titlePanels.get(LEFT)
new Dimension(MINIMUM_PANEL_WIDTH, titlePanels.get(LEFT).getMinimumSize().height)); .setMinimumSize(
titlePanels.get(RIGHT).setMinimumSize( new Dimension(MINIMUM_PANEL_WIDTH,
new Dimension(MINIMUM_PANEL_WIDTH, titlePanels.get(RIGHT).getMinimumSize().height)); titlePanels.get(LEFT).getMinimumSize().height));
titlePanels.get(RIGHT)
.setMinimumSize(
new Dimension(MINIMUM_PANEL_WIDTH,
titlePanels.get(RIGHT).getMinimumSize().height));
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, titlePanels.get(LEFT), splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, titlePanels.get(LEFT),
titlePanels.get(RIGHT)); titlePanels.get(RIGHT));
@@ -26,6 +26,7 @@ import ghidra.app.decompiler.DecompileOptions;
import ghidra.app.decompiler.component.*; import ghidra.app.decompiler.component.*;
import ghidra.framework.options.ToolOptions; import ghidra.framework.options.ToolOptions;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.ServiceProvider;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
@@ -38,6 +39,7 @@ import ghidra.program.util.ProgramLocation;
public class CDisplay { public class CDisplay {
private final static String OPTIONS_TITLE = "Decompiler"; private final static String OPTIONS_TITLE = "Decompiler";
private ServiceProvider serviceProvider;
private DecompilerController controller; private DecompilerController controller;
private DecompileOptions decompileOptions; private DecompileOptions decompileOptions;
private FieldLocation lastCursorPosition; private FieldLocation lastCursorPosition;
@@ -46,10 +48,12 @@ public class CDisplay {
private DecompilerProgramListener programListener; private DecompilerProgramListener programListener;
public CDisplay(DecompilerCodeComparisonOptions comparisonOptions, public CDisplay(ServiceProvider serviceProvider,
DecompilerCodeComparisonOptions comparisonOptions,
DecompileResultsListener decompileListener, DecompileResultsListener decompileListener,
Consumer<ProgramLocation> locationConsumer) { Consumer<ProgramLocation> locationConsumer) {
this.serviceProvider = serviceProvider;
highlightController = new DiffClangHighlightController(comparisonOptions); highlightController = new DiffClangHighlightController(comparisonOptions);
decompileOptions = new DecompileOptions(); decompileOptions = new DecompileOptions();
@@ -61,7 +65,7 @@ public class CDisplay {
} }
}; };
controller = new DecompilerController(handler, decompileOptions, null) { controller = new DecompilerController(serviceProvider, handler, decompileOptions, null) {
@Override @Override
public void setDecompileData(DecompileData decompileData) { public void setDecompileData(DecompileData decompileData) {
super.setDecompileData(decompileData); super.setDecompileData(decompileData);
@@ -226,7 +226,7 @@ public class DecompilerCodeComparisonPanel
} }
private CDisplay buildCDisplay(Side side) { private CDisplay buildCDisplay(Side side) {
return new CDisplay(comparisonOptions, return new CDisplay(getTool(), comparisonOptions,
decompileData -> decompileDataSet(side, decompileData), decompileData -> decompileDataSet(side, decompileData),
l -> locationChanged(side, l)); l -> locationChanged(side, l));
} }
@@ -4,7 +4,6 @@ color.bg.decompiler = color.bg
color.fg.decompiler = color.fg color.fg.decompiler = color.fg
color.fg.decompiler.keyword = color.palette.blue color.fg.decompiler.keyword = color.palette.blue
color.fg.decompiler.function.name = color.palette.blue
color.fg.decompiler.comment = color.palette.blueviolet color.fg.decompiler.comment = color.palette.blueviolet
color.fg.decompiler.error = color.palette.crimson color.fg.decompiler.error = color.palette.crimson
color.fg.decompiler.variable = color.palette.olive color.fg.decompiler.variable = color.palette.olive
@@ -418,9 +418,6 @@ public class DecompileOptions {
private final static String HIGHLIGHT_KEYWORD_MSG = "Display.Color for Keywords"; private final static String HIGHLIGHT_KEYWORD_MSG = "Display.Color for Keywords";
private final static GColor HIGHLIGHT_KEYWORD_COLOR = new GColor("color.fg.decompiler.keyword"); private final static GColor HIGHLIGHT_KEYWORD_COLOR = new GColor("color.fg.decompiler.keyword");
private final static String HIGHLIGHT_FUNCTION_MSG = "Display.Color for Function names";
private final static GColor HIGHLIGHT_FUNCTION_COLOR = new GColor("color.fg.decompiler.function.name");
private final static String HIGHLIGHT_COMMENT_MSG = "Display.Color for Comments"; private final static String HIGHLIGHT_COMMENT_MSG = "Display.Color for Comments";
private final static GColor HIGHLIGHT_COMMENT_COLOR = new GColor( "color.fg.decompiler.comment"); private final static GColor HIGHLIGHT_COMMENT_COLOR = new GColor( "color.fg.decompiler.comment");
@@ -751,9 +748,6 @@ public class DecompileOptions {
opt.registerThemeColorBinding(HIGHLIGHT_TYPE_MSG, HIGHLIGHT_TYPE_COLOR.getId(), opt.registerThemeColorBinding(HIGHLIGHT_TYPE_MSG, HIGHLIGHT_TYPE_COLOR.getId(),
new HelpLocation(HelpTopics.DECOMPILER, "DisplayTokenColor"), new HelpLocation(HelpTopics.DECOMPILER, "DisplayTokenColor"),
"Color used for highlighting types."); "Color used for highlighting types.");
opt.registerThemeColorBinding(HIGHLIGHT_FUNCTION_MSG, HIGHLIGHT_FUNCTION_COLOR.getId(),
new HelpLocation(HelpTopics.DECOMPILER, "DisplayTokenColor"),
"Color used for highlighting function names.");
opt.registerThemeColorBinding(HIGHLIGHT_COMMENT_MSG, HIGHLIGHT_COMMENT_COLOR.getId(), opt.registerThemeColorBinding(HIGHLIGHT_COMMENT_MSG, HIGHLIGHT_COMMENT_COLOR.getId(),
new HelpLocation(HelpTopics.DECOMPILER, "DisplayTokenColor"), new HelpLocation(HelpTopics.DECOMPILER, "DisplayTokenColor"),
"Color used for highlighting comments."); "Color used for highlighting comments.");
@@ -1054,13 +1048,6 @@ public class DecompileOptions {
return HIGHLIGHT_TYPE_COLOR; return HIGHLIGHT_TYPE_COLOR;
} }
/**
* @return color associated with a function name token
*/
public Color getFunctionColor() {
return HIGHLIGHT_FUNCTION_COLOR;
}
/** /**
* @return color used to display comments * @return color used to display comments
*/ */
@@ -27,10 +27,14 @@ import docking.widgets.fieldpanel.listener.IndexMapper;
import docking.widgets.fieldpanel.listener.LayoutModelListener; import docking.widgets.fieldpanel.listener.LayoutModelListener;
import docking.widgets.fieldpanel.support.*; import docking.widgets.fieldpanel.support.*;
import ghidra.app.decompiler.*; import ghidra.app.decompiler.*;
import ghidra.app.util.SymbolInspector;
import ghidra.app.util.viewer.field.CommentUtils; import ghidra.app.util.viewer.field.CommentUtils;
import ghidra.framework.plugintool.ServiceProvider;
import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.pcode.HighFunction; import ghidra.program.model.pcode.HighFunction;
import ghidra.program.model.symbol.Symbol;
import ghidra.util.UndefinedFunction;
/** /**
* Control the GUI layout for displaying tokenized C code * Control the GUI layout for displaying tokenized C code
@@ -39,8 +43,9 @@ public class ClangLayoutController implements LayoutModel, LayoutModelListener {
private int maxWidth; private int maxWidth;
private int indentWidth; private int indentWidth;
private DecompileOptions options; private SymbolInspector symbolInspector;
private DecompilerPanel decompilerPanel; private DecompilerPanel decompilerPanel;
private DecompileOptions options;
private ClangTokenGroup docroot; // Root of displayed document private ClangTokenGroup docroot; // Root of displayed document
private Field[] fieldList; // Array of fields comprising layout private Field[] fieldList; // Array of fields comprising layout
private FontMetrics metrics; private FontMetrics metrics;
@@ -61,6 +66,10 @@ public class ClangLayoutController implements LayoutModel, LayoutModelListener {
this.hlFactory = hlFactory; this.hlFactory = hlFactory;
listeners = new ArrayList<>(); listeners = new ArrayList<>();
buildLayouts(null, null, null, false); buildLayouts(null, null, null, false);
DecompilerController controller = decompilerPanel.getController();
ServiceProvider serviceProvider = controller.getServiceProvider();
symbolInspector = new SymbolInspector(serviceProvider, decompilerPanel);
} }
public List<ClangLine> getLines() { public List<ClangLine> getLines() {
@@ -173,7 +182,8 @@ public class ClangLayoutController implements LayoutModel, LayoutModelListener {
int columnPosition = 0; int columnPosition = 0;
for (int i = 0; i < tokens.size(); ++i) { for (int i = 0; i < tokens.size(); ++i) {
ClangToken token = tokens.get(i); ClangToken token = tokens.get(i);
Color color = syntaxColor[token.getSyntaxType()]; Color color = getTokenColor(token);
if (token instanceof ClangCommentToken) { if (token instanceof ClangCommentToken) {
AttributedString prototype = new AttributedString("prototype", color, metrics); AttributedString prototype = new AttributedString("prototype", color, metrics);
Program program = decompilerPanel.getProgram(); Program program = decompilerPanel.getProgram();
@@ -190,6 +200,22 @@ public class ClangLayoutController implements LayoutModel, LayoutModelListener {
return elements; return elements;
} }
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 (function instanceof UndefinedFunction) {
return null;
}
Symbol symbol = function.getSymbol();
return symbolInspector.getColor(symbol);
}
return tokenColor;
}
/** /**
* Update to the current Decompiler display options * Update to the current Decompiler display options
*/ */
@@ -198,8 +224,8 @@ public class ClangLayoutController implements LayoutModel, LayoutModelListener {
private void updateOptions() { private void updateOptions() {
syntaxColor[ClangToken.KEYWORD_COLOR] = options.getKeywordColor(); syntaxColor[ClangToken.KEYWORD_COLOR] = options.getKeywordColor();
syntaxColor[ClangToken.TYPE_COLOR] = options.getTypeColor(); syntaxColor[ClangToken.TYPE_COLOR] = options.getTypeColor();
syntaxColor[ClangToken.FUNCTION_COLOR] = options.getFunctionColor();
syntaxColor[ClangToken.COMMENT_COLOR] = options.getCommentColor(); syntaxColor[ClangToken.COMMENT_COLOR] = options.getCommentColor();
syntaxColor[ClangToken.FUNCTION_COLOR] = null; // not used by the UI
syntaxColor[ClangToken.VARIABLE_COLOR] = options.getVariableColor(); syntaxColor[ClangToken.VARIABLE_COLOR] = options.getVariableColor();
syntaxColor[ClangToken.CONST_COLOR] = options.getConstantColor(); syntaxColor[ClangToken.CONST_COLOR] = options.getConstantColor();
syntaxColor[ClangToken.PARAMETER_COLOR] = options.getParameterColor(); syntaxColor[ClangToken.PARAMETER_COLOR] = options.getParameterColor();
@@ -24,6 +24,7 @@ import com.google.common.cache.CacheBuilder;
import docking.widgets.fieldpanel.support.ViewerPosition; import docking.widgets.fieldpanel.support.ViewerPosition;
import ghidra.app.decompiler.*; import ghidra.app.decompiler.*;
import ghidra.app.plugin.core.decompile.DecompilerClipboardProvider; import ghidra.app.plugin.core.decompile.DecompilerClipboardProvider;
import ghidra.framework.plugintool.ServiceProvider;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.model.pcode.HighFunction; import ghidra.program.model.pcode.HighFunction;
@@ -38,6 +39,8 @@ import utility.function.Callback;
*/ */
public class DecompilerController { public class DecompilerController {
private ServiceProvider serviceProvider;
private DecompilerPanel decompilerPanel; private DecompilerPanel decompilerPanel;
private DecompilerManager decompilerMgr; private DecompilerManager decompilerMgr;
private final DecompilerCallbackHandler callbackHandler; private final DecompilerCallbackHandler callbackHandler;
@@ -46,8 +49,10 @@ public class DecompilerController {
private Cache<Function, DecompileResults> decompilerCache; private Cache<Function, DecompileResults> decompilerCache;
private int cacheSize; private int cacheSize;
public DecompilerController(DecompilerCallbackHandler handler, DecompileOptions options, public DecompilerController(ServiceProvider serviceProvider, DecompilerCallbackHandler handler,
DecompileOptions options,
DecompilerClipboardProvider clipboard) { DecompilerClipboardProvider clipboard) {
this.serviceProvider = serviceProvider;
this.cacheSize = options.getCacheSize(); this.cacheSize = options.getCacheSize();
this.callbackHandler = handler; this.callbackHandler = handler;
decompilerCache = buildCache(); decompilerCache = buildCache();
@@ -58,6 +63,10 @@ public class DecompilerController {
decompilerPanel.setHoverMode(true); decompilerPanel.setHoverMode(true);
} }
public ServiceProvider getServiceProvider() {
return serviceProvider;
}
public DecompilerPanel getDecompilerPanel() { public DecompilerPanel getDecompilerPanel() {
return decompilerPanel; return decompilerPanel;
} }
@@ -159,6 +159,10 @@ public class DecompilerPanel extends JPanel implements FieldMouseListener, Field
} }
} }
public DecompilerController getController() {
return controller;
}
public List<ClangLine> getLines() { public List<ClangLine> getLines() {
return layoutController.getLines(); return layoutController.getLines();
} }
@@ -134,7 +134,8 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
decompilerOptions = new DecompileOptions(); decompilerOptions = new DecompileOptions();
initializeDecompilerOptions(); initializeDecompilerOptions();
controller = new DecompilerController(this, decompilerOptions, clipboardProvider); controller =
new DecompilerController(getTool(), this, decompilerOptions, clipboardProvider);
DecompilerPanel decompilerPanel = controller.getDecompilerPanel(); DecompilerPanel decompilerPanel = controller.getDecompilerPanel();
// TODO move the hl controller into the panel // TODO move the hl controller into the panel