Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 218647
b: refs/heads/master
c: 469b9b8
h: refs/heads/master
i:
  218645: f7bc65a
  218643: 6e71073
  218639: 9e358ef
v: v3
  • Loading branch information
Masami Hiramatsu authored and Arnaldo Carvalho de Melo committed Oct 21, 2010
1 parent 6d3ad52 commit 01ea0a5
Show file tree
Hide file tree
Showing 8 changed files with 240 additions and 70 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: fb8c5a56c7ddbc2b0d2ee7a8da60fe1355f75141
refs/heads/master: 469b9b88488e89114bb3e9ac5ee7906b7b96123f
9 changes: 7 additions & 2 deletions trunk/tools/perf/Documentation/perf-probe.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ or
or
'perf probe' --list
or
'perf probe' --line='FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]'
'perf probe' [options] --line='FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]'
or
'perf probe' [--externs] --vars='PROBEPOINT'
'perf probe' [options] --vars='PROBEPOINT'

DESCRIPTION
-----------
Expand All @@ -33,6 +33,11 @@ OPTIONS
--vmlinux=PATH::
Specify vmlinux path which has debuginfo (Dwarf binary).

-m::
--module=MODNAME::
Specify module name in which perf-probe searches probe points
or lines.

-s::
--source=PATH::
Specify path to kernel source.
Expand Down
11 changes: 8 additions & 3 deletions trunk/tools/perf/builtin-probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ static struct {
struct perf_probe_event events[MAX_PROBES];
struct strlist *dellist;
struct line_range line_range;
const char *target_module;
int max_probe_points;
} params;

Expand Down Expand Up @@ -162,8 +163,8 @@ static const char * const probe_usage[] = {
"perf probe [<options>] --del '[GROUP:]EVENT' ...",
"perf probe --list",
#ifdef DWARF_SUPPORT
"perf probe --line 'LINEDESC'",
"perf probe [--externs] --vars 'PROBEPOINT'",
"perf probe [<options>] --line 'LINEDESC'",
"perf probe [<options>] --vars 'PROBEPOINT'",
#endif
NULL
};
Expand Down Expand Up @@ -214,6 +215,8 @@ static const struct option options[] = {
"file", "vmlinux pathname"),
OPT_STRING('s', "source", &symbol_conf.source_prefix,
"directory", "path to kernel source"),
OPT_STRING('m', "module", &params.target_module,
"modname", "target module name"),
#endif
OPT__DRY_RUN(&probe_event_dry_run),
OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
Expand Down Expand Up @@ -278,7 +281,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
usage_with_options(probe_usage, options);
}

