X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=plugins%2Flttng-utils%2Fdebug-info%2Fbin-info.c;h=bad796d225dd7aa43921ca0e49bd3865f857b986;hb=3fadfbc0c91f82c46bd36e6e0657ea93570c9db1;hp=5393cdbaefd54bf5fbab5cabc3bbeccb85c519e8;hpb=af54bd1801ea51b6710a9926ed12b82fc43cc944;p=babeltrace.git diff --git a/plugins/lttng-utils/debug-info/bin-info.c b/plugins/lttng-utils/debug-info/bin-info.c index 5393cdba..bad796d2 100644 --- a/plugins/lttng-utils/debug-info/bin-info.c +++ b/plugins/lttng-utils/debug-info/bin-info.c @@ -42,7 +42,7 @@ #include -#include +#include #include "bin-info.h" #include "crc32.h" @@ -90,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); } @@ -146,41 +145,6 @@ 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. * @@ -192,7 +156,6 @@ 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; @@ -205,11 +168,6 @@ int bin_info_set_elf_file(struct bin_info *bin) } 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(bin->elf_handle), ELF_C_READ, NULL); if (!elf_file) { @@ -233,39 +191,43 @@ error: } /** - * From a note section data buffer, check if it is a build id note. + * From a note section data struct, check if it is a build id note. * - * @param buf Pointer to a note section + * @param note_data Pointer to a note section * * @returns 1 on match, 0 if `buf` does not contain a * valid build id note */ static -int is_build_id_note_section(uint8_t *buf) +int is_build_id_note_section(Elf_Data *note_data) { + size_t name_offset, desc_offset; + GElf_Nhdr note_header; int ret = 0; - uint32_t name_sz, desc_sz, note_type; - /* The note section header has 3 32bit integer for the following: - * - Section name size - * - Description size - * - Note type + /* + * Discard the return value as it contains the size of the note section + * and we don't need it. */ - name_sz = (uint32_t) *buf; - buf += sizeof(name_sz); + (void) gelf_getnote(note_data, 0, ¬e_header, &name_offset, + &desc_offset); - buf += sizeof(desc_sz); - - note_type = (uint32_t) *buf; - buf += sizeof(note_type); + /* + * Check the note name length. The name_sz field includes the + * terminating null byte. + */ + if (note_header.n_namesz != sizeof(BUILD_ID_NOTE_NAME)) { + goto invalid; + } /* Check the note type. */ - if (note_type != NT_GNU_BUILD_ID) { + if (note_header.n_type != NT_GNU_BUILD_ID) { goto invalid; } /* Check the note name. */ - if (memcmp(buf, BUILD_ID_NOTE_NAME, name_sz) != 0) { + if (memcmp(note_data->d_buf + name_offset, BUILD_ID_NOTE_NAME, + note_header.n_namesz) != 0) { goto invalid; } @@ -276,46 +238,38 @@ invalid: } /** - * From a build id note section data buffer, check if the build id it contains + * From a build id note section data struct, check if the build id it contains * is identical to the build id passed as parameter. * - * @param file_build_id_note Pointer to the file build id note section. + * @param note_data Pointer to the file build id note section. * @param build_id Pointer to a build id to compare to. * @param build_id_len length of the build id. * * @returns 1 on match, 0 otherwise. */ static -int is_build_id_note_section_matching(uint8_t *file_build_id_note, +int is_build_id_note_section_matching(Elf_Data *note_data, uint8_t *build_id, size_t build_id_len) { - uint32_t name_sz, desc_sz, note_type; + size_t name_offset, desc_offset; + GElf_Nhdr note_header; if (build_id_len <= 0) { goto end; } - /* The note section header has 3 32bit integer for the following: - * - Section name size - * - Description size - * - Note type - */ - name_sz = (uint32_t) *file_build_id_note; - file_build_id_note += sizeof(name_sz); - file_build_id_note += sizeof(desc_sz); - file_build_id_note += sizeof(note_type); - /* - * Move the pointer pass the name char array. This corresponds to the - * beginning of the description section. The description is the build - * id in the case of a build id note. + * Discard the return value as it contains the size of the note section + * and we don't need it. */ - file_build_id_note += name_sz; + (void) gelf_getnote(note_data, 0, ¬e_header, &name_offset, + &desc_offset); /* * Compare the binary build id with the supplied build id. */ - if (memcmp(build_id, file_build_id_note, build_id_len) == 0) { + if (memcmp(build_id, note_data->d_buf + desc_offset, + build_id_len) == 0) { return 1; } end: @@ -339,7 +293,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; - GElf_Shdr *curr_section_hdr = NULL; + GElf_Shdr curr_section_hdr; if (!bin->build_id) { goto error; @@ -354,58 +308,36 @@ 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; + Elf_Data *note_data = NULL; 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; } - 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. + * elf_getdata() translates the data to native byte order. */ - 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); + note_data = elf_getdata(curr_section, NULL); + if (!note_data) { + goto error; + } /* Check if the note is of the build-id type. */ - is_build_id = is_build_id_note_section(native_note_data.d_buf); + is_build_id = is_build_id_note_section(note_data); if (!is_build_id) { - g_free(native_note_data.d_buf); continue; } @@ -414,15 +346,12 @@ int is_build_id_matching(struct bin_info *bin) * the build id recorded in the trace. */ 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); + note_data, bin->build_id, bin->build_id_len); if (!is_matching) { break; } } error: - g_free(curr_section_hdr); return is_matching; } @@ -572,7 +501,7 @@ static int bin_info_set_dwarf_info_build_id(struct bin_info *bin) { int i = 0, ret = 0; - char *path = NULL, *build_id_file = NULL; + char *path = NULL, *build_id_prefix_dir = NULL, *build_id_file = NULL; const char *dbg_dir = NULL; size_t build_id_char_len, build_id_suffix_char_len, build_id_file_len; @@ -582,25 +511,49 @@ int bin_info_set_dwarf_info_build_id(struct bin_info *bin) dbg_dir = bin->debug_info_dir ? bin->debug_info_dir : DEFAULT_DEBUG_DIR; - /* 2 characters per byte printed in hex, +1 for '/' and +1 for '\0' */ - build_id_char_len = (2 * bin->build_id_len) + 1; + /* + * The prefix dir is the first byte of the build id, represented in + * lowercase hex as two characters per byte, +1 for '\0'. + */ + build_id_prefix_dir = g_new0(gchar, BUILD_ID_PREFIX_DIR_LEN + 1); + if (!build_id_prefix_dir) { + goto error; + } + g_snprintf(build_id_prefix_dir, BUILD_ID_PREFIX_DIR_LEN + 1, "%02x", bin->build_id[0]); + + /* + * The build id file is the remaining bytes of the build id, + * represented in lowercase hex, as two characters per byte. + */ + build_id_char_len = (2 * (bin->build_id_len - 1)); + + /* To which the build id suffix is added, +1 for '\0'. */ build_id_suffix_char_len = strlen(BUILD_ID_SUFFIX) + 1; + + /* + * The resulting filename string is the concatenation of the + * hex build id and the suffix. + */ build_id_file_len = build_id_char_len + build_id_suffix_char_len; build_id_file = g_new0(gchar, build_id_file_len); if (!build_id_file) { goto error; } - g_snprintf(build_id_file, 4, "%02x/", bin->build_id[0]); + /* + * For each byte, starting at offset 1, append two characters + * in lowercase hex. + */ for (i = 1; i < bin->build_id_len; ++i) { - int path_idx = 3 + 2 * (i - 1); + int path_idx = 2 * (i - 1); g_snprintf(&build_id_file[path_idx], 3, "%02x", bin->build_id[i]); } + /* Append the suffix to the generated string, including the '\0'. */ 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_prefix_dir, build_id_file, NULL); if (!path) { goto error; } @@ -615,8 +568,9 @@ int bin_info_set_dwarf_info_build_id(struct bin_info *bin) error: ret = -1; end: - free(build_id_file); - free(path); + g_free(build_id_prefix_dir); + g_free(build_id_file); + g_free(path); return ret; } @@ -677,22 +631,17 @@ int bin_info_set_dwarf_info_debug_link(struct bin_info *bin) { int ret = 0; const gchar *dbg_dir = NULL; - gchar *bin_dir = NULL, *dir_name = NULL, *path = NULL; + gchar *bin_dir = NULL, *path = NULL; if (!bin || !bin->dbg_link_filename) { goto error; } dbg_dir = bin->debug_info_dir ? bin->debug_info_dir : DEFAULT_DEBUG_DIR; - dir_name = g_path_get_dirname(bin->elf_path); - if (!dir_name) { - goto error; - } - - bin_dir = g_strconcat(dir_name, "/", NULL); + bin_dir = g_path_get_dirname(bin->elf_path); /* First look in the executable's dir */ - path = g_strconcat(bin_dir, bin->dbg_link_filename, NULL); + path = g_build_filename(bin_dir, bin->dbg_link_filename, NULL); if (is_valid_debug_file(bin, path, bin->dbg_link_crc)) { goto found; @@ -700,7 +649,7 @@ int bin_info_set_dwarf_info_debug_link(struct bin_info *bin) /* If not found, look in .debug subdir */ g_free(path); - path = g_strconcat(bin_dir, DEBUG_SUBDIR, bin->dbg_link_filename, NULL); + path = g_build_filename(bin_dir, DEBUG_SUBDIR, bin->dbg_link_filename, NULL); if (is_valid_debug_file(bin, path, bin->dbg_link_crc)) { goto found; @@ -709,7 +658,7 @@ int bin_info_set_dwarf_info_debug_link(struct bin_info *bin) /* Lastly, look under the global debug directory */ g_free(path); - path = g_strconcat(dbg_dir, bin_dir, bin->dbg_link_filename, NULL); + path = g_build_filename(dbg_dir, bin_dir, bin->dbg_link_filename, NULL); if (is_valid_debug_file(bin, path, bin->dbg_link_crc)) { goto found; } @@ -718,7 +667,6 @@ error: ret = -1; end: g_free(bin_dir); - g_free(dir_name); g_free(path); return ret; @@ -1434,7 +1382,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 @@ -1446,7 +1396,7 @@ int bin_info_lookup_cu_src_loc_no_inl(struct bt_dwarf_cu *cu, uint64_t addr, const char *filename = NULL; Dwarf_Line *line = NULL; Dwarf_Addr line_addr; - int ret, line_no; + int ret = 0, line_no; if (!cu || !src_loc) { goto error; @@ -1459,7 +1409,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); @@ -1487,18 +1438,18 @@ int bin_info_lookup_cu_src_loc_no_inl(struct bt_dwarf_cu *cu, uint64_t addr, _src_loc->filename = g_strdup(filename); } - bt_dwarf_die_destroy(die); - if (_src_loc) { *src_loc = _src_loc; } - return 0; + goto end; error: source_location_destroy(_src_loc); + ret = -1; +end: bt_dwarf_die_destroy(die); - return -1; + return ret; } /**