Closed staringatphones closed 1 year ago
Hi @staringatphones,
My apologies first off - you said "Windows Command Prompt" in your last post, and somehow I just didn't register the fact that you were running Windows. We are aware of this issue, and a fix (probably based on ConPty) is on our TODO list. May be awhile though.
I'd suggest checking out the previous issues #2908 and #3102 in Issues, and #2721 in Discussions. The basic workaround is to use the "GDB over SSH" agent rather than "IN-VM GDB" and either a WSL client or separate Linux VM running a gdbserver. Definitely, too complicated by half, but....let us know if neither of those will work for you or if you get stuck.
D
P.S. Thanks for closing out the other issue, by the by!
Future readers from 2023 and onwards, for anyone who is looking into this issue about how to use the "IN-VM GNU gdb local debugger" in Ghidra 10.2.2 Stable on a Windows operating system:
Please make sure you use DOUBLE BACKSLASHES when you put in the absolute path in the "GDB launch command" text field:
Otherwise, you will get an error message: GetLastError() returned 2
The 2
here means ERROR_FILE_NOT_FOUND in Win32 API.
Why double backslashes? You would ask. Well, well, well............
This is how Java interprets backslashes, when parsed into string values. The first backslash is to escape the proceeding second backslash.
Yes, we should probably try to validate the input for this. As noted, double-backslashes (or forward slashes) will work.
On the latest Ghidra 10.2.3, doing the same steps in OP now gives the following 2 errors, depending on whether you have "Use existing session via new-ui" checked or not.
Checked:
ghidra.dbg.error.DebuggerModelTerminatingException: Error while starting GDB: Pty implementation does not support null
sessions. Try D:\devkitPro\devkitARM\bin\arm-none-eabi-gdb.exe i mi2
---------------------------------------------------
Build Date: 2023-Feb-08 1242 EST
Ghidra Version: 10.2.3
Java Home: D:\Java\jdk-17.35
JVM Version: Eclipse Adoptium 17
OS: Windows 10 10.0 amd64
Workstation: DESKTOP-CV0SBRD
Unchecked:
java.lang.UnsupportedOperationException: ConPTY does not have a name
---------------------------------------------------
Build Date: 2023-Feb-08 1242 EST
Ghidra Version: 10.2.3
Java Home: D:\Java\jdk-17.35
JVM Version: Eclipse Adoptium 17
OS: Windows 10 10.0 amd64
Workstation: DESKTOP-PC
If you used the GDB interpreter modes hinted by the error message -i mi2
, you will get this:
ghidra.async.DisposedException: ghidra.dbg.error.DebuggerModelTerminatingException: GDB is terminating. Could not get target endian. Could not get target os. Could not get target architecture.
---------------------------------------------------
Build Date: 2023-Feb-08 1242 EST
Ghidra Version: 10.2.3
Java Home: D:\Java\jdk-17.35
JVM Version: Eclipse Adoptium 17
OS: Windows 10 10.0 amd64
Workstation: DESKTOP-CV0SBRD
Also, strangely enough, my operating system is actually Windows 11 Pro 22H2, not Windows 10 as printed in the text field.
Steps I did:
I have already verified the GDB server is able to communicate with GDB on a different Linux machine. So this is a Windows-specifc issue. This is more specific to the new changes made for 10.2.3:
* Debugger. Added GDB connector support for Windows (tested with GDB 11.1 on msys64). (GP-869, Issue #2908)
What is not really clear is, whether 7ab2f5d adds the Windows native implemention of ConPty to Ghidra, or Ghidra still has to go through MinGW to be able to connect to the GDB server.
Hmmm, well, let's see if we can move the ball down the field a little....
You probably do not want "Use existing session via new-ui". This involves running gdb outside of Ghidra, issuing the command to spawn a new ui, and connectiing to that. For now, let's assume that's more than you need.
I think you were closest to succeeding with the "-i m2". For example, on my box, I am using "GDB launch command" == "C:/msys64/mingw64/bin/gdb -i mi2". The error message you are getting suggests that your version of arm-none-eabi-gdb does not support the commands: "show endian", "show os", and "show architecture". Maybe, try running arm-none-eabi-gdb on your client machine outside of Ghidra and executing those commands. If they are not defined, I think we can fake them out, but I have to remember how to load those definitions early enough in the process to make Ghidra happy.
Another option if those commands are not supported is to use "gdb-multiarch".
@d-millar I'm able to run arm-none-eabi-gdb
in GDB/MI 2 interpreter mode, as output here:
D:\devkitPro\devkitARM\bin> .\arm-none-eabi-gdb.exe -i mi2
D:\devkitPro\devkitARM\bin\arm-none-eabi-gdb.exe: warning: Couldn't determine a path for the index cache directory.
=thread-group-added,id="i1"
~"GNU gdb (GDB) 10.2\n"
~"Copyright (C) 2021 Free Software Foundation, Inc.\n"
~"License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law."
~"\nType \"show copying\" and \"show warranty\" for details.\n"
~"This GDB was configured as \"--host=x86_64-w64-mingw32 --target=arm-none-eabi\".\n"
~"Type \"show configuration\" for configuration details.\n"
~"For bug reporting instructions, please see:\n"
~"<https://www.gnu.org/software/gdb/bugs/>.\n"
~"Find the GDB manual and other documentation resources online at:\n <http://www.gnu.org/software/gdb/documentation/>."
~"\n\n"
~"For help, type \"help\".\n"
~"Type \"apropos word\" to search for commands related to \"word\".\n"
(gdb)
echo "Hello world"
&"echo \"Hello world\"\n"
~"\"Hello world\""
^done
(gdb)
This is the same one with the latest compiled gdb-multiarch for Windows:
E:\gdb_multiarch\bin> ./gdb.exe -i mi2
=thread-group-added,id="i1"
~"GNU gdb (GDB) 12.1\n"
~"Copyright (C) 2022 Free Software Foundation, Inc.\n"
~"License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law."
~"\nType \"show copying\" and \"show warranty\" for details.\n"
~"This GDB was configured as \"x86_64-w64-mingw32\".\n"
~"Type \"show configuration\" for configuration details.\n"
~"For bug reporting instructions, please see:\n"
~"<https://www.gnu.org/software/gdb/bugs/>.\n"
~"Find the GDB manual and other documentation resources online at:\n <http://www.gnu.org/software/gdb/documentation/>."
~"\n\n"
~"For help, type \"help\".\n"
~"Type \"apropos word\" to search for commands related to \"word\".\n"
(gdb)
echo "hello world"
&"echo \"hello world\"\n"
~"\"hello world\""
^done
(gdb)
I believed all GDB version 6.0+ and above should have GDB/MI 2 by default.
@d-millar Oh, just re-read your post. Here are the outputs for the show os
, show endian
, and show architecture
on the arm-none-eabi-gdb
:
show os
&"show os\n"
~"The current OS ABI is \"auto\" (currently \"none\").\n"
^done
(gdb)
show endian
&"show endian\n"
~"The target endianness is set automatically (currently little endian).\n"
^done
(gdb)
show architecutre
&"show architecutre\n"
&"Undefined show command: \"architecutre\". Try \"help show\".\n"
^error,msg="Undefined show command: \"architecutre\". Try \"help show\"."
(gdb)
show architecture
&"show architecture\n"
~"The target architecture is set to \"auto\" (currently \"arm\").\n"
^done
(gdb)
Interesting - all of that is basically good news, i.e. the necessary commands are supported. So, the initial connection must be failing in some less-than-obvious way that is getting masked by the "show" errors. I will dig into the code some more tomorrow - see if I can re-create your issue.
OK, this is totally a maybe, but try setting the environment variable HOME to %USERPROFILE%, re-launch Ghidra, and make sure space and slashes are escaped in the cmdline. I just tried this with "C:/Program\ Files\ (x86)/GNU\ Arm\ Embedded\ Toolchain/10\ 2021.10/bin/arm-none-eabi-gdb -i mi2".
@d-millar I don't think it works. I still get the same errors Could not connect: GDB is terminating
, even when I put the environment variable HOME in both the User Variables and in the System Variables. I even logged out and relogin just to make extra sure the environment variables are loaded up.
OK, I thought that was possible but unlikely as I hit problems starting arm-none-eabi-gdb that I hadn't seen before, but they weren' terminating GDB. Are you running using ghidraRun or support/ghidraDebug? Any error messages you get either in the shell for ghidraDebug or the DebugConsole might be helpful - figuring out how it icould be dying is proving to be a bit of a challenge as I can't reproduce the error.
One more idea, in launch.properties, try adding "VMARG=-Dagent.gdb.manger.log=true" - this will generate a GDB.log file in your home directory(?).
@d-millar Noticed that the flag is spelled incorrectly, so I modified it a bit.
Here's the corrected flag:
VMARGS=-Dagent.gdb.manager.log=true
I tried this flag in the launch.properties
file, and nothing happened. So I modified the launch.bat
and added:
:: Set GDB logging enabled
set VMARG_LIST=%VMARG_LIST% -Dagent.gdb.manager.log=true
To force it to create the %USERPROFILE%\.ghidra\.ghidra_10.2.3_PUBLIC\GDB.log
.
Here are the contents of the GDB.log:
<MI2: =thread-group-added,id="i1"
*CMD: class agent.gdb.manager.impl.cmd.GdbListInferiorsCommand
>MI2: -list-thread-groups
There's not much in here. The output contents are the same if I relaunch Ghidra with .\ghidraDebug.bat
.
And here are the contents from the console terminal after running .\ghidraDebug.bat
:
Listening for transport dt_socket at address: 18001
INFO Using log config file: file:/D:/ghidra/ghidra_10.2.3_PUBLIC/support/debug.log4j.xml (LoggingInitialization.java:51)
INFO Using log file: C:\Users\fakeUser\.ghidra\.ghidra_10.2.3_PUBLIC\application.log (LoggingInitialization.java:52)
INFO Loading user preferences: C:\Users\fakeUser\.ghidra\.ghidra_10.2.3_PUBLIC\preferences (Preferences.java:117)
INFO Loading previous preferences: C:\Users\fakeUser\.ghidra\.ghidra_10.2.2_PUBLIC\preferences (Preferences.java:170)
INFO Class search complete (1703 ms) (ClassSearcher.java:276)
INFO Initializing SSL Context (SSLContextInitializer.java:76)
INFO Initializing Random Number Generator... (SecureRandomFactory.java:37)
INFO Random Number Generator initialization complete: SHA1PRNG (SecureRandomFactory.java:41)
INFO Trust manager disabled, cacerts have not been set (ApplicationTrustManagerFactory.java:95)
INFO User fakeUser started Ghidra. (GhidraRun.java:80)
DEBUG Recovery snapshot timer set to 5 minute(s) (RecoverySnapshotMgrPlugin.java:170)
INFO Opening project: D:\Documents\ghidra\MyGhidraTestProject (DefaultProject.java:134)
INFO Packed database cache: C:\Users\fakeUser\AppData\Local\Ghidra\packed-db-cache (PackedDatabaseCache.java:64)
DEBUG Using cached packed database: D:\ghidra\ghidra_10.2.3_PUBLIC\Ghidra\Features\Base\data\typeinfo\generic\generic_clib.gdt (PackedDatabaseCache.java:364)
INFO local Windows Pty session. PID = 1136 (LocalWindowsNativeProcessPtySession.java:40)
DEBUG Terminating agent.gdb.manager.impl.GdbManagerImpl@7503781a (GdbManagerImpl.java:799)
DEBUG Terminating agent.gdb.manager.impl.GdbManagerImpl@7503781a (GdbManagerImpl.java:799)
DEBUG STDOUT,MI2 reader exiting because java.lang.NumberFormatException: For input string: "" (GdbManagerImpl.java:161)
ERROR Could not connect: ghidra.dbg.error.DebuggerModelTerminatingException: GDB is terminating (ConsoleErrorDisplay.java:59)
WARN Could not get target architecture: java.util.concurrent.CompletionException: ghidra.dbg.error.DebuggerModelTerminatingException: GDB is terminating (DebuggerObjectModel.java:562)
WARN Could not get target os: java.util.concurrent.CompletionException: ghidra.dbg.error.DebuggerModelTerminatingException: GDB is terminating (DebuggerObjectModel.java:562)
WARN Could not get target endian: java.util.concurrent.CompletionException: ghidra.dbg.error.DebuggerModelTerminatingException: GDB is terminating (DebuggerObjectModel.java:562)
I did see a NumberFormatException
, so perhaps there's something wrong with it?
I'm curious about your steps such that you're not able to reproduce the error. May I take reference on your steps?
Well, I think your assessment may be correct - it might be the NumberFormatException. At a guess, this might be coming from "info proc mappings", but...again, not feeling like that's likely. So, my steps as exactly as I can describe them:
(1) From fresh download of ghidra_10.2.3_PUBLIC, execute ghidraRun.bat (double-clicked) (2) Set up a project in the usual way, and open the default Debugger tool (3) From Targets, hit "Create a new connection..." (4) From the pull-down menu, select "IN-VM GNU gdb local debugger" (5) For "GDB launch command", enter "C:/Program\ Files\ (x86)/GNU\ Arm\ Embedded\ Toolchain/10\ 2021.10/bin/arm-none-eabi-gdb -i mi2". This is the path I had for the default install from the download link you sent. (6) Leave "Use existing session via new-ui" unchecked, and hit "Connect" (7) At this point, in the Objects tree, I have Session->Inferiors->1 - \<null> (8) I can open this node and verify the Environment node, and I can run commands in the Interpreter
It sounds like you have done the same thing, but somewhere between 6 and 7 things went south.
Some things that are different:
I am running Windows Server 2019 (shouldn't make a difference?)
I am using OpenJDK 17.0.1 2021-10-19 LTS (also shouldn't make a difference?)
What do you get if you run "info proc mappings" in arm-none-eabi-gdb? I am getting "Not supported on this target".
@d-millar Same here.
(gdb)
info proc mappings
&"info proc mappings\n"
&"Not supported on this target.\n"
^error,msg="Not supported on this target."
(gdb)
However, we can trick GDB to give us info proc mappings
:
define info proc mappings
echo 0x0 0xFFFFFFFF 0x100000000 0x0 mem \n
end
source path/to/text/file/containing/info proc mappings
This is what I did in GDB interpreter mode:
(gdb)
define info proc mappings
&"define info proc mappings\n"
~"Type commands for definition of \"info proc mappings\".\n"
~"End with a line saying just \"end\".\n"
~">"
echo 0x0 0xFFFFFFFF 0x100000000 0x0 mem \n
~">"
end
^done
(gdb)
info proc mappings
&"info proc mappings\n"
~"0x0 0xFFFFFFFF 0x100000000 0x0 mem \n"
^done
(gdb)
Would this be helpful to you in some way?
LOL - that's my trick. (Glad it's catching on.) Just checking, though, you're not using that (say, from a .gdbinit file) in your current Ghidra tests, correct?
@d-millar No. I'm not even aware that you can put this in a .gdbinit
some where.
Good, I guess - I'd hate to be burned by my own trick. Will drag some extra eyes on the log file tomorrow; see if anyone has a brilliant insight into the current problem.
@d-millar Here's a better debug log messages I discovered as I finished setting up the Ghidra development environment and actually launching the debugger on my machine:
INFO Using log config file: file:/E:/LargeGithubProjects/ghidra/Ghidra/Framework/Generic/bin/main/generic.log4jdev.xml (LoggingInitialization.java:50)
INFO Using log file: C:\Users\fakeUser\.ghidra\.ghidra_10.3_DEV_location_LargeGithubProjects\application.log (LoggingInitialization.java:51)
INFO Loading user preferences: C:\Users\fakeUser\.ghidra\.ghidra_10.3_DEV_location_LargeGithubProjects\preferences (Preferences.java:122)
INFO Searching for classes... (ClassSearcher.java:257)
INFO Class search complete (3579 ms) (ClassSearcher.java:276)
INFO User fakeUser started Ghidra. (GhidraRun.java:77)
INFO local Windows Pty session. PID = 24716 (LocalWindowsNativeProcessPtySession.java:40)
ERROR Could not connect: ghidra.dbg.error.DebuggerModelTerminatingException: Error while starting GDB: Could not detect GDB's interpreter mode.
Try D:\devkitPro\devkitARM\bin\arm-none-eabi-gdb.exe -i mi2 (ConsoleErrorDisplay.java:59)
ERROR Could not get target architecture java.util.concurrent.CompletionException: java.lang.NullPointerException: Cannot invoke "java.io.PrintWriter.print(String)" because "wr" is null
at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:315)
at java.base/java.util.concurrent.CompletableFuture.uniAcceptNow(CompletableFuture.java:761)
at java.base/java.util.concurrent.CompletableFuture.uniAcceptStage(CompletableFuture.java:735)
at java.base/java.util.concurrent.CompletableFuture.thenAccept(CompletableFuture.java:2182)
at agent.gdb.manager.impl.GdbManagerImpl.doExecute(GdbManagerImpl.java:853)
at agent.gdb.manager.impl.GdbManagerImpl.execute(GdbManagerImpl.java:838)
at agent.gdb.manager.impl.GdbManagerImpl.consoleCapture(GdbManagerImpl.java:1747)
at agent.gdb.model.impl.GdbModelTargetEnvironment.lambda$1(GdbModelTargetEnvironment.java:87)
at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1187)
at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2309)
at agent.gdb.model.impl.GdbModelTargetEnvironment.refreshArchitecture(GdbModelTargetEnvironment.java:86)
at agent.gdb.model.impl.GdbModelTargetEnvironment.refreshInternal(GdbModelTargetEnvironment.java:168)
at agent.gdb.model.impl.GdbModelTargetEnvironment.<init>(GdbModelTargetEnvironment.java:65)
at agent.gdb.model.impl.GdbModelTargetInferior.<init>(GdbModelTargetInferior.java:100)
at agent.gdb.model.impl.GdbModelTargetInferiorContainer.getTargetInferior(GdbModelTargetInferiorContainer.java:163)
at agent.gdb.model.impl.GdbModelTargetInferiorContainer.inferiorAdded(GdbModelTargetInferiorContainer.java:58)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at ghidra.util.datastruct.ListenerMap$ListenerHandler.lambda$0(ListenerMap.java:134)
at ghidra.util.datastruct.ListenerMap$1.execute(ListenerMap.java:57)
at ghidra.util.datastruct.ListenerMap$ListenerHandler.invoke(ListenerMap.java:122)
at jdk.proxy2/jdk.proxy2.$Proxy55.inferiorAdded(Unknown Source)
at agent.gdb.manager.impl.GdbManagerImpl.lambda$58(GdbManagerImpl.java:470)
at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1804)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.NullPointerException: Cannot invoke "java.io.PrintWriter.print(String)" because "wr" is null
at agent.gdb.manager.impl.GdbManagerImpl.lambda$68(GdbManagerImpl.java:880)
at java.base/java.util.concurrent.CompletableFuture.uniAcceptNow(CompletableFuture.java:757)
... 27 more
(DebuggerObjectModel.java:571)
ERROR Could not get target os java.util.concurrent.CompletionException: java.lang.NullPointerException: Cannot invoke "java.io.PrintWriter.print(String)" because "wr" is null
at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:315)
at java.base/java.util.concurrent.CompletableFuture.uniAcceptNow(CompletableFuture.java:761)
at java.base/java.util.concurrent.CompletableFuture.uniAcceptStage(CompletableFuture.java:735)
at java.base/java.util.concurrent.CompletableFuture.thenAccept(CompletableFuture.java:2182)
at agent.gdb.manager.impl.GdbManagerImpl.doExecute(GdbManagerImpl.java:853)
at agent.gdb.manager.impl.GdbManagerImpl.execute(GdbManagerImpl.java:838)
at agent.gdb.manager.impl.GdbManagerImpl.consoleCapture(GdbManagerImpl.java:1747)
at agent.gdb.model.impl.GdbModelTargetEnvironment.lambda$5(GdbModelTargetEnvironment.java:120)
at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1187)
at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2309)
at agent.gdb.model.impl.GdbModelTargetEnvironment.refreshOS(GdbModelTargetEnvironment.java:119)
at agent.gdb.model.impl.GdbModelTargetEnvironment.refreshInternal(GdbModelTargetEnvironment.java:169)
at agent.gdb.model.impl.GdbModelTargetEnvironment.<init>(GdbModelTargetEnvironment.java:65)
at agent.gdb.model.impl.GdbModelTargetInferior.<init>(GdbModelTargetInferior.java:100)
at agent.gdb.model.impl.GdbModelTargetInferiorContainer.getTargetInferior(GdbModelTargetInferiorContainer.java:163)
at agent.gdb.model.impl.GdbModelTargetInferiorContainer.inferiorAdded(GdbModelTargetInferiorContainer.java:58)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at ghidra.util.datastruct.ListenerMap$ListenerHandler.lambda$0(ListenerMap.java:134)
at ghidra.util.datastruct.ListenerMap$1.execute(ListenerMap.java:57)
at ghidra.util.datastruct.ListenerMap$ListenerHandler.invoke(ListenerMap.java:122)
at jdk.proxy2/jdk.proxy2.$Proxy55.inferiorAdded(Unknown Source)
at agent.gdb.manager.impl.GdbManagerImpl.lambda$58(GdbManagerImpl.java:470)
at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1804)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.NullPointerException: Cannot invoke "java.io.PrintWriter.print(String)" because "wr" is null
at agent.gdb.manager.impl.GdbManagerImpl.lambda$68(GdbManagerImpl.java:880)
at java.base/java.util.concurrent.CompletableFuture.uniAcceptNow(CompletableFuture.java:757)
... 27 more
(DebuggerObjectModel.java:571)
ERROR Could not get target endian java.util.concurrent.CompletionException: java.lang.NullPointerException: Cannot invoke "java.io.PrintWriter.print(String)" because "wr" is null
at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:315)
at java.base/java.util.concurrent.CompletableFuture.uniAcceptNow(CompletableFuture.java:761)
at java.base/java.util.concurrent.CompletableFuture.uniAcceptStage(CompletableFuture.java:735)
at java.base/java.util.concurrent.CompletableFuture.thenAccept(CompletableFuture.java:2182)
at agent.gdb.manager.impl.GdbManagerImpl.doExecute(GdbManagerImpl.java:853)
at agent.gdb.manager.impl.GdbManagerImpl.execute(GdbManagerImpl.java:838)
at agent.gdb.manager.impl.GdbManagerImpl.consoleCapture(GdbManagerImpl.java:1747)
at agent.gdb.model.impl.GdbModelTargetEnvironment.lambda$9(GdbModelTargetEnvironment.java:149)
at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1187)
at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2309)
at agent.gdb.model.impl.GdbModelTargetEnvironment.refreshEndian(GdbModelTargetEnvironment.java:148)
at agent.gdb.model.impl.GdbModelTargetEnvironment.refreshInternal(GdbModelTargetEnvironment.java:170)
at agent.gdb.model.impl.GdbModelTargetEnvironment.<init>(GdbModelTargetEnvironment.java:65)
at agent.gdb.model.impl.GdbModelTargetInferior.<init>(GdbModelTargetInferior.java:100)
at agent.gdb.model.impl.GdbModelTargetInferiorContainer.getTargetInferior(GdbModelTargetInferiorContainer.java:163)
at agent.gdb.model.impl.GdbModelTargetInferiorContainer.inferiorAdded(GdbModelTargetInferiorContainer.java:58)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at ghidra.util.datastruct.ListenerMap$ListenerHandler.lambda$0(ListenerMap.java:134)
at ghidra.util.datastruct.ListenerMap$1.execute(ListenerMap.java:57)
at ghidra.util.datastruct.ListenerMap$ListenerHandler.invoke(ListenerMap.java:122)
at jdk.proxy2/jdk.proxy2.$Proxy55.inferiorAdded(Unknown Source)
at agent.gdb.manager.impl.GdbManagerImpl.lambda$58(GdbManagerImpl.java:470)
at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1804)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.NullPointerException: Cannot invoke "java.io.PrintWriter.print(String)" because "wr" is null
at agent.gdb.manager.impl.GdbManagerImpl.lambda$68(GdbManagerImpl.java:880)
at java.base/java.util.concurrent.CompletableFuture.uniAcceptNow(CompletableFuture.java:757)
... 27 more
(DebuggerObjectModel.java:571)
It seems like in GdbManagerImpl.java:135
, it first enters the while
loop. It is then successful at reading the first line, which has the value:
=thread-group-added,id="i1"
And then on the second while
loop iteration, just before it attempts to finish invoking reader.readLine()
, it throws a NumberFormatException. Thus, I dug a bit even deeper. Here is the second line that has the value:
~"GNU gdb (GDB) 10.2\n"[K
Github won't show the control character ESC, so here it is in picture form:
After the K
is parsed, the next character is what throws the NumberFormatException. It seems like GDB interpreter mode terminated its output string too soon here, as Ghidra is expecting a number here, either a 0
, 1
, or 2
, but GDB sends back an empty character.
We all know that when logging into GDB interpreter mode, it outputs the following:
D:\devkitPro\devkitARM\bin> .\arm-none-eabi-gdb.exe -i mi2
=thread-group-added,id="i1"
~"GNU gdb (GDB) 10.2\n" <-----------------------------------------------------------------------
~"Copyright (C) 2021 Free Software Foundation, Inc.\n"
~"License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law."
~"\nType \"show copying\" and \"show warranty\" for details.\n"
~"This GDB was configured as \"--host=x86_64-w64-mingw32 --target=arm-none-eabi\".\n"
~"Type \"show configuration\" for configuration details.\n"
~"For bug reporting instructions, please see:\n"
~"<https://www.gnu.org/software/gdb/bugs/>.\n"
~"Find the GDB manual and other documentation resources online at:\n <http://www.gnu.org/software/gdb/documentation/>."
~"\n\n"
~"For help, type \"help\".\n"
~"Type \"apropos word\" to search for commands related to \"word\".\n"
(gdb)
It is the line marked with a <-----
that showed where Ghidra couldn't finish parsing and exited too quickly.
Somehow, in the AnsiBufferedInputStream.java:368
in the Debugger-agent-gdb
project, where in the parseNumericBuffer()
, it is supposely expecting a numeric code when for whatever reason, on Windows operating systems, the GDB doesn't really give any numbers to execute an "Erase In Line" operation.
I'm not even sure whether if it's a bug on the GDB side, a bug on the Debugger-agent-gdb
side, or it could be a minor difference due to different operating systems that's not taken into account yet. If anyone else have insights on this issue, it would be great to hear more about this.
It might just be a shorthand case we hadn't considered in the ANSI parsing: https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
Looks like ESC[K
is same as ESC[0K
. Thanks for pointing it out. A lot of this ANSI stuff was introduced in order to handle Windows ConPTY. It inserts a lot of these control sequences when piping output from the child application to the parent console, so I suspect the difference in ANSI codes is due to a difference in Windows version. In any case, an ANSI decode problem like that shouldn't be throwing an exception :/ .
If you're willing to try a quick and dirty patch, where you pointed out in AnsiBufferedInputStream.java
, patch the method:
protected int parseNumericBuffer() {
String numeric = readAndClearEscBuf();
if (numeric.isEmpty()) {
return 0;
}
int result = Integer.parseInt(numeric);
return result;
}
Other things call that where blank may not imply 0, so I'm not sure this is a solution, but it should at least move us forward troubleshooting.
@nsadeveloper789 It worked. Applying the patch made Ghidra able to communicate with GDB successfully on the ARM device. I'll go ahead and create a pull request for this.
Wow, score - nice call @nsadeveloper789
@d-millar @nsadeveloper789 Made a pull request. I credited @nsadeveloper789 for the patch.
Yep - thanks!
Glad to know it worked. As mentioned, I'm not certain it's The Right Solution (TM). On the other hand, if it works, then why not? Good news is this only applies to GDB on Windows, so I think it's relatively low risk to just take it. Thanks for submitting the patch!
I don't have the IN-VM GNU gdb local debugger option.
I'm using Ghidra 11.0.1 btw.
Has the name changed or something?. Here's the screenshot
In addition, when I modify the GDB launch command and indicate the following path:
C:\\Users\\Stevens\\Desktop\\gdb-multiarch-14.1\\bin\\gdb-multiarch.exe
I get the -i mi2 error shown in this screenshot. I'm using the 14.1 version of gdb-multiarch-windows
EDIT: If I run gdb-multiarch as administrator then I get this error:
Build Date: 2024-Jan-30 1212 EST Ghidra Version: 11.0.1 Java Home: C:\Program Files\Java\jdk-17 JVM Version: Oracle Corporation 17.0.10 OS: Windows 10 10.0 amd64 Workstation: DESKTOP-6N85SK3
A few things:
-i mi2
to the gdb path (launch command).I don't have any insight on the 740 error, as I've not tried running this as administrator on Windows.
I don't have any insight on the 740 error, as I've not tried running this as administrator on Windows.
I tried the suggestions and I still get the 740 error.
And I need to run gdb-multiarch as administrator to bypass the -i mi2 error.
And I need to run gdb-multiarch as administrator to bypass the -i mi2 error.
I'm not sure I understand. Is trying to workaround the -i mi2
thing the only reason you need to run gdb as admin? I wouldn't ordinarily recommend running gdb as admin, unless you need to attach to a process of higher privilege. I suspect the 740 error (operation requires elevation) actually comes earlier in the launch process than whatever error related to -i mi2
.
Please try the following and, if it doesn't work, please include all the details from the error message you can:
-i mi2
. No quotes. If gdb's path contains spaces, you can quote the path to gdb, but the -i mi2
part must be outside the quotes.If you indeed need to run gdb with higher privileges than Ghidra, you may try writing a batch script that wraps gdb -i mi2
with runas. In theory, you can then supply the path to that script instead of gdb when configuring the launch.
Describe the bug The "IN-VM GNU gdb local debugger" option on Windows throws an uncaught exception and does not continue when supplied with the official GNU Arm Embedded Toolchain version of GDB.
To Reproduce Steps to reproduce the behavior:
gcc-arm-none-eabi-10.3-2021.10-win32.exe
installer was used. (Link to downloads page, Direct Download Link to installer)."C:\Program Files (x86)\GNU Arm Embedded Toolchain\10 2021.10\bin\arm-none-eabi-gdb.exe"
(with quotes)Expected behavior The ARM-specific GDB executable should launch within Ghidra, which allows the Debugger tool to debug the binary. (Note, a remote GDB server will be necessary to interface with an arm processor. The command
target remote hostname:port
would then be given to GDB. However, GDB fails to even launch in this scenario.)Screenshots
The screenshot above shows the error message. A text file containing the entire contents of the error message is included in the Attachments section below.
Attachments error-output.txt This text file contains the complete text of the error given.
Environment (please complete the following information):