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