X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=blobdiff_plain;f=lib%2Fso-info.c;h=93d7167fee60244932fc15634a3fa797a5b54352;hp=3a603b8f1561f0b2c52cb8e2b5765a559b9501b3;hb=b7b61ced2a4d4e3222640ad20e6655cb4379c012;hpb=e362dc9319fe4863cf6d60ac41f8779807b7fbce diff --git a/lib/so-info.c b/lib/so-info.c index 3a603b8f..93d7167f 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; } @@ -536,6 +542,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 +726,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 +758,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 +772,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 +793,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 +825,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 +908,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 +927,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: