xref: /llvm-project/llvm/docs/DebuggingJITedCode.rst (revision 24b780ce74beec4ef457da479ac7ef7d3b649a3e)
1=====================
2Debugging JIT-ed Code
3=====================
4
5Background
6==========
7
8Without special runtime support, debugging dynamically generated code can be
9quite painful.  Debuggers generally read debug information from object files on
10disk, but for JITed code there is no such file to look for.
11
12In order to hand over the necessary debug info, `GDB established an
13interface <https://sourceware.org/gdb/onlinedocs/gdb/JIT-Interface.html>`_
14for registering JITed code with debuggers. LLDB implements it in the
15JITLoaderGDB plugin.  On the JIT side, LLVM MCJIT does implement the interface
16for ELF object files.
17
18At a high level, whenever MCJIT generates new machine code, it does so in an
19in-memory object file that contains the debug information in DWARF format.
20MCJIT then adds this in-memory object file to a global list of dynamically
21generated object files and calls a special function
22``__jit_debug_register_code`` that the debugger knows about. When the debugger
23attaches to a process, it puts a breakpoint in this function and associates a
24special handler with it.  Once MCJIT calls the registration function, the
25debugger catches the breakpoint signal, loads the new object file from the
26inferior's memory and resumes execution.  This way it can obtain debug
27information for pure in-memory object files.
28
29
30GDB Version
31===========
32
33In order to debug code JIT-ed by LLVM, you need GDB 7.0 or newer, which is
34available on most modern distributions of Linux.  The version of GDB that
35Apple ships with Xcode has been frozen at 6.3 for a while.
36
37
38LLDB Version
39============
40
41Due to a regression in release 6.0, LLDB didn't support JITed code debugging for
42a while.  The bug was fixed in mainline recently, so that debugging JITed ELF
43objects should be possible again from the upcoming release 12.0 on. On macOS the
44feature must be enabled explicitly using the ``plugin.jit-loader.gdb.enable``
45setting.
46
47
48Debugging MCJIT-ed code
49=======================
50
51The emerging MCJIT component of LLVM allows full debugging of JIT-ed code with
52GDB.  This is due to MCJIT's ability to use the MC emitter to provide full
53DWARF debugging information to GDB.
54
55Note that lli has to be passed the ``--jit-kind=mcjit`` flag to JIT the code
56with MCJIT instead of the newer ORC JIT.
57
58Example
59-------
60
61Consider the following C code (with line numbers added to make the example
62easier to follow):
63
64..
65   FIXME:
66   Sphinx has the ability to automatically number these lines by adding
67   :linenos: on the line immediately following the `.. code-block:: c`, but
68   it looks like garbage; the line numbers don't even line up with the
69   lines. Is this a Sphinx bug, or is it a CSS problem?
70
71.. code-block:: c
72
73   1   int compute_factorial(int n)
74   2   {
75   3       if (n <= 1)
76   4           return 1;
77   5
78   6       int f = n;
79   7       while (--n > 1)
80   8           f *= n;
81   9       return f;
82   10  }
83   11
84   12
85   13  int main(int argc, char** argv)
86   14  {
87   15      if (argc < 2)
88   16          return -1;
89   17      char firstletter = argv[1][0];
90   18      int result = compute_factorial(firstletter - '0');
91   19
92   20      // Returned result is clipped at 255...
93   21      return result;
94   22  }
95
96Here is a sample command line session that shows how to build and run this
97code via ``lli`` inside LLDB:
98
99.. code-block:: bash
100
101   > export BINPATH=/workspaces/llvm-project/build/bin
102   > $BINPATH/clang -g -S -emit-llvm --target=x86_64-unknown-unknown-elf showdebug.c
103   > lldb $BINPATH/lli
104   (lldb) target create "/workspaces/llvm-project/build/bin/lli"
105   Current executable set to '/workspaces/llvm-project/build/bin/lli' (x86_64).
106   (lldb) settings set plugin.jit-loader.gdb.enable on
107   (lldb) b compute_factorial
108   Breakpoint 1: no locations (pending).
109   WARNING:  Unable to resolve breakpoint to any actual locations.
110   (lldb) run --jit-kind=mcjit showdebug.ll 5
111   1 location added to breakpoint 1
112   Process 21340 stopped
113   * thread #1, name = 'lli', stop reason = breakpoint 1.1
114      frame #0: 0x00007ffff7fd0007 JIT(0x45c2cb0)`compute_factorial(n=5) at showdebug.c:3:11
115      1    int compute_factorial(int n)
116      2    {
117   -> 3        if (n <= 1)
118      4            return 1;
119      5        int f = n;
120      6        while (--n > 1)
121      7            f *= n;
122   (lldb) p n
123   (int) $0 = 5
124   (lldb) b showdebug.c:9
125   Breakpoint 2: where = JIT(0x45c2cb0)`compute_factorial + 60 at showdebug.c:9:1, address = 0x00007ffff7fd003c
126   (lldb) c
127   Process 21340 resuming
128   Process 21340 stopped
129   * thread #1, name = 'lli', stop reason = breakpoint 2.1
130      frame #0: 0x00007ffff7fd003c JIT(0x45c2cb0)`compute_factorial(n=1) at showdebug.c:9:1
131      6        while (--n > 1)
132      7            f *= n;
133      8        return f;
134   -> 9    }
135      10
136      11   int main(int argc, char** argv)
137      12   {
138   (lldb) p f
139   (int) $1 = 120
140   (lldb) bt
141   * thread #1, name = 'lli', stop reason = breakpoint 2.1
142   * frame #0: 0x00007ffff7fd003c JIT(0x45c2cb0)`compute_factorial(n=1) at showdebug.c:9:1
143      frame #1: 0x00007ffff7fd0095 JIT(0x45c2cb0)`main(argc=2, argv=0x00000000046122f0) at showdebug.c:16:18
144      frame #2: 0x0000000002a8306e lli`llvm::MCJIT::runFunction(this=0x000000000458ed10, F=0x0000000004589ff8, ArgValues=ArrayRef<llvm::GenericValue> @ 0x00007fffffffc798) at MCJIT.cpp:554:31
145      frame #3: 0x00000000029bdb45 lli`llvm::ExecutionEngine::runFunctionAsMain(this=0x000000000458ed10, Fn=0x0000000004589ff8, argv=size=0, envp=0x00007fffffffe140) at ExecutionEngine.cpp:467:10
146      frame #4: 0x0000000001f2fc2f lli`main(argc=4, argv=0x00007fffffffe118, envp=0x00007fffffffe140) at lli.cpp:643:18
147      frame #5: 0x00007ffff788c09b libc.so.6`__libc_start_main(main=(lli`main at lli.cpp:387), argc=4, argv=0x00007fffffffe118, init=<unavailable>, fini=<unavailable>, rtld_fini=<unavailable>, stack_end=0x00007fffffffe108) at libc-start.c:308:16
148      frame #6: 0x0000000001f2dc7a lli`_start + 42
149   (lldb) finish
150   Process 21340 stopped
151   * thread #1, name = 'lli', stop reason = step out
152   Return value: (int) $2 = 120
153
154      frame #0: 0x00007ffff7fd0095 JIT(0x45c2cb0)`main(argc=2, argv=0x00000000046122f0) at showdebug.c:16:9
155      13       if (argc < 2)
156      14           return -1;
157      15       char firstletter = argv[1][0];
158   -> 16       int result = compute_factorial(firstletter - '0');
159      17
160      18       // Returned result is clipped at 255...
161      19       return result;
162   (lldb) p result
163   (int) $3 = 73670648
164   (lldb) n
165   Process 21340 stopped
166   * thread #1, name = 'lli', stop reason = step over
167      frame #0: 0x00007ffff7fd0098 JIT(0x45c2cb0)`main(argc=2, argv=0x00000000046122f0) at showdebug.c:19:12
168      16       int result = compute_factorial(firstletter - '0');
169      17
170      18       // Returned result is clipped at 255...
171   -> 19       return result;
172      20   }
173   (lldb) p result
174   (int) $4 = 120
175   (lldb) expr result=42
176   (int) $5 = 42
177   (lldb) p result
178   (int) $6 = 42
179   (lldb) c
180   Process 21340 resuming
181   Process 21340 exited with status = 42 (0x0000002a)
182   (lldb) exit
183