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