Closed sbrptdev2 closed 1 week ago
Taking a peek at this trace, this code seems to have a bug in it (but this bug does not explain this stack trace):
@Override
protected void dispose() {
FrontEndService frontEnd = tool.getService(FrontEndService.class);
frontEnd.addProjectListener(this);
Project activeProject = tool.getProjectManager().getActiveProject();
if (activeProject != null) {
projectClosed(activeProject);
}
}
I believe the call to addProjectListener()
should be removeProjectListener()
The code above does not expect the frontEnd
to be null at the time of disposal. I'm guessing that there is some other exception happening that is causing the front end to be cleared inside tool so that the call the tool.getService()
is failing.
This is happening with and without loading the extension being developed (just tested again).
It might be a separate issue but there is also no way to verify why a given plugin might not be loaded (or I don't see how to enable verbose output for the ClassSearch -which I guess is responsible for it-). I was about to test this one more time but the extension I am working on simply ceased to load. It compiles just fine and no out of the norm changes have been applied to its ProgramPlugin class.
You can enable logging for the ClassSearcher and Extension related packages to get more details on what is happening during the load process. These packages have embedded trace() messages that you may find helpful.
Changing the log levels varies by development setup. Are you running from a pull of the repo, using the source code inside of Eclipse? Or are you building Ghidra from source code and then using that to write your own code?
Yes, using Eclipse, replicated the instructions in "Building" and "Advanced Development".
Currently developing the extension that way, until there is a need to make a PR for integration. Haven't done any modifications to the Ghidra sources as-is.
Testing now with the above PR #6939 modifying the extension's run configuration like so:
-Dlog4j.configurationFile=file:BASEPATH/ghidra/Ghidra/Framework/Generic/src/main/resources/generic.log4jdev.xml
Unfortunately, still at the same spot:
TRACE Using restricted extension class loader? false (ClassSearcher.java:109)
INFO Searching for classes... (ClassSearcher.java:409)
TRACE Searching jar file: REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Framework/Utility/lib/Utility.jar (ClassSearcher.java:425)
TRACE Scanning module root directories: [REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/6502, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/68000, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/8048, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/8051, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/8085, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/AARCH64, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/ARM, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Debug/AnnotationValidator, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/Atmel, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/BPF, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/BSim, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/BSimFeatureVisualizer, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/Base, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/BytePatterns, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/ByteViewer, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/CP1600, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/CR16, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/CodeCompare, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/DATA, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Framework/DB, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/../GPL/DMG, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/Dalvik, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/DebugUtils, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Debug/Debugger, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Debug/Debugger-agent-dbgeng, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Debug/Debugger-agent-dbgmodel, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Debug/Debugger-agent-dbgmodel-traceloader, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Debug/Debugger-agent-frida, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Debug/Debugger-agent-gdb, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Debug/Debugger-agent-lldb, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Debug/Debugger-api, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Debug/Debugger-gadp, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Debug/Debugger-isf, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Debug/Debugger-jpda, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Debug/Debugger-rmi-trace, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Debug/Debugger-swig-lldb, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/Decompiler, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/DecompilerDependent, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/../GPL/DemanglerGnu, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Framework/Docking, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Framework/Emulation, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/FileFormats, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Framework/FileSystem, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Debug/Framework-AsyncComm, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Debug/Framework-Debugging, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Debug/Framework-TraceModeling, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/FunctionGraph, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/FunctionGraphDecompilerExtension, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/FunctionID, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Framework/Generic, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/GhidraGo, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/GhidraServer, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/GnuDemangler, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Framework/Graph, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/GraphFunctionCalls, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/GraphServices, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Framework/Gui, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/HCS08, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/HCS12, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Framework/Help, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/JVM, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/Jython, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/Loongarch, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/M16C, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/M8C, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/MC6800, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/MCS96, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/MIPS, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/MicrosoftCodeAnalyzer, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/MicrosoftDemangler, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/MicrosoftDmang, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/PA-RISC, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/PDB, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/PIC, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/PowerPC, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/ProgramDiff, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/ProgramGraph, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Framework/Project, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Debug/ProposedUtils, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Framework/Pty, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Configurations/Public_Release, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/PyGhidra, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/RISCV, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/Recognizers, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/Sarif, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Framework/SoftwareModeling, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/SourceCodeLookup, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/Sparc, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/SuperH, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/SuperH4, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/SwiftDemangler, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/SystemEmulation, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/TI_MSP430, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Debug/TaintAnalysis, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Framework/Utility, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/V850, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/VersionTracking, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/VersionTrackingBSim, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Features/WildcardAssembler, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/Xtensa, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/Z80, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/eBPF, REDACTED/extensions/ghidra-yara/ghidra_yara, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/tricore, REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/Processors/x86] (ClassSearcher.java:558)
TRACE Using extension point pattern: .*(TypeMapper|FieldFactory|VMInstruction|Constraint|FieldMouseHandler|ChecksumAlgorithm|FormatModel|ResultHandler|Analyzer|Exporter|DisassemblyInject|ContentHandler|ElfExtension|DebuggerMappingOpinion|PluginPackage|FSBFileHandler|FileSystem|TraceRmiLaunchOpinion|ProjectDataColumn|PcodeStateInitializer|Stringable|DebuggerProgramLaunchOpinion|RelocationFixupHandler|CodeComparisonPanTRACE Using extension point pattern: .*(TypeMapper|FieldFactory|VMInstruction|Constraint|FieldMouseHandler|ChecksumAlgorithm|FormatModel|ResultHandler|Analyzer|Exporter|DisassemblyInject|ContentHandler|ElfExtension|DebuggerMappingOpinion|PluginPackage|FSBFileHandler|FileSystem|TraceRmiLaunchOpinion|ProjectDataColumn|PcodeStateInitializer|Stringable|DebuggerProgramLaunchOpinion|RelocationFixupHandler|CodeComparisonPanel|DebuggerRegisterColumnFactory|DebuggerClientFactory|StringHandler|AutoReadMemorySpec|TableColumn|ProgramCorrelator|ProgramCorrelatorFactory|Recognizer|ElfInfoProducer|ToolAssociation|Initializer|LanguageTranslator|AutoMapSpec|InstructionSkipper|DebuggerBot|GraphExporter|Demangler|DebuggerPcodeEmulatorFactory|CoffRelocationHandler|FileSystemModel|BinaryAnalysisCommand|DWARFFunctionFixup|Loader|TableRowMapper|AddressCorrelatorFactory|RunHandler|GhidraProtocolHandler|GraphDisplayProvider|LocationTrackingSpecFactory|DataType|DataTypeReferenceFinder|AnnotationHandler|ScriptProvider|Decryptor|DebuggerPlatformOpinion|AddressCorrelator|OverviewColorService|DebuggerModelFactory|LayoutProvider|MachoRelocationHandler|ColumnConstraintProvider|Theme|ElfRelocationHandler|Validator|Plugin|RelocationHandler)$ (ClassSearcher.java:611)
el|DebuggerRegisterColumnFactory|DebuggerClientFactory|StringHandler|AutoReadMemorySpec|TableColumn|ProgramCorrelator|ProgramCorrelatorFactory|Recognizer|ElfInfoProducer|ToolAssociation|Initializer|LanguageTranslator|AutoMapSpec|InstructionSkipper|DebuggerBot|GraphExporter|Demangler|DebuggerPcodeEmulatorFactory|CoffRelocationHandler|FileSystemModel|BinaryAnalysisCommand|DWARFFunctionFixup|Loader|TableRowMapper|AddressCorrelatorFactory|RunHandler|GhidraProtocolHandler|GraphDisplayProvider|LocationTrackingSpecFactory|DataType|DataTypeReferenceFinder|AnnotationHandler|ScriptProvider|Decryptor|DebuggerPlatformOpinion|AddressCorrelator|OverviewColorService|DebuggerModelFactory|LayoutProvider|MachoRelocationHandler|ColumnConstraintProvider|Theme|ElfRelocationHandler|Validator|Plugin|RelocationHandler)$ (ClassSearcher.java:611)
TRACE Searching classpath directory: REDACTED/extensions/ghidra-yara/ghidra_yara/bin/main (ClassSearcher.java:429)
TRACE Searching classpath directory: REDACTED/ghidra/build/dist/ghidra_11.3_DEV/Ghidra/patch (ClassSearcher.java:429)
TRACE Ignoring jar file: REDACTED/extensions/ghidra-yara/ghidra_yara/lib/libyara-4.5.2-SNAPSHOT-linux64.jar (ClassSearcher.java:421)
TRACE Ignoring jar file: REDACTED/extensions/ghidra-yara/ghidra_yara/lib/libyara-4.5.2-SNAPSHOT.jar (ClassSearcher.java:421)
TRACE Ignoring jar file: REDACTED/extensions/ghidra-yara/ghidra_yara/lib/original-libyara-4.5.2-SNAPSHOT.jar (ClassSearcher.java:421)
The error still manifests when closing Ghidra, and also the Plugin class does not load (but the Analyzer does). The extension point pattern should match.
Also after gradle cleanEclipse eclipse
(and doing a workspace-wide refresh and build) the AbstractAnalyzer class (from Ghidra) appears missing to Eclipse. I do think we need more documentation for all the possible quirks and problems with the development environment. You obviously have become accustomed to these over the years and curated a significant amount of knowhow in dealing with them, but to outsiders these toolchain "heisenbugs" can be mistifying.
Until I can figure out why the extension is no longer being "found" and loaded in its entirety, I can't re-test the exception. It still occurs without loading it, so I might test the modification you suggested. I do agree that this should have manifested for other people before, something else is amiss.
The search continues...
I do think we need more documentation for all the possible quirks and problems with the development environment. You obviously have become accustomed to these over the years and curated a significant amount of knowhow in dealing with them, but to outsiders these toolchain "heisenbugs" can be mistifying.
So true. (Imagine how hard it is to keep all of this straight when you remember all the old ways of configuring and building that we have had over the decades.) There was a point where this dev process was simple. Things used to be easy when all of the code lived in one Eclipse project, with a simple Ant build system. As with software design, flexibility comes at a cost of understandability. We are very flexible now. So much that it feels near impossible to keep the entirety of the system in your head. Situations like yours are especially difficult for me, since I don't develop extensions regularly. I agree that we should have much better documentation for the happy paths of scripting development, as well as some basic troubleshooting steps.
Not sure if you are running into this or not, but for me, Eclipse has become quite flaky over the years. I pretty regularly get odd compile errors that eventually just go away. Regarding your Plugin not being loaded, it seems like your path is correct, based on the traces. I can't tell if you have all tracing on inside of the ghidra.util.classfinder
package. There are more fine-grained messages that will show the actually directories being processed. Some things that may help (excuse me if they are already obvious to you; it sounds like you have done some of this):
gradle cleanEclipse eclipse
will ensure that your project and classpath files are created, are up to date with the directory contents, and can then be imported into Eclipse.bin
directory by using the Project Explorer window in Eclipse.Plugin
, then it should get loaded as long as it is in the classpath (which the tracing should verify). If needed, you can debug this using ClassSearcher.loadExtensionPoint()
, with conditional breakpoints for your class or even by altering the code and adding your own prints for when your class is encountered.File -> Configure
menu. The easiest thing to do in that GUI is to click the plug icon on the toolbar to show all found Plugins, then use the filter to find yours in the list, ensuring it is checked.Quick response:
gradle cleanEclipse eclipse will ensure that your project and classpath files are created, are up to date with the directory contents, and can then be imported into Eclipse.
This was done always whenever touching the source (ex. pulls).
If you already have imported the projects, and then use the gradle command again, you must refresh all of the projects inside of Eclipse by selecting your projects and pressing F5 or using the right-click menu and pressing 'Refresh'. Eclipse is slow to pick up changes to the generated project files, so refreshing helps.
Noticed this, as nonsensical as it might be considering it's 2024 and there are a million ways (inotify and all) to watch filesystem activity to trigger a refresh.
You should be able to verify that your plugin class has been compiled and lives inside of your project's bin directory by using the Project Explorer window in Eclipse.
They are present but have not been rebuilt in a few days. Odd.
$ tree bin
bin
├── main
│ ├── ghidra_yara
│ │ ├── GhidraYaraAnalyzer.class
│ │ ├── GhidraYaraComponent$1.class
│ │ ├── GhidraYaraComponent.class
│ │ ├── GhidraYaraPlugin.class
│ │ ├── GhidraYaraRule.class
│ │ ├── GhidraYaraRuleTableModel.class
│ │ ├── IterableHelper.class
│ │ ├── ScanMethod.class
│ │ ├── Utils.class
│ │ ├── YaraRuleTableProvider$YaraRuleTableContextMenuAction.class
│ │ └── YaraRuleTableProvider.class
│ ├── help
│ │ ├── TOC_Source.xml
│ │ └── topics
│ │ └── ghidra_yara
│ │ └── help.html
│ └── images
│ └── README.txt
├── scripts
│ └── README.txt
└── test
└── README.test.txt
Removing them entirely, and refreshing does not repopulate the project.
Nothing shows up in Configure as expected, as it isn't loaded.
If your plugin class name ends with Plugin, then it should get loaded as long as it is in the classpath (which the tracing should verify). If needed, you can debug this using ClassSearcher.loadExtensionPoint(), with conditional breakpoints for your class or even by altering the code and adding your own prints for when your class is encountered.
Yes, GhidraYaraPlugin. We can give you access to the private repository (it will be released when it is ready for public consumption in any case) if you want to test yourself.
After cleaning up bin
:
$ tree
.
├── bin
├── build.gradle
├── data
│ ├── README.txt
│ └── rules
│ ├── findcrypt3.yar
│ ├── packer.yar
│ ├── peid.yar
│ ├── README.md
│ └── signsrch
│ └── signsrch_le_be.yar
├── extension.properties
├── ghidra_scripts
│ └── README.txt
├── lib
│ ├── libyara-4.5.2-SNAPSHOT.jar
│ ├── libyara-4.5.2-SNAPSHOT-linux64.jar
│ ├── original-libyara-4.5.2-SNAPSHOT.jar
│ └── README.txt
├── LICENSE
├── Module.manifest
├── os
│ ├── linux_x86_64
│ │ └── README.txt
│ ├── mac_x86_64
│ │ └── README.txt
│ └── win_x86_64
│ └── README.txt
└── src
├── main
│ ├── help
│ │ └── help
│ │ ├── TOC_Source.xml
│ │ └── topics
│ │ └── ghidra_yara
│ │ └── help.html
│ ├── java
│ │ └── ghidra_yara
│ │ ├── GhidraYaraAnalyzer.java
│ │ ├── GhidraYaraComponent.java
│ │ ├── GhidraYaraPlugin.java
│ │ ├── GhidraYaraRule.java
│ │ ├── GhidraYaraRuleTableModel.java
│ │ ├── IterableHelper.java
│ │ ├── ScanMethod.java
│ │ ├── Utils.java
│ │ └── YaraRuleTableProvider.java
│ └── resources
│ └── images
│ └── README.txt
└── test
└── java
└── README.test.txt
Building out of band with gradle:
ghidra_yara (main)
$ gradle
> Task :buildExtension
Created ghidra_11.3_DEV_20240921_ghidra_yara.zip in /.../ghidra/extensions/ghidra-yara/ghidra_yara/dist
BUILD SUCCESSFUL in 4s
7 actionable tasks: 7 executed
Keeping things sane for now, I have not added the Maven package dependency from our Github package repository (but that is entirely public and there is CI to autobuild things for linux64). Instead, the jars are copied directly. I know they are the correct ones.
Edit:
And:
After "Link with Ghidra", which is not documented anywhere but seemed like a good candidate to try.
It seems like the issue is that Eclipse is not building your source for your project. This could be that the project's source inclusions are not setup correctly. Or, it could just be some flakiness of Eclipse, sadly. The project structure looks good to me. You can try deleting and re-importing the project (without deleting the contents) to see if that will force Eclipse to recompile.
Regarding the issues of running Ghidra, @ryanmkurtz is more up to speed with that.
Indeed. Got it:
So, turns out the linking with Ghidra is needed (no surprise there, as you are essentially telling gradle internally where to find the GHIDRA_INSTALL_DIR... but this is odd, as it should be immediately provided by Run As (Ghidra).
The error related to Jython is also strange, as I have the correct PyDev 9.3 packages. Even more odd is that Eclipse happily finalizes the configuration despite the error, so closing the dialog and refreshing, and then re-running 'Run As' worked happily. Eclipse is truly an enterprise class environment. All the frustration, none of the basic decency of telling you why it takes a piss when it does. Alas....
Now we are back to a working point where I can check your suggestion regarding the frontEnd exception.
Eclipse is truly an enterprise class environment. All the frustration, none of the basic decency of telling you why it takes a piss when it does. Alas....
Agreed. I do think Eclipse's best days are 15+ years ago.
@dragonmacher So, preliminary debugging:
frontEnd is indeed null, replacing the call for removeProjectListener yields the same situation however:
java.lang.NullPointerException: Cannot invoke "ghidra.framework.main.FrontEndService.removeProjectListener(ghidra.framework.model.ProjectListener)" because "frontEnd" is null
I'm still trying to figure out where Eclipse hides the stack trace/call tree in the debugger. It must be the famed Java println debugging system being forced on me.
I'm assuming you want to open the Debug
view, which is where the threads are shown, along with breakpoint controls (which area also in the main window toolbar).
Honestly, print statements are my usual go to, since we are heavily multithreaded.
As mentioned before, I think there is some other initialization failure happening, which is polluting Ghidra's tear down process.
Some notes:
From PluginManager, where the plugin list is iterated and the cleanup method gets called:
void dispose() {
for (Iterator<Plugin> it = pluginList.iterator(); it.hasNext();) {
Plugin plugin = it.next();
plugin.cleanup();
it.remove();
}
}
Up to the point where DomainFolderChangesDisplayPlugin.dispose() gets called nothing seems out of the norm.
Looking at services
from the FrontEndPlugin
the list is pretty empty, only [0] ServiceInterfaceImplementationPair (id=495)
remains at the time the dispose() method is called and frontEnd is returned as null from getService()
.
I don't know if this is the expected state, and I'm not sure if adding a check for null returns on getService()
makes sense (as you say, this might be an issue elsewhere and the throwable handling in this later callstack is doing its job).
Nervemind, FrontendPlugin
is getting disposed of before the offending plugin:
Is this the correct behavior? I have no knowledge of the internals of Ghidra's handling inter-plugin dependency. In any case, it makes sense that any services provided by FrontendPlugin will not be there anymore past the lifetime of 'FrontendPlugin' itself.
Another edit:
Indeed, disposed=true for this$0 FrontEndPlugin (id=137)
, and its services list is mostly empty with only [0] ServiceInterfaceImplementationPair (id=558)
left in place. The 9 other services are disposed/null.
The commit (https://github.com/subreption/ghidra/commit/50aa3dfef20e3101aad22d90a511eeb09fe2b545) in our fork seems to fix the manifestation of this issue at least for the DomainFolderChangesDisplayPlugin
. Just tested on my local build. No apparent side-effects.
It's quite possible that this is a latent issue that we have simply not encountered. I don't recall, but I would expect that dependents would be disposed before their dependencies. Even that could lead to arbitrary behavior if the dependency tree is complicated. The odd thing to me in this case is that I would expect the Front End to be disposed last of all, since that is the main entry into the system. But, it's possible that we do not have any special code to make this the case.
I will investigate more to see how this is all wired now.
Agreed, appreciated. Back to the extension work here, will keep an eye on this issue however.
Describe the bug
I'm encountering this exception when closing the Ghidra process via exit menu, while developing an extension with Eclipse. There is no indication to the actual source of the problem that I can see, and searching for occurrences of this exception yields nothing.
Expected behavior Clean exit.