NationalSecurityAgency / ghidra

Ghidra is a software reverse engineering (SRE) framework
https://www.nsa.gov/ghidra
Apache License 2.0
52.21k stars 5.91k forks source link

Ghidra 10.2.2 failed to load LLDB 14.0.0 Binding library liblldb-java.a on Linux with java.library.path set to include liblldb-java.a #4884

Closed Zimm3r closed 1 year ago

Zimm3r commented 1 year ago

Issue: Debugger > Debug helloworld > in LLDB locally IN-VM > Connect fails to load the LIBLLDB-JAVA library bindings for LIBLLDB.

2023-01-10 07:46:48 ERROR agent.lldb.manager.impl.LldbManagerImpl java.library.path => /home/nibble/Downloads/llvm-project-llvmorg-14.0.0/build/lib/:/home/nibble/ghidra_10.2.2_PUBLIC/Ghidra/Debug/Debugger-swig-lldb/build/libs/main/static/linux_x86_64  
2023-01-10 07:46:48 ERROR agent.lldb.manager.impl.LldbManagerImpl liblldb-java not found - add relevant java.library.path to support/launch.properties  
2023-01-10 07:46:48 ERROR ghidra.SwingExceptionHandler Error: Uncaught Exception! 
UnsatisfiedLinkError - 'int SWIG.lldbJNI.SBTarget_eBroadcastBitBreakpointChanged_get()' java.lang.UnsatisfiedLinkError: 'int SWIG.lldbJNI.SBTarget_eBroadcastBitBreakpointChanged_get()'
    at SWIG.lldbJNI.SBTarget_eBroadcastBitBreakpointChanged_get(Native Method)
    at SWIG.SBTarget.<clinit>(SBTarget.java:562)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:375)
    at jdk.proxy2/jdk.proxy2.$Proxy52.<clinit>(Unknown Source)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
    at java.base/java.lang.reflect.Proxy.newProxyInstance(Proxy.java:1053)
    at java.base/java.lang.reflect.Proxy.newProxyInstance(Proxy.java:1039)
    at ghidra.util.datastruct.ListenerMap.<init>(ListenerMap.java:212)
    at ghidra.util.datastruct.ListenerSet$1.<init>(ListenerSet.java:59)
    at ghidra.util.datastruct.ListenerSet.<init>(ListenerSet.java:59)
    at ghidra.util.datastruct.ListenerSet.<init>(ListenerSet.java:49)
    at agent.lldb.manager.impl.LldbManagerImpl.<init>(LldbManagerImpl.java:96)
    at agent.lldb.manager.LldbManager.newInstance(LldbManager.java:58)
    at agent.lldb.model.impl.LldbModelImpl.<init>(LldbModelImpl.java:70)
    at agent.lldb.LldbInJvmDebuggerModelFactory.build(LldbInJvmDebuggerModelFactory.java:41)
    at ghidra.app.plugin.core.debug.service.model.DebuggerConnectDialog.connect(DebuggerConnectDialog.java:242)
    at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972)

Environment Details:

Ghidra Version:

application.name=Ghidra
application.version=10.2.2
application.release.name=PUBLIC
application.layout.version=1
application.gradle.min=7.3
application.java.min=17
application.java.max=
application.java.compiler=17
application.build.date=2022-Nov-15 1249 EST
application.build.date.short=20221115
application.revision.ghidra=9813cde2db1f31f92fed49a4dd8aa29b21d72581
application.revision.ghidra.bin=44ca5b263a955ba19ec4f57a5646d4a406a34f70

Java Version:

$ java --version
openjdk 17.0.5 2022-10-18
OpenJDK Runtime Environment (build 17.0.5+8-Ubuntu-2ubuntu122.04)
OpenJDK 64-Bit Server VM (build 17.0.5+8-Ubuntu-2ubuntu122.04, mixed mode, sharing)

LLDB Version:

lldb version 14.0.0

Unix Version:

$ uname -a
Linux Ubunutu 5.15.0-57-generic #63-Ubuntu SMP Thu Nov 24 13:43:17 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

Library and Loading Details

LIBLLDB does not report failing (with a ‘bad’ java.library.path it does report failing) so I assume it succeeded.

LIBLLDB-JAVA fails with the following error, UnsatisfiedLinkError - 'int SWIG.lldbJNI.SBProcess_eBroadcastBitStateChanged_get()' java.lang.UnsatisfiedLinkError: 'int SWIG.lldbJNI.SBProcess_eBroadcastBitStateChanged_get()'

java.library.path reported by Ghidra Log agent.lldb.manager.impl.LldbManagerImpl java.library.path => /home/nibble/Downloads/llvm-project-llvmorg-14.0.0/build/lib/:/home/nibble/ghidra_10.2.2_PUBLIC/Ghidra/Debug/Debugger-swig-lldb/build/libs/main/static/linux_x86_64

/home/nibble/Downloads/llvm-project-llvmorg-14.0.0/build/lib/ - contains liblldb.so

$ ls -lsa /home/nibble/Downloads/llvm-project-llvmorg-14.0.0/build/lib/liblldb.so*
     0 lrwxrwxrwx 1 nibble nibble        13 Jan  8 21:13 /home/nibble/Downloads/llvm-project-llvmorg-14.0.0/build/lib/liblldb.so -> liblldb.so.14
     0 lrwxrwxrwx 1 nibble nibble        17 Jan  8 21:13 /home/nibble/Downloads/llvm-project-llvmorg-14.0.0/build/lib/liblldb.so.14 -> liblldb.so.14.0.0
158064 -rwxrwxr-x 1 nibble nibble 161850496 Jan  8 21:13 /home/nibble/Downloads/llvm-project-llvmorg-14.0.0/build/lib/liblldb.so.14.0.0

/home/nibble/ghidra_10.2.2_PUBLIC/Ghidra/Debug/Debugger-swig-lldb/build/libs/main/static/linux_x86_64 – contains liblldb-java.a

$ ls -lsa /home/nibble/ghidra_10.2.2_PUBLIC/Ghidra/Debug/Debugger-swig-lldb/build/libs/main/static/linux_x86_64
total 1404
   4 drwxrwxr-x 2 nibble nibble    4096 Jan 10 02:41 .
   4 drwxrwxr-x 3 nibble nibble    4096 Jan  8 18:30 ..
1396 -rw-rw-r-- 1 nibble nibble 1425514 Jan 10 00:56 liblldb-java.a

Using nm the library does contain what I assume is the matching C/C++ side function

$ nm /home/nibble/ghidra_10.2.2_PUBLIC/Ghidra/Debug/Debugger-swig-lldb/build/libs/main/static/linux_x86_64/liblldb-java.a | grep eBroadcastBitStateChanged
0000000000024c50 T Java_SWIG_lldbJNI_SBProcess_1eBroadcastBitStateChanged_1get  

I have also run Ghidra with -verbose:jni using $ ./launch.sh debug jdk ghidraconsole "" "-verbose:jni" ghidra.GhidraRun which didn’t seems to add any more useful data.

I also tried setting the LD_LIBRARY_PATH to the folder of the liblldb-java file as well as having the java.library.path set to both the liblldb and liblldb-java folders and that didn’t change anything.

Also this is the only liblldb-java file on the system (SWIG mentioned a common issue of loading multiple of the same library)

$ sudo find / -name *lib*lldb*java* 
/home/nibble/ghidra_10.2.2_PUBLIC/Ghidra/Debug/Debugger-swig-lldb/build/libs/main/static/linux_x86_64/liblldb-java.a
find: ‘/run/user/1000/doc’: Permission denied
find: ‘/run/user/1000/gvfs’: Permission denied
d-millar commented 1 year ago

