diff options
author | Eunseon Lee <es.lee@lge.com> | 2023-12-27 19:22:19 +0900 |
---|---|---|
committer | Hengqi Chen <chenhengqi@outlook.com> | 2024-05-02 08:17:59 +0800 |
commit | fef9003e2e2f29c893543d49b762dd413a352f05 (patch) | |
tree | 52b3d31599f74f83db6df141cf1cf8d96520584c | |
parent | 74fe7200ffb1d991c4e839f184c705f0a45006d9 (diff) | |
download | bcc-upstream-master.tar.gz |
libbpf-tools/trace_helpers: Fix incorrect DSO information in stacktraceupstream-master
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
-rw-r--r-- | libbpf-tools/futexctn.c | 17 | ||||
-rw-r--r-- | libbpf-tools/memleak.c | 15 | ||||
-rw-r--r-- | libbpf-tools/offcputime.c | 16 | ||||
-rw-r--r-- | libbpf-tools/trace_helpers.c | 21 | ||||
-rw-r--r-- | libbpf-tools/trace_helpers.h | 11 | ||||
m--------- | src/cc/libbpf | 0 |
6 files changed, 45 insertions, 35 deletions
diff --git a/libbpf-tools/futexctn.c b/libbpf-tools/futexctn.c index 4a780fb2..a29578db 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 eae32fea..6bdcaef5 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 c70bccdd..578b8b5b 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 @@ print_ustack: 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 afd3a10a..732627a2 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 171bc4ee..651cd107 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 -Subproject 3b0973892891744d20ae79e99c0d1a26a59c422 +Subproject 44b0bc9ad70a73cddc3528f12da48cc3520ad06 |