Reid Kleckner | 22884dd | 2009-09-21 02:34:59 +0000 | [diff] [blame] | 1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
| 2 | "http://www.w3.org/TR/html4/strict.dtd"> |
| 3 | <html> |
| 4 | <head> |
NAKAMURA Takumi | 5c6e4df | 2011-10-31 11:21:59 +0000 | [diff] [blame] | 5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> |
Reid Kleckner | 22884dd | 2009-09-21 02:34:59 +0000 | [diff] [blame] | 6 | <title>Debugging JITed Code With GDB</title> |
Daniel Dunbar | adea497 | 2012-04-19 20:20:34 +0000 | [diff] [blame] | 7 | <link rel="stylesheet" href="_static/llvm.css" type="text/css"> |
Reid Kleckner | 22884dd | 2009-09-21 02:34:59 +0000 | [diff] [blame] | 8 | </head> |
| 9 | <body> |
| 10 | |
Eli Bendersky | f8b30f9 | 2012-05-01 06:15:40 +0000 | [diff] [blame^] | 11 | <h1>Debugging JIT-ed Code With GDB</h1> |
Reid Kleckner | 22884dd | 2009-09-21 02:34:59 +0000 | [diff] [blame] | 12 | <ol> |
Reid Kleckner | 8947282 | 2010-07-07 20:16:45 +0000 | [diff] [blame] | 13 | <li><a href="#background">Background</a></li> |
Eli Bendersky | f8b30f9 | 2012-05-01 06:15:40 +0000 | [diff] [blame^] | 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> |
Reid Kleckner | 22884dd | 2009-09-21 02:34:59 +0000 | [diff] [blame] | 19 | </ol> |
Eli Bendersky | f8b30f9 | 2012-05-01 06:15:40 +0000 | [diff] [blame^] | 20 | <div class="doc_author">Written by Reid Kleckner and Eli Bendersky</div> |
Reid Kleckner | 8947282 | 2010-07-07 20:16:45 +0000 | [diff] [blame] | 21 | |
| 22 | <!--=========================================================================--> |
NAKAMURA Takumi | 05d0265 | 2011-04-18 23:59:50 +0000 | [diff] [blame] | 23 | <h2><a name="background">Background</a></h2> |
Reid Kleckner | 8947282 | 2010-07-07 20:16:45 +0000 | [diff] [blame] | 24 | <!--=========================================================================--> |
NAKAMURA Takumi | f5af6ad | 2011-04-23 00:30:22 +0000 | [diff] [blame] | 25 | <div> |
Reid Kleckner | 8947282 | 2010-07-07 20:16:45 +0000 | [diff] [blame] | 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 | |
Reid Kleckner | 8947282 | 2010-07-07 20:16:45 +0000 | [diff] [blame] | 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 |
Eli Bendersky | f8b30f9 | 2012-05-01 06:15:40 +0000 | [diff] [blame^] | 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 |
Reid Kleckner | 8947282 | 2010-07-07 20:16:45 +0000 | [diff] [blame] | 40 | GDB attaches to a process, it puts a breakpoint in this function and loads all |
Eli Bendersky | f8b30f9 | 2012-05-01 06:15:40 +0000 | [diff] [blame^] | 41 | of the object files in the global list. When MCJIT calls the registration |
Reid Kleckner | 8947282 | 2010-07-07 20:16:45 +0000 | [diff] [blame] | 42 | function, GDB catches the breakpoint signal, loads the new object file from |
Eli Bendersky | f8b30f9 | 2012-05-01 06:15:40 +0000 | [diff] [blame^] | 43 | the inferior's memory, and resumes the execution. In this way, GDB can get the |
Reid Kleckner | 8947282 | 2010-07-07 20:16:45 +0000 | [diff] [blame] | 44 | necessary debug information. |
| 45 | </p> |
Reid Kleckner | 8947282 | 2010-07-07 20:16:45 +0000 | [diff] [blame] | 46 | </div> |
Reid Kleckner | 22884dd | 2009-09-21 02:34:59 +0000 | [diff] [blame] | 47 | |
Eli Bendersky | f8b30f9 | 2012-05-01 06:15:40 +0000 | [diff] [blame^] | 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 | |
Reid Kleckner | 22884dd | 2009-09-21 02:34:59 +0000 | [diff] [blame] | 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> |
Eli Bendersky | f8b30f9 | 2012-05-01 06:15:40 +0000 | [diff] [blame^] | 178 | <a href="mailto:reid.kleckner@gmail.com">Reid Kleckner</a>, |
| 179 | <a href="mailto:eliben@gmail.com">Eli Bendersky</a><br> |
NAKAMURA Takumi | b9a3363 | 2011-04-09 02:13:37 +0000 | [diff] [blame] | 180 | <a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br> |
Reid Kleckner | 8947282 | 2010-07-07 20:16:45 +0000 | [diff] [blame] | 181 | Last modified: $Date$ |
Reid Kleckner | 22884dd | 2009-09-21 02:34:59 +0000 | [diff] [blame] | 182 | </address> |
| 183 | </body> |
| 184 | </html> |