From fef9003e2e2f29c893543d49b762dd413a352f05 Mon Sep 17 00:00:00 2001 From: Eunseon Lee Date: Wed, 27 Dec 2023 19:22:19 +0900 Subject: [PATCH] libbpf-tools/trace_helpers: Fix incorrect DSO information in stacktrace offcputime may display inaccurate DSO information in the stacktrace. Here's an example of the issue: It shows the same DSO offset for different addresses, which is incorrect. $ ./offcputime -v .. #14 0x00007f8b912a8c (/usr/lib/libcbe.so_0x22afa8c) #15 0x000044000a3ee0 (/usr/lib/libcbe.so_0x22afa8c) #16 0x000044001fc56c (/usr/lib/libcbe.so_0x22afa8c) This is why syms__map_addr_dso simply returns NULL when syms__find_dso also returns NULL. In that case, the values of dso_name and dso_offset are not changed. If the dso_name and dso_offset variables have a garbage value before calling syms__map_addr_dso, those garbage values are maintained after calling syms__map_addr_dso. To ensure consistent usage of DSO info and symbol info, the prototype of syms__map_addr_dso has been modified to be similar to dladdr[1]. This is the prototype of dladdr: int dladdr(void *addr, Dl_info *info); The information is returned in a Dl_info structure. If no symbol matching addr could be found, then dli_sname and dli_saddr are set to NULL. typedef struct { const char *dli_fname; /* Pathname of shared object that contains address */ void *dli_fbase; /* Base address at which shared object is loaded */ const char *dli_sname; /* Name of symbol whose definition overlaps addr */ void *dli_saddr; /* Exact address of symbol named in dli_sname */ } Dl_info; Similarly, if no symbol matching the addr could be found, then sym_name and sym_offset are set to NULL in syms__map_addr_dso of this patch. Also, apply the modified API usage to offcputime, futexctn, and memleak. [1] https://man7.org/linux/man-pages/man3/dladdr.3.html --- libbpf-tools/futexctn.c | 17 +++++++---------- libbpf-tools/memleak.c | 15 +++++++-------- libbpf-tools/offcputime.c | 16 +++++++--------- libbpf-tools/trace_helpers.c | 21 +++++++++++++++------ libbpf-tools/trace_helpers.h | 11 +++++++++-- src/cc/libbpf | 2 +- 6 files changed, 46 insertions(+), 36 deletions(-) diff --git a/libbpf-tools/futexctn.c b/libbpf-tools/futexctn.c index 4a780fb2152b..a29578db9dd4 100644 --- a/libbpf-tools/futexctn.c +++ b/libbpf-tools/futexctn.c @@ -194,8 +194,7 @@ static int print_stack(struct futexctn_bpf *obj, struct hist_key *info) #else const struct syms *syms; const struct sym *sym; - char *dso_name; - unsigned long dso_offset; + struct sym_info sinfo; int idx = 0; #endif int i, err = 0, fd; @@ -245,14 +244,12 @@ static int print_stack(struct futexctn_bpf *obj, struct hist_key *info) else printf(" [unknown]\n"); } else { - dso_name = NULL; - dso_offset = 0; - sym = syms__map_addr_dso(syms, ip[i], &dso_name, &dso_offset); - printf(" #%-2d 0x%016lx", idx++, ip[i]); - if (sym) - printf(" %s+0x%lx", sym->name, sym->offset); - if (dso_name) - printf(" (%s+0x%lx)", dso_name, dso_offset); + err = syms__map_addr_dso(syms, ip[i], &sinfo); + if (err == 0) { + if (sinfo.sym_name) + printf(" %s+0x%lx", sinfo.sym_name, sinfo.sym_offset); + printf(" (%s+0x%lx)", sinfo.dso_name, sinfo.dso_offset); + } printf("\n"); } } diff --git a/libbpf-tools/memleak.c b/libbpf-tools/memleak.c index eae32feae35c..6bdcaef57e27 100644 --- a/libbpf-tools/memleak.c +++ b/libbpf-tools/memleak.c @@ -766,14 +766,13 @@ void print_stack_frames_by_syms_cache() if (addr == 0) break; - char *dso_name; - uint64_t dso_offset; - const struct sym *sym = syms__map_addr_dso(syms, addr, &dso_name, &dso_offset); - if (sym) { - printf("\t%zu [<%016lx>] %s+0x%lx", i, addr, sym->name, sym->offset); - if (dso_name) - printf(" [%s]", dso_name); - printf("\n"); + struct sym_info sinfo; + int ret = syms__map_addr_dso(syms, addr, &sinfo); + if (ret == 0) { + printf("\t%zu [<%016lx>]", i, addr); + if (sinfo.sym_name) + printf(" %s+0x%lx", sinfo.sym_name, sinfo.sym_offset); + printf(" [%s]\n", sinfo.dso_name); } else { printf("\t%zu [<%016lx>] <%s>\n", i, addr, "null sym"); } diff --git a/libbpf-tools/offcputime.c b/libbpf-tools/offcputime.c index c70bccdd25cd..578b8b5b297d 100644 --- a/libbpf-tools/offcputime.c +++ b/libbpf-tools/offcputime.c @@ -195,8 +195,7 @@ static void print_map(struct ksyms *ksyms, struct syms_cache *syms_cache, int err, i, ifd, sfd; unsigned long *ip; struct val_t val; - char *dso_name; - unsigned long dso_offset; + struct sym_info sinfo; int idx; ip = calloc(env.perf_max_stack_depth, sizeof(*ip)); @@ -262,14 +261,13 @@ static void print_map(struct ksyms *ksyms, struct syms_cache *syms_cache, else printf(" [unknown]\n"); } else { - dso_name = NULL; - dso_offset = 0; - sym = syms__map_addr_dso(syms, ip[i], &dso_name, &dso_offset); printf(" #%-2d 0x%016lx", idx++, ip[i]); - if (sym) - printf(" %s+0x%lx", sym->name, sym->offset); - if (dso_name) - printf(" (%s+0x%lx)", dso_name, dso_offset); + err = syms__map_addr_dso(syms, ip[i], &sinfo); + if (err == 0) { + if (sinfo.sym_name) + printf(" %s+0x%lx", sinfo.sym_name, sinfo.sym_offset); + printf(" (%s+0x%lx)", sinfo.dso_name, sinfo.dso_offset); + } printf("\n"); } } diff --git a/libbpf-tools/trace_helpers.c b/libbpf-tools/trace_helpers.c index afd3a10ae9e6..732627a21407 100644 --- a/libbpf-tools/trace_helpers.c +++ b/libbpf-tools/trace_helpers.c @@ -738,20 +738,29 @@ const struct sym *syms__map_addr(const struct syms *syms, unsigned long addr) return dso__find_sym(dso, offset); } -const struct sym *syms__map_addr_dso(const struct syms *syms, unsigned long addr, - char **dso_name, unsigned long *dso_offset) +int syms__map_addr_dso(const struct syms *syms, unsigned long addr, + struct sym_info *sinfo) { struct dso *dso; + struct sym *sym; uint64_t offset; + memset(sinfo, 0x0, sizeof(struct sym_info)); + dso = syms__find_dso(syms, addr, &offset); if (!dso) - return NULL; + return -1; - *dso_name = dso->name; - *dso_offset = offset; + sinfo->dso_name = dso->name; + sinfo->dso_offset = offset; - return dso__find_sym(dso, offset); + sym = dso__find_sym(dso, offset); + if (sym) { + sinfo->sym_name = sym->name; + sinfo->sym_offset = sym->offset; + } + + return 0; } struct syms_cache { diff --git a/libbpf-tools/trace_helpers.h b/libbpf-tools/trace_helpers.h index 171bc4ee2102..651cd107e91a 100644 --- a/libbpf-tools/trace_helpers.h +++ b/libbpf-tools/trace_helpers.h @@ -27,14 +27,21 @@ struct sym { unsigned long offset; }; +struct sym_info { + const char *dso_name; + unsigned long dso_offset; + const char *sym_name; + unsigned long sym_offset; +}; + struct syms; struct syms *syms__load_pid(int tgid); struct syms *syms__load_file(const char *fname); void syms__free(struct syms *syms); const struct sym *syms__map_addr(const struct syms *syms, unsigned long addr); -const struct sym *syms__map_addr_dso(const struct syms *syms, unsigned long addr, - char **dso_name, unsigned long *dso_offset); +int syms__map_addr_dso(const struct syms *syms, unsigned long addr, + struct sym_info *sinfo); struct syms_cache; diff --git a/src/cc/libbpf b/src/cc/libbpf index 3b0973892891..44b0bc9ad70a 160000 --- a/src/cc/libbpf +++ b/src/cc/libbpf @@ -1 +1 @@ -Subproject commit 3b0973892891744d20ae79e99c0d1a26a59c4222 +Subproject commit 44b0bc9ad70a73cddc3528f12da48cc3520ad060