From b4ce3012d7f94acb4460c4d8a99832fe30f9f1a3 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Wed, 12 Feb 2020 18:21:10 -0500 Subject: [PATCH] GT-3481 - Gnu Demangler - Checkpoint 2 - Most docs and tests done; analyzer test remains --- .../src/main/help/help/shared/Frontpage.css | 10 +- .../src/main/help/help/shared/Frontpage.css | 10 +- Ghidra/Features/Base/certification.manifest | 1 - .../src/main/help/help/shared/Frontpage.css | 10 +- .../src/main/help/help/shared/helpWarning.png | Bin 1354 -> 0 bytes .../AutoAnalysisPlugin/AutoAnalysis.htm | 123 ++++++-- .../ghidra/app/cmd/label/DemanglerCmd.java | 2 +- .../analysis/AbstractDemanglerAnalyzer.java | 75 ++++- .../core/analysis/AnalysisOptionsDialog.java | 16 +- .../plugin/core/analysis/AnalysisPanel.java | 79 +++-- .../FindNoReturnFunctionsAnalyzer.java | 107 +++---- .../analysis/OperandReferenceAnalyzer.java | 72 ++--- .../core/disassembler/EntryPointAnalyzer.java | 46 +-- .../core/function/SharedReturnAnalyzer.java | 17 +- .../plugin/core/string/StringsAnalyzer.java | 16 +- .../ghidra/app/util/demangler/Demangler.java | 39 ++- .../app/util/demangler/DemanglerUtil.java | 8 +- .../ghidra_scripts/BuildFuncDB.java | 72 ----- .../src/main/help/help/shared/Frontpage.css | 10 +- .../java/ghidra/app/analyzers/LibHashDB.java | 111 ------- .../app/analyzers/LibraryHashAnalyzer.java | 271 ------------------ .../src/main/help/help/shared/Frontpage.css | 10 +- .../Decompiler/src/main/doc/Frontpage.css | 10 +- .../src/main/help/help/shared/Frontpage.css | 10 +- .../analysis/DecompilerFunctionAnalyzer.java | 2 +- .../src/main/help/help/shared/Frontpage.css | 25 +- .../src/main/help/help/shared/Frontpage.css | 10 +- .../src/main/help/help/shared/Frontpage.css | 10 +- .../DemangleElfWithOptionScript.java | 95 +----- .../ghidra_scripts/VxWorksSymTab_5_4.java | 17 +- .../ghidra_scripts/VxWorksSymTab_6_1.java | 2 +- .../ghidra_scripts/VxWorksSymTab_Finder.java | 23 +- .../core/analysis/GnuDemanglerAnalyzer.java | 76 +++-- .../GnuDemanglerOptionsPropertyEditor.java | 179 ------------ .../analysis/GnuDemanglerWrappedOption.java | 125 -------- .../app/util/demangler/gnu/GnuDemangler.java | 1 + .../gnu/GnuDemanglerNativeProcess.java | 43 ++- .../demangler/gnu/GnuDemanglerOptions.java | 58 ++-- .../analysis/GnuDemanglerAnalyzerTest.java | 130 +++++++++ .../demangler/GnuDemanglerParserTest.java | 2 +- .../util/demangler/gnu/GnuDemanglerTest.java | 19 +- .../src/main/help/help/shared/Frontpage.css | 10 +- .../MicrosoftDemanglerScript.java | 2 +- .../analysis/MicrosoftDemanglerAnalyzer.java | 3 + .../microsoft/MicrosoftDemangler.java | 33 +-- .../microsoft/MicrosoftDemanglerTest.java | 26 +- .../src/main/help/help/shared/Frontpage.css | 10 +- .../src/main/help/help/shared/Frontpage.css | 10 +- .../src/main/help/help/shared/Frontpage.css | 10 +- .../src/main/help/help/shared/Frontpage.css | 10 +- .../src/main/help/help/shared/Frontpage.css | 10 +- .../options/editor/CustomOptionComponent.java | 27 +- .../gnu/GnuDemanglerIntegrationTest.java | 9 +- .../src/main/help/help/shared/Frontpage.css | 10 +- GhidraDocs/languages/html/Frontpage.css | 25 +- 55 files changed, 854 insertions(+), 1283 deletions(-) delete mode 100644 Ghidra/Features/Base/src/main/help/help/shared/helpWarning.png delete mode 100644 Ghidra/Features/BytePatterns/ghidra_scripts/BuildFuncDB.java delete mode 100644 Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/LibHashDB.java delete mode 100644 Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/LibraryHashAnalyzer.java delete mode 100644 Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/plugin/core/analysis/GnuDemanglerOptionsPropertyEditor.java delete mode 100644 Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/plugin/core/analysis/GnuDemanglerWrappedOption.java create mode 100644 Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/plugin/core/analysis/GnuDemanglerAnalyzerTest.java diff --git a/Ghidra/Extensions/SampleTablePlugin/src/main/help/help/shared/Frontpage.css b/Ghidra/Extensions/SampleTablePlugin/src/main/help/help/shared/Frontpage.css index 452bf6e6b5..b8471669f4 100644 --- a/Ghidra/Extensions/SampleTablePlugin/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Extensions/SampleTablePlugin/src/main/help/help/shared/Frontpage.css @@ -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 { 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; } diff --git a/Ghidra/Extensions/sample/src/main/help/help/shared/Frontpage.css b/Ghidra/Extensions/sample/src/main/help/help/shared/Frontpage.css index 452bf6e6b5..b8471669f4 100644 --- a/Ghidra/Extensions/sample/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Extensions/sample/src/main/help/help/shared/Frontpage.css @@ -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 { 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; } diff --git a/Ghidra/Features/Base/certification.manifest b/Ghidra/Features/Base/certification.manifest index f801e96de0..219f7fc8ff 100644 --- a/Ghidra/Features/Base/certification.manifest +++ b/Ghidra/Features/Base/certification.manifest @@ -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| diff --git a/Ghidra/Features/Base/src/main/help/help/shared/Frontpage.css b/Ghidra/Features/Base/src/main/help/help/shared/Frontpage.css index 452bf6e6b5..b8471669f4 100644 --- a/Ghidra/Features/Base/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Features/Base/src/main/help/help/shared/Frontpage.css @@ -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 { 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; } diff --git a/Ghidra/Features/Base/src/main/help/help/shared/helpWarning.png b/Ghidra/Features/Base/src/main/help/help/shared/helpWarning.png deleted file mode 100644 index 8e9133789b0c5f9a2fd7cfd29fce85a35e8fa120..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1354 zcmV-Q1-1H#P)E2L1Q&_V>FBm^-K zqXA4L(MT}7Nc71>ebr!yF~$TFjp&0f`pyGBX@Z#WqA!LtVgSFQAzIM3(C+TcZ0GZO zr#p3;-Bd|wC7$G$b29gyIsbEJ=VM7qiF;{G@jn)DmiRn(VavY+pHdOM#pCd2YY1=- z`{e9@C*VBgBAtI7wVxORB-rf7msy*?8#|=4`j_A$iAZBF26pGD=y)2U?J$BFeKfMf zO91iJ7Z4yPUG}nQe~Msq0GS?$j$;(rcm)@bUo`<~_u|#i>*`{?2LZ1-59@mjp;PFD z5GUh3t0$m_+Wvzj{;E*fm=gVS2z~@xf&2v!E);%(Utdo_FkN`asqs;^&NVGm-YjZ zHD8RgsuEx!bZX$d3dooWc>69TiVnd=-^vI$OL}0j_emel@=PBPHHvYe1gPRtO+n}t z05yd=Zsq|okO^$|VVrw+0*DA5*bvs~QQo;5AWM-HQblFmR#-|v6`%ynK$M0M*mNMy z1raS@z-Q3?fSo~htIo|#Tv$q23IQIiwfwoKmL}=5t zdlug#%3A=cGz72)+^B*)3*=j>V5M=KC+jo|t=tR0hCR5YZ3C8`g1}Pt2@J0syvy^$ z8W&RlbU-rz5{e8U0+{6-h--kZ1Gxx*Y#;$n1e%%<-t5E~{d4Ta<8bd>z$s$bCm!~0 zuwCYT)4<#h044LHm^jG8`z;UY+JI95++-~_*>GBSH|kg9PS(Tsic|C@UYF6G2^fJ< zzZJgC+IqMs{Qh_0)JMu!k?Cr53$8GcSSmmm(_p1;=FLu?79)5FK>ZGW1H{5ke%QO6 z9n*VVKt}^3!A!gc^gmle|M6O~-h{5uLYPAuyh$1j+xVe)vj6@;a+9*w7Z|5C8-{b6 zeg;_5Axoe%c7D{sG7{!Gf1&Hxr$n)5u*U}=r>_5$--_+cA1$o;8_yqS$NWmiMsr;i z&=xvLSk&pvg&c04E@I-160C7^q3d+NNZ=7N_Y>SnZKHpK9R-LjEnpBi=em4N-`GdI zFbN2xXsM5j`M(Nq!aUwDT3VPdniw@;+3PU3u7^7JNnAy?NkH1YJHcKEoSs2*Xfj@D zVeyIE57uFHsqO|s6b{sZ2(8G4SR%72fIDpt)~~VW<65o1fs0g}`G&3;+aBo2Zoag* zUfFaVm+a#!;ASmrLHfnyzq&|rg(*3RZ1bA7P8?peaN3ECO zD&^Ek#qSEtfcW`0mcBAnf{sc=AeHhz8zbi17A@AzSsdxu0^wj3XXKM zTq0&F4i~B>F$-lpVE{Lf$7PI3yJ-SV?|~5zR>Q7BHop(<`QP)u0Nfb>!wJQD)Bpeg M07*qoM6N<$g1EwNvj6}9 diff --git a/Ghidra/Features/Base/src/main/help/help/topics/AutoAnalysisPlugin/AutoAnalysis.htm b/Ghidra/Features/Base/src/main/help/help/topics/AutoAnalysisPlugin/AutoAnalysis.htm index 6080e1a543..fc1f56ae04 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/AutoAnalysisPlugin/AutoAnalysis.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/AutoAnalysisPlugin/AutoAnalysis.htm @@ -5,7 +5,7 @@ - Auto-analysis + Auto Analysis @@ -24,7 +24,7 @@
    -
  1. User Disassembles
  2. +
  3. The user triggers disassembly
  4. Function Analyzer - looks at all calls and creates Functions
  5. @@ -34,9 +34,8 @@
  6. Operand Analyzer - looks at scalar operands for possible address references
  7. Data Reference Analyzer - looks at references for possible strings or pointers to - code.
    - References to code are disassembled.
    - ..... Cycle repeats with 2) as additional code is disassembled.
  8. + code. References to code are disassembled.
    + .....The cycle repeats with 2) as additional code is disassembled.

