microsoft / MIEngine

The Visual Studio MI Debug Engine ("MIEngine") provides an open-source Visual Studio Debugger extension that works with MI-enabled debuggers such as gdb and lldb.
MIT License
818 stars 218 forks source link

Fix LLDB core dumps loading in separate debug targets #1396

Closed iridinite closed 1 year ago

iridinite commented 1 year ago

Environment:

Problem overview:

When we load a core in LLDB, we do so by first sending -file-exec-and-symbols, followed by a non-MI command target create --core. However, this approach causes LLDB to create two separate debug targets: one with the desired executable loaded, and another one that only has the core file loaded.

We can see this when manually running the above in an lldb-mi instance, and observing the output of target list (reformatted for readability):

(gdb) -file-exec-and-symbols example.elf
^done
=library-loaded,id="/path/to/example.elf", [ ... truncated ]
(gdb) target create --core core
~"Core file '/path/to/core' (x86_64) was loaded.\n"
^done
(gdb) target list
~"Current targets:
  target #0: /path/to/example.elf ( arch=x86_64-*-linux, platform=host )
* target #1: <none> ( arch=x86_64-*-linux, platform=host, pid=40, state=stopped )
"
^done

The core is loaded in selected debug target 1, threads/PID/stop reason and all, but does not have an executable file associated with it at all, because that one is in debug target 0:

(gdb) target modules list
&"error: the target has no associated executable images\n"

Resulting behavior:

When MIEngine then submits its other initialization commands to actually begin debugging, LLDB still does not have an executable file loaded. So what it will do instead, is try to locate the binary using the module file name recorded in the core dump itself.

This may or may not work, depending on whether a binary with the same name happens to be in the solib search paths, but it is most certainly not the executable file the user wanted to load. Thus, in effect, the executable file input field in Visual Studio's core dump dialog is completely ignored.

You can observe this behavior in Visual Studio by loading a core file with a different executable file name than what was recorded by the core file. LLDB will fail to find the file, will be unable to load any modules, and Visual Studio will not be able to resolve (or even show) any thread call stacks.

For example, in this screenshot the Modules list is empty, and the call stack is not displayed at all:

devenv_9b6aC3Dt3c

This problem does not occur with GDB.

Proposed solution:

According to LLDB's built-in documentation, the correct method to load an executable file and a core file into the same target, is by specifying both in the same target create (or file for short) command, e.g. file example.elf -c my_core.

This patch attempts to implement this solution, by merging the -file-exec-and-symbols and target create commands into one file command. GDB behavior is left unchanged (still two separate commands) since that appears to work fine.

I've tried to adhere to the surrounding code style - please do let me know if something needs to be changed. :)

Thank you very much for your time!

iridinite commented 1 year ago

@microsoft-github-policy-service agree

iridinite commented 1 year ago

Apologies, I need to sort out some CLA details; closing this and will re-open later.

iridinite commented 1 year ago

@microsoft-github-policy-service agree company="Sony Interactive Entertainment LLC"

iridinite commented 1 year ago

Hi @WardenGnaw, would you have time to look at this by any chance? 😄

WardenGnaw commented 1 year ago

@iridinite Thank you for making this PR. We will try to get this into the next release