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