Fix: flt.lttng-utils.debug-info: cannot find addr past the first CU
[babeltrace.git] / plugins / lttng-utils / debug-info / bin-info.c
index 023902c77b900f2248be6093ddb2601293e198cd..c0546c861df8a4288f489bb089d860800fbdc7c5 100644 (file)
@@ -42,6 +42,8 @@
 
 #include <glib.h>
 
+#include <babeltrace/common-internal.h>
+
 #include "bin-info.h"
 #include "crc32.h"
 #include "dwarf.h"
@@ -88,8 +90,7 @@ struct bin_info *bin_info_create(struct bt_fd_cache *fdc, const char *path,
        }
 
        if (target_prefix) {
-               bin->elf_path = g_build_path("/", target_prefix,
-                                               path, NULL);
+               bin->elf_path = g_build_filename(target_prefix, path, NULL);
        } else {
                bin->elf_path = g_strdup(path);
        }
@@ -144,6 +145,41 @@ void bin_info_destroy(struct bin_info *bin)
        g_free(bin);
 }
 
+static
+int bin_info_set_endianness(struct bin_info *bin)
+{
+       int ret, fd;
+       uint8_t e_ident[EI_NIDENT];
+
+       fd = bt_fd_cache_handle_get_fd(bin->elf_handle);
+
+       /*
+        * Read the identification fields of the elf file.
+        */
+       if (lseek(fd, 0, SEEK_SET) < 0) {
+               BT_LOGE("Error seeking the beginning of ELF file: %s",
+                       strerror(errno));
+               ret = -1;
+               goto error;
+       }
+
+       ret = bt_common_read(fd, e_ident, EI_NIDENT);
+       if (ret < EI_NIDENT) {
+               BT_LOGE_STR("Error reading the ELF identification fields");
+               ret = -1;
+               goto error;
+       }
+
+       /*
+        * Set the endianness.
+        */
+        bin->endianness = e_ident[EI_DATA];
+        ret = 0;
+
+error:
+       return ret;
+}
+
 /**
  * Initialize the ELF file for a given executable.
  *
@@ -155,6 +191,7 @@ int bin_info_set_elf_file(struct bin_info *bin)
 {
        struct bt_fd_cache_handle *elf_handle = NULL;
        Elf *elf_file = NULL;
+       int ret;
 
        if (!bin) {
                goto error;
@@ -165,21 +202,27 @@ int bin_info_set_elf_file(struct bin_info *bin)
                BT_LOGD("Failed to open %s", bin->elf_path);
                goto error;
        }
+       bin->elf_handle = elf_handle;
+
+       ret = bin_info_set_endianness(bin);
+       if (ret) {
+               goto error;
+       }
 
-       elf_file = elf_begin(bt_fd_cache_handle_get_fd(elf_handle),
+       elf_file = elf_begin(bt_fd_cache_handle_get_fd(bin->elf_handle),
                ELF_C_READ, NULL);
        if (!elf_file) {
                BT_LOGE("elf_begin failed: %s", elf_errmsg(-1));
                goto error;
        }
 
+       bin->elf_file = elf_file;
+
        if (elf_kind(elf_file) != ELF_K_ELF) {
                BT_LOGE("Error: %s is not an ELF object", bin->elf_path);
                goto error;
        }
 
-       bin->elf_handle = elf_handle;
-       bin->elf_file = elf_file;
        return 0;
 
 error:
@@ -208,8 +251,18 @@ int is_build_id_note_section(uint8_t *buf)
         * - Note type
         */
        name_sz = (uint32_t) *buf;
+
+       /*
+        * Check the note name length. The name_sz field includes the
+        * terminating null byte.
+        */
+       if (name_sz != sizeof(BUILD_ID_NOTE_NAME)) {
+               goto invalid;
+       }
+
        buf += sizeof(name_sz);
 
+       /* Ignore the note description size. */
        buf += sizeof(desc_sz);
 
        note_type = (uint32_t) *buf;
@@ -295,8 +348,7 @@ int is_build_id_matching(struct bin_info *bin)
 {
        int ret, is_build_id, is_matching = 0;
        Elf_Scn *curr_section = NULL, *next_section = NULL;
-       Elf_Data *note_data = NULL;
-       GElf_Shdr *curr_section_hdr = NULL;
+       GElf_Shdr curr_section_hdr;
 
        if (!bin->build_id) {
                goto error;
@@ -311,38 +363,51 @@ int is_build_id_matching(struct bin_info *bin)
                }
        }
 