One program change might cause several Analyzers to become active, however only one @@ -210,46 +209,46 @@

Options

Entry Point Analyzer

diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/label/DemanglerCmd.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/label/DemanglerCmd.java index 40de47106e..612a6fcfa3 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/label/DemanglerCmd.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/label/DemanglerCmd.java @@ -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()) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AbstractDemanglerAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AbstractDemanglerAnalyzer.java index 01a2184080..d64b50f6c0 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AbstractDemanglerAnalyzer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AbstractDemanglerAnalyzer.java @@ -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. + * + *

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. + * + *

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 not 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) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AnalysisOptionsDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AnalysisOptionsDialog.java index 774e58e738..24981b85ce 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AnalysisOptionsDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AnalysisOptionsDialog.java @@ -43,7 +43,7 @@ public class AnalysisOptionsDialog extends DialogComponentProvider implements AnalysisOptionsDialog(Program program) { this(List.of(program)); } - + /** * Constructor * @@ -53,20 +53,20 @@ public class AnalysisOptionsDialog extends DialogComponentProvider implements super("Analysis Options"); setHelpLocation(new HelpLocation("AutoAnalysisPlugin", "AnalysisOptions")); panel = buildComponent(programs); - + addWorkPanel(panel); addOKButton(); addCancelButton(); setOkButtonText("Analyze"); okButton.setMnemonic('A'); setOkEnabled(true); - setPreferredSize(800, 400); - setRememberSize(true); + setPreferredSize(1000, 600); + setRememberSize(true); } @Override public void propertyChange(PropertyChangeEvent evt) { - + // On any analyzer status change, update the options for all programs // being analyzed. This is necessary to keep options consistent across all // programs being analyzed. @@ -75,9 +75,9 @@ 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()); } - } + } @Override public void okCallback() { @@ -94,7 +94,7 @@ public class AnalysisOptionsDialog extends DialogComponentProvider implements boolean wasAnalyzeButtonSelected() { return doAnalysis; } - + /** * Constructs a new {@link AnalysisPanel} * diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AnalysisPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AnalysisPanel.java index c107b8731c..a47cb4795c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AnalysisPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AnalysisPanel.java @@ -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 propertyNames = analysisOptions.getOptionNames(); - Collections.sort(propertyNames, new Comparator() { - @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,25 +321,22 @@ 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) { - if (e.getValueIsAdjusting()) { - return; - } - ListSelectionModel lsm = (ListSelectionModel) e.getSource(); - - int selectedRow = lsm.getMinSelectionIndex(); - if (selectedRow == -1) {//TODO - analyzerOptionsPanel.removeAll(); - analyzerOptionsPanel.validate(); - analyzerOptionsPanel.repaint(); - descriptionComponent.setText(""); - return; - } - String analyzerName = analyzerNames.get(selectedRow); - setAnalyzerSelected(analyzerName); + table.getSelectionModel().addListSelectionListener(e -> { + if (e.getValueIsAdjusting()) { + return; } + ListSelectionModel lsm = (ListSelectionModel) e.getSource(); + + int selectedRow = lsm.getMinSelectionIndex(); + if (selectedRow == -1) {//TODO + analyzerOptionsPanel.removeAll(); + analyzerOptionsPanel.validate(); + analyzerOptionsPanel.repaint(); + descriptionComponent.setText(""); + return; + } + 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 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); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/FindNoReturnFunctionsAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/FindNoReturnFunctionsAnalyzer.java index 4410b560f6..d836946e4d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/FindNoReturnFunctionsAnalyzer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/FindNoReturnFunctionsAnalyzer.java @@ -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,14 +60,14 @@ 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; private boolean createBookmarksEnabled = OPTION_DEFAULT_CREATE_BOOKMARKS_ENABLED; @@ -105,16 +105,16 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer { this.reasonList = new ArrayList<>(); monitor.setMessage("NoReturn - Finding non-returning functions"); - + AddressSet noReturnSet = new AddressSet(); - + boolean hadOtherSuspiciousFunctions = detectNoReturn(program, noReturnSet, set); - + // run again with the new known noReturnSet if (hadOtherSuspiciousFunctions) { detectNoReturn(program, noReturnSet, set); } - + // mark all detected non-returning functions AddressIterator noreturns = noReturnSet.getAddresses(true); for (Address address : noreturns) { @@ -130,12 +130,12 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer { } // repair the damage for all non-returning functions - if (repairDamageEnabled) { + if (repairDamageEnabled) { AddressSet clearInstSet = new AddressSet(); noreturns = noReturnSet.getAddresses(true); for (Address address : noreturns) { clearInstSet.add(findPotentialDamagedLocations(program, address)); - } + } repairDamagedLocations(monitor, clearInstSet); } } @@ -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); } @@ -213,7 +214,7 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer { } } } - + /** * find locations of potential damage from calls to non-returning functions * @@ -278,7 +279,7 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer { if (fallthruAddr == null) { continue; } - + // if location right below is an entry point, don't clear it Address checkAddr = skipNOPS(fallthruAddr); if (program.getSymbolTable().isExternalEntryPoint(checkAddr) || @@ -301,7 +302,7 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer { // entries that are data should not be cleared, only possible bookmarks ClearFlowAndRepairCmd.clearBadBookmarks(program, clearDataSet, monitor); } - + return clearInstSet; } @@ -313,9 +314,9 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer { AddressSet checkedSet = new AddressSet(); boolean hadSuspiciousFunctions = false; - + AddressIterator refIter = - cp.getReferenceManager().getReferenceSourceIterator(checkSet, true); + cp.getReferenceManager().getReferenceSourceIterator(checkSet, true); for (Address address : refIter) { monitor.checkCanceled(); @@ -344,7 +345,7 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer { // detected a calling issue, check other instructions calling the same place Address[] flows = inst.getFlows(); for (Address target : flows) { - + int count = 1; ReferenceIterator refsTo = cp.getReferenceManager().getReferencesTo(target); for (Reference reference : refsTo) { @@ -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; } @@ -375,7 +377,7 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer { break; } } - + // was suspicious, but evidence didn't pass threshold if (count < evidenceThresholdFunctions) { // if function only calls non-returning functions @@ -393,41 +395,42 @@ 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); - + // follow the flow of the instructions // if hit return, then no good // if hit call, check noReturn, if is stop following // if hit place that is called, then stop, and return no-good - - Stack

todo = new Stack
(); + + Stack
todo = new Stack<>(); todo.push(target); AddressSet visited = new AddressSet(); boolean hitNoReturn = false; - + while (!todo.isEmpty()) { Address blockAddr = todo.pop(); CodeBlock block = model.getCodeBlockAt(blockAddr, monitor); - + if (block == null) { return false; - } + } if (visited.contains(blockAddr)) { continue; } visited.add(blockAddr); - + FlowType flowType = block.getFlowType(); if (flowType.isTerminal()) { return false; } - + // if target has a call to it, then can't tell, but suspect... // add all destinations to todo CodeBlockReferenceIterator destinations = block.getDestinations(monitor); - + // no destinations if (!destinations.hasNext()) { return false; @@ -457,7 +460,7 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer { todo.push(destAddr); } } - + return hitNoReturn; } @@ -487,11 +490,11 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer { if (flows != null && flows.length > 0) { target = flows[0]; } - + // 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(); } @@ -514,11 +517,12 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer { reasonList.add(location); return true; } - + /* 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,8 +602,9 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer { protected void fixCallingFunctionBody(Program cp, Address entry) throws CancelledException { if (createBookmarksEnabled) { - cp.getBookmarkManager().setBookmark(entry, BookmarkType.ANALYSIS, - "Non-Returning Function", "Non-Returning Function Found"); + cp.getBookmarkManager() + .setBookmark(entry, BookmarkType.ANALYSIS, + "Non-Returning Function", "Non-Returning Function Found"); } AddressSet fixedSet = new AddressSet(); @@ -666,19 +671,19 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer { if (!instructionAt.getFlowType().isFallthrough()) { return addr; } - + // instruction has PCODE, might not be a NOP PcodeOp[] pcode = instructionAt.getPcode(); if (pcode != null && pcode.length != 0) { // must do an operation, or assign to non-unique for (PcodeOp pCode : pcode) { int opcode = pCode.getOpcode(); - switch(opcode) { - case PcodeOp.LOAD: - case PcodeOp.STORE: - case PcodeOp.CALLOTHER: - case PcodeOp.SEGMENTOP: - return addr; + switch (opcode) { + case PcodeOp.LOAD: + case PcodeOp.STORE: + case PcodeOp.CALLOTHER: + case PcodeOp.SEGMENTOP: + return addr; } Varnode output = pCode.getOutput(); if (output != null && !output.isUnique()) { @@ -686,7 +691,7 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer { } } } - + addr = instructionAt.getFallThrough(); // this shouldn't happen, to have no fallthru, you should have flow, but could be override if (addr == null) { @@ -710,15 +715,15 @@ 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, OPTION_DESCRIPTION_FUNCTION_NONRETURN_THRESHOLD); options.registerOption(OPTION_NAME_REPAIR_DAMAGE, repairDamageEnabled, null, - OPTION_DESCRIPTION_REPAIR_DAMAGE); - + OPTION_DESCRIPTION_REPAIR_DAMAGE); + options.registerOption(OPTION_NAME_CREATE_BOOKMARKS, createBookmarksEnabled, null, OPTION_DESCRIPTION_CREATE_BOOKMARKS); @@ -731,8 +736,8 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer { options.getInt(OPTION_FUNCTION_NONRETURN_THRESHOLD, OPTION_DEFAULT_EVIDENCE_THRESHOLD); repairDamageEnabled = - options.getBoolean(OPTION_NAME_REPAIR_DAMAGE, repairDamageEnabled); - + options.getBoolean(OPTION_NAME_REPAIR_DAMAGE, repairDamageEnabled); + createBookmarksEnabled = options.getBoolean(OPTION_NAME_CREATE_BOOKMARKS, createBookmarksEnabled); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/OperandReferenceAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/OperandReferenceAnalyzer.java index d207148bf2..4f78a810fa 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/OperandReferenceAnalyzer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/OperandReferenceAnalyzer.java @@ -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; @@ -179,7 +145,7 @@ public class OperandReferenceAnalyzer extends AbstractAnalyzer { pointerEnabled = false; addressTablesEnabled = false; } - + // only analyze programs with address spaces > 16 bits int bitSize = defaultAddressSpace.getSize(); return bitSize > 16; @@ -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,8 +500,9 @@ public class OperandReferenceAnalyzer extends AbstractAnalyzer { AddressIterator foundIter = foundCodeBookmarkLocations.getAddresses(true); while (foundIter.hasNext()) { Address target = foundIter.next(); - program.getBookmarkManager().setBookmark(target, BookmarkType.ANALYSIS, - "Found Code", "Found code from operand reference"); + program.getBookmarkManager() + .setBookmark(target, BookmarkType.ANALYSIS, + "Found Code", "Found code from operand reference"); } } @@ -622,8 +590,9 @@ 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, - Disassembler.ERROR_BOOKMARK_CATEGORY, monitor); + program.getBookmarkManager() + .removeBookmarks(set, BookmarkType.ERROR, + Disassembler.ERROR_BOOKMARK_CATEGORY, monitor); } // make sure function created at destination @@ -808,9 +777,10 @@ public class OperandReferenceAnalyzer extends AbstractAnalyzer { if (lastGoodTable != null) { instr.removeOperandReference(opIndex, target); - program.getReferenceManager().addOffsetMemReference(instr.getMinAddress(), - lastGoodTable.getTopAddress(), -((i + 3) * entryLen), RefType.DATA, - SourceType.ANALYSIS, opIndex); + program.getReferenceManager() + .addOffsetMemReference(instr.getMinAddress(), + lastGoodTable.getTopAddress(), -((i + 3) * entryLen), RefType.DATA, + SourceType.ANALYSIS, opIndex); } return lastGoodTable; @@ -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); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/EntryPointAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/EntryPointAnalyzer.java index 8a7782e77b..8fd8b4d85e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/EntryPointAnalyzer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/EntryPointAnalyzer.java @@ -43,7 +43,7 @@ public class EntryPointAnalyzer extends AbstractAnalyzer { private final static String NAME = "Disassemble Entry Points"; private static final String DESCRIPTION = "Disassembles entry points in newly added memory."; - + private final static String OPTION_NAME_RESPECT_EXECUTE_FLAG = "Respect Execute Flag"; private static final String OPTION_DESCRIPTION_RESPECT_EXECUTE_FLAG = @@ -52,7 +52,7 @@ public class EntryPointAnalyzer extends AbstractAnalyzer { private final static boolean OPTION_DEFAULT_RESPECT_EXECUTE_ENABLED = true; private boolean respectExecuteFlags = OPTION_DEFAULT_RESPECT_EXECUTE_ENABLED; - + private AddressSetView executeSet; public EntryPointAnalyzer() { @@ -60,12 +60,11 @@ public class EntryPointAnalyzer extends AbstractAnalyzer { setPriority(AnalysisPriority.BLOCK_ANALYSIS); setDefaultEnablement(true); } - + @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
doNowSet = new HashSet
(); - Set
doLaterSet = new HashSet
(); + Set
doNowSet = new HashSet<>(); + Set
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
dummyFunctionSet = new HashSet
(); - Set
redoFunctionSet = new HashSet
(); + Set
dummyFunctionSet = new HashSet<>(); + Set
redoFunctionSet = new HashSet<>(); findDummyFunctions(program, addressSet, dummyFunctionSet, redoFunctionSet); // disassemble dummy functions now, re-create the function bodies later @@ -150,14 +150,15 @@ public class EntryPointAnalyzer extends AbstractAnalyzer { if (doLaterSet.isEmpty()) { return; } - + // Put off the do-later until later if doing block analysis... if (this.getPriority() == AnalysisPriority.BLOCK_ANALYSIS) { AutoAnalysisManager analysisManager = AutoAnalysisManager.getAnalysisManager(program); 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
redoFunctionSet) throws CancelledException { - Set
recreateFunctionSet = new HashSet
(); + Set
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,8 +234,9 @@ public class EntryPointAnalyzer extends AbstractAnalyzer { while (referencesTo.hasNext()) { Reference reference = referencesTo.next(); Function func = - program.getFunctionManager().getFunctionContaining( - reference.getFromAddress()); + program.getFunctionManager() + .getFunctionContaining( + reference.getFromAddress()); if (func != null) { recreateFunctionSet.add(func.getEntryPoint()); } @@ -246,7 +249,7 @@ public class EntryPointAnalyzer extends AbstractAnalyzer { recreateFunctionSet.add(func.getEntryPoint()); } } - + recreateFunctionSet.add(entry); // Never clear functions that are already created // program.getFunctionManager().removeFunction(entry); @@ -274,7 +277,7 @@ public class EntryPointAnalyzer extends AbstractAnalyzer { laterIter.remove(); continue; } - + // relocation at this place, don't trust it if (program.getRelocationTable().getRelocation(entry) != null) { laterIter.remove(); @@ -340,8 +343,9 @@ public class EntryPointAnalyzer extends AbstractAnalyzer { int defaultPointerSize = program.getDefaultPointerSize(); try { Data data = - program.getListing().createData(entry, - PointerDataType.getPointer(null, defaultPointerSize)); + program.getListing() + .createData(entry, + PointerDataType.getPointer(null, defaultPointerSize)); Object value = data.getValue(); if (value instanceof Address) { Address codeLoc = (Address) value; @@ -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
codeSet = new HashSet
(); + Set
codeSet = new HashSet<>(); AddressIterator aiter = codeProp.getAddresses(); while (aiter.hasNext()) { codeSet.add(aiter.next()); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/SharedReturnAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/SharedReturnAnalyzer.java index 242161f0e5..3ba2b09d09 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/SharedReturnAnalyzer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/SharedReturnAnalyzer.java @@ -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, diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/string/StringsAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/string/StringsAnalyzer.java index 3f3eb928ac..508a06d04b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/string/StringsAnalyzer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/string/StringsAnalyzer.java @@ -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 " + diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/Demangler.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/Demangler.java index 0dd7d84232..ac0519e7aa 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/Demangler.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/Demangler.java @@ -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(); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemanglerUtil.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemanglerUtil.java index a896a61a7d..c51f9d2b9a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemanglerUtil.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemanglerUtil.java @@ -47,9 +47,7 @@ public class DemanglerUtil { List 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; } diff --git a/Ghidra/Features/BytePatterns/ghidra_scripts/BuildFuncDB.java b/Ghidra/Features/BytePatterns/ghidra_scripts/BuildFuncDB.java deleted file mode 100644 index a911cb82b7..0000000000 --- a/Ghidra/Features/BytePatterns/ghidra_scripts/BuildFuncDB.java +++ /dev/null @@ -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; - } -} diff --git a/Ghidra/Features/BytePatterns/src/main/help/help/shared/Frontpage.css b/Ghidra/Features/BytePatterns/src/main/help/help/shared/Frontpage.css index 452bf6e6b5..b8471669f4 100644 --- a/Ghidra/Features/BytePatterns/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Features/BytePatterns/src/main/help/help/shared/Frontpage.css @@ -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 { 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; } diff --git a/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/LibHashDB.java b/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/LibHashDB.java deleted file mode 100644 index 989cdb5fcc..0000000000 --- a/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/LibHashDB.java +++ /dev/null @@ -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 libraries; - - //Empty Constructor - public LibHashDB() { - this.libraries = new TreeSet(); - } - - //Construct a DB from the current program, with a record for every function. - public LibHashDB(Program prgm) throws CancelledException { - this.libraries = new TreeSet(); - 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 getRecords() { - TreeSet results = new TreeSet(); - for (LibraryRecord lib : this.libraries) { - results.addAll(lib.getRecords()); - } - return results; - } - - //Find an entry of the database based on actual underlying function. - public ArrayList query(Function func) throws CancelledException { - FuncRecord queryHash = new FuncRecord(func); - ArrayList result = this.query(queryHash.hashValue); //Use the hash query method instead. - for (FuncRecord entry : result) { - if (entry.func == func) { - ArrayList newResult = new ArrayList(); - 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 query(Long hash) { - ArrayList result = new ArrayList(); //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("\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("\n"); //Finish up. - return; - } -} diff --git a/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/LibraryHashAnalyzer.java b/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/LibraryHashAnalyzer.java deleted file mode 100644 index dedbc2ed8e..0000000000 --- a/Ghidra/Features/BytePatterns/src/main/java/ghidra/app/analyzers/LibraryHashAnalyzer.java +++ /dev/null @@ -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 pinning = new HashMap(); //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 libResponse = db.query(func); - if (libResponse.size() != 1) { //Check uniqueness in libraries. - continue; - } - FuncRecord libVal = libResponse.get(0); - - ArrayList queResponse = qdb.query(libVal.hashValue); - if (queResponse.size() != 1) { //Check uniqueness in query. - continue; - } - FuncRecord queVal = queResponse.get(0); - - pinning.put(queVal, libVal); - } - - PriorityQueue q = new PriorityQueue(pinning.keySet()); - HashSet seen = new HashSet(); - - while (q.size() > 0) { - FuncRecord current = q.remove(); //A query record which is already matched. - seen.add(current); - Iterator qit = current.children.iterator(); - FuncRecord partner = pinning.get(current); - Iterator 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; - } -} diff --git a/Ghidra/Features/ByteViewer/src/main/help/help/shared/Frontpage.css b/Ghidra/Features/ByteViewer/src/main/help/help/shared/Frontpage.css index 452bf6e6b5..b8471669f4 100644 --- a/Ghidra/Features/ByteViewer/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Features/ByteViewer/src/main/help/help/shared/Frontpage.css @@ -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 { 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; } diff --git a/Ghidra/Features/Decompiler/src/main/doc/Frontpage.css b/Ghidra/Features/Decompiler/src/main/doc/Frontpage.css index 452bf6e6b5..b8471669f4 100644 --- a/Ghidra/Features/Decompiler/src/main/doc/Frontpage.css +++ b/Ghidra/Features/Decompiler/src/main/doc/Frontpage.css @@ -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 { 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; } diff --git a/Ghidra/Features/Decompiler/src/main/help/help/shared/Frontpage.css b/Ghidra/Features/Decompiler/src/main/help/help/shared/Frontpage.css index 452bf6e6b5..b8471669f4 100644 --- a/Ghidra/Features/Decompiler/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Features/Decompiler/src/main/help/help/shared/Frontpage.css @@ -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 { 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; } diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/analysis/DecompilerFunctionAnalyzer.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/analysis/DecompilerFunctionAnalyzer.java index c7866df832..912faa9022 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/analysis/DecompilerFunctionAnalyzer.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/analysis/DecompilerFunctionAnalyzer.java @@ -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); diff --git a/Ghidra/Features/FileFormats/src/main/help/help/shared/Frontpage.css b/Ghidra/Features/FileFormats/src/main/help/help/shared/Frontpage.css index 4c4f708c53..b8471669f4 100644 --- a/Ghidra/Features/FileFormats/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Features/FileFormats/src/main/help/help/shared/Frontpage.css @@ -24,13 +24,13 @@ */ -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 way it had been done in the beginning). The net effect is that the text is indented. In @@ -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 { 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; } diff --git a/Ghidra/Features/FunctionGraph/src/main/help/help/shared/Frontpage.css b/Ghidra/Features/FunctionGraph/src/main/help/help/shared/Frontpage.css index 452bf6e6b5..b8471669f4 100644 --- a/Ghidra/Features/FunctionGraph/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Features/FunctionGraph/src/main/help/help/shared/Frontpage.css @@ -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 { 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; } diff --git a/Ghidra/Features/FunctionID/src/main/help/help/shared/Frontpage.css b/Ghidra/Features/FunctionID/src/main/help/help/shared/Frontpage.css index 452bf6e6b5..b8471669f4 100644 --- a/Ghidra/Features/FunctionID/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Features/FunctionID/src/main/help/help/shared/Frontpage.css @@ -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 { 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; } diff --git a/Ghidra/Features/GnuDemangler/ghidra_scripts/DemangleElfWithOptionScript.java b/Ghidra/Features/GnuDemangler/ghidra_scripts/DemangleElfWithOptionScript.java index d355b97543..c4e4988054 100644 --- a/Ghidra/Features/GnuDemangler/ghidra_scripts/DemangleElfWithOptionScript.java +++ b/Ghidra/Features/GnuDemangler/ghidra_scripts/DemangleElfWithOptionScript.java @@ -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 { - String executableFormat = currentProgram.getExecutableFormat(); - if (!canDemangle(executableFormat)) { + GnuDemangler demangler = new GnuDemangler(); + if (!demangler.canDemangle(currentProgram)) { + String executableFormat = currentProgram.getExecutableFormat(); 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); } } diff --git a/Ghidra/Features/GnuDemangler/ghidra_scripts/VxWorksSymTab_5_4.java b/Ghidra/Features/GnuDemangler/ghidra_scripts/VxWorksSymTab_5_4.java index d9a3f92902..47af9fb626 100644 --- a/Ghidra/Features/GnuDemangler/ghidra_scripts/VxWorksSymTab_5_4.java +++ b/Ghidra/Features/GnuDemangler/ghidra_scripts/VxWorksSymTab_5_4.java @@ -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 diff --git a/Ghidra/Features/GnuDemangler/ghidra_scripts/VxWorksSymTab_6_1.java b/Ghidra/Features/GnuDemangler/ghidra_scripts/VxWorksSymTab_6_1.java index c2804f7d56..a58aafd326 100644 --- a/Ghidra/Features/GnuDemangler/ghidra_scripts/VxWorksSymTab_6_1.java +++ b/Ghidra/Features/GnuDemangler/ghidra_scripts/VxWorksSymTab_6_1.java @@ -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 diff --git a/Ghidra/Features/GnuDemangler/ghidra_scripts/VxWorksSymTab_Finder.java b/Ghidra/Features/GnuDemangler/ghidra_scripts/VxWorksSymTab_Finder.java index 6a4a3207e4..4878c8a422 100644 --- a/Ghidra/Features/GnuDemangler/ghidra_scripts/VxWorksSymTab_Finder.java +++ b/Ghidra/Features/GnuDemangler/ghidra_scripts/VxWorksSymTab_Finder.java @@ -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,8 +137,9 @@ 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, - DataTypeConflictHandler.REPLACE_HANDLER); + 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,8 +651,9 @@ public class VxWorksSymTab_Finder extends GhidraScript { if (demangled != null) { new DemanglerCmd(addr, mangled).applyTo(currentProgram, monitor); - currentProgram.getSymbolTable().removeSymbolSpecial( - getSymbol(mangled, currentProgram.getGlobalNamespace())); + currentProgram.getSymbolTable() + .removeSymbolSpecial( + getSymbol(mangled, currentProgram.getGlobalNamespace())); } return; @@ -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()) { diff --git a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/plugin/core/analysis/GnuDemanglerAnalyzer.java b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/plugin/core/analysis/GnuDemanglerAnalyzer.java index 88238bab48..6e34bf7545 100644 --- a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/plugin/core/analysis/GnuDemanglerAnalyzer.java +++ b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/plugin/core/analysis/GnuDemanglerAnalyzer.java @@ -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); } diff --git a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/plugin/core/analysis/GnuDemanglerOptionsPropertyEditor.java b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/plugin/core/analysis/GnuDemanglerOptionsPropertyEditor.java deleted file mode 100644 index 51731b3709..0000000000 --- a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/plugin/core/analysis/GnuDemanglerOptionsPropertyEditor.java +++ /dev/null @@ -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; - } -} diff --git a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/plugin/core/analysis/GnuDemanglerWrappedOption.java b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/plugin/core/analysis/GnuDemanglerWrappedOption.java deleted file mode 100644 index 502f906e13..0000000000 --- a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/plugin/core/analysis/GnuDemanglerWrappedOption.java +++ /dev/null @@ -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 - } -} diff --git a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemangler.java b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemangler.java index b612071096..452e8c2acc 100644 --- a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemangler.java +++ b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemangler.java @@ -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(); diff --git a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerNativeProcess.java b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerNativeProcess.java index a058be8526..a5dcf6e56d 100644 --- a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerNativeProcess.java +++ b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerNativeProcess.java @@ -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 { diff --git a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerOptions.java b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerOptions.java index abf44c2379..1bfc65e8a0 100644 --- a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerOptions.java +++ b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerOptions.java @@ -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 diff --git a/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/plugin/core/analysis/GnuDemanglerAnalyzerTest.java b/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/plugin/core/analysis/GnuDemanglerAnalyzerTest.java new file mode 100644 index 0000000000..476bf0e5cb --- /dev/null +++ b/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/plugin/core/analysis/GnuDemanglerAnalyzerTest.java @@ -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); + } +} diff --git a/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/GnuDemanglerParserTest.java b/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/GnuDemanglerParserTest.java index 5424c41c98..ec7bceda67 100644 --- a/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/GnuDemanglerParserTest.java +++ b/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/GnuDemanglerParserTest.java @@ -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); } diff --git a/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/gnu/GnuDemanglerTest.java b/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/gnu/GnuDemanglerTest.java index 902c64e59d..32874d1ece 100644 --- a/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/gnu/GnuDemanglerTest.java +++ b/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/gnu/GnuDemanglerTest.java @@ -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); diff --git a/Ghidra/Features/GraphFunctionCalls/src/main/help/help/shared/Frontpage.css b/Ghidra/Features/GraphFunctionCalls/src/main/help/help/shared/Frontpage.css index 452bf6e6b5..b8471669f4 100644 --- a/Ghidra/Features/GraphFunctionCalls/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Features/GraphFunctionCalls/src/main/help/help/shared/Frontpage.css @@ -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 { 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; } diff --git a/Ghidra/Features/MicrosoftDemangler/developer_scripts/MicrosoftDemanglerScript.java b/Ghidra/Features/MicrosoftDemangler/developer_scripts/MicrosoftDemanglerScript.java index 3d4e81fb7e..f975186c91 100644 --- a/Ghidra/Features/MicrosoftDemangler/developer_scripts/MicrosoftDemanglerScript.java +++ b/Ghidra/Features/MicrosoftDemangler/developer_scripts/MicrosoftDemanglerScript.java @@ -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); } } diff --git a/Ghidra/Features/MicrosoftDemangler/src/main/java/ghidra/app/plugin/core/analysis/MicrosoftDemanglerAnalyzer.java b/Ghidra/Features/MicrosoftDemangler/src/main/java/ghidra/app/plugin/core/analysis/MicrosoftDemanglerAnalyzer.java index c98ceb23ca..f191e0cb96 100644 --- a/Ghidra/Features/MicrosoftDemangler/src/main/java/ghidra/app/plugin/core/analysis/MicrosoftDemanglerAnalyzer.java +++ b/Ghidra/Features/MicrosoftDemangler/src/main/java/ghidra/app/plugin/core/analysis/MicrosoftDemanglerAnalyzer.java @@ -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"; diff --git a/Ghidra/Features/MicrosoftDemangler/src/main/java/ghidra/app/util/demangler/microsoft/MicrosoftDemangler.java b/Ghidra/Features/MicrosoftDemangler/src/main/java/ghidra/app/util/demangler/microsoft/MicrosoftDemangler.java index 201dbfa52e..41bb8536dc 100644 --- a/Ghidra/Features/MicrosoftDemangler/src/main/java/ghidra/app/util/demangler/microsoft/MicrosoftDemangler.java +++ b/Ghidra/Features/MicrosoftDemangler/src/main/java/ghidra/app/util/demangler/microsoft/MicrosoftDemangler.java @@ -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; -// } } diff --git a/Ghidra/Features/MicrosoftDemangler/src/test/java/ghidra/app/util/demangler/microsoft/MicrosoftDemanglerTest.java b/Ghidra/Features/MicrosoftDemangler/src/test/java/ghidra/app/util/demangler/microsoft/MicrosoftDemanglerTest.java index 79c5b440be..023233c13c 100644 --- a/Ghidra/Features/MicrosoftDemangler/src/test/java/ghidra/app/util/demangler/microsoft/MicrosoftDemanglerTest.java +++ b/Ghidra/Features/MicrosoftDemangler/src/test/java/ghidra/app/util/demangler/microsoft/MicrosoftDemanglerTest.java @@ -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 diff --git a/Ghidra/Features/PDB/src/main/help/help/shared/Frontpage.css b/Ghidra/Features/PDB/src/main/help/help/shared/Frontpage.css index 452bf6e6b5..b8471669f4 100644 --- a/Ghidra/Features/PDB/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Features/PDB/src/main/help/help/shared/Frontpage.css @@ -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 { 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; } diff --git a/Ghidra/Features/ProgramDiff/src/main/help/help/shared/Frontpage.css b/Ghidra/Features/ProgramDiff/src/main/help/help/shared/Frontpage.css index 452bf6e6b5..b8471669f4 100644 --- a/Ghidra/Features/ProgramDiff/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Features/ProgramDiff/src/main/help/help/shared/Frontpage.css @@ -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 { 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; } diff --git a/Ghidra/Features/Python/src/main/help/help/shared/Frontpage.css b/Ghidra/Features/Python/src/main/help/help/shared/Frontpage.css index 452bf6e6b5..b8471669f4 100644 --- a/Ghidra/Features/Python/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Features/Python/src/main/help/help/shared/Frontpage.css @@ -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 { 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; } diff --git a/Ghidra/Features/SourceCodeLookup/src/main/help/help/shared/Frontpage.css b/Ghidra/Features/SourceCodeLookup/src/main/help/help/shared/Frontpage.css index 452bf6e6b5..b8471669f4 100644 --- a/Ghidra/Features/SourceCodeLookup/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Features/SourceCodeLookup/src/main/help/help/shared/Frontpage.css @@ -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 { 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; } diff --git a/Ghidra/Features/VersionTracking/src/main/help/help/shared/Frontpage.css b/Ghidra/Features/VersionTracking/src/main/help/help/shared/Frontpage.css index 452bf6e6b5..b8471669f4 100644 --- a/Ghidra/Features/VersionTracking/src/main/help/help/shared/Frontpage.css +++ b/Ghidra/Features/VersionTracking/src/main/help/help/shared/Frontpage.css @@ -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 { 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; } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/CustomOptionComponent.java b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/CustomOptionComponent.java index c55e2be6e8..75ac057733 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/options/editor/CustomOptionComponent.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/options/editor/CustomOptionComponent.java @@ -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 class is designed to let the editor component handle the display and editing - add( editorState.getEditorComponent() ); - } + // this layout allows us to easily left-align the single component in this container + setLayout(new HorizontalLayout(0)); - @Override - protected Dimension getPreferredAlignmentSize() { - return new Dimension( 0, 0 ); - } + // this class is designed to let the editor component handle the display and editing + add(editorState.getEditorComponent()); + } + + @Override + protected Dimension getPreferredAlignmentSize() { + return new Dimension(0, 0); + } } diff --git a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/util/demangler/gnu/GnuDemanglerIntegrationTest.java b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/util/demangler/gnu/GnuDemanglerIntegrationTest.java index c439821a3b..67de329e85 100644 --- a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/util/demangler/gnu/GnuDemanglerIntegrationTest.java +++ b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/util/demangler/gnu/GnuDemanglerIntegrationTest.java @@ -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 diff --git a/GhidraBuild/Skeleton/src/main/help/help/shared/Frontpage.css b/GhidraBuild/Skeleton/src/main/help/help/shared/Frontpage.css index 452bf6e6b5..b8471669f4 100644 --- a/GhidraBuild/Skeleton/src/main/help/help/shared/Frontpage.css +++ b/GhidraBuild/Skeleton/src/main/help/help/shared/Frontpage.css @@ -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 { 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; } diff --git a/GhidraDocs/languages/html/Frontpage.css b/GhidraDocs/languages/html/Frontpage.css index 4c4f708c53..b8471669f4 100644 --- a/GhidraDocs/languages/html/Frontpage.css +++ b/GhidraDocs/languages/html/Frontpage.css @@ -24,13 +24,13 @@ */ -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 way it had been done in the beginning). The net effect is that the text is indented. In @@ -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 { 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; }