[NFC][Py Reformat] Reformat python files in llvm
[llvm-project.git] / lldb / docs / use / intel_pt.rst
blob694615c83fbc22f56653186ff10214992005638a
1 Tracing with Intel Processor Trace
2 ==================================
4 .. contents::
5   :local:
7 Intel PT is a technology available in modern Intel CPUs that allows efficient
8 tracing of all the instructions executed by a process.
9 LLDB can collect traces and dump them using its symbolication stack.
10 You can read more here
11 https://easyperf.net/blog/2019/08/23/Intel-Processor-Trace.
13 Prerequisites
14 -------------
16 Confirm that your CPU supports Intel PT
17 (see https://www.intel.com/content/www/us/en/support/articles/000056730/processors.html)
18 and that your operating system is Linux.
20 Check for the existence of this particular file on your Linux system
24   $ cat /sys/bus/event_source/devices/intel_pt/type
26 The output should be a number. Otherwise, try upgrading your kernel.
29 Build Instructions
30 ------------------
32 Clone and build the low level Intel PT
33 decoder library [LibIPT library](https://github.com/intel/libipt).
36   $ git clone git@github.com:intel/libipt.git
37   $ mkdir libipt-build
38   $ cmake -S libipt -B libipt-build
39   $ cd libipt-build
40   $ make
42 This will generate a few files in the ``<libipt-build>/lib``
43 and ``<libipt-build>/libipt/include`` directories.
45 Configure and build LLDB with Intel PT support
49   $ cmake \
50       -DLLDB_BUILD_INTEL_PT=ON \
51       -DLIBIPT_INCLUDE_PATH="<libipt-build>/libipt/include" \
52       -DLIBIPT_LIBRARY_PATH="<libipt-build>/lib" \
53       ... other common configuration parameters
57   $ cd <lldb-build> && ninja lldb lldb-server # if using Ninja
60 How to Use
61 ----------
63 When you are debugging a process, you can turn on intel-pt tracing,
64 which will “record” all the instructions that the process will execute.
65 After turning it on, you can continue debugging, and at any breakpoint,
66 you can inspect the instruction list.
68 For example:
72   lldb <target>
73   > b main
74   > run
75   > process trace start # start tracing on all threads, including future ones
76   # keep debugging until you hit a breakpoint
78   > thread trace dump instructions
79   # this should output something like
81   thread #2: tid = 2861133, total instructions = 5305673
82     libc.so.6`__GI___libc_read + 45 at read.c:25:1
83       [4962255] 0x00007fffeb64c63d    subq   $0x10, %rsp
84       [4962256] 0x00007fffeb64c641    movq   %rdi, -0x18(%rbp)
85     libc.so.6`__GI___libc_read + 53 [inlined] __libc_read at read.c:26:10
86       [4962257] 0x00007fffeb64c645    callq  0x7fffeb66b640            ; __libc_enable_asynccancel
87     libc.so.6`__libc_enable_asynccancel
88       [4962258] 0x00007fffeb66b640    movl   %fs:0x308, %eax
89     libc.so.6`__libc_enable_asynccancel + 8
90       [4962259] 0x00007fffeb66b648    movl   %eax, %r11d
92   # you can keep pressing ENTER to see more and more instructions
94 The number between brackets is the instruction index,
95 and by default the current thread will be picked.
97 Configuring the trace size
98 --------------------------
100 The CPU stores the instruction list in a compressed format in a ring buffer,
101 which keeps the latest information.
102 By default, LLDB uses a buffer of 4KB per thread,
103 but you can change it by running.
104 The size must be a power of 2 and at least 4KB.
108   thread trace start all -s <size_in_bytes>
110 For reference, a 1MB trace buffer can easily store around 5M instructions.
112 Printing more instructions
113 --------------------------
115 If you want to dump more instructions at a time, you can run
119   thread trace dump instructions -c <count>
121 Printing the instructions of another thread
122 -------------------------------------------
124 By default the current thread will be picked when dumping instructions,
125 but you can do
129   thread trace dump instructions <#thread index>
130   #e.g.
131   thread trace dump instructions 8
133 to select another thread.
135 Crash Analysis
136 --------------
138 What if you are debugging + tracing a process that crashes?
139 Then you can just do
143   thread trace dump instructions
145 To inspect how it crashed! There's nothing special that you need to do.
146 For example
150     * thread #1, name = 'a.out', stop reason = signal SIGFPE: integer divide by zero
151         frame #0: 0x00000000004009f1 a.out`main at main.cpp:8:14
152       6       int x;
153       7       cin >> x;
154    -> 8       cout << 12 / x << endl;
155       9       return 0;
156       10  }
157     (lldb) thread trace dump instructions -c 5
158     thread #1: tid = 604302, total instructions = 8388
159       libstdc++.so.6`std::istream::operator>>(int&) + 181
160         [8383] 0x00007ffff7b41665    popq   %rbp
161         [8384] 0x00007ffff7b41666    retq
162       a.out`main + 66 at main.cpp:8:14
163         [8385] 0x00000000004009e8    movl   -0x4(%rbp), %ecx
164         [8386] 0x00000000004009eb    movl   $0xc, %eax
165         [8387] 0x00000000004009f0    cltd
167 .. note::
168   At this moment, we are not including the failed instruction in the trace,
169   but in the future we might do it for readability.
172 Offline Trace Analysis
173 ----------------------
175 It's also possible to record a trace using a custom Intel PT collector
176 and decode + symbolicate the trace using LLDB.
177 For that, the command trace load is useful.
178 In order to use trace load, you need to first create a JSON file with
179 the definition of the trace session.
180 For example
184   {
185     "type": "intel-pt",
186     "cpuInfo": {
187       "vendor": "GenuineIntel",
188       "family": 6,
189       "model": 79,
190       "stepping": 1
191     },
192     "processes": [
193       {
194         "pid": 815455,
195         "triple": "x86_64-*-linux",
196         "threads": [
197           {
198             "tid": 815455,
199             "iptTrace": "trace.file" # raw thread-specific trace from the AUX buffer
200           }
201         ],
202         "modules": [ # this are all the shared libraries + the main executable
203           {
204             "file": "a.out", # optional if it's the same as systemPath
205             "systemPath": "a.out",
206             "loadAddress": 4194304,
207           },
208           {
209             "file": "libfoo.so",
210             "systemPath": "/usr/lib/libfoo.so",
211             "loadAddress": "0x00007ffff7bd9000",
212           },
213           {
214             "systemPath": "libbar.so",
215             "loadAddress": "0x00007ffff79d7000",
216           }
217         ]
218       }
219     ]
220   }
222 You can see the full schema by typing
226   trace schema intel-pt
228 The JSON file mainly contains all the shared libraries that
229 were part of the traced process, along with their memory load address.
230 If the analysis is done on the same computer where the traces were obtained,
231 it's enough to use the “systemPath” field.
232 If the analysis is done on a different machines, these files need to be
233 copied over and the “file” field should point to the
234 location of the file relative to the JSON file.
235 Once you have the JSON file and the module files in place, you can simple run
239   lldb
240   > trace load /path/to/json
241   > thread trace dump instructions <optional thread index>
243 Then it's like in the live session case
245 References
246 ----------
248 - Original RFC document_ for this feature.
249 - Some details about how Meta is using Intel Processor Trace can be found in this blog_ post.
251 .. _document: https://docs.google.com/document/d/1cOVTGp1sL_HBXjP9eB7qjVtDNr5xnuZvUUtv43G5eVI
252 .. _blog: https://engineering.fb.com/2021/04/27/developer-tools/reverse-debugging/