Remove legacy printf_verbose()/printf_debug() and others
[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
139 BT_HIDDEN
140 int bin_info_set_build_id(struct bin_info *bin, uint8_t *build_id,
141 size_t build_id_len)
142 {
143 if (!bin || !build_id) {
144 goto error;
145 }
146
147 bin->build_id = malloc(build_id_len);
148 if (!bin->build_id) {
149 goto error;
150 }
151
152 memcpy(bin->build_id, build_id, build_id_len);
153 bin->build_id_len = build_id_len;
154
155 /*
156 * Reset the is_elf_only flag in case it had been set
157 * previously, because we might find separate debug info using
158 * the new build id information.
159 */
160 bin->is_elf_only = false;
161
162 return 0;
163
164 error:
165
166 return -1;
167 }
168
169 BT_HIDDEN
170 int bin_info_set_debug_link(struct bin_info *bin, const char *filename,
171 uint32_t crc)
172 {
173 if (!bin || !filename) {
174 goto error;
175 }
176
177 bin->dbg_link_filename = strdup(filename);
178 if (!bin->dbg_link_filename) {
179 goto error;
180 }
181
182 bin->dbg_link_crc = crc;
183
184 /*
185 * Reset the is_elf_only flag in case it had been set
186 * previously, because we might find separate debug info using
187 * the new build id information.
188 */
189 bin->is_elf_only = false;
190
191 return 0;
192
193 error:
194
195 return -1;
196 }
197
198 /**
199 * Tries to read DWARF info from the location given by path, and
200 * attach it to the given bin_info instance if it exists.
201 *
202 * @param bin bin_info instance for which to set DWARF info
203 * @param path Presumed location of the DWARF info
204 * @returns 0 on success, negative value on failure
205 */
206 static
207 int bin_info_set_dwarf_info_from_path(struct bin_info *bin, char *path)
208 {
209 int fd = -1, ret = 0;
210 struct bt_dwarf_cu *cu = NULL;
211 Dwarf *dwarf_info = NULL;
212
213 if (!bin || !path) {
214 goto error;
215 }
216
217 fd = open(path, O_RDONLY);
218 if (fd < 0) {
219 fd = -errno;
220 goto error;
221 }
222
223 dwarf_info = dwarf_begin(fd, DWARF_C_READ);
224 if (!dwarf_info) {
225 goto error;
226 }
227
228 /*
229 * Check if the dwarf info has any CU. If not, the
230 * executable's object file contains no DWARF info.
231 */
232 cu = bt_dwarf_cu_create(dwarf_info);
233 if (!cu) {
234 goto error;
235 }
236
237 ret = bt_dwarf_cu_next(cu);
238 if (ret) {
239 goto error;
240 }
241
242 bin->dwarf_fd = fd;
243 bin->dwarf_path = strdup(path);
244 if (!bin->dwarf_path) {
245 goto error;
246 }
247 bin->dwarf_info = dwarf_info;
248 free(cu);
249
250 return 0;
251
252 error:
253 if (fd >= 0) {
254 close(fd);
255 fd = -1;
256 }
257 dwarf_end(dwarf_info);
258 g_free(dwarf_info);
259 free(cu);
260
261 return fd;
262 }
263
264 /**
265 * Try to set the dwarf_info for a given bin_info instance via the
266 * build ID method.
267 *
268 * @param bin bin_info instance for which to retrieve the
269 * DWARF info via build ID
270 * @returns 0 on success (i.e. dwarf_info set), -1 on failure
271 */
272 static
273 int bin_info_set_dwarf_info_build_id(struct bin_info *bin)
274 {
275 int i = 0, ret = 0;
276 char *path = NULL, *build_id_file = NULL;
277 const char *dbg_dir = NULL;
278 size_t build_id_file_len;
279
280 if (!bin || !bin->build_id) {
281 goto error;
282 }
283
284 dbg_dir = bin->debug_info_dir ? : DEFAULT_DEBUG_DIR;
285
286 /* 2 characters per byte printed in hex, +1 for '/' and +1 for '\0' */
287 build_id_file_len = (2 * bin->build_id_len) + 1 +
288 strlen(BUILD_ID_SUFFIX) + 1;
289 build_id_file = malloc(build_id_file_len);
290 if (!build_id_file) {
291 goto error;
292 }
293
294 snprintf(build_id_file, 4, "%02x/", bin->build_id[0]);
295 for (i = 1; i < bin->build_id_len; ++i) {
296 int path_idx = 3 + 2 * (i - 1);
297
298 snprintf(&build_id_file[path_idx], 3, "%02x", bin->build_id[i]);
299 }
300 strcat(build_id_file, BUILD_ID_SUFFIX);
301
302 path = g_build_path("/", dbg_dir, BUILD_ID_SUBDIR, build_id_file, NULL);
303 if (!path) {
304 goto error;
305 }
306
307 ret = bin_info_set_dwarf_info_from_path(bin, path);
308 if (ret) {
309 goto error;
310 }
311
312 goto end;
313
314 error:
315 ret = -1;
316 end:
317 free(build_id_file);
318 free(path);
319
320 return ret;
321 }
322
323 /**
324 * Tests whether the file located at path exists and has the expected
325 * checksum.
326 *
327 * This predicate is used when looking up separate debug info via the
328 * GNU debuglink method. The expected crc can be found .gnu_debuglink
329 * section in the original ELF file, along with the filename for the
330 * file containing the debug info.
331 *
332 * @param path Full path at which to look for the debug file
333 * @param crc Expected checksum for the debug file
334 * @returns 1 if the file exists and has the correct checksum,
335 * 0 otherwise
336 */
337 static
338 int is_valid_debug_file(char *path, uint32_t crc)
339 {
340 int ret = 0, fd = -1;
341 uint32_t _crc = 0;
342
343 if (!path) {
344 goto end_noclose;
345 }
346
347 fd = open(path, O_RDONLY);
348 if (fd < 0) {
349 goto end_noclose;
350 }
351
352 ret = crc32(fd, &_crc);
353 if (ret) {
354 ret = 0;
355 goto end;
356 }
357
358 ret = (crc == _crc);
359
360 end:
361 close(fd);
362 end_noclose:
363 return ret;
364 }
365
366 /**
367 * Try to set the dwarf_info for a given bin_info instance via the
368 * build ID method.
369 *
370 * @param bin bin_info instance for which to retrieve the
371 * DWARF info via debug link
372 * @returns 0 on success (i.e. dwarf_info set), -1 on failure
373 */
374 static
375 int bin_info_set_dwarf_info_debug_link(struct bin_info *bin)
376 {
377 int ret = 0;
378 const char *dbg_dir = NULL;
379 char *dir_name = NULL, *bin_dir = NULL, *path = NULL;
380 size_t max_path_len = 0;
381
382 if (!bin || !bin->dbg_link_filename) {
383 goto error;
384 }
385
386 dbg_dir = bin->debug_info_dir ? : DEFAULT_DEBUG_DIR;
387
388 dir_name = dirname(bin->elf_path);
389 if (!dir_name) {
390 goto error;
391 }
392
393 /* bin_dir is just dir_name with a trailing slash */
394 bin_dir = malloc(strlen(dir_name) + 2);
395 if (!bin_dir) {
396 goto error;
397 }
398
399 strcpy(bin_dir, dir_name);
400 strcat(bin_dir, "/");
401
402 max_path_len = strlen(dbg_dir) + strlen(bin_dir) +
403 strlen(DEBUG_SUBDIR) + strlen(bin->dbg_link_filename)
404 + 1;
405 path = malloc(max_path_len);
406 if (!path) {
407 goto error;
408 }
409
410 /* First look in the executable's dir */
411 strcpy(path, bin_dir);
412 strcat(path, bin->dbg_link_filename);
413
414 if (is_valid_debug_file(path, bin->dbg_link_crc)) {
415 goto found;
416 }
417
418 /* If not found, look in .debug subdir */
419 strcpy(path, bin_dir);
420 strcat(path, DEBUG_SUBDIR);
421 strcat(path, bin->dbg_link_filename);
422
423 if (is_valid_debug_file(path, bin->dbg_link_crc)) {
424 goto found;
425 }
426
427 /* Lastly, look under the global debug directory */
428 strcpy(path, dbg_dir);
429 strcat(path, bin_dir);
430 strcat(path, bin->dbg_link_filename);
431
432 if (is_valid_debug_file(path, bin->dbg_link_crc)) {
433 goto found;
434 }
435
436 error:
437 ret = -1;
438 end:
439 free(path);
440 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.071826 seconds and 5 git commands to generate.