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