X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=lib%2Fso-info.c;h=88106f39daccb8d3285e3698a9d82ccc69a8faf1;hb=36ae9941b114aae1593dd343f1784a88c7753686;hp=f1124b34cb76ba557c086f05c6f660e45108d3ee;hpb=c40a57e579977be9eb7682480428a89af5ca529c;p=babeltrace.git diff --git a/lib/so-info.c b/lib/so-info.c index f1124b34..88106f39 100644 --- a/lib/so-info.c +++ b/lib/so-info.c @@ -40,6 +40,7 @@ #include #include #include +#include /* * An address printed in hex is at most 20 bytes (16 for 64-bits + @@ -64,10 +65,9 @@ int so_info_init(void) BT_HIDDEN struct so_info *so_info_create(const char *path, uint64_t low_addr, - uint64_t memsz) + uint64_t memsz, bool is_pic) { struct so_info *so = NULL; - GElf_Ehdr *ehdr = NULL; if (!path) { goto error; @@ -83,46 +83,14 @@ struct so_info *so_info_create(const char *path, uint64_t low_addr, goto error; } - so->elf_fd = open(path, O_RDONLY); - if (so->elf_fd < 0) { - fprintf(stderr, "Failed to open %s\n", path); - goto error; - } - - so->elf_file = elf_begin(so->elf_fd, ELF_C_READ, NULL); - if (!so->elf_file) { - fprintf(stderr, "elf_begin failed: %s\n", elf_errmsg(-1)); - goto error; - } - - if (elf_kind(so->elf_file) != ELF_K_ELF) { - fprintf(stderr, "Error: %s is not an ELF object\n", - so->elf_path); - goto error; - } - - ehdr = g_new0(GElf_Ehdr, 1); - if (!ehdr) { - goto error; - } - - if (!gelf_getehdr(so->elf_file, ehdr)) { - fprintf(stderr, "Error: couldn't get ehdr for %s\n", - so->elf_path); - goto error; - } - - /* Position independent code has an e_type value of ET_DYN. */ - so->is_pic = ehdr->e_type == ET_DYN; + so->is_pic = is_pic; so->memsz = memsz; so->low_addr = low_addr; so->high_addr = so->low_addr + so->memsz; - g_free(ehdr); return so; error: - g_free(ehdr); so_info_destroy(so); return NULL; } @@ -149,6 +117,7 @@ void so_info_destroy(struct so_info *so) g_free(so); } + BT_HIDDEN int so_info_set_build_id(struct so_info *so, uint8_t *build_id, size_t build_id_len) @@ -289,7 +258,7 @@ int so_info_set_dwarf_info_build_id(struct so_info *so) goto error; } - dbg_dir = opt_debug_dir ? : DEFAULT_DEBUG_DIR; + dbg_dir = opt_debug_info_dir ? : DEFAULT_DEBUG_DIR; dbg_dir_trailing_slash = dbg_dir[strlen(dbg_dir) - 1] == '/'; @@ -404,7 +373,7 @@ int so_info_set_dwarf_info_debug_link(struct so_info *so) goto error; } - dbg_dir = opt_debug_dir ? : DEFAULT_DEBUG_DIR; + dbg_dir = opt_debug_info_dir ? : DEFAULT_DEBUG_DIR; dir_name = dirname(so->elf_path); if (!dir_name) { @@ -512,6 +481,51 @@ end: return ret; } +/** + * Initialize the ELF file for a given executable. + * + * @param so so_info instance + * @returns 0 on success, -1 on failure + */ +static +int so_info_set_elf_file(struct so_info *so) +{ + int elf_fd; + Elf *elf_file = NULL; + + if (!so) { + goto error; + } + + elf_fd = open(so->elf_path, O_RDONLY); + if (elf_fd < 0) { + fprintf(stderr, "Failed to open %s\n", so->elf_path); + goto error; + } + + elf_file = elf_begin(elf_fd, ELF_C_READ, NULL); + if (!elf_file) { + fprintf(stderr, "elf_begin failed: %s\n", elf_errmsg(-1)); + goto error; + } + + if (elf_kind(elf_file) != ELF_K_ELF) { + fprintf(stderr, "Error: %s is not an ELF object\n", + so->elf_path); + goto error; + } + + so->elf_fd = elf_fd; + so->elf_file = elf_file; + return 0; + +error: + close(elf_fd); + elf_end(elf_file); + return -1; +} + + BT_HIDDEN void source_location_destroy(struct source_location *src_loc) { @@ -659,6 +673,15 @@ int so_info_lookup_elf_function_name(struct so_info *so, uint64_t addr, char *_func_name = NULL; char offset_str[ADDR_STR_LEN]; + /* Set ELF file if it hasn't been accessed yet. */ + if (!so->elf_file) { + ret = so_info_set_elf_file(so); + if (ret) { + /* Failed to set ELF file. */ + goto error; + } + } + scn = elf_nextscn(so->elf_file, scn); if (!scn) { goto error; @@ -863,14 +886,39 @@ int so_info_lookup_function_name(struct so_info *so, uint64_t addr, ret = so_info_lookup_dwarf_function_name(so, addr, &_func_name); } - if (ret) { + if (ret || !_func_name) { goto error; } - if (_func_name) { - *func_name = _func_name; + *func_name = _func_name; + return 0; + +error: + return -1; +} + +BT_HIDDEN +int so_info_get_bin_loc(struct so_info *so, uint64_t addr, char **bin_loc) +{ + int ret = 0; + char *_bin_loc = NULL; + + if (!so || !bin_loc) { + goto error; + } + + if (so->is_pic) { + addr -= so->low_addr; + ret = asprintf(&_bin_loc, "+%#0" PRIx64, addr); + } else { + ret = asprintf(&_bin_loc, "@%#0" PRIx64, addr); + } + + if (ret == -1 || !_bin_loc) { + goto error; } + *bin_loc = _bin_loc; return 0; error: