Python bindings: add has_intersection property to TraceCollection
[babeltrace.git] / lib / bin-info.c
1 /*
2 * bin-info.c
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>
40 #include <babeltrace/bin-info.h>
41 #include <babeltrace/crc32.h>
42 #include <babeltrace/babeltrace-internal.h>
43 #include <babeltrace/utils.h>
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
52 BT_HIDDEN
53 int bin_info_init(void)
54 {
55 int ret = 0;
56
57 if (elf_version(EV_CURRENT) == EV_NONE) {
58 printf_debug("ELF library initialization failed: %s\n",
59 elf_errmsg(-1));
60 ret = -1;
61 }
62
63 return ret;
64 }
65
66 BT_HIDDEN
67 struct bin_info *bin_info_create(const char *path, uint64_t low_addr,
68 uint64_t memsz, bool is_pic)
69 {
70 struct bin_info *bin = NULL;
71
72 if (!path) {
73 goto error;
74 }
75
76 bin = g_new0(struct bin_info, 1);
77 if (!bin) {
78 goto error;
79 }
80
81 if (opt_debug_info_target_prefix) {
82 bin->elf_path = g_build_path("/", opt_debug_info_target_prefix,
83 path, NULL);
84 } else {
85 bin->elf_path = strdup(path);
86 }
87
88 if (!bin->elf_path) {
89 goto error;
90 }
91
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;
96
97 return bin;
98
99 error:
100 bin_info_destroy(bin);
101 return NULL;
102 }
103
104 BT_HIDDEN
105 void bin_info_destroy(struct bin_info *bin)
106 {
107 if (!bin) {
108 return;
109 }
110
111 dwarf_end(bin->dwarf_info);
112
113 free(bin->elf_path);
114 free(bin->dwarf_path);
115 free(bin->build_id);
116 free(bin->dbg_link_filename);
117
118 elf_end(bin->elf_file);
119
120 close(bin->elf_fd);
121 close(bin->dwarf_fd);
122
123 g_free(bin);
124 }
125
126
127 BT_HIDDEN
128 int bin_info_set_build_id(struct bin_info *bin, uint8_t *build_id,
129 size_t build_id_len)
130 {
131 if (!bin || !build_id) {
132 goto error;
133 }
134
135 bin->build_id = malloc(build_id_len);
136 if (!bin->build_id) {
137 goto error;
138 }
139
140 memcpy(bin->build_id, build_id, build_id_len);
141 bin->build_id_len = build_id_len;
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 */
148 bin->is_elf_only = false;
149
150 return 0;
151
152 error:
153
154 return -1;
155 }
156
157 BT_HIDDEN
158 int bin_info_set_debug_link(struct bin_info *bin, char *filename, uint32_t crc)
159 {
160 if (!bin || !filename) {
161 goto error;
162 }
163
164 bin->dbg_link_filename = strdup(filename);
165 if (!bin->dbg_link_filename) {
166 goto error;
167 }
168
169 bin->dbg_link_crc = crc;
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 */
176 bin->is_elf_only = false;
177
178 return 0;
179
180 error:
181
182 return -1;
183 }
184
185 /**
186 * Tries to read DWARF info from the location given by path, and
187 * attach it to the given bin_info instance if it exists.
188 *
189 * @param bin bin_info instance for which to set DWARF info
190 * @param path Presumed location of the DWARF info
191 * @returns 0 on success, -1 on failure
192 */
193 static
194 int bin_info_set_dwarf_info_from_path(struct bin_info *bin, char *path)
195 {
196 int fd = -1, ret = 0;
197 struct bt_dwarf_cu *cu = NULL;
198 Dwarf *dwarf_info = NULL;
199
200 if (!bin || !path) {
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 /*
215 * Check if the dwarf info has any CU. If not, the
216 * executable's object file contains no DWARF info.
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
228 bin->dwarf_fd = fd;
229 bin->dwarf_path = strdup(path);
230 if (!bin->dwarf_path) {
231 goto error;
232 }
233 bin->dwarf_info = dwarf_info;
234 free(cu);
235
236 return 0;
237
238 error:
239 close(fd);
240 dwarf_end(dwarf_info);
241 g_free(dwarf_info);
242 free(cu);
243
244 return -1;
245 }
246
247 /**
248 * Try to set the dwarf_info for a given bin_info instance via the
249 * build ID method.
250 *
251 * @param bin bin_info instance for which to retrieve the
252 * DWARF info via build ID
253 * @returns 0 on success (i.e. dwarf_info set), -1 on failure
254 */
255 static
256 int bin_info_set_dwarf_info_build_id(struct bin_info *bin)
257 {
258 int i = 0, ret = 0;
259 char *path = NULL, *build_id_file = NULL;
260 const char *dbg_dir = NULL;
261 size_t build_id_file_len;
262
263 if (!bin || !bin->build_id) {
264 goto error;
265 }
266
267 dbg_dir = opt_debug_info_dir ? : DEFAULT_DEBUG_DIR;
268
269 /* 2 characters per byte printed in hex, +1 for '/' and +1 for
270 * '\0' */
271 build_id_file_len = (2 * bin->build_id_len) + 1 +
272 strlen(BUILD_ID_SUFFIX) + 1;
273 build_id_file = malloc(build_id_file_len);
274 if (!build_id_file) {
275 goto error;
276 }
277
278 snprintf(build_id_file, 4, "%02x/", bin->build_id[0]);
279 for (i = 1; i < bin->build_id_len; ++i) {
280 int path_idx = 3 + 2 * (i - 1);
281
282 snprintf(&build_id_file[path_idx], 3, "%02x", bin->build_id[i]);
283 }
284 strcat(build_id_file, BUILD_ID_SUFFIX);
285
286 path = g_build_path("/", dbg_dir, BUILD_ID_SUBDIR, build_id_file, NULL);
287 if (!path) {
288 goto error;
289 }
290
291 ret = bin_info_set_dwarf_info_from_path(bin, path);
292 if (ret) {
293 goto error;
294 }
295
296 goto end;
297
298 error:
299 ret = -1;
300 end:
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 */
321 static
322 int 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
344 end:
345 close(fd);
346 return ret;
347 }
348
349 /**
350 * Try to set the dwarf_info for a given bin_info instance via the
351 * build ID method.
352 *
353 * @param bin bin_info instance for which to retrieve the
354 * DWARF info via debug link
355 * @returns 0 on success (i.e. dwarf_info set), -1 on failure
356 */
357 static
358 int bin_info_set_dwarf_info_debug_link(struct bin_info *bin)
359 {
360 int ret = 0;
361 const char *dbg_dir = NULL;
362 char *dir_name = NULL, *bin_dir = NULL, *path = NULL;
363 size_t max_path_len = 0;
364
365 if (!bin || !bin->dbg_link_filename) {
366 goto error;
367 }
368
369 dbg_dir = opt_debug_info_dir ? : DEFAULT_DEBUG_DIR;
370
371 dir_name = dirname(bin->elf_path);
372 if (!dir_name) {
373 goto error;
374 }
375
376 /* bin_dir is just dir_name with a trailing slash */
377 bin_dir = malloc(strlen(dir_name) + 2);
378 if (!bin_dir) {
379 goto error;
380 }
381
382 strcpy(bin_dir, dir_name);
383 strcat(bin_dir, "/");
384
385 max_path_len = strlen(dbg_dir) + strlen(bin_dir) +
386 strlen(DEBUG_SUBDIR) + strlen(bin->dbg_link_filename)
387 + 1;
388 path = malloc(max_path_len);
389 if (!path) {
390 goto error;
391 }
392
393 /* First look in the executable's dir */
394 strcpy(path, bin_dir);
395 strcat(path, bin->dbg_link_filename);
396
397 if (is_valid_debug_file(path, bin->dbg_link_crc)) {
398 goto found;
399 }
400
401 /* If not found, look in .debug subdir */
402 strcpy(path, bin_dir);
403 strcat(path, DEBUG_SUBDIR);
404 strcat(path, bin->dbg_link_filename);
405
406 if (is_valid_debug_file(path, bin->dbg_link_crc)) {
407 goto found;
408 }
409
410 /* Lastly, look under the global debug directory */
411 strcpy(path, dbg_dir);
412 strcat(path, bin_dir);
413 strcat(path, bin->dbg_link_filename);
414
415 if (is_valid_debug_file(path, bin->dbg_link_crc)) {
416 goto found;
417 }
418
419 error:
420 ret = -1;
421 end:
422 free(path);
423 free(bin_dir);
424
425 return ret;
426
427 found:
428 ret = bin_info_set_dwarf_info_from_path(bin, path);
429 if (ret) {
430 goto error;
431 }
432
433 goto end;
434 }
435
436 /**
437 * Initialize the DWARF info for a given executable.
438 *
439 * @param bin bin_info instance
440 * @returns 0 on success, -1 on failure
441 */
442 static
443 int bin_info_set_dwarf_info(struct bin_info *bin)
444 {
445 int ret = 0;
446
447 if (!bin) {
448 goto error;
449 }
450
451 /* First try to set the DWARF info from the ELF file */
452 ret = bin_info_set_dwarf_info_from_path(bin, bin->elf_path);
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 */
461 ret = bin_info_set_dwarf_info_build_id(bin);
462 if (!ret) {
463 goto end;
464 }
465
466 ret = bin_info_set_dwarf_info_debug_link(bin);
467 if (!ret) {
468 goto end;
469 }
470
471 error:
472 ret = -1;
473 end:
474 return ret;
475 }
476
477 /**
478 * Initialize the ELF file for a given executable.
479 *
480 * @param bin bin_info instance
481 * @returns 0 on success, -1 on failure
482 */
483 static
484 int bin_info_set_elf_file(struct bin_info *bin)
485 {
486 int elf_fd;
487 Elf *elf_file = NULL;
488
489 if (!bin) {
490 goto error;
491 }
492
493 elf_fd = open(bin->elf_path, O_RDONLY);
494 if (elf_fd < 0) {
495 printf_verbose("Failed to open %s\n", bin->elf_path);
496 goto error;
497 }
498
499 elf_file = elf_begin(elf_fd, ELF_C_READ, NULL);
500 if (!elf_file) {
501 printf_debug("elf_begin failed: %s\n", elf_errmsg(-1));
502 goto error;
503 }
504
505 if (elf_kind(elf_file) != ELF_K_ELF) {
506 printf_verbose("Error: %s is not an ELF object\n",
507 bin->elf_path);
508 goto error;
509 }
510
511 bin->elf_fd = elf_fd;
512 bin->elf_file = elf_file;
513 return 0;
514
515 error:
516 close(elf_fd);
517 elf_end(elf_file);
518 return -1;
519 }
520
521
522 BT_HIDDEN
523 void 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 }
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 */
548 static
549 int bin_info_append_offset_str(const char *base_str, uint64_t low_addr,
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
578 error:
579 free(_result);
580 return -1;
581 }
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 */
601 static
602 int bin_info_get_nearest_symbol_from_section(Elf_Scn *scn, uint64_t addr,
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
667 end:
668 if (nearest_sym) {
669 *sym = nearest_sym;
670 *shdr = _shdr;
671 } else {
672 g_free(_shdr);
673 }
674
675 return 0;
676
677 error:
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 *
694 * @param bin bin_info instance for the executable containing
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 */
701 static
702 int bin_info_lookup_elf_function_name(struct bin_info *bin, uint64_t addr,
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;
716
717 /* Set ELF file if it hasn't been accessed yet. */
718 if (!bin->elf_file) {
719 ret = bin_info_set_elf_file(bin);
720 if (ret) {
721 /* Failed to set ELF file. */
722 goto error;
723 }
724 }
725
726 scn = elf_nextscn(bin->elf_file, scn);
727 if (!scn) {
728 goto error;
729 }
730
731 while (scn && !sym) {
732 ret = bin_info_get_nearest_symbol_from_section(
733 scn, addr, &sym, &shdr);
734 if (ret) {
735 goto error;
736 }
737
738 scn = elf_nextscn(bin->elf_file, scn);
739 }
740
741 if (sym) {
742 sym_name = elf_strptr(bin->elf_file, shdr->sh_link,
743 sym->st_name);
744 if (!sym_name) {
745 goto error;
746 }
747
748 ret = bin_info_append_offset_str(sym_name, sym->st_value, addr,
749 func_name);
750 if (ret) {
751 goto error;
752 }
753 }
754
755 g_free(shdr);
756 g_free(sym);
757 return 0;
758
759 error:
760 g_free(shdr);
761 g_free(sym);
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 */
778 static
779 int bin_info_lookup_cu_function_name(struct bt_dwarf_cu *cu, uint64_t addr,
780 char **func_name)
781 {
782 int ret = 0;
783 bool found = false;
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) {
816 uint64_t low_addr = 0;
817 char *die_name = NULL;
818
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);
825 if (ret) {
826 goto error;
827 }
828
829 ret = bin_info_append_offset_str(die_name, low_addr, addr,
830 func_name);
831 if (ret) {
832 goto error;
833 }
834 }
835
836 bt_dwarf_die_destroy(die);
837 return 0;
838
839 error:
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 *
851 * @param bin bin_info instance for the executable containing
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 */
858 static
859 int bin_info_lookup_dwarf_function_name(struct bin_info *bin, uint64_t addr,
860 char **func_name)
861 {
862 int ret = 0;
863 char *_func_name = NULL;
864 struct bt_dwarf_cu *cu = NULL;
865
866 if (!bin || !func_name) {
867 goto error;
868 }
869
870 cu = bt_dwarf_cu_create(bin->dwarf_info);
871 if (!cu) {
872 goto error;
873 }
874
875 while (bt_dwarf_cu_next(cu) == 0) {
876 ret = bin_info_lookup_cu_function_name(cu, addr, &_func_name);
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;
888 } else {
889 goto error;
890 }
891
892 bt_dwarf_cu_destroy(cu);
893 return 0;
894
895 error:
896 bt_dwarf_cu_destroy(cu);
897 return -1;
898 }
899
900 BT_HIDDEN
901 int bin_info_lookup_function_name(struct bin_info *bin, uint64_t addr,
902 char **func_name)
903 {
904 int ret = 0;
905 char *_func_name = NULL;
906
907 if (!bin || !func_name) {
908 goto error;
909 }
910
911 /* Set DWARF info if it hasn't been accessed yet. */
912 if (!bin->dwarf_info && !bin->is_elf_only) {
913 ret = bin_info_set_dwarf_info(bin);
914 if (ret) {
915 /* Failed to set DWARF info, fallback to ELF. */
916 bin->is_elf_only = true;
917 }
918 }
919
920 if (!bin_info_has_address(bin, addr)) {
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 */
928 if (bin->is_pic) {
929 addr -= bin->low_addr;
930 }
931
932 if (bin->is_elf_only) {
933 ret = bin_info_lookup_elf_function_name(bin, addr, &_func_name);
934 } else {
935 ret = bin_info_lookup_dwarf_function_name(bin, addr, &_func_name);
936 }
937
938 if (ret || !_func_name) {
939 goto error;
940 }
941
942 *func_name = _func_name;
943 return 0;
944
945 error:
946 return -1;
947 }
948
949 BT_HIDDEN
950 int bin_info_get_bin_loc(struct bin_info *bin, uint64_t addr, char **bin_loc)
951 {
952 int ret = 0;
953 char *_bin_loc = NULL;
954
955 if (!bin || !bin_loc) {
956 goto error;
957 }
958
959 if (bin->is_pic) {
960 addr -= bin->low_addr;
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;
971 return 0;
972
973 error:
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 *
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 *
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 *
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
1001 */
1002 static
1003 int bin_info_child_die_has_address(struct bt_dwarf_die *die, uint64_t addr, bool *contains)
1004 {
1005 int ret = 0;
1006 bool _contains = false;
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) {
1026 ret = bt_dwarf_die_contains_addr(die, addr, &_contains);
1027 if (ret) {
1028 goto error;
1029 }
1030
1031 if (contains) {
1032 goto end;
1033 }
1034 }
1035 } while (bt_dwarf_die_next(die) == 0);
1036
1037 end:
1038 *contains = _contains;
1039 return 0;
1040
1041 error:
1042 return -1;
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 */
1056 static
1057 int bin_info_lookup_cu_src_loc_inl(struct bt_dwarf_cu *cu, uint64_t addr,
1058 struct source_location **src_loc)
1059 {
1060 int ret = 0;
1061 bool found = false;
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) {
1083 bool contains = false;
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 */
1095 ret = bin_info_child_die_has_address(die, addr,
1096 &found);
1097 if(ret) {
1098 goto error;
1099 }
1100
1101 goto end;
1102 }
1103 }
1104 }
1105
1106 end:
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
1134 error:
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 */
1155 static
1156 int bin_info_lookup_cu_src_loc_no_inl(struct bt_dwarf_cu *cu, uint64_t addr,
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
1213 error:
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 *
1226 * @param cu bt_dwarf_cu instance for the compile unit which
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 */
1233 static
1234 int bin_info_lookup_cu_src_loc(struct bt_dwarf_cu *cu, uint64_t addr,
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
1244 ret = bin_info_lookup_cu_src_loc_inl(cu, addr, &_src_loc);
1245 if (ret) {
1246 goto error;
1247 }
1248
1249 if (_src_loc) {
1250 goto end;
1251 }
1252
1253 ret = bin_info_lookup_cu_src_loc_no_inl(cu, addr, &_src_loc);
1254 if (ret) {
1255 goto error;
1256 }
1257
1258 if (_src_loc) {
1259 goto end;
1260 }
1261
1262 end:
1263 if (_src_loc) {
1264 *src_loc = _src_loc;
1265 }
1266
1267 return 0;
1268
1269 error:
1270 source_location_destroy(_src_loc);
1271 return -1;
1272 }
1273
1274 BT_HIDDEN
1275 int bin_info_lookup_source_location(struct bin_info *bin, uint64_t addr,
1276 struct source_location **src_loc)
1277 {
1278 struct bt_dwarf_cu *cu = NULL;
1279 struct source_location *_src_loc = NULL;
1280
1281 if (!bin || !src_loc) {
1282 goto error;
1283 }
1284
1285 /* Set DWARF info if it hasn't been accessed yet. */
1286 if (!bin->dwarf_info && !bin->is_elf_only) {
1287 if (bin_info_set_dwarf_info(bin)) {
1288 /* Failed to set DWARF info. */
1289 bin->is_elf_only = true;
1290 }
1291 }
1292
1293 if (bin->is_elf_only) {
1294 /* We cannot lookup source location without DWARF info. */
1295 goto error;
1296 }
1297
1298 if (!bin_info_has_address(bin, addr)) {
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 */
1306 if (bin->is_pic) {
1307 addr -= bin->low_addr;
1308 }
1309
1310 cu = bt_dwarf_cu_create(bin->dwarf_info);
1311 if (!cu) {
1312 goto error;
1313 }
1314
1315 while (bt_dwarf_cu_next(cu) == 0) {
1316 int ret;
1317
1318 ret = bin_info_lookup_cu_src_loc(cu, addr, &_src_loc);
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
1335 error:
1336 source_location_destroy(_src_loc);
1337 bt_dwarf_cu_destroy(cu);
1338 return -1;
1339 }
This page took 0.05863 seconds and 4 git commands to generate.