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

MIEngine crashes if the debuggee stops at an internal GDB breakpoint #1370

Closed gareth-rees closed 2 years ago

gareth-rees commented 2 years ago

Background

GDB uses negative breakpoint numbers to represent "internal" breakpoints. See the "Setting Breakpoints" documentation which says:

GDB itself sometimes sets breakpoints in your program for special purposes, such as proper handling of longjmp (in C programs). These internal breakpoints are assigned negative numbers, starting with -1; info breakpoints does not display them. You can see these breakpoints with the GDB maintenance command maint info breakpoints

"Internal" breakpoints can also be created using GDB's Python breakpoints interface, for example:

python gdb.Breakpoint("function_name", internal=True)

Steps to reproduce the bug

  1. Put the following test program in test.c and compile it using gcc -g -o test test.c (or otherwise) to make an executable test with debug information.

    #include <stdio.h>
    
    int
    main(void)
    {
        printf("Hello, world!\n");
        return 0;
    }
  2. Launch Visual Studio Code.
  3. Install the C/C++ extension if not already installed.
  4. Select Run ⟶ Add Configuration... and add a "(gdb) Launch" configuration. Edit the "program" key to refer to the compiled test and set "stopAtEntry": true.
  5. Select View ⟶ Run and launch the new configuration.
  6. In the DEBUG CONSOLE window, create an internal breakpoint by typing
    `python gdb.Breakpoint(line=7, internal=True)
  7. Press the Continue button.
  8. We expect execution to stop at the internal breakpoint just created, but in fact the debugging session ends. The DEBUG CONSOLE shows the following text (see screenshot below).

    Breakpoint -14, main () at test.c:7
    7       return 0;
    ERROR: Error while trying to enter break state. Debugging will now stop. Internal error in MIEngine. Exception of type 'System.OverflowException' was thrown.
    
       at System.Number.ThrowOverflowOrFormatException(ParsingStatus status, TypeCode type)
       at System.Convert.ToUInt32(String value, IFormatProvider provider)
       at Microsoft.MIDebugEngine.ExceptionManager.TryGetExceptionBreakpoint(String bkptno, UInt64 address, TupleValue frame, String& exceptionName, String& exceptionDescription, Guid& exceptionCategoryGuid)
       at Microsoft.MIDebugEngine.DebuggedProcess.HandleBreakModeEvent(ResultEventArgs results, BreakRequest breakRequest)
       at Microsoft.MIDebugEngine.DebuggedProcess.<.ctor>b__63_6(Object o, EventArgs args)
    The program '/home/grees/core/release-x64/examples/test' has exited with code 42 (0x0000002a).

Screenshot from 2022-11-07 13-59-40

Analysis

GDB represents a breakpoint number as an int. See the definition of struct breakpoint in breakpoint.h, which includes:

/* Number assigned to distinguish breakpoints.  */
int number = 0;

This means that when the debuggee stops at an internal GDB breakpoint, the MIEngine function TryGetExceptionBreakpoint() is called with an argument containing the string representation of a negative number, for example, bkptno = "-28" as shown in the screenshot below, which is from a debugger attached to the OpenDebugAD7 instance from a reproducer like the one described above:

Screenshot from 2022-11-07 11-18-49

This string is passed to Convert.ToUint32() which raises System.OverflowException. This is caught by an exception handler in the DebuggedProcess constructor (see screenshot below) that handles it by calling Terminate() which terminates MIEngine.

Screenshot from 2022-11-07 11-34-11

To prevent MIEngine from crashing when the debuggee stops at an internal GDB breakpoint, MIEngine must represent breakpoint numbers use a data type that's compatible with GDB. Since GDB uses int, it should be safe for MIEngine to use long.

Version numbers

C/C++ extension: 1.12.4 Version: 1.73.0 Commit: 8fa188b2b301d36553cbc9ce1b0a146ccb93351f Date: 2022-11-01T15:44:09.336Z Electron: 19.0.17 Chromium: 102.0.5005.167 Node.js: 16.14.2 V8: 10.2.154.15-electron.0 OS: Linux x64 5.4.0-125-generic Sandboxed: No