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