Move to kernel style SPDX license identifiers
[lttng-ust.git] / liblttng-ust / lttng-ust-statedump.c
1 /*
2 * SPDX-License-Identifier: LGPL-2.1-or-later
3 *
4 * Copyright (C) 2013 Paul Woegerer <paul_woegerer@mentor.com>
5 * Copyright (C) 2015 Antoine Busque <abusque@efficios.com>
6 * Copyright (C) 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 */
8
9 #define _LGPL_SOURCE
10 #include <link.h>
11 #include <limits.h>
12 #include <stdio.h>
13 #include <stdint.h>
14 #include <stdlib.h>
15 #include <stdbool.h>
16 #include <sys/types.h>
17 #include <unistd.h>
18
19 #include <lttng/ust-elf.h>
20 #include <helper.h>
21 #include "lttng-tracer-core.h"
22 #include "lttng-ust-statedump.h"
23 #include "jhash.h"
24 #include "getenv.h"
25 #include "compat.h"
26
27 #define TRACEPOINT_DEFINE
28 #include "ust_lib.h" /* Only define. */
29
30 #define TRACEPOINT_CREATE_PROBES
31 #define TP_SESSION_CHECK
32 #include "lttng-ust-statedump-provider.h" /* Define and create probes. */
33
34 struct dl_iterate_data {
35 int exec_found;
36 bool first;
37 bool cancel;
38 };
39
40 struct bin_info_data {
41 void *base_addr_ptr;
42 char resolved_path[PATH_MAX];
43 char *dbg_file;
44 uint8_t *build_id;
45 uint64_t memsz;
46 size_t build_id_len;
47 int vdso;
48 uint32_t crc;
49 uint8_t is_pic;
50 uint8_t has_build_id;
51 uint8_t has_debug_link;
52 };
53
54 struct lttng_ust_dl_node {
55 struct bin_info_data bin_data;
56 struct cds_hlist_node node;
57 bool traced;
58 bool marked;
59 };
60
61 #define UST_DL_STATE_HASH_BITS 8
62 #define UST_DL_STATE_TABLE_SIZE (1 << UST_DL_STATE_HASH_BITS)
63 struct cds_hlist_head dl_state_table[UST_DL_STATE_TABLE_SIZE];
64
65 typedef void (*tracepoint_cb)(struct lttng_session *session, void *priv);
66
67 static
68 struct lttng_ust_dl_node *alloc_dl_node(const struct bin_info_data *bin_data)
69 {
70 struct lttng_ust_dl_node *e;
71
72 e = zmalloc(sizeof(struct lttng_ust_dl_node));
73 if (!e)
74 return NULL;
75 if (bin_data->dbg_file) {
76 e->bin_data.dbg_file = strdup(bin_data->dbg_file);
77 if (!e->bin_data.dbg_file)
78 goto error;
79 }
80 if (bin_data->build_id) {
81 e->bin_data.build_id = zmalloc(bin_data->build_id_len);
82 if (!e->bin_data.build_id)
83 goto error;
84 memcpy(e->bin_data.build_id, bin_data->build_id,
85 bin_data->build_id_len);
86 }
87 e->bin_data.base_addr_ptr = bin_data->base_addr_ptr;
88 memcpy(e->bin_data.resolved_path, bin_data->resolved_path, PATH_MAX);
89 e->bin_data.memsz = bin_data->memsz;
90 e->bin_data.build_id_len = bin_data->build_id_len;
91 e->bin_data.vdso = bin_data->vdso;
92 e->bin_data.crc = bin_data->crc;
93 e->bin_data.is_pic = bin_data->is_pic;
94 e->bin_data.has_build_id = bin_data->has_build_id;
95 e->bin_data.has_debug_link = bin_data->has_debug_link;
96 return e;
97
98 error:
99 free(e->bin_data.build_id);
100 free(e->bin_data.dbg_file);
101 free(e);
102 return NULL;
103 }
104
105 static
106 void free_dl_node(struct lttng_ust_dl_node *e)
107 {
108 free(e->bin_data.build_id);
109 free(e->bin_data.dbg_file);
110 free(e);
111 }
112
113 /* Return 0 if same, nonzero if not. */
114 static
115 int compare_bin_data(const struct bin_info_data *a,
116 const struct bin_info_data *b)
117 {
118 if (a->base_addr_ptr != b->base_addr_ptr)
119 return -1;
120 if (strcmp(a->resolved_path, b->resolved_path) != 0)
121 return -1;
122 if (a->dbg_file && !b->dbg_file)
123 return -1;
124 if (!a->dbg_file && b->dbg_file)
125 return -1;
126 if (a->dbg_file && strcmp(a->dbg_file, b->dbg_file) != 0)
127 return -1;
128 if (a->build_id && !b->build_id)
129 return -1;
130 if (!a->build_id && b->build_id)
131 return -1;
132 if (a->build_id_len != b->build_id_len)
133 return -1;
134 if (a->build_id &&
135 memcmp(a->build_id, b->build_id, a->build_id_len) != 0)
136 return -1;
137 if (a->memsz != b->memsz)
138 return -1;
139 if (a->vdso != b->vdso)
140 return -1;
141 if (a->crc != b->crc)
142 return -1;
143 if (a->is_pic != b->is_pic)
144 return -1;
145 if (a->has_build_id != b->has_build_id)
146 return -1;
147 if (a->has_debug_link != b->has_debug_link)
148 return -1;
149 return 0;
150 }
151
152 static
153 struct lttng_ust_dl_node *find_or_create_dl_node(struct bin_info_data *bin_data)
154 {
155 struct cds_hlist_head *head;
156 struct lttng_ust_dl_node *e;
157 unsigned int hash;
158 bool found = false;
159
160 hash = jhash(&bin_data->base_addr_ptr,
161 sizeof(bin_data->base_addr_ptr), 0);
162 head = &dl_state_table[hash & (UST_DL_STATE_TABLE_SIZE - 1)];
163 cds_hlist_for_each_entry_2(e, head, node) {
164 if (compare_bin_data(&e->bin_data, bin_data) != 0)
165 continue;
166 found = true;
167 break;
168 }
169 if (!found) {
170 /* Create */
171 e = alloc_dl_node(bin_data);
172 if (!e)
173 return NULL;
174 cds_hlist_add_head(&e->node, head);
175 }
176 return e;
177 }
178
179 static
180 void remove_dl_node(struct lttng_ust_dl_node *e)
181 {
182 cds_hlist_del(&e->node);
183 }
184
185 /*
186 * Trace statedump event into all sessions owned by the caller thread
187 * for which statedump is pending.
188 */
189 static
190 void trace_statedump_event(tracepoint_cb tp_cb, void *owner, void *priv)
191 {
192 struct cds_list_head *sessionsp;
193 struct lttng_session *session;
194
195 sessionsp = _lttng_get_sessions();
196 cds_list_for_each_entry(session, sessionsp, node) {
197 if (session->owner != owner)
198 continue;
199 if (!session->statedump_pending)
200 continue;
201 tp_cb(session, priv);
202 }
203 }
204
205 static
206 void trace_bin_info_cb(struct lttng_session *session, void *priv)
207 {
208 struct bin_info_data *bin_data = (struct bin_info_data *) priv;
209
210 tracepoint(lttng_ust_statedump, bin_info,
211 session, bin_data->base_addr_ptr,
212 bin_data->resolved_path, bin_data->memsz,
213 bin_data->is_pic, bin_data->has_build_id,
214 bin_data->has_debug_link);
215 }
216
217 static
218 void trace_build_id_cb(struct lttng_session *session, void *priv)
219 {
220 struct bin_info_data *bin_data = (struct bin_info_data *) priv;
221
222 tracepoint(lttng_ust_statedump, build_id,
223 session, bin_data->base_addr_ptr,
224 bin_data->build_id, bin_data->build_id_len);
225 }
226
227 static
228 void trace_debug_link_cb(struct lttng_session *session, void *priv)
229 {
230 struct bin_info_data *bin_data = (struct bin_info_data *) priv;
231
232 tracepoint(lttng_ust_statedump, debug_link,
233 session, bin_data->base_addr_ptr,
234 bin_data->dbg_file, bin_data->crc);
235 }
236
237 static
238 void procname_cb(struct lttng_session *session, void *priv)
239 {
240 char *procname = (char *) priv;
241 tracepoint(lttng_ust_statedump, procname, session, procname);
242 }
243
244 static
245 void trace_start_cb(struct lttng_session *session, void *priv)
246 {
247 tracepoint(lttng_ust_statedump, start, session);
248 }
249
250 static
251 void trace_end_cb(struct lttng_session *session, void *priv)
252 {
253 tracepoint(lttng_ust_statedump, end, session);
254 }
255
256 static
257 int get_elf_info(struct bin_info_data *bin_data)
258 {
259 struct lttng_ust_elf *elf;
260 int ret = 0, found;
261
262 elf = lttng_ust_elf_create(bin_data->resolved_path);
263 if (!elf) {
264 ret = -1;
265 goto end;
266 }
267
268 ret = lttng_ust_elf_get_memsz(elf, &bin_data->memsz);
269 if (ret) {
270 goto end;
271 }
272
273 found = 0;
274 ret = lttng_ust_elf_get_build_id(elf, &bin_data->build_id,
275 &bin_data->build_id_len,
276 &found);
277 if (ret) {
278 goto end;
279 }
280 bin_data->has_build_id = !!found;
281 found = 0;
282 ret = lttng_ust_elf_get_debug_link(elf, &bin_data->dbg_file,
283 &bin_data->crc,
284 &found);
285 if (ret) {
286 goto end;
287 }
288 bin_data->has_debug_link = !!found;
289
290 bin_data->is_pic = lttng_ust_elf_is_pic(elf);
291
292 end:
293 lttng_ust_elf_destroy(elf);
294 return ret;
295 }
296
297 static
298 void trace_baddr(struct bin_info_data *bin_data, void *owner)
299 {
300 trace_statedump_event(trace_bin_info_cb, owner, bin_data);
301
302 if (bin_data->has_build_id)
303 trace_statedump_event(trace_build_id_cb, owner, bin_data);
304
305 if (bin_data->has_debug_link)
306 trace_statedump_event(trace_debug_link_cb, owner, bin_data);
307 }
308
309 static
310 int extract_baddr(struct bin_info_data *bin_data)
311 {
312 int ret = 0;
313 struct lttng_ust_dl_node *e;
314
315 if (!bin_data->vdso) {
316 ret = get_elf_info(bin_data);
317 if (ret) {
318 goto end;
319 }
320 } else {
321 bin_data->memsz = 0;
322 bin_data->has_build_id = 0;
323 bin_data->has_debug_link = 0;
324 }
325
326 e = find_or_create_dl_node(bin_data);
327 if (!e) {
328 ret = -1;
329 goto end;
330 }
331 e->marked = true;
332 end:
333 free(bin_data->build_id);
334 bin_data->build_id = NULL;
335 free(bin_data->dbg_file);
336 bin_data->dbg_file = NULL;
337 return ret;
338 }
339
340 static
341 void trace_statedump_start(void *owner)
342 {
343 trace_statedump_event(trace_start_cb, owner, NULL);
344 }
345
346 static
347 void trace_statedump_end(void *owner)
348 {
349 trace_statedump_event(trace_end_cb, owner, NULL);
350 }
351
352 static
353 void iter_begin(struct dl_iterate_data *data)
354 {
355 unsigned int i;
356
357 /*
358 * UST lock nests within dynamic loader lock.
359 *
360 * Hold this lock across handling of the module listing to
361 * protect memory allocation at early process start, due to
362 * interactions with libc-wrapper lttng malloc instrumentation.
363 */
364 if (ust_lock()) {
365 data->cancel = true;
366 return;
367 }
368
369 /* Ensure all entries are unmarked. */
370 for (i = 0; i < UST_DL_STATE_TABLE_SIZE; i++) {
371 struct cds_hlist_head *head;
372 struct lttng_ust_dl_node *e;
373
374 head = &dl_state_table[i];
375 cds_hlist_for_each_entry_2(e, head, node)
376 assert(!e->marked);
377 }
378 }
379
380 static
381 void trace_lib_load(const struct bin_info_data *bin_data, void *ip)
382 {
383 tracepoint(lttng_ust_lib, load,
384 ip, bin_data->base_addr_ptr, bin_data->resolved_path,
385 bin_data->memsz, bin_data->has_build_id,
386 bin_data->has_debug_link);
387
388 if (bin_data->has_build_id) {
389 tracepoint(lttng_ust_lib, build_id,
390 ip, bin_data->base_addr_ptr, bin_data->build_id,
391 bin_data->build_id_len);
392 }
393
394 if (bin_data->has_debug_link) {
395 tracepoint(lttng_ust_lib, debug_link,
396 ip, bin_data->base_addr_ptr, bin_data->dbg_file,
397 bin_data->crc);
398 }
399 }
400
401 static
402 void trace_lib_unload(const struct bin_info_data *bin_data, void *ip)
403 {
404 tracepoint(lttng_ust_lib, unload, ip, bin_data->base_addr_ptr);
405 }
406
407 static
408 void iter_end(struct dl_iterate_data *data, void *ip)
409 {
410 unsigned int i;
411
412 if (data->cancel)
413 goto end;
414 /*
415 * Iterate on hash table.
416 * For each marked, traced, do nothing.
417 * For each marked, not traced, trace lib open event. traced = true.
418 * For each unmarked, traced, trace lib close event. remove node.
419 * For each unmarked, not traced, remove node.
420 */
421 for (i = 0; i < UST_DL_STATE_TABLE_SIZE; i++) {
422 struct cds_hlist_head *head;
423 struct lttng_ust_dl_node *e;
424
425 head = &dl_state_table[i];
426 cds_hlist_for_each_entry_2(e, head, node) {
427 if (e->marked) {
428 if (!e->traced) {
429 trace_lib_load(&e->bin_data, ip);
430 e->traced = true;
431 }
432 e->marked = false;
433 } else {
434 if (e->traced)
435 trace_lib_unload(&e->bin_data, ip);
436 remove_dl_node(e);
437 free_dl_node(e);
438 }
439 }
440 }
441 end:
442 ust_unlock();
443 }
444
445 static
446 int extract_bin_info_events(struct dl_phdr_info *info, size_t size, void *_data)
447 {
448 int j, ret = 0;
449 struct dl_iterate_data *data = _data;
450
451 if (data->first) {
452 iter_begin(data);
453 data->first = false;
454 }
455
456 if (data->cancel)
457 goto end;
458
459 for (j = 0; j < info->dlpi_phnum; j++) {
460 struct bin_info_data bin_data;
461
462 if (info->dlpi_phdr[j].p_type != PT_LOAD)
463 continue;
464
465 memset(&bin_data, 0, sizeof(bin_data));
466
467 /* Calculate virtual memory address of the loadable segment */
468 bin_data.base_addr_ptr = (void *) info->dlpi_addr +
469 info->dlpi_phdr[j].p_vaddr;
470
471 if ((info->dlpi_name == NULL || info->dlpi_name[0] == 0)) {
472 /*
473 * Only the first phdr without a dlpi_name
474 * encountered is considered as the program
475 * executable. The rest are vdsos.
476 */
477 if (!data->exec_found) {
478 ssize_t path_len;
479 data->exec_found = 1;
480
481 /*
482 * Use /proc/self/exe to resolve the
483 * executable's full path.
484 */
485 path_len = readlink("/proc/self/exe",
486 bin_data.resolved_path,
487 PATH_MAX - 1);
488 if (path_len <= 0)
489 break;
490
491 bin_data.resolved_path[path_len] = '\0';
492 bin_data.vdso = 0;
493 } else {
494 snprintf(bin_data.resolved_path,
495 PATH_MAX - 1, "[vdso]");
496 bin_data.vdso = 1;
497 }
498 } else {
499 /*
500 * For regular dl_phdr_info entries check if
501 * the path to the binary really exists. If not,
502 * treat as vdso and use dlpi_name as 'path'.
503 */
504 if (!realpath(info->dlpi_name,
505 bin_data.resolved_path)) {
506 snprintf(bin_data.resolved_path,
507 PATH_MAX - 1, "[%s]",
508 info->dlpi_name);
509 bin_data.vdso = 1;
510 } else {
511 bin_data.vdso = 0;
512 }
513 }
514
515 ret = extract_baddr(&bin_data);
516 break;
517 }
518 end:
519 return ret;
520 }
521
522 static
523 void ust_dl_table_statedump(void *owner)
524 {
525 unsigned int i;
526
527 if (ust_lock())
528 goto end;
529
530 /* Statedump each traced table entry into session for owner. */
531 for (i = 0; i < UST_DL_STATE_TABLE_SIZE; i++) {
532 struct cds_hlist_head *head;
533 struct lttng_ust_dl_node *e;
534
535 head = &dl_state_table[i];
536 cds_hlist_for_each_entry_2(e, head, node) {
537 if (e->traced)
538 trace_baddr(&e->bin_data, owner);
539 }
540 }
541
542 end:
543 ust_unlock();
544 }
545
546 void lttng_ust_dl_update(void *ip)
547 {
548 struct dl_iterate_data data;
549
550 if (lttng_getenv("LTTNG_UST_WITHOUT_BADDR_STATEDUMP"))
551 return;
552
553 /*
554 * Fixup lttng-ust TLS when called from dlopen/dlclose
555 * instrumentation.
556 */
557 lttng_ust_fixup_tls();
558
559 data.exec_found = 0;
560 data.first = true;
561 data.cancel = false;
562 /*
563 * Iterate through the list of currently loaded shared objects and
564 * generate tables entries for loadable segments using
565 * extract_bin_info_events.
566 * Removed libraries are detected by mark-and-sweep: marking is
567 * done in the iteration over libraries, and sweeping is
568 * performed by iter_end().
569 */
570 dl_iterate_phdr(extract_bin_info_events, &data);
571 if (data.first)
572 iter_begin(&data);
573 iter_end(&data, ip);
574 }
575
576 /*
577 * Generate a statedump of base addresses of all shared objects loaded
578 * by the traced application, as well as for the application's
579 * executable itself.
580 */
581 static
582 int do_baddr_statedump(void *owner)
583 {
584 if (lttng_getenv("LTTNG_UST_WITHOUT_BADDR_STATEDUMP"))
585 return 0;
586 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
587 ust_dl_table_statedump(owner);
588 return 0;
589 }
590
591 static
592 int do_procname_statedump(void *owner)
593 {
594 if (lttng_getenv("LTTNG_UST_WITHOUT_PROCNAME_STATEDUMP"))
595 return 0;
596
597 trace_statedump_event(procname_cb, owner, lttng_ust_sockinfo_get_procname(owner));
598 return 0;
599 }
600
601 /*
602 * Generate a statedump of a given traced application. A statedump is
603 * delimited by start and end events. For a given (process, session)
604 * pair, begin/end events are serialized and will match. However, in a
605 * session, statedumps from different processes may be
606 * interleaved. The vpid context should be used to identify which
607 * events belong to which process.
608 *
609 * Grab the ust_lock outside of the RCU read-side lock because we
610 * perform synchronize_rcu with the ust_lock held, which can trigger
611 * deadlocks otherwise.
612 */
613 int do_lttng_ust_statedump(void *owner)
614 {
615 ust_lock_nocheck();
616 trace_statedump_start(owner);
617 ust_unlock();
618
619 do_procname_statedump(owner);
620 do_baddr_statedump(owner);
621
622 ust_lock_nocheck();
623 trace_statedump_end(owner);
624 ust_unlock();
625
626 return 0;
627 }
628
629 void lttng_ust_statedump_init(void)
630 {
631 __tracepoints__init();
632 __tracepoints__ptrs_init();
633 __lttng_events_init__lttng_ust_statedump();
634 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
635 }
636
637 static
638 void ust_dl_state_destroy(void)
639 {
640 unsigned int i;
641
642 for (i = 0; i < UST_DL_STATE_TABLE_SIZE; i++) {
643 struct cds_hlist_head *head;
644 struct lttng_ust_dl_node *e, *tmp;
645
646 head = &dl_state_table[i];
647 cds_hlist_for_each_entry_safe_2(e, tmp, head, node)
648 free_dl_node(e);
649 CDS_INIT_HLIST_HEAD(head);
650 }
651 }
652
653 void lttng_ust_statedump_destroy(void)
654 {
655 __lttng_events_exit__lttng_ust_statedump();
656 __tracepoints__ptrs_destroy();
657 __tracepoints__destroy();
658 ust_dl_state_destroy();
659 }
This page took 0.041575 seconds and 4 git commands to generate.