2 * SPDX-License-Identifier: LGPL-2.1-or-later
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>
16 #include <sys/types.h>
19 #include "common/elf.h"
20 #include "common/macros.h"
21 #include "lttng-tracer-core.h"
22 #include "lttng-ust-statedump.h"
23 #include "common/jhash.h"
24 #include "common/getenv.h"
25 #include "lib/lttng-ust/events.h"
27 #define LTTNG_UST_TRACEPOINT_HIDDEN_DEFINITION
28 #define LTTNG_UST_TRACEPOINT_PROVIDER_HIDDEN_DEFINITION
30 #define LTTNG_UST_TRACEPOINT_DEFINE
31 #include "ust_lib.h" /* Only define. */
33 #define LTTNG_UST_TRACEPOINT_CREATE_PROBES
34 #define LTTNG_UST_TP_SESSION_CHECK
35 #include "lttng-ust-statedump-provider.h" /* Define and create probes. */
37 struct dl_iterate_data
{
43 struct bin_info_data
{
45 char resolved_path
[PATH_MAX
];
54 uint8_t has_debug_link
;
57 struct lttng_ust_dl_node
{
58 struct bin_info_data bin_data
;
59 struct cds_hlist_node node
;
64 #define UST_DL_STATE_HASH_BITS 8
65 #define UST_DL_STATE_TABLE_SIZE (1 << UST_DL_STATE_HASH_BITS)
66 static struct cds_hlist_head dl_state_table
[UST_DL_STATE_TABLE_SIZE
];
68 typedef void (*tracepoint_cb
)(struct lttng_ust_session
*session
, void *priv
);
71 struct lttng_ust_dl_node
*alloc_dl_node(const struct bin_info_data
*bin_data
)
73 struct lttng_ust_dl_node
*e
;
75 e
= zmalloc(sizeof(struct lttng_ust_dl_node
));
78 if (bin_data
->dbg_file
) {
79 e
->bin_data
.dbg_file
= strdup(bin_data
->dbg_file
);
80 if (!e
->bin_data
.dbg_file
)
83 if (bin_data
->build_id
) {
84 e
->bin_data
.build_id
= zmalloc(bin_data
->build_id_len
);
85 if (!e
->bin_data
.build_id
)
87 memcpy(e
->bin_data
.build_id
, bin_data
->build_id
,
88 bin_data
->build_id_len
);
90 e
->bin_data
.base_addr_ptr
= bin_data
->base_addr_ptr
;
91 memcpy(e
->bin_data
.resolved_path
, bin_data
->resolved_path
, PATH_MAX
);
92 e
->bin_data
.memsz
= bin_data
->memsz
;
93 e
->bin_data
.build_id_len
= bin_data
->build_id_len
;
94 e
->bin_data
.vdso
= bin_data
->vdso
;
95 e
->bin_data
.crc
= bin_data
->crc
;
96 e
->bin_data
.is_pic
= bin_data
->is_pic
;
97 e
->bin_data
.has_build_id
= bin_data
->has_build_id
;
98 e
->bin_data
.has_debug_link
= bin_data
->has_debug_link
;
102 free(e
->bin_data
.build_id
);
103 free(e
->bin_data
.dbg_file
);
109 void free_dl_node(struct lttng_ust_dl_node
*e
)
111 free(e
->bin_data
.build_id
);
112 free(e
->bin_data
.dbg_file
);
116 /* Return 0 if same, nonzero if not. */
118 int compare_bin_data(const struct bin_info_data
*a
,
119 const struct bin_info_data
*b
)
121 if (a
->base_addr_ptr
!= b
->base_addr_ptr
)
123 if (strcmp(a
->resolved_path
, b
->resolved_path
) != 0)
125 if (a
->dbg_file
&& !b
->dbg_file
)
127 if (!a
->dbg_file
&& b
->dbg_file
)
129 if (a
->dbg_file
&& strcmp(a
->dbg_file
, b
->dbg_file
) != 0)
131 if (a
->build_id
&& !b
->build_id
)
133 if (!a
->build_id
&& b
->build_id
)
135 if (a
->build_id_len
!= b
->build_id_len
)
138 memcmp(a
->build_id
, b
->build_id
, a
->build_id_len
) != 0)
140 if (a
->memsz
!= b
->memsz
)
142 if (a
->vdso
!= b
->vdso
)
144 if (a
->crc
!= b
->crc
)
146 if (a
->is_pic
!= b
->is_pic
)
148 if (a
->has_build_id
!= b
->has_build_id
)
150 if (a
->has_debug_link
!= b
->has_debug_link
)
156 struct lttng_ust_dl_node
*find_or_create_dl_node(struct bin_info_data
*bin_data
)
158 struct cds_hlist_head
*head
;
159 struct lttng_ust_dl_node
*e
;
163 hash
= jhash(&bin_data
->base_addr_ptr
,
164 sizeof(bin_data
->base_addr_ptr
), 0);
165 head
= &dl_state_table
[hash
& (UST_DL_STATE_TABLE_SIZE
- 1)];
166 cds_hlist_for_each_entry_2(e
, head
, node
) {
167 if (compare_bin_data(&e
->bin_data
, bin_data
) != 0)
174 e
= alloc_dl_node(bin_data
);
177 cds_hlist_add_head(&e
->node
, head
);
183 void remove_dl_node(struct lttng_ust_dl_node
*e
)
185 cds_hlist_del(&e
->node
);
189 * Trace statedump event into all sessions owned by the caller thread
190 * for which statedump is pending.
193 void trace_statedump_event(tracepoint_cb tp_cb
, void *owner
, void *priv
)
195 struct cds_list_head
*sessionsp
;
196 struct lttng_ust_session_private
*session_priv
;
198 sessionsp
= lttng_get_sessions();
199 cds_list_for_each_entry(session_priv
, sessionsp
, node
) {
200 if (session_priv
->owner
!= owner
)
202 if (!session_priv
->statedump_pending
)
204 tp_cb(session_priv
->pub
, priv
);
209 void trace_bin_info_cb(struct lttng_ust_session
*session
, void *priv
)
211 struct bin_info_data
*bin_data
= (struct bin_info_data
*) priv
;
213 lttng_ust_tracepoint(lttng_ust_statedump
, bin_info
,
214 session
, bin_data
->base_addr_ptr
,
215 bin_data
->resolved_path
, bin_data
->memsz
,
216 bin_data
->is_pic
, bin_data
->has_build_id
,
217 bin_data
->has_debug_link
);
221 void trace_build_id_cb(struct lttng_ust_session
*session
, void *priv
)
223 struct bin_info_data
*bin_data
= (struct bin_info_data
*) priv
;
225 lttng_ust_tracepoint(lttng_ust_statedump
, build_id
,
226 session
, bin_data
->base_addr_ptr
,
227 bin_data
->build_id
, bin_data
->build_id_len
);
231 void trace_debug_link_cb(struct lttng_ust_session
*session
, void *priv
)
233 struct bin_info_data
*bin_data
= (struct bin_info_data
*) priv
;
235 lttng_ust_tracepoint(lttng_ust_statedump
, debug_link
,
236 session
, bin_data
->base_addr_ptr
,
237 bin_data
->dbg_file
, bin_data
->crc
);
241 void procname_cb(struct lttng_ust_session
*session
, void *priv
)
243 char *procname
= (char *) priv
;
244 lttng_ust_tracepoint(lttng_ust_statedump
, procname
, session
, procname
);
248 void trace_start_cb(struct lttng_ust_session
*session
, void *priv
__attribute__((unused
)))
250 lttng_ust_tracepoint(lttng_ust_statedump
, start
, session
);
254 void trace_end_cb(struct lttng_ust_session
*session
, void *priv
__attribute__((unused
)))
256 lttng_ust_tracepoint(lttng_ust_statedump
, end
, session
);
260 int get_elf_info(struct bin_info_data
*bin_data
)
262 struct lttng_ust_elf
*elf
;
265 elf
= lttng_ust_elf_create(bin_data
->resolved_path
);
271 ret
= lttng_ust_elf_get_memsz(elf
, &bin_data
->memsz
);
277 ret
= lttng_ust_elf_get_build_id(elf
, &bin_data
->build_id
,
278 &bin_data
->build_id_len
,
283 bin_data
->has_build_id
= !!found
;
285 ret
= lttng_ust_elf_get_debug_link(elf
, &bin_data
->dbg_file
,
291 bin_data
->has_debug_link
= !!found
;
293 bin_data
->is_pic
= lttng_ust_elf_is_pic(elf
);
296 lttng_ust_elf_destroy(elf
);
301 void trace_baddr(struct bin_info_data
*bin_data
, void *owner
)
303 trace_statedump_event(trace_bin_info_cb
, owner
, bin_data
);
305 if (bin_data
->has_build_id
)
306 trace_statedump_event(trace_build_id_cb
, owner
, bin_data
);
308 if (bin_data
->has_debug_link
)
309 trace_statedump_event(trace_debug_link_cb
, owner
, bin_data
);
313 int extract_baddr(struct bin_info_data
*bin_data
)
316 struct lttng_ust_dl_node
*e
;
318 if (!bin_data
->vdso
) {
319 ret
= get_elf_info(bin_data
);
325 bin_data
->has_build_id
= 0;
326 bin_data
->has_debug_link
= 0;
329 e
= find_or_create_dl_node(bin_data
);
336 free(bin_data
->build_id
);
337 bin_data
->build_id
= NULL
;
338 free(bin_data
->dbg_file
);
339 bin_data
->dbg_file
= NULL
;
344 void trace_statedump_start(void *owner
)
346 trace_statedump_event(trace_start_cb
, owner
, NULL
);
350 void trace_statedump_end(void *owner
)
352 trace_statedump_event(trace_end_cb
, owner
, NULL
);
356 void iter_begin(struct dl_iterate_data
*data
)
361 * UST lock nests within dynamic loader lock.
363 * Hold this lock across handling of the module listing to
364 * protect memory allocation at early process start, due to
365 * interactions with libc-wrapper lttng malloc instrumentation.
372 /* Ensure all entries are unmarked. */
373 for (i
= 0; i
< UST_DL_STATE_TABLE_SIZE
; i
++) {
374 struct cds_hlist_head
*head
;
375 struct lttng_ust_dl_node
*e
;
377 head
= &dl_state_table
[i
];
378 cds_hlist_for_each_entry_2(e
, head
, node
)
384 void trace_lib_load(const struct bin_info_data
*bin_data
, void *ip
)
386 lttng_ust_tracepoint(lttng_ust_lib
, load
,
387 ip
, bin_data
->base_addr_ptr
, bin_data
->resolved_path
,
388 bin_data
->memsz
, bin_data
->has_build_id
,
389 bin_data
->has_debug_link
);
391 if (bin_data
->has_build_id
) {
392 lttng_ust_tracepoint(lttng_ust_lib
, build_id
,
393 ip
, bin_data
->base_addr_ptr
, bin_data
->build_id
,
394 bin_data
->build_id_len
);
397 if (bin_data
->has_debug_link
) {
398 lttng_ust_tracepoint(lttng_ust_lib
, debug_link
,
399 ip
, bin_data
->base_addr_ptr
, bin_data
->dbg_file
,
405 void trace_lib_unload(const struct bin_info_data
*bin_data
, void *ip
)
407 lttng_ust_tracepoint(lttng_ust_lib
, unload
, ip
, bin_data
->base_addr_ptr
);
411 void iter_end(struct dl_iterate_data
*data
, void *ip
)
418 * Iterate on hash table.
419 * For each marked, traced, do nothing.
420 * For each marked, not traced, trace lib open event. traced = true.
421 * For each unmarked, traced, trace lib close event. remove node.
422 * For each unmarked, not traced, remove node.
424 for (i
= 0; i
< UST_DL_STATE_TABLE_SIZE
; i
++) {
425 struct cds_hlist_head
*head
;
426 struct lttng_ust_dl_node
*e
, *tmp
;
428 head
= &dl_state_table
[i
];
429 cds_hlist_for_each_entry_safe_2(e
, tmp
, head
, node
) {
432 trace_lib_load(&e
->bin_data
, ip
);
438 trace_lib_unload(&e
->bin_data
, ip
);
449 int extract_bin_info_events(struct dl_phdr_info
*info
, size_t size
__attribute__((unused
)), void *_data
)
452 struct dl_iterate_data
*data
= _data
;
462 for (j
= 0; j
< info
->dlpi_phnum
; j
++) {
463 struct bin_info_data bin_data
;
465 if (info
->dlpi_phdr
[j
].p_type
!= PT_LOAD
)
468 memset(&bin_data
, 0, sizeof(bin_data
));
470 /* Calculate virtual memory address of the loadable segment */
471 bin_data
.base_addr_ptr
= (void *) info
->dlpi_addr
+
472 info
->dlpi_phdr
[j
].p_vaddr
;
474 if ((info
->dlpi_name
== NULL
|| info
->dlpi_name
[0] == 0)) {
476 * Only the first phdr without a dlpi_name
477 * encountered is considered as the program
478 * executable. The rest are vdsos.
480 if (!data
->exec_found
) {
482 data
->exec_found
= 1;
485 * Use /proc/self/exe to resolve the
486 * executable's full path.
488 path_len
= readlink("/proc/self/exe",
489 bin_data
.resolved_path
,
494 bin_data
.resolved_path
[path_len
] = '\0';
497 snprintf(bin_data
.resolved_path
,
498 PATH_MAX
- 1, "[vdso]");
503 * For regular dl_phdr_info entries check if
504 * the path to the binary really exists. If not,
505 * treat as vdso and use dlpi_name as 'path'.
507 if (!realpath(info
->dlpi_name
,
508 bin_data
.resolved_path
)) {
509 snprintf(bin_data
.resolved_path
,
510 PATH_MAX
- 1, "[%s]",
518 ret
= extract_baddr(&bin_data
);
526 void ust_dl_table_statedump(void *owner
)
533 /* Statedump each traced table entry into session for owner. */
534 for (i
= 0; i
< UST_DL_STATE_TABLE_SIZE
; i
++) {
535 struct cds_hlist_head
*head
;
536 struct lttng_ust_dl_node
*e
;
538 head
= &dl_state_table
[i
];
539 cds_hlist_for_each_entry_2(e
, head
, node
) {
541 trace_baddr(&e
->bin_data
, owner
);
549 void lttng_ust_dl_update(void *ip
)
551 struct dl_iterate_data data
;
553 if (lttng_ust_getenv("LTTNG_UST_WITHOUT_BADDR_STATEDUMP"))
557 * Force the allocation of lttng-ust TLS variables when called from
558 * dlopen/dlclose instrumentation.
560 lttng_ust_alloc_tls();
566 * Iterate through the list of currently loaded shared objects and
567 * generate tables entries for loadable segments using
568 * extract_bin_info_events.
569 * Removed libraries are detected by mark-and-sweep: marking is
570 * done in the iteration over libraries, and sweeping is
571 * performed by iter_end().
573 dl_iterate_phdr(extract_bin_info_events
, &data
);
580 * Generate a statedump of base addresses of all shared objects loaded
581 * by the traced application, as well as for the application's
585 int do_baddr_statedump(void *owner
)
587 if (lttng_ust_getenv("LTTNG_UST_WITHOUT_BADDR_STATEDUMP"))
589 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
590 ust_dl_table_statedump(owner
);
595 int do_procname_statedump(void *owner
)
597 if (lttng_ust_getenv("LTTNG_UST_WITHOUT_PROCNAME_STATEDUMP"))
600 trace_statedump_event(procname_cb
, owner
, lttng_ust_sockinfo_get_procname(owner
));
605 * Generate a statedump of a given traced application. A statedump is
606 * delimited by start and end events. For a given (process, session)
607 * pair, begin/end events are serialized and will match. However, in a
608 * session, statedumps from different processes may be
609 * interleaved. The vpid context should be used to identify which
610 * events belong to which process.
612 * Grab the ust_lock outside of the RCU read-side lock because we
613 * perform synchronize_rcu with the ust_lock held, which can trigger
614 * deadlocks otherwise.
616 int do_lttng_ust_statedump(void *owner
)
619 trace_statedump_start(owner
);
622 do_procname_statedump(owner
);
623 do_baddr_statedump(owner
);
626 trace_statedump_end(owner
);
632 void lttng_ust_statedump_init(void)
634 lttng_ust__tracepoints__init();
635 lttng_ust__tracepoints__ptrs_init();
636 lttng_ust__events_init__lttng_ust_statedump();
637 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
641 void ust_dl_state_destroy(void)
645 for (i
= 0; i
< UST_DL_STATE_TABLE_SIZE
; i
++) {
646 struct cds_hlist_head
*head
;
647 struct lttng_ust_dl_node
*e
, *tmp
;
649 head
= &dl_state_table
[i
];
650 cds_hlist_for_each_entry_safe_2(e
, tmp
, head
, node
)
652 CDS_INIT_HLIST_HEAD(head
);
656 void lttng_ust_statedump_destroy(void)
658 lttng_ust__events_exit__lttng_ust_statedump();
659 lttng_ust__tracepoints__ptrs_destroy();
660 lttng_ust__tracepoints__destroy();
661 ust_dl_state_destroy();