Fix: initialize build id and debug link flags to 0
[lttng-ust.git] / liblttng-ust / lttng-ust-statedump.c
1 /*
2 * Copyright (C) 2013 Paul Woegerer <paul_woegerer@mentor.com>
3 * Copyright (C) 2015 Antoine Busque <abusque@efficios.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #define _LGPL_SOURCE
21 #define _GNU_SOURCE
22
23 #include <link.h>
24 #include <limits.h>
25 #include <stdio.h>
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30
31 #include <lttng/ust-elf.h>
32 #include "lttng-tracer-core.h"
33 #include "lttng-ust-statedump.h"
34
35 #define TRACEPOINT_DEFINE
36 #define TRACEPOINT_CREATE_PROBES
37 #define TP_SESSION_CHECK
38 #include "lttng-ust-statedump-provider.h"
39
40 struct dl_iterate_data {
41 void *owner;
42 int exec_found;
43 };
44
45 struct bin_info_data {
46 void *owner;
47 void *base_addr_ptr;
48 const char *resolved_path;
49 char *dbg_file;
50 uint8_t *build_id;
51 uint64_t memsz;
52 size_t build_id_len;
53 int vdso;
54 uint32_t crc;
55 uint8_t is_pic;
56 uint8_t has_build_id;
57 uint8_t has_debug_link;
58 };
59
60 typedef void (*tracepoint_cb)(struct lttng_session *session, void *priv);
61
62 /*
63 * Trace statedump event into all sessions owned by the caller thread
64 * for which statedump is pending.
65 */
66 static
67 int trace_statedump_event(tracepoint_cb tp_cb, void *owner, void *priv)
68 {
69 struct cds_list_head *sessionsp;
70 struct lttng_session *session;
71
72 sessionsp = _lttng_get_sessions();
73 cds_list_for_each_entry(session, sessionsp, node) {
74 if (session->owner != owner)
75 continue;
76 if (!session->statedump_pending)
77 continue;
78 tp_cb(session, priv);
79 }
80 return 0;
81 }
82
83 static
84 void trace_bin_info_cb(struct lttng_session *session, void *priv)
85 {
86 struct bin_info_data *bin_data = (struct bin_info_data *) priv;
87
88 tracepoint(lttng_ust_statedump, bin_info,
89 session, bin_data->base_addr_ptr,
90 bin_data->resolved_path, bin_data->memsz,
91 bin_data->is_pic, bin_data->has_build_id,
92 bin_data->has_debug_link);
93 }
94
95 static
96 void trace_build_id_cb(struct lttng_session *session, void *priv)
97 {
98 struct bin_info_data *bin_data = (struct bin_info_data *) priv;
99
100 tracepoint(lttng_ust_statedump, build_id,
101 session, bin_data->base_addr_ptr,
102 bin_data->build_id, bin_data->build_id_len);
103 }
104
105 static
106 void trace_debug_link_cb(struct lttng_session *session, void *priv)
107 {
108 struct bin_info_data *bin_data = (struct bin_info_data *) priv;
109
110 tracepoint(lttng_ust_statedump, debug_link,
111 session, bin_data->base_addr_ptr,
112 bin_data->dbg_file, bin_data->crc);
113 }
114
115 static
116 void trace_start_cb(struct lttng_session *session, void *priv)
117 {
118 tracepoint(lttng_ust_statedump, start, session);
119 }
120
121 static
122 void trace_end_cb(struct lttng_session *session, void *priv)
123 {
124 tracepoint(lttng_ust_statedump, end, session);
125 }
126
127 static
128 int get_elf_info(struct bin_info_data *bin_data)
129 {
130 struct lttng_ust_elf *elf;
131 int ret = 0, found;
132
133 elf = lttng_ust_elf_create(bin_data->resolved_path);
134 if (!elf) {
135 ret = -1;
136 goto end;
137 }
138
139 ret = lttng_ust_elf_get_memsz(elf, &bin_data->memsz);
140 if (ret) {
141 goto end;
142 }
143
144 found = 0;
145 ret = lttng_ust_elf_get_build_id(elf, &bin_data->build_id,
146 &bin_data->build_id_len,
147 &found);
148 if (ret) {
149 goto end;
150 }
151 bin_data->has_build_id = !!found;
152 found = 0;
153 ret = lttng_ust_elf_get_debug_link(elf, &bin_data->dbg_file,
154 &bin_data->crc,
155 &found);
156 if (ret) {
157 goto end;
158 }
159 bin_data->has_debug_link = !!found;
160
161 bin_data->is_pic = lttng_ust_elf_is_pic(elf);
162
163 end:
164 lttng_ust_elf_destroy(elf);
165 return ret;
166 }
167
168 static
169 int trace_baddr(struct bin_info_data *bin_data)
170 {
171 int ret = 0;
172
173 if (!bin_data->vdso) {
174 ret = get_elf_info(bin_data);
175 if (ret) {
176 goto end;
177 }
178 } else {
179 bin_data->memsz = 0;
180 bin_data->has_build_id = 0;
181 bin_data->has_debug_link = 0;
182 }
183
184 ret = trace_statedump_event(trace_bin_info_cb, bin_data->owner,
185 bin_data);
186 if (ret) {
187 goto end;
188 }
189
190 if (bin_data->has_build_id) {
191 ret = trace_statedump_event(
192 trace_build_id_cb, bin_data->owner, bin_data);
193 free(bin_data->build_id);
194 if (ret) {
195 goto end;
196 }
197 }
198
199 if (bin_data->has_debug_link) {
200 ret = trace_statedump_event(
201 trace_debug_link_cb, bin_data->owner, bin_data);
202 free(bin_data->dbg_file);
203 if (ret) {
204 goto end;
205 }
206 }
207
208 end:
209 return ret;
210 }
211
212 static
213 int trace_statedump_start(void *owner)
214 {
215 return trace_statedump_event(trace_start_cb, owner, NULL);
216 }
217
218 static
219 int trace_statedump_end(void *owner)
220 {
221 return trace_statedump_event(trace_end_cb, owner, NULL);
222 }
223
224 static
225 int extract_bin_info_events(struct dl_phdr_info *info, size_t size, void *_data)
226 {
227 int j, ret = 0;
228 struct dl_iterate_data *data = _data;
229
230 /*
231 * UST lock nests within dynamic loader lock.
232 *
233 * Hold this lock across handling of the entire module to
234 * protect memory allocation at early process start, due to
235 * interactions with libc-wrapper lttng malloc instrumentation.
236 */
237 if (ust_lock()) {
238 goto end;
239 }
240
241 for (j = 0; j < info->dlpi_phnum; j++) {
242 struct bin_info_data bin_data;
243 char resolved_path[PATH_MAX];
244 void *base_addr_ptr;
245
246 if (info->dlpi_phdr[j].p_type != PT_LOAD)
247 continue;
248
249 /* Calculate virtual memory address of the loadable segment */
250 base_addr_ptr = (void *) info->dlpi_addr +
251 info->dlpi_phdr[j].p_vaddr;
252
253 if ((info->dlpi_name == NULL || info->dlpi_name[0] == 0)) {
254 /*
255 * Only the first phdr without a dlpi_name
256 * encountered is considered as the program
257 * executable. The rest are vdsos.
258 */
259 if (!data->exec_found) {
260 ssize_t path_len;
261 data->exec_found = 1;
262
263 /*
264 * Use /proc/self/exe to resolve the
265 * executable's full path.
266 */
267 path_len = readlink("/proc/self/exe",
268 resolved_path,
269 PATH_MAX - 1);
270 if (path_len <= 0)
271 break;
272
273 resolved_path[path_len] = '\0';
274 bin_data.vdso = 0;
275 } else {
276 snprintf(resolved_path, PATH_MAX - 1, "[vdso]");
277 bin_data.vdso = 1;
278 }
279 } else {
280 /*
281 * For regular dl_phdr_info entries check if
282 * the path to the binary really exists. If not,
283 * treat as vdso and use dlpi_name as 'path'.
284 */
285 if (!realpath(info->dlpi_name, resolved_path)) {
286 snprintf(resolved_path, PATH_MAX - 1, "[%s]",
287 info->dlpi_name);
288 bin_data.vdso = 1;
289 } else {
290 bin_data.vdso = 0;
291 }
292 }
293
294 bin_data.owner = data->owner;
295 bin_data.base_addr_ptr = base_addr_ptr;
296 bin_data.resolved_path = resolved_path;
297 ret = trace_baddr(&bin_data);
298 break;
299 }
300 end:
301 ust_unlock();
302 return ret;
303 }
304
305 /*
306 * Generate a statedump of base addresses of all shared objects loaded
307 * by the traced application, as well as for the application's
308 * executable itself.
309 */
310 static
311 int do_baddr_statedump(void *owner)
312 {
313 struct dl_iterate_data data;
314
315 if (getenv("LTTNG_UST_WITHOUT_BADDR_STATEDUMP"))
316 return 0;
317
318 data.owner = owner;
319 data.exec_found = 0;
320 /*
321 * Iterate through the list of currently loaded shared objects and
322 * generate events for loadable segments using
323 * extract_bin_info_events.
324 */
325 dl_iterate_phdr(extract_bin_info_events, &data);
326
327 return 0;
328 }
329
330 /*
331 * Generate a statedump of a given traced application. A statedump is
332 * delimited by start and end events. For a given (process, session)
333 * pair, begin/end events are serialized and will match. However, in a
334 * session, statedumps from different processes may be
335 * interleaved. The vpid context should be used to identify which
336 * events belong to which process.
337 */
338 int do_lttng_ust_statedump(void *owner)
339 {
340 trace_statedump_start(owner);
341 do_baddr_statedump(owner);
342 trace_statedump_end(owner);
343
344 return 0;
345 }
346
347 void lttng_ust_statedump_init(void)
348 {
349 __tracepoints__init();
350 __tracepoints__ptrs_init();
351 __lttng_events_init__lttng_ust_statedump();
352 }
353
354 void lttng_ust_statedump_destroy(void)
355 {
356 __lttng_events_exit__lttng_ust_statedump();
357 __tracepoints__ptrs_destroy();
358 __tracepoints__destroy();
359 }
This page took 0.037932 seconds and 5 git commands to generate.