Bug 29681 - VS 2022 Preview C++ Android debugger crashes on breakpoint in thread on arm64v8a device
Summary: VS 2022 Preview C++ Android debugger crashes on breakpoint in thread on arm64...
Status: RESOLVED NOTABUG
Alias: None
Product: gdb
Classification: Unclassified
Component: threads (show other bugs)
Version: unknown
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-10-13 13:54 UTC by Daniel Hilburn
Modified: 2022-10-15 14:12 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
AndroidApp.zip (9.56 MB, application/x-zip-compressed)
2022-10-13 14:01 UTC, Daniel Hilburn
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Daniel Hilburn 2022-10-13 13:54:49 UTC
I have an Android app which I am attempting to debug on my Samsung Galaxy S21. I’m using VS 2022 Preview. Ultimately, my goal is to create a fully native project using the NativeActivity, as the old project template using ANT was removed. This project is just the provided Gradle Android App project modified to use the NativeActivity implemented in a second SharedLib project. When I deploy the app to my phone and connect the debugger, it correctly starts the NativeActivity and I can hit a breakpoint in the ANativeActivity_onCreate function. So far so good. ANativeActivity_onCreate creates a second thread on which to run my app code so that ANativeActivity_onCreate can return. That second thread executes correctly without crashing. However, if I put a breakpoint into the code running on that second thread, the debugger throws an error and stops the app and disconnects.

I’ve enabled debugger logging using “Debug.MIDebugLog /On:MIDebugLog.txt /OutputWindow” in the Command Terminal window in VS and the error it provides is “Call Frame Instruction op 45 in vendor extension space is not handled on this architecture.” It seems to be unable to retrieve the call stack from the second thread. If I put a breakpoint in the ANativeActivity_onCreate immediately after it creates the thread, I can see the new thread in the Threads window. However, selecting it shows the same error and Visual Studio shows a window explaining that the selected thread is not supported.

