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