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