-       curr_section_hdr = g_new0(GElf_Shdr, 1);
-       if (!curr_section_hdr) {
-               goto error;
-       }
-
        next_section = elf_nextscn(bin->elf_file, curr_section);
        if (!next_section) {
                goto error;
        }
 
        while (next_section) {
+               Elf_Data *file_note_data = NULL;
+               Elf_Data native_note_data;
+
                curr_section = next_section;
                next_section = elf_nextscn(bin->elf_file, curr_section);
 
-               curr_section_hdr = gelf_getshdr(curr_section, curr_section_hdr);
-
-               if (!curr_section_hdr) {
+               if (!gelf_getshdr(curr_section, &curr_section_hdr)) {
                        goto error;
                }
 
-               if (curr_section_hdr->sh_type != SHT_NOTE) {
+               if (curr_section_hdr.sh_type != SHT_NOTE) {
                        continue;
                }
 
-               note_data = elf_getdata(curr_section, NULL);
-               if (!note_data) {
+               file_note_data = elf_getdata(curr_section, NULL);
+               if (!file_note_data) {
                        goto error;
                }
 
+               /*
+                * Prepare the destination buffer to receive the natively
+                * ordered note. The `d_buf`, `d_size`, and `d_version` fields
+                * of the destination structure must be set before invoking the
+                * `gelf_xlatetom()` function.
+                */
+               native_note_data.d_buf = g_new0(uint8_t, file_note_data->d_size);
+               BT_ASSERT(native_note_data.d_buf);
+
+               native_note_data.d_size = file_note_data->d_size;
+               native_note_data.d_version = file_note_data->d_version;
+
+               /* Translate the note data buffer to the host endianness. */
+               gelf_xlatetom(bin->elf_file, &native_note_data, file_note_data,
+                       bin->endianness);
+
                /* Check if the note is of the build-id type. */
-               is_build_id = is_build_id_note_section(note_data->d_buf);
+               is_build_id = is_build_id_note_section(native_note_data.d_buf);
                if (!is_build_id) {
+                       g_free(native_note_data.d_buf);
                        continue;
                }
 
@@ -350,14 +415,15 @@ int is_build_id_matching(struct bin_info *bin)
                 * Compare the build id of the on-disk file and
                 * the build id recorded in the trace.
                 */
-               is_matching = is_build_id_note_section_matching(note_data->d_buf,
-                               bin->build_id, bin->build_id_len);
+               is_matching = is_build_id_note_section_matching(
+                       native_note_data.d_buf, bin->build_id,
+                       bin->build_id_len);
+               g_free(native_note_data.d_buf);
                if (!is_matching) {
                        break;
                }
        }
 error:
-       g_free(curr_section_hdr);
        return is_matching;
 }
 
@@ -535,7 +601,7 @@ int bin_info_set_dwarf_info_build_id(struct bin_info *bin)
        g_snprintf(&build_id_file[build_id_char_len], build_id_suffix_char_len,
                BUILD_ID_SUFFIX);
 
-       path = g_build_path("/", dbg_dir, BUILD_ID_SUBDIR, build_id_file, NULL);
+       path = g_build_filename(dbg_dir, BUILD_ID_SUBDIR, build_id_file, NULL);
        if (!path) {
                goto error;
        }
@@ -652,6 +718,7 @@ int bin_info_set_dwarf_info_debug_link(struct bin_info *bin)
 error:
        ret = -1;
 end:
+       g_free(bin_dir);
        g_free(dir_name);
        g_free(path);
 
@@ -740,7 +807,6 @@ int bin_info_append_offset_str(const char *base_str, uint64_t low_addr,
        uint64_t offset;
        char *_result = NULL;
 
-
        if (!base_str || !result) {
                goto error;
        }
@@ -1369,7 +1435,9 @@ error:
  * @param cu           bt_dwarf_cu instance in which to look for the address
  * @param addr         The address for which to look for
  * @param src_loc      Out parameter, the source location (filename and
- *                     line number) for the address
+ *                     line number) for the address. Set only if the address
+ *                     is found and resolved successfully
+ *
  * @returns            0 on success, -1 on failure
  */
 static
@@ -1394,7 +1462,8 @@ int bin_info_lookup_cu_src_loc_no_inl(struct bt_dwarf_cu *cu, uint64_t addr,
 
        line = dwarf_getsrc_die(die->dwarf_die, addr);
        if (!line) {
-               goto error;
+               /* This is not an error. The caller needs to keep looking. */
+               goto end;
        }
 
        ret = dwarf_lineaddr(line, &line_addr);
@@ -1428,6 +1497,7 @@ int bin_info_lookup_cu_src_loc_no_inl(struct bt_dwarf_cu *cu, uint64_t addr,
                *src_loc = _src_loc;
        }
 
+end:
        return 0;
 
 error:
This page took 0.030359 seconds and 4 git commands to generate.