@Zimm3r Hi and apologies - probably not completely clear in the documentation, but you need to point java.library.path at the dynamic library locations. Java won't load static libraries, as far as I know. Liblldb-java.so should reside in Ghidra/Debug/Debugger-swig-lldb/build/os/linux_x86_64 or possibly .../bin/build/os/linux_x86_64.

Zimm3r commented 1 year ago

@d-millar

So looking at the build I do have a static version of the library (.a) and I do have a shared folder but no actual shared library version (.so). Is there some build setting I have to change to get that?

$ find . -name '*'
.
./shared
./shared/linux_x86_64
./static
./static/linux_x86_64
./static/linux_x86_64/liblldb-java.a

Also, my fault for not mentioning this, I did look into Java supporting shared vs static libraries and I thought it did support static libraries?

https://stackoverflow.com/questions/24493337/linking-static-library-with-jni

https://openjdk.org/jeps/178

Update

Added -shared to the gradle gccCompiler arguments and it does seem to generate a so file, I'll test to see if it works

                if (b.toolChain in Gcc) {
                    b.cppCompiler.args "-I$llvm_dir/lldb/include"
                    b.cppCompiler.args "-I${JAVA_HOME}/include"
                    b.cppCompiler.args "-shared" // generated shared library?
                    b.linker.args "-L$llvm_build_dir/lib"           
                    b.linker.args "-llldb"          
                    b.cppCompiler.args "-std=c++14"
                    b.cppCompiler.args "-O3"
                    // b.cppCompiler.args "-g"      // for DEBUG, uncomment this line
                }

Update

Set my java.library.path to

VMARGS=-Djava.library.path=/home/nibble/Downloads/llvm-project-llvmorg-14.0.0/build/lib/:/home/nibble/ghidra_10.2.2_PUBLIC/Ghidra/Debug/Debugger-swig-lldb/build/os/linux_x86_64/

Where /home/nibble/ghidra_10.2.2_PUBLIC/Ghidra/Debug/Debugger-swig-lldb/build/os/linux_x86_64/ contains the shared library version of liblldb-java

$ find ~/ghidra_10.2.2_PUBLIC/Ghidra/Debug/Debugger-swig-lldb/ -name *liblldb-java*
/home/nibble/ghidra_10.2.2_PUBLIC/Ghidra/Debug/Debugger-swig-lldb/build/libs/main/static/linux_x86_64/liblldb-java.a
/home/nibble/ghidra_10.2.2_PUBLIC/Ghidra/Debug/Debugger-swig-lldb/build/os/linux_x86_64/liblldb-java.so
d-millar commented 1 year ago

Hmmm, I don't recognize your file structure at all - you're listing directories in Debugger-swig-lldb? What was your build process? Did you run "gradle build"? I'm running on the same version of Ubuntu with the same versions of Ghidra, Java, and lldb, and nothing I'm doing generates "shared" or "static".

d-millar commented 1 year ago

OK, I think you're doing way more work than you need to, i.e. you shouldn't have to modify any of the build scripts. Are you running into errors with th build process described in InstructionsForBuildingLLDBInterface.txt?

Zimm3r commented 1 year ago

Correct these are in Debugger-swig-lldb folder. I did run into some other issues (I had to build LLDB 14.0.0 to fix lldb-public.h missing in the apt version of it) that I do have a list of so it wouldn't surprise me if I have changed the build in some way causing all of this :)

The only issue I ran into in the troubleshooting section was the UnsatisfiedLinkError but in troubleshooting that is suggesting it is because the libraries aren't there or the paths are wrong, my paths are 'right' but pointing to libraries that Java won't load.

d-millar commented 1 year ago

OK, well, the fact that you have neither the bin nor build subdirectories suggests the "gradle build" command did not do what it should have. Let me know if you're still having issues after resolving the .so piece!

Zimm3r commented 1 year ago