I contacted Visual Studio support about this issue (https://developercommunity.visualstudio.com/t/VS-2022-Preview-C-Android-debugger-cra/10165250?space=62&entry=problem) and they said that it is an issue with GDB and recommended that I contact you guys.

I have attached an AndroidApp.zip file containing the small example project. The test project is basically just the provided C++ Android App Gradle project with an additional C++ Android Shared Object Library project compiling the android_native_app_glue.c code. You can reproduce by putting a breakpoint in android_native_app_glue.c in android_app_create() at line 314 and another in android_app_entry() at line 240. The first breakpoint will hit on the initial thread without trouble and the second breakpoint from the second thread will cause the debugger to crash.

Please let me know if you need any additional information from me on this issue, and thanks in advance for your assistance.
Comment 1 Daniel Hilburn 2022-10-13 14:01:01 UTC
Created attachment 14397 [details]
AndroidApp.zip
Comment 2 Daniel Hilburn 2022-10-13 14:01:45 UTC
Comment on attachment 14397 [details]
AndroidApp.zip

Contains a test VS solution to demonstrate the bug, MIDebugLog.txt with gdb output from a crash, and AboutVS.txt with Visual Studio installation info
Comment 3 Daniel Hilburn 2022-10-13 14:02:02 UTC
Comment on attachment 14397 [details]
AndroidApp.zip

Contains a test VS solution to demonstrate the bug, MIDebugLog.txt with gdb output from a crash, and AboutVS.txt with Visual Studio installation info.
Comment 4 Simon Marchi 2022-10-14 01:07:55 UTC
When you say it crashes, are you talking about this?

17: (2106595) <-1060-stack-list-frames 0 1000
17: (2106628) ->1060^error,msg="Call Frame Instruction op 45 in vendor extension space is not handled on this architecture."

That's the only abnormal thing I see, and that would prevent VSCode from showing a stack trace.

According to the message, a DWARF CFI expression uses the 45 (0x2d) vendor-specific operator.  From your logs, I see that you are on AArch64 (ARM64), so it's probably
DW_CFA_AARCH64_negate_ra_state:

https://gitlab.com/gnutools/binutils-gdb/-/blob/091782c46d9b321f5b7c5e5330b5febe015d73d6/include/dwarf2.def#L791

I see that we handle it here: https://gitlab.com/gnutools/binutils-gdb/-/blob/091782c46d9b321f5b7c5e5330b5febe015d73d6/gdb/aarch64-tdep.c#L1339

Looks like you are using GDB 8.3, which is too old.  It looks like it was added in GDB 9.
Comment 5 Daniel Hilburn 2022-10-14 01:59:57 UTC
Yes. I suspect that it isn't really crashing, but just that the callstack error causes the VS debugger to stop, which immediately closes the app.

Thank you so much for the detailed and useful information. I'll try updating my GDB version and see if that fixes things.
Comment 6 Daniel Hilburn 2022-10-14 13:19:56 UTC
In attempting to update my gdb version, it appears that Visual Studio's Android debugger is adb and it uses gdbserver deployed to the device with the deployed app to debug it remotely. Where did you see my gdb version information? I'd like to also check the gdbserver and adb versions to make sure that they are also up-to-date.
Comment 7 Simon Marchi 2022-10-14 14:08:53 UTC
(In reply to Daniel Hilburn from comment #6)
> In attempting to update my gdb version, it appears that Visual Studio's
> Android debugger is adb and it uses gdbserver deployed to the device with
> the deployed app to debug it remotely. Where did you see my gdb version
> information? I'd like to also check the gdbserver and adb versions to make
> sure that they are also up-to-date.

In your MI logs:

17: (2094895) ->~"GNU gdb (GDB) 8.3\n"

adb is the tool used to access / connect to devices, but you definitely have a GDB somewhere.  Any idea where it comes from, Android SDK or shipped with a Visual Studio extension?
Comment 8 Daniel Hilburn 2022-10-14 14:17:35 UTC
As I understand it Visual Studio has a gdb "frontend" (not sure what that means), so maybe that is it on my PC side of things. The Android NDK ships with a prebuilt gdbserver, which Visual Studio deploys with my application to the Android device. I thought that adb was communicating with that, but maybe it is Visual Studio itself. In trying to track down my local gdb file to update it, I debugged my application from Visual Studio and looked in Task Manager to see what programs were running. I saw adb but no gdb, so that's why I was thinking that VS was using adb. I'll look into how Visual Studio's gdb debugger works and see if I can track that down.

Incidentally, do you think that the error is originating from the gdbserver on the device or from the gdb on my host PC? The way it emits seems like Visual Studio is sending a command to gdbserver to retrieve the callstack when the breakpoint hits and gdbserver is replying that the specified command is not handled. Does that correct? If so, that would imply that the host debugger in VS is more up-to-date than the gdbserver instance running on the device.
Comment 9 Simon Marchi 2022-10-14 15:11:31 UTC
(In reply to Daniel Hilburn from comment #8)
> As I understand it Visual Studio has a gdb "frontend" (not sure what that
> means), so maybe that is it on my PC side of things. The Android NDK ships
> with a prebuilt gdbserver, which Visual Studio deploys with my application
> to the Android device. I thought that adb was communicating with that, but
> maybe it is Visual Studio itself. In trying to track down my local gdb file
> to update it, I debugged my application from Visual Studio and looked in
> Task Manager to see what programs were running. I saw adb but no gdb, so
> that's why I was thinking that VS was using adb. I'll look into how Visual
> Studio's gdb debugger works and see if I can track that down.

You definitely have a gdb binary somewhere, because this kind of chatter in the logs:

-1060-stack-list-frames 0 1000
1060^error,msg="Call Frame Instruction op 45 in vendor extension space is not handled on this architecture."

is GDB MI (machine interface).  It is your GUI application (Visual Studio) talking to GDB.

If I had to guess, adb is involved as the communication bridge between gdb and gdbserver.

To locate which gdb is used, you could try to look at the processes (ps) while your debug session is running.  I tried download the Android NDK, but couldn't find a GDB executable in there.  Perhaps it is downloaded separately / on-demand.

> Incidentally, do you think that the error is originating from the gdbserver
> on the device or from the gdb on my host PC? The way it emits seems like
> Visual Studio is sending a command to gdbserver to retrieve the callstack
> when the breakpoint hits and gdbserver is replying that the specified
> command is not handled. Does that correct? If so, that would imply that the
> host debugger in VS is more up-to-date than the gdbserver instance running
> on the device.

The error originates from GDB on your host PC.  The stack trace is generated by GDB on the host, using the DWARF information present in the executable.  GDBserver doesn't do stack unwind.

Visual Studio talk on your host talks with GDB on your host.  GDB talks to GDBserver whenever it needs to interact with the debugged process, for instance to read memory or registers, or to resume threads.  In your case, it's GDB that generates the error, the DWARF information in the executable contains an operation that GDB does not know about.

Again, if I had to guess, I'd say that your GDB and GDBserver versions are the same, if they come from the same place.  In theory, you can upgrade only your GDB, as it's supposed to be able to talk with older GDBservers.  Some newer features might not be available, but in most cases it degrades gracefully.  But in your case, the problem you encounter only concerns work done on the host, so it should work fine to use a newer GDB with your current GDBserver.  I say should, because it's not the best tested scenario.
Comment 10 Daniel Hilburn 2022-10-14 15:30:40 UTC
Ah! You were absolutely right! I looked again and found it nested underneath Visual Studio's process in Task Manager. It looks like gdb and gdbserver both come from the Android NDK. I've posted on the NDK github page to request an update in the next version.

Thank you so much for all of your help on this. Do you know if there is a prebuilt gdb binary for windows which I can download? I tried downloading the 12.1 gdb source code, but it won't build for me. I extracted it and then ran "./configure" and then "make" and it emits "no targets specified and no makefile found".
Comment 11 Simon Marchi 2022-10-14 15:56:16 UTC
(In reply to Daniel Hilburn from comment #10)
> Thank you so much for all of your help on this. Do you know if there is a
> prebuilt gdb binary for windows which I can download? I tried downloading
> the 12.1 gdb source code, but it won't build for me. I extracted it and then
> ran "./configure" and then "make" and it emits "no targets specified and no
> makefile found".

I don't know if someone provides a pre-built binary.  What's more is that in your case, since you want to debug AArch64 code, you'll need to enable the AArch64 target.  That means passing a flag like --target=aarch64-something-something to configure.  You can try to start your existing GDB and do "show configuration" to see how that one was configured, and start from there.

After that, the build environment on Windows is very different from Linux, so I may not be able to help you much.
Comment 12 Daniel Hilburn 2022-10-14 16:07:49 UTC
You've already helped so much. Thank you! I'll ask NDK support for information on building gdb. Surely, they know how to do it. =D
Comment 13 Daniel Hilburn 2022-10-14 16:09:13 UTC
Marking Resolve NotABug, as this wasn't a bug with gdb or gdbserver. Thanks again for all of your help.
Comment 14 Daniel Hilburn 2022-10-15 14:12:10 UTC
As a sort of epilogue to this issue, it turns out that Android NDK has dropped gdb support in favor of lldb. They have a Visual Studio extension called Android Game Developer Extension which uses that. It seems much better than the older Visual Studio integration.