X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=blobdiff_plain;f=lib%2Fso-info.c;h=88106f39daccb8d3285e3698a9d82ccc69a8faf1;hp=a5ddfe51ed866a76ac1a71252140829b04970dd4;hb=dc419b6cc12d26c840d29440d5077f0a29221952;hpb=1a4a1345c93d716d50cf10e4717f4cc895e313c6 diff --git a/lib/so-info.c b/lib/so-info.c index a5ddfe51..88106f39 100644 --- a/lib/so-info.c +++ b/lib/so-info.c @@ -68,7 +68,6 @@ struct so_info *so_info_create(const char *path, uint64_t low_addr, uint64_t memsz, bool is_pic) { struct so_info *so = NULL; - GElf_Ehdr *ehdr = NULL; if (!path) { goto error; @@ -84,45 +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; - } - 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) @@ -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; @@ -826,12 +849,11 @@ error: } BT_HIDDEN -int so_info_lookup_function_name(struct so_info *so, uint64_t ip, +int so_info_lookup_function_name(struct so_info *so, uint64_t addr, char **func_name) { int ret = 0; char *_func_name = NULL; - uint64_t relative_addr; if (!so || !func_name) { goto error; @@ -846,46 +868,57 @@ int so_info_lookup_function_name(struct so_info *so, uint64_t ip, } } - if (!so_info_has_address(so, ip)) { + if (!so_info_has_address(so, addr)) { goto error; } - relative_addr = ip - so->low_addr; /* * Addresses in ELF and DWARF are relative to base address for * PIC, so make the address argument relative too if needed. */ + if (so->is_pic) { + addr -= so->low_addr; + } + if (so->is_elf_only) { - ret = so_info_lookup_elf_function_name(so, - so->is_pic ? relative_addr : ip, - &_func_name); + ret = so_info_lookup_elf_function_name(so, addr, &_func_name); } else { - ret = so_info_lookup_dwarf_function_name(so, - so->is_pic ? relative_addr : ip, - &_func_name); + ret = so_info_lookup_dwarf_function_name(so, addr, &_func_name); } - if (ret) { + if (ret || !_func_name) { goto error; } - if (!_func_name) { - /* - * Can't map to a function; fallback to a generic output of the - * form binary+/@address. - * - * FIXME check position independence flag. - */ - const char *binary_name = get_filename_from_path(so->elf_path); + *func_name = _func_name; + return 0; - ret = asprintf(&_func_name, "%s+%#0" PRIx64, binary_name, - relative_addr); - if (!_func_name) { - goto error; - } +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; } - *func_name = _func_name; + 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: