2 * Copyright (C) 2013 Paul Woegerer <paul_woegerer@mentor.com>
3 * Copyright (C) 2015 Antoine Busque <abusque@efficios.com>
4 * Copyright (C) 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 #include <sys/types.h>
32 #include <lttng/ust-elf.h>
34 #include "lttng-tracer-core.h"
35 #include "lttng-ust-statedump.h"
40 #define TRACEPOINT_DEFINE
41 #include "ust_lib.h" /* Only define. */
43 #define TRACEPOINT_CREATE_PROBES
44 #define TP_SESSION_CHECK
45 #include "lttng-ust-statedump-provider.h" /* Define and create probes. */
47 struct dl_iterate_data
{
53 struct bin_info_data
{
55 char resolved_path
[PATH_MAX
];
64 uint8_t has_debug_link
;
67 struct lttng_ust_dl_node
{
68 struct bin_info_data bin_data
;
69 struct cds_hlist_node node
;
74 #define UST_DL_STATE_HASH_BITS 8
75 #define UST_DL_STATE_TABLE_SIZE (1 << UST_DL_STATE_HASH_BITS)
76 struct cds_hlist_head dl_state_table
[UST_DL_STATE_TABLE_SIZE
];
78 typedef void (*tracepoint_cb
)(struct lttng_session
*session
, void *priv
);
81 struct lttng_ust_dl_node
*alloc_dl_node(const struct bin_info_data
*bin_data
)
83 struct lttng_ust_dl_node
*e
;
85 e
= zmalloc(sizeof(struct lttng_ust_dl_node
));
88 if (bin_data
->dbg_file
) {
89 e
->bin_data
.dbg_file
= strdup(bin_data
->dbg_file
);
90 if (!e
->bin_data
.dbg_file
)
93 if (bin_data
->build_id
) {
94 e
->bin_data
.build_id
= zmalloc(bin_data
->build_id_len
);
95 if (!e
->bin_data
.build_id
)
97 memcpy(e
->bin_data
.build_id
, bin_data
->build_id
,
98 bin_data
->build_id_len
);
100 e
->bin_data
.base_addr_ptr
= bin_data
->base_addr_ptr
;
101 memcpy(e
->bin_data
.resolved_path
, bin_data
->resolved_path
, PATH_MAX
);
102 e
->bin_data
.memsz
= bin_data
->memsz
;
103 e
->bin_data
.build_id_len
= bin_data
->build_id_len
;
104 e
->bin_data
.vdso
= bin_data
->vdso
;
105 e
->bin_data
.crc
= bin_data
->crc
;
106 e
->bin_data
.is_pic
= bin_data
->is_pic
;
107 e
->bin_data
.has_build_id
= bin_data
->has_build_id
;
108 e
->bin_data
.has_debug_link
= bin_data
->has_debug_link
;
112 free(e
->bin_data
.build_id
);
113 free(e
->bin_data
.dbg_file
);
119 void free_dl_node(struct lttng_ust_dl_node
*e
)
121 free(e
->bin_data
.build_id
);
122 free(e
->bin_data
.dbg_file
);
126 /* Return 0 if same, nonzero if not. */
128 int compare_bin_data(const struct bin_info_data
*a
,
129 const struct bin_info_data
*b
)
131 if (a
->base_addr_ptr
!= b
->base_addr_ptr
)
133 if (strcmp(a
->resolved_path
, b
->resolved_path
) != 0)
135 if (a
->dbg_file
&& !b
->dbg_file
)
137 if (!a
->dbg_file
&& b
->dbg_file
)
139 if (a
->dbg_file
&& strcmp(a
->dbg_file
, b
->dbg_file
) != 0)
141 if (a
->build_id
&& !b
->build_id
)
143 if (!a
->build_id
&& b
->build_id
)
145 if (a
->build_id_len
!= b
->build_id_len
)
148 memcmp(a
->build_id
, b
->build_id
, a
->build_id_len
) != 0)
150 if (a
->memsz
!= b
->memsz
)
152 if (a
->vdso
!= b
->vdso
)
154 if (a
->crc
!= b
->crc
)
156 if (a
->is_pic
!= b
->is_pic
)
158 if (a
->has_build_id
!= b
->has_build_id
)
160 if (a
->has_debug_link
!= b
->has_debug_link
)
166 struct lttng_ust_dl_node
*find_or_create_dl_node(struct bin_info_data
*bin_data
)
168 struct cds_hlist_head
*head
;
169 struct lttng_ust_dl_node
*e
;
173 hash
= jhash(&bin_data
->base_addr_ptr
,
174 sizeof(bin_data
->base_addr_ptr
), 0);
175 head
= &dl_state_table
[hash
& (UST_DL_STATE_TABLE_SIZE
- 1)];
176 cds_hlist_for_each_entry_2(e
, head
, node
) {
177 if (compare_bin_data(&e
->bin_data
, bin_data
) != 0)
184 e
= alloc_dl_node(bin_data
);
187 cds_hlist_add_head(&e
->node
, head
);
193 void remove_dl_node(struct lttng_ust_dl_node
*e
)
195 cds_hlist_del(&e
->node
);
199 * Trace statedump event into all sessions owned by the caller thread
200 * for which statedump is pending.
203 void trace_statedump_event(tracepoint_cb tp_cb
, void *owner
, void *priv
)
205 struct cds_list_head
*sessionsp
;
206 struct lttng_session
*session
;
208 sessionsp
= _lttng_get_sessions();
209 cds_list_for_each_entry(session
, sessionsp
, node
) {
210 if (session
->owner
!= owner
)
212 if (!session
->statedump_pending
)
214 tp_cb(session
, priv
);
219 void trace_bin_info_cb(struct lttng_session
*session
, void *priv
)
221 struct bin_info_data
*bin_data
= (struct bin_info_data
*) priv
;
223 tracepoint(lttng_ust_statedump
, bin_info
,
224 session
, bin_data
->base_addr_ptr
,
225 bin_data
->resolved_path
, bin_data
->memsz
,
226 bin_data
->is_pic
, bin_data
->has_build_id
,
227 bin_data
->has_debug_link
);
231 void trace_build_id_cb(struct lttng_session
*session
, void *priv
)
233 struct bin_info_data
*bin_data
= (struct bin_info_data
*) priv
;
235 tracepoint(lttng_ust_statedump
, build_id
,
236 session
, bin_data
->base_addr_ptr
,
237 bin_data
->build_id
, bin_data
->build_id_len
);
241 void trace_debug_link_cb(struct lttng_session
*session
, void *priv
)
243 struct bin_info_data
*bin_data
= (struct bin_info_data
*) priv
;
245 tracepoint(lttng_ust_statedump
, debug_link
,
246 session
, bin_data
->base_addr_ptr
,
247 bin_data
->dbg_file
, bin_data
->crc
);
251 void procname_cb(struct lttng_session
*session
, void *priv
)
253 char *procname
= (char *) priv
;
254 tracepoint(lttng_ust_statedump
, procname
, session
, procname
);
258 void trace_start_cb(struct lttng_session
*session
, void *priv
)
260 tracepoint(lttng_ust_statedump
, start
, session
);
264 void trace_end_cb(struct lttng_session
*session
, void *priv
)
266 tracepoint(lttng_ust_statedump
, end
, session
);
270 int get_elf_info(struct bin_info_data
*bin_data
)
272 struct lttng_ust_elf
*elf
;
275 elf
= lttng_ust_elf_create(bin_data
->resolved_path
);
281 ret
= lttng_ust_elf_get_memsz(elf
, &bin_data
->memsz
);
287 ret
= lttng_ust_elf_get_build_id(elf
, &bin_data
->build_id
,
288 &bin_data
->build_id_len
,
293 bin_data
->has_build_id
= !!found
;
295 ret
= lttng_ust_elf_get_debug_link(elf
, &bin_data
->dbg_file
,
301 bin_data
->has_debug_link
= !!found
;
303 bin_data
->is_pic
= lttng_ust_elf_is_pic(elf
);
306 lttng_ust_elf_destroy(elf
);
311 void trace_baddr(struct bin_info_data
*bin_data
, void *owner
)
313 trace_statedump_event(trace_bin_info_cb
, owner
, bin_data
);
315 if (bin_data
->has_build_id
)
316 trace_statedump_event(trace_build_id_cb
, owner
, bin_data
);
318 if (bin_data
->has_debug_link
)
319 trace_statedump_event(trace_debug_link_cb
, owner
, bin_data
);
323 int extract_baddr(struct bin_info_data
*bin_data
)
326 struct lttng_ust_dl_node
*e
;
328 if (!bin_data
->vdso
) {
329 ret
= get_elf_info(bin_data
);
335 bin_data
->has_build_id
= 0;
336 bin_data
->has_debug_link
= 0;
339 e
= find_or_create_dl_node(bin_data
);
346 free(bin_data
->build_id
);
347 bin_data
->build_id
= NULL
;
348 free(bin_data
->dbg_file
);
349 bin_data
->dbg_file
= NULL
;
354 void trace_statedump_start(void *owner
)
356 trace_statedump_event(trace_start_cb
, owner
, NULL
);
360 void trace_statedump_end(void *owner
)
362 trace_statedump_event(trace_end_cb
, owner
, NULL
);
366 void iter_begin(struct dl_iterate_data
*data
)
371 * UST lock nests within dynamic loader lock.
373 * Hold this lock across handling of the module listing to
374 * protect memory allocation at early process start, due to
375 * interactions with libc-wrapper lttng malloc instrumentation.
382 /* Ensure all entries are unmarked. */
383 for (i
= 0; i
< UST_DL_STATE_TABLE_SIZE
; i
++) {
384 struct cds_hlist_head
*head
;
385 struct lttng_ust_dl_node
*e
;
387 head
= &dl_state_table
[i
];
388 cds_hlist_for_each_entry_2(e
, head
, node
)
394 void trace_lib_load(const struct bin_info_data
*bin_data
, void *ip
)
396 tracepoint(lttng_ust_lib
, load
,
397 ip
, bin_data
->base_addr_ptr
, bin_data
->resolved_path
,
398 bin_data
->memsz
, bin_data
->has_build_id
,
399 bin_data
->has_debug_link
);
401 if (bin_data
->has_build_id
) {
402 tracepoint(lttng_ust_lib
, build_id
,
403 ip
, bin_data
->base_addr_ptr
, bin_data
->build_id
,
404 bin_data
->build_id_len
);
407 if (bin_data
->has_debug_link
) {
408 tracepoint(lttng_ust_lib
, debug_link
,
409 ip
, bin_data
->base_addr_ptr
, bin_data
->dbg_file
,
415 void trace_lib_unload(const struct bin_info_data
*bin_data
, void *ip
)
417 tracepoint(lttng_ust_lib
, unload
, ip
, bin_data
->base_addr_ptr
);
421 void iter_end(struct dl_iterate_data
*data
, void *ip
)
428 * Iterate on hash table.
429 * For each marked, traced, do nothing.
430 * For each marked, not traced, trace lib open event. traced = true.
431 * For each unmarked, traced, trace lib close event. remove node.
432 * For each unmarked, not traced, remove node.
434 for (i
= 0; i
< UST_DL_STATE_TABLE_SIZE
; i
++) {
435 struct cds_hlist_head
*head
;
436 struct lttng_ust_dl_node
*e
, *tmp
;
438 head
= &dl_state_table
[i
];
439 cds_hlist_for_each_entry_safe_2(e
, tmp
, head
, node
) {
442 trace_lib_load(&e
->bin_data
, ip
);
448 trace_lib_unload(&e
->bin_data
, ip
);
459 int extract_bin_info_events(struct dl_phdr_info
*info
, size_t size
, void *_data
)
462 struct dl_iterate_data
*data
= _data
;
472 for (j
= 0; j
< info
->dlpi_phnum
; j
++) {
473 struct bin_info_data bin_data
;
475 if (info
->dlpi_phdr
[j
].p_type
!= PT_LOAD
)
478 memset(&bin_data
, 0, sizeof(bin_data
));
480 /* Calculate virtual memory address of the loadable segment */
481 bin_data
.base_addr_ptr
= (void *) info
->dlpi_addr
+
482 info
->dlpi_phdr
[j
].p_vaddr
;
484 if ((info
->dlpi_name
== NULL
|| info
->dlpi_name
[0] == 0)) {
486 * Only the first phdr without a dlpi_name
487 * encountered is considered as the program
488 * executable. The rest are vdsos.
490 if (!data
->exec_found
) {
492 data
->exec_found
= 1;
495 * Use /proc/self/exe to resolve the
496 * executable's full path.
498 path_len
= readlink("/proc/self/exe",
499 bin_data
.resolved_path
,
504 bin_data
.resolved_path
[path_len
] = '\0';
507 snprintf(bin_data
.resolved_path
,
508 PATH_MAX
- 1, "[vdso]");
513 * For regular dl_phdr_info entries check if
514 * the path to the binary really exists. If not,
515 * treat as vdso and use dlpi_name as 'path'.
517 if (!realpath(info
->dlpi_name
,
518 bin_data
.resolved_path
)) {
519 snprintf(bin_data
.resolved_path
,
520 PATH_MAX
- 1, "[%s]",
528 ret
= extract_baddr(&bin_data
);
536 void ust_dl_table_statedump(void *owner
)
543 /* Statedump each traced table entry into session for owner. */
544 for (i
= 0; i
< UST_DL_STATE_TABLE_SIZE
; i
++) {
545 struct cds_hlist_head
*head
;
546 struct lttng_ust_dl_node
*e
;
548 head
= &dl_state_table
[i
];
549 cds_hlist_for_each_entry_2(e
, head
, node
) {
551 trace_baddr(&e
->bin_data
, owner
);
559 void lttng_ust_dl_update(void *ip
)
561 struct dl_iterate_data data
;
563 if (lttng_getenv("LTTNG_UST_WITHOUT_BADDR_STATEDUMP"))
567 * Fixup lttng-ust TLS when called from dlopen/dlclose
570 lttng_ust_fixup_tls();
576 * Iterate through the list of currently loaded shared objects and
577 * generate tables entries for loadable segments using
578 * extract_bin_info_events.
579 * Removed libraries are detected by mark-and-sweep: marking is
580 * done in the iteration over libraries, and sweeping is
581 * performed by iter_end().
583 dl_iterate_phdr(extract_bin_info_events
, &data
);
590 * Generate a statedump of base addresses of all shared objects loaded
591 * by the traced application, as well as for the application's
595 int do_baddr_statedump(void *owner
)
597 if (lttng_getenv("LTTNG_UST_WITHOUT_BADDR_STATEDUMP"))
599 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
600 ust_dl_table_statedump(owner
);
605 int do_procname_statedump(void *owner
)
607 if (lttng_getenv("LTTNG_UST_WITHOUT_PROCNAME_STATEDUMP"))
610 trace_statedump_event(procname_cb
, owner
, lttng_ust_sockinfo_get_procname(owner
));
615 * Generate a statedump of a given traced application. A statedump is
616 * delimited by start and end events. For a given (process, session)
617 * pair, begin/end events are serialized and will match. However, in a
618 * session, statedumps from different processes may be
619 * interleaved. The vpid context should be used to identify which
620 * events belong to which process.
622 * Grab the ust_lock outside of the RCU read-side lock because we
623 * perform synchronize_rcu with the ust_lock held, which can trigger
624 * deadlocks otherwise.
626 int do_lttng_ust_statedump(void *owner
)
629 trace_statedump_start(owner
);
632 do_procname_statedump(owner
);
633 do_baddr_statedump(owner
);
636 trace_statedump_end(owner
);
642 void lttng_ust_statedump_init(void)
644 __tracepoints__init();
645 __tracepoints__ptrs_init();
646 __lttng_events_init__lttng_ust_statedump();
647 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
651 void ust_dl_state_destroy(void)
655 for (i
= 0; i
< UST_DL_STATE_TABLE_SIZE
; i
++) {
656 struct cds_hlist_head
*head
;
657 struct lttng_ust_dl_node
*e
, *tmp
;
659 head
= &dl_state_table
[i
];
660 cds_hlist_for_each_entry_safe_2(e
, tmp
, head
, node
)
662 CDS_INIT_HLIST_HEAD(head
);
666 void lttng_ust_statedump_destroy(void)
668 __lttng_events_exit__lttng_ust_statedump();
669 __tracepoints__ptrs_destroy();
670 __tracepoints__destroy();
671 ust_dl_state_destroy();