Commit ff741783 authored by Masami Hiramatsu's avatar Masami Hiramatsu Committed by Steven Rostedt

perf probe: Introduce debuginfo to encapsulate dwarf information

Introduce debuginfo to encapsulate dwarf information.
This new object allows us to reuse and expand debuginfo easily.
Signed-off-by: default avatarMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Link: http://lkml.kernel.org/r/20110627072739.6528.12438.stgit@fedora15Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
parent e0d153c6
...@@ -170,16 +170,17 @@ const char *kernel_get_module_path(const char *module) ...@@ -170,16 +170,17 @@ const char *kernel_get_module_path(const char *module)
} }
#ifdef DWARF_SUPPORT #ifdef DWARF_SUPPORT
static int open_vmlinux(const char *module) /* Open new debuginfo of given module */
static struct debuginfo *open_debuginfo(const char *module)
{ {
const char *path = kernel_get_module_path(module); const char *path = kernel_get_module_path(module);
if (!path) { if (!path) {
pr_err("Failed to find path of %s module.\n", pr_err("Failed to find path of %s module.\n",
module ?: "kernel"); module ?: "kernel");
return -ENOENT; return NULL;
} }
pr_debug("Try to open %s\n", path); return debuginfo__new(path);
return open(path, O_RDONLY);
} }
/* /*
...@@ -193,13 +194,24 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, ...@@ -193,13 +194,24 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
struct map *map; struct map *map;
u64 addr; u64 addr;
int ret = -ENOENT; int ret = -ENOENT;
struct debuginfo *dinfo;
sym = __find_kernel_function_by_name(tp->symbol, &map); sym = __find_kernel_function_by_name(tp->symbol, &map);
if (sym) { if (sym) {
addr = map->unmap_ip(map, sym->start + tp->offset); addr = map->unmap_ip(map, sym->start + tp->offset);
pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol, pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol,
tp->offset, addr); tp->offset, addr);
ret = find_perf_probe_point((unsigned long)addr, pp);
dinfo = debuginfo__new_online_kernel(addr);
if (dinfo) {
ret = debuginfo__find_probe_point(dinfo,
(unsigned long)addr, pp);
debuginfo__delete(dinfo);
} else {
pr_debug("Failed to open debuginfo at 0x%" PRIx64 "\n",
addr);
ret = -ENOENT;
}
} }
if (ret <= 0) { if (ret <= 0) {
pr_debug("Failed to find corresponding probes from " pr_debug("Failed to find corresponding probes from "
...@@ -220,20 +232,22 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, ...@@ -220,20 +232,22 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
int max_tevs, const char *module) int max_tevs, const char *module)
{ {
bool need_dwarf = perf_probe_event_need_dwarf(pev); bool need_dwarf = perf_probe_event_need_dwarf(pev);
int fd, ntevs; struct debuginfo *dinfo = open_debuginfo(module);
int ntevs;
fd = open_vmlinux(module); if (!dinfo) {
if (fd < 0) {
if (need_dwarf) { if (need_dwarf) {
pr_warning("Failed to open debuginfo file.\n"); pr_warning("Failed to open debuginfo file.\n");
return fd; return -ENOENT;
} }
pr_debug("Could not open vmlinux. Try to use symbols.\n"); pr_debug("Could not open debuginfo. Try to use symbols.\n");
return 0; return 0;
} }
/* Searching trace events corresponding to probe event */ /* Searching trace events corresponding to a probe event */
ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs); ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs);
debuginfo__delete(dinfo);
if (ntevs > 0) { /* Succeeded to find trace events */ if (ntevs > 0) { /* Succeeded to find trace events */
pr_debug("find %d probe_trace_events.\n", ntevs); pr_debug("find %d probe_trace_events.\n", ntevs);
...@@ -371,8 +385,9 @@ int show_line_range(struct line_range *lr, const char *module) ...@@ -371,8 +385,9 @@ int show_line_range(struct line_range *lr, const char *module)
{ {
int l = 1; int l = 1;
struct line_node *ln; struct line_node *ln;
struct debuginfo *dinfo;
FILE *fp; FILE *fp;
int fd, ret; int ret;
char *tmp; char *tmp;
/* Search a line range */ /* Search a line range */
...@@ -380,13 +395,14 @@ int show_line_range(struct line_range *lr, const char *module) ...@@ -380,13 +395,14 @@ int show_line_range(struct line_range *lr, const char *module)
if (ret < 0) if (ret < 0)
return ret; return ret;
fd = open_vmlinux(module); dinfo = open_debuginfo(module);
if (fd < 0) { if (!dinfo) {
pr_warning("Failed to open debuginfo file.\n"); pr_warning("Failed to open debuginfo file.\n");
return fd; return -ENOENT;
} }
ret = find_line_range(fd, lr); ret = debuginfo__find_line_range(dinfo, lr);
debuginfo__delete(dinfo);
if (ret == 0) { if (ret == 0) {
pr_warning("Specified source line is not found.\n"); pr_warning("Specified source line is not found.\n");
return -ENOENT; return -ENOENT;
...@@ -448,7 +464,8 @@ int show_line_range(struct line_range *lr, const char *module) ...@@ -448,7 +464,8 @@ int show_line_range(struct line_range *lr, const char *module)
return ret; return ret;
} }
static int show_available_vars_at(int fd, struct perf_probe_event *pev, static int show_available_vars_at(struct debuginfo *dinfo,
struct perf_probe_event *pev,
int max_vls, struct strfilter *_filter, int max_vls, struct strfilter *_filter,
bool externs) bool externs)
{ {
...@@ -463,7 +480,8 @@ static int show_available_vars_at(int fd, struct perf_probe_event *pev, ...@@ -463,7 +480,8 @@ static int show_available_vars_at(int fd, struct perf_probe_event *pev,
return -EINVAL; return -EINVAL;
pr_debug("Searching variables at %s\n", buf); pr_debug("Searching variables at %s\n", buf);
ret = find_available_vars_at(fd, pev, &vls, max_vls, externs); ret = debuginfo__find_available_vars_at(dinfo, pev, &vls,
max_vls, externs);
if (ret <= 0) { if (ret <= 0) {
pr_err("Failed to find variables at %s (%d)\n", buf, ret); pr_err("Failed to find variables at %s (%d)\n", buf, ret);
goto end; goto end;
...@@ -504,24 +522,26 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs, ...@@ -504,24 +522,26 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
int max_vls, const char *module, int max_vls, const char *module,
struct strfilter *_filter, bool externs) struct strfilter *_filter, bool externs)
{ {
int i, fd, ret = 0; int i, ret = 0;
struct debuginfo *dinfo;
ret = init_vmlinux(); ret = init_vmlinux();
if (ret < 0) if (ret < 0)
return ret; return ret;
dinfo = open_debuginfo(module);
if (!dinfo) {
pr_warning("Failed to open debuginfo file.\n");
return -ENOENT;
}
setup_pager(); setup_pager();
for (i = 0; i < npevs && ret >= 0; i++) { for (i = 0; i < npevs && ret >= 0; i++)
fd = open_vmlinux(module); ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter,
if (fd < 0) {
pr_warning("Failed to open debug information file.\n");
ret = fd;
break;
}
ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter,
externs); externs);
}
debuginfo__delete(dinfo);
return ret; return ret;
} }
......
...@@ -116,29 +116,37 @@ static const Dwfl_Callbacks offline_callbacks = { ...@@ -116,29 +116,37 @@ static const Dwfl_Callbacks offline_callbacks = {
}; };
/* Get a Dwarf from offline image */ /* Get a Dwarf from offline image */
static Dwarf *dwfl_init_offline_dwarf(int fd, Dwfl **dwflp, Dwarf_Addr *bias) static int debuginfo__init_offline_dwarf(struct debuginfo *self,
const char *path)
{ {
Dwfl_Module *mod; Dwfl_Module *mod;
Dwarf *dbg = NULL; int fd;
if (!dwflp) fd = open(path, O_RDONLY);
return NULL; if (fd < 0)
return fd;
*dwflp = dwfl_begin(&offline_callbacks); self->dwfl = dwfl_begin(&offline_callbacks);
if (!*dwflp) if (!self->dwfl)
return NULL; goto error;
mod = dwfl_report_offline(*dwflp, "", "", fd); mod = dwfl_report_offline(self->dwfl, "", "", fd);
if (!mod) if (!mod)
goto error; goto error;
dbg = dwfl_module_getdwarf(mod, bias); self->dbg = dwfl_module_getdwarf(mod, &self->bias);
if (!dbg) { if (!self->dbg)
goto error;
return 0;
error: error:
dwfl_end(*dwflp); if (self->dwfl)
*dwflp = NULL; dwfl_end(self->dwfl);
} else
return dbg; close(fd);
memset(self, 0, sizeof(*self));
return -ENOENT;
} }
#if _ELFUTILS_PREREQ(0, 148) #if _ELFUTILS_PREREQ(0, 148)
...@@ -174,53 +182,82 @@ static const Dwfl_Callbacks kernel_callbacks = { ...@@ -174,53 +182,82 @@ static const Dwfl_Callbacks kernel_callbacks = {
}; };
/* Get a Dwarf from live kernel image */ /* Get a Dwarf from live kernel image */
static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp, static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
Dwarf_Addr *bias) Dwarf_Addr addr)
{ {
Dwarf *dbg; self->dwfl = dwfl_begin(&kernel_callbacks);
if (!self->dwfl)
if (!dwflp) return -EINVAL;
return NULL;
*dwflp = dwfl_begin(&kernel_callbacks);
if (!*dwflp)
return NULL;
/* Load the kernel dwarves: Don't care the result here */ /* Load the kernel dwarves: Don't care the result here */
dwfl_linux_kernel_report_kernel(*dwflp); dwfl_linux_kernel_report_kernel(self->dwfl);
dwfl_linux_kernel_report_modules(*dwflp); dwfl_linux_kernel_report_modules(self->dwfl);
dbg = dwfl_addrdwarf(*dwflp, addr, bias); self->dbg = dwfl_addrdwarf(self->dwfl, addr, &self->bias);
/* Here, check whether we could get a real dwarf */ /* Here, check whether we could get a real dwarf */
if (!dbg) { if (!self->dbg) {
pr_debug("Failed to find kernel dwarf at %lx\n", pr_debug("Failed to find kernel dwarf at %lx\n",
(unsigned long)addr); (unsigned long)addr);
dwfl_end(*dwflp); dwfl_end(self->dwfl);
*dwflp = NULL; memset(self, 0, sizeof(*self));
return -ENOENT;
} }
return dbg;
return 0;
} }
#else #else
/* With older elfutils, this just support kernel module... */ /* With older elfutils, this just support kernel module... */
static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr __used, Dwfl **dwflp, static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
Dwarf_Addr *bias) Dwarf_Addr addr __used)
{ {
int fd;
const char *path = kernel_get_module_path("kernel"); const char *path = kernel_get_module_path("kernel");
if (!path) { if (!path) {
pr_err("Failed to find vmlinux path\n"); pr_err("Failed to find vmlinux path\n");
return NULL; return -ENOENT;
} }
pr_debug2("Use file %s for debuginfo\n", path); pr_debug2("Use file %s for debuginfo\n", path);
fd = open(path, O_RDONLY); return debuginfo__init_offline_dwarf(self, path);
if (fd < 0) }
#endif
struct debuginfo *debuginfo__new(const char *path)
{
struct debuginfo *self = zalloc(sizeof(struct debuginfo));
if (!self)
return NULL; return NULL;
return dwfl_init_offline_dwarf(fd, dwflp, bias); if (debuginfo__init_offline_dwarf(self, path) < 0) {
free(self);
self = NULL;
}
return self;
}
struct debuginfo *debuginfo__new_online_kernel(unsigned long addr)
{
struct debuginfo *self = zalloc(sizeof(struct debuginfo));
if (!self)
return NULL;
if (debuginfo__init_online_kernel_dwarf(self, (Dwarf_Addr)addr) < 0) {
free(self);
self = NULL;
}
return self;
}
void debuginfo__delete(struct debuginfo *self)
{
if (self) {
if (self->dwfl)
dwfl_end(self->dwfl);
free(self);
}
} }
#endif
/* /*
* Probe finder related functions * Probe finder related functions
...@@ -949,28 +986,18 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data) ...@@ -949,28 +986,18 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
} }
/* Find probe points from debuginfo */ /* Find probe points from debuginfo */
static int find_probes(int fd, struct probe_finder *pf) static int debuginfo__find_probes(struct debuginfo *self,
struct probe_finder *pf)
{ {
struct perf_probe_point *pp = &pf->pev->point; struct perf_probe_point *pp = &pf->pev->point;
Dwarf_Off off, noff; Dwarf_Off off, noff;
size_t cuhl; size_t cuhl;
Dwarf_Die *diep; Dwarf_Die *diep;
Dwarf *dbg = NULL;
Dwfl *dwfl;
Dwarf_Addr bias; /* Currently ignored */
int ret = 0; int ret = 0;
dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
if (!dbg) {
pr_warning("No debug information found in the vmlinux - "
"please rebuild with CONFIG_DEBUG_INFO=y.\n");
close(fd); /* Without dwfl_end(), fd isn't closed. */
return -EBADF;
}
#if _ELFUTILS_PREREQ(0, 142) #if _ELFUTILS_PREREQ(0, 142)
/* Get the call frame information from this dwarf */ /* Get the call frame information from this dwarf */
pf->cfi = dwarf_getcfi(dbg); pf->cfi = dwarf_getcfi(self->dbg);
#endif #endif
off = 0; off = 0;
...@@ -989,7 +1016,8 @@ static int find_probes(int fd, struct probe_finder *pf) ...@@ -989,7 +1016,8 @@ static int find_probes(int fd, struct probe_finder *pf)
.data = pf, .data = pf,
}; };
dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0); dwarf_getpubnames(self->dbg, pubname_search_cb,
&pubname_param, 0);
if (pubname_param.found) { if (pubname_param.found) {
ret = probe_point_search_cb(&pf->sp_die, &probe_param); ret = probe_point_search_cb(&pf->sp_die, &probe_param);
if (ret) if (ret)
...@@ -998,9 +1026,9 @@ static int find_probes(int fd, struct probe_finder *pf) ...@@ -998,9 +1026,9 @@ static int find_probes(int fd, struct probe_finder *pf)
} }
/* Loop on CUs (Compilation Unit) */ /* Loop on CUs (Compilation Unit) */
while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { while (!dwarf_nextcu(self->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
/* Get the DIE(Debugging Information Entry) of this CU */ /* Get the DIE(Debugging Information Entry) of this CU */
diep = dwarf_offdie(dbg, off + cuhl, &pf->cu_die); diep = dwarf_offdie(self->dbg, off + cuhl, &pf->cu_die);
if (!diep) if (!diep)
continue; continue;
...@@ -1027,8 +1055,6 @@ static int find_probes(int fd, struct probe_finder *pf) ...@@ -1027,8 +1055,6 @@ static int find_probes(int fd, struct probe_finder *pf)
found: found:
line_list__free(&pf->lcache); line_list__free(&pf->lcache);
if (dwfl)
dwfl_end(dwfl);
return ret; return ret;
} }
...@@ -1074,8 +1100,9 @@ static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf) ...@@ -1074,8 +1100,9 @@ static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf)
} }
/* Find probe_trace_events specified by perf_probe_event from debuginfo */ /* Find probe_trace_events specified by perf_probe_event from debuginfo */
int find_probe_trace_events(int fd, struct perf_probe_event *pev, int debuginfo__find_trace_events(struct debuginfo *self,
struct probe_trace_event **tevs, int max_tevs) struct perf_probe_event *pev,
struct probe_trace_event **tevs, int max_tevs)
{ {
struct trace_event_finder tf = { struct trace_event_finder tf = {
.pf = {.pev = pev, .callback = add_probe_trace_event}, .pf = {.pev = pev, .callback = add_probe_trace_event},
...@@ -1090,7 +1117,7 @@ int find_probe_trace_events(int fd, struct perf_probe_event *pev, ...@@ -1090,7 +1117,7 @@ int find_probe_trace_events(int fd, struct perf_probe_event *pev,
tf.tevs = *tevs; tf.tevs = *tevs;
tf.ntevs = 0; tf.ntevs = 0;
ret = find_probes(fd, &tf.pf); ret = debuginfo__find_probes(self, &tf.pf);
if (ret < 0) { if (ret < 0) {
free(*tevs); free(*tevs);
*tevs = NULL; *tevs = NULL;
...@@ -1184,9 +1211,10 @@ static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf) ...@@ -1184,9 +1211,10 @@ static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf)
} }
/* Find available variables at given probe point */ /* Find available variables at given probe point */
int find_available_vars_at(int fd, struct perf_probe_event *pev, int debuginfo__find_available_vars_at(struct debuginfo *self,
struct variable_list **vls, int max_vls, struct perf_probe_event *pev,
bool externs) struct variable_list **vls,
int max_vls, bool externs)
{ {
struct available_var_finder af = { struct available_var_finder af = {
.pf = {.pev = pev, .callback = add_available_vars}, .pf = {.pev = pev, .callback = add_available_vars},
...@@ -1201,7 +1229,7 @@ int find_available_vars_at(int fd, struct perf_probe_event *pev, ...@@ -1201,7 +1229,7 @@ int find_available_vars_at(int fd, struct perf_probe_event *pev,
af.vls = *vls; af.vls = *vls;
af.nvls = 0; af.nvls = 0;
ret = find_probes(fd, &af.pf); ret = debuginfo__find_probes(self, &af.pf);
if (ret < 0) { if (ret < 0) {
/* Free vlist for error */ /* Free vlist for error */
while (af.nvls--) { while (af.nvls--) {
...@@ -1219,28 +1247,19 @@ int find_available_vars_at(int fd, struct perf_probe_event *pev, ...@@ -1219,28 +1247,19 @@ int find_available_vars_at(int fd, struct perf_probe_event *pev,
} }
/* Reverse search */ /* Reverse search */
int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt) int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr,
struct perf_probe_point *ppt)
{ {
Dwarf_Die cudie, spdie, indie; Dwarf_Die cudie, spdie, indie;
Dwarf *dbg = NULL; Dwarf_Addr _addr, baseaddr;
Dwfl *dwfl = NULL;
Dwarf_Addr _addr, baseaddr, bias = 0;
const char *fname = NULL, *func = NULL, *tmp; const char *fname = NULL, *func = NULL, *tmp;
int baseline = 0, lineno = 0, ret = 0; int baseline = 0, lineno = 0, ret = 0;
/* Open the live linux kernel */
dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias);
if (!dbg) {
pr_warning("No debug information found in the vmlinux - "
"please rebuild with CONFIG_DEBUG_INFO=y.\n");
ret = -EINVAL;
goto end;
}
/* Adjust address with bias */ /* Adjust address with bias */
addr += bias; addr += self->bias;
/* Find cu die */ /* Find cu die */
if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr - bias, &cudie)) { if (!dwarf_addrdie(self->dbg, (Dwarf_Addr)addr - self->bias, &cudie)) {
pr_warning("Failed to find debug information for address %lx\n", pr_warning("Failed to find debug information for address %lx\n",
addr); addr);
ret = -EINVAL; ret = -EINVAL;
...@@ -1316,8 +1335,6 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt) ...@@ -1316,8 +1335,6 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
} }
} }
end: end:
if (dwfl)
dwfl_end(dwfl);
if (ret == 0 && (fname || func)) if (ret == 0 && (fname || func))
ret = 1; /* Found a point */ ret = 1; /* Found a point */
return ret; return ret;
...@@ -1427,26 +1444,15 @@ static int find_line_range_by_func(struct line_finder *lf) ...@@ -1427,26 +1444,15 @@ static int find_line_range_by_func(struct line_finder *lf)
return param.retval; return param.retval;
} }
int find_line_range(int fd, struct line_range *lr) int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr)
{ {
struct line_finder lf = {.lr = lr, .found = 0}; struct line_finder lf = {.lr = lr, .found = 0};
int ret = 0; int ret = 0;
Dwarf_Off off = 0, noff; Dwarf_Off off = 0, noff;
size_t cuhl; size_t cuhl;
Dwarf_Die *diep; Dwarf_Die *diep;
Dwarf *dbg = NULL;
Dwfl *dwfl;
Dwarf_Addr bias; /* Currently ignored */
const char *comp_dir; const char *comp_dir;
dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
if (!dbg) {
pr_warning("No debug information found in the vmlinux - "
"please rebuild with CONFIG_DEBUG_INFO=y.\n");
close(fd); /* Without dwfl_end(), fd isn't closed. */
return -EBADF;
}
/* Fastpath: lookup by function name from .debug_pubnames section */ /* Fastpath: lookup by function name from .debug_pubnames section */
if (lr->function) { if (lr->function) {
struct pubname_callback_param pubname_param = { struct pubname_callback_param pubname_param = {
...@@ -1455,7 +1461,8 @@ int find_line_range(int fd, struct line_range *lr) ...@@ -1455,7 +1461,8 @@ int find_line_range(int fd, struct line_range *lr)
struct dwarf_callback_param line_range_param = { struct dwarf_callback_param line_range_param = {
.data = (void *)&lf, .retval = 0}; .data = (void *)&lf, .retval = 0};
dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0); dwarf_getpubnames(self->dbg, pubname_search_cb,
&pubname_param, 0);
if (pubname_param.found) { if (pubname_param.found) {
line_range_search_cb(&lf.sp_die, &line_range_param); line_range_search_cb(&lf.sp_die, &line_range_param);
if (lf.found) if (lf.found)
...@@ -1465,11 +1472,12 @@ int find_line_range(int fd, struct line_range *lr) ...@@ -1465,11 +1472,12 @@ int find_line_range(int fd, struct line_range *lr)
/* Loop on CUs (Compilation Unit) */ /* Loop on CUs (Compilation Unit) */
while (!lf.found && ret >= 0) { while (!lf.found && ret >= 0) {
if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0) if (dwarf_nextcu(self->dbg, off, &noff, &cuhl,
NULL, NULL, NULL) != 0)
break; break;
/* Get the DIE(Debugging Information Entry) of this CU */ /* Get the DIE(Debugging Information Entry) of this CU */
diep = dwarf_offdie(dbg, off + cuhl, &lf.cu_die); diep = dwarf_offdie(self->dbg, off + cuhl, &lf.cu_die);
if (!diep) if (!diep)
continue; continue;
...@@ -1503,7 +1511,6 @@ int find_line_range(int fd, struct line_range *lr) ...@@ -1503,7 +1511,6 @@ int find_line_range(int fd, struct line_range *lr)
} }
pr_debug("path: %s\n", lr->path); pr_debug("path: %s\n", lr->path);
dwfl_end(dwfl);
return (ret < 0) ? ret : lf.found; return (ret < 0) ? ret : lf.found;
} }
...@@ -16,23 +16,42 @@ static inline int is_c_varname(const char *name) ...@@ -16,23 +16,42 @@ static inline int is_c_varname(const char *name)
} }
#ifdef DWARF_SUPPORT #ifdef DWARF_SUPPORT
#include "dwarf-aux.h"
/* TODO: export debuginfo data structure even if no dwarf support */
/* debug information structure */
struct debuginfo {
Dwarf *dbg;
Dwfl *dwfl;
Dwarf_Addr bias;
};
extern struct debuginfo *debuginfo__new(const char *path);
extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr);
extern void debuginfo__delete(struct debuginfo *self);
/* Find probe_trace_events specified by perf_probe_event from debuginfo */ /* Find probe_trace_events specified by perf_probe_event from debuginfo */
extern int find_probe_trace_events(int fd, struct perf_probe_event *pev, extern int debuginfo__find_trace_events(struct debuginfo *self,
struct probe_trace_event **tevs, struct perf_probe_event *pev,
int max_tevs); struct probe_trace_event **tevs,
int max_tevs);
/* Find a perf_probe_point from debuginfo */ /* Find a perf_probe_point from debuginfo */
extern int find_perf_probe_point(unsigned long addr, extern int debuginfo__find_probe_point(struct debuginfo *self,
struct perf_probe_point *ppt); unsigned long addr,
struct perf_probe_point *ppt);
/* Find a line range */ /* Find a line range */
extern int find_line_range(int fd, struct line_range *lr); extern int debuginfo__find_line_range(struct debuginfo *self,
struct line_range *lr);
/* Find available variables */ /* Find available variables */
extern int find_available_vars_at(int fd, struct perf_probe_event *pev, extern int debuginfo__find_available_vars_at(struct debuginfo *self,
struct variable_list **vls, int max_points, struct perf_probe_event *pev,
bool externs); struct variable_list **vls,
#include "dwarf-aux.h" int max_points, bool externs);
struct probe_finder { struct probe_finder {
struct perf_probe_event *pev; /* Target probe event */ struct perf_probe_event *pev; /* Target probe event */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment