From: Francis Deslauriers Date: Fri, 3 May 2019 16:39:59 +0000 (-0400) Subject: Fix: flt.lttng-utils.debug-info: build id note section non-native byte order X-Git-Tag: v2.0.0-pre5~1 X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=commitdiff_plain;h=8d48beb93387cf8e35da8adf2ea62bed40d194c7 Fix: flt.lttng-utils.debug-info: build id note section non-native byte order Issue ===== The build id comparison code does not take into account that the target binary file could be compiled for another architecture and thus could be of a different byte order. This makes the build_id testcase fail on PowerPC. The artefacts used for this testcase are compiled on x86 and are thus in little endian as opposed to PowerPC's big endianness. Solution ======== Parse the Elf file to extract the endianness of the binary and use that information to change the byte order of the note section if necessary. Drawbacks ========= None. Signed-off-by: Francis Deslauriers Change-Id: Id5d761832f9463b38ea0452da36053e885929aa9 Reviewed-on: https://review.lttng.org/c/babeltrace/+/1246 Reviewed-by: Jérémie Galarneau Reviewed-by: Michael Jeanson --- diff --git a/plugins/lttng-utils/debug-info/bin-info.c b/plugins/lttng-utils/debug-info/bin-info.c index ac9bb68f..5393cdba 100644 --- a/plugins/lttng-utils/debug-info/bin-info.c +++ b/plugins/lttng-utils/debug-info/bin-info.c @@ -42,6 +42,8 @@ #include +#include + #include "bin-info.h" #include "crc32.h" #include "dwarf.h" @@ -144,6 +146,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 +192,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 +203,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: @@ -295,7 +339,6 @@ 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; if (!bin->build_id) { @@ -322,6 +365,9 @@ int is_build_id_matching(struct bin_info *bin) } 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); @@ -335,14 +381,31 @@ int is_build_id_matching(struct bin_info *bin) 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,8 +413,10 @@ 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; } @@ -741,7 +806,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; } diff --git a/plugins/lttng-utils/debug-info/bin-info.h b/plugins/lttng-utils/debug-info/bin-info.h index f6848fb3..8e3a4fc6 100644 --- a/plugins/lttng-utils/debug-info/bin-info.h +++ b/plugins/lttng-utils/debug-info/bin-info.h @@ -66,7 +66,12 @@ struct bin_info { gchar *debug_info_dir; /* Denotes whether the executable is position independent code. */ bool is_pic:1; - /* denotes whether the build id in the trace matches to one on disk. */ + /* + * Endianness of the binary file. (may differ from system endianness). + * Two possible values are ELFDATA2MSB and ELFDATA2LSB. + */ + uint8_t endianness; + /* Denotes whether the build id in the trace matches to one on disk. */ bool file_build_id_matches:1; /* * Denotes whether the executable only has ELF symbols and no