• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1==============================
2Debugging JIT-ed Code With GDB
3==============================
4
5Background
6==========
7
8Without special runtime support, debugging dynamically generated code with
9GDB (as well as most debuggers) can be quite painful.  Debuggers generally
10read debug information from the object file of the code, but for JITed
11code, there is no such file to look for.
12
13In order to communicate the necessary debug info to GDB, an interface for
14registering JITed code with debuggers has been designed and implemented for
15GDB and LLVM MCJIT.  At a high level, whenever MCJIT generates new machine code,
16it does so in an in-memory object file that contains the debug information in
17DWARF format.  MCJIT then adds this in-memory object file to a global list of
18dynamically generated object files and calls a special function
19(``__jit_debug_register_code``) marked noinline that GDB knows about.  When
20GDB attaches to a process, it puts a breakpoint in this function and loads all
21of the object files in the global list.  When MCJIT calls the registration
22function, GDB catches the breakpoint signal, loads the new object file from
23the inferior's memory, and resumes the execution.  In this way, GDB can get the
24necessary debug information.
25
26GDB Version
27===========
28
29In order to debug code JIT-ed by LLVM, you need GDB 7.0 or newer, which is
30available on most modern distributions of Linux.  The version of GDB that
31Apple ships with Xcode has been frozen at 6.3 for a while.  LLDB may be a
32better option for debugging JIT-ed code on Mac OS X.
33
34
35Debugging MCJIT-ed code
36=======================
37
38The emerging MCJIT component of LLVM allows full debugging of JIT-ed code with
39GDB.  This is due to MCJIT's ability to use the MC emitter to provide full
40DWARF debugging information to GDB.
41
42Note that lli has to be passed the ``-use-mcjit`` flag to JIT the code with
43MCJIT instead of the old JIT.
44
45Example
46-------
47
48Consider the following C code (with line numbers added to make the example
49easier 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
83Here is a sample command line session that shows how to build and run this
84code 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