Python bindings: add has_intersection property to TraceCollection
[babeltrace.git] / lib / bin-info.c
CommitLineData
b5a8598f 1/*
dae52e76 2 * bin-info.c
b5a8598f
AB
3 *
4 * Babeltrace - Executable and Shared Object Debug Info Reader
5 *
6 * Copyright 2015 Antoine Busque <abusque@efficios.com>
7 *
8 * Author: Antoine Busque <abusque@efficios.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
29#include <fcntl.h>
30#include <math.h>
31#include <libgen.h>
32#include <stdio.h>
33#include <inttypes.h>
34#include <stdlib.h>
35#include <string.h>
36#include <unistd.h>
37#include <dwarf.h>
38#include <glib.h>
39#include <babeltrace/dwarf.h>
dae52e76 40#include <babeltrace/bin-info.h>
b5a8598f
AB
41#include <babeltrace/crc32.h>
42#include <babeltrace/babeltrace-internal.h>
beef86dc 43#include <babeltrace/utils.h>
b5a8598f
AB
44
45/*
46 * An address printed in hex is at most 20 bytes (16 for 64-bits +
47 * leading 0x + optional leading '+' if addr is an offset + null
48 * character).
49 */
50#define ADDR_STR_LEN 20
51
52BT_HIDDEN
dae52e76 53int bin_info_init(void)
b5a8598f
AB
54{
55 int ret = 0;
56
57 if (elf_version(EV_CURRENT) == EV_NONE) {
1036949d
AB
58 printf_debug("ELF library initialization failed: %s\n",
59 elf_errmsg(-1));
b5a8598f
AB
60 ret = -1;
61 }
62
63 return ret;
64}
65
66BT_HIDDEN
dae52e76 67struct bin_info *bin_info_create(const char *path, uint64_t low_addr,
1a4a1345 68 uint64_t memsz, bool is_pic)
b5a8598f 69{
dae52e76 70 struct bin_info *bin = NULL;
b5a8598f
AB
71
72 if (!path) {
73 goto error;
74 }
75
dae52e76
AB
76 bin = g_new0(struct bin_info, 1);
77 if (!bin) {
b5a8598f
AB
78 goto error;
79 }
80
b7b61ced 81 if (opt_debug_info_target_prefix) {
dae52e76 82 bin->elf_path = g_build_path("/", opt_debug_info_target_prefix,
b7b61ced
AB
83 path, NULL);
84 } else {
dae52e76 85 bin->elf_path = strdup(path);
b7b61ced
AB
86 }
87
dae52e76 88 if (!bin->elf_path) {
b5a8598f
AB
89 goto error;
90 }
91
dae52e76
AB
92 bin->is_pic = is_pic;
93 bin->memsz = memsz;
94 bin->low_addr = low_addr;
95 bin->high_addr = bin->low_addr + bin->memsz;
b5a8598f 96
dae52e76 97 return bin;
b5a8598f
AB
98
99error:
dae52e76 100 bin_info_destroy(bin);
b5a8598f
AB
101 return NULL;
102}
103
104BT_HIDDEN
dae52e76 105void bin_info_destroy(struct bin_info *bin)
b5a8598f 106{
dae52e76 107 if (!bin) {
b5a8598f
AB
108 return;
109 }
110
dae52e76 111 dwarf_end(bin->dwarf_info);
b5a8598f 112
dae52e76
AB
113 free(bin->elf_path);
114 free(bin->dwarf_path);
115 free(bin->build_id);
116 free(bin->dbg_link_filename);
b5a8598f 117
dae52e76 118 elf_end(bin->elf_file);
b5a8598f 119
dae52e76
AB
120 close(bin->elf_fd);
121 close(bin->dwarf_fd);
b5a8598f 122
dae52e76 123 g_free(bin);
b5a8598f
AB
124}
125
b8652b58 126
b5a8598f 127BT_HIDDEN
dae52e76 128int bin_info_set_build_id(struct bin_info *bin, uint8_t *build_id,
b5a8598f
AB
129 size_t build_id_len)
130{
dae52e76 131 if (!bin || !build_id) {
b5a8598f
AB
132 goto error;
133 }
134
dae52e76
AB
135 bin->build_id = malloc(build_id_len);
136 if (!bin->build_id) {
b5a8598f
AB
137 goto error;
138 }
139
dae52e76
AB
140 memcpy(bin->build_id, build_id, build_id_len);
141 bin->build_id_len = build_id_len;
b5a8598f
AB
142
143 /*
144 * Reset the is_elf_only flag in case it had been set
145 * previously, because we might find separate debug info using
146 * the new build id information.
147 */
dae52e76 148 bin->is_elf_only = false;
b5a8598f
AB
149
150 return 0;
151
152error:
153
154 return -1;
155}
156
157BT_HIDDEN
dae52e76 158int bin_info_set_debug_link(struct bin_info *bin, char *filename, uint32_t crc)
b5a8598f 159{
dae52e76 160 if (!bin || !filename) {
b5a8598f
AB
161 goto error;
162 }
163
dae52e76
AB
164 bin->dbg_link_filename = strdup(filename);
165 if (!bin->dbg_link_filename) {
b5a8598f
AB
166 goto error;
167 }
168
dae52e76 169 bin->dbg_link_crc = crc;
b5a8598f
AB
170
171 /*
172 * Reset the is_elf_only flag in case it had been set
173 * previously, because we might find separate debug info using
174 * the new build id information.
175 */
dae52e76 176 bin->is_elf_only = false;
b5a8598f
AB
177
178 return 0;
179
180error:
181
182 return -1;
183}
184
185/**
186 * Tries to read DWARF info from the location given by path, and
dae52e76 187 * attach it to the given bin_info instance if it exists.
b5a8598f 188 *
dae52e76 189 * @param bin bin_info instance for which to set DWARF info
b5a8598f
AB
190 * @param path Presumed location of the DWARF info
191 * @returns 0 on success, -1 on failure
192 */
193static
dae52e76 194int bin_info_set_dwarf_info_from_path(struct bin_info *bin, char *path)
b5a8598f
AB
195{
196 int fd = -1, ret = 0;
197 struct bt_dwarf_cu *cu = NULL;
198 Dwarf *dwarf_info = NULL;
199
dae52e76 200 if (!bin || !path) {
b5a8598f
AB
201 goto error;
202 }
203
204 fd = open(path, O_RDONLY);
205 if (fd < 0) {
206 goto error;
207 }
208
209 dwarf_info = dwarf_begin(fd, DWARF_C_READ);
210 if (!dwarf_info) {
211 goto error;
212 }
213
214 /*
dae52e76
AB
215 * Check if the dwarf info has any CU. If not, the
216 * executable's object file contains no DWARF info.
b5a8598f
AB
217 */
218 cu = bt_dwarf_cu_create(dwarf_info);
219 if (!cu) {
220 goto error;
221 }
222
223 ret = bt_dwarf_cu_next(cu);
224 if (ret) {
225 goto error;
226 }
227
dae52e76
AB
228 bin->dwarf_fd = fd;
229 bin->dwarf_path = strdup(path);
230 if (!bin->dwarf_path) {
b5a8598f
AB
231 goto error;
232 }
dae52e76 233 bin->dwarf_info = dwarf_info;
b5a8598f
AB
234 free(cu);
235
236 return 0;
237
238error:
239 close(fd);
240 dwarf_end(dwarf_info);
241 g_free(dwarf_info);
242 free(cu);
243
244 return -1;
245}
246
247/**
dae52e76 248 * Try to set the dwarf_info for a given bin_info instance via the
b5a8598f
AB
249 * build ID method.
250 *
dae52e76 251 * @param bin bin_info instance for which to retrieve the
b5a8598f
AB
252 * DWARF info via build ID
253 * @returns 0 on success (i.e. dwarf_info set), -1 on failure
254 */
255static
dae52e76 256int bin_info_set_dwarf_info_build_id(struct bin_info *bin)
b5a8598f 257{
1b3f6ee3 258 int i = 0, ret = 0;
b5a8598f
AB
259 char *path = NULL, *build_id_file = NULL;
260 const char *dbg_dir = NULL;
1b3f6ee3 261 size_t build_id_file_len;
b5a8598f 262
dae52e76 263 if (!bin || !bin->build_id) {
b5a8598f
AB
264 goto error;
265 }
266
3be1e3c9 267 dbg_dir = opt_debug_info_dir ? : DEFAULT_DEBUG_DIR;
b5a8598f 268
1b3f6ee3
AB
269 /* 2 characters per byte printed in hex, +1 for '/' and +1 for
270 * '\0' */
dae52e76 271 build_id_file_len = (2 * bin->build_id_len) + 1 +
1b3f6ee3 272 strlen(BUILD_ID_SUFFIX) + 1;
b5a8598f
AB
273 build_id_file = malloc(build_id_file_len);
274 if (!build_id_file) {
275 goto error;
276 }
277
dae52e76
AB
278 snprintf(build_id_file, 4, "%02x/", bin->build_id[0]);
279 for (i = 1; i < bin->build_id_len; ++i) {
b5a8598f
AB
280 int path_idx = 3 + 2 * (i - 1);
281
dae52e76 282 snprintf(&build_id_file[path_idx], 3, "%02x", bin->build_id[i]);
b5a8598f 283 }
1b3f6ee3 284 strcat(build_id_file, BUILD_ID_SUFFIX);
b5a8598f 285
1b3f6ee3 286 path = g_build_path("/", dbg_dir, BUILD_ID_SUBDIR, build_id_file, NULL);
b5a8598f
AB
287 if (!path) {
288 goto error;
289 }
290
dae52e76 291 ret = bin_info_set_dwarf_info_from_path(bin, path);
b5a8598f
AB
292 if (ret) {
293 goto error;
294 }
295
296 goto end;
297
298error:
299 ret = -1;
300end:
301 free(build_id_file);
302 free(path);
303
304 return ret;
305}
306
307/**
308 * Tests whether the file located at path exists and has the expected
309 * checksum.
310 *
311 * This predicate is used when looking up separate debug info via the
312 * GNU debuglink method. The expected crc can be found .gnu_debuglink
313 * section in the original ELF file, along with the filename for the
314 * file containing the debug info.
315 *
316 * @param path Full path at which to look for the debug file
317 * @param crc Expected checksum for the debug file
318 * @returns 1 if the file exists and has the correct checksum,
319 * 0 otherwise
320 */
321static
322int is_valid_debug_file(char *path, uint32_t crc)
323{
324 int ret = 0, fd = -1;
325 uint32_t _crc = 0;
326
327 if (!path) {
328 goto end;
329 }
330
331 fd = open(path, O_RDONLY);
332 if (fd < 0) {
333 goto end;
334 }
335
336 ret = crc32(fd, &_crc);
337 if (ret) {
338 ret = 0;
339 goto end;
340 }
341
342 ret = (crc == _crc);
343
344end:
345 close(fd);
346 return ret;
347}
348
349/**
dae52e76 350 * Try to set the dwarf_info for a given bin_info instance via the
b5a8598f
AB
351 * build ID method.
352 *
dae52e76 353 * @param bin bin_info instance for which to retrieve the
b5a8598f
AB
354 * DWARF info via debug link
355 * @returns 0 on success (i.e. dwarf_info set), -1 on failure
356 */
357static
dae52e76 358int bin_info_set_dwarf_info_debug_link(struct bin_info *bin)
b5a8598f
AB
359{
360 int ret = 0;
361 const char *dbg_dir = NULL;
dae52e76 362 char *dir_name = NULL, *bin_dir = NULL, *path = NULL;
b5a8598f
AB
363 size_t max_path_len = 0;
364
dae52e76 365 if (!bin || !bin->dbg_link_filename) {
b5a8598f
AB
366 goto error;
367 }
368
3be1e3c9 369 dbg_dir = opt_debug_info_dir ? : DEFAULT_DEBUG_DIR;
b5a8598f 370
dae52e76 371 dir_name = dirname(bin->elf_path);
b5a8598f
AB
372 if (!dir_name) {
373 goto error;
374 }
375
dae52e76
AB
376 /* bin_dir is just dir_name with a trailing slash */
377 bin_dir = malloc(strlen(dir_name) + 2);
378 if (!bin_dir) {
b5a8598f
AB
379 goto error;
380 }
381
dae52e76
AB
382 strcpy(bin_dir, dir_name);
383 strcat(bin_dir, "/");
b5a8598f 384
dae52e76
AB
385 max_path_len = strlen(dbg_dir) + strlen(bin_dir) +
386 strlen(DEBUG_SUBDIR) + strlen(bin->dbg_link_filename)
b5a8598f
AB
387 + 1;
388 path = malloc(max_path_len);
389 if (!path) {
390 goto error;
391 }
392
dae52e76
AB
393 /* First look in the executable's dir */
394 strcpy(path, bin_dir);
395 strcat(path, bin->dbg_link_filename);
b5a8598f 396
dae52e76 397 if (is_valid_debug_file(path, bin->dbg_link_crc)) {
b5a8598f
AB
398 goto found;
399 }
400
401 /* If not found, look in .debug subdir */
dae52e76 402 strcpy(path, bin_dir);
b5a8598f 403 strcat(path, DEBUG_SUBDIR);
dae52e76 404 strcat(path, bin->dbg_link_filename);
b5a8598f 405
dae52e76 406 if (is_valid_debug_file(path, bin->dbg_link_crc)) {
b5a8598f
AB
407 goto found;
408 }
409
410 /* Lastly, look under the global debug directory */
411 strcpy(path, dbg_dir);
dae52e76
AB
412 strcat(path, bin_dir);
413 strcat(path, bin->dbg_link_filename);
b5a8598f 414
dae52e76 415 if (is_valid_debug_file(path, bin->dbg_link_crc)) {
b5a8598f
AB
416 goto found;
417 }
418
419error:
420 ret = -1;
421end:
422 free(path);
dae52e76 423 free(bin_dir);
b5a8598f
AB
424
425 return ret;
426
427found:
dae52e76 428 ret = bin_info_set_dwarf_info_from_path(bin, path);
b5a8598f
AB
429 if (ret) {
430 goto error;
431 }
432
433 goto end;
434}
435
436/**
437 * Initialize the DWARF info for a given executable.
438 *
dae52e76 439 * @param bin bin_info instance
b5a8598f
AB
440 * @returns 0 on success, -1 on failure
441 */
442static
dae52e76 443int bin_info_set_dwarf_info(struct bin_info *bin)
b5a8598f
AB
444{
445 int ret = 0;
446
dae52e76 447 if (!bin) {
b5a8598f
AB
448 goto error;
449 }
450
451 /* First try to set the DWARF info from the ELF file */
dae52e76 452 ret = bin_info_set_dwarf_info_from_path(bin, bin->elf_path);
b5a8598f
AB
453 if (!ret) {
454 goto end;
455 }
456
457 /*
458 * If that fails, try to find separate debug info via build ID
459 * and debug link.
460 */
dae52e76 461 ret = bin_info_set_dwarf_info_build_id(bin);
b5a8598f
AB
462 if (!ret) {
463 goto end;
464 }
465
dae52e76 466 ret = bin_info_set_dwarf_info_debug_link(bin);
b5a8598f
AB
467 if (!ret) {
468 goto end;
469 }
470
471error:
472 ret = -1;
473end:
474 return ret;
475}
476
b8652b58
AB
477/**
478 * Initialize the ELF file for a given executable.
479 *
dae52e76 480 * @param bin bin_info instance
b8652b58
AB
481 * @returns 0 on success, -1 on failure
482 */
483static
dae52e76 484int bin_info_set_elf_file(struct bin_info *bin)
b8652b58
AB
485{
486 int elf_fd;
e362dc93 487 Elf *elf_file = NULL;
b8652b58 488
dae52e76 489 if (!bin) {
b8652b58
AB
490 goto error;
491 }
492
dae52e76 493 elf_fd = open(bin->elf_path, O_RDONLY);
b8652b58 494 if (elf_fd < 0) {
dae52e76 495 printf_verbose("Failed to open %s\n", bin->elf_path);
b8652b58
AB
496 goto error;
497 }
498
499 elf_file = elf_begin(elf_fd, ELF_C_READ, NULL);
500 if (!elf_file) {
1036949d 501 printf_debug("elf_begin failed: %s\n", elf_errmsg(-1));
b8652b58
AB
502 goto error;
503 }
504
505 if (elf_kind(elf_file) != ELF_K_ELF) {
1036949d 506 printf_verbose("Error: %s is not an ELF object\n",
dae52e76 507 bin->elf_path);
b8652b58
AB
508 goto error;
509 }
510
dae52e76
AB
511 bin->elf_fd = elf_fd;
512 bin->elf_file = elf_file;
b8652b58
AB
513 return 0;
514
515error:
516 close(elf_fd);
517 elf_end(elf_file);
518 return -1;
519}
520
521
b5a8598f
AB
522BT_HIDDEN
523void source_location_destroy(struct source_location *src_loc)
524{
525 if (!src_loc) {
526 return;
527 }
528
529 free(src_loc->filename);
530 g_free(src_loc);
531}
1c47ec6c
AB
532/**
533 * Append a string representation of an address offset to an existing
534 * string.
535 *
536 * On success, the out parameter `result` will contain the base string
537 * followed by the offset string of the form "+0x1234". On failure,
538 * `result` remains unchanged.
539 *
540 * @param base_str The string to which to append an offset string
541 * @param low_addr The lower virtual memory address, the base from
542 * which the offset is computed
543 * @param high_addr The higher virtual memory address
544 * @param result Out parameter, the base string followed by the
545 * offset string
546 * @returns 0 on success, -1 on failure
547 */
548static
dae52e76 549int bin_info_append_offset_str(const char *base_str, uint64_t low_addr,
1c47ec6c
AB
550 uint64_t high_addr, char **result)
551{
552 int ret;
553 uint64_t offset;
554 char *_result = NULL;
555 char offset_str[ADDR_STR_LEN];
556
557 if (!base_str || !result) {
558 goto error;
559 }
560
561 offset = high_addr - low_addr;
562
563 _result = malloc(strlen(base_str) + ADDR_STR_LEN);
564 if (!_result) {
565 goto error;
566 }
567
568 ret = snprintf(offset_str, ADDR_STR_LEN, "+%#0" PRIx64, offset);
569 if (ret < 0) {
570 goto error;
571 }
572 strcpy(_result, base_str);
573 strcat(_result, offset_str);
574 *result = _result;
575
576 return 0;
577
578error:
579 free(_result);
580 return -1;
581}
b5a8598f
AB
582
583/**
584 * Try to find the symbol closest to an address within a given ELF
585 * section.
586 *
587 * Only function symbols are taken into account. The symbol's address
588 * must precede `addr`. A symbol with a closer address might exist
589 * after `addr` but is irrelevant because it cannot encompass `addr`.
590 *
591 * On success, if found, the out parameters `sym` and `shdr` are
592 * set. On failure or if none are found, they remain unchanged.
593 *
594 * @param scn ELF section in which to look for the address
595 * @param addr Virtual memory address for which to find the
596 * nearest function symbol
597 * @param sym Out parameter, the nearest function symbol
598 * @param shdr Out parameter, the section header for scn
599 * @returns 0 on success, -1 on failure
600 */
601static
dae52e76 602int bin_info_get_nearest_symbol_from_section(Elf_Scn *scn, uint64_t addr,
b5a8598f
AB
603 GElf_Sym **sym, GElf_Shdr **shdr)
604{
605 int i;
606 size_t symbol_count;
607 Elf_Data *data = NULL;
608 GElf_Shdr *_shdr = NULL;
609 GElf_Sym *nearest_sym = NULL;
610
611 if (!scn || !sym || !shdr) {
612 goto error;
613 }
614
615 _shdr = g_new0(GElf_Shdr, 1);
616 if (!_shdr) {
617 goto error;
618 }
619
620 _shdr = gelf_getshdr(scn, _shdr);
621 if (!_shdr) {
622 goto error;
623 }
624
625 if (_shdr->sh_type != SHT_SYMTAB) {
626 /*
627 * We are only interested in symbol table (symtab)
628 * sections, skip this one.
629 */
630 goto end;
631 }
632
633 data = elf_getdata(scn, NULL);
634 if (!data) {
635 goto error;
636 }
637
638 symbol_count = _shdr->sh_size / _shdr->sh_entsize;
639
640 for (i = 0; i < symbol_count; ++i) {
641 GElf_Sym *cur_sym = NULL;
642
643 cur_sym = g_new0(GElf_Sym, 1);
644 if (!cur_sym) {
645 goto error;
646 }
647 cur_sym = gelf_getsym(data, i, cur_sym);
648 if (!cur_sym) {
649 goto error;
650 }
651 if (GELF_ST_TYPE(cur_sym->st_info) != STT_FUNC) {
652 /* We're only interested in the functions. */
653 g_free(cur_sym);
654 continue;
655 }
656
657 if (cur_sym->st_value <= addr &&
658 (!nearest_sym ||
659 cur_sym->st_value > nearest_sym->st_value)) {
660 g_free(nearest_sym);
661 nearest_sym = cur_sym;
662 } else {
663 g_free(cur_sym);
664 }
665 }
666
667end:
668 if (nearest_sym) {
669 *sym = nearest_sym;
670 *shdr = _shdr;
671 } else {
672 g_free(_shdr);
673 }
674
675 return 0;
676
677error:
678 g_free(nearest_sym);
679 g_free(_shdr);
680 return -1;
681}
682
683/**
684 * Get the name of the function containing a given address within an
685 * executable using ELF symbols.
686 *
687 * The function name is in fact the name of the nearest ELF symbol,
688 * followed by the offset in bytes between the address and the symbol
689 * (in hex), separated by a '+' character.
690 *
691 * If found, the out parameter `func_name` is set on success. On failure,
692 * it remains unchanged.
693 *
dae52e76 694 * @param bin bin_info instance for the executable containing
b5a8598f
AB
695 * the address
696 * @param addr Virtual memory address for which to find the
697 * function name
698 * @param func_name Out parameter, the function name
699 * @returns 0 on success, -1 on failure
700 */
701static
dae52e76 702int bin_info_lookup_elf_function_name(struct bin_info *bin, uint64_t addr,
b5a8598f
AB
703 char **func_name)
704{
705 /*
706 * TODO (possible optimisation): if an ELF has no symtab
707 * section, it has been stripped. Therefore, it would be wise
708 * to store a flag indicating the stripped status after the
709 * first iteration to prevent subsequent ones.
710 */
711 int ret = 0;
712 Elf_Scn *scn = NULL;
713 GElf_Sym *sym = NULL;
714 GElf_Shdr *shdr = NULL;
715 char *sym_name = NULL;
b5a8598f 716
b8652b58 717 /* Set ELF file if it hasn't been accessed yet. */
dae52e76
AB
718 if (!bin->elf_file) {
719 ret = bin_info_set_elf_file(bin);
b8652b58
AB
720 if (ret) {
721 /* Failed to set ELF file. */
722 goto error;
723 }
724 }
725
dae52e76 726 scn = elf_nextscn(bin->elf_file, scn);
b5a8598f
AB
727 if (!scn) {
728 goto error;
729 }
730
731 while (scn && !sym) {
dae52e76 732 ret = bin_info_get_nearest_symbol_from_section(
b5a8598f
AB
733 scn, addr, &sym, &shdr);
734 if (ret) {
735 goto error;
736 }
737
dae52e76 738 scn = elf_nextscn(bin->elf_file, scn);
b5a8598f
AB
739 }
740
741 if (sym) {
dae52e76 742 sym_name = elf_strptr(bin->elf_file, shdr->sh_link,
b5a8598f
AB
743 sym->st_name);
744 if (!sym_name) {
745 goto error;
746 }
747
dae52e76 748 ret = bin_info_append_offset_str(sym_name, sym->st_value, addr,
1c47ec6c
AB
749 func_name);
750 if (ret) {
b5a8598f
AB
751 goto error;
752 }
b5a8598f
AB
753 }
754
755 g_free(shdr);
756 g_free(sym);
757 return 0;
758
759error:
760 g_free(shdr);
761 g_free(sym);
b5a8598f
AB
762 return -1;
763}
764
765/**
766 * Get the name of the function containing a given address within a
767 * given compile unit (CU).
768 *
769 * If found, the out parameter `func_name` is set on success. On
770 * failure, it remains unchanged.
771 *
772 * @param cu bt_dwarf_cu instance which may contain the address
773 * @param addr Virtual memory address for which to find the
774 * function name
775 * @param func_name Out parameter, the function name
776 * @returns 0 on success, -1 on failure
777 */
778static
dae52e76 779int bin_info_lookup_cu_function_name(struct bt_dwarf_cu *cu, uint64_t addr,
b5a8598f
AB
780 char **func_name)
781{
302314ec
AB
782 int ret = 0;
783 bool found = false;
b5a8598f
AB
784 struct bt_dwarf_die *die = NULL;
785
786 if (!cu || !func_name) {
787 goto error;
788 }
789
790 die = bt_dwarf_die_create(cu);
791 if (!die) {
792 goto error;
793 }
794
795 while (bt_dwarf_die_next(die) == 0) {
796 int tag;
797
798 ret = bt_dwarf_die_get_tag(die, &tag);
799 if (ret) {
800 goto error;
801 }
802
803 if (tag == DW_TAG_subprogram) {
804 ret = bt_dwarf_die_contains_addr(die, addr, &found);
805 if (ret) {
806 goto error;
807 }
808
809 if (found) {
810 break;
811 }
812 }
813 }
814
815 if (found) {
1c47ec6c
AB
816 uint64_t low_addr = 0;
817 char *die_name = NULL;
818
d3c33bc6
AB
819 ret = bt_dwarf_die_get_name(die, &die_name);
820 if (ret) {
821 goto error;
822 }
823
824 ret = dwarf_lowpc(die->dwarf_die, &low_addr);
b5a8598f
AB
825 if (ret) {
826 goto error;
827 }
828
dae52e76 829 ret = bin_info_append_offset_str(die_name, low_addr, addr,
1c47ec6c
AB
830 func_name);
831 if (ret) {
d3c33bc6
AB
832 goto error;
833 }
b5a8598f
AB
834 }
835
836 bt_dwarf_die_destroy(die);
837 return 0;
838
839error:
840 bt_dwarf_die_destroy(die);
841 return -1;
842}
843
844/**
845 * Get the name of the function containing a given address within an
846 * executable using DWARF debug info.
847 *
848 * If found, the out parameter `func_name` is set on success. On
849 * failure, it remains unchanged.
850 *
dae52e76 851 * @param bin bin_info instance for the executable containing
b5a8598f
AB
852 * the address
853 * @param addr Virtual memory address for which to find the
854 * function name
855 * @param func_name Out parameter, the function name
856 * @returns 0 on success, -1 on failure
857 */
858static
dae52e76 859int bin_info_lookup_dwarf_function_name(struct bin_info *bin, uint64_t addr,
b5a8598f
AB
860 char **func_name)
861{
862 int ret = 0;
863 char *_func_name = NULL;
864 struct bt_dwarf_cu *cu = NULL;
865
dae52e76 866 if (!bin || !func_name) {
b5a8598f
AB
867 goto error;
868 }
869
dae52e76 870 cu = bt_dwarf_cu_create(bin->dwarf_info);
b5a8598f
AB
871 if (!cu) {
872 goto error;
873 }
874
875 while (bt_dwarf_cu_next(cu) == 0) {
dae52e76 876 ret = bin_info_lookup_cu_function_name(cu, addr, &_func_name);
b5a8598f
AB
877 if (ret) {
878 goto error;
879 }
880
881 if (_func_name) {
882 break;
883 }
884 }
885
886 if (_func_name) {
887 *func_name = _func_name;
fcd94e37
JG
888 } else {
889 goto error;
b5a8598f
AB
890 }
891
892 bt_dwarf_cu_destroy(cu);
893 return 0;
894
895error:
896 bt_dwarf_cu_destroy(cu);
897 return -1;
898}
899
900BT_HIDDEN
dae52e76 901int bin_info_lookup_function_name(struct bin_info *bin, uint64_t addr,
b5a8598f
AB
902 char **func_name)
903{
904 int ret = 0;
905 char *_func_name = NULL;
906
dae52e76 907 if (!bin || !func_name) {
b5a8598f
AB
908 goto error;
909 }
910
911 /* Set DWARF info if it hasn't been accessed yet. */
dae52e76
AB
912 if (!bin->dwarf_info && !bin->is_elf_only) {
913 ret = bin_info_set_dwarf_info(bin);
b5a8598f
AB
914 if (ret) {
915 /* Failed to set DWARF info, fallback to ELF. */
dae52e76 916 bin->is_elf_only = true;
b5a8598f
AB
917 }
918 }
919
dae52e76 920 if (!bin_info_has_address(bin, addr)) {
b5a8598f
AB
921 goto error;
922 }
923
924 /*
925 * Addresses in ELF and DWARF are relative to base address for
926 * PIC, so make the address argument relative too if needed.
927 */
dae52e76
AB
928 if (bin->is_pic) {
929 addr -= bin->low_addr;
dc419b6c
AB
930 }
931
dae52e76
AB
932 if (bin->is_elf_only) {
933 ret = bin_info_lookup_elf_function_name(bin, addr, &_func_name);
b5a8598f 934 } else {
dae52e76 935 ret = bin_info_lookup_dwarf_function_name(bin, addr, &_func_name);
b5a8598f
AB
936 }
937
dc419b6c 938 if (ret || !_func_name) {
b5a8598f
AB
939 goto error;
940 }
941
dc419b6c
AB
942 *func_name = _func_name;
943 return 0;
beef86dc 944
dc419b6c
AB
945error:
946 return -1;
947}
948
949BT_HIDDEN
dae52e76 950int bin_info_get_bin_loc(struct bin_info *bin, uint64_t addr, char **bin_loc)
dc419b6c
AB
951{
952 int ret = 0;
953 char *_bin_loc = NULL;
954
dae52e76 955 if (!bin || !bin_loc) {
dc419b6c 956 goto error;
b5a8598f
AB
957 }
958
dae52e76
AB
959 if (bin->is_pic) {
960 addr -= bin->low_addr;
dc419b6c
AB
961 ret = asprintf(&_bin_loc, "+%#0" PRIx64, addr);
962 } else {
963 ret = asprintf(&_bin_loc, "@%#0" PRIx64, addr);
964 }
965
966 if (ret == -1 || !_bin_loc) {
967 goto error;
968 }
969
970 *bin_loc = _bin_loc;
b5a8598f
AB
971 return 0;
972
973error:
974 return -1;
975}
976
977/**
978 * Predicate used to determine whether the children of a given DIE
979 * contain a specific address.
980 *
981 * More specifically, the parameter `die` is expected to be a
982 * subprogram (function) DIE, and this predicate tells whether any
983 * subroutines are inlined within this function and would contain
984 * `addr`.
985 *
302314ec
AB
986 * On success, the out parameter `contains` is set with the boolean
987 * value indicating whether the DIE's range covers `addr`. On failure,
988 * it remains unchanged.
989 *
b5a8598f
AB
990 * Do note that this function advances the position of `die`. If the
991 * address is found within one of its children, `die` will be pointing
992 * to that child upon returning from the function, allowing to extract
993 * the information deemed necessary.
994 *
302314ec
AB
995 * @param die The parent DIE in whose children the address will be
996 * looked for
997 * @param addr The address for which to look for in the DIEs
998 * @param contains Out parameter, true if addr is contained,
999 * false if not
1000 * @returns Returns 0 on success, -1 on failure
b5a8598f
AB
1001 */
1002static
302314ec 1003int bin_info_child_die_has_address(struct bt_dwarf_die *die, uint64_t addr, bool *contains)
b5a8598f 1004{
302314ec
AB
1005 int ret = 0;
1006 bool _contains = false;
b5a8598f
AB
1007
1008 if (!die) {
1009 goto error;
1010 }
1011
1012 ret = bt_dwarf_die_child(die);
1013 if (ret) {
1014 goto error;
1015 }
1016
1017 do {
1018 int tag;
1019
1020 ret = bt_dwarf_die_get_tag(die, &tag);
1021 if (ret) {
1022 goto error;
1023 }
1024
1025 if (tag == DW_TAG_inlined_subroutine) {
302314ec 1026 ret = bt_dwarf_die_contains_addr(die, addr, &_contains);
b5a8598f
AB
1027 if (ret) {
1028 goto error;
1029 }
1030
1031 if (contains) {
b5a8598f
AB
1032 goto end;
1033 }
1034 }
1035 } while (bt_dwarf_die_next(die) == 0);
1036
1037end:
302314ec
AB
1038 *contains = _contains;
1039 return 0;
b5a8598f
AB
1040
1041error:
302314ec 1042 return -1;
b5a8598f
AB
1043}
1044
1045/**
1046 * Lookup the source location for a given address within a CU, making
1047 * the assumption that it is contained within an inline routine in a
1048 * function.
1049 *
1050 * @param cu bt_dwarf_cu instance in which to look for the address
1051 * @param addr The address for which to look for
1052 * @param src_loc Out parameter, the source location (filename and
1053 * line number) for the address
1054 * @returns 0 on success, -1 on failure
1055 */
1056static
dae52e76 1057int bin_info_lookup_cu_src_loc_inl(struct bt_dwarf_cu *cu, uint64_t addr,
b5a8598f
AB
1058 struct source_location **src_loc)
1059{
302314ec
AB
1060 int ret = 0;
1061 bool found = false;
b5a8598f
AB
1062 struct bt_dwarf_die *die = NULL;
1063 struct source_location *_src_loc = NULL;
1064
1065 if (!cu || !src_loc) {
1066 goto error;
1067 }
1068
1069 die = bt_dwarf_die_create(cu);
1070 if (!die) {
1071 goto error;
1072 }
1073
1074 while (bt_dwarf_die_next(die) == 0) {
1075 int tag;
1076
1077 ret = bt_dwarf_die_get_tag(die, &tag);
1078 if (ret) {
1079 goto error;
1080 }
1081
1082 if (tag == DW_TAG_subprogram) {
302314ec 1083 bool contains = false;
b5a8598f
AB
1084
1085 ret = bt_dwarf_die_contains_addr(die, addr, &contains);
1086 if (ret) {
1087 goto error;
1088 }
1089
1090 if (contains) {
1091 /*
1092 * Try to find an inlined subroutine
1093 * child of this DIE containing addr.
1094 */
302314ec
AB
1095 ret = bin_info_child_die_has_address(die, addr,
1096 &found);
1097 if(ret) {
1098 goto error;
1099 }
1100
b5a8598f
AB
1101 goto end;
1102 }
1103 }
1104 }
1105
1106end:
1107 if (found) {
1108 char *filename = NULL;
1109 uint64_t line_no;
1110
1111 _src_loc = g_new0(struct source_location, 1);
1112 if (!_src_loc) {
1113 goto error;
1114 }
1115
1116 ret = bt_dwarf_die_get_call_file(die, &filename);
1117 if (ret) {
1118 goto error;
1119 }
1120 ret = bt_dwarf_die_get_call_line(die, &line_no);
1121 if (ret) {
1122 free(filename);
1123 goto error;
1124 }
1125
1126 _src_loc->filename = filename;
1127 _src_loc->line_no = line_no;
1128 *src_loc = _src_loc;
1129 }
1130
1131 bt_dwarf_die_destroy(die);
1132 return 0;
1133
1134error:
1135 source_location_destroy(_src_loc);
1136 bt_dwarf_die_destroy(die);
1137 return -1;
1138}
1139
1140/**
1141 * Lookup the source location for a given address within a CU,
1142 * assuming that it is contained within an inlined function.
1143 *
1144 * A source location can be found regardless of inlining status for
1145 * this method, but in the case of an inlined function, the returned
1146 * source location will point not to the callsite but rather to the
1147 * definition site of the inline function.
1148 *
1149 * @param cu bt_dwarf_cu instance in which to look for the address
1150 * @param addr The address for which to look for
1151 * @param src_loc Out parameter, the source location (filename and
1152 * line number) for the address
1153 * @returns 0 on success, -1 on failure
1154 */
1155static
dae52e76 1156int bin_info_lookup_cu_src_loc_no_inl(struct bt_dwarf_cu *cu, uint64_t addr,
b5a8598f
AB
1157 struct source_location **src_loc)
1158{
1159 struct source_location *_src_loc = NULL;
1160 struct bt_dwarf_die *die = NULL;
1161 const char *filename = NULL;
1162 Dwarf_Line *line = NULL;
1163 Dwarf_Addr line_addr;
1164 int ret, line_no;
1165
1166 if (!cu || !src_loc) {
1167 goto error;
1168 }
1169
1170 die = bt_dwarf_die_create(cu);
1171 if (!die) {
1172 goto error;
1173 }
1174
1175 line = dwarf_getsrc_die(die->dwarf_die, addr);
1176 if (!line) {
1177 goto error;
1178 }
1179
1180 ret = dwarf_lineaddr(line, &line_addr);
1181 if (ret) {
1182 goto error;
1183 }
1184
1185 filename = dwarf_linesrc(line, NULL, NULL);
1186 if (!filename) {
1187 goto error;
1188 }
1189
1190 if (addr == line_addr) {
1191 _src_loc = g_new0(struct source_location, 1);
1192 if (!_src_loc) {
1193 goto error;
1194 }
1195
1196 ret = dwarf_lineno(line, &line_no);
1197 if (ret) {
1198 goto error;
1199 }
1200
1201 _src_loc->line_no = line_no;
1202 _src_loc->filename = strdup(filename);
1203 }
1204
1205 bt_dwarf_die_destroy(die);
1206
1207 if (_src_loc) {
1208 *src_loc = _src_loc;
1209 }
1210
1211 return 0;
1212
1213error:
1214 source_location_destroy(_src_loc);
1215 bt_dwarf_die_destroy(die);
1216 return -1;
1217}
1218
1219/**
1220 * Get the source location (file name and line number) for a given
1221 * address within a compile unit (CU).
1222 *
1223 * On success, the out parameter `src_loc` is set if found. On
1224 * failure, it remains unchanged.
1225 *
dae52e76 1226 * @param cu bt_dwarf_cu instance for the compile unit which
b5a8598f
AB
1227 * may contain the address
1228 * @param addr Virtual memory address for which to find the
1229 * source location
1230 * @param src_loc Out parameter, the source location
1231 * @returns 0 on success, -1 on failure
1232 */
1233static
dae52e76 1234int bin_info_lookup_cu_src_loc(struct bt_dwarf_cu *cu, uint64_t addr,
b5a8598f
AB
1235 struct source_location **src_loc)
1236{
1237 int ret = 0;
1238 struct source_location *_src_loc = NULL;
1239
1240 if (!cu || !src_loc) {
1241 goto error;
1242 }
1243
dae52e76 1244 ret = bin_info_lookup_cu_src_loc_inl(cu, addr, &_src_loc);
b5a8598f
AB
1245 if (ret) {
1246 goto error;
1247 }
1248
1249 if (_src_loc) {
1250 goto end;
1251 }
1252
dae52e76 1253 ret = bin_info_lookup_cu_src_loc_no_inl(cu, addr, &_src_loc);
b5a8598f
AB
1254 if (ret) {
1255 goto error;
1256 }
1257
1258 if (_src_loc) {
1259 goto end;
1260 }
1261
1262end:
1263 if (_src_loc) {
1264 *src_loc = _src_loc;
1265 }
1266
1267 return 0;
1268
1269error:
1270 source_location_destroy(_src_loc);
1271 return -1;
1272}
1273
1274BT_HIDDEN
dae52e76 1275int bin_info_lookup_source_location(struct bin_info *bin, uint64_t addr,
b5a8598f
AB
1276 struct source_location **src_loc)
1277{
1278 struct bt_dwarf_cu *cu = NULL;
1279 struct source_location *_src_loc = NULL;
1280
dae52e76 1281 if (!bin || !src_loc) {
b5a8598f
AB
1282 goto error;
1283 }
1284
1285 /* Set DWARF info if it hasn't been accessed yet. */
dae52e76
AB
1286 if (!bin->dwarf_info && !bin->is_elf_only) {
1287 if (bin_info_set_dwarf_info(bin)) {
b5a8598f 1288 /* Failed to set DWARF info. */
dae52e76 1289 bin->is_elf_only = true;
b5a8598f
AB
1290 }
1291 }
1292
dae52e76 1293 if (bin->is_elf_only) {
b5a8598f
AB
1294 /* We cannot lookup source location without DWARF info. */
1295 goto error;
1296 }
1297
dae52e76 1298 if (!bin_info_has_address(bin, addr)) {
b5a8598f
AB
1299 goto error;
1300 }
1301
1302 /*
1303 * Addresses in ELF and DWARF are relative to base address for
1304 * PIC, so make the address argument relative too if needed.
1305 */
dae52e76
AB
1306 if (bin->is_pic) {
1307 addr -= bin->low_addr;
b5a8598f
AB
1308 }
1309
dae52e76 1310 cu = bt_dwarf_cu_create(bin->dwarf_info);
b5a8598f
AB
1311 if (!cu) {
1312 goto error;
1313 }
1314
1315 while (bt_dwarf_cu_next(cu) == 0) {
1316 int ret;
1317
dae52e76 1318 ret = bin_info_lookup_cu_src_loc(cu, addr, &_src_loc);
b5a8598f
AB
1319 if (ret) {
1320 goto error;
1321 }
1322
1323 if (_src_loc) {
1324 break;
1325 }
1326 }
1327
1328 bt_dwarf_cu_destroy(cu);
1329 if (_src_loc) {
1330 *src_loc = _src_loc;
1331 }
1332
1333 return 0;
1334
1335error:
1336 source_location_destroy(_src_loc);
1337 bt_dwarf_cu_destroy(cu);
1338 return -1;
1339}
This page took 0.078471 seconds and 4 git commands to generate.