Home | History | Annotate | Download | only in docs
      1 ==============================
      2 Debugging JIT-ed Code With GDB
      3 ==============================
      4 
      5 Background
      6 ==========
      7 
      8 Without special runtime support, debugging dynamically generated code with
      9 GDB (as well as most debuggers) can be quite painful.  Debuggers generally
     10 read debug information from the object file of the code, but for JITed
     11 code, there is no such file to look for.
     12 
     13 In order to communicate the necessary debug info to GDB, an interface for
     14 registering JITed code with debuggers has been designed and implemented for
     15 GDB and LLVM MCJIT.  At a high level, whenever MCJIT generates new machine code,
     16 it does so in an in-memory object file that contains the debug information in
     17 DWARF format.  MCJIT then adds this in-memory object file to a global list of
     18 dynamically generated object files and calls a special function
     19 (``__jit_debug_register_code``) marked noinline that GDB knows about.  When
     20 GDB attaches to a process, it puts a breakpoint in this function and loads all
     21 of the object files in the global list.  When MCJIT calls the registration
     22 function, GDB catches the breakpoint signal, loads the new object file from
     23 the inferior's memory, and resumes the execution.  In this way, GDB can get the
     24 necessary debug information.
     25 
     26 GDB Version
     27 ===========
     28 
     29 In order to debug code JIT-ed by LLVM, you need GDB 7.0 or newer, which is
     30 available on most modern distributions of Linux.  The version of GDB that
     31 Apple ships with Xcode has been frozen at 6.3 for a while.  LLDB may be a
     32 better option for debugging JIT-ed code on Mac OS X.
     33 
     34 
     35 Debugging MCJIT-ed code
     36 =======================
     37 
     38 The emerging MCJIT component of LLVM allows full debugging of JIT-ed code with
     39 GDB.  This is due to MCJIT's ability to use the MC emitter to provide full
     40 DWARF debugging information to GDB.
     41 
     42 Note that lli has to be passed the ``-use-mcjit`` flag to JIT the code with
     43 MCJIT instead of the old JIT.
     44 
     45 Example
     46 -------
     47 
     48 Consider the following C code (with line numbers added to make the example
     49 easier to follow):
     50 
     51 ..
     52    FIXME:
     53    Sphinx has the ability to automatically number these lines by adding
     54    :linenos: on the line immediately following the `.. code-block:: c`, but
     55    it looks like garbage; the line numbers don't even line up with the
     56    lines. Is this a Sphinx bug, or is it a CSS problem?
     57 
     58 .. code-block:: c
     59 
     60    1   int compute_factorial(int n)
     61    2   {
     62    3       if (n <= 1)
     63    4           return 1;
     64    5
     65    6       int f = n;
     66    7       while (--n > 1)
     67    8           f *= n;
     68    9       return f;
     69    10  }
     70    11
     71    12
     72    13  int main(int argc, char** argv)
     73    14  {
     74    15      if (argc < 2)
     75    16          return -1;
     76    17      char firstletter = argv[1][0];
     77    18      int result = compute_factorial(firstletter - '0');
     78    19
     79    20      // Returned result is clipped at 255...
     80    21      return result;
     81    22  }
     82 
     83 Here is a sample command line session that shows how to build and run this
     84 code via ``lli`` inside GDB:
     85 
     86 .. code-block:: bash
     87 
     88    $ $BINPATH/clang -cc1 -O0 -g -emit-llvm showdebug.c
     89    $ gdb --quiet --args $BINPATH/lli -use-mcjit showdebug.ll 5
     90    Reading symbols from $BINPATH/lli...done.
     91    (gdb) b showdebug.c:6
     92    No source file named showdebug.c.
     93    Make breakpoint pending on future shared library load? (y or [n]) y
     94    Breakpoint 1 (showdebug.c:6) pending.
     95    (gdb) r
     96    Starting program: $BINPATH/lli -use-mcjit showdebug.ll 5
     97    [Thread debugging using libthread_db enabled]
     98 
     99    Breakpoint 1, compute_factorial (n=5) at showdebug.c:6
    100    6	    int f = n;
    101    (gdb) p n
    102    $1 = 5
    103    (gdb) p f
    104    $2 = 0
    105    (gdb) n
    106    7	    while (--n > 1)
    107    (gdb) p f
    108    $3 = 5
    109    (gdb) b showdebug.c:9
    110    Breakpoint 2 at 0x7ffff7ed404c: file showdebug.c, line 9.
    111    (gdb) c
    112    Continuing.
    113 
    114    Breakpoint 2, compute_factorial (n=1) at showdebug.c:9
    115    9	    return f;
    116    (gdb) p f
    117    $4 = 120
    118    (gdb) bt
    119    #0  compute_factorial (n=1) at showdebug.c:9
    120    #1  0x00007ffff7ed40a9 in main (argc=2, argv=0x16677e0) at showdebug.c:18
    121    #2  0x3500000001652748 in ?? ()
    122    #3  0x00000000016677e0 in ?? ()
    123    #4  0x0000000000000002 in ?? ()
    124    #5  0x0000000000d953b3 in llvm::MCJIT::runFunction (this=0x16151f0, F=0x1603020, ArgValues=...) at /home/ebenders_test/llvm_svn_rw/lib/ExecutionEngine/MCJIT/MCJIT.cpp:161
    125    #6  0x0000000000dc8872 in llvm::ExecutionEngine::runFunctionAsMain (this=0x16151f0, Fn=0x1603020, argv=..., envp=0x7fffffffe040)
    126        at /home/ebenders_test/llvm_svn_rw/lib/ExecutionEngine/ExecutionEngine.cpp:397
    127    #7  0x000000000059c583 in main (argc=4, argv=0x7fffffffe018, envp=0x7fffffffe040) at /home/ebenders_test/llvm_svn_rw/tools/lli/lli.cpp:324
    128    (gdb) finish
    129    Run till exit from #0  compute_factorial (n=1) at showdebug.c:9
    130    0x00007ffff7ed40a9 in main (argc=2, argv=0x16677e0) at showdebug.c:18
    131    18	    int result = compute_factorial(firstletter - '0');
    132    Value returned is $5 = 120
    133    (gdb) p result
    134    $6 = 23406408
    135    (gdb) n
    136    21	    return result;
    137    (gdb) p result
    138    $7 = 120
    139    (gdb) c
    140    Continuing.
    141 
    142    Program exited with code 0170.
    143    (gdb)
    144