Fix: flt.lttng-utils.debug-info: build id note section non-native byte order
[babeltrace.git] / plugins / lttng-utils / debug-info / 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
f4f9e43b
PP
29#define BT_LOG_TAG "PLUGIN-CTF-LTTNG-UTILS-DEBUG-INFO-FLT-BIN-INFO"
30#include "logging.h"
31
8d7183bd
FD
32#include <dwarf.h>
33#include <errno.h>
c40a57e5 34#include <fcntl.h>
8d7183bd 35#include <inttypes.h>
c40a57e5 36#include <libgen.h>
8d7183bd 37#include <math.h>
c40a57e5 38#include <stdio.h>
c40a57e5
AB
39#include <stdlib.h>
40#include <string.h>
41#include <unistd.h>
8d7183bd 42
c40a57e5 43#include <glib.h>
8d7183bd 44
8d48beb9
FD
45#include <babeltrace/common-internal.h>
46
4f45f9bb
JD
47#include "bin-info.h"
48#include "crc32.h"
8d7183bd 49#include "dwarf.h"
4f45f9bb 50#include "utils.h"
c40a57e5
AB
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
58f6d595 58#define BUILD_ID_NOTE_NAME "GNU"
c40a57e5
AB
59
60BT_HIDDEN
d5ddf820 61int bin_info_init(void)
c40a57e5
AB
62{
63 int ret = 0;
64
65 if (elf_version(EV_CURRENT) == EV_NONE) {
f4f9e43b
PP
66 BT_LOGD("ELF library initialization failed: %s.",
67 elf_errmsg(-1));
c40a57e5
AB
68 ret = -1;
69 }
70
71 return ret;
72}
73
74BT_HIDDEN
8d7183bd
FD
75struct 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)
c40a57e5 78{
d5ddf820 79 struct bin_info *bin = NULL;
c40a57e5 80
8d7183bd
FD
81 BT_ASSERT(fdc);
82
c40a57e5
AB
83 if (!path) {
84 goto error;
85 }
86
d5ddf820
AB
87 bin = g_new0(struct bin_info, 1);
88 if (!bin) {
c40a57e5
AB
89 goto error;
90 }
91
9d325e17
PP
92 if (target_prefix) {
93 bin->elf_path = g_build_path("/", target_prefix,
5cde0dc1
AB
94 path, NULL);
95 } else {
58f6d595 96 bin->elf_path = g_strdup(path);
5cde0dc1
AB
97 }
98
d5ddf820 99 if (!bin->elf_path) {
c40a57e5
AB
100 goto error;
101 }
102
9d325e17 103 if (debug_info_dir) {
2638950d 104 bin->debug_info_dir = g_strdup(debug_info_dir);
9d325e17
PP
105 if (!bin->debug_info_dir) {
106 goto error;
107 }
108 }
109
d5ddf820
AB
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;
58f6d595
FD
114 bin->build_id = NULL;
115 bin->build_id_len = 0;
116 bin->file_build_id_matches = false;
8d7183bd 117 bin->fd_cache = fdc;
c40a57e5 118
d5ddf820 119 return bin;
c40a57e5
AB
120
121error:
d5ddf820 122 bin_info_destroy(bin);
c40a57e5
AB
123 return NULL;
124}
125
126BT_HIDDEN
d5ddf820 127void bin_info_destroy(struct bin_info *bin)
c40a57e5 128{
d5ddf820 129 if (!bin) {
c40a57e5
AB
130 return;
131 }
132
d5ddf820 133 dwarf_end(bin->dwarf_info);
c40a57e5 134
2638950d
FD
135 g_free(bin->debug_info_dir);
136 g_free(bin->elf_path);
137 g_free(bin->dwarf_path);
4f45f9bb 138 g_free(bin->build_id);
2638950d 139 g_free(bin->dbg_link_filename);
c40a57e5 140
d5ddf820 141 elf_end(bin->elf_file);
c40a57e5 142
8d7183bd
FD
143 bt_fd_cache_put_handle(bin->fd_cache, bin->elf_handle);
144 bt_fd_cache_put_handle(bin->fd_cache, bin->dwarf_handle);
c40a57e5 145
d5ddf820 146 g_free(bin);
c40a57e5
AB
147}
148
8d48beb9
FD
149static
150int 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
180error:
181 return ret;
182}
183
58f6d595
FD
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 */
190static
191int bin_info_set_elf_file(struct bin_info *bin)
192{
8d7183bd 193 struct bt_fd_cache_handle *elf_handle = NULL;
58f6d595 194 Elf *elf_file = NULL;
8d48beb9 195 int ret;
58f6d595
FD
196
197 if (!bin) {
198 goto error;
199 }
200
8d7183bd
FD
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);
58f6d595
FD
204 goto error;
205 }
8d48beb9
FD
206 bin->elf_handle = elf_handle;
207
208 ret = bin_info_set_endianness(bin);
209 if (ret) {
210 goto error;
211 }
58f6d595 212
8d48beb9 213 elf_file = elf_begin(bt_fd_cache_handle_get_fd(bin->elf_handle),
8d7183bd 214 ELF_C_READ, NULL);
58f6d595 215 if (!elf_file) {
8d7183bd 216 BT_LOGE("elf_begin failed: %s", elf_errmsg(-1));
58f6d595
FD
217 goto error;
218 }
219
8d48beb9
FD
220 bin->elf_file = elf_file;
221
58f6d595 222 if (elf_kind(elf_file) != ELF_K_ELF) {
8d7183bd 223 BT_LOGE("Error: %s is not an ELF object", bin->elf_path);
58f6d595
FD
224 goto error;
225 }
226
58f6d595
FD
227 return 0;
228
229error:
8d7183bd 230 bt_fd_cache_put_handle(bin->fd_cache, elf_handle);
58f6d595 231 elf_end(elf_file);
8d7183bd 232 return -1;
58f6d595
FD
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 */
243static
244int 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
274invalid:
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 */
288static
289int 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 }
321end:
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 */
337static
338int 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;
58f6d595
FD
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) {
8d48beb9
FD
368 Elf_Data *file_note_data = NULL;
369 Elf_Data native_note_data;
370
58f6d595
FD
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
8d48beb9
FD
384 file_note_data = elf_getdata(curr_section, NULL);
385 if (!file_note_data) {
58f6d595
FD
386 goto error;
387 }
388
8d48beb9
FD
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
58f6d595 405 /* Check if the note is of the build-id type. */
8d48beb9 406 is_build_id = is_build_id_note_section(native_note_data.d_buf);
58f6d595 407 if (!is_build_id) {
8d48beb9 408 g_free(native_note_data.d_buf);
58f6d595
FD
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 */
8d48beb9
FD
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);
58f6d595
FD
420 if (!is_matching) {
421 break;
422 }
423 }
424error:
425 g_free(curr_section_hdr);
426 return is_matching;
427}
428
c40a57e5 429BT_HIDDEN
d5ddf820 430int bin_info_set_build_id(struct bin_info *bin, uint8_t *build_id,
c40a57e5
AB
431 size_t build_id_len)
432{
d5ddf820 433 if (!bin || !build_id) {
c40a57e5
AB
434 goto error;
435 }
436
58f6d595
FD
437 /* Set the build id. */
438 bin->build_id = g_new0(uint8_t, build_id_len);
d5ddf820 439 if (!bin->build_id) {
c40a57e5
AB
440 goto error;
441 }
442
d5ddf820
AB
443 memcpy(bin->build_id, build_id, build_id_len);
444 bin->build_id_len = build_id_len;
c40a57e5 445
58f6d595
FD
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
c40a57e5
AB
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 */
d5ddf820 462 bin->is_elf_only = false;
c40a57e5
AB
463
464 return 0;
465
466error:
c40a57e5
AB
467 return -1;
468}
469
470BT_HIDDEN
4f45f9bb
JD
471int bin_info_set_debug_link(struct bin_info *bin, const char *filename,
472 uint32_t crc)
c40a57e5 473{
d5ddf820 474 if (!bin || !filename) {
c40a57e5
AB
475 goto error;
476 }
477
2638950d 478 bin->dbg_link_filename = g_strdup(filename);
d5ddf820 479 if (!bin->dbg_link_filename) {
c40a57e5
AB
480 goto error;
481 }
482
d5ddf820 483 bin->dbg_link_crc = crc;
c40a57e5
AB
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 */
d5ddf820 490 bin->is_elf_only = false;
c40a57e5
AB
491
492 return 0;
493
494error:
495
496 return -1;
497}
498
499/**
500 * Tries to read DWARF info from the location given by path, and
d5ddf820 501 * attach it to the given bin_info instance if it exists.
c40a57e5 502 *
d5ddf820 503 * @param bin bin_info instance for which to set DWARF info
c40a57e5 504 * @param path Presumed location of the DWARF info
545e1e92 505 * @returns 0 on success, negative value on failure
c40a57e5
AB
506 */
507static
d5ddf820 508int bin_info_set_dwarf_info_from_path(struct bin_info *bin, char *path)
c40a57e5 509{
8d7183bd
FD
510 int ret = 0;
511 struct bt_fd_cache_handle *dwarf_handle = NULL;
c40a57e5
AB
512 struct bt_dwarf_cu *cu = NULL;
513 Dwarf *dwarf_info = NULL;
514
d5ddf820 515 if (!bin || !path) {
c40a57e5
AB
516 goto error;
517 }
518
8d7183bd
FD
519 dwarf_handle = bt_fd_cache_get_handle(bin->fd_cache, path);
520 if (!dwarf_handle) {
c40a57e5
AB
521 goto error;
522 }
523
8d7183bd
FD
524 dwarf_info = dwarf_begin(bt_fd_cache_handle_get_fd(dwarf_handle),
525 DWARF_C_READ);
c40a57e5
AB
526 if (!dwarf_info) {
527 goto error;
528 }
529
530 /*
d5ddf820
AB
531 * Check if the dwarf info has any CU. If not, the
532 * executable's object file contains no DWARF info.
c40a57e5
AB
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
8d7183bd 544 bin->dwarf_handle = dwarf_handle;
2638950d 545 bin->dwarf_path = g_strdup(path);
d5ddf820 546 if (!bin->dwarf_path) {
c40a57e5
AB
547 goto error;
548 }
d5ddf820 549 bin->dwarf_info = dwarf_info;
c40a57e5
AB
550 free(cu);
551
552 return 0;
553
554error:
8d7183bd 555 bt_fd_cache_put_handle(bin->fd_cache, dwarf_handle);
c40a57e5
AB
556 dwarf_end(dwarf_info);
557 g_free(dwarf_info);
558 free(cu);
559
8d7183bd 560 return -1;
c40a57e5
AB
561}
562
563/**
d5ddf820 564 * Try to set the dwarf_info for a given bin_info instance via the
c40a57e5
AB
565 * build ID method.
566 *
d5ddf820 567 * @param bin bin_info instance for which to retrieve the
c40a57e5
AB
568 * DWARF info via build ID
569 * @returns 0 on success (i.e. dwarf_info set), -1 on failure
570 */
571static
d5ddf820 572int bin_info_set_dwarf_info_build_id(struct bin_info *bin)
c40a57e5 573{
f06ce5e5 574 int i = 0, ret = 0;
c40a57e5
AB
575 char *path = NULL, *build_id_file = NULL;
576 const char *dbg_dir = NULL;
7d18de7b 577 size_t build_id_char_len, build_id_suffix_char_len, build_id_file_len;
c40a57e5 578
d5ddf820 579 if (!bin || !bin->build_id) {
c40a57e5
AB
580 goto error;
581 }
582
2638950d 583 dbg_dir = bin->debug_info_dir ? bin->debug_info_dir : DEFAULT_DEBUG_DIR;
c40a57e5 584
b3599eb3 585 /* 2 characters per byte printed in hex, +1 for '/' and +1 for '\0' */
7d18de7b
FD
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;
2638950d 589 build_id_file = g_new0(gchar, build_id_file_len);
c40a57e5
AB
590 if (!build_id_file) {
591 goto error;
592 }
593
2638950d 594 g_snprintf(build_id_file, 4, "%02x/", bin->build_id[0]);
d5ddf820 595 for (i = 1; i < bin->build_id_len; ++i) {
c40a57e5
AB
596 int path_idx = 3 + 2 * (i - 1);
597
2638950d 598 g_snprintf(&build_id_file[path_idx], 3, "%02x", bin->build_id[i]);
c40a57e5 599 }
7d18de7b
FD
600 g_snprintf(&build_id_file[build_id_char_len], build_id_suffix_char_len,
601 BUILD_ID_SUFFIX);
c40a57e5 602
f06ce5e5 603 path = g_build_path("/", dbg_dir, BUILD_ID_SUBDIR, build_id_file, NULL);
c40a57e5
AB
604 if (!path) {
605 goto error;
606 }
607
d5ddf820 608 ret = bin_info_set_dwarf_info_from_path(bin, path);
c40a57e5
AB
609 if (ret) {
610 goto error;
611 }
612
613 goto end;
614
615error:
616 ret = -1;
617end:
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 */
638static
8d7183bd 639int is_valid_debug_file(struct bin_info *bin, char *path, uint32_t crc)
c40a57e5 640{
8d7183bd
FD
641 int ret = 0;
642 struct bt_fd_cache_handle *debug_handle = NULL;
c40a57e5
AB
643 uint32_t _crc = 0;
644
645 if (!path) {
8d7183bd 646 goto end;
c40a57e5
AB
647 }
648
8d7183bd
FD
649 debug_handle = bt_fd_cache_get_handle(bin->fd_cache, path);
650 if (!debug_handle) {
651 goto end;
c40a57e5
AB
652 }
653
8d7183bd 654 ret = crc32(bt_fd_cache_handle_get_fd(debug_handle), &_crc);
c40a57e5
AB
655 if (ret) {
656 ret = 0;
657 goto end;
658 }
659
660 ret = (crc == _crc);
661
662end:
8d7183bd 663 bt_fd_cache_put_handle(bin->fd_cache, debug_handle);
c40a57e5
AB
664 return ret;
665}
666
667/**
d5ddf820 668 * Try to set the dwarf_info for a given bin_info instance via the
58f6d595 669 * debug-link method.
c40a57e5 670 *
d5ddf820 671 * @param bin bin_info instance for which to retrieve the
c40a57e5
AB
672 * DWARF info via debug link
673 * @returns 0 on success (i.e. dwarf_info set), -1 on failure
674 */
675static
d5ddf820 676int bin_info_set_dwarf_info_debug_link(struct bin_info *bin)
c40a57e5
AB
677{
678 int ret = 0;
2638950d
FD
679 const gchar *dbg_dir = NULL;
680 gchar *bin_dir = NULL, *dir_name = NULL, *path = NULL;
c40a57e5 681
d5ddf820 682 if (!bin || !bin->dbg_link_filename) {
c40a57e5
AB
683 goto error;
684 }
685
2638950d 686 dbg_dir = bin->debug_info_dir ? bin->debug_info_dir : DEFAULT_DEBUG_DIR;
d30bb635 687 dir_name = g_path_get_dirname(bin->elf_path);
c40a57e5
AB
688 if (!dir_name) {
689 goto error;
690 }
691
2638950d 692 bin_dir = g_strconcat(dir_name, "/", NULL);
c40a57e5 693
d5ddf820 694 /* First look in the executable's dir */
2638950d 695 path = g_strconcat(bin_dir, bin->dbg_link_filename, NULL);
c40a57e5 696
8d7183bd 697 if (is_valid_debug_file(bin, path, bin->dbg_link_crc)) {
c40a57e5
AB
698 goto found;
699 }
700
701 /* If not found, look in .debug subdir */
2638950d
FD
702 g_free(path);
703 path = g_strconcat(bin_dir, DEBUG_SUBDIR, bin->dbg_link_filename, NULL);
c40a57e5 704
8d7183bd 705 if (is_valid_debug_file(bin, path, bin->dbg_link_crc)) {
c40a57e5
AB
706 goto found;
707 }
708
709 /* Lastly, look under the global debug directory */
2638950d 710 g_free(path);
c40a57e5 711
2638950d 712 path = g_strconcat(dbg_dir, bin_dir, bin->dbg_link_filename, NULL);
8d7183bd 713 if (is_valid_debug_file(bin, path, bin->dbg_link_crc)) {
c40a57e5
AB
714 goto found;
715 }
716
717error:
718 ret = -1;
719end:
9184eefe 720 g_free(bin_dir);
d30bb635
FD
721 g_free(dir_name);
722 g_free(path);
c40a57e5
AB
723
724 return ret;
725
726found:
d5ddf820 727 ret = bin_info_set_dwarf_info_from_path(bin, path);
c40a57e5
AB
728 if (ret) {
729 goto error;
730 }
731
732 goto end;
733}
734
735/**
736 * Initialize the DWARF info for a given executable.
737 *
d5ddf820 738 * @param bin bin_info instance
545e1e92 739 * @returns 0 on success, negative value on failure
c40a57e5
AB
740 */
741static
d5ddf820 742int bin_info_set_dwarf_info(struct bin_info *bin)
c40a57e5
AB
743{
744 int ret = 0;
745
d5ddf820 746 if (!bin) {
545e1e92
JG
747 ret = -1;
748 goto end;
c40a57e5
AB
749 }
750
751 /* First try to set the DWARF info from the ELF file */
d5ddf820 752 ret = bin_info_set_dwarf_info_from_path(bin, bin->elf_path);
c40a57e5
AB
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 */
d5ddf820 761 ret = bin_info_set_dwarf_info_build_id(bin);
c40a57e5
AB
762 if (!ret) {
763 goto end;
764 }
765
d5ddf820 766 ret = bin_info_set_dwarf_info_debug_link(bin);
c40a57e5
AB
767 if (!ret) {
768 goto end;
769 }
770
c40a57e5
AB
771end:
772 return ret;
773}
774
775BT_HIDDEN
776void 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}
d6d3f4e8 785
d2ac1099
AB
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 */
802static
d5ddf820 803int bin_info_append_offset_str(const char *base_str, uint64_t low_addr,
d2ac1099
AB
804 uint64_t high_addr, char **result)
805{
d2ac1099
AB
806 uint64_t offset;
807 char *_result = NULL;
2638950d 808
d2ac1099
AB
809 if (!base_str || !result) {
810 goto error;
811 }
812
813 offset = high_addr - low_addr;
814
2638950d 815 _result = g_strdup_printf("%s+%#0" PRIx64, base_str, offset);
d2ac1099
AB
816 if (!_result) {
817 goto error;
818 }
d2ac1099
AB
819 *result = _result;
820
821 return 0;
822
823error:
824 free(_result);
825 return -1;
826}
c40a57e5
AB
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 */
846static
d5ddf820 847int bin_info_get_nearest_symbol_from_section(Elf_Scn *scn, uint64_t addr,
c40a57e5
AB
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
912end:
913 if (nearest_sym) {
914 *sym = nearest_sym;
915 *shdr = _shdr;
916 } else {
917 g_free(_shdr);
918 }
919
920 return 0;
921
922error:
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 *
d5ddf820 939 * @param bin bin_info instance for the executable containing
c40a57e5
AB
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 */
946static
d5ddf820 947int bin_info_lookup_elf_function_name(struct bin_info *bin, uint64_t addr,
c40a57e5
AB
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;
c40a57e5 961
49824faa 962 /* Set ELF file if it hasn't been accessed yet. */
d5ddf820
AB
963 if (!bin->elf_file) {
964 ret = bin_info_set_elf_file(bin);
49824faa
AB
965 if (ret) {
966 /* Failed to set ELF file. */
967 goto error;
968 }
969 }
970
d5ddf820 971 scn = elf_nextscn(bin->elf_file, scn);
c40a57e5
AB
972 if (!scn) {
973 goto error;
974 }
975
976 while (scn && !sym) {
d5ddf820 977 ret = bin_info_get_nearest_symbol_from_section(
c40a57e5
AB
978 scn, addr, &sym, &shdr);
979 if (ret) {
980 goto error;
981 }
982
d5ddf820 983 scn = elf_nextscn(bin->elf_file, scn);
c40a57e5
AB
984 }
985
986 if (sym) {
d5ddf820 987 sym_name = elf_strptr(bin->elf_file, shdr->sh_link,
c40a57e5
AB
988 sym->st_name);
989 if (!sym_name) {
990 goto error;
991 }
992
d5ddf820 993 ret = bin_info_append_offset_str(sym_name, sym->st_value, addr,
d2ac1099
AB
994 func_name);
995 if (ret) {
c40a57e5
AB
996 goto error;
997 }
c40a57e5
AB
998 }
999
1000 g_free(shdr);
1001 g_free(sym);
1002 return 0;
1003
1004error:
1005 g_free(shdr);
1006 g_free(sym);
545e1e92 1007 return ret;
c40a57e5
AB
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 */
1023static
d5ddf820 1024int bin_info_lookup_cu_function_name(struct bt_dwarf_cu *cu, uint64_t addr,
c40a57e5
AB
1025 char **func_name)
1026{
a54aa699
AB
1027 int ret = 0;
1028 bool found = false;
c40a57e5
AB
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) {
d2ac1099
AB
1061 uint64_t low_addr = 0;
1062 char *die_name = NULL;
1063
7935ee7a
AB
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);
c40a57e5 1070 if (ret) {
7d41a84b 1071 free(die_name);
c40a57e5
AB
1072 goto error;
1073 }
1074
d5ddf820 1075 ret = bin_info_append_offset_str(die_name, low_addr, addr,
d2ac1099 1076 func_name);
7d41a84b 1077 free(die_name);
d2ac1099 1078 if (ret) {
7935ee7a
AB
1079 goto error;
1080 }
c40a57e5
AB
1081 }
1082
1083 bt_dwarf_die_destroy(die);
1084 return 0;
1085
1086error:
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 *
d5ddf820 1098 * @param bin bin_info instance for the executable containing
c40a57e5
AB
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 */
1105static
d5ddf820 1106int bin_info_lookup_dwarf_function_name(struct bin_info *bin, uint64_t addr,
c40a57e5
AB
1107 char **func_name)
1108{
1109 int ret = 0;
1110 char *_func_name = NULL;
1111 struct bt_dwarf_cu *cu = NULL;
1112
d5ddf820 1113 if (!bin || !func_name) {
c40a57e5
AB
1114 goto error;
1115 }
1116
d5ddf820 1117 cu = bt_dwarf_cu_create(bin->dwarf_info);
c40a57e5
AB
1118 if (!cu) {
1119 goto error;
1120 }
1121
1122 while (bt_dwarf_cu_next(cu) == 0) {
d5ddf820 1123 ret = bin_info_lookup_cu_function_name(cu, addr, &_func_name);
c40a57e5
AB
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;
93d65223
JG
1135 } else {
1136 goto error;
c40a57e5
AB
1137 }
1138
1139 bt_dwarf_cu_destroy(cu);
1140 return 0;
1141
1142error:
1143 bt_dwarf_cu_destroy(cu);
1144 return -1;
1145}
1146
1147BT_HIDDEN
9d325e17
PP
1148int bin_info_lookup_function_name(struct bin_info *bin,
1149 uint64_t addr, char **func_name)
c40a57e5
AB
1150{
1151 int ret = 0;
1152 char *_func_name = NULL;
1153
d5ddf820 1154 if (!bin || !func_name) {
c40a57e5
AB
1155 goto error;
1156 }
1157
58f6d595
FD
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
c40a57e5 1166 /* Set DWARF info if it hasn't been accessed yet. */
d5ddf820
AB
1167 if (!bin->dwarf_info && !bin->is_elf_only) {
1168 ret = bin_info_set_dwarf_info(bin);
c40a57e5 1169 if (ret) {
8d7183bd
FD
1170 BT_LOGD_STR("Failed to set bin dwarf info, falling "
1171 "back to ELF lookup.");
c40a57e5 1172 /* Failed to set DWARF info, fallback to ELF. */
d5ddf820 1173 bin->is_elf_only = true;
c40a57e5
AB
1174 }
1175 }
1176
d5ddf820 1177 if (!bin_info_has_address(bin, addr)) {
c40a57e5
AB
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 */
d5ddf820
AB
1185 if (bin->is_pic) {
1186 addr -= bin->low_addr;
36ae9941
AB
1187 }
1188
d5ddf820 1189 if (bin->is_elf_only) {
b7022cb5
FD
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 }
c40a57e5 1196 } else {
b7022cb5
FD
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 }
c40a57e5
AB
1203 }
1204
36ae9941
AB
1205 *func_name = _func_name;
1206 return 0;
55cd033d 1207
36ae9941
AB
1208error:
1209 return -1;
1210}
1211
1212BT_HIDDEN
d5ddf820 1213int bin_info_get_bin_loc(struct bin_info *bin, uint64_t addr, char **bin_loc)
36ae9941 1214{
2638950d 1215 gchar *_bin_loc = NULL;
36ae9941 1216
d5ddf820 1217 if (!bin || !bin_loc) {
36ae9941 1218 goto error;
c40a57e5
AB
1219 }
1220
58f6d595
FD
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
d5ddf820
AB
1229 if (bin->is_pic) {
1230 addr -= bin->low_addr;
2638950d 1231 _bin_loc = g_strdup_printf("+%#0" PRIx64, addr);
36ae9941 1232 } else {
2638950d 1233 _bin_loc = g_strdup_printf("@%#0" PRIx64, addr);
36ae9941
AB
1234 }
1235
2638950d 1236 if (!_bin_loc) {
36ae9941
AB
1237 goto error;
1238 }
1239
1240 *bin_loc = _bin_loc;
c40a57e5
AB
1241 return 0;
1242
1243error:
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 *
a54aa699
AB
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 *
c40a57e5
AB
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 *
a54aa699
AB
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
c40a57e5
AB
1271 */
1272static
a54aa699 1273int bin_info_child_die_has_address(struct bt_dwarf_die *die, uint64_t addr, bool *contains)
c40a57e5 1274{
a54aa699
AB
1275 int ret = 0;
1276 bool _contains = false;
c40a57e5
AB
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 {
54bc9710 1288 ret = bt_dwarf_die_contains_addr(die, addr, &_contains);
c40a57e5
AB
1289 if (ret) {
1290 goto error;
1291 }
1292
54bc9710
FD
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);
c40a57e5
AB
1301 if (ret) {
1302 goto error;
1303 }
1304
54bc9710
FD
1305 if (tag == DW_TAG_inlined_subroutine) {
1306 /* Found the tracepoint. */
c40a57e5
AB
1307 goto end;
1308 }
54bc9710
FD
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 }
c40a57e5
AB
1319 }
1320 } while (bt_dwarf_die_next(die) == 0);
1321
1322end:
a54aa699
AB
1323 *contains = _contains;
1324 return 0;
c40a57e5
AB
1325
1326error:
a54aa699 1327 return -1;
c40a57e5
AB
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 */
1341static
d5ddf820 1342int bin_info_lookup_cu_src_loc_inl(struct bt_dwarf_cu *cu, uint64_t addr,
c40a57e5
AB
1343 struct source_location **src_loc)
1344{
a54aa699
AB
1345 int ret = 0;
1346 bool found = false;
c40a57e5
AB
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) {
a54aa699 1368 bool contains = false;
c40a57e5
AB
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 */
a54aa699
AB
1380 ret = bin_info_child_die_has_address(die, addr,
1381 &found);
1382 if(ret) {
1383 goto error;
1384 }
1385
c40a57e5
AB
1386 goto end;
1387 }
1388 }
1389 }
1390
1391end:
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
1419error:
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 */
1440static
d5ddf820 1441int bin_info_lookup_cu_src_loc_no_inl(struct bt_dwarf_cu *cu, uint64_t addr,
c40a57e5
AB
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;
2638950d 1487 _src_loc->filename = g_strdup(filename);
c40a57e5
AB
1488 }
1489
1490 bt_dwarf_die_destroy(die);
1491
1492 if (_src_loc) {
1493 *src_loc = _src_loc;
1494 }
1495
1496 return 0;
1497
1498error:
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 *
d5ddf820 1511 * @param cu bt_dwarf_cu instance for the compile unit which
c40a57e5
AB
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 */
1518static
d5ddf820 1519int bin_info_lookup_cu_src_loc(struct bt_dwarf_cu *cu, uint64_t addr,
c40a57e5
AB
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
d5ddf820 1529 ret = bin_info_lookup_cu_src_loc_inl(cu, addr, &_src_loc);
c40a57e5
AB
1530 if (ret) {
1531 goto error;
1532 }
1533
1534 if (_src_loc) {
1535 goto end;
1536 }
1537
d5ddf820 1538 ret = bin_info_lookup_cu_src_loc_no_inl(cu, addr, &_src_loc);
c40a57e5
AB
1539 if (ret) {
1540 goto error;
1541 }
1542
1543 if (_src_loc) {
1544 goto end;
1545 }
1546
1547end:
1548 if (_src_loc) {
1549 *src_loc = _src_loc;
1550 }
1551
1552 return 0;
1553
1554error:
1555 source_location_destroy(_src_loc);
1556 return -1;
1557}
1558
1559BT_HIDDEN
d5ddf820 1560int bin_info_lookup_source_location(struct bin_info *bin, uint64_t addr,
c40a57e5
AB
1561 struct source_location **src_loc)
1562{
1563 struct bt_dwarf_cu *cu = NULL;
1564 struct source_location *_src_loc = NULL;
1565
d5ddf820 1566 if (!bin || !src_loc) {
c40a57e5
AB
1567 goto error;
1568 }
1569
58f6d595
FD
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
c40a57e5 1578 /* Set DWARF info if it hasn't been accessed yet. */
d5ddf820
AB
1579 if (!bin->dwarf_info && !bin->is_elf_only) {
1580 if (bin_info_set_dwarf_info(bin)) {
c40a57e5 1581 /* Failed to set DWARF info. */
d5ddf820 1582 bin->is_elf_only = true;
c40a57e5
AB
1583 }
1584 }
1585
d5ddf820 1586 if (bin->is_elf_only) {
c40a57e5
AB
1587 /* We cannot lookup source location without DWARF info. */
1588 goto error;
1589 }
1590
d5ddf820 1591 if (!bin_info_has_address(bin, addr)) {
c40a57e5
AB
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 */
d5ddf820
AB
1599 if (bin->is_pic) {
1600 addr -= bin->low_addr;
c40a57e5
AB
1601 }
1602
d5ddf820 1603 cu = bt_dwarf_cu_create(bin->dwarf_info);
c40a57e5
AB
1604 if (!cu) {
1605 goto error;
1606 }
1607
1608 while (bt_dwarf_cu_next(cu) == 0) {
1609 int ret;
1610
d5ddf820 1611 ret = bin_info_lookup_cu_src_loc(cu, addr, &_src_loc);
c40a57e5
AB
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
1628error:
1629 source_location_destroy(_src_loc);
1630 bt_dwarf_cu_destroy(cu);
1631 return -1;
1632}
This page took 0.159723 seconds and 4 git commands to generate.