X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=lib%2Fso-info.c;h=239320d9c30cf5582d5e4034bef4b7ff1a4fba4c;hb=f06ce5e5686facfe26a00072aee04f623d162174;hp=a82e86b809f4d8ad959ed5a1690240635af2f81d;hpb=49824faab68301740f46afb5d87aef1f8505104b;p=babeltrace.git diff --git a/lib/so-info.c b/lib/so-info.c index a82e86b8..239320d9 100644 --- a/lib/so-info.c +++ b/lib/so-info.c @@ -78,7 +78,13 @@ struct so_info *so_info_create(const char *path, uint64_t low_addr, goto error; } - so->elf_path = strdup(path); + if (opt_debug_info_target_prefix) { + so->elf_path = g_build_path("/", opt_debug_info_target_prefix, + path, NULL); + } else { + so->elf_path = strdup(path); + } + if (!so->elf_path) { goto error; } @@ -249,10 +255,10 @@ error: static int so_info_set_dwarf_info_build_id(struct so_info *so) { - int i = 0, ret = 0, dbg_dir_trailing_slash = 0; + int i = 0, ret = 0; char *path = NULL, *build_id_file = NULL; const char *dbg_dir = NULL; - size_t build_id_file_len, path_len; + size_t build_id_file_len; if (!so || !so->build_id) { goto error; @@ -260,10 +266,10 @@ int so_info_set_dwarf_info_build_id(struct so_info *so) dbg_dir = opt_debug_info_dir ? : DEFAULT_DEBUG_DIR; - dbg_dir_trailing_slash = dbg_dir[strlen(dbg_dir) - 1] == '/'; - - /* 2 characters per byte printed in hex, +2 for '/' and '\0' */ - build_id_file_len = (2 * so->build_id_len) + 2; + /* 2 characters per byte printed in hex, +1 for '/' and +1 for + * '\0' */ + build_id_file_len = (2 * so->build_id_len) + 1 + + strlen(BUILD_ID_SUFFIX) + 1; build_id_file = malloc(build_id_file_len); if (!build_id_file) { goto error; @@ -275,26 +281,13 @@ int so_info_set_dwarf_info_build_id(struct so_info *so) snprintf(&build_id_file[path_idx], 3, "%02x", so->build_id[i]); } + strcat(build_id_file, BUILD_ID_SUFFIX); - path_len = strlen(dbg_dir) + strlen(BUILD_ID_SUBDIR) + - strlen(build_id_file) + strlen(BUILD_ID_SUFFIX) + 1; - if (!dbg_dir_trailing_slash) { - path_len += 1; - } - - path = malloc(path_len); + path = g_build_path("/", dbg_dir, BUILD_ID_SUBDIR, build_id_file, NULL); if (!path) { goto error; } - strcpy(path, dbg_dir); - if (!dbg_dir_trailing_slash) { - strcat(path, "/"); - } - strcat(path, BUILD_ID_SUBDIR); - strcat(path, build_id_file); - strcat(path, BUILD_ID_SUFFIX); - ret = so_info_set_dwarf_info_from_path(so, path); if (ret) { goto error; @@ -491,7 +484,7 @@ static int so_info_set_elf_file(struct so_info *so) { int elf_fd; - Elf *elf_file; + Elf *elf_file = NULL; if (!so) { goto error; @@ -536,6 +529,56 @@ void source_location_destroy(struct source_location *src_loc) free(src_loc->filename); g_free(src_loc); } +/** + * Append a string representation of an address offset to an existing + * string. + * + * On success, the out parameter `result` will contain the base string + * followed by the offset string of the form "+0x1234". On failure, + * `result` remains unchanged. + * + * @param base_str The string to which to append an offset string + * @param low_addr The lower virtual memory address, the base from + * which the offset is computed + * @param high_addr The higher virtual memory address + * @param result Out parameter, the base string followed by the + * offset string + * @returns 0 on success, -1 on failure + */ +static +int so_info_append_offset_str(const char *base_str, uint64_t low_addr, + uint64_t high_addr, char **result) +{ + int ret; + uint64_t offset; + char *_result = NULL; + char offset_str[ADDR_STR_LEN]; + + if (!base_str || !result) { + goto error; + } + + offset = high_addr - low_addr; + + _result = malloc(strlen(base_str) + ADDR_STR_LEN); + if (!_result) { + goto error; + } + + ret = snprintf(offset_str, ADDR_STR_LEN, "+%#0" PRIx64, offset); + if (ret < 0) { + goto error; + } + strcpy(_result, base_str); + strcat(_result, offset_str); + *result = _result; + + return 0; + +error: + free(_result); + return -1; +} /** * Try to find the symbol closest to an address within a given ELF @@ -670,8 +713,6 @@ int so_info_lookup_elf_function_name(struct so_info *so, uint64_t addr, GElf_Sym *sym = NULL; GElf_Shdr *shdr = NULL; char *sym_name = NULL; - char *_func_name = NULL; - char offset_str[ADDR_STR_LEN]; /* Set ELF file if it hasn't been accessed yet. */ if (!so->elf_file) { @@ -704,16 +745,11 @@ int so_info_lookup_elf_function_name(struct so_info *so, uint64_t addr, goto error; } - snprintf(offset_str, ADDR_STR_LEN, "+%#0" PRIx64, - addr - sym->st_value); - _func_name = malloc(strlen(sym_name) + ADDR_STR_LEN); - if (!_func_name) { + ret = so_info_append_offset_str(sym_name, sym->st_value, addr, + func_name); + if (ret) { goto error; } - - strcpy(_func_name, sym_name); - strcat(_func_name, offset_str); - *func_name = _func_name; } g_free(shdr); @@ -723,7 +759,6 @@ int so_info_lookup_elf_function_name(struct so_info *so, uint64_t addr, error: g_free(shdr); g_free(sym); - free(_func_name); return -1; } @@ -745,7 +780,6 @@ int so_info_lookup_cu_function_name(struct bt_dwarf_cu *cu, uint64_t addr, char **func_name) { int ret = 0, found = 0; - char *_func_name = NULL; struct bt_dwarf_die *die = NULL; if (!cu || !func_name) { @@ -778,12 +812,24 @@ int so_info_lookup_cu_function_name(struct bt_dwarf_cu *cu, uint64_t addr, } if (found) { - ret = bt_dwarf_die_get_name(die, &_func_name); + uint64_t low_addr = 0; + char *die_name = NULL; + + ret = bt_dwarf_die_get_name(die, &die_name); if (ret) { goto error; } - *func_name = _func_name; + ret = dwarf_lowpc(die->dwarf_die, &low_addr); + if (ret) { + goto error; + } + + ret = so_info_append_offset_str(die_name, low_addr, addr, + func_name); + if (ret) { + goto error; + } } bt_dwarf_die_destroy(die); @@ -849,12 +895,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; @@ -869,46 +914,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: