GT-3481 - Gnu Demangler - Checkpoint 2 - Most docs and tests done;

analyzer test remains
This commit is contained in:
dragonmacher 2020-02-12 18:21:10 -05:00
parent b774ecb2d6
commit b4ce3012d7
55 changed files with 854 additions and 1283 deletions

View file

@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1
li { font-family:times new roman; font-size:14pt; }
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
@ -55,4 +55,10 @@ table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
code { color: black; font-family: courier new; font-size: 14pt; }
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE>
*/
code { color: black; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }

View file

@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1
li { font-family:times new roman; font-size:14pt; }
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
@ -55,4 +55,10 @@ table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
code { color: black; font-family: courier new; font-size: 14pt; }
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE>
*/
code { color: black; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }

View file

@ -82,7 +82,6 @@ ghidra_scripts/world.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END
src/main/help/help/TOC_Source.xml||GHIDRA||||END|
src/main/help/help/shared/arrow.gif||GHIDRA||||END|
src/main/help/help/shared/close16.gif||GHIDRA||||END|
src/main/help/help/shared/helpWarning.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END|
src/main/help/help/shared/menu16.gif||GHIDRA||||END|
src/main/help/help/shared/note-red.png||Oxygen Icons - LGPL 3.0|||renamed from flag-red.png|END|
src/main/help/help/shared/note.png||Oxygen Icons - LGPL 3.0|||renamed from flag-green.png|END|

View file

@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1
li { font-family:times new roman; font-size:14pt; }
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
@ -55,4 +55,10 @@ table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
code { color: black; font-family: courier new; font-size: 14pt; }
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE>
*/
code { color: black; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -5,7 +5,7 @@
<META name="generator" content=
"HTML Tidy for Java (vers. 2009-12-01), see jtidy.sourceforge.net">
<TITLE>Auto-analysis</TITLE>
<TITLE>Auto Analysis</TITLE>
<META http-equiv="Content-Type" content="text/html; charset=windows-1252">
<LINK rel="stylesheet" type="text/css" href="../../shared/Frontpage.css">
</HEAD>
@ -24,7 +24,7 @@
<BLOCKQUOTE>
<OL>
<LI>User Disassembles</LI>
<LI>The user triggers disassembly</LI>
<LI>Function Analyzer - looks at all calls and creates Functions</LI>
@ -34,9 +34,8 @@
<LI>Operand Analyzer - looks at scalar operands for possible address references</LI>
<LI>Data Reference Analyzer - looks at references for possible strings or pointers to
code.<BR>
References to code are disassembled.<BR>
..... Cycle repeats with 2) as additional code is disassembled.</LI>
code. References to code are disassembled.<BR>
.....The cycle repeats with 2) as additional code is disassembled.</LI>
</OL>
<P>One program change might cause several Analyzers to become active, however only one
@ -210,46 +209,46 @@
<H4><B>Options</B></H4>
<UL>
<LI><B>Create strings containing existing strings</B> - if checked, strings will be
<LI><B>Create Strings Containing Existing Strings</B> - if checked, strings will be
created even if they contain existing substrings (existing strings will be cleared). The
string will be created only if existing strings (a) are wholly contained within the
potential string, (b) do not share the same starting address as the potential string, (c)
share the same ending address as the potential string, and (d) are the same datatype as
the potential string to be created).</LI>
<LI><B>Create strings containing references</B> - if checked, strings that contain, but
<LI><B>Create Strings Containing References</B> - if checked, strings that contain, but
do not start with, one or more references will be created.</LI>
<LI><B>Force model reload</B> - if checked, forces the model to be reloaded every time
<LI><B>Force Model Reload</B> - if checked, forces the model to be reloaded every time
the analyzer is run (in cases where the user wishes to see the effect of changing a model
without restarting Ghidra).</LI>
<LI><B>Minimum string length</B> - specifies the smallest number of characters in a
<LI><B>Minimum String Length</B> - specifies the smallest number of characters in a
string for it to be considered a valid string. For this analyzer, null termination
characters are ignored for the purposes of counting characters. Note that smaller numbers
will result in a larger number of false positives. String length must be at least 4.</LI>
<LI><B>Model file</B> - Specifies the model file built using the BuildStringModels class
<LI><B>Model File</B> - Specifies the model file built using the BuildStringModels class
(default is 'StringModel.sng'). Note that the location of the model file does not need to
be specified, as models should always be placed in the
'Ghidra/Features/Base/data/stringngrams' directory.</LI>
<CODE CLASS="path">&lt;GHIDRA_INSTALL_DIR&gt;/Ghidra/Features/Base/data/stringngrams/</CODE> directory.</LI>
<LI><B>Require null termination for string</B> - if checked, only null-terminated strings
<LI><B>Require Null Termination for String</B> - if checked, only null-terminated strings
are created.</LI>
<LI><B>Search only in accessible memory blocks</B> - if checked, searches only in memory
<LI><B>Search Only in Accessible Memory Blocks</B> - if checked, searches only in memory
blocks that have at least one of the Read (R), Write (W), or Execute (X) permissions set
to true. Enabling this option ensures strings are not created in areas such as overlays
or debug sections.</LI>
<LI><B>String end alignment</B> - specifies the byte alignment requirement for the end of
<LI><B>String End Alignment</B> - specifies the byte alignment requirement for the end of
the string. An alignment of 1 means the string can end at any address. Alignments greater
than 1 require that (a) the 'require null termination' option be enabled, and (b) if the
null-terminated string does not end at an aligned boundary, that there exist enough
trailing '0' bytes following the string to allow alignment. If neither (a) nor (b) apply,
end alignment is not enforced.</LI>
<LI><B>String start alignment</B> - specifies the byte alignment requirement for the
<LI><B>String Start Alignment</B> - specifies the byte alignment requirement for the
start of the string. An alignment of 1 means that strings can start at any address. An
alignment of 2 means that strings must start on an even address. An alignment of 4 means
that strings must start on an address that is a multiple of 4.</LI>
@ -344,7 +343,99 @@
name and create a new primary symbol for the demangled name. It will also assign the
appropriate datatypes to the parameters and return type.</P>
<P><U>Started By:</U> New defined functions</P>
<P>
The default demangler options are:
<TABLE BORDER="1">
<TR>
<TH WIDTH="25%">Name</TH>
<TH WIDTH="75%">Description</TH>
</TR>
<TR>
<TD>Apply Function Signatures
</TD>
<TD>
Apply any recovered function signature type information
in addition to the function name
</TD>
</TR>
<TR>
<TD>Only Demangle Known Mangled Symbols
</TD>
<TD>
Only demangle symbols that follow known compiler mangling patterns.
Leaving this option off may cause non-mangled symbols to get demangled.
</TD>
</TR>
</TABLE>
</P>
<P><A name="Gnu_Demangler_Options">
<BR>
<BR>
<B>The GNU Demangler</B> adds the following analysis options:
<BLOCKQUOTE>
<P>
<U><B>Use Deprecated Demangler</B></U> -
By default, GCC symbols will be demangled using the most up-to-date demangler
that Ghidra contains (<B>version 2.33.1</B> as of this writing). Turning this
option on will also invoke the now deprecated previous version of the demangler
(<B>version 2.24</B>) if the preferred demangler cannot demangle a given symbol.
</P>
<P>
Support for older demangling styles was removed in <CODE>c++filt (v2.32)</CODE>.
Specifically, the following formats are no longer supported:
<CODE>Lucid, ARM, HP, and EDG</CODE>. To use these formats, you must enable
usage of the deprecated demangler, which is <B>version 2.24</B>. Further, you
may have to pass the required external demangler options using the Ghidra
option below.
</P>
<P>
<U><B>Use External Demangler Options</B></U> -
This allows users to pass settings to the demangler. As an example, you can enter
in this Ghidra option text field the following text to use the <CODE>rust</CODE>
format: <CODE>-s rust</CODE>. This is not needed for
normal operation. To see a full list of supported options, query each demangler
directly sing the <CODE>--help</CODE> switch.
</P>
<P>
The GNU demanglers can be found at:
<CODE CLASS="path">
&lt;GHIDRA_INSTALL_DIR&gt;/GPL/DemanglerGnu/build/os/&lt;OS&gt;/
</CODE><BR>
</P>
<BLOCKQUOTE>
<P>
The available programs are:
<UL>
<LI><CODE>demangler_gnu_v2_33_1</CODE></LI>
<LI><CODE>demangler_gnu_v2_24</CODE></LI>
</UL>
</P>
<P style="background-color: #FFF0E0;">
<IMG SRC="../../shared/warning.png" />When using an external GNU demangler,
please understand the risks associated with using that version of the
software. The <CODE>demangler_gnu_v2_24</CODE> version of the
demangler is a modified version of GNU's <CODE>c++filt (v2.24)</CODE>. The
original version has known vulnerabilities which have been mitigated in
the version created for Ghidra.
</P>
</BLOCKQUOTE>
<P>
<IMG SRC="../../shared/tip.png" />The Demangler Analyzer is designed to be extensible.
You can extend <CODE>ghidra.app.plugin.core.analysis.AbstractDemanglerAnalyzer</CODE>
to add your demangler analyzer callback. This allows you to precisely control
which demanglers get called, as well as which options are used.
</P>
</BLOCKQUOTE>
<P STYLE="margin-top: 30px;"><U>Started By:</U> New defined functions</P>
</BLOCKQUOTE>
<H3><A name="Auto_Analysis_Option_Byte"></A>Entry Point Analyzer</H3>

View file

@ -72,7 +72,7 @@ public class DemanglerCmd extends BackgroundCommand {
private boolean doDemangle(Demangler demangler, Program program, TaskMonitor monitor) {
try {
demangledObject = demangler.demangle(mangled, options.demangleOnlyKnownPatterns());
demangledObject = demangler.demangle(mangled, options);
}
catch (DemangledException e) {
if (e.isInvalidMangledName()) {

View file

@ -25,7 +25,20 @@ import ghidra.program.model.symbol.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
// TODO docme
/**
* The base demangler analyzer. Implementations of this analyzer will attempt to demangle
* symbols in the binary being analyzed.
*
* <P>Default implementations of this class exist for Microsoft and GNU. These two analyzers will
* only be enabled when the program being analyzed has an architecture that fits each respective
* analyzer. Users can subclass this analyzer to easily control the demangling behavior from
* the analyzer UI.
*
* <P>This analyzer will call each implementation's
* {@link #doDemangle(String, DemanglerOptions, MessageLog)} method for each symbol.
* See the various protected methods of this class for points at which behavior can be overridden.
*
*/
public abstract class AbstractDemanglerAnalyzer extends AbstractAnalyzer {
public AbstractDemanglerAnalyzer(String name, String description) {
@ -35,7 +48,7 @@ public abstract class AbstractDemanglerAnalyzer extends AbstractAnalyzer {
@Override
public boolean canAnalyze(Program program) {
// override this to be enable for a binary containing symbols you wisht to process
// override this to control program-specific enablement
return true;
}
@ -78,13 +91,38 @@ public abstract class AbstractDemanglerAnalyzer extends AbstractAnalyzer {
return true;
}
// TODO callback before demangling begins...
/**
* The implementation-specific demangling callback
*
* @param mangled the mangled string
* @param options the demangler options
* @param log the error log
* @return the demangled object; null if demangling was unsuccessful
* @throws DemangledException if there is a problem demangling or building the result
*/
protected abstract DemangledObject doDemangle(String mangled, DemanglerOptions options,
MessageLog log) throws DemangledException;
/**
* Called before each analysis request to ensure that the current options (which may have
* user-defined input) will work with the current demangler
*
* @param options the current options in use
* @param log the error log into which error message can be written
* @return true if valid
*/
protected boolean validateOptions(DemanglerOptions options, MessageLog log) {
// override to validate custom options for a particular demangler
return true;
}
private boolean skipSymbol(Symbol symbol) {
/**
* True if this analyzer should <b>not</b> attempt to demangle the given symbol
*
* @param symbol the symbol
* @return true to skip the symbol
*/
protected boolean skipSymbol(Symbol symbol) {
if (symbol.getSource() == SourceType.DEFAULT) {
return true;
}
@ -111,9 +149,13 @@ public abstract class AbstractDemanglerAnalyzer extends AbstractAnalyzer {
return false;
}
protected abstract DemangledObject doDemangle(String mangled, DemanglerOptions options,
MessageLog log) throws DemangledException;
/**
* Creates the options for the demangler used by implementations of this analyzer. This will
* be called before each {@link #added(Program, AddressSetView, TaskMonitor, MessageLog)}
* call processes symbols.
*
* @return the options
*/
protected DemanglerOptions getOptions() {
// note: these can be stored in the analyzer subclass and updated when the
// analysis options change
@ -124,6 +166,15 @@ public abstract class AbstractDemanglerAnalyzer extends AbstractAnalyzer {
return options;
}
/**
* This calss's default demangle method. This may be overridden to change how errors are
* handled.
*
* @param mangled the mangled string
* @param options the demangler options
* @param log the error log
* @return the demangled object; null if unsuccessful
*/
protected DemangledObject demangle(String mangled, DemanglerOptions options,
MessageLog log) {
@ -148,6 +199,16 @@ public abstract class AbstractDemanglerAnalyzer extends AbstractAnalyzer {
return demangled;
}
/**
* Applies the given demangled object to the program
*
* @param program the program
* @param address the apply address
* @param demangled the demangled object
* @param options the options used during the apply
* @param log the error log
* @param monitor the task monitor
*/
protected void apply(Program program, Address address, DemangledObject demangled,
DemanglerOptions options, MessageLog log, TaskMonitor monitor) {

View file

@ -60,7 +60,7 @@ public class AnalysisOptionsDialog extends DialogComponentProvider implements
setOkButtonText("Analyze");
okButton.setMnemonic('A');
setOkEnabled(true);
setPreferredSize(800, 400);
setPreferredSize(1000, 600);
setRememberSize(true);
}
@ -75,7 +75,7 @@ public class AnalysisOptionsDialog extends DialogComponentProvider implements
// analysis panel has finished being constructed, so protect against
// that before calling the update method.
if (panel != null) {
panel.updateOptionForAllPrograms(evt.getPropertyName(), (Boolean)evt.getNewValue());
panel.updateOptionForAllPrograms(evt.getPropertyName(), (Boolean) evt.getNewValue());
}
}

View file

@ -16,20 +16,18 @@
package ghidra.app.plugin.core.analysis;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.*;
import org.apache.commons.collections4.CollectionUtils;
import docking.help.Help;
import docking.help.HelpService;
import docking.options.editor.GenericOptionsComponent;
import docking.widgets.OptionDialog;
import docking.widgets.label.GLabel;
@ -39,11 +37,11 @@ import ghidra.app.services.Analyzer;
import ghidra.framework.options.*;
import ghidra.program.model.listing.Program;
import ghidra.util.ColorUtils;
import ghidra.util.HelpLocation;
import ghidra.util.exception.AssertException;
import ghidra.util.layout.VerticalLayout;
class AnalysisPanel extends JPanel implements PropertyChangeListener {
private static final long serialVersionUID = 1L;
public static final String PROTOTYPE = " (Prototype)";
@ -132,12 +130,7 @@ class AnalysisPanel extends JPanel implements PropertyChangeListener {
AutoAnalysisManager manager = AutoAnalysisManager.getAnalysisManager(programs.get(0));
List<String> propertyNames = analysisOptions.getOptionNames();
Collections.sort(propertyNames, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareToIgnoreCase(o2);
}
});
Collections.sort(propertyNames, (o1, o2) -> o1.compareToIgnoreCase(o2));
for (String analyzerName : propertyNames) {
if (analyzerName.indexOf('.') == -1) {
if (analysisOptions.getType(analyzerName) != OptionType.BOOLEAN_TYPE) {
@ -217,26 +210,11 @@ class AnalysisPanel extends JPanel implements PropertyChangeListener {
private JPanel buildButtonPanel() {
JButton selectAllButton = new JButton("Select All");
selectAllButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
selectAll();
}
});
selectAllButton.addActionListener(e -> selectAll());
JButton deselectAllButton = new JButton("Deselect All");
deselectAllButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
deselectAll();
}
});
deselectAllButton.addActionListener(e -> deselectAll());
JButton restoreDefaultsButton = new JButton("Restore Defaults");
restoreDefaultsButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
restoreDefaults();
}
});
restoreDefaultsButton.addActionListener(e -> restoreDefaults());
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
buttonPanel.add(selectAllButton);
buttonPanel.add(deselectAllButton);
@ -343,9 +321,7 @@ class AnalysisPanel extends JPanel implements PropertyChangeListener {
private void buildTable() {
table = new GTable(model);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
table.getSelectionModel().addListSelectionListener(e -> {
if (e.getValueIsAdjusting()) {
return;
}
@ -361,7 +337,6 @@ class AnalysisPanel extends JPanel implements PropertyChangeListener {
}
String analyzerName = analyzerNames.get(selectedRow);
setAnalyzerSelected(analyzerName);
}
});
}
@ -532,6 +507,8 @@ class AnalysisPanel extends JPanel implements PropertyChangeListener {
noOptionsPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
noOptionsPanel.add(new GLabel("No options available."));
HelpService help = Help.getHelpService();
for (Options optionsGroup : optionGroups) {
String analyzerName = optionsGroup.getName();
@ -550,10 +527,18 @@ class AnalysisPanel extends JPanel implements PropertyChangeListener {
List<GenericOptionsComponent> optionComponents = new ArrayList<>();
for (String childOptionName : optionNames) {
EditorState childState =
editorStateFactory.getEditorState(optionsGroup, childOptionName, this);
GenericOptionsComponent comp =
GenericOptionsComponent.createOptionComponent(childState);
HelpLocation helpLoc = analysisOptions
.getHelpLocation(analyzerName + Options.DELIMITER_STRING + childOptionName);
if (helpLoc != null) {
help.registerHelp(comp, helpLoc);
}
optionsContainer.add(comp);
optionComponents.add(comp);
analyzerManagedComponentsMap.get(analyzerName).add(comp);

View file

@ -49,7 +49,7 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer {
"analyzer was disabled or not present.";
private final static String OPTION_FUNCTION_NONRETURN_THRESHOLD =
"Function non-return threshold";
"Function Non-return Threshold";
private static final String OPTION_DESCRIPTION_FUNCTION_NONRETURN_THRESHOLD =
"Enter the number of indications for a given function before it is considered non-returning.";
@ -60,12 +60,12 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer {
private static final String OPTION_NAME_REPAIR_DAMAGE = "Repair Flow Damage";
private static final String OPTION_DESCRIPTION_REPAIR_DAMAGE =
"If checked, repair any flow after a call to found non-returning functions.";
"Signals to repair any flow after a call to found non-returning functions.";
private static final boolean OPTION_DEFAULT_REPAIR_DAMAGE_ENABLED = true;
private static final String OPTION_NAME_CREATE_BOOKMARKS = "Create Analysis Bookmarks";
private static final String OPTION_DESCRIPTION_CREATE_BOOKMARKS =
"If checked, an analysis bookmark will created on each function marked as non-returning.";
"Signals to create an analysis bookmark on each function marked as non-returning.";
private static final boolean OPTION_DEFAULT_CREATE_BOOKMARKS_ENABLED = true;
private boolean repairDamageEnabled = OPTION_DEFAULT_REPAIR_DAMAGE_ENABLED;
@ -164,7 +164,8 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer {
// entries including data flow referenced from instructions will be repaired
ClearFlowAndRepairCmd cmd = new ClearFlowAndRepairCmd(clearInstSet, protectedSet, true, false, true);
ClearFlowAndRepairCmd cmd =
new ClearFlowAndRepairCmd(clearInstSet, protectedSet, true, false, true);
cmd.applyTo(program, monitor);
}
@ -364,7 +365,8 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer {
continue;
}
Instruction oinst = cp.getListing().getInstructionAt(fromAddress);
if ( oinst == null || !checkNonReturningIndicators(oinst, noReturnSet, blockModel)) {
if (oinst == null ||
!checkNonReturningIndicators(oinst, noReturnSet, blockModel)) {
continue;
}
@ -393,7 +395,8 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer {
return hadSuspiciousFunctions;
}
private boolean targetOnlyCallsNoReturn(Program cp, Address target, AddressSet noReturnSet) throws CancelledException {
private boolean targetOnlyCallsNoReturn(Program cp, Address target, AddressSet noReturnSet)
throws CancelledException {
SimpleBlockModel model = new SimpleBlockModel(cp);
@ -402,7 +405,7 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer {
// if hit call, check noReturn, if is stop following
// if hit place that is called, then stop, and return no-good
Stack<Address> todo = new Stack<Address>();
Stack<Address> todo = new Stack<>();
todo.push(target);
AddressSet visited = new AddressSet();
boolean hitNoReturn = false;
@ -491,7 +494,7 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer {
// get the address of the next function after this instruction
Address nextFuncAddr = null;
if (fallThru != null) {
FunctionIterator functions = program.getFunctionManager().getFunctions(fallThru,true);
FunctionIterator functions = program.getFunctionManager().getFunctions(fallThru, true);
if (functions.hasNext()) {
nextFuncAddr = functions.next().getEntryPoint();
}
@ -518,7 +521,8 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer {
/* check for codeblock containing a function */
if (nextFuncAddr != null && block.contains(nextFuncAddr)) {
NoReturnLocations location =
new NoReturnLocations(target, fallThru, "Function defined in instruction after call");
new NoReturnLocations(target, fallThru,
"Function defined in instruction after call");
reasonList.add(location);
return true;
}
@ -598,7 +602,8 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer {
protected void fixCallingFunctionBody(Program cp, Address entry) throws CancelledException {
if (createBookmarksEnabled) {
cp.getBookmarkManager().setBookmark(entry, BookmarkType.ANALYSIS,
cp.getBookmarkManager()
.setBookmark(entry, BookmarkType.ANALYSIS,
"Non-Returning Function", "Non-Returning Function Found");
}
AddressSet fixedSet = new AddressSet();
@ -673,7 +678,7 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer {
// must do an operation, or assign to non-unique
for (PcodeOp pCode : pcode) {
int opcode = pCode.getOpcode();
switch(opcode) {
switch (opcode) {
case PcodeOp.LOAD:
case PcodeOp.STORE:
case PcodeOp.CALLOTHER:
@ -710,7 +715,7 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer {
@Override
public void registerOptions(Options options, Program prog) {
HelpLocation helpLocation = new HelpLocation("AutoAnalysisPlugin",
"Auto_Analysis_Option_Instruction" + getAnalysisType());
"Auto_Analysis_Option_Instructions");
options.registerOption(OPTION_FUNCTION_NONRETURN_THRESHOLD,
OPTION_DEFAULT_EVIDENCE_THRESHOLD, helpLocation,

View file

@ -27,57 +27,23 @@ import ghidra.app.cmd.function.CreateFunctionCmd;
import ghidra.app.cmd.function.CreateThunkFunctionCmd;
import ghidra.app.plugin.core.disassembler.AddressTable;
import ghidra.app.plugin.core.function.FunctionAnalyzer;
import ghidra.app.services.AbstractAnalyzer;
import ghidra.app.services.AnalysisPriority;
import ghidra.app.services.AnalyzerType;
import ghidra.app.services.*;
import ghidra.app.util.PseudoDisassembler;
import ghidra.app.util.importer.MessageLog;
import ghidra.app.util.opinion.PeLoader;
import ghidra.framework.cmd.BackgroundCommand;
import ghidra.framework.cmd.Command;
import ghidra.framework.cmd.CompoundBackgroundCommand;
import ghidra.framework.cmd.*;
import ghidra.framework.options.Options;
import ghidra.program.disassemble.Disassembler;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressIterator;
import ghidra.program.model.address.AddressOutOfBoundsException;
import ghidra.program.model.address.AddressOverflowException;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.address.SegmentedAddressSpace;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.FunctionDefinition;
import ghidra.program.model.data.Pointer;
import ghidra.program.model.data.PointerDataType;
import ghidra.program.model.data.StringDataType;
import ghidra.program.model.data.Undefined;
import ghidra.program.model.address.*;
import ghidra.program.model.data.*;
import ghidra.program.model.lang.RegisterValue;
import ghidra.program.model.listing.BookmarkType;
import ghidra.program.model.listing.CodeUnit;
import ghidra.program.model.listing.CodeUnitIterator;
import ghidra.program.model.listing.Data;
import ghidra.program.model.listing.FlowOverride;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.FunctionManager;
import ghidra.program.model.listing.Instruction;
import ghidra.program.model.listing.Listing;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.DumbMemBufferImpl;
import ghidra.program.model.mem.Memory;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.model.listing.*;
import ghidra.program.model.mem.*;
import ghidra.program.model.pcode.PcodeOp;
import ghidra.program.model.pcode.Varnode;
import ghidra.program.model.reloc.RelocationTable;
import ghidra.program.model.scalar.Scalar;
import ghidra.program.model.symbol.FlowType;
import ghidra.program.model.symbol.OffsetReference;
import ghidra.program.model.symbol.RefType;
import ghidra.program.model.symbol.Reference;
import ghidra.program.model.symbol.ReferenceIterator;
import ghidra.program.model.symbol.SourceType;
import ghidra.program.model.symbol.Symbol;
import ghidra.program.model.symbol.*;
import ghidra.util.HelpLocation;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
@ -328,7 +294,8 @@ public class OperandReferenceAnalyzer extends AbstractAnalyzer {
// New information from the thunked function (noreturn, callfixup, etc...)
// may affect callers to the function, so tell analyzers about it.
// TODO: this should be done by the Auto Thunking mechanisms...
if ((!func.isThunk() && CreateThunkFunctionCmd.isThunk(program, func))) {
if ((!func.isThunk() &&
CreateThunkFunctionCmd.isThunk(program, func))) {
CreateFunctionCmd createFunctionCmd = new CreateFunctionCmd(null,
func.getEntryPoint(), null, SourceType.ANALYSIS, false, true);
if (createFunctionCmd.applyTo(program)) {
@ -533,7 +500,8 @@ public class OperandReferenceAnalyzer extends AbstractAnalyzer {
AddressIterator foundIter = foundCodeBookmarkLocations.getAddresses(true);
while (foundIter.hasNext()) {
Address target = foundIter.next();
program.getBookmarkManager().setBookmark(target, BookmarkType.ANALYSIS,
program.getBookmarkManager()
.setBookmark(target, BookmarkType.ANALYSIS,
"Found Code", "Found code from operand reference");
}
}
@ -622,7 +590,8 @@ public class OperandReferenceAnalyzer extends AbstractAnalyzer {
instr.setFlowOverride(FlowOverride.CALL_RETURN);
// Get rid of any bad disassembly bookmark
AddressSet set = new AddressSet(toAddr);
program.getBookmarkManager().removeBookmarks(set, BookmarkType.ERROR,
program.getBookmarkManager()
.removeBookmarks(set, BookmarkType.ERROR,
Disassembler.ERROR_BOOKMARK_CATEGORY, monitor);
}
@ -808,7 +777,8 @@ public class OperandReferenceAnalyzer extends AbstractAnalyzer {
if (lastGoodTable != null) {
instr.removeOperandReference(opIndex, target);
program.getReferenceManager().addOffsetMemReference(instr.getMinAddress(),
program.getReferenceManager()
.addOffsetMemReference(instr.getMinAddress(),
lastGoodTable.getTopAddress(), -((i + 3) * entryLen), RefType.DATA,
SourceType.ANALYSIS, opIndex);
}
@ -1266,7 +1236,7 @@ public class OperandReferenceAnalyzer extends AbstractAnalyzer {
@Override
public void registerOptions(Options options, Program program) {
HelpLocation helpLocation = new HelpLocation("AutoAnalysisPlugin",
"Auto_Analysis_Option_Instruction" + getAnalysisType());
"Auto_Analysis_Option_Instructions");
if (minimumAddressTableSize == -1) {
calculateMinimumAddressTableSize(program);

View file

@ -64,8 +64,7 @@ public class EntryPointAnalyzer extends AbstractAnalyzer {
@Override
public void registerOptions(Options options, Program program) {
HelpLocation helpLocation =
new HelpLocation("AutoAnalysisPlugin", "Auto_Analysis_Option_Instruction" +
getAnalysisType());
new HelpLocation("AutoAnalysisPlugin", "Auto_Analysis_Option_Instructions");
options.registerOption(OPTION_NAME_RESPECT_EXECUTE_FLAG, respectExecuteFlags, helpLocation,
OPTION_DESCRIPTION_RESPECT_EXECUTE_FLAG);
@ -73,7 +72,8 @@ public class EntryPointAnalyzer extends AbstractAnalyzer {
@Override
public void optionsChanged(Options options, Program program) {
respectExecuteFlags = options.getBoolean(OPTION_NAME_RESPECT_EXECUTE_FLAG, respectExecuteFlags);
respectExecuteFlags =
options.getBoolean(OPTION_NAME_RESPECT_EXECUTE_FLAG, respectExecuteFlags);
}
@Override
@ -83,8 +83,8 @@ public class EntryPointAnalyzer extends AbstractAnalyzer {
monitor.initialize(addressSet.getNumAddresses());
Set<Address> doNowSet = new HashSet<Address>();
Set<Address> doLaterSet = new HashSet<Address>();
Set<Address> doNowSet = new HashSet<>();
Set<Address> doLaterSet = new HashSet<>();
executeSet = program.getMemory().getExecuteSet();
@ -100,8 +100,8 @@ public class EntryPointAnalyzer extends AbstractAnalyzer {
// Someone created them as a placeholder
// Disassemble them
// Remember them so the function body can be fixed later
Set<Address> dummyFunctionSet = new HashSet<Address>();
Set<Address> redoFunctionSet = new HashSet<Address>();
Set<Address> dummyFunctionSet = new HashSet<>();
Set<Address> redoFunctionSet = new HashSet<>();
findDummyFunctions(program, addressSet, dummyFunctionSet, redoFunctionSet);
// disassemble dummy functions now, re-create the function bodies later
@ -157,7 +157,8 @@ public class EntryPointAnalyzer extends AbstractAnalyzer {
EntryPointAnalyzer entryPointAnalyzer = new EntryPointAnalyzer();
entryPointAnalyzer.setPriority(AnalysisPriority.REFERENCE_ANALYSIS.before());
analysisManager.scheduleOneTimeAnalysis(entryPointAnalyzer, toAddressSet(doLaterSet));
} else {
}
else {
// came back in, just do it now
doDisassembly(program, monitor, doLaterSet);
}
@ -195,7 +196,7 @@ public class EntryPointAnalyzer extends AbstractAnalyzer {
private void fixDummyFunctionBodies(Program program, TaskMonitor monitor,
Set<Address> redoFunctionSet) throws CancelledException {
Set<Address> recreateFunctionSet = new HashSet<Address>();
Set<Address> recreateFunctionSet = new HashSet<>();
for (Address entry : redoFunctionSet) {
Function function = program.getFunctionManager().getFunctionAt(entry);
if (function == null) {
@ -219,7 +220,8 @@ public class EntryPointAnalyzer extends AbstractAnalyzer {
if (!foundNonJumpRef) {
// check if we have been thunked
Address[] functionThunkAddresses = function.getFunctionThunkAddresses();
foundNonJumpRef = functionThunkAddresses != null && functionThunkAddresses.length != 0;
foundNonJumpRef =
functionThunkAddresses != null && functionThunkAddresses.length != 0;
}
// if found non-jump ref, or is external
@ -232,7 +234,8 @@ public class EntryPointAnalyzer extends AbstractAnalyzer {
while (referencesTo.hasNext()) {
Reference reference = referencesTo.next();
Function func =
program.getFunctionManager().getFunctionContaining(
program.getFunctionManager()
.getFunctionContaining(
reference.getFromAddress());
if (func != null) {
recreateFunctionSet.add(func.getEntryPoint());
@ -340,7 +343,8 @@ public class EntryPointAnalyzer extends AbstractAnalyzer {
int defaultPointerSize = program.getDefaultPointerSize();
try {
Data data =
program.getListing().createData(entry,
program.getListing()
.createData(entry,
PointerDataType.getPointer(null, defaultPointerSize));
Object value = data.getValue();
if (value instanceof Address) {
@ -401,7 +405,7 @@ public class EntryPointAnalyzer extends AbstractAnalyzer {
private void disassembleCodeMapMarkers(Program program, TaskMonitor monitor) {
AddressSetPropertyMap codeProp = program.getAddressSetPropertyMap("CodeMap");
if (codeProp != null) {
Set<Address> codeSet = new HashSet<Address>();
Set<Address> codeSet = new HashSet<>();
AddressIterator aiter = codeProp.getAddresses();
while (aiter.hasNext()) {
codeSet.add(aiter.next());

View file

@ -41,17 +41,17 @@ public class SharedReturnAnalyzer extends AbstractAnalyzer {
"analyzer was disabled or not present.";
private final static String OPTION_NAME_ASSUME_CONTIGUOUS_FUNCTIONS =
"Assume contiguous functions only";
"Assume Contiguous Functions oOnly";
private final static String OPTION_NAME_CONSIDER_CONDITIONAL_BRANCHES_FUNCTIONS =
"Allow conditional Jumps";
"Allow Conditional Jumps";
private static final String OPTION_DESCRIPTION_ASSUME_CONTIGUOUS_FUNCTIONS =
"Select this check box to assume all function bodies are contiguous " +
"Signals to assume all function bodies are contiguous " +
"and all jumps across other functions should be treated as a call-return.";
private static final String OPTION_DESCRIPTION_CONSIDER_CONDITIONAL_BRANCHES_FUNCTIONS =
"Select this check box to allow conditional jumps to be consider for " +
"Signals to allow conditional jumps to be consider for " +
"shared return jumps to other functions.";
private final static boolean OPTION_DEFAULT_ASSUME_CONTIGUOUS_FUNCTIONS_ENABLED = false;
@ -71,11 +71,7 @@ public class SharedReturnAnalyzer extends AbstractAnalyzer {
setSupportsOneTimeAnalysis();
}
/**
* Called when a function has been added. Looks at address for call
* reference
* @throws CancelledException
*/
@Override
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
throws CancelledException {
@ -86,6 +82,7 @@ public class SharedReturnAnalyzer extends AbstractAnalyzer {
return true;
}
@Override
public boolean getDefaultEnablement(Program program) {
Language language = program.getLanguage();
@ -98,7 +95,7 @@ public class SharedReturnAnalyzer extends AbstractAnalyzer {
@Override
public void registerOptions(Options options, Program program) {
HelpLocation helpLocation = new HelpLocation("AutoAnalysisPlugin",
"Auto_Analysis_Option_Instruction" + getAnalysisType());
"Auto_Analysis_Option_Instructions");
options.registerOption(OPTION_NAME_ASSUME_CONTIGUOUS_FUNCTIONS,
OPTION_DEFAULT_ASSUME_CONTIGUOUS_FUNCTIONS_ENABLED, helpLocation,

View file

@ -38,37 +38,37 @@ public class StringsAnalyzer extends AbstractAnalyzer {
"This analyzer searches for valid ASCII strings and automatically creates them in the binary.";
// Option Names
private static final String MODELFILE_OPTION_NAME = "Model file";
private static final String MODELFILE_OPTION_NAME = "Model File";
private static final String MODELFILE_OPTION_DESCRIPTION =
"Model file built using Ghidra's BuildStringModels class. Any model files for this analyzer " +
"should be located in the Ghidra/Features/Base/data/stringngrams directory and " +
"end in \".sng\".";
private static final String FORCE_MODEL_RELOAD_OPTION_NAME = "Force model reload";
private static final String FORCE_MODEL_RELOAD_OPTION_NAME = "Force Model Reload";
private static final String FORCE_MODEL_RELOAD_OPTION_DESCRIPTION =
"When checked, forces reload of model files every time the analyzer is run. When unchecked, " +
"model files will only be reloaded when Ghidra is restarted or when model file option " +
"name is changed.";
private static final String MINIMUM_STRING_LENGTH_OPTION_NAME = "Minimum string length";
private static final String MINIMUM_STRING_LENGTH_OPTION_NAME = "Minimum String Length";
private static final String MINIMUM_STRING_LENGTH_OPTION_DESCRIPTION =
"The smallest number of characters in a string to be considered a valid string. " +
"(Smaller numbers will give more false positives). String length must be 4 " +
"or greater.";
private static final String REQUIRE_NULL_TERMINATION_OPTION_NAME =
"Require null termination for string";
"Require Null Termination for String";
private static final String REQUIRE_NULL_TERMINATION_OPTION_DESCRIPTION =
"If set to true, requires all strings to end in null.";
private static final String ALLOW_STRING_CREATION_WITH_MIDDLE_REF_NAME =
"Create strings containing references";
"Create Strings Containing References";
private static final String ALLOW_STRING_CREATION_WITH_MIDDLE_REF_DESCRIPTION =
"If checked, allows a string that contains, but does not start with, one or more references" +
" to be created.";
private static final String ALLOW_STRING_CREATION_WITH_EXISTING_SUBSTR_NAME =
"Create strings containing existing strings";
"Create Strings Containing Existing Strings";
private static final String ALLOW_STRING_CREATION_WITH_EXISTING_SUBSTR_DESCRIPTION =
"If checked, allows a string to be created even if it contains existing strings (existing " +
"strings will be cleared). The string will be created only if existing strings (a) " +
@ -76,7 +76,7 @@ public class StringsAnalyzer extends AbstractAnalyzer {
"address as the potential string, (c) share the same ending address as the potential " +
"string, and (d) are the same datatype as the potential string.";
private static final String START_ALIGNMENT_OPTION_NAME = "String start alignment";
private static final String START_ALIGNMENT_OPTION_NAME = "String Start Alignment";
private static final String START_ALIGNMENT_OPTION_DESCRIPTION =
"Specifies an alignment requirement for the start of the string. An alignment of 1 " +
"means the string can start at any address. An alignment of 2 means the string " +
@ -92,7 +92,7 @@ public class StringsAnalyzer extends AbstractAnalyzer {
"alignment is not enforced.";
private static final String SEARCH_ONLY_ACCESSIBLE_MEM_BLOCKS_NAME =
"Search only in accessible memory blocks";
"Search Only in Accessible Memory Blocks";
private static final String SEARCH_ONLY_ACCESSIBLE_MEM_BLOCKS_DESCRIPTION =
"If checked, this " +
"analyzer only searches in memory blocks that have at least one of the Read (R), Write " +

View file

@ -26,15 +26,48 @@ public interface Demangler extends ExtensionPoint {
public boolean canDemangle(Program program);
// TODO deprecate
@Deprecated
/**
* Deprecated. Use {@link #demangle(String)} or
* {@link #demangle(String, DemanglerOptions)}.
*
* @param mangled the mangled string
* @param demangleOnlyKnownPatterns true signals to avoid demangling strings that do
* not fit known demangled patterns for this demangler
* @return the result
* @throws DemangledException if the string cannot be demangled
* @deprecated see above
*/
@Deprecated(since = "9.2", forRemoval = true)
public DemangledObject demangle(String mangled, boolean demangleOnlyKnownPatterns)
throws DemangledException;
// TODO docme
/**
* Attempts to demangle the given string using the default options
* ({@link #createDefaultOptions()}
*
* @param mangled the mangled string
* @return the result
* @throws DemangledException if the string cannot be demangled
*/
public default DemangledObject demangle(String mangled) throws DemangledException {
return demangle(mangled, createDefaultOptions());
}
/**
* Attempts to demangle the given string using the given options
*
* @param mangled the mangled string
* @param options the options
* @return the result
* @throws DemangledException if the string cannot be demangled
*/
public DemangledObject demangle(String mangled, DemanglerOptions options)
throws DemangledException;
/**
* Creates default options for this particular demangler
* @return the options
*/
public default DemanglerOptions createDefaultOptions() {
return new DemanglerOptions();
}

View file

@ -47,9 +47,7 @@ public class DemanglerUtil {
List<Demangler> demanglers = getDemanglers();
for (Demangler demangler : demanglers) {
try {
// not sure if we should be doing all symbols, but this is what it used to do
boolean onlyKnownTypes = false;
DemangledObject demangledObject = demangler.demangle(mangled, onlyKnownTypes);
DemangledObject demangledObject = demangler.demangle(mangled);
if (demangledObject != null) {
return demangledObject;
}
@ -82,9 +80,7 @@ public class DemanglerUtil {
continue;
}
// not sure if we should be doing all symbols, but this is what it used to do
boolean onlyKnownTypes = false;
DemangledObject demangledObject = demangler.demangle(mangled, onlyKnownTypes);
DemangledObject demangledObject = demangler.demangle(mangled);
if (demangledObject != null) {
return demangledObject;
}

View file

@ -1,72 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//@category CodeAnalysis
import ghidra.app.analyzers.LibHashDB;
import ghidra.app.script.GhidraScript;
import ghidra.framework.Application;
import ghidra.xml.NonThreadedXmlPullParserImpl;
import ghidra.xml.XmlPullParser;
import java.io.*;
import org.xml.sax.*;
public class BuildFuncDB extends GhidraScript {
@Override
protected void run() throws Exception {
//If the file is already there, it adds more function records to it. If not, it creates and populates the file.
File dbFile =
Application.getModuleDataSubDirectory("BytePatterns", "lib/db.xml").getFile(true);
LibHashDB db = new LibHashDB();
if (dbFile.exists()) {
db.restoreXml(getParser(dbFile));
}
LibHashDB dbCurrent = new LibHashDB(this.currentProgram);
db.mergeWith(dbCurrent);
FileWriter fwrite = new FileWriter(dbFile);
db.saveXml(fwrite);
fwrite.close();
return;
}
private static XmlPullParser getParser(File xmlfile) throws SAXException, IOException {
ErrorHandler handler = new ErrorHandler() {
@Override
public void warning(SAXParseException exception) throws SAXException {
throw exception;
}
@Override
public void error(SAXParseException exception) throws SAXException {
throw exception;
}
@Override
public void fatalError(SAXParseException exception) throws SAXException {
throw exception;
}
};
XmlPullParser parser;
parser = new NonThreadedXmlPullParserImpl(xmlfile, handler, false);
return parser;
}
}

View file

@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1
li { font-family:times new roman; font-size:14pt; }
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
@ -55,4 +55,10 @@ table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
code { color: black; font-family: courier new; font-size: 14pt; }
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE>
*/
code { color: black; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }

View file

@ -1,111 +0,0 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.analyzers;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.Program;
import ghidra.util.exception.CancelledException;
import ghidra.xml.XmlPullParser;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.TreeSet;
public class LibHashDB {
private TreeSet<LibraryRecord> libraries;
//Empty Constructor
public LibHashDB() {
this.libraries = new TreeSet<LibraryRecord>();
}
//Construct a DB from the current program, with a record for every function.
public LibHashDB(Program prgm) throws CancelledException {
this.libraries = new TreeSet<LibraryRecord>();
this.libraries.add(new LibraryRecord(prgm));
}
//Merge another DB into this one.
public void mergeWith(LibHashDB toMergeIn) {
this.libraries.addAll(toMergeIn.libraries);
}
//Add a library to the database.
public void addLibrary(LibraryRecord libRec) {
this.libraries.add(libRec);
return;
}
public TreeSet<FuncRecord> getRecords() {
TreeSet<FuncRecord> results = new TreeSet<FuncRecord>();
for (LibraryRecord lib : this.libraries) {
results.addAll(lib.getRecords());
}
return results;
}
//Find an entry of the database based on actual underlying function.
public ArrayList<FuncRecord> query(Function func) throws CancelledException {
FuncRecord queryHash = new FuncRecord(func);
ArrayList<FuncRecord> result = this.query(queryHash.hashValue); //Use the hash query method instead.
for (FuncRecord entry : result) {
if (entry.func == func) {
ArrayList<FuncRecord> newResult = new ArrayList<FuncRecord>();
newResult.add(entry);
return newResult;
}
}
return result; //Return all matches.
}
//Find an entry of the database based on hash. Returns all records with that hash.
public ArrayList<FuncRecord> query(Long hash) {
ArrayList<FuncRecord> result = new ArrayList<FuncRecord>(); //Set up the result.
FuncRecord temp = new FuncRecord();
temp.hashValue = hash;
for (LibraryRecord libRec : this.libraries) { //Search each library for a record matching the hash.
result.addAll(libRec.query(hash));
}
return result;
}
//DB is made up of libraries. To get a DB from a file/parser, look for the "funcDB" tag, and then pass the buck to the LibraryRecord class.
public void restoreXml(XmlPullParser parser) {
parser.start("funcDB"); //The XML tag for an entire DB.
while (parser.peek().isStart()) {
LibraryRecord libRec = new LibraryRecord();
libRec.restoreXml(parser); //Pass the buck.
this.addLibrary(libRec); //DB is a collection of library records.
}
parser.end();
return;
}
//Save DB to an XML file.
public void saveXml(Writer fwrite) throws IOException {
StringBuffer buf = new StringBuffer();
buf.append("<funcDB>\n"); //The XML tag for the entire DB.
fwrite.append(buf.toString());
for (LibraryRecord libRec : this.libraries) {
libRec.saveXml(fwrite); //Write out each library in XML.
}
fwrite.append("</funcDB>\n"); //Finish up.
return;
}
}

View file

@ -1,271 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.analyzers;
import java.io.*;
import java.util.*;
import org.xml.sax.*;
import ghidra.app.cmd.label.*;
import ghidra.app.services.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.framework.Application;
import ghidra.framework.cmd.Command;
import ghidra.framework.options.Options;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.*;
import ghidra.util.Msg;
import ghidra.util.task.TaskMonitor;
import ghidra.xml.NonThreadedXmlPullParserImpl;
import ghidra.xml.XmlPullParser;
public class LibraryHashAnalyzer extends AbstractAnalyzer {
private static final String NAME = "Library Hash Identification";
private static final String DESCRIPTION =
"Analyzes program for statically linked library functions (e.g., printf, scanf, etc.).";
private final static String OPTION_NAME_MEM_SEARCH = "Analyze undefined bytes";
private final static String OPTION_NAME_DISASSEMBLE = "Disassemble matches in undefined bytes";
private static final String OPTION_DESCRIPTION_MEM_SEARCH =
"Search for known library signatures in undefined bytes.";
private static final String OPTION_DESCRIPTION_DISASSEMBLE =
"Disassemble any library functions found while searching undefined bytes.";
private final static boolean OPTION_DEFAULT_MEM_SEARCH = true;
private final static boolean OPTION_DEFAULT_DISASSEMBLE = true;
private boolean memSearchOption = OPTION_DEFAULT_MEM_SEARCH;
private boolean disassembleOption = OPTION_DEFAULT_DISASSEMBLE;
public LibraryHashAnalyzer() {
super(NAME, DESCRIPTION, AnalyzerType.BYTE_ANALYZER);
setPrototype();
setPriority(AnalysisPriority.DATA_TYPE_PROPOGATION.before());
setSupportsOneTimeAnalysis();
}
@Override
public boolean canAnalyze(Program program) {
// TODO: for now, this can't analyze anything!
// WARNING: this will cause this analyzer not to show up for anything!
return false;
}
@Override
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log) {
this.identifyLibraryFunctions(set, program, monitor);
return true;
}
@Override
public void registerOptions(Options options, Program program) {
options.registerOption(OPTION_NAME_MEM_SEARCH, memSearchOption, null,
OPTION_DESCRIPTION_MEM_SEARCH);
options.registerOption(OPTION_NAME_DISASSEMBLE, disassembleOption, null,
OPTION_DESCRIPTION_DISASSEMBLE);
}
/**
* @see ghidra.app.services.Analyzer#optionsChanged(ghidra.framework.options.Options, Program)
*/
@Override
public void optionsChanged(Options options, Program program) {
memSearchOption = options.getBoolean(OPTION_NAME_MEM_SEARCH, memSearchOption);
disassembleOption = options.getBoolean(OPTION_NAME_DISASSEMBLE, disassembleOption);
}
private void identifyLibraryFunctions(AddressSetView set, Program p, TaskMonitor monitor) {
//Get the library from the xml database file.
File libraryFile;
try {
libraryFile = Application.getModuleDataFile("lib/db.xml").getFile(true);
}
catch (FileNotFoundException e1) {
Msg.error(this, "Cannot find db.xml file--not hashing functions", e1);
return;
}
LibHashDB db = new LibHashDB();
//Handler is for the XML parser.
ErrorHandler handler = new ErrorHandler() {
@Override
public void warning(SAXParseException exception) throws SAXException {
throw exception;
}
@Override
public void error(SAXParseException exception) throws SAXException {
throw exception;
}
@Override
public void fatalError(SAXParseException exception) throws SAXException {
throw exception;
}
};
try {
InputStream hstream = new FileInputStream(libraryFile);
//Create the parser.
XmlPullParser parser = new NonThreadedXmlPullParserImpl(hstream,
"Function Database parser", handler, false);
hstream.close();
//Create the database.
db.restoreXml(parser);
HashMap<FuncRecord, FuncRecord> pinning = new HashMap<FuncRecord, FuncRecord>(); //Matching between query and library functions.
LibHashDB qdb = new LibHashDB(p);
FunctionIterator funcIter = p.getListing().getFunctions(true);
//If a signature is unique in the libraries and in the query, we may as well match them.
while (funcIter.hasNext()) {
Function func = funcIter.next();
ArrayList<FuncRecord> libResponse = db.query(func);
if (libResponse.size() != 1) { //Check uniqueness in libraries.
continue;
}
FuncRecord libVal = libResponse.get(0);
ArrayList<FuncRecord> queResponse = qdb.query(libVal.hashValue);
if (queResponse.size() != 1) { //Check uniqueness in query.
continue;
}
FuncRecord queVal = queResponse.get(0);
pinning.put(queVal, libVal);
}
PriorityQueue<FuncRecord> q = new PriorityQueue<FuncRecord>(pinning.keySet());
HashSet<FuncRecord> seen = new HashSet<FuncRecord>();
while (q.size() > 0) {
FuncRecord current = q.remove(); //A query record which is already matched.
seen.add(current);
Iterator<FuncRecord> qit = current.children.iterator();
FuncRecord partner = pinning.get(current);
Iterator<FuncRecord> lit = partner.children.iterator();
while (qit.hasNext()) {
FuncRecord qKid = qit.next(); //Child on the query side.
if (!lit.hasNext()) {
break;
}
FuncRecord lKid = lit.next(); //Child to match on the library side.
//Should we add a second seen set for the lKids?
if (qKid.hashValue != lKid.hashValue || seen.contains(qKid)) {
continue;
}
//Match 'em and put 'em in the queue.
//This little check is unnecessary, except that calls can be incorrectly disassembled.
if (qKid.children.size() != lKid.children.size()) {
continue;
}
pinning.put(qKid, lKid);
this.addSymbol(p, qKid.func.getEntryPoint(), lKid.funcName, false);
q.add(qKid);
}
}
/*
File outFile = new File(dataDir, "testy.txt");
File outFile2 = new File(dataDir, "testy2.txt");
FileWriter writer = new FileWriter(outFile);
FileWriter writer2 = new FileWriter(outFile2);
writer.write("Matched: " + pinning.size() + "\n");
writer2.write("Unmatched:\n");
for(FuncRecord key : qdb.getRecords()){
if(pinning.containsKey(key)){
writer.write(key.toString() + "\n");
}
else{
writer2.write(key.toString() + "\n");
}
}
writer.close();
writer2.close();
*/
}
catch (Exception e) {
e.printStackTrace();
}
return;
}
@Override
public void analysisEnded(Program program) {
// don't care
}
private void addSymbol(Program program, Address addr, String name, boolean localscope) {
SymbolTable st = program.getSymbolTable();
Symbol existSym = st.getPrimarySymbol(addr);
Command cmd = null;
if (existSym == null) { //Symbol didn't exist
cmd = new AddLabelCmd(addr, name, localscope, SourceType.IMPORTED); //So we prepare to add it.
}
else if (!existSym.getName().equals(name)) { //There is a symbol there with the wrong name.
if (existSym.getSource() == SourceType.DEFAULT || //It's got a non-smart name.
(existSym.getSource() == SourceType.ANALYSIS &&
existSym.getSymbolType().equals(SymbolType.FUNCTION))) {
cmd = new RenameLabelCmd(addr, existSym.getName(), name, //Prepare to rename it.
existSym.getParentNamespace(), SourceType.IMPORTED);
}
else {
cmd = new AddLabelCmd(addr, name, localscope, SourceType.IMPORTED); //Our name is better?
}
}
if (cmd != null && cmd.applyTo(program)) { //Apply the name, make sure it worked.
Msg.debug(this, "Created symbol for library function " + name + " at address " + addr);
Namespace space = st.getNamespace(addr);
if (!localscope) {
space = null;
}
cmd = new SetLabelPrimaryCmd(addr, name, space);
cmd.applyTo(program);
cmd = new DemanglerCmd(addr, name);
if (cmd.applyTo(program)) {
Msg.debug(this, "Demangled library function " + name);
}
//resolved.add(addr);
}
/*
program.getBookmarkManager().setBookmark(addr, "Analysis",
LibraryIdentificationConstants.LIB_BOOKMARK_CATEGORY, "Library function");
if (disassembleOption) {
PseudoDisassembler pdis = new PseudoDisassembler(program);
// make sure it is a disassembly
if (pdis.isValidSubroutine(addr, false)) {
disassembleSet.addRange(addr, addr);
}
}
*/
return;
}
}

View file

@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1
li { font-family:times new roman; font-size:14pt; }
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
@ -55,4 +55,10 @@ table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
code { color: black; font-family: courier new; font-size: 14pt; }
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE>
*/
code { color: black; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }

View file

@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1
li { font-family:times new roman; font-size:14pt; }
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
@ -55,4 +55,10 @@ table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
code { color: black; font-family: courier new; font-size: 14pt; }
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE>
*/
code { color: black; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }

View file

@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1
li { font-family:times new roman; font-size:14pt; }
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
@ -55,4 +55,10 @@ table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
code { color: black; font-family: courier new; font-size: 14pt; }
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE>
*/
code { color: black; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }

View file

@ -110,7 +110,7 @@ public class DecompilerFunctionAnalyzer extends AbstractAnalyzer {
@Override
public void registerOptions(Options options, Program program) {
HelpLocation helpLocation = new HelpLocation("AutoAnalysisPlugin",
"Auto_Analysis_Option_Instruction" + getAnalysisType());
"Decompiler_Parameter_ID_Analyzer");
options.registerOption(OPTION_NAME_CLEAR_LEVEL, SourceType.ANALYSIS, helpLocation,
OPTION_DESCRIPTION_CLEAR_LEVEL);

View file

@ -24,12 +24,12 @@
*/
body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px;} /* some padding to improve readability */
body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 10px; } /* some padding to improve readability */
li { font-family:times new roman; font-size:14pt; }
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; font-family:times new roman; font-size:14pt; font-style:italic; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
P tag code. Most of the help files nest P tags inside of blockquote tags (the was the
@ -40,12 +40,25 @@ h4 { margin-left: 10px; font-family:times new roman; font-size:14pt; font-style:
*/
p { margin-left: 40px; font-family:times new roman; font-size:14pt; }
blockquote p { margin-left: 10px; }
p.providedbyplugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px }
p.ProvidedByPlugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px }
p.relatedtopic { color:#800080; margin-left: 10px; font-size:14pt; }
p.RelatedTopic { color:#800080; margin-left: 10px; font-size:14pt; }
/*
We wish for a tables to have space between it and the preceding element, so that text
is not too close to the top of the table. Also, nest the table a bit so that it is clear
the table relates to the preceding text.
*/
table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
code { color: black; font-family: courier new; font-size: 14pt; }
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE>
*/
code { color: black; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }

View file

@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1
li { font-family:times new roman; font-size:14pt; }
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
@ -55,4 +55,10 @@ table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
code { color: black; font-family: courier new; font-size: 14pt; }
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE>
*/
code { color: black; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }

View file

@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1
li { font-family:times new roman; font-size:14pt; }
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
@ -55,4 +55,10 @@ table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
code { color: black; font-family: courier new; font-size: 14pt; }
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE>
*/
code { color: black; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }

View file

@ -19,17 +19,10 @@
//
//@category Examples.Demangler
import java.io.*;
import ghidra.app.script.GhidraScript;
import ghidra.app.util.demangler.DemangledObject;
import ghidra.app.util.demangler.DemanglerOptions;
import ghidra.app.util.demangler.gnu.GnuDemanglerNativeProcess;
import ghidra.app.util.demangler.gnu.GnuDemanglerParser;
import ghidra.app.util.opinion.ElfLoader;
import ghidra.app.util.opinion.MachoLoader;
import ghidra.framework.*;
import ghidra.program.model.lang.CompilerSpec;
import ghidra.app.util.demangler.gnu.GnuDemangler;
import ghidra.app.util.demangler.gnu.GnuDemanglerOptions;
import ghidra.program.model.symbol.Symbol;
public class DemangleElfWithOptionScript extends GhidraScript {
@ -37,8 +30,9 @@ public class DemangleElfWithOptionScript extends GhidraScript {
@Override
protected void run() throws Exception {
GnuDemangler demangler = new GnuDemangler();
if (!demangler.canDemangle(currentProgram)) {
String executableFormat = currentProgram.getExecutableFormat();
if (!canDemangle(executableFormat)) {
println("Cannot use the elf demangling options for executable format: " +
executableFormat);
return;
@ -55,81 +49,22 @@ public class DemangleElfWithOptionScript extends GhidraScript {
String mangled = symbol.getName();
Process process = createProcess(executableFormat);
GnuDemanglerOptions options = new GnuDemanglerOptions();
options.setDoDisassembly(false);
options.setDemanglerApplicationArguments("-s auto");
InputStream in = process.getInputStream();
OutputStream out = process.getOutputStream();
/*
// for older formats use the deprecated demangler
options.setDemanglerName(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
options.setDemanglerApplicationArguments("-s arm");
*/
BufferedReader input = new BufferedReader(new InputStreamReader(in));
PrintWriter output = new PrintWriter(out);
output.println(mangled);
output.flush();
String demangled = input.readLine();
println("demangled: " + demangled);
GnuDemanglerParser parser = new GnuDemanglerParser(null);
DemangledObject demangledObject = parser.parse(mangled, demangled);
DemangledObject demangledObject = demangler.demangle(mangled, options);
if (demangledObject == null) {
println("Could not demangle: " + mangled);
return;
}
// TODO change to GnuDemanglerOptions
DemanglerOptions options = new DemanglerOptions();
options.setDoDisassembly(false);
options.setApplySignature(true);
options.setDemangleOnlyKnownPatterns(true);
if (!demangledObject.applyTo(currentProgram, currentAddress, options, monitor)) {
println("Failed to apply demangled data for " + mangled);
}
println("Succesfully demangled " + mangled + " to " + demangled);
}
private boolean canDemangle(String executableFormat) {
//check if language is GCC - this is not altogether correct !
// Objective-C and other non-GCC based symbols may be handled improperly
if (isELF(executableFormat) || isMacho(executableFormat)) {
return true;
}
CompilerSpec compilerSpec = currentProgram.getCompilerSpec();
if (compilerSpec.getCompilerSpecID()
.getIdAsString()
.toLowerCase()
.indexOf("windows") == -1) {
return true;
}
return false;
}
private boolean isELF(String executableFormat) {
return executableFormat != null && executableFormat.indexOf(ElfLoader.ELF_NAME) != -1;
}
private boolean isMacho(String executableFormat) {
return executableFormat != null && executableFormat.indexOf(MachoLoader.MACH_O_NAME) != -1;
}
/// TODO this is here because we did not support program arguments. replace this code
private Process createProcess(String executableName) throws Exception {
String demanglerName = GnuDemanglerNativeProcess.DEMANGLER_GNU;
OperatingSystem OS = Platform.CURRENT_PLATFORM.getOperatingSystem();
String demanglerExe =
(OS == OperatingSystem.WINDOWS) ? demanglerName + ".exe" : demanglerName;
File commandPath = Application.getOSFile("GnuDemangler", demanglerExe);
//
// This is where special options are to be passed. Put your own here as necessary.
//
String[] command = new String[] { commandPath.getAbsolutePath(), "-s", "arm" };
Process process = Runtime.getRuntime().exec(command);
return process;
println("Succesfully demangled " + mangled + " to " + demangledObject);
}
}

View file

@ -95,8 +95,9 @@ public class VxWorksSymTab_5_4 extends GhidraScript {
Address vxSymTbl = vxNumSymEntriesAddr.subtract(vxNumSymEntries * SYM_ENTRY_SIZE);
for (int i = 0; i < vxNumSymEntries; i++) {
if (monitor.isCancelled())
if (monitor.isCancelled()) {
return; // check for cancel button
}
println("i=" + i); // visual counter
// Extract symbol table entry values
@ -112,15 +113,19 @@ public class VxWorksSymTab_5_4 extends GhidraScript {
Address a;
String symName;
for (a = symNameAddr; mem.getByte(a) != 0; a = a.add(1)) {
if (getDataAt(a) != null)
if (getDataAt(a) != null) {
removeDataAt(a);
if (getInstructionAt(a) != null)
}
if (getInstructionAt(a) != null) {
removeInstructionAt(a);
}
if (getDataAt(a) != null)
}
if (getDataAt(a) != null) {
removeDataAt(a);
if (getInstructionAt(a) != null)
}
if (getInstructionAt(a) != null) {
removeInstructionAt(a);
}
// Turn *symNameAddr into a string and store it in symName
try {
@ -137,7 +142,7 @@ public class VxWorksSymTab_5_4 extends GhidraScript {
String symDemangledName = null;
try {
// if successful, symDemangledName will be non-NULL
symDemangledName = demangler.demangle(symName, true).getSignature(false);
symDemangledName = demangler.demangle(symName).getSignature(false);
}
catch (DemangledException e) {
// if symName wasn't a mangled name, silently continue

View file

@ -138,7 +138,7 @@ public class VxWorksSymTab_6_1 extends GhidraScript {
String symDemangledName = null;
try {
// if successful, symDemangledName will be non-NULL
symDemangledName = demangler.demangle(symName, true).getSignature(false);
symDemangledName = demangler.demangle(symName).getSignature(false);
}
catch (DemangledException e) {
// if symName wasn't a mangled name, silently continue

View file

@ -50,13 +50,7 @@ import ghidra.app.util.demangler.DemangledException;
import ghidra.app.util.demangler.gnu.GnuDemangler;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.data.ArrayDataType;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.DataTypeComponent;
import ghidra.program.model.data.DataTypeConflictHandler;
import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.data.PointerDataType;
import ghidra.program.model.data.StructureDataType;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Data;
import ghidra.program.model.listing.Instruction;
import ghidra.program.model.mem.MemoryBlock;
@ -143,7 +137,8 @@ public class VxWorksSymTab_Finder extends GhidraScript {
// Add SYMBOL data type to Program DataTypeManager
// (if data type already exists, replace it)
public void createGhidraType() {
currentProgram.getDataTypeManager().addDataType(dt,
currentProgram.getDataTypeManager()
.addDataType(dt,
DataTypeConflictHandler.REPLACE_HANDLER);
}
}
@ -351,8 +346,7 @@ public class VxWorksSymTab_Finder extends GhidraScript {
}
}
if (_byte == 0x00)
{
if (_byte == 0x00) {
return true; // Scan stopped at null.
}
return false; // Scan stopped at invalid char.
@ -657,7 +651,8 @@ public class VxWorksSymTab_Finder extends GhidraScript {
if (demangled != null) {
new DemanglerCmd(addr, mangled).applyTo(currentProgram, monitor);
currentProgram.getSymbolTable().removeSymbolSpecial(
currentProgram.getSymbolTable()
.removeSymbolSpecial(
getSymbol(mangled, currentProgram.getGlobalNamespace()));
}
@ -772,7 +767,7 @@ public class VxWorksSymTab_Finder extends GhidraScript {
// Demangle symName
String symDemangledName = null;
try {
symDemangledName = demangler.demangle(symName, true).getSignature(false);
symDemangledName = demangler.demangle(symName).getSignature(false);
}
catch (DemangledException e) { // report demangling error
if (!e.isInvalidMangledName()) {

View file

@ -22,11 +22,13 @@ import org.apache.commons.lang3.StringUtils;
import ghidra.app.util.demangler.*;
import ghidra.app.util.demangler.gnu.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.framework.options.*;
import ghidra.framework.options.Options;
import ghidra.program.model.listing.Program;
import ghidra.util.HelpLocation;
import ghidra.util.Msg;
/**
* A version of the demangler analyzer to handle GNU GCC symbols
*/
public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
private static final String NAME = "Demangler GNU";
@ -35,7 +37,7 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
"the name and apply datatypes to parameters.";
private static final String OPTION_NAME_DEMANGLE_USE_KNOWN_PATTERNS =
"Only Demangle Known Mangled Symbols";
"Demangle Only Known Mangled Symbols";
private static final String OPTION_DESCRIPTION_USE_KNOWN_PATTERNS =
"Only demangle symbols that follow known compiler mangling patterns. " +
"Leaving this option off may cause non-mangled symbols to get demangled.";
@ -44,14 +46,20 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
private static final String OPTION_DESCRIPTION_APPLY_SIGNATURE =
"Apply any recovered function signature, in addition to the function name";
// note: we use 'Z' as a trick to be below the other options
private static final String OPTION_NAME_GNU_DEMANGLER = "Z GNU Demangler";
static final String OPTION_NAME_USE_DEPRECATED_DEMANGLER = "Use Deprecated Demangler";
private static final String OPTION_DESCRIPTION_DEPRECATED_DEMANGLER =
"Signals to use the deprecated demangler when the modern demangler cannot demangle a " +
"given string";
private static final String OPTION_NAME_DEMANGLER_PARAMETERS =
"Use External Demangler Options";
private static final String OPTION_DESCRIPTION_DEMANGLER_PARAMETERS =
"Signals to use pass the given parameters to the demangler program";
private boolean doSignatureEnabled = true;
private boolean demangleOnlyKnownPatterns = false;
private GnuDemanglerOptionsPropertyEditor gnuOptionsEditor =
new GnuDemanglerOptionsPropertyEditor();
private GnuDemanglerWrappedOption gnuWrappedOptions;
private boolean useDeprecatedDemangler = false;
private String demanglerParameters = "";
private GnuDemangler demangler = new GnuDemangler();
@ -67,28 +75,20 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
@Override
public void registerOptions(Options options, Program program) {
options.registerOption(OPTION_NAME_APPLY_SIGNATURE, doSignatureEnabled, null,
OPTION_DESCRIPTION_APPLY_SIGNATURE);
options.registerOption(OPTION_NAME_DEMANGLE_USE_KNOWN_PATTERNS, false, null,
OPTION_DESCRIPTION_USE_KNOWN_PATTERNS);
options.registerOptionsEditor(null);
HelpLocation help = new HelpLocation("AutoAnalysisPlugin", "Demangler_Analyzer");
options.registerOption(OPTION_NAME_GNU_DEMANGLER, OptionType.CUSTOM_TYPE,
new GnuDemanglerWrappedOption(), help, "Advanced GNU demangler options",
gnuOptionsEditor);
options.registerOption(OPTION_NAME_APPLY_SIGNATURE, doSignatureEnabled, help,
OPTION_DESCRIPTION_APPLY_SIGNATURE);
CustomOption customOption = options.getCustomOption(OPTION_NAME_GNU_DEMANGLER,
new GnuDemanglerWrappedOption());
if (!(customOption instanceof GnuDemanglerWrappedOption)) {
customOption = new GnuDemanglerWrappedOption();
Msg.debug(this, "Unexpected custom option type for GNU Demangler: " +
customOption.getClass());
}
gnuWrappedOptions = (GnuDemanglerWrappedOption) customOption;
options.registerOption(OPTION_NAME_DEMANGLE_USE_KNOWN_PATTERNS, demangleOnlyKnownPatterns,
help,
OPTION_DESCRIPTION_USE_KNOWN_PATTERNS);
options.registerOption(OPTION_NAME_USE_DEPRECATED_DEMANGLER, useDeprecatedDemangler, help,
OPTION_DESCRIPTION_DEPRECATED_DEMANGLER);
options.registerOption(OPTION_NAME_DEMANGLER_PARAMETERS, demanglerParameters, help,
OPTION_DESCRIPTION_DEMANGLER_PARAMETERS);
}
@Override
@ -97,9 +97,11 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
demangleOnlyKnownPatterns =
options.getBoolean(OPTION_NAME_DEMANGLE_USE_KNOWN_PATTERNS, demangleOnlyKnownPatterns);
gnuWrappedOptions =
(GnuDemanglerWrappedOption) options.getCustomOption(OPTION_NAME_GNU_DEMANGLER,
new GnuDemanglerWrappedOption());
useDeprecatedDemangler =
options.getBoolean(OPTION_NAME_USE_DEPRECATED_DEMANGLER, useDeprecatedDemangler);
demanglerParameters =
options.getString(OPTION_NAME_DEMANGLER_PARAMETERS, demanglerParameters);
}
@Override
@ -109,15 +111,7 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
options.setDoDisassembly(true);
options.setApplySignature(doSignatureEnabled);
options.setDemangleOnlyKnownPatterns(demangleOnlyKnownPatterns);
options.setUseDeprecatedDemangler(gnuWrappedOptions.useDeprecatedDemangler());
String text = null;
if (gnuWrappedOptions.useDemanglerParameters()) {
text = gnuWrappedOptions.getDemanglerParametersText();
}
options.setDemanglerApplicationArguments(text);
options.setDemanglerApplicationArguments(demanglerParameters);
return options;
}
@ -144,7 +138,7 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
log.appendException(e);
}
if (options.useDeprecatedDemangler()) {
if (useDeprecatedDemangler) {
// see if the options work in the deprecated demangler
GnuDemanglerOptions deprecatedOptions = options.withDeprecatedDemangler();
String deprecatedName = deprecatedOptions.getDemanglerName();
@ -176,7 +170,7 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
demangled = demangler.demangle(mangled, options);
}
catch (DemangledException e) {
if (!options.useDeprecatedDemangler()) {
if (!useDeprecatedDemangler) {
throw e; // let our parent handle this
}
}
@ -185,7 +179,7 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
return demangled;
}
if (options.useDeprecatedDemangler()) {
if (useDeprecatedDemangler) {
GnuDemanglerOptions newOptions = options.withDeprecatedDemangler();
demangled = demangler.demangle(mangled, newOptions);
}

View file

@ -1,179 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.plugin.core.analysis;
import java.awt.Component;
import java.awt.Container;
import java.beans.PropertyEditorSupport;
import java.util.Objects;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import docking.widgets.checkbox.GCheckBox;
import ghidra.framework.options.CustomOptionsEditor;
import ghidra.util.layout.HorizontalLayout;
import ghidra.util.layout.VerticalLayout;
public class GnuDemanglerOptionsPropertyEditor extends PropertyEditorSupport
implements CustomOptionsEditor {
private static final String USE_DEPRECATED_DEMANGLER = "Use Deprecated Demangler";
private static final String USE_DEMANGLER_PARAMETERS = "Use Demangler Program Parameters";
private static final String USE_DEPRECATED_DEMANGLER_TOOLTIP =
"Signals to use the deprecated demangler when the modern demangler cannot demangle a " +
"given string";
private static final String USE_DEMANGLER_PARAMETERS_TOOLTIP =
"Signals to use pass the given parameters to the demangler program";
private static final String[] NAMES =
{ USE_DEPRECATED_DEMANGLER, USE_DEMANGLER_PARAMETERS };
private static final String[] DESCRIPTIONS = { USE_DEPRECATED_DEMANGLER_TOOLTIP,
USE_DEMANGLER_PARAMETERS_TOOLTIP };
private GnuDemanglerWrappedOption wrappedOption;
private Component editorComponent;
private GCheckBox useDeprecatedDemanglerBox;
private GCheckBox useDemanglerParametersBox;
private JTextField demanglerParametersTextField;
public GnuDemanglerOptionsPropertyEditor() {
editorComponent = buildEditor();
}
private Component buildEditor() {
// we want to have a panel with our options so that we may group them together
JPanel panel = new JPanel(new VerticalLayout(3));
useDeprecatedDemanglerBox = new GCheckBox(USE_DEPRECATED_DEMANGLER);
useDeprecatedDemanglerBox.setSelected(false);
useDeprecatedDemanglerBox.setToolTipText(USE_DEPRECATED_DEMANGLER_TOOLTIP);
useDeprecatedDemanglerBox.addItemListener(e -> firePropertyChange());
panel.add(useDeprecatedDemanglerBox);
createParameterComponent(panel);
return panel;
}
private void createParameterComponent(Container parent) {
JPanel textFieldPanel = new JPanel(new HorizontalLayout(0));
JTextField textField = new JTextField(15);
useDemanglerParametersBox = new GCheckBox(USE_DEMANGLER_PARAMETERS);
useDemanglerParametersBox.setToolTipText(USE_DEMANGLER_PARAMETERS_TOOLTIP);
useDemanglerParametersBox.addItemListener(e -> {
textField.setEnabled(useDemanglerParametersBox.isSelected());
firePropertyChange();
});
textField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent e) {
firePropertyChange();
}
@Override
public void insertUpdate(DocumentEvent e) {
firePropertyChange();
}
@Override
public void removeUpdate(DocumentEvent e) {
firePropertyChange();
}
});
textField.setEnabled(false);
textFieldPanel.add(useDemanglerParametersBox);
textFieldPanel.add(Box.createHorizontalStrut(10));
textFieldPanel.add(textField);
parent.add(textFieldPanel);
demanglerParametersTextField = textField;
}
@Override
public void setValue(Object value) {
if (!(value instanceof GnuDemanglerWrappedOption)) {
return;
}
wrappedOption = (GnuDemanglerWrappedOption) value;
setLocalValues(wrappedOption);
firePropertyChange();
}
private void setLocalValues(GnuDemanglerWrappedOption newOption) {
if (newOption.useDeprecatedDemangler() != useDeprecatedDemanglerBox.isSelected()) {
useDeprecatedDemanglerBox.setSelected(newOption.useDeprecatedDemangler());
}
if (newOption.useDemanglerParameters() != useDemanglerParametersBox.isSelected()) {
useDemanglerParametersBox.setSelected(newOption.useDemanglerParameters());
}
String newText = newOption.getDemanglerParametersText();
String currentText = demanglerParametersTextField.getText();
if (!Objects.equals(newText, currentText)) {
demanglerParametersTextField.setText(newText);
}
}
@Override
public Object getValue() {
return cloneNamespaceValues();
}
private GnuDemanglerWrappedOption cloneNamespaceValues() {
GnuDemanglerWrappedOption newOption = new GnuDemanglerWrappedOption();
newOption.setUseDeprecatedDemangler(useDeprecatedDemanglerBox.isSelected());
newOption.setUseDemanglerParameters(useDemanglerParametersBox.isSelected());
newOption.setDemanglerParametersText(demanglerParametersTextField.getText());
return newOption;
}
@Override
public String[] getOptionNames() {
return NAMES;
}
@Override
public String[] getOptionDescriptions() {
return DESCRIPTIONS;
}
@Override
public Component getCustomEditor() {
return editorComponent;
}
@Override
public boolean supportsCustomEditor() {
return true;
}
}

View file

@ -1,125 +0,0 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.plugin.core.analysis;
import java.util.Objects;
import ghidra.framework.options.CustomOption;
import ghidra.framework.options.SaveState;
/**
* A simple java bean adapted to the {@link CustomOption} interface. The public
* getters and setters are self-documenting.
*/
public class GnuDemanglerWrappedOption implements CustomOption {
private static final String USE_DEPRECATED_DEMANGLER = "USE_DEPRECATED_DEMANGLER";
private static final String USE_DEMANGLER_PARAMETERS = "USE_DEMANGLER_PARAMETERS";
private static final String DEMANGLER_PARAMETERS = "DEMANGLER_PARAMETERS";
private boolean useDeprecatedDemangler = false;
private boolean useDemanglerParameters = false;
private String demanglerParametersText = null;
public void setUseDeprecatedDemangler(boolean doUse) {
this.useDeprecatedDemangler = doUse;
}
public boolean useDeprecatedDemangler() {
return useDeprecatedDemangler;
}
public void setDemanglerParametersText(String text) {
this.demanglerParametersText = text;
}
public String getDemanglerParametersText() {
return demanglerParametersText;
}
public void setUseDemanglerParameters(boolean doUse) {
this.useDemanglerParameters = doUse;
}
public boolean useDemanglerParameters() {
return useDemanglerParameters;
}
@Override
public void readState(SaveState state) {
useDeprecatedDemangler =
state.getBoolean(USE_DEPRECATED_DEMANGLER, useDemanglerParameters);
useDemanglerParameters =
state.getBoolean(USE_DEPRECATED_DEMANGLER, useDemanglerParameters);
demanglerParametersText =
state.getString(DEMANGLER_PARAMETERS, demanglerParametersText);
}
@Override
public void writeState(SaveState state) {
state.putBoolean(USE_DEPRECATED_DEMANGLER, useDeprecatedDemangler);
state.putBoolean(USE_DEMANGLER_PARAMETERS, useDemanglerParameters);
state.putString(USE_DEMANGLER_PARAMETERS, demanglerParametersText);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result +
((demanglerParametersText == null) ? 0 : demanglerParametersText.hashCode());
result = prime * result + (useDemanglerParameters ? 1231 : 1237);
result = prime * result + (useDeprecatedDemangler ? 1231 : 1237);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
GnuDemanglerWrappedOption other = (GnuDemanglerWrappedOption) obj;
if (!Objects.equals(demanglerParametersText, other.demanglerParametersText)) {
return false;
}
if (useDemanglerParameters != other.useDemanglerParameters) {
return false;
}
if (useDeprecatedDemangler != other.useDeprecatedDemangler) {
return false;
}
return true;
}
@Override
public String toString() {
//@formatter:off
return "{\n" +
"\tuseDeprecatedDemangler: " + useDeprecatedDemangler + ",\n" +
"\tuseDemanglerParameters: " + useDemanglerParameters + ",\n" +
"\tdemanglerParametersText: " + demanglerParametersText + ",\n" +
"}";
//@formatter:on
}
}

View file

@ -60,6 +60,7 @@ public class GnuDemangler implements Demangler {
}
@Override
@Deprecated(since = "9.2", forRemoval = true)
public DemangledObject demangle(String mangled, boolean demangleOnlyKnownPatterns)
throws DemangledException {
GnuDemanglerOptions options = new GnuDemanglerOptions();

View file

@ -27,6 +27,11 @@ import org.apache.commons.lang3.StringUtils;
import ghidra.framework.Application;
import ghidra.framework.Platform;
/**
* A class that allows for the reuse of native demangler executable processes. This class will
* cache the process by name and by any arguments passed to the process when started. Once
* successfully started, the process will persist
*/
public class GnuDemanglerNativeProcess {
public static final String DEMANGLER_GNU = GnuDemanglerOptions.GNU_DEMANGLER_DEFAULT;
@ -42,21 +47,35 @@ public class GnuDemanglerNativeProcess {
private BufferedReader reader;
private PrintWriter writer;
// TODO docme
/**
* Gets the default GNU demangler native process
* @return the process
* @throws IOException if the process cannot be started
*/
public static synchronized GnuDemanglerNativeProcess getDemanglerNativeProcess()
throws IOException {
return getDemanglerNativeProcess(DEMANGLER_GNU);
}
// TODO docme
/**
* Gets the default GNU demangler native process
* @param name the specific executable name to launch
* @return the process
* @throws IOException if the process cannot be started
*/
public static synchronized GnuDemanglerNativeProcess getDemanglerNativeProcess(String name)
throws IOException {
return getDemanglerNativeProcess(name, DEFAULT_NATIVE_OPTIONS);
}
// TODO docme
// TODO we should probably age-off all demanglers by access time
/**
* Gets the default GNU demangler native process
* @param name the specific executable name to launch
* @param nativeOptions the arguments string to pass to the native demangler
* @return the process
* @throws IOException if the process cannot be started
*/
public static synchronized GnuDemanglerNativeProcess getDemanglerNativeProcess(String name,
String nativeOptions)
throws IOException {
@ -66,15 +85,18 @@ public class GnuDemanglerNativeProcess {
options = DEFAULT_NATIVE_OPTIONS;
}
String key = name + nativeOptions;
String key = getKey(name, options);
GnuDemanglerNativeProcess nativeProcess = processesByName.get(key);
if (nativeProcess == null) {
nativeProcess = new GnuDemanglerNativeProcess(name, options);
processesByName.put(key, nativeProcess);
}
return nativeProcess;
}
private static String getKey(String name, String options) {
return name + ' ' + options;
}
private GnuDemanglerNativeProcess(String applicationName, String options) throws IOException {
this.applicationName = applicationName;
this.options = options;
@ -95,7 +117,6 @@ public class GnuDemanglerNativeProcess {
catch (IOException e) {
dispose();
if (!restart) {
processesByName.remove(applicationName);
throw new IOException("Demangler process is not running.", e);
}
createProcess();
@ -109,7 +130,11 @@ public class GnuDemanglerNativeProcess {
return reader.readLine();
}
private void dispose() {
public void dispose() {
String key = getKey(applicationName, options);
processesByName.remove(key);
try {
if (process != null) {
process.destroy();
@ -139,6 +164,8 @@ public class GnuDemanglerNativeProcess {
checkForError(command);
isDisposed = false;
String key = getKey(applicationName, options);
processesByName.put(key, this);
}
private String[] buildCommand() throws FileNotFoundException {

View file

@ -15,12 +15,19 @@
*/
package ghidra.app.util.demangler.gnu;
import org.apache.commons.lang3.StringUtils;
import ghidra.app.util.demangler.DemanglerOptions;
/**
* GNU demangler options
*/
public class GnuDemanglerOptions extends DemanglerOptions {
/*
Note!
If you update the demangler versions, then you also must update the help (search the
html files for the old version strings).
*/
/**
* Version 2.24 of the GNU demangler. This version supports older formats and older bugs.
*/
@ -38,7 +45,6 @@ public class GnuDemanglerOptions extends DemanglerOptions {
private String demanglerName = GNU_DEMANGLER_DEFAULT;
private String demanglerApplicationArguments;
private boolean useDeprecatedDemangler;
public GnuDemanglerOptions() {
// use default values
@ -51,48 +57,47 @@ public class GnuDemanglerOptions extends DemanglerOptions {
GnuDemanglerOptions gCopy = (GnuDemanglerOptions) copy;
demanglerName = gCopy.demanglerName;
demanglerApplicationArguments = gCopy.demanglerApplicationArguments;
useDeprecatedDemangler = gCopy.useDeprecatedDemangler;
}
}
// TODO docme
/**
* Returns the external demangler executable name to be used for demangling. The
* default value is {@link #GNU_DEMANGLER_DEFAULT}.
* @return the name
*/
public String getDemanglerName() {
return demanglerName;
}
// TODO docme
// TODO should we validate and or log a message it the name is unknown?
/**
* Sets the external demangler executable name to be used for demangling
* @param name the name
*/
public void setDemanglerName(String name) {
this.demanglerName = name;
}
// TODO docme
/**
* Returns the current arguments to be passed to the external demangler executable
* @return the arguments
*/
public String getDemanglerApplicationArguments() {
return demanglerApplicationArguments;
}
// TODO docme
/**
* Sets the arguments to be passed to the external demangler executable
* @param args the arguments
*/
public void setDemanglerApplicationArguments(String args) {
this.demanglerApplicationArguments = args;
}
// TODO docme
// TODO mabye rename to hasNativeApplicationOptions()
public boolean hasDemanglerApplicationArguments() {
return !StringUtils.isBlank(demanglerApplicationArguments);
}
// TODO docme
public void setUseDeprecatedDemangler(boolean doUse) {
this.useDeprecatedDemangler = doUse;
}
// TODO docme
public boolean useDeprecatedDemangler() {
return useDeprecatedDemangler;
}
// TODO docme
/**
* A convenience method to copy the state of this options object, changing the
* demangler executable name to the deprecated demangler
* @return the new options
*/
public GnuDemanglerOptions withDeprecatedDemangler() {
GnuDemanglerOptions newOptions = new GnuDemanglerOptions(this);
newOptions.setDemanglerName(GNU_DEMANGLER_V2_24);
@ -107,7 +112,6 @@ public class GnuDemanglerOptions extends DemanglerOptions {
"\tapplySignature: " + applySignature() + ",\n" +
"\tdemangleOnlyKnownPatterns: " + demangleOnlyKnownPatterns() + ",\n" +
"\tdemanglerName: " + demanglerName + ",\n" +
"\tuseDeprecatedDemangler: " + useDeprecatedDemangler + ",\n" +
"\tdemanglerApplicationArguments: " + demanglerApplicationArguments + ",\n" +
"}";
//@formatter:on

View file

@ -0,0 +1,130 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.plugin.core.analysis;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import ghidra.app.cmd.label.AddLabelCmd;
import ghidra.app.util.importer.MessageLog;
import ghidra.framework.options.Options;
import ghidra.program.database.ProgramBuilder;
import ghidra.program.database.ProgramDB;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.program.model.symbol.SourceType;
import ghidra.test.AbstractGhidraHeadlessIntegrationTest;
import ghidra.test.ToyProgramBuilder;
import ghidra.util.Msg;
import ghidra.util.exception.RollbackException;
import ghidra.util.task.TaskMonitor;
public class GnuDemanglerAnalyzerTest extends AbstractGhidraHeadlessIntegrationTest {
private GnuDemanglerAnalyzer analyzer = new GnuDemanglerAnalyzer();
private ProgramDB program;
@Before
public void setUp() throws Exception {
ProgramBuilder builder = new ToyProgramBuilder("test", true);
builder.createMemory(".text", "0x0100", 0x100);
program = builder.getProgram();
registerOptions();
}
@Test
public void testDeprectedDemangledString() throws Exception {
//
// The below demangles to MsoDAL::VertFrame::__dt( (void))
// note the (void) syntax
//
// from program Microsoft Entourage
//
String mangled = "__dt__Q26MsoDAL9VertFrameFv";
Address addr = addr("0x110");
createSymbol(addr, mangled);
setOption(GnuDemanglerAnalyzer.OPTION_NAME_USE_DEPRECATED_DEMANGLER, true);
MessageLog log = new MessageLog();
analyzer.added(program, program.getMemory(), TaskMonitor.DUMMY, log);
}
private void setOption(String optionNameUseDeprecatedDemangler, boolean b) {
Options options = program.getOptions("Analyzers");
for (String name : options.getOptionNames()) {
if (name.contains("Demangler GNU")) {
Msg.out("found it: " + name);
}
else {
Msg.out("no it: " + name);
}
}
}
private void createSymbol(Address addr, String mangled) {
AddLabelCmd cmd = new AddLabelCmd(addr, mangled, SourceType.ANALYSIS);
int txId = program.startTransaction(cmd.getName());
boolean commit = true;
try {
boolean status = cmd.applyTo(program);
program.flushEvents();
if (!status) {
fail("Could not apply command: " + cmd.getStatusMsg());
}
}
catch (RollbackException e) {
commit = false;
throw e;
}
finally {
program.endTransaction(txId, commit);
}
}
@Test
public void testDeprectedDemangledString_WithArguments_Valid() {
fail();
}
@Test
public void testDeprectedDemangledString_WithArguments_Invalid() {
fail();
}
private Address addr(String addr) {
return program.getAddressFactory().getAddress(addr);
}
private void registerOptions() {
Options options = program.getOptions(Program.ANALYSIS_PROPERTIES);
Options analyzerOptions = options.getOptions(analyzer.getName());
analyzer.registerOptions(analyzerOptions, program);
}
}

View file

@ -1130,7 +1130,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
String mangled = "uv__dup";
GnuDemangler demangler = new GnuDemangler();
DemangledObject res = demangler.demangle(mangled, true);
DemangledObject res = demangler.demangle(mangled);
assertNull(res);
}

View file

@ -23,7 +23,8 @@ import org.junit.Before;
import org.junit.Test;
import generic.test.AbstractGenericTest;
import ghidra.app.util.demangler.*;
import ghidra.app.util.demangler.DemangledException;
import ghidra.app.util.demangler.DemangledObject;
import ghidra.program.database.ProgramDB;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.TerminatedStringDataType;
@ -54,7 +55,7 @@ public class GnuDemanglerTest extends AbstractGenericTest {
demangler.canDemangle(program);// this perform initialization
// this throws an exception with the bug in place
demangler.demangle(mangled, true);
demangler.demangle(mangled);
}
@Test
@ -65,8 +66,10 @@ public class GnuDemanglerTest extends AbstractGenericTest {
GnuDemangler demangler = new GnuDemangler();
demangler.canDemangle(program);// this perform initialization
GnuDemanglerOptions options = new GnuDemanglerOptions();
options.setDemangleOnlyKnownPatterns(false);
try {
demangler.demangle(mangled, false);
demangler.demangle(mangled, options);
fail("Demangle should have failed attempting to demangle a non-mangled string");
}
catch (DemangledException e) {
@ -82,7 +85,7 @@ public class GnuDemanglerTest extends AbstractGenericTest {
GnuDemangler demangler = new GnuDemangler();
demangler.canDemangle(program);// this perform initialization
DemangledObject result = demangler.demangle(mangled, true);
DemangledObject result = demangler.demangle(mangled);
assertNull("Demangle did not skip a name that does not match a known mangled pattern",
result);
}
@ -99,13 +102,13 @@ public class GnuDemanglerTest extends AbstractGenericTest {
symbolTable.createLabel(addr("01001000"), mangled, SourceType.IMPORTED);
GnuDemangler demangler = new GnuDemangler();
DemangledObject obj = demangler.demangle(mangled, true);
DemangledObject obj = demangler.demangle(mangled);
assertNotNull(obj);
//assertEquals("typeinfo for AP_HAL::HAL::Callbacks", obj.getSignature(false));
assertTrue(
obj.applyTo(program, addr("01001000"), new DemanglerOptions(), TaskMonitor.DUMMY));
obj.applyTo(program, addr("01001000"), new GnuDemanglerOptions(), TaskMonitor.DUMMY));
Symbol s = symbolTable.getPrimarySymbol(addr("01001000"));
assertNotNull(s);
@ -132,13 +135,13 @@ public class GnuDemanglerTest extends AbstractGenericTest {
symbolTable.createLabel(addr("01001000"), mangled, SourceType.IMPORTED);
GnuDemangler demangler = new GnuDemangler();
DemangledObject obj = demangler.demangle(mangled, true);
DemangledObject obj = demangler.demangle(mangled);
assertNotNull(obj);
assertEquals("typeinfo name for AP_HAL::HAL::Callbacks", obj.getSignature(false));
assertTrue(
obj.applyTo(program, addr("01001000"), new DemanglerOptions(), TaskMonitor.DUMMY));
obj.applyTo(program, addr("01001000"), new GnuDemanglerOptions(), TaskMonitor.DUMMY));
Symbol s = symbolTable.getPrimarySymbol(addr("01001000"));
assertNotNull(s);

View file

@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1
li { font-family:times new roman; font-size:14pt; }
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
@ -55,4 +55,10 @@ table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
code { color: black; font-family: courier new; font-size: 14pt; }
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE>
*/
code { color: black; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }

View file

@ -94,7 +94,7 @@ public class MicrosoftDemanglerScript extends GhidraScript {
}
private void demangle(String mangled) throws Exception {
DemangledObject demangled = demangler.demangle(mangled, true);
DemangledObject demangled = demangler.demangle(mangled);
printf("magled %s\ndemangled %s", mangled, demangled);
}
}

View file

@ -21,6 +21,9 @@ import ghidra.app.util.importer.MessageLog;
import ghidra.framework.options.Options;
import ghidra.program.model.listing.Program;
/**
* A version of the demangler analyzer to handle microsoft symbols
*/
public class MicrosoftDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
private static final String NAME = "Demangler Microsoft";

View file

@ -39,6 +39,7 @@ public class MicrosoftDemangler implements Demangler {
}
@Override
@Deprecated(since = "9.2", forRemoval = true)
public DemangledObject demangle(String mangled, boolean demangleOnlyKnownPatterns)
throws DemangledException {
try {
@ -82,36 +83,4 @@ public class MicrosoftDemangler implements Demangler {
throw gde;
}
}
// /**
// * This represents an odd symbol that looks mangled, but we don't know what to do with. It
// * is of the form:
// * ?BobsStuffIO@344text__@@U_text@@?W
// *
// * where the last character is preceded by a special character, such as ?, *, -, etc
// */
// private static Pattern INVALID_TRAILING_CHARS_PATTERN = Pattern.compile(".*@@[?*`%~+/-][A-Z]");
// private boolean isMangled(String mangled) {
// int atpos = mangled.indexOf("@");
// boolean isMangled = mangled.charAt(0) == '?' && atpos != -1;
//
// if (!isMangled) {
// return false;
// }
//
// if (mangled.endsWith("~")) {
// return false;
// }
//
// //
// // Now check for some odd things that we've seen.
// //
// Matcher matcher = INVALID_TRAILING_CHARS_PATTERN.matcher(mangled);
// if (matcher.matches()) {
// return false;
// }
//
// return true;
// }
}

View file

@ -33,10 +33,6 @@ public class MicrosoftDemanglerTest extends AbstractGenericTest {
private ProgramDB program;
public MicrosoftDemanglerTest() {
super();
}
@Before
public void setUp() throws Exception {
ToyProgramBuilder builder = new ToyProgramBuilder("test", true);
@ -49,7 +45,7 @@ public class MicrosoftDemanglerTest extends AbstractGenericTest {
String mangled = "?Te@NS1@BobsStuff@@0QAY0BAA@$$CBIA";
MicrosoftDemangler demangler = new MicrosoftDemangler();
DemangledObject demangledObject = demangler.demangle(mangled, true);
DemangledObject demangledObject = demangler.demangle(mangled);
int txID = program.startTransaction("Test");
@ -67,7 +63,7 @@ public class MicrosoftDemanglerTest extends AbstractGenericTest {
String mangled = "??0_LocaleUpdate@@QAE@PAUlocaleinfo_struct@@@Z";
MicrosoftDemangler demangler = new MicrosoftDemangler();
DemangledObject demangledObj = demangler.demangle(mangled, true);
DemangledObject demangledObj = demangler.demangle(mangled);
assertNotNull(demangledObj);
}
@ -78,7 +74,7 @@ public class MicrosoftDemanglerTest extends AbstractGenericTest {
MicrosoftDemangler demangler = new MicrosoftDemangler();
DemangledObject demangledObj = null;
try {
demangledObj = demangler.demangle(mangled, true);
demangledObj = demangler.demangle(mangled);
}
catch (DemangledException e) {
// Expected
@ -94,7 +90,7 @@ public class MicrosoftDemanglerTest extends AbstractGenericTest {
MicrosoftDemangler demangler = new MicrosoftDemangler();
DemangledObject demangledObj = null;
try {
demangledObj = demangler.demangle(mangled, true);
demangledObj = demangler.demangle(mangled);
}
catch (DemangledException e) {
// Expected
@ -110,7 +106,7 @@ public class MicrosoftDemanglerTest extends AbstractGenericTest {
MicrosoftDemangler demangler = new MicrosoftDemangler();
DemangledObject demangledObj = null;
try {
demangledObj = demangler.demangle(mangled, true);
demangledObj = demangler.demangle(mangled);
}
catch (DemangledException e) {
// Expected
@ -126,7 +122,7 @@ public class MicrosoftDemanglerTest extends AbstractGenericTest {
MicrosoftDemangler demangler = new MicrosoftDemangler();
DemangledObject demangledObj = null;
try {
demangledObj = demangler.demangle(mangled, true);
demangledObj = demangler.demangle(mangled);
}
catch (DemangledException e) {
// Expected
@ -142,7 +138,7 @@ public class MicrosoftDemanglerTest extends AbstractGenericTest {
MicrosoftDemangler demangler = new MicrosoftDemangler();
DemangledObject demangledObj = null;
try {
demangledObj = demangler.demangle(mangled, true);
demangledObj = demangler.demangle(mangled);
}
catch (DemangledException e) {
// Expected
@ -158,7 +154,7 @@ public class MicrosoftDemanglerTest extends AbstractGenericTest {
MicrosoftDemangler demangler = new MicrosoftDemangler();
DemangledObject demangledObj = null;
try {
demangledObj = demangler.demangle(mangled, true);
demangledObj = demangler.demangle(mangled);
}
catch (DemangledException e) {
// Expected
@ -174,7 +170,7 @@ public class MicrosoftDemanglerTest extends AbstractGenericTest {
MicrosoftDemangler demangler = new MicrosoftDemangler();
DemangledObject demangledObj = null;
try {
demangledObj = demangler.demangle(mangled, true);
demangledObj = demangler.demangle(mangled);
}
catch (DemangledException e) {
// Expected
@ -190,7 +186,7 @@ public class MicrosoftDemanglerTest extends AbstractGenericTest {
MicrosoftDemangler demangler = new MicrosoftDemangler();
DemangledObject demangledObj = null;
try {
demangledObj = demangler.demangle(mangled, true);
demangledObj = demangler.demangle(mangled);
}
catch (DemangledException e) {
// Expected
@ -206,7 +202,7 @@ public class MicrosoftDemanglerTest extends AbstractGenericTest {
MicrosoftDemangler demangler = new MicrosoftDemangler();
DemangledObject demangledObj = null;
try {
demangledObj = demangler.demangle(mangled, true);
demangledObj = demangler.demangle(mangled);
}
catch (DemangledException e) {
// Expected

View file

@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1
li { font-family:times new roman; font-size:14pt; }
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
@ -55,4 +55,10 @@ table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
code { color: black; font-family: courier new; font-size: 14pt; }
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE>
*/
code { color: black; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }

View file

@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1
li { font-family:times new roman; font-size:14pt; }
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
@ -55,4 +55,10 @@ table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
code { color: black; font-family: courier new; font-size: 14pt; }
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE>
*/
code { color: black; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }

View file

@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1
li { font-family:times new roman; font-size:14pt; }
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
@ -55,4 +55,10 @@ table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
code { color: black; font-family: courier new; font-size: 14pt; }
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE>
*/
code { color: black; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }

View file

@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1
li { font-family:times new roman; font-size:14pt; }
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
@ -55,4 +55,10 @@ table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
code { color: black; font-family: courier new; font-size: 14pt; }
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE>
*/
code { color: black; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }

View file

@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1
li { font-family:times new roman; font-size:14pt; }
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
@ -55,4 +55,10 @@ table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
code { color: black; font-family: courier new; font-size: 14pt; }
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE>
*/
code { color: black; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,25 +15,29 @@
*/
package docking.options.editor;
import ghidra.framework.options.EditorState;
import java.awt.Dimension;
import ghidra.framework.options.EditorState;
import ghidra.util.layout.HorizontalLayout;
/**
* A custom OptionComponent that controls it's own display using the editor component of the
* given EditorState.
*/
public class CustomOptionComponent extends GenericOptionsComponent {
protected CustomOptionComponent( EditorState editorState ) {
super( editorState );
protected CustomOptionComponent(EditorState editorState) {
super(editorState);
// this layout allows us to easily left-align the single component in this container
setLayout(new HorizontalLayout(0));
// this class is designed to let the editor component handle the display and editing
add( editorState.getEditorComponent() );
add(editorState.getEditorComponent());
}
@Override
protected Dimension getPreferredAlignmentSize() {
return new Dimension( 0, 0 );
return new Dimension(0, 0);
}
}

View file

@ -21,7 +21,8 @@ import org.junit.Before;
import org.junit.Test;
import ghidra.app.cmd.label.DemanglerCmd;
import ghidra.app.util.demangler.*;
import ghidra.app.util.demangler.DemangledException;
import ghidra.app.util.demangler.DemangledObject;
import ghidra.program.database.ProgramDB;
import ghidra.program.model.address.Address;
import ghidra.test.AbstractGhidraHeadlessIntegrationTest;
@ -58,13 +59,13 @@ public class GnuDemanglerIntegrationTest extends AbstractGhidraHeadlessIntegrati
GnuDemangler demangler = new GnuDemangler();
demangler.canDemangle(program);// this perform initialization
DemangledObject result = demangler.demangle(mangled, false);
GnuDemanglerOptions options = new GnuDemanglerOptions();
options.setDemangleOnlyKnownPatterns(false);
DemangledObject result = demangler.demangle(mangled, options);
assertNotNull(result);
assertEquals("undefined MyNamespace::MyFunction($ParamNamespace::paramName *)",
result.getSignature(false));
DemanglerOptions options = new DemanglerOptions();
options.setDemangleOnlyKnownPatterns(false);
DemanglerCmd cmd = new DemanglerCmd(addr("01001000"), mangled, options);
// this used to trigger an exception

View file

@ -28,7 +28,7 @@ body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 1
li { font-family:times new roman; font-size:14pt; }
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
@ -55,4 +55,10 @@ table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
code { color: black; font-family: courier new; font-size: 14pt; }
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE>
*/
code { color: black; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }

View file

@ -24,12 +24,12 @@
*/
body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px;} /* some padding to improve readability */
body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 10px; } /* some padding to improve readability */
li { font-family:times new roman; font-size:14pt; }
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; font-family:times new roman; font-size:14pt; font-style:italic; }
h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; `font-size:14pt; font-weight:bold; }
h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; }
/*
P tag code. Most of the help files nest P tags inside of blockquote tags (the was the
@ -40,12 +40,25 @@ h4 { margin-left: 10px; font-family:times new roman; font-size:14pt; font-style:
*/
p { margin-left: 40px; font-family:times new roman; font-size:14pt; }
blockquote p { margin-left: 10px; }
p.providedbyplugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px }
p.ProvidedByPlugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px }
p.relatedtopic { color:#800080; margin-left: 10px; font-size:14pt; }
p.RelatedTopic { color:#800080; margin-left: 10px; font-size:14pt; }
/*
We wish for a tables to have space between it and the preceding element, so that text
is not too close to the top of the table. Also, nest the table a bit so that it is clear
the table relates to the preceding text.
*/
table { margin-left: 20px; margin-top: 10px; width: 80%;}
td { font-family:times new roman; font-size:14pt; vertical-align: top; }
th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; }
code { color: black; font-family: courier new; font-size: 14pt; }
/*
Code-like formatting for things such as file system paths and proper names of classes,
methods, etc. To apply this to a file path, use this syntax:
<CODE CLASS="path">...</CODE>
*/
code { color: black; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }
code.path { color: #4682B4; font-weight: bold; font-family: courier new, monospace; font-size: 14pt; white-space: nowrap; }