ret = show_line_range(&params.line_range);
ret = show_line_range(&params.line_range, params.target_module);
if (ret < 0)
pr_err(" Error: Failed to show lines. (%d)\n", ret);
return ret;
Expand All @@ -291,6 +294,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
}
ret = show_available_vars(params.events, params.nevents,
params.max_probe_points,
params.target_module,
params.show_ext_vars);
if (ret < 0)
pr_err(" Error: Failed to show vars. (%d)\n", ret);
Expand All @@ -310,6 +314,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
if (params.nevents) {
ret = add_perf_probe_events(params.events, params.nevents,
params.max_probe_points,
params.target_module,
params.force_add);
if (ret < 0) {
pr_err(" Error: Failed to add events. (%d)\n", ret);
Expand Down
10 changes: 10 additions & 0 deletions trunk/tools/perf/util/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,16 @@ struct symbol *map_groups__find_function_by_name(struct map_groups *self,
return map_groups__find_symbol_by_name(self, MAP__FUNCTION, name, mapp, filter);
}

static inline
struct symbol *machine__find_kernel_function_by_name(struct machine *self,
const char *name,
struct map **mapp,
symbol_filter_t filter)
{
return map_groups__find_function_by_name(&self->kmaps, name, mapp,
filter);
}

int map_groups__fixup_overlappings(struct map_groups *self, struct map *map,
int verbose, FILE *fp);

Expand Down
123 changes: 79 additions & 44 deletions trunk/tools/perf/util/probe-event.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,9 @@ static int e_snprintf(char *str, size_t size, const char *format, ...)
static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
static struct machine machine;

/* Initialize symbol maps and path of vmlinux */
/* Initialize symbol maps and path of vmlinux/modules */
static int init_vmlinux(void)
{
struct dso *kernel;
int ret;

symbol_conf.sort_by_name = true;
Expand All @@ -91,54 +90,81 @@ static int init_vmlinux(void)
goto out;
}

ret = machine__init(&machine, "/", 0);
ret = machine__init(&machine, "", HOST_KERNEL_ID);
if (ret < 0)
goto out;

kernel = dso__new_kernel(symbol_conf.vmlinux_name);
if (kernel == NULL)
die("Failed to create kernel dso.");

ret = __machine__create_kernel_maps(&machine, kernel);
if (ret < 0)
pr_debug("Failed to create kernel maps.\n");

if (machine__create_kernel_maps(&machine) < 0) {
pr_debug("machine__create_kernel_maps ");
goto out;
}
out:
if (ret < 0)
pr_warning("Failed to init vmlinux path.\n");
return ret;
}

static struct symbol *__find_kernel_function_by_name(const char *name,
struct map **mapp)
{
return machine__find_kernel_function_by_name(&machine, name, mapp,
NULL);
}

const char *kernel_get_module_path(const char *module)
{
struct dso *dso;

if (module) {
list_for_each_entry(dso, &machine.kernel_dsos, node) {
if (strncmp(dso->short_name + 1, module,
dso->short_name_len - 2) == 0)
goto found;
}
pr_debug("Failed to find module %s.\n", module);
return NULL;
} else {
dso = machine.vmlinux_maps[MAP__FUNCTION]->dso;
if (dso__load_vmlinux_path(dso,
machine.vmlinux_maps[MAP__FUNCTION], NULL) < 0) {
pr_debug("Failed to load kernel map.\n");
return NULL;
}
}
found:
return dso->long_name;
}

#ifdef DWARF_SUPPORT
static int open_vmlinux(void)
static int open_vmlinux(const char *module)
{
if (map__load(machine.vmlinux_maps[MAP__FUNCTION], NULL) < 0) {
pr_debug("Failed to load kernel map.\n");
return -EINVAL;
const char *path = kernel_get_module_path(module);
if (!path) {
pr_err("Failed to find path of %s module", module ?: "kernel");
return -ENOENT;
}
pr_debug("Try to open %s\n", machine.vmlinux_maps[MAP__FUNCTION]->dso->long_name);
return open(machine.vmlinux_maps[MAP__FUNCTION]->dso->long_name, O_RDONLY);
pr_debug("Try to open %s\n", path);
return open(path, O_RDONLY);
}

/*
* Convert trace point to probe point with debuginfo
* Currently only handles kprobes.
*/
static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
struct perf_probe_point *pp)
struct perf_probe_point *pp)
{
struct symbol *sym;
int fd, ret = -ENOENT;
struct map *map;
u64 addr;
int ret = -ENOENT;

sym = map__find_symbol_by_name(machine.vmlinux_maps[MAP__FUNCTION],
tp->symbol, NULL);
sym = __find_kernel_function_by_name(tp->symbol, &map);
if (sym) {
fd = open_vmlinux();
if (fd >= 0) {
ret = find_perf_probe_point(fd,
sym->start + tp->offset, pp);
close(fd);
}
addr = map->unmap_ip(map, sym->start + tp->offset);
pr_debug("try to find %s+%ld@%llx\n", tp->symbol,
tp->offset, addr);
ret = find_perf_probe_point((unsigned long)addr, pp);
}
if (ret <= 0) {
pr_debug("Failed to find corresponding probes from "
Expand All @@ -156,12 +182,12 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
/* Try to find perf_probe_event with debuginfo */
static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
struct probe_trace_event **tevs,
int max_tevs)
int max_tevs, const char *module)
{
bool need_dwarf = perf_probe_event_need_dwarf(pev);
int fd, ntevs;

fd = open_vmlinux();
fd = open_vmlinux(module);
if (fd < 0) {
if (need_dwarf) {
pr_warning("Failed to open debuginfo file.\n");
Expand Down Expand Up @@ -300,7 +326,7 @@ static int show_one_line(FILE *fp, int l, bool skip, bool show_num)
* Show line-range always requires debuginfo to find source file and
* line number.
*/
int show_line_range(struct line_range *lr)
int show_line_range(struct line_range *lr, const char *module)
{
int l = 1;
struct line_node *ln;
Expand All @@ -313,7 +339,7 @@ int show_line_range(struct line_range *lr)
if (ret < 0)
return ret;

fd = open_vmlinux();
fd = open_vmlinux(module);
if (fd < 0) {
pr_warning("Failed to open debuginfo file.\n");
return fd;
Expand Down Expand Up @@ -421,15 +447,15 @@ static int show_available_vars_at(int fd, struct perf_probe_event *pev,

/* Show available variables on given probe point */
int show_available_vars(struct perf_probe_event *pevs, int npevs,
int max_vls, bool externs)
int max_vls, const char *module, bool externs)
{
int i, fd, ret = 0;

ret = init_vmlinux();
if (ret < 0)
return ret;

fd = open_vmlinux();
fd = open_vmlinux(module);
if (fd < 0) {
pr_warning("Failed to open debuginfo file.\n");
return fd;
Expand All @@ -447,8 +473,15 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
#else /* !DWARF_SUPPORT */

static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
struct perf_probe_point *pp)
struct perf_probe_point *pp)
{
struct symbol *sym;

sym = __find_kernel_function_by_name(tp->symbol, NULL);
if (!sym) {
pr_err("Failed to find symbol %s in kernel.\n", tp->symbol);
return -ENOENT;
}
pp->function = strdup(tp->symbol);
if (pp->function == NULL)
return -ENOMEM;
Expand All @@ -460,7 +493,7 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,

static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
struct probe_trace_event **tevs __unused,
int max_tevs __unused)
int max_tevs __unused, const char *mod __unused)
{
if (perf_probe_event_need_dwarf(pev)) {
pr_warning("Debuginfo-analysis is not supported.\n");
Expand All @@ -469,14 +502,15 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
return 0;
}

int show_line_range(struct line_range *lr __unused)
int show_line_range(struct line_range *lr __unused, const char *module __unused)
{
pr_warning("Debuginfo-analysis is not supported.\n");
return -ENOSYS;
}

int show_available_vars(struct perf_probe_event *pevs __unused,
int npevs __unused, int max_probe_points __unused)
int npevs __unused, int max_vls __unused,
const char *module __unused, bool externs __unused)
{
pr_warning("Debuginfo-analysis is not supported.\n");
return -ENOSYS;
Expand Down Expand Up @@ -1159,7 +1193,7 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
}

static int convert_to_perf_probe_event(struct probe_trace_event *tev,
struct perf_probe_event *pev)
struct perf_probe_event *pev)
{
char buf[64] = "";
int i, ret;
Expand Down Expand Up @@ -1588,14 +1622,14 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,

static int convert_to_probe_trace_events(struct perf_probe_event *pev,
struct probe_trace_event **tevs,
int max_tevs)
int max_tevs, const char *module)
{
struct symbol *sym;
int ret = 0, i;
struct probe_trace_event *tev;

/* Convert perf_probe_event with debuginfo */
ret = try_to_find_probe_trace_events(pev, tevs, max_tevs);
ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, module);
if (ret != 0)
return ret;

Expand Down Expand Up @@ -1644,8 +1678,7 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
}

/* Currently just checking function name from symbol map */
sym = map__find_symbol_by_name(machine.vmlinux_maps[MAP__FUNCTION],
tev->point.symbol, NULL);
sym = __find_kernel_function_by_name(tev->point.symbol, NULL);
if (!sym) {
pr_warning("Kernel symbol \'%s\' not found.\n",
tev->point.symbol);
Expand All @@ -1668,7 +1701,7 @@ struct __event_package {
};

int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
int max_tevs, bool force_add)
int max_tevs, const char *module, bool force_add)
{
int i, j, ret;
struct __event_package *pkgs;
Expand All @@ -1689,7 +1722,9 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
pkgs[i].pev = &pevs[i];
/* Convert with or without debuginfo */
ret = convert_to_probe_trace_events(pkgs[i].pev,
&pkgs[i].tevs, max_tevs);
&pkgs[i].tevs,
max_tevs,
module);
if (ret < 0)
goto end;
pkgs[i].ntevs = ret;
Expand Down
10 changes: 7 additions & 3 deletions trunk/tools/perf/util/probe-event.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,18 @@ extern void clear_perf_probe_event(struct perf_probe_event *pev);
/* Command string to line-range */
extern int parse_line_range_desc(const char *cmd, struct line_range *lr);

/* Internal use: Return kernel/module path */
extern const char *kernel_get_module_path(const char *module);

extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
int max_probe_points, bool force_add);
int max_probe_points, const char *module,
bool force_add);
extern int del_perf_probe_events(struct strlist *dellist);
extern int show_perf_probe_events(void);
extern int show_line_range(struct line_range *lr);
extern int show_line_range(struct line_range *lr, const char *module);
extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
int max_probe_points, bool externs);
int max_probe_points, const char *module,
bool externs);


/* Maximum index number of event-name postfix */
Expand Down
Loading

0 comments on commit 01ea0a5

Please sign in to comment.