Commit | Line | Data |
---|---|---|
34a4aed0 AB |
1 | Babeltrace Debug Info Analysis |
2 | ----------------------------- | |
3 | ||
4 | The babeltrace debug info analysis is a set of features which allow | |
5 | mapping events from a trace to their location in source code or within | |
6 | a binary file, based on their `ip` (instruction pointer) field. | |
7 | ||
8 | Prerequisites | |
9 | ------------- | |
10 | ||
11 | In order to install a version of babeltrace with debug info support, | |
12 | the following libraries are required: | |
13 | ||
14 | * libelf | |
15 | * libdw | |
16 | ||
17 | Both of them are provided by the elfutils project | |
18 | (https://fedorahosted.org/elfutils/), and can be installed through the | |
19 | elfutils package on Ubuntu, Debian, RHEL, and others. | |
20 | ||
21 | Compiling for Debug Info Analysis | |
22 | --------------------------------- | |
23 | ||
24 | Traced programs on which debug info analysis is to be performed can be | |
25 | compiled in a few different ways, and still lead to useful results. | |
26 | ||
27 | Ideally, one should compile the program in debug mode, which is | |
28 | achieved on gcc by simply using the `-g` flag. This generates debug | |
29 | information in the operating system's native format, which is then | |
30 | used by babeltrace to map an event's source location to a file and | |
31 | line number, and the name of the surrounding function. | |
32 | ||
33 | Do note that only debug information in DWARF format, version 2 or | |
34 | later, is currently supported by babeltrace. Use the `-gdwarf` or | |
35 | `-gdwarf-(VERSION)` to explicitly generate DWARF debug information. | |
36 | ||
37 | If the executable is not compiled with `-g` or an equivalent option | |
38 | enabled, and thus no DWARF information is available, babeltrace will | |
39 | use ELF symbols from the executable. Instead of providing source file, | |
40 | line number and function name, however, the analysis will provide the | |
41 | name of the nearest function symbol, plus an offset in bytes to the | |
42 | location in the executable from which the event originated. | |
43 | ||
44 | If the executable has neither ELF symbols nor DWARF information, | |
45 | babeltrace will be unable to map an event to its source location and | |
46 | will simply display the instruction pointer (address), as in prior | |
47 | versions of babeltrace. | |
48 | ||
49 | Getting the Right Tracer | |
50 | ------------------------ | |
51 | ||
52 | Debug info analysis is performed automatically by babeltrace, provided | |
53 | the trace contains sufficient information. In order to be able to | |
54 | trace all the necessary information, the following software is | |
55 | required: | |
56 | ||
57 | * lttng-ust version 2.8.0 or later | |
58 | * lttng-tools, corresponding version | |
59 | ||
60 | You can get these from source at: | |
61 | ||
62 | * https://github.com/lttng/lttng-ust | |
63 | * https://github.com/lttng/lttng-tools | |
64 | ||
65 | Ubuntu users also have the option of installing via the LTTng daily | |
66 | PPA: | |
67 | ||
68 | * https://launchpad.net/~lttng/+archive/ubuntu/daily | |
69 | ||
70 | Tracing for Debug Info Analysis | |
71 | ------------------------------- | |
72 | ||
73 | Babeltrace needs some extra information from contexts, namely ip and | |
74 | vpid, to perform its analysis. These can be enabled after the creation | |
75 | of a tracing session as follows: | |
76 | ||
77 | $ lttng add-context --userspace --type ip --type vpid | |
78 | ||
79 | The tracing can then be performed as it normally would. Once the trace | |
80 | is collected, it can the be read by babeltrace for analysis. | |
81 | ||
82 | Analysing the Trace | |
83 | ------------------- | |
84 | ||
85 | To perform the analysis, the trace can simply be read as it normally | |
86 | would: | |
87 | ||
88 | $ babeltrace <path/to/trace> | |
89 | ||
90 | Debug info analysis is on by default and will automatically print the | |
91 | extra source location information if it can find it. A sample output | |
92 | may look like this: | |
93 | ||
94 | [...] | |
95 | [19:53:41.648394410] (+0.000022616) colossus my_provider:my_first_tracepoint: { cpu_id = 2 }, { ip = 0x7F75AEDFB4D4, debug_info = { func = "foo", source_loc = "/home/efficios/example/libhello.c:7" }, vpid = 25577 }, { my_string_field = "hello, tracer", my_integer_field = 42 } | |
96 | [19:53:41.648423786] (+0.000029376) colossus my_provider:my_first_tracepoint: { cpu_id = 2 }, { ip = 0x7F75AEDFB5A6, debug_info = { func = "bar", source_loc = "/home/efficios/example/libhello.c:13" }, vpid = 25577 }, { my_string_field = "recoltes et semailles", my_integer_field = 57 } | |
97 | [19:53:41.648435726] (+0.000011940) colossus my_provider:my_other_tracepoint: { cpu_id = 2 }, { ip = 0x7F75AEDFB66B, debug_info = { func = "baz", source_loc = "/home/efficios/example/libhello.c:20" }, vpid = 25577 }, { some_field = 1729 } | |
98 | [...] | |
99 | ||
100 | The interesting part is the debug_info section of the context: | |
101 | ||
102 | debug_info = { func = "foo", source_loc = "/home/efficios/example/libhello.c:7" } | |
103 | ||
104 | This is the expected output for events generated by an executable for | |
105 | which DWARF information is available. It shows the name of the | |
106 | function containing the tracepoint instance which generated the event | |
107 | ("foo"), and its source location ("libhello.c", line 7). | |
108 | ||
109 | The second event in the sample output is of the same type | |
110 | ("my_first_tracepoint"), but it was generated by a different | |
111 | tracepoint instance, hence the different source location (line 13) and | |
112 | function ("bar"). | |
113 | ||
114 | The third event, of a different type, also shows debug information. | |
115 | ||
116 | If DWARF info is absent, but ELF symbols are not stripped, the output | |
117 | will instead look like this: | |
118 | ||
119 | [...] | |
120 | [19:53:41.648394410] (+0.000022616) colossus my_provider:my_first_tracepoint: { cpu_id = 2 }, { ip = 0x7F75AEDFB4D4, debug_info = { func = "foo+0xa9" }, vpid = 25577 }, { my_string_field = "hello, tracer", my_integer_field = 42 } | |
121 | [19:53:41.648423786] (+0.000029376) colossus my_provider:my_first_tracepoint: { cpu_id = 2 }, { ip = 0x7F75AEDFB5A6, debug_info = { func = "bar+0xa9" }, vpid = 25577 }, { my_string_field = "recoltes et semailles", my_integer_field = 57 } | |
122 | [19:53:41.648435726] (+0.000011940) colossus my_provider:my_other_tracepoint: { cpu_id = 2 }, { ip = 0x7F75AEDFB66B, debug_info = { func = "baz+0x9c" }, vpid = 25577 }, { some_field = 1729 } | |
123 | [...] | |
124 | ||
125 | The debug information now provides only the function name as given by | |
126 | ELF symbols, plus an offset in bytes from the symbol to the actual | |
127 | location of the tracepoint instance. | |
128 | ||
129 | Debug Info and Dynamic Loading | |
130 | ------------------------------ | |
131 | ||
132 | Babeltrace can resolve addresses of events originating from | |
133 | dynamically loaded libraries, provided that some extra information is | |
134 | collected at tracing time. | |
135 | ||
136 | This can be achieved by preloading LTTng UST's libdl helper when | |
137 | launching the program to be traced, like so: | |
138 | ||
139 | $ LD_PRELOAD="liblttng-ust-dl.so" <path/to/executable> | |
140 | ||
141 | The tracing and analysis can now be performed as described in prior | |
142 | sections, and events from tracepoints in dlopened libraries will be | |
143 | resolved automatically by babeltrace. | |
144 | ||
145 | Separate Debug Info | |
146 | ------------------- | |
147 | ||
148 | It is possible to store DWARF debug information separate from an | |
149 | executable, whether for concerns of file size, or simply to facilitate | |
150 | the sharing of the debug information. | |
151 | ||
152 | This is usually achieved via one of two mechanisms, namely build ID | |
153 | and debug link. Both methods permit separate executables and debug | |
154 | information. Their use and operation is described in GDB's | |
155 | documentation at: | |
156 | ||
157 | https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html | |
158 | ||
159 | Babeltrace will find separate debug files automatically, provided they | |
160 | follow the requirements described in the documentation above. The | |
161 | debug information lookup order is the same as GDB's, that is first | |
162 | debug info is looked for within the executable, then through the build | |
163 | ID method in the standard /usr/lib/debug/.build-id/ location, and | |
164 | finally in the various possible debug link locations. The first debug | |
165 | information file found is used. | |
166 | ||
167 | Debug Info Directory | |
168 | -------------------- | |
169 | ||
170 | When performing debug info analysis, babeltrace uses an executable's | |
171 | path from when it was traced to resolve debug information. If, | |
172 | however, the trace was taken on a different machine, or the executable | |
173 | was simply moved since the trace was taken, it is possible to override | |
174 | the base path from which to look for the debug information. To do so, | |
175 | the --debug-info-dir babeltrace command-line flag is available. | |
176 | ||
177 | If a --debug-info-dir value is given, it will replace the default | |
178 | /usr/lib/debug path used in build ID and debug link lookups. | |
179 | ||
180 | Note that multiple debug directories are not currently supported. |