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