Home | History | Annotate | Download | only in docs
      1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
      2                       "http://www.w3.org/TR/html4/strict.dtd">
      3 <html>
      4 <head>
      5   <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      6   <title>Debugging JITed Code With GDB</title>
      7   <link rel="stylesheet" href="_static/llvm.css" type="text/css">
      8 </head>
      9 <body>
     10 
     11 <h1>Debugging JIT-ed Code With GDB</h1>
     12 <ol>
     13   <li><a href="#background">Background</a></li>
     14   <li><a href="#gdbversion">GDB Version</a></li>
     15   <li><a href="#mcjitdebug">Debugging MCJIT-ed code</a></li>
     16   <ul>
     17     <li><a href="#mcjitdebug_example">Example</a></li>
     18   </ul>
     19 </ol>
     20 <div class="doc_author">Written by Reid Kleckner and Eli Bendersky</div>
     21 
     22 <!--=========================================================================-->
     23 <h2><a name="background">Background</a></h2>
     24 <!--=========================================================================-->
     25 <div>
     26 
     27 <p>Without special runtime support, debugging dynamically generated code with
     28 GDB (as well as most debuggers) can be quite painful.  Debuggers generally read
     29 debug information from the object file of the code, but for JITed code, there is
     30 no such file to look for.
     31 </p>
     32 
     33 <p>In order to communicate the necessary debug info to GDB, an interface for
     34 registering JITed code with debuggers has been designed and implemented for
     35 GDB and LLVM MCJIT.  At a high level, whenever MCJIT generates new machine code,
     36 it does so in an in-memory object file that contains the debug information in
     37 DWARF format.  MCJIT then adds this in-memory object file to a global list of
     38 dynamically generated object files and calls a special function
     39 (<tt>__jit_debug_register_code</tt>) marked noinline that GDB knows about.  When
     40 GDB attaches to a process, it puts a breakpoint in this function and loads all
     41 of the object files in the global list.  When MCJIT calls the registration
     42 function, GDB catches the breakpoint signal, loads the new object file from
     43 the inferior's memory, and resumes the execution.  In this way, GDB can get the
     44 necessary debug information.
     45 </p>
     46 </div>
     47 
     48 <!--=========================================================================-->
     49 <h2><a name="gdbversion">GDB Version</a></h2>
     50 <!--=========================================================================-->
     51 
     52 <p>In order to debug code JIT-ed by LLVM, you need GDB 7.0 or newer, which is
     53 available on most modern distributions of Linux.  The version of GDB that Apple
     54 ships with Xcode has been frozen at 6.3 for a while.  LLDB may be a better
     55 option for debugging JIT-ed code on Mac OS X.
     56 </p>
     57 
     58 
     59 <!--=========================================================================-->
     60 <h2><a name="mcjitdebug">Debugging MCJIT-ed code</a></h2>
     61 <!--=========================================================================-->
     62 <div>
     63 
     64 <p>The emerging MCJIT component of LLVM allows full debugging of JIT-ed code with
     65 GDB.  This is due to MCJIT's ability to use the MC emitter to provide full
     66 DWARF debugging information to GDB.</p>
     67 
     68 <p>Note that lli has to be passed the <tt>-use-mcjit</tt> flag to JIT the code
     69 with MCJIT instead of the old JIT.</p>
     70 
     71 <h3><a name="mcjitdebug_example">Example</a></h3>
     72 
     73 <div>
     74 
     75 <p>Consider the following C code (with line numbers added to make the example
     76 easier to follow):</p>
     77 
     78 <pre class="doc_code">
     79 1   int compute_factorial(int n)
     80 2   {
     81 3       if (n <= 1)
     82 4           return 1;
     83 5
     84 6       int f = n;
     85 7       while (--n > 1) 
     86 8           f *= n;
     87 9       return f;
     88 10  }
     89 11
     90 12
     91 13  int main(int argc, char** argv)
     92 14  {
     93 15      if (argc < 2)
     94 16          return -1;
     95 17      char firstletter = argv[1][0];
     96 18      int result = compute_factorial(firstletter - '0');
     97 19  
     98 20      // Returned result is clipped at 255...
     99 21      return result;
    100 22  }
    101 </pre>
    102 
    103 <p>Here is a sample command line session that shows how to build and run this
    104 code via lli inside GDB:
    105 </p>
    106 
    107 <pre class="doc_code">
    108 $ $BINPATH/clang -cc1 -O0 -g -emit-llvm showdebug.c
    109 $ gdb --quiet --args $BINPATH/lli -use-mcjit showdebug.ll 5
    110 Reading symbols from $BINPATH/lli...done.
    111 (gdb) b showdebug.c:6
    112 No source file named showdebug.c.
    113 Make breakpoint pending on future shared library load? (y or [n]) y
    114 Breakpoint 1 (showdebug.c:6) pending.
    115 (gdb) r
    116 Starting program: $BINPATH/lli -use-mcjit showdebug.ll 5
    117 [Thread debugging using libthread_db enabled]
    118 
    119 Breakpoint 1, compute_factorial (n=5) at showdebug.c:6
    120 6	    int f = n;
    121 (gdb) p n
    122 $1 = 5
    123 (gdb) p f
    124 $2 = 0
    125 (gdb) n
    126 7	    while (--n > 1) 
    127 (gdb) p f
    128 $3 = 5
    129 (gdb) b showdebug.c:9
    130 Breakpoint 2 at 0x7ffff7ed404c: file showdebug.c, line 9.
    131 (gdb) c
    132 Continuing.
    133 
    134 Breakpoint 2, compute_factorial (n=1) at showdebug.c:9
    135 9	    return f;
    136 (gdb) p f
    137 $4 = 120
    138 (gdb) bt
    139 #0  compute_factorial (n=1) at showdebug.c:9
    140 #1  0x00007ffff7ed40a9 in main (argc=2, argv=0x16677e0) at showdebug.c:18
    141 #2  0x3500000001652748 in ?? ()
    142 #3  0x00000000016677e0 in ?? ()
    143 #4  0x0000000000000002 in ?? ()
    144 #5  0x0000000000d953b3 in llvm::MCJIT::runFunction (this=0x16151f0, F=0x1603020, ArgValues=...) at /home/ebenders_test/llvm_svn_rw/lib/ExecutionEngine/MCJIT/MCJIT.cpp:161
    145 #6  0x0000000000dc8872 in llvm::ExecutionEngine::runFunctionAsMain (this=0x16151f0, Fn=0x1603020, argv=..., envp=0x7fffffffe040)
    146     at /home/ebenders_test/llvm_svn_rw/lib/ExecutionEngine/ExecutionEngine.cpp:397
    147 #7  0x000000000059c583 in main (argc=4, argv=0x7fffffffe018, envp=0x7fffffffe040) at /home/ebenders_test/llvm_svn_rw/tools/lli/lli.cpp:324
    148 (gdb) finish
    149 Run till exit from #0  compute_factorial (n=1) at showdebug.c:9
    150 0x00007ffff7ed40a9 in main (argc=2, argv=0x16677e0) at showdebug.c:18
    151 18	    int result = compute_factorial(firstletter - '0');
    152 Value returned is $5 = 120
    153 (gdb) p result
    154 $6 = 23406408
    155 (gdb) n
    156 21	    return result;
    157 (gdb) p result
    158 $7 = 120
    159 (gdb) c
    160 Continuing.
    161 
    162 Program exited with code 0170.
    163 (gdb) 
    164 
    165 </pre>
    166 
    167 </div>
    168 </div>
    169 
    170 
    171 <!-- *********************************************************************** -->
    172 <hr>
    173 <address>
    174   <a href="http://jigsaw.w3.org/css-validator/check/referer"><img
    175   src="http://jigsaw.w3.org/css-validator/images/vcss-blue" alt="Valid CSS"></a>
    176   <a href="http://validator.w3.org/check/referer"><img
    177   src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
    178   <a href="mailto:reid.kleckner (a] gmail.com">Reid Kleckner</a>,
    179   <a href="mailto:eliben (a] gmail.com">Eli Bendersky</a><br>
    180   <a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
    181   Last modified: $Date$
    182 </address>
    183 </body>
    184 </html>
    185