It seems I got past this part of the issue so I will close it but I do get other errors after clicking connect though it does seem to 'work' (e.g breakpoints are activated and it seems it is running some type of debug session).

Note for the LD shared library I think it is a Ghidra setting, the file does seem to exist so I assume this is more user error than anything else :).

The module /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 was not found in the project
*** State Changed: 1
0x7f7bf4001170 Event: broadcaster = 0x7f7bdc1b9c38 (lldb.process), type = 0x00000004 (stdout-available), data = { process = 0x7f7bdc1b9c00 (pid = 27669), state = running}
*** Console STDOUT: 4
*** Module Loaded: 2
*** Module Loaded: 2
*** Module Loaded: 2
*** Module Unloaded: 4
*** Module Loaded: 2
*** State Changed: 1
Unexpected register bank replacement
Unexpected register bank replacement
Selected first mapping offer: <Offer: 'LLDB on Linux x86_64' lang=x86:LE:64:default cs=gcc confidence=100 target=Sessions[6c15].Processes[6c15]>
Using os=linux arch=x86_64
expected TargetExecutionState for _state, but got null

and after resuming from the initial breakpoint clearly the biggest issue, colors being null :D !

Seems after this Swing gets unhappy and there is some degree of graphic glitches

Cannot invoke "ghidra.app.plugin.core.marker.MarkerManager$MarkerSetCacheEntry.getBackgroundColor(ghidra.program.model.address.Address)" because "entry" is null
java.lang.NullPointerException: Cannot invoke "ghidra.app.plugin.core.marker.MarkerManager$MarkerSetCacheEntry.getBackgroundColor(ghidra.program.model.address.Address)" because "entry" is null
    at ghidra.app.plugin.core.marker.MarkerManager.getBackgroundColor(MarkerManager.java:414)
    at ghidra.app.plugin.core.marker.MarkerManager.getBackgroundColor(MarkerManager.java:410)
    at ghidra.app.plugin.core.codebrowser.MarkerServiceBackgroundColorModel.getBackgroundColor(MarkerServiceBackgroundColorModel.java:56)
    at ghidra.app.plugin.core.debug.gui.listing.MultiBlendedListingBackgroundColorModel.getBackgroundColor(MultiBlendedListingBackgroundColorModel.java:48)
    at ghidra.app.plugin.core.codebrowser.LayeredColorModel.getBackgroundColor(LayeredColorModel.java:43)
    at docking.widgets.fieldpanel.FieldPanel.getLayoutSelectionMap(FieldPanel.java:1138)
    at docking.widgets.fieldpanel.FieldPanel.paintComponent(FieldPanel.java:1050)
    at java.desktop/javax.swing.JComponent.paint(JComponent.java:1119)
    ...

---------------------------------------------------
Build Date: 2022-Nov-15 1249 EST
Ghidra Version: 10.2.2
Java Home: /usr/lib/jvm/java-17-openjdk-amd64
JVM Version: Private Build 17.0.5
OS: Linux 5.15.0-57-generic amd64

For these issues I'll look at them later, I assume they aren't hopefully as bad. I also will try to look at why my build was so different I imagine it very well could be I changed something and forgot etc (e.g at one point as I mentioned above I was using the apt version of LLDB and because of the lldb-public.h missing issue I moved to build LLDB and so changed the LLVM_HOME and LLVM_BUILD paths so maybe that caused it 🤷‍♂️ ).

d-millar commented 1 year ago

Looking at it now...

d-millar commented 1 year ago

@Zimm3r OK, was able to reproduce the MarkerManager error in the 10.2.2 build, but not in the source build. I'm pretty sure (although, honestly, I haven't found where) this bug has been fixed. I believe it only occurs in the 10.2.2 build if you've closed/killed a target and restarted or have no active program in the static listing. Not sure if you have the time or interest in building from the source, but, if you do and see the bug again, we'd certainly appreciate the heads up.