Marus / cortex-debug

Visual Studio Code extension for enhancing debug capabilities for Cortex-M Microcontrollers
MIT License
1.01k stars 240 forks source link

Demangling symbols #242

Closed MabezDev closed 4 years ago

MabezDev commented 4 years ago

The current approach assumes the symbols, such as function names are not mangled: https://github.com/Marus/cortex-debug/blob/149073ecf0bf8c9cfb3580d52941345e1816c2f6/src/backend/symbols.ts#L32

This means that disassembly for Rust, C++ etc won't work. There are two ways I see of solving this.

  1. Running the output of objdump through a filter, c++filt or rustc-demangle.

  2. Extracting the information out of GDB instead. info functions lists the functions in there demangled form, but the output looks a little tricky to parse.

Thoughts?

haneefdm commented 4 years ago

In my fork, I added a launch.json option for demangling. Could you try that out please while I finish testing other changes I made. See the ChangeLog.

https://github.com/haneefdm/cortex-debug

Please let me know if it works. I chose a third option. Use -C option on objdump.

I have already looked at other options to get symbols out of gdb and we can't do that until we all start using GDB 9.1+ where there are new machine interface queries (MI3) for getting information like this. Working with non-MI interface is very risky and can fail with the tens of versions of gdb people are using.

Most people are using version 8.1 or less version of GDB and ARM has not even started the port of version 9. Too new. So, we may be stuck with objdump method for a while.

MabezDev commented 4 years ago

I tried your fork but it's still reporting "No fucntion with name X found".

I ran your extension through the launch extension task, upon searching for the disassembly of a function the following is printed into the debug console:

rejected promise not handled within 1 second: Error: cannot open file:///undefined. Detail: Unable to read file (Error: File not found (/undefined))
stack trace: Error: cannot open file:///undefined. Detail: Unable to read file (Error: File not found (/undefined))
    at file:///opt/visual-studio-code/resources/app/out/vs/workbench/workbench.desktop.main.js:5328:687

Hope that helps.

haneefdm commented 4 years ago

That issue was always there if a function was not found, had nothing to do with demangling per say. I fixed it just now so the rejected promise does not happen. But there is a bigger problem.

Cortex Debug uses :: to construct a url for VSCode disassembly:///file-name::function-name which is later decoded so, if you have a de-mangled name with those characters, it would not decode properly. Well, :: is also a scope separator in demangled names. In the process of using a different separator.

So, what exact function name were you actually searching for? Need to know because I have no experience with rust and not sure what o expect. Can you attach your executable?

MabezDev commented 4 years ago

Ah ok I think I can see a possible issue. I can't upload the binary, but if you have Rust on your system cloning https://github.com/MWatch/kernel and running make debug will get you a binary.

arm-none-eabi-objdump --syms target/thumbv7em-none-eabi/debug/mwatch_kernel

gives mangled results like so:

08003fd4 g     F .text  0000003c _ZN8heapless4spsc30Queue$LT$T$C$N$C$usize$C$C$GT$7enqueue17h5decca9936587b66E

using the -C option gives demangled results like this:

08003fd4 g     F .text  0000003c heapless::spsc::Queue<T,N,usize,C>::enqueue

I'm guessing more than one :: would break things?

haneefdm commented 4 years ago

Yes, even one :: would break things. What precedes the first :: will look like a file-name and there was an assumption that there be no more than one :: so even the function name would not pick up the whole name.

The Rust de-mangled name looks just like a standard C++ name. That is good to know.

MabezDev commented 4 years ago

Yes, even one :: would break things.

Ah. Is it a case of using a different delimiter or is it more complex than that?

The Rust de-mangled name looks just like a standard C++ name. That is good to know.

Which lang are you using the demangling option for?

haneefdm commented 4 years ago

is it more complex than that?

It is used in multiple places both in the front-end and the back-end. Changing the delimiter means I have to find (and test) every possible use case and make sure it does not break something that was working for everyone before. This has a huge potential for regressions.

@MabezDev May I ask why you couldn't create a simple test case to demonstrate your issue? Nothing proprietary needed. You are asking me to download/install a whole bunch of stuff and spend a few hours/days on it to duplicate what you are seeing?

MabezDev commented 4 years ago

Here you go: mwatch.zip. Let me know if you need anything else.

haneefdm commented 4 years ago

I updated my fork and submitted a PR. Hopefully, it will be in the next release

My fork: https://github.com/haneefdm/cortex-debug

I have a general fix along with a bunch of other fixes. I used another users' test case. If you have time, try it out and give feedback.

haneefdm commented 4 years ago

@MabezDev Is it possible to try out my fork again, to see if it works? My PR #248 is in the approval stage, but if you see issues, there may still be time to address them before the next release.

https://github.com/haneefdm/cortex-debug

I checked out the executable you posted earlier. It has some strange files and symbols but should still be okay.

00000000 l    df *ABS*  00000000 mwatch_kernel.cikqiqi4-cgu.0

Above is probably not a real file on disk anywhere. They typically end in a \.[0-9]+ pattern. But under such files, there are functions and data objects and some of them are not real (as in compiler/linker-generated). Since I can't debug, I don't know what gdb thinks they are.

haneefdm commented 4 years ago

There is another strange thing I saw...

20000000 l     O .data  00000004 mwatch_kernel::APP::LOGGER
200004e0 l     O .uninit    00000890 mwatch_kernel::APP::SYSTEM

The first line above is normal. the second hex-number is the size of the object/function. Since everything is strictly character-positional, and the length field is empty, the second line is ignored. I could not find documentation as to how to interpret it. If these symbols are important, we have to figure out what they could be and how to interpret them. There are tons of these. I can tell what follows after 00000890 is the real symbol name but what does 00000890 mean? Why is the size field empty. Even the position of 00000890 is off by one space.

I need to see some official documentation.

Since the section says .uninit, it means un-initialized data. Fine. I think these are static mut variables. I don't know how they affect the debugging experience. What little I know, I am liking Rust :-)

MabezDev commented 4 years ago

I checked out the executable you posted earlier. It has some strange files and symbols but should still be okay. 00000000 l df ABS 00000000 mwatch_kernel.cikqiqi4-cgu.0

I believe those are metadata the rust compiler embeds into the elf, so no need to worry about them as they never make it to the flash on a device.

Since the section says .uninit, it means un-initialized data. Fine. I think these are static mut variables. I don't know how they affect the debugging experience.

Correct, they are static mut variables and yes, these really have a size of zero. They are initialized at run time, hence they take no flash space.

https://github.com/MWatch/kernel/blob/c707a4520a32c526a9ca63b6c5c1f91686c8a808/src/main.rs#L328-L340

What little I know, I am liking Rust :-)

It's fun, give it a try! :) (Shameless plug: https://mabez.dev/blog/posts/esp32-rust-svd-pac/ a blog post I wrote using Rust on an ESP32, and debugging it with this extension!)

Unfortunately I'm still not having any joy, I'll run you through what I've tried just incase I'm missing something:

  1. Cloned your fork, opened in vscode & ran the 'Launch Extension' task which opens a new vscode window
  2. Open a rust project, in this case I've used my mwatch project as its source is publically available
  3. Launched a cortex-debug session with the following config:
{
            "cwd": "${workspaceRoot}",
            "executable": "./target/thumbv7em-none-eabi/debug/mwatch_kernel",
            "name": "Cortex-debug Debug",
            "request": "launch",
            "type": "cortex-debug",
            "servertype": "openocd",
            "interface": "swd",
            "demangle": true,
            "device": "STM32L432KC",
            "configFiles": [
                "openocd.cfg"
            ],
        },
  1. View disassembly of a function that is never mangled, for me that is main, which works
  2. View disassembly of a mangled function, I chose horizontal_centre in https://github.com/MWatch/kernel/blob/master/src/application/render_util.rs because it is a simple, standalone function. Unfortunately this results in the same issue of it not finding any function called horizontal_centre
haneefdm commented 4 years ago

Did you chose the full name? It is quite long...

0800535c g     F .text  0000002c mwatch_kernel_lib::application::render_util::horizontal_centre
MabezDev commented 4 years ago

Yeah I tried the full name too. Is there an easy way to list the symbols its collected for a given file?

haneefdm commented 4 years ago

Not without adding some typescript code. I did and that symbol is definitely found. What is the exact message you are seeing? Depending on the actual message, I can probably tell how far it is getting before it fails. Also, how are you launching the VSCode for testing? Did you do

  1. Use 'Launch Extension & Server'?
  2. In your project launch.json, do you have lines "debugServer": 4711,and "demangle": true If you don't have this, then you are not using my version. You are using the previous version of the debug adapter. You are also not de-mangling.
haneefdm commented 4 years ago

I am now, fairly certain you were not actually using the updated code from my fork. I say that because I have done this with C++ with similar de-mangling and it works.

The frontend and backend run in separate processes. I have a feeling you were using the debug front-end but using previous production backend. How VSCode works. The backend does most of the heavy lifting though

You may want to refresh your clone. I just added a feature where you can use a regular expression for a function name disassembly. See updated ChangeLog. There is no guarantee that such a change will be accepted, but try it out, provide feedback.

MabezDev commented 4 years ago

Yeah you're right, the debug server was silently failing because the node on my system was not built with the inspection tools for debugging. The full path works now :).

I'll try out the regex search. What would be really nice is if view disassembly opened a listen of the current symbols in the file, and you could just search that list.

MabezDev commented 4 years ago

The regex search works pretty nice!

One thing I've noticed though is that if a function isn't actually used in the binary the disassembly isn't available... which is obvious of course but when searching manually there is no distinction between not finding it in the search and it never exisiting in the first place. That's probably something to work on in the future though, this is working really well for my rust project(s)!

MabezDev commented 4 years ago

Bonus: Predictably, the dissasembly view seamlessly works for xtensa assembly too!

2020-02-13-212547_1920x1045_scrot

haneefdm commented 4 years ago

Why does the disassembly window title (tab name) show a mangled name? For me, I see a de-mangled name if de-mangling is enabled. Something wrong with color-coding as well. The addresses stop coloring after the first non-digit hex char on the right side.

MabezDev commented 4 years ago

Hmm on arm, the tab name is correctly demangled 2020-02-13-223201_1920x1045_scrot

still has the address highlighting issue though.

Object dump sucessfully demangles when I run it manually (obviously) xtensa-esp32-elf-objdump --syms target/xtensa-esp32-none-elf/debug/esp32 -C | grep delay 40080ca0 l F .iram.text 00000039 esp32::delay

Versions of each:

$ xtensa-esp32-elf-objdump --version
GNU objdump (crosstool-NG esp32-2019r1) 2.31.1
$ arm-none-eabi-objdump --version   
GNU objdump (GNU Tools for Arm Embedded Processors 8-2019-q3-update) 2.32.0.20190703
haneefdm commented 4 years ago

The coloring of hex numbers in assembly is fixed.

I am gonna close this issue as everything is already in the PR. I think Cortex-Debug is a better C++/Rust debugger now. If other issues pop up, we have to deal with them in separate issues.