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