1*332e220eSStefan Gränitz=====================
2*332e220eSStefan GränitzDebugging JIT-ed Code
3*332e220eSStefan Gränitz=====================
451fc86ddSSean Silva
551fc86ddSSean SilvaBackground
651fc86ddSSean Silva==========
751fc86ddSSean Silva
8*332e220eSStefan GränitzWithout special runtime support, debugging dynamically generated code can be
9*332e220eSStefan Gränitzquite painful.  Debuggers generally read debug information from object files on
10*332e220eSStefan Gränitzdisk, but for JITed code there is no such file to look for.
1151fc86ddSSean Silva
12*332e220eSStefan GränitzIn order to hand over the necessary debug info, `GDB established an
13*332e220eSStefan Gränitzinterface <https://sourceware.org/gdb/current/onlinedocs/gdb/JIT-Interface.html>`_
14*332e220eSStefan Gränitzfor registering JITed code with debuggers. LLDB implements it in the
15*332e220eSStefan GränitzJITLoaderGDB plugin.  On the JIT side, LLVM MCJIT does implement the interface
16*332e220eSStefan Gränitzfor ELF object files.
17*332e220eSStefan Gränitz
18*332e220eSStefan GränitzAt a high level, whenever MCJIT generates new machine code, it does so in an
19*332e220eSStefan Gränitzin-memory object file that contains the debug information in DWARF format.
20*332e220eSStefan GränitzMCJIT then adds this in-memory object file to a global list of dynamically
21*332e220eSStefan Gränitzgenerated object files and calls a special function
22*332e220eSStefan Gränitz``__jit_debug_register_code`` that the debugger knows about. When the debugger
23*332e220eSStefan Gränitzattaches to a process, it puts a breakpoint in this function and associates a
24*332e220eSStefan Gränitzspecial handler with it.  Once MCJIT calls the registration function, the
25*332e220eSStefan Gränitzdebugger catches the breakpoint signal, loads the new object file from the
26*332e220eSStefan Gränitzinferior's memory and resumes execution.  This way it can obtain debug
27*332e220eSStefan Gränitzinformation for pure in-memory object files.
28*332e220eSStefan Gränitz
2951fc86ddSSean Silva
3051fc86ddSSean SilvaGDB Version
3151fc86ddSSean Silva===========
3251fc86ddSSean Silva
3351fc86ddSSean SilvaIn order to debug code JIT-ed by LLVM, you need GDB 7.0 or newer, which is
3451fc86ddSSean Silvaavailable on most modern distributions of Linux.  The version of GDB that
35*332e220eSStefan GränitzApple ships with Xcode has been frozen at 6.3 for a while.
36*332e220eSStefan Gränitz
37*332e220eSStefan Gränitz
38*332e220eSStefan GränitzLLDB Version
39*332e220eSStefan Gränitz============
40*332e220eSStefan Gränitz
41*332e220eSStefan GränitzDue to a regression in release 6.0, LLDB didn't support JITed code debugging for
42*332e220eSStefan Gränitza while.  The bug was fixed in mainline recently, so that debugging JITed ELF
43*332e220eSStefan Gränitzobjects should be possible again from the upcoming release 12.0 on. On macOS the
44*332e220eSStefan Gränitzfeature must be enabled explicitly using the ``plugin.jit-loader.gdb.enable``
45*332e220eSStefan Gränitzsetting.
4651fc86ddSSean Silva
4751fc86ddSSean Silva
4851fc86ddSSean SilvaDebugging MCJIT-ed code
4951fc86ddSSean Silva=======================
5051fc86ddSSean Silva
5151fc86ddSSean SilvaThe emerging MCJIT component of LLVM allows full debugging of JIT-ed code with
5251fc86ddSSean SilvaGDB.  This is due to MCJIT's ability to use the MC emitter to provide full
5351fc86ddSSean SilvaDWARF debugging information to GDB.
5451fc86ddSSean Silva
55*332e220eSStefan GränitzNote that lli has to be passed the ``--jit-kind=mcjit`` flag to JIT the code
56*332e220eSStefan Gränitzwith MCJIT instead of the newer ORC JIT.
5751fc86ddSSean Silva
5851fc86ddSSean SilvaExample
5951fc86ddSSean Silva-------
6051fc86ddSSean Silva
6151fc86ddSSean SilvaConsider the following C code (with line numbers added to make the example
6251fc86ddSSean Silvaeasier to follow):
6351fc86ddSSean Silva
6451fc86ddSSean Silva..
6551fc86ddSSean Silva   FIXME:
6651fc86ddSSean Silva   Sphinx has the ability to automatically number these lines by adding
6751fc86ddSSean Silva   :linenos: on the line immediately following the `.. code-block:: c`, but
6851fc86ddSSean Silva   it looks like garbage; the line numbers don't even line up with the
6951fc86ddSSean Silva   lines. Is this a Sphinx bug, or is it a CSS problem?
7051fc86ddSSean Silva
7151fc86ddSSean Silva.. code-block:: c
7251fc86ddSSean Silva
7351fc86ddSSean Silva   1   int compute_factorial(int n)
7451fc86ddSSean Silva   2   {
7551fc86ddSSean Silva   3       if (n <= 1)
7651fc86ddSSean Silva   4           return 1;
7751fc86ddSSean Silva   5
7851fc86ddSSean Silva   6       int f = n;
7951fc86ddSSean Silva   7       while (--n > 1)
8051fc86ddSSean Silva   8           f *= n;
8151fc86ddSSean Silva   9       return f;
8251fc86ddSSean Silva   10  }
8351fc86ddSSean Silva   11
8451fc86ddSSean Silva   12
8551fc86ddSSean Silva   13  int main(int argc, char** argv)
8651fc86ddSSean Silva   14  {
8751fc86ddSSean Silva   15      if (argc < 2)
8851fc86ddSSean Silva   16          return -1;
8951fc86ddSSean Silva   17      char firstletter = argv[1][0];
9051fc86ddSSean Silva   18      int result = compute_factorial(firstletter - '0');
9151fc86ddSSean Silva   19
9251fc86ddSSean Silva   20      // Returned result is clipped at 255...
9351fc86ddSSean Silva   21      return result;
9451fc86ddSSean Silva   22  }
9551fc86ddSSean Silva
9651fc86ddSSean SilvaHere is a sample command line session that shows how to build and run this
97*332e220eSStefan Gränitzcode via ``lli`` inside LLDB:
9851fc86ddSSean Silva
9951fc86ddSSean Silva.. code-block:: bash
10051fc86ddSSean Silva
101*332e220eSStefan Gränitz   > export BINPATH=/workspaces/llvm-project/build/bin
102*332e220eSStefan Gränitz   > $BINPATH/clang -g -S -emit-llvm --target=x86_64-unknown-unknown-elf showdebug.c
103*332e220eSStefan Gränitz   > lldb $BINPATH/lli
104*332e220eSStefan Gränitz   (lldb) target create "/workspaces/llvm-project/build/bin/lli"
105*332e220eSStefan Gränitz   Current executable set to '/workspaces/llvm-project/build/bin/lli' (x86_64).
106*332e220eSStefan Gränitz   (lldb) settings set plugin.jit-loader.gdb.enable on
107*332e220eSStefan Gränitz   (lldb) b compute_factorial
108*332e220eSStefan Gränitz   Breakpoint 1: no locations (pending).
109*332e220eSStefan Gränitz   WARNING:  Unable to resolve breakpoint to any actual locations.
110*332e220eSStefan Gränitz   (lldb) run --jit-kind=mcjit showdebug.ll 5
111*332e220eSStefan Gränitz   1 location added to breakpoint 1
112*332e220eSStefan Gränitz   Process 21340 stopped
113*332e220eSStefan Gränitz   * thread #1, name = 'lli', stop reason = breakpoint 1.1
114*332e220eSStefan Gränitz      frame #0: 0x00007ffff7fd0007 JIT(0x45c2cb0)`compute_factorial(n=5) at showdebug.c:3:11
115*332e220eSStefan Gränitz      1    int compute_factorial(int n)
116*332e220eSStefan Gränitz      2    {
117*332e220eSStefan Gränitz   -> 3        if (n <= 1)
118*332e220eSStefan Gränitz      4            return 1;
119*332e220eSStefan Gränitz      5        int f = n;
120*332e220eSStefan Gränitz      6        while (--n > 1)
121*332e220eSStefan Gränitz      7            f *= n;
122*332e220eSStefan Gränitz   (lldb) p n
123*332e220eSStefan Gränitz   (int) $0 = 5
124*332e220eSStefan Gränitz   (lldb) b showdebug.c:9
125*332e220eSStefan Gränitz   Breakpoint 2: where = JIT(0x45c2cb0)`compute_factorial + 60 at showdebug.c:9:1, address = 0x00007ffff7fd003c
126*332e220eSStefan Gränitz   (lldb) c
127*332e220eSStefan Gränitz   Process 21340 resuming
128*332e220eSStefan Gränitz   Process 21340 stopped
129*332e220eSStefan Gränitz   * thread #1, name = 'lli', stop reason = breakpoint 2.1
130*332e220eSStefan Gränitz      frame #0: 0x00007ffff7fd003c JIT(0x45c2cb0)`compute_factorial(n=1) at showdebug.c:9:1
131*332e220eSStefan Gränitz      6        while (--n > 1)
132*332e220eSStefan Gränitz      7            f *= n;
133*332e220eSStefan Gränitz      8        return f;
134*332e220eSStefan Gränitz   -> 9    }
135*332e220eSStefan Gränitz      10
136*332e220eSStefan Gränitz      11   int main(int argc, char** argv)
137*332e220eSStefan Gränitz      12   {
138*332e220eSStefan Gränitz   (lldb) p f
139*332e220eSStefan Gränitz   (int) $1 = 120
140*332e220eSStefan Gränitz   (lldb) bt
141*332e220eSStefan Gränitz   * thread #1, name = 'lli', stop reason = breakpoint 2.1
142*332e220eSStefan Gränitz   * frame #0: 0x00007ffff7fd003c JIT(0x45c2cb0)`compute_factorial(n=1) at showdebug.c:9:1
143*332e220eSStefan Gränitz      frame #1: 0x00007ffff7fd0095 JIT(0x45c2cb0)`main(argc=2, argv=0x00000000046122f0) at showdebug.c:16:18
144*332e220eSStefan Gränitz      frame #2: 0x0000000002a8306e lli`llvm::MCJIT::runFunction(this=0x000000000458ed10, F=0x0000000004589ff8, ArgValues=ArrayRef<llvm::GenericValue> @ 0x00007fffffffc798) at MCJIT.cpp:554:31
145*332e220eSStefan Gränitz      frame #3: 0x00000000029bdb45 lli`llvm::ExecutionEngine::runFunctionAsMain(this=0x000000000458ed10, Fn=0x0000000004589ff8, argv=size=0, envp=0x00007fffffffe140) at ExecutionEngine.cpp:467:10
146*332e220eSStefan Gränitz      frame #4: 0x0000000001f2fc2f lli`main(argc=4, argv=0x00007fffffffe118, envp=0x00007fffffffe140) at lli.cpp:643:18
147*332e220eSStefan Gränitz      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*332e220eSStefan Gränitz      frame #6: 0x0000000001f2dc7a lli`_start + 42
149*332e220eSStefan Gränitz   (lldb) finish
150*332e220eSStefan Gränitz   Process 21340 stopped
151*332e220eSStefan Gränitz   * thread #1, name = 'lli', stop reason = step out
152*332e220eSStefan Gränitz   Return value: (int) $2 = 120
15351fc86ddSSean Silva
154*332e220eSStefan Gränitz      frame #0: 0x00007ffff7fd0095 JIT(0x45c2cb0)`main(argc=2, argv=0x00000000046122f0) at showdebug.c:16:9
155*332e220eSStefan Gränitz      13       if (argc < 2)
156*332e220eSStefan Gränitz      14           return -1;
157*332e220eSStefan Gränitz      15       char firstletter = argv[1][0];
158*332e220eSStefan Gränitz   -> 16       int result = compute_factorial(firstletter - '0');
159*332e220eSStefan Gränitz      17
160*332e220eSStefan Gränitz      18       // Returned result is clipped at 255...
161*332e220eSStefan Gränitz      19       return result;
162*332e220eSStefan Gränitz   (lldb) p result
163*332e220eSStefan Gränitz   (int) $3 = 73670648
164*332e220eSStefan Gränitz   (lldb) n
165*332e220eSStefan Gränitz   Process 21340 stopped
166*332e220eSStefan Gränitz   * thread #1, name = 'lli', stop reason = step over
167*332e220eSStefan Gränitz      frame #0: 0x00007ffff7fd0098 JIT(0x45c2cb0)`main(argc=2, argv=0x00000000046122f0) at showdebug.c:19:12
168*332e220eSStefan Gränitz      16       int result = compute_factorial(firstletter - '0');
169*332e220eSStefan Gränitz      17
170*332e220eSStefan Gränitz      18       // Returned result is clipped at 255...
171*332e220eSStefan Gränitz   -> 19       return result;
172*332e220eSStefan Gränitz      20   }
173*332e220eSStefan Gränitz   (lldb) p result
174*332e220eSStefan Gränitz   (int) $4 = 120
175*332e220eSStefan Gränitz   (lldb) expr result=42
176*332e220eSStefan Gränitz   (int) $5 = 42
177*332e220eSStefan Gränitz   (lldb) p result
178*332e220eSStefan Gränitz   (int) $6 = 42
179*332e220eSStefan Gränitz   (lldb) c
180*332e220eSStefan Gränitz   Process 21340 resuming
181*332e220eSStefan Gränitz   Process 21340 exited with status = 42 (0x0000002a)
182*332e220eSStefan Gränitz   (lldb) exit
183