From: Tobias Brunner Date: Thu, 1 Dec 2022 08:29:17 +0000 (+0100) Subject: backtrace: Add ability to lookup function names via libbfd X-Git-Tag: 5.9.9rc1~29 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=21af89f94194e9af9a9114d7b08253862f3bd0f4;p=thirdparty%2Fstrongswan.git backtrace: Add ability to lookup function names via libbfd dladdr() is not always able to determine the function names while libbfd often can in such cases. --- diff --git a/src/libstrongswan/utils/backtrace.c b/src/libstrongswan/utils/backtrace.c index 30f19cb156..2fdfab1ee0 100644 --- a/src/libstrongswan/utils/backtrace.c +++ b/src/libstrongswan/utils/backtrace.c @@ -207,10 +207,16 @@ typedef struct { bfd_entry_t *entry; /** backtrace address */ bfd_vma vma; - /** stream to log to */ - FILE *file; - /** TRUE if complete */ + /** TRUE if address found */ bool found; + /** optional stream to log to */ + FILE *file; + /** optional list of function names to match */ + char **list; + /** optional number of names in list */ + int count; + /** TRUE if found function name is in list */ + bool in_list; } bfd_find_data_t; /** @@ -279,39 +285,56 @@ static void find_addr(bfd *abfd, asection *section, bfd_find_data_t *data) const char *function; char fbuf[512] = "", sbuf[512] = ""; u_int line; + int i; + + if (data->found || (get_section_flags(abfd, section) & SEC_ALLOC) == 0) + { + return; + } + vma = get_section_vma(abfd, section); + if (data->vma < vma) + { + return; + } + size = get_section_size(section); + if (data->vma >= vma + size) + { + return; + } - if (!data->found || (get_section_flags(abfd, section) & SEC_ALLOC) != 0) + data->found = bfd_find_nearest_line(abfd, section, data->entry->syms, + data->vma - vma, &source, &function, + &line); + if (!data->found) + { + return; + } + if (data->count && function) { - vma = get_section_vma(abfd, section); - if (data->vma >= vma) + for (i = 0; i < data->count; i++) { - size = get_section_size(section); - if (data->vma < vma + size) + if (streq(function, data->list[i])) { - data->found = bfd_find_nearest_line(abfd, section, - data->entry->syms, data->vma - vma, - &source, &function, &line); - if (data->found) - { - if (source || function) - { - if (function) - { - snprintf(fbuf, sizeof(fbuf), "%s%s() ", - esc(data->file, TTY_FG_BLUE), function); - } - if (source) - { - snprintf(sbuf, sizeof(sbuf), "%s@ %s:%d", - esc(data->file, TTY_FG_GREEN), source, line); - } - println(data->file, " -> %s%s%s", fbuf, sbuf, - esc(data->file, TTY_FG_DEF)); - } - } + data->in_list = TRUE; + break; } } } + else if (data->file && (source || function)) + { + if (function) + { + snprintf(fbuf, sizeof(fbuf), "%s%s() ", + esc(data->file, TTY_FG_BLUE), function); + } + if (source) + { + snprintf(sbuf, sizeof(sbuf), "%s@ %s:%d", + esc(data->file, TTY_FG_GREEN), source, line); + } + println(data->file, " -> %s%s%s", fbuf, sbuf, + esc(data->file, TTY_FG_DEF)); + } } /** @@ -380,15 +403,11 @@ static bfd_entry_t *get_bfd_entry(char *filename) } /** - * Print the source file with line number to file, libbfd variant + * Lookup the given address */ -static void print_sourceline(FILE *file, char *filename, void *ptr, void *base) +static void lookup_addr(char *filename, bfd_find_data_t *data) { bfd_entry_t *entry; - bfd_find_data_t data = { - .file = file, - .vma = (uintptr_t)ptr, - }; bool old = FALSE; bfd_mutex->lock(bfd_mutex); @@ -399,8 +418,8 @@ static void print_sourceline(FILE *file, char *filename, void *ptr, void *base) entry = get_bfd_entry(filename); if (entry) { - data.entry = entry; - bfd_map_over_sections(entry->abfd, (void*)find_addr, &data); + data->entry = entry; + bfd_map_over_sections(entry->abfd, (void*)find_addr, data); } if (lib && lib->leak_detective) { @@ -409,6 +428,35 @@ static void print_sourceline(FILE *file, char *filename, void *ptr, void *base) bfd_mutex->unlock(bfd_mutex); } +/** + * Print the source file with line number to file, libbfd variant + */ +static void print_sourceline(FILE *file, char *filename, void *ptr, void *base) +{ + bfd_find_data_t data = { + .file = file, + .vma = (uintptr_t)ptr, + }; + + lookup_addr(filename, &data); +} + +/** + * Check if the function name of the source line is in the given list + */ +static bool contains_function_bfd(char *filename, void *ptr, char *list[], + int count) +{ + bfd_find_data_t data = { + .vma = (uintptr_t)ptr, + .list = list, + .count = count, + }; + + lookup_addr(filename, &data); + return data.in_list; +} + #else /* !HAVE_BFD_H */ void backtrace_init() {} @@ -619,15 +667,34 @@ METHOD(backtrace_t, contains_function, bool, { Dl_info info; - if (dladdr(this->frames[i], &info) && info.dli_sname) + if (dladdr(this->frames[i], &info)) { - for (j = 0; j < count; j++) + if (info.dli_sname) + { + for (j = 0; j < count; j++) + { + if (streq(info.dli_sname, function[j])) + { + return TRUE; + } + } + } +#ifdef HAVE_BFD_H + else if (info.dli_fname[0]) { - if (streq(info.dli_sname, function[j])) + void *ptr = this->frames[i]; + + if (strstr(info.dli_fname, ".so")) + { + ptr = (void*)(this->frames[i] - info.dli_fbase); + } + if (contains_function_bfd((char*)info.dli_fname, ptr, + function, count)) { return TRUE; } } +#endif /* HAVE_BFD_H */ } } #elif defined(HAVE_DBGHELP)