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