mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 02:09:44 +02:00
GP-1981 - Theming - Decompiler Module
This commit is contained in:
parent
466db9efe3
commit
2dade60b3e
16 changed files with 175 additions and 137 deletions
|
@ -13,6 +13,24 @@ color.fg.decompiler.global = darkCyan
|
||||||
|
|
||||||
color.bg.decompiler.middle.mouse = rgba(255,255,0,.5)
|
color.bg.decompiler.middle.mouse = rgba(255,255,0,.5)
|
||||||
color.bg.decompiler.current.variable = rgba(255,255,0,0.5)
|
color.bg.decompiler.current.variable = rgba(255,255,0,0.5)
|
||||||
|
color.fg.line.numbers = gray
|
||||||
|
|
||||||
|
color.bg.decompiler.highlights.default = rgba(255, 255, 0, .5)
|
||||||
|
color.bg.decompiler.highlights.special = sandybrown
|
||||||
|
color.bg.decompiler.highlights.search = mediumslateblue
|
||||||
|
|
||||||
|
color.bg.decompiler.pcode.dfg.vertex.default = red
|
||||||
|
color.bg.decompiler.pcode.dfg.vertex.selected = deeppink
|
||||||
|
color.bg.decompiler.pcode.dfg.vertex.constant = darkgreen
|
||||||
|
color.bg.decompiler.pcode.dfg.vertex.register = navy
|
||||||
|
color.bg.decompiler.pcode.dfg.vertex.unique = black
|
||||||
|
color.bg.decompiler.pcode.dfg.vertex.persistent = darkorange
|
||||||
|
color.bg.decompiler.pcode.dfg.vertex.address.tied = orange
|
||||||
|
color.bg.decompiler.pcode.dfg.vertex.op = red
|
||||||
|
color.bg.decompiler.pcode.dfg.edge.default = navy
|
||||||
|
color.bg.decompiler.pcode.dfg.edge.selected = deeppink
|
||||||
|
color.bg.decompiler.pcode.dfg.edge.within.block = black
|
||||||
|
color.bg.decompiler.pcode.dfg.edge.between.blocks = red
|
||||||
|
|
||||||
[Dark Defaults]
|
[Dark Defaults]
|
||||||
|
|
||||||
|
|
|
@ -54,18 +54,11 @@
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import classrecovery.DecompilerScriptUtils;
|
import classrecovery.*;
|
||||||
import classrecovery.RTTIClassRecoverer;
|
import generic.theme.GThemeDefaults.Colors.Palette;
|
||||||
import classrecovery.RTTIGccClassRecoverer;
|
|
||||||
import classrecovery.RTTIWindowsClassRecoverer;
|
|
||||||
import classrecovery.RecoveredClass;
|
|
||||||
import classrecovery.RecoveredClassHelper;
|
|
||||||
import ghidra.app.decompiler.DecompInterface;
|
import ghidra.app.decompiler.DecompInterface;
|
||||||
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
||||||
import ghidra.app.plugin.core.analysis.DecompilerFunctionAnalyzer;
|
import ghidra.app.plugin.core.analysis.DecompilerFunctionAnalyzer;
|
||||||
|
@ -81,29 +74,11 @@ import ghidra.app.util.importer.MessageLog;
|
||||||
import ghidra.app.util.opinion.ElfLoader;
|
import ghidra.app.util.opinion.ElfLoader;
|
||||||
import ghidra.framework.options.Options;
|
import ghidra.framework.options.Options;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.address.AddressSet;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.address.AddressSetView;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.data.CategoryPath;
|
|
||||||
import ghidra.program.model.data.DataType;
|
|
||||||
import ghidra.program.model.data.DataTypeComponent;
|
|
||||||
import ghidra.program.model.data.DataTypeManager;
|
|
||||||
import ghidra.program.model.data.Structure;
|
|
||||||
import ghidra.program.model.listing.Function;
|
|
||||||
import ghidra.program.model.listing.Parameter;
|
|
||||||
import ghidra.program.model.listing.Program;
|
|
||||||
import ghidra.program.model.mem.MemoryBlock;
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
import ghidra.service.graph.AttributedEdge;
|
import ghidra.service.graph.*;
|
||||||
import ghidra.service.graph.AttributedGraph;
|
|
||||||
import ghidra.service.graph.AttributedVertex;
|
|
||||||
import ghidra.service.graph.GraphDisplay;
|
|
||||||
import ghidra.service.graph.GraphDisplayOptions;
|
|
||||||
import ghidra.service.graph.GraphDisplayOptionsBuilder;
|
|
||||||
import ghidra.service.graph.GraphDisplayProvider;
|
|
||||||
import ghidra.service.graph.GraphType;
|
|
||||||
import ghidra.service.graph.GraphTypeBuilder;
|
|
||||||
import ghidra.service.graph.VertexShape;
|
|
||||||
import ghidra.util.WebColors;
|
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.exception.GraphException;
|
import ghidra.util.exception.GraphException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
@ -403,11 +378,10 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void analyzeChanges(Program program) {
|
public void analyzeChanges(Program program) {
|
||||||
AutoAnalysisManager mgr = AutoAnalysisManager.getAnalysisManager(program);
|
AutoAnalysisManager mgr = AutoAnalysisManager.getAnalysisManager(program);
|
||||||
mgr.startAnalysis(monitor, false);
|
mgr.startAnalysis(monitor, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to create a class hierarchy graph where the parents are at the top of the graph and
|
* Method to create a class hierarchy graph where the parents are at the top of the graph and
|
||||||
|
@ -486,7 +460,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
edge.setEdgeType(NON_VIRTUAL_INHERITANCE);
|
edge.setEdgeType(NON_VIRTUAL_INHERITANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,13 +481,13 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
display = service.getGraphDisplay(false, TaskMonitor.DUMMY);
|
display = service.getGraphDisplay(false, TaskMonitor.DUMMY);
|
||||||
|
|
||||||
GraphDisplayOptions graphOptions = new GraphDisplayOptionsBuilder(graph.getGraphType())
|
GraphDisplayOptions graphOptions = new GraphDisplayOptionsBuilder(graph.getGraphType())
|
||||||
.vertex(NO_INHERITANCE, VertexShape.RECTANGLE, WebColors.BLUE)
|
.vertex(NO_INHERITANCE, VertexShape.RECTANGLE, Palette.BLUE)
|
||||||
.vertex(SINGLE_INHERITANCE, VertexShape.RECTANGLE, WebColors.GREEN)
|
.vertex(SINGLE_INHERITANCE, VertexShape.RECTANGLE, Palette.GREEN)
|
||||||
.vertex(MULTIPLE_INHERITANCE, VertexShape.RECTANGLE, WebColors.RED)
|
.vertex(MULTIPLE_INHERITANCE, VertexShape.RECTANGLE, Palette.RED)
|
||||||
.edge(NON_VIRTUAL_INHERITANCE, WebColors.LIME_GREEN)
|
.edge(NON_VIRTUAL_INHERITANCE, Palette.LIME)
|
||||||
.edge(VIRTUAL_INHERITANCE, WebColors.ORANGE)
|
.edge(VIRTUAL_INHERITANCE, Palette.ORANGE)
|
||||||
.defaultVertexColor(WebColors.PURPLE)
|
.defaultVertexColor(Palette.PURPLE)
|
||||||
.defaultEdgeColor(WebColors.PURPLE)
|
.defaultEdgeColor(Palette.PURPLE)
|
||||||
.defaultLayoutAlgorithm("Compact Hierarchical")
|
.defaultLayoutAlgorithm("Compact Hierarchical")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -534,7 +507,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
return doOutput;
|
return doOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void printClassHierarchyLists(List<RecoveredClass> recoveredClasses)
|
private void printClassHierarchyLists(List<RecoveredClass> recoveredClasses)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
|
|
||||||
|
@ -551,9 +523,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Script works on versions of ghidra including and after 9.2 except for 9.2.1 because a method
|
* Script works on versions of ghidra including and after 9.2 except for 9.2.1 because a method
|
||||||
* was accidentally removed from FillOutStructureCmd that is needed
|
* was accidentally removed from FillOutStructureCmd that is needed
|
||||||
|
@ -579,8 +548,11 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isCompilerSpecGcc =
|
boolean isCompilerSpecGcc =
|
||||||
currentProgram.getCompilerSpec().getCompilerSpecID().getIdAsString().equalsIgnoreCase(
|
currentProgram.getCompilerSpec()
|
||||||
"gcc");
|
.getCompilerSpecID()
|
||||||
|
.getIdAsString()
|
||||||
|
.equalsIgnoreCase(
|
||||||
|
"gcc");
|
||||||
if (isCompilerSpecGcc) {
|
if (isCompilerSpecGcc) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -598,8 +570,9 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
byte[] gccBytes = { (byte) 0x47, (byte) 0x43, (byte) 0x43, (byte) 0x3a };
|
byte[] gccBytes = { (byte) 0x47, (byte) 0x43, (byte) 0x43, (byte) 0x3a };
|
||||||
byte[] maskBytes = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
|
byte[] maskBytes = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
|
||||||
|
|
||||||
Address found = currentProgram.getMemory().findBytes(commentBlock.getStart(),
|
Address found = currentProgram.getMemory()
|
||||||
commentBlock.getEnd(), gccBytes, maskBytes, true, monitor);
|
.findBytes(commentBlock.getStart(),
|
||||||
|
commentBlock.getEnd(), gccBytes, maskBytes, true, monitor);
|
||||||
if (found == null) {
|
if (found == null) {
|
||||||
isGcc = false;
|
isGcc = false;
|
||||||
}
|
}
|
||||||
|
@ -621,8 +594,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
return isWindows;
|
return isWindows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to determine if somehow the constructor list and destructor list for a class contain
|
* Method to determine if somehow the constructor list and destructor list for a class contain
|
||||||
* overlapping functions
|
* overlapping functions
|
||||||
|
@ -637,12 +608,18 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
recoverClassesFromRTTI.getAllClassDestructors(recoveredClass);
|
recoverClassesFromRTTI.getAllClassDestructors(recoveredClass);
|
||||||
|
|
||||||
List<Function> commonFunctions1 =
|
List<Function> commonFunctions1 =
|
||||||
allClassConstructors.stream().distinct().filter(allClassDestructors::contains).collect(
|
allClassConstructors.stream()
|
||||||
Collectors.toList());
|
.distinct()
|
||||||
|
.filter(allClassDestructors::contains)
|
||||||
|
.collect(
|
||||||
|
Collectors.toList());
|
||||||
|
|
||||||
List<Function> commonFunctions2 =
|
List<Function> commonFunctions2 =
|
||||||
allClassDestructors.stream().distinct().filter(allClassConstructors::contains).collect(
|
allClassDestructors.stream()
|
||||||
Collectors.toList());
|
.distinct()
|
||||||
|
.filter(allClassConstructors::contains)
|
||||||
|
.collect(
|
||||||
|
Collectors.toList());
|
||||||
|
|
||||||
if (commonFunctions1.isEmpty() && commonFunctions2.isEmpty()) {
|
if (commonFunctions1.isEmpty() && commonFunctions2.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -661,8 +638,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
analyzer.added(currentProgram, set, monitor, new MessageLog());
|
analyzer.added(currentProgram, set, monitor, new MessageLog());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the version of Ghidra that was used to analyze this program
|
* Get the version of Ghidra that was used to analyze this program
|
||||||
* @return a string containing the version number of Ghidra used to analyze the current program
|
* @return a string containing the version number of Ghidra used to analyze the current program
|
||||||
|
@ -673,7 +648,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
return options.getString("Created With Ghidra Version", null);
|
return options.getString("Created With Ghidra Version", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to bookmark all of the constructor/destructor/indeterminate functions
|
* Method to bookmark all of the constructor/destructor/indeterminate functions
|
||||||
* @param recoveredClasses List of classes
|
* @param recoveredClasses List of classes
|
||||||
|
@ -686,7 +660,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
bookmarkRemainingIndeterminateConstructorsAndDestructors(recoveredClasses);
|
bookmarkRemainingIndeterminateConstructorsAndDestructors(recoveredClasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to print class hierarchy of the form child : parent: grandparent : etc...
|
* Method to print class hierarchy of the form child : parent: grandparent : etc...
|
||||||
* @param stringBuffer the buffer to add the newly created string to
|
* @param stringBuffer the buffer to add the newly created string to
|
||||||
|
@ -707,7 +680,7 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
Map<RecoveredClass, List<RecoveredClass>> classHierarchyMap =
|
Map<RecoveredClass, List<RecoveredClass>> classHierarchyMap =
|
||||||
recoveredClass.getClassHierarchyMap();
|
recoveredClass.getClassHierarchyMap();
|
||||||
|
|
||||||
List<RecoveredClass> parents = new ArrayList<RecoveredClass>(classHierarchyMap.keySet());
|
List<RecoveredClass> parents = new ArrayList<>(classHierarchyMap.keySet());
|
||||||
|
|
||||||
// if single inheritance - simple linear case
|
// if single inheritance - simple linear case
|
||||||
if (recoveredClass.hasSingleInheritance()) {
|
if (recoveredClass.hasSingleInheritance()) {
|
||||||
|
@ -742,9 +715,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to retrieve the AddressSet of the current program's initialized memory
|
* Method to retrieve the AddressSet of the current program's initialized memory
|
||||||
* @return the AddressSet of the current program's initialized memory
|
* @return the AddressSet of the current program's initialized memory
|
||||||
|
@ -765,8 +735,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
return dataAddresses;
|
return dataAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to bookmark found constructor functions
|
* Method to bookmark found constructor functions
|
||||||
* @param recoveredClasses List of classes
|
* @param recoveredClasses List of classes
|
||||||
|
@ -810,7 +778,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to add/append analysis bookmarks with the given comment to the given list of functions
|
* Method to add/append analysis bookmarks with the given comment to the given list of functions
|
||||||
* @param functions List of functions
|
* @param functions List of functions
|
||||||
|
@ -831,7 +798,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to optionally print to console or output to file various types of class information
|
* Method to optionally print to console or output to file various types of class information
|
||||||
* depending on the options set at top of script
|
* depending on the options set at top of script
|
||||||
|
@ -894,7 +860,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void outputClassDefinitions(List<RecoveredClass> recoveredClasses, PrintWriter out)
|
private void outputClassDefinitions(List<RecoveredClass> recoveredClasses, PrintWriter out)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
for (RecoveredClass recoveredClass : recoveredClasses) {
|
for (RecoveredClass recoveredClass : recoveredClasses) {
|
||||||
|
@ -904,7 +869,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -938,7 +902,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to print class hierarchies for the given list of classes starting with the lowest child classes in each family of classes
|
* Method to print class hierarchies for the given list of classes starting with the lowest child classes in each family of classes
|
||||||
* @param recoveredClasses the list of classes
|
* @param recoveredClasses the list of classes
|
||||||
|
@ -947,7 +910,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
private void printClassHierarchiesFromLowestChildren(
|
private void printClassHierarchiesFromLowestChildren(
|
||||||
List<RecoveredClass> recoveredClasses) throws CancelledException {
|
List<RecoveredClass> recoveredClasses) throws CancelledException {
|
||||||
|
|
||||||
|
|
||||||
StringBuffer wholeBuffer = new StringBuffer();
|
StringBuffer wholeBuffer = new StringBuffer();
|
||||||
wholeBuffer.append("\r\n");
|
wholeBuffer.append("\r\n");
|
||||||
for (RecoveredClass recoveredClass : recoveredClasses) {
|
for (RecoveredClass recoveredClass : recoveredClasses) {
|
||||||
|
@ -1006,7 +968,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to print counts of various class items for the given classes, such as number of constructors, destructors, etc...
|
* Method to print counts of various class items for the given classes, such as number of constructors, destructors, etc...
|
||||||
* @param recoveredClasses list of classes
|
* @param recoveredClasses list of classes
|
||||||
|
@ -1014,7 +975,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
*/
|
*/
|
||||||
private void printCounts(List<RecoveredClass> recoveredClasses) throws CancelledException {
|
private void printCounts(List<RecoveredClass> recoveredClasses) throws CancelledException {
|
||||||
|
|
||||||
|
|
||||||
println("Total number of constructors: " +
|
println("Total number of constructors: " +
|
||||||
recoverClassesFromRTTI.getNumberOfConstructors(recoveredClasses));
|
recoverClassesFromRTTI.getNumberOfConstructors(recoveredClasses));
|
||||||
println("Total number of inlined constructors: " +
|
println("Total number of inlined constructors: " +
|
||||||
|
@ -1050,7 +1010,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to get the total number of
|
* Method to get the total number of
|
||||||
* @param recoveredClasses list of classes
|
* @param recoveredClasses list of classes
|
||||||
|
@ -1099,7 +1058,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to output the class, it's parents and it's children for each of the listed classes
|
* Method to output the class, it's parents and it's children for each of the listed classes
|
||||||
* @param recoveredClasses the given classes
|
* @param recoveredClasses the given classes
|
||||||
|
@ -1219,7 +1177,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
stringBuffer.append("\tNone\r\n");
|
stringBuffer.append("\tNone\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// print child classes
|
// print child classes
|
||||||
stringBuffer.append("\r\n");
|
stringBuffer.append("\r\n");
|
||||||
stringBuffer.append("child class(es):\r\n");
|
stringBuffer.append("child class(es):\r\n");
|
||||||
|
@ -1279,7 +1236,7 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
// print const/dest that couldn't be classified correctly
|
// print const/dest that couldn't be classified correctly
|
||||||
List<Function> indeterminateList = recoveredClass.getIndeterminateList();
|
List<Function> indeterminateList = recoveredClass.getIndeterminateList();
|
||||||
if (indeterminateList.size() > 0) {
|
if (indeterminateList.size() > 0) {
|
||||||
stringBuffer.append("\r\nindeterminate constructor(s) or destructor(s):\r\n");
|
stringBuffer.append("\r\nindeterminate constructor(s) or destructor(s):\r\n");
|
||||||
for (Function indeterminateFunction : indeterminateList) {
|
for (Function indeterminateFunction : indeterminateList) {
|
||||||
monitor.checkCanceled();
|
monitor.checkCanceled();
|
||||||
stringBuffer.append("\t" + indeterminateFunction.getName() + " " +
|
stringBuffer.append("\t" + indeterminateFunction.getName() + " " +
|
||||||
|
@ -1332,7 +1289,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
return stringBuffer;
|
return stringBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to get the function signature string, from the decompiler if possible, otherwise from
|
* Method to get the function signature string, from the decompiler if possible, otherwise from
|
||||||
* the listing
|
* the listing
|
||||||
|
@ -1387,7 +1343,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
return stringBuffer.toString();
|
return stringBuffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to create a string containing a C++-like representation of the given class
|
* Method to create a string containing a C++-like representation of the given class
|
||||||
* @param recoveredClass the given class
|
* @param recoveredClass the given class
|
||||||
|
@ -1397,7 +1352,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
private StringBuffer createClassDefinitionString(RecoveredClass recoveredClass)
|
private StringBuffer createClassDefinitionString(RecoveredClass recoveredClass)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
|
|
||||||
|
|
||||||
StringBuffer stringBuffer = new StringBuffer();
|
StringBuffer stringBuffer = new StringBuffer();
|
||||||
stringBuffer.append("\r\n\r\n");
|
stringBuffer.append("\r\n\r\n");
|
||||||
|
|
||||||
|
@ -1405,7 +1359,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
|
|
||||||
stringBuffer.append("\r\n{\r\n");
|
stringBuffer.append("\r\n{\r\n");
|
||||||
|
|
||||||
|
|
||||||
// print constructor signature(s)
|
// print constructor signature(s)
|
||||||
stringBuffer.append("constructor(s):\r\n");
|
stringBuffer.append("constructor(s):\r\n");
|
||||||
List<Function> constructorList = recoveredClass.getConstructorList();
|
List<Function> constructorList = recoveredClass.getConstructorList();
|
||||||
|
@ -1474,7 +1427,6 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
}
|
}
|
||||||
stringBuffer.append("};\r\n");
|
stringBuffer.append("};\r\n");
|
||||||
|
|
||||||
|
|
||||||
// Then recursively process the child classes
|
// Then recursively process the child classes
|
||||||
if (recoveredClass.hasChildClass()) {
|
if (recoveredClass.hasChildClass()) {
|
||||||
List<RecoveredClass> childClasses = recoveredClass.getChildClasses();
|
List<RecoveredClass> childClasses = recoveredClass.getChildClasses();
|
||||||
|
@ -1487,6 +1439,4 @@ public class RecoverClassesFromRTTIScript extends GhidraScript {
|
||||||
return stringBuffer;
|
return stringBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -349,7 +349,8 @@ public class DecompileOptions {
|
||||||
|
|
||||||
private static final String SEARCH_HIGHLIGHT_MSG =
|
private static final String SEARCH_HIGHLIGHT_MSG =
|
||||||
"Display.Color for Highlighting Find Matches";
|
"Display.Color for Highlighting Find Matches";
|
||||||
private static final Color SEARCH_HIGHLIGHT_DEF = new Color(100, 100, 255);
|
private static final Color SEARCH_HIGHLIGHT_DEF =
|
||||||
|
new GColor("color.bg.decompiler.highlights.search");
|
||||||
private Color defaultSearchHighlightColor = SEARCH_HIGHLIGHT_DEF;
|
private Color defaultSearchHighlightColor = SEARCH_HIGHLIGHT_DEF;
|
||||||
|
|
||||||
// Color applied to a token to indicate warning/error
|
// Color applied to a token to indicate warning/error
|
||||||
|
|
|
@ -21,6 +21,7 @@ import java.awt.Graphics;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
|
||||||
import docking.widgets.fieldpanel.field.*;
|
import docking.widgets.fieldpanel.field.*;
|
||||||
|
import generic.theme.GThemeDefaults.Colors.Palette;
|
||||||
import ghidra.app.decompiler.ClangToken;
|
import ghidra.app.decompiler.ClangToken;
|
||||||
|
|
||||||
public class ClangFieldElement extends AbstractTextFieldElement {
|
public class ClangFieldElement extends AbstractTextFieldElement {
|
||||||
|
@ -49,7 +50,7 @@ public class ClangFieldElement extends AbstractTextFieldElement {
|
||||||
|
|
||||||
if (token.isMatchingToken()) {
|
if (token.isMatchingToken()) {
|
||||||
// paint a bounding box around the token
|
// paint a bounding box around the token
|
||||||
g.setColor(Color.GRAY);
|
g.setColor(Palette.GRAY);
|
||||||
int offset = 1;
|
int offset = 1;
|
||||||
g.drawRect(x - offset, y - getHeightAbove() - offset, getStringWidth() + (offset * 2),
|
g.drawRect(x - offset, y - getHeightAbove() - offset, getStringWidth() + (offset * 2),
|
||||||
getHeightAbove() + getHeightBelow() + (offset * 2));
|
getHeightAbove() + getHeightBelow() + (offset * 2));
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.apache.commons.collections4.map.LazyMap;
|
||||||
import docking.widgets.EventTrigger;
|
import docking.widgets.EventTrigger;
|
||||||
import docking.widgets.fieldpanel.field.Field;
|
import docking.widgets.fieldpanel.field.Field;
|
||||||
import docking.widgets.fieldpanel.support.FieldLocation;
|
import docking.widgets.fieldpanel.support.FieldLocation;
|
||||||
|
import generic.theme.GColor;
|
||||||
import ghidra.app.decompiler.*;
|
import ghidra.app.decompiler.*;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.program.model.pcode.HighFunction;
|
import ghidra.program.model.pcode.HighFunction;
|
||||||
|
@ -63,7 +64,8 @@ import util.CollectionUtils;
|
||||||
*/
|
*/
|
||||||
public abstract class ClangHighlightController {
|
public abstract class ClangHighlightController {
|
||||||
|
|
||||||
public static Color DEFAULT_HIGHLIGHT_COLOR = new Color(255, 255, 0, 128);
|
public static Color DEFAULT_HIGHLIGHT_COLOR =
|
||||||
|
new GColor("color.bg.decompiler.highlights.default");
|
||||||
|
|
||||||
public static ClangHighlightController dummyIfNull(ClangHighlightController c) {
|
public static ClangHighlightController dummyIfNull(ClangHighlightController c) {
|
||||||
if (c == null) {
|
if (c == null) {
|
||||||
|
|
|
@ -63,7 +63,8 @@ public class DecompilerPanel extends JPanel implements FieldMouseListener, Field
|
||||||
private final static Color NON_FUNCTION_BACKGROUND_COLOR_DEF = new GColor("color.bg.undefined");
|
private final static Color NON_FUNCTION_BACKGROUND_COLOR_DEF = new GColor("color.bg.undefined");
|
||||||
|
|
||||||
// Default color for specially highlighted tokens
|
// Default color for specially highlighted tokens
|
||||||
private final static Color SPECIAL_COLOR_DEF = new Color(255, 100, 0, 128);
|
private final static Color SPECIAL_COLOR_DEF =
|
||||||
|
new GColor("color.bg.decompiler.highlights.special");
|
||||||
|
|
||||||
private final DecompilerController controller;
|
private final DecompilerController controller;
|
||||||
private final DecompileOptions options;
|
private final DecompileOptions options;
|
||||||
|
|
|
@ -42,6 +42,6 @@ public class HighlightToken {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return token.toString() + "; color=" + color;
|
return token.toString() + "; highlight=" + color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,21 +18,27 @@ package ghidra.app.decompiler.component;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import generic.theme.Gui;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class to create and store colors related to token names
|
* A class to create and store colors related to token names
|
||||||
*/
|
*/
|
||||||
public class TokenHighlightColors {
|
public class TokenHighlightColors {
|
||||||
|
|
||||||
private int minColorSaturation = 100;
|
|
||||||
private int defaultColorAlpha = 100;
|
|
||||||
private Map<String, Color> colorsByName = new HashMap<>();
|
private Map<String, Color> colorsByName = new HashMap<>();
|
||||||
private List<Color> recentColors = new ArrayList<>();
|
private List<Color> recentColors = new ArrayList<>();
|
||||||
|
|
||||||
private Color generateColor() {
|
private Color generateColor() {
|
||||||
return new Color((int) (minColorSaturation + Math.random() * (256 - minColorSaturation)),
|
|
||||||
(int) (minColorSaturation + Math.random() * (256 - minColorSaturation)),
|
float h = (float) Math.random(); // 0-360
|
||||||
(int) (minColorSaturation + Math.random() * (256 - minColorSaturation)),
|
float s = .25f; // saturation; gray to full color; full color is too harsh for highlights
|
||||||
defaultColorAlpha);
|
float b = 1f; // brightness; black to full color
|
||||||
|
if (Gui.getActiveTheme().useDarkDefaults()) {
|
||||||
|
s = .5f; // a bit more color against a dark background
|
||||||
|
b = .5f; // less brightness, as the background is not as bright
|
||||||
|
}
|
||||||
|
|
||||||
|
return Color.getHSBColor(h, s, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Color getColor(String text) {
|
public Color getColor(String text) {
|
||||||
|
|
|
@ -18,9 +18,11 @@ package ghidra.app.plugin.core.decompile.actions;
|
||||||
import static ghidra.app.plugin.core.decompile.actions.PCodeDfgGraphType.*;
|
import static ghidra.app.plugin.core.decompile.actions.PCodeDfgGraphType.*;
|
||||||
import static ghidra.service.graph.VertexShape.*;
|
import static ghidra.service.graph.VertexShape.*;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
|
||||||
|
import generic.theme.GColor;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.service.graph.*;
|
import ghidra.service.graph.*;
|
||||||
import ghidra.util.WebColors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link GraphDisplayOptions} for {@link PCodeDfgGraphType}
|
* {@link GraphDisplayOptions} for {@link PCodeDfgGraphType}
|
||||||
|
@ -28,6 +30,32 @@ import ghidra.util.WebColors;
|
||||||
public class PCodeDfgDisplayOptions extends GraphDisplayOptions {
|
public class PCodeDfgDisplayOptions extends GraphDisplayOptions {
|
||||||
public static final String SHAPE_ATTRIBUTE = "Shape";
|
public static final String SHAPE_ATTRIBUTE = "Shape";
|
||||||
|
|
||||||
|
private static final Color BG_VERTEX_DEFAULT =
|
||||||
|
new GColor("color.bg.decompiler.pcode.dfg.vertex.default");
|
||||||
|
private static final Color BG_VERTEX_SELECTED =
|
||||||
|
new GColor("color.bg.decompiler.pcode.dfg.vertex.selected");
|
||||||
|
private static final Color BG_VERTEX_CONSTANT =
|
||||||
|
new GColor("color.bg.decompiler.pcode.dfg.vertex.constant");
|
||||||
|
private static final Color BG_VERTEX_REGISTER =
|
||||||
|
new GColor("color.bg.decompiler.pcode.dfg.vertex.register");
|
||||||
|
private static final Color BG_VERTEX_UNIQUE =
|
||||||
|
new GColor("color.bg.decompiler.pcode.dfg.vertex.unique");
|
||||||
|
private static final Color BG_VERTEX_PERSISTENT =
|
||||||
|
new GColor("color.bg.decompiler.pcode.dfg.vertex.persistent");
|
||||||
|
private static final Color BG_VERTEX_ADDRESS_TIED =
|
||||||
|
new GColor("color.bg.decompiler.pcode.dfg.vertex.address.tied");
|
||||||
|
private static final Color BG_VERTEX_OP =
|
||||||
|
new GColor("color.bg.decompiler.pcode.dfg.vertex.op");
|
||||||
|
|
||||||
|
private static final Color BG_EDGE_DEFAULT =
|
||||||
|
new GColor("color.bg.decompiler.pcode.dfg.edge.default");
|
||||||
|
private static final Color BG_EDGE_SELECTED =
|
||||||
|
new GColor("color.bg.decompiler.pcode.dfg.edge.selected");
|
||||||
|
private static final Color BG_EDGE_WITHIN_BLOCK =
|
||||||
|
new GColor("color.bg.decompiler.pcode.dfg.edge.within.block");
|
||||||
|
private static final Color BG_EDGE_BETWEEN_BLOCKS =
|
||||||
|
new GColor("color.bg.decompiler.pcode.dfg.edge.between.blocks");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* constructor
|
* constructor
|
||||||
* @param tool if non-null, will load values from tool options
|
* @param tool if non-null, will load values from tool options
|
||||||
|
@ -39,10 +67,10 @@ public class PCodeDfgDisplayOptions extends GraphDisplayOptions {
|
||||||
@Override
|
@Override
|
||||||
protected void initializeDefaults() {
|
protected void initializeDefaults() {
|
||||||
setDefaultVertexShape(ELLIPSE);
|
setDefaultVertexShape(ELLIPSE);
|
||||||
setDefaultVertexColor(WebColors.RED);
|
setDefaultVertexColor(BG_VERTEX_DEFAULT);
|
||||||
setDefaultEdgeColor(WebColors.NAVY);
|
setDefaultEdgeColor(BG_EDGE_DEFAULT);
|
||||||
setVertexSelectionColor(WebColors.DEEP_PINK);
|
setVertexSelectionColor(BG_VERTEX_SELECTED);
|
||||||
setEdgeSelectionColor(WebColors.DEEP_PINK);
|
setEdgeSelectionColor(BG_EDGE_SELECTED);
|
||||||
setDefaultLayoutAlgorithmName(LayoutAlgorithmNames.MIN_CROSS_COFFMAN_GRAHAM);
|
setDefaultLayoutAlgorithmName(LayoutAlgorithmNames.MIN_CROSS_COFFMAN_GRAHAM);
|
||||||
setUsesIcons(false);
|
setUsesIcons(false);
|
||||||
setArrowLength(15);
|
setArrowLength(15);
|
||||||
|
@ -50,16 +78,16 @@ public class PCodeDfgDisplayOptions extends GraphDisplayOptions {
|
||||||
setVertexShapeOverrideAttributeKey(SHAPE_ATTRIBUTE);
|
setVertexShapeOverrideAttributeKey(SHAPE_ATTRIBUTE);
|
||||||
setMaxNodeCount(1000);
|
setMaxNodeCount(1000);
|
||||||
|
|
||||||
configureVertexType(DEFAULT_VERTEX, VertexShape.ELLIPSE, WebColors.RED);
|
configureVertexType(DEFAULT_VERTEX, VertexShape.ELLIPSE, BG_VERTEX_DEFAULT);
|
||||||
configureVertexType(CONSTANT, VertexShape.ELLIPSE, WebColors.DARK_GREEN);
|
configureVertexType(CONSTANT, VertexShape.ELLIPSE, BG_VERTEX_CONSTANT);
|
||||||
configureVertexType(REGISTER, VertexShape.ELLIPSE, WebColors.NAVY);
|
configureVertexType(REGISTER, VertexShape.ELLIPSE, BG_VERTEX_REGISTER);
|
||||||
configureVertexType(UNIQUE, VertexShape.ELLIPSE, WebColors.BLACK);
|
configureVertexType(UNIQUE, VertexShape.ELLIPSE, BG_VERTEX_UNIQUE);
|
||||||
configureVertexType(PERSISTENT, VertexShape.ELLIPSE, WebColors.DARK_ORANGE);
|
configureVertexType(PERSISTENT, VertexShape.ELLIPSE, BG_VERTEX_PERSISTENT);
|
||||||
configureVertexType(ADDRESS_TIED, VertexShape.ELLIPSE, WebColors.ORANGE);
|
configureVertexType(ADDRESS_TIED, VertexShape.ELLIPSE, BG_VERTEX_ADDRESS_TIED);
|
||||||
configureVertexType(OP, VertexShape.ELLIPSE, WebColors.RED);
|
configureVertexType(OP, VertexShape.ELLIPSE, BG_VERTEX_OP);
|
||||||
|
|
||||||
configureEdgeType(DEFAULT_EDGE, WebColors.BLUE);
|
configureEdgeType(DEFAULT_EDGE, BG_EDGE_DEFAULT);
|
||||||
configureEdgeType(WITHIN_BLOCK, WebColors.BLACK);
|
configureEdgeType(WITHIN_BLOCK, BG_EDGE_WITHIN_BLOCK);
|
||||||
configureEdgeType(BETWEEN_BLOCKS, WebColors.RED);
|
configureEdgeType(BETWEEN_BLOCKS, BG_EDGE_BETWEEN_BLOCKS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ import docking.widgets.dialogs.InputDialog;
|
||||||
import docking.widgets.fieldpanel.FieldPanel;
|
import docking.widgets.fieldpanel.FieldPanel;
|
||||||
import docking.widgets.fieldpanel.field.Field;
|
import docking.widgets.fieldpanel.field.Field;
|
||||||
import docking.widgets.fieldpanel.support.FieldLocation;
|
import docking.widgets.fieldpanel.support.FieldLocation;
|
||||||
|
import generic.theme.GThemeDefaults.Colors.Palette;
|
||||||
import ghidra.app.cmd.comments.SetCommentCmd;
|
import ghidra.app.cmd.comments.SetCommentCmd;
|
||||||
import ghidra.app.decompiler.*;
|
import ghidra.app.decompiler.*;
|
||||||
import ghidra.app.decompiler.DecompileOptions.NamespaceStrategy;
|
import ghidra.app.decompiler.DecompileOptions.NamespaceStrategy;
|
||||||
|
@ -927,7 +928,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||||
String secondaryHighlightText = token.getText();
|
String secondaryHighlightText = token.getText();
|
||||||
assertEquals("_printf", secondaryHighlightText);
|
assertEquals("_printf", secondaryHighlightText);
|
||||||
|
|
||||||
Color myColor = Color.PINK;
|
Color myColor = Palette.PINK;
|
||||||
highlightWithColorChooser(myColor);
|
highlightWithColorChooser(myColor);
|
||||||
assertAllFieldsSecondaryHighlighted(token, myColor);
|
assertAllFieldsSecondaryHighlighted(token, myColor);
|
||||||
}
|
}
|
||||||
|
@ -964,7 +965,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||||
String secondaryHighlightText = token.getText();
|
String secondaryHighlightText = token.getText();
|
||||||
assertEquals("_printf", secondaryHighlightText);
|
assertEquals("_printf", secondaryHighlightText);
|
||||||
|
|
||||||
Color myColor = Color.PINK;
|
Color myColor = Palette.PINK;
|
||||||
highlightWithColorChooser(myColor);
|
highlightWithColorChooser(myColor);
|
||||||
|
|
||||||
removeSecondaryHighlight();
|
removeSecondaryHighlight();
|
||||||
|
@ -1130,7 +1131,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||||
decompile("100000d60"); // '_call_structure_A'
|
decompile("100000d60"); // '_call_structure_A'
|
||||||
|
|
||||||
String hlText = "_printf";
|
String hlText = "_printf";
|
||||||
Color hlColor = Color.PINK;
|
Color hlColor = Palette.PINK;
|
||||||
CTokenHighlightMatcher hlMatcher = token -> {
|
CTokenHighlightMatcher hlMatcher = token -> {
|
||||||
if (token.getText().contains(hlText)) {
|
if (token.getText().contains(hlText)) {
|
||||||
return hlColor;
|
return hlColor;
|
||||||
|
@ -1180,7 +1181,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||||
assertPrimaryHighlights("(\"call_structure_A: %s\\n\",a->name)");
|
assertPrimaryHighlights("(\"call_structure_A: %s\\n\",a->name)");
|
||||||
|
|
||||||
String hlText = "_printf";
|
String hlText = "_printf";
|
||||||
Color hlColor = Color.PINK;
|
Color hlColor = Palette.PINK;
|
||||||
CTokenHighlightMatcher hlMatcher = token -> {
|
CTokenHighlightMatcher hlMatcher = token -> {
|
||||||
if (token.getText().contains(hlText)) {
|
if (token.getText().contains(hlText)) {
|
||||||
return hlColor;
|
return hlColor;
|
||||||
|
@ -1242,7 +1243,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||||
assertAllFieldsSecondaryHighlighted(secondrayToken, secondaryHlColor);
|
assertAllFieldsSecondaryHighlighted(secondrayToken, secondaryHlColor);
|
||||||
|
|
||||||
String hlText = "_printf";
|
String hlText = "_printf";
|
||||||
Color hlColor = Color.PINK;
|
Color hlColor = Palette.PINK;
|
||||||
CTokenHighlightMatcher hlMatcher = token -> {
|
CTokenHighlightMatcher hlMatcher = token -> {
|
||||||
if (token.getText().contains(hlText)) {
|
if (token.getText().contains(hlText)) {
|
||||||
return hlColor;
|
return hlColor;
|
||||||
|
@ -1304,7 +1305,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||||
assertAllFieldsSecondaryHighlighted(secondaryToken, secondaryHlColor);
|
assertAllFieldsSecondaryHighlighted(secondaryToken, secondaryHlColor);
|
||||||
|
|
||||||
String hlText = "_printf";
|
String hlText = "_printf";
|
||||||
Color hlColor = Color.PINK;
|
Color hlColor = Palette.PINK;
|
||||||
CTokenHighlightMatcher hlMatcher = token -> {
|
CTokenHighlightMatcher hlMatcher = token -> {
|
||||||
if (token.getText().contains(hlText)) {
|
if (token.getText().contains(hlText)) {
|
||||||
return hlColor;
|
return hlColor;
|
||||||
|
@ -1352,7 +1353,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||||
decompile("100000d60"); // '_call_structure_A'
|
decompile("100000d60"); // '_call_structure_A'
|
||||||
|
|
||||||
String hlText1 = "_printf";
|
String hlText1 = "_printf";
|
||||||
Color hlColor1 = Color.PINK;
|
Color hlColor1 = Palette.PINK;
|
||||||
CTokenHighlightMatcher hlMatcher1 = token -> {
|
CTokenHighlightMatcher hlMatcher1 = token -> {
|
||||||
if (token.getText().contains(hlText1)) {
|
if (token.getText().contains(hlText1)) {
|
||||||
return hlColor1;
|
return hlColor1;
|
||||||
|
@ -1370,7 +1371,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||||
assertNoFieldsSecondaryHighlighted(hlText1);
|
assertNoFieldsSecondaryHighlighted(hlText1);
|
||||||
|
|
||||||
String hlText2 = "name";
|
String hlText2 = "name";
|
||||||
Color hlColor2 = Color.GREEN;
|
Color hlColor2 = Palette.GREEN;
|
||||||
CTokenHighlightMatcher hlMatcher2 = token -> {
|
CTokenHighlightMatcher hlMatcher2 = token -> {
|
||||||
if (token.getText().contains(hlText2)) {
|
if (token.getText().contains(hlText2)) {
|
||||||
return hlColor2;
|
return hlColor2;
|
||||||
|
@ -1424,7 +1425,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||||
assertPrimaryHighlights("(\"call_structure_A: %s\\n\",a->name)");
|
assertPrimaryHighlights("(\"call_structure_A: %s\\n\",a->name)");
|
||||||
|
|
||||||
String hlText = "_printf";
|
String hlText = "_printf";
|
||||||
Color hlColor1 = Color.PINK;
|
Color hlColor1 = Palette.PINK;
|
||||||
CTokenHighlightMatcher hlMatcher1 = token -> {
|
CTokenHighlightMatcher hlMatcher1 = token -> {
|
||||||
if (token.getText().contains(hlText)) {
|
if (token.getText().contains(hlText)) {
|
||||||
return hlColor1;
|
return hlColor1;
|
||||||
|
@ -1436,7 +1437,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||||
DecompilerHighlighter highlighter1 = hlService.createHighlighter(spyMatcher1);
|
DecompilerHighlighter highlighter1 = hlService.createHighlighter(spyMatcher1);
|
||||||
highlighter1.applyHighlights();
|
highlighter1.applyHighlights();
|
||||||
|
|
||||||
Color hlColor2 = Color.GREEN;
|
Color hlColor2 = Palette.GREEN;
|
||||||
CTokenHighlightMatcher hlMatcher2 = token -> {
|
CTokenHighlightMatcher hlMatcher2 = token -> {
|
||||||
if (token.getText().contains(hlText)) {
|
if (token.getText().contains(hlText)) {
|
||||||
return hlColor2;
|
return hlColor2;
|
||||||
|
@ -1485,7 +1486,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||||
decompile("100000d60"); // '_call_structure_A'
|
decompile("100000d60"); // '_call_structure_A'
|
||||||
|
|
||||||
String hlText = "_printf";
|
String hlText = "_printf";
|
||||||
Color hlColor = Color.PINK;
|
Color hlColor = Palette.PINK;
|
||||||
CTokenHighlightMatcher hlMatcher = token -> {
|
CTokenHighlightMatcher hlMatcher = token -> {
|
||||||
if (token.getText().contains(hlText)) {
|
if (token.getText().contains(hlText)) {
|
||||||
return hlColor;
|
return hlColor;
|
||||||
|
@ -1532,7 +1533,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||||
decompile("100000d60"); // '_call_structure_A'
|
decompile("100000d60"); // '_call_structure_A'
|
||||||
|
|
||||||
String hlText = "_printf";
|
String hlText = "_printf";
|
||||||
Color hlColor = Color.PINK;
|
Color hlColor = Palette.PINK;
|
||||||
CTokenHighlightMatcher hlMatcher = token -> {
|
CTokenHighlightMatcher hlMatcher = token -> {
|
||||||
if (token.getText().contains(hlText)) {
|
if (token.getText().contains(hlText)) {
|
||||||
return hlColor;
|
return hlColor;
|
||||||
|
@ -1590,7 +1591,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||||
decompile("100000d60"); // '_call_structure_A'
|
decompile("100000d60"); // '_call_structure_A'
|
||||||
|
|
||||||
String hlText = "_printf";
|
String hlText = "_printf";
|
||||||
Color hlColor = Color.PINK;
|
Color hlColor = Palette.PINK;
|
||||||
CTokenHighlightMatcher hlMatcher = token -> {
|
CTokenHighlightMatcher hlMatcher = token -> {
|
||||||
if (token.getText().contains(hlText)) {
|
if (token.getText().contains(hlText)) {
|
||||||
return hlColor;
|
return hlColor;
|
||||||
|
@ -1638,7 +1639,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||||
decompile("100000d60"); // '_call_structure_A'
|
decompile("100000d60"); // '_call_structure_A'
|
||||||
|
|
||||||
String hlText = "_printf";
|
String hlText = "_printf";
|
||||||
Color hlColor = Color.PINK;
|
Color hlColor = Palette.PINK;
|
||||||
CTokenHighlightMatcher hlMatcher = token -> {
|
CTokenHighlightMatcher hlMatcher = token -> {
|
||||||
if (token.getText().contains(hlText)) {
|
if (token.getText().contains(hlText)) {
|
||||||
return hlColor;
|
return hlColor;
|
||||||
|
@ -1688,7 +1689,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||||
decompile("100000d60"); // '_call_structure_A'
|
decompile("100000d60"); // '_call_structure_A'
|
||||||
|
|
||||||
String hlText = "_printf";
|
String hlText = "_printf";
|
||||||
Color hlColor = Color.PINK;
|
Color hlColor = Palette.PINK;
|
||||||
CTokenHighlightMatcher hlMatcher = token -> {
|
CTokenHighlightMatcher hlMatcher = token -> {
|
||||||
if (token.getText().contains(hlText)) {
|
if (token.getText().contains(hlText)) {
|
||||||
return hlColor;
|
return hlColor;
|
||||||
|
@ -1736,7 +1737,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||||
decompile("100000d60"); // '_call_structure_A'
|
decompile("100000d60"); // '_call_structure_A'
|
||||||
|
|
||||||
String hlText = "_printf";
|
String hlText = "_printf";
|
||||||
Color hlColor = Color.PINK;
|
Color hlColor = Palette.PINK;
|
||||||
CTokenHighlightMatcher hlMatcher = token -> {
|
CTokenHighlightMatcher hlMatcher = token -> {
|
||||||
if (token.getText().contains(hlText)) {
|
if (token.getText().contains(hlText)) {
|
||||||
return hlColor;
|
return hlColor;
|
||||||
|
|
|
@ -30,6 +30,7 @@ color.palette.orange = orange
|
||||||
color.palette.palegreen = palegreen
|
color.palette.palegreen = palegreen
|
||||||
color.palette.palevioletred = PaleVioletRed
|
color.palette.palevioletred = PaleVioletRed
|
||||||
color.palette.pink = pink
|
color.palette.pink = pink
|
||||||
|
color.palette.purple = purple
|
||||||
color.palette.red = red
|
color.palette.red = red
|
||||||
color.palette.yellow = yellow
|
color.palette.yellow = yellow
|
||||||
color.palette.yellowgreen = yellowgreen
|
color.palette.yellowgreen = yellowgreen
|
||||||
|
|
|
@ -26,20 +26,31 @@ import ghidra.util.Swing;
|
||||||
* Property Editor for Colors. Uses a {@link GhidraColorChooser} as its custom component
|
* Property Editor for Colors. Uses a {@link GhidraColorChooser} as its custom component
|
||||||
*/
|
*/
|
||||||
public class ColorPropertyEditor extends PropertyEditorSupport {
|
public class ColorPropertyEditor extends PropertyEditorSupport {
|
||||||
|
|
||||||
private GhidraColorChooser colorChooser;
|
private GhidraColorChooser colorChooser;
|
||||||
|
|
||||||
private void colorChanged() {
|
private void colorChanged() {
|
||||||
// run later - allows debugging without hanging amazon aws
|
// run later - allows debugging without hanging the UI in some environments
|
||||||
Swing.runLater(() -> setValue(colorChooser.getColor()));
|
Swing.runLater(() -> setValue(colorChooser.getColor()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Component getCustomEditor() {
|
public Component getCustomEditor() {
|
||||||
|
if (colorChooser != null) {
|
||||||
|
return colorChooser;
|
||||||
|
}
|
||||||
|
|
||||||
colorChooser = new GhidraColorChooser();
|
colorChooser = new GhidraColorChooser();
|
||||||
colorChooser.getSelectionModel().addChangeListener(e -> colorChanged());
|
colorChooser.getSelectionModel().addChangeListener(e -> colorChanged());
|
||||||
return colorChooser;
|
return colorChooser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void saveState() {
|
||||||
|
if (colorChooser != null) {
|
||||||
|
colorChooser.addColorToHistory(colorChooser.getColor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportsCustomEditor() {
|
public boolean supportsCustomEditor() {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -44,10 +44,16 @@ public class GhidraColorChooser extends JColorChooser {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addColorToHistory(Color c) {
|
||||||
|
recentColorCache.addColor(c);
|
||||||
|
maybeInstallSettableColorSwatchChooserPanel();
|
||||||
|
}
|
||||||
|
|
||||||
public void setColorHistory(List<Color> colors) {
|
public void setColorHistory(List<Color> colors) {
|
||||||
for (Color color : colors) {
|
for (Color color : colors) {
|
||||||
recentColorCache.addColor(color);
|
recentColorCache.addColor(color);
|
||||||
}
|
}
|
||||||
|
maybeInstallSettableColorSwatchChooserPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Color> getColorHistory() {
|
public List<Color> getColorHistory() {
|
||||||
|
@ -66,8 +72,6 @@ public class GhidraColorChooser extends JColorChooser {
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public Color showDialog(Component centerOverComponent) {
|
public Color showDialog(Component centerOverComponent) {
|
||||||
maybeInstallSettableColorSwatchChooserPanel();
|
|
||||||
|
|
||||||
OKListener okListener = new OKListener();
|
OKListener okListener = new OKListener();
|
||||||
JDialog dialog = createDialog(centerOverComponent, title, true, this, okListener, null);
|
JDialog dialog = createDialog(centerOverComponent, title, true, this, okListener, null);
|
||||||
doSetActiveTab(dialog);
|
doSetActiveTab(dialog);
|
||||||
|
@ -123,7 +127,7 @@ public class GhidraColorChooser extends JColorChooser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void maybeInstallSettableColorSwatchChooserPanel() {
|
private void maybeInstallSettableColorSwatchChooserPanel() {
|
||||||
if (recentColorCache.size() == 0) {
|
if (recentColorCache.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@ import java.awt.Color;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
|
|
||||||
import docking.options.editor.ColorPropertyEditor;
|
import docking.options.editor.ColorPropertyEditor;
|
||||||
import docking.theme.*;
|
|
||||||
import generic.theme.*;
|
import generic.theme.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,4 +44,8 @@ public class ColorValueEditor extends ThemeValueEditor<Color> {
|
||||||
return new ColorValue(id, color);
|
return new ColorValue(id, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void storeState() {
|
||||||
|
((ColorPropertyEditor) editor).saveState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ public abstract class ThemeValueEditor<T> {
|
||||||
protected ThemeValue<T> currentThemeValue;
|
protected ThemeValue<T> currentThemeValue;
|
||||||
private EditorDialog dialog;
|
private EditorDialog dialog;
|
||||||
private String typeName;
|
private String typeName;
|
||||||
private PropertyEditor editor;
|
protected PropertyEditor editor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
@ -67,6 +67,14 @@ public abstract class ThemeValueEditor<T> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the user has pressed ok. This allows sub-classes to store any state for
|
||||||
|
* future dialog invocations.
|
||||||
|
*/
|
||||||
|
protected void storeState() {
|
||||||
|
// for sub-classes
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the actual value (Color, Font, or Icon)
|
* Returns the actual value (Color, Font, or Icon)
|
||||||
* @param id the theme property id for the value
|
* @param id the theme property id for the value
|
||||||
|
@ -136,6 +144,7 @@ public abstract class ThemeValueEditor<T> {
|
||||||
@Override
|
@Override
|
||||||
protected void okCallback() {
|
protected void okCallback() {
|
||||||
close();
|
close();
|
||||||
|
storeState();
|
||||||
dialog = null;
|
dialog = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,5 +154,6 @@ public abstract class ThemeValueEditor<T> {
|
||||||
close();
|
close();
|
||||||
dialog = null;
|
dialog = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,7 @@ public class GThemeDefaults {
|
||||||
public static final GColor MAGENTA = getColor("magenta");
|
public static final GColor MAGENTA = getColor("magenta");
|
||||||
public static final GColor ORANGE = getColor("orange");
|
public static final GColor ORANGE = getColor("orange");
|
||||||
public static final GColor PINK = getColor("pink");
|
public static final GColor PINK = getColor("pink");
|
||||||
|
public static final GColor PURPLE = getColor("purple");
|
||||||
public static final GColor RED = getColor("red");
|
public static final GColor RED = getColor("red");
|
||||||
public static final GColor WHITE = getColor("white");
|
public static final GColor WHITE = getColor("white");
|
||||||
public static final GColor YELLOW = getColor("yellow");
|
public static final GColor YELLOW = getColor("yellow");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue