aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEunseon Lee <es.lee@lge.com>2023-12-27 19:22:19 +0900
committerHengqi Chen <chenhengqi@outlook.com>2024-05-02 08:17:59 +0800
commitfef9003e2e2f29c893543d49b762dd413a352f05 (patch)
tree52b3d31599f74f83db6df141cf1cf8d96520584c
parent74fe7200ffb1d991c4e839f184c705f0a45006d9 (diff)
downloadbcc-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.c17
-rw-r--r--libbpf-tools/memleak.c15
-rw-r--r--libbpf-tools/offcputime.c16
-rw-r--r--libbpf-tools/trace_helpers.c21
-rw-r--r--libbpf-tools/trace_helpers.h11
m---------src/cc/libbpf0
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