You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/urgent
This commit is contained in:
@@ -16,7 +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' [options] --vars='PROBEPOINT'
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -31,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.
|
||||
@@ -57,6 +64,15 @@ OPTIONS
|
||||
Show source code lines which can be probed. This needs an argument
|
||||
which specifies a range of the source code. (see LINE SYNTAX for detail)
|
||||
|
||||
-V::
|
||||
--vars=::
|
||||
Show available local variables at given probe point. The argument
|
||||
syntax is same as PROBE SYNTAX, but NO ARGs.
|
||||
|
||||
--externs::
|
||||
(Only for --vars) Show external defined variables in addition to local
|
||||
variables.
|
||||
|
||||
-f::
|
||||
--force::
|
||||
Forcibly add events with existing name.
|
||||
|
||||
+67
-11
@@ -50,14 +50,17 @@ static struct {
|
||||
bool list_events;
|
||||
bool force_add;
|
||||
bool show_lines;
|
||||
bool show_vars;
|
||||
bool show_ext_vars;
|
||||
bool mod_events;
|
||||
int nevents;
|
||||
struct perf_probe_event events[MAX_PROBES];
|
||||
struct strlist *dellist;
|
||||
struct line_range line_range;
|
||||
const char *target_module;
|
||||
int max_probe_points;
|
||||
} params;
|
||||
|
||||
|
||||
/* Parse an event definition. Note that any error must die. */
|
||||
static int parse_probe_event(const char *str)
|
||||
{
|
||||
@@ -92,6 +95,7 @@ static int parse_probe_event_argv(int argc, const char **argv)
|
||||
len = 0;
|
||||
for (i = 0; i < argc; i++)
|
||||
len += sprintf(&buf[len], "%s ", argv[i]);
|
||||
params.mod_events = true;
|
||||
ret = parse_probe_event(buf);
|
||||
free(buf);
|
||||
return ret;
|
||||
@@ -100,9 +104,10 @@ static int parse_probe_event_argv(int argc, const char **argv)
|
||||
static int opt_add_probe_event(const struct option *opt __used,
|
||||
const char *str, int unset __used)
|
||||
{
|
||||
if (str)
|
||||
if (str) {
|
||||
params.mod_events = true;
|
||||
return parse_probe_event(str);
|
||||
else
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -110,6 +115,7 @@ static int opt_del_probe_event(const struct option *opt __used,
|
||||
const char *str, int unset __used)
|
||||
{
|
||||
if (str) {
|
||||
params.mod_events = true;
|
||||
if (!params.dellist)
|
||||
params.dellist = strlist__new(true, NULL);
|
||||
strlist__add(params.dellist, str);
|
||||
@@ -130,6 +136,25 @@ static int opt_show_lines(const struct option *opt __used,
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int opt_show_vars(const struct option *opt __used,
|
||||
const char *str, int unset __used)
|
||||
{
|
||||
struct perf_probe_event *pev = ¶ms.events[params.nevents];
|
||||
int ret;
|
||||
|
||||
if (!str)
|
||||
return 0;
|
||||
|
||||
ret = parse_probe_event(str);
|
||||
if (!ret && pev->nargs != 0) {
|
||||
pr_err(" Error: '--vars' doesn't accept arguments.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
params.show_vars = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char * const probe_usage[] = {
|
||||
@@ -138,7 +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 [<options>] --line 'LINEDESC'",
|
||||
"perf probe [<options>] --vars 'PROBEPOINT'",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
@@ -180,10 +206,17 @@ static const struct option options[] = {
|
||||
OPT_CALLBACK('L', "line", NULL,
|
||||
"FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]",
|
||||
"Show source code lines.", opt_show_lines),
|
||||
OPT_CALLBACK('V', "vars", NULL,
|
||||
"FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT",
|
||||
"Show accessible variables on PROBEDEF", opt_show_vars),
|
||||
OPT_BOOLEAN('\0', "externs", ¶ms.show_ext_vars,
|
||||
"Show external variables too (with --vars only)"),
|
||||
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
|
||||
"file", "vmlinux pathname"),
|
||||
OPT_STRING('s', "source", &symbol_conf.source_prefix,
|
||||
"directory", "path to kernel source"),
|
||||
OPT_STRING('m', "module", ¶ms.target_module,
|
||||
"modname", "target module name"),
|
||||
#endif
|
||||
OPT__DRY_RUN(&probe_event_dry_run),
|
||||
OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points,
|
||||
@@ -217,7 +250,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
|
||||
usage_with_options(probe_usage, options);
|
||||
|
||||
if (params.list_events) {
|
||||
if (params.nevents != 0 || params.dellist) {
|
||||
if (params.mod_events) {
|
||||
pr_err(" Error: Don't use --list with --add/--del.\n");
|
||||
usage_with_options(probe_usage, options);
|
||||
}
|
||||
@@ -225,6 +258,10 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
|
||||
pr_err(" Error: Don't use --list with --line.\n");
|
||||
usage_with_options(probe_usage, options);
|
||||
}
|
||||
if (params.show_vars) {
|
||||
pr_err(" Error: Don't use --list with --vars.\n");
|
||||
usage_with_options(probe_usage, options);
|
||||
}
|
||||
ret = show_perf_probe_events();
|
||||
if (ret < 0)
|
||||
pr_err(" Error: Failed to show event list. (%d)\n",
|
||||
@@ -234,17 +271,35 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
|
||||
|
||||
#ifdef DWARF_SUPPORT
|
||||
if (params.show_lines) {
|
||||
if (params.nevents != 0 || params.dellist) {
|
||||
pr_warning(" Error: Don't use --line with"
|
||||
" --add/--del.\n");
|
||||
if (params.mod_events) {
|
||||
pr_err(" Error: Don't use --line with"
|
||||
" --add/--del.\n");
|
||||
usage_with_options(probe_usage, options);
|
||||
}
|
||||
if (params.show_vars) {
|
||||
pr_err(" Error: Don't use --line with --vars.\n");
|
||||
usage_with_options(probe_usage, options);
|
||||
}
|
||||
|
||||
ret = show_line_range(¶ms.line_range);
|
||||
ret = show_line_range(¶ms.line_range, params.target_module);
|
||||
if (ret < 0)
|
||||
pr_err(" Error: Failed to show lines. (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (params.show_vars) {
|
||||
if (params.mod_events) {
|
||||
pr_err(" Error: Don't use --vars with"
|
||||
" --add/--del.\n");
|
||||
usage_with_options(probe_usage, options);
|
||||
}
|
||||
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);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (params.dellist) {
|
||||
@@ -258,8 +313,9 @@ 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.force_add,
|
||||
params.max_probe_points);
|
||||
params.max_probe_points,
|
||||
params.target_module,
|
||||
params.force_add);
|
||||
if (ret < 0) {
|
||||
pr_err(" Error: Failed to add events. (%d)\n", ret);
|
||||
return ret;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+149
-42
@@ -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;
|
||||
@@ -91,33 +90,61 @@ 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;
|
||||
}
|
||||
|
||||
#ifdef DWARF_SUPPORT
|
||||
static int open_vmlinux(void)
|
||||
static struct symbol *__find_kernel_function_by_name(const char *name,
|
||||
struct map **mapp)
|
||||
{
|
||||
if (map__load(machine.vmlinux_maps[MAP__FUNCTION], NULL) < 0) {
|
||||
pr_debug("Failed to load kernel map.\n");
|
||||
return -EINVAL;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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);
|
||||
found:
|
||||
return dso->long_name;
|
||||
}
|
||||
|
||||
#ifdef DWARF_SUPPORT
|
||||
static int open_vmlinux(const char *module)
|
||||
{
|
||||
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", path);
|
||||
return open(path, O_RDONLY);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -125,20 +152,19 @@ static int open_vmlinux(void)
|
||||
* 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 "
|
||||
@@ -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");
|
||||
@@ -300,7 +326,7 @@ error:
|
||||
* 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;
|
||||
@@ -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;
|
||||
@@ -378,11 +404,84 @@ end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int show_available_vars_at(int fd, struct perf_probe_event *pev,
|
||||
int max_vls, bool externs)
|
||||
{
|
||||
char *buf;
|
||||
int ret, i;
|
||||
struct str_node *node;
|
||||
struct variable_list *vls = NULL, *vl;
|
||||
|
||||
buf = synthesize_perf_probe_point(&pev->point);
|
||||
if (!buf)
|
||||
return -EINVAL;
|
||||
pr_debug("Searching variables at %s\n", buf);
|
||||
|
||||
ret = find_available_vars_at(fd, pev, &vls, max_vls, externs);
|
||||
if (ret > 0) {
|
||||
/* Some variables were found */
|
||||
fprintf(stdout, "Available variables at %s\n", buf);
|
||||
for (i = 0; i < ret; i++) {
|
||||
vl = &vls[i];
|
||||
/*
|
||||
* A probe point might be converted to
|
||||
* several trace points.
|
||||
*/
|
||||
fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol,
|
||||
vl->point.offset);
|
||||
free(vl->point.symbol);
|
||||
if (vl->vars) {
|
||||
strlist__for_each(node, vl->vars)
|
||||
fprintf(stdout, "\t\t%s\n", node->s);
|
||||
strlist__delete(vl->vars);
|
||||
} else
|
||||
fprintf(stdout, "(No variables)\n");
|
||||
}
|
||||
free(vls);
|
||||
} else
|
||||
pr_err("Failed to find variables at %s (%d)\n", buf, ret);
|
||||
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Show available variables on given probe point */
|
||||
int show_available_vars(struct perf_probe_event *pevs, int npevs,
|
||||
int max_vls, const char *module, bool externs)
|
||||
{
|
||||
int i, fd, ret = 0;
|
||||
|
||||
ret = init_vmlinux();
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
fd = open_vmlinux(module);
|
||||
if (fd < 0) {
|
||||
pr_warning("Failed to open debuginfo file.\n");
|
||||
return fd;
|
||||
}
|
||||
|
||||
setup_pager();
|
||||
|
||||
for (i = 0; i < npevs && ret >= 0; i++)
|
||||
ret = show_available_vars_at(fd, &pevs[i], max_vls, externs);
|
||||
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#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;
|
||||
@@ -394,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");
|
||||
@@ -403,12 +502,19 @@ 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_vls __unused,
|
||||
const char *module __unused, bool externs __unused)
|
||||
{
|
||||
pr_warning("Debuginfo-analysis is not supported.\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif
|
||||
|
||||
int parse_line_range_desc(const char *arg, struct line_range *lr)
|
||||
@@ -1087,7 +1193,7 @@ error:
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -1516,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;
|
||||
|
||||
@@ -1572,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);
|
||||
@@ -1596,7 +1701,7 @@ struct __event_package {
|
||||
};
|
||||
|
||||
int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
|
||||
bool force_add, int max_tevs)
|
||||
int max_tevs, const char *module, bool force_add)
|
||||
{
|
||||
int i, j, ret;
|
||||
struct __event_package *pkgs;
|
||||
@@ -1617,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;
|
||||
|
||||
@@ -90,6 +90,12 @@ struct line_range {
|
||||
struct list_head line_list; /* Visible lines */
|
||||
};
|
||||
|
||||
/* List of variables */
|
||||
struct variable_list {
|
||||
struct probe_trace_point point; /* Actual probepoint */
|
||||
struct strlist *vars; /* Available variables */
|
||||
};
|
||||
|
||||
/* Command string to events */
|
||||
extern int parse_perf_probe_command(const char *cmd,
|
||||
struct perf_probe_event *pev);
|
||||
@@ -109,12 +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,
|
||||
bool force_add, int max_probe_points);
|
||||
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, const char *module,
|
||||
bool externs);
|
||||
|
||||
|
||||
/* Maximum index number of event-name postfix */
|
||||
|
||||
+510
-134
File diff suppressed because it is too large
Load Diff
@@ -22,20 +22,27 @@ extern int find_probe_trace_events(int fd, struct perf_probe_event *pev,
|
||||
int max_tevs);
|
||||
|
||||
/* Find a perf_probe_point from debuginfo */
|
||||
extern int find_perf_probe_point(int fd, unsigned long addr,
|
||||
extern int find_perf_probe_point(unsigned long addr,
|
||||
struct perf_probe_point *ppt);
|
||||
|
||||
/* Find a line range */
|
||||
extern int find_line_range(int fd, struct line_range *lr);
|
||||
|
||||
/* Find available variables */
|
||||
extern int find_available_vars_at(int fd, struct perf_probe_event *pev,
|
||||
struct variable_list **vls, int max_points,
|
||||
bool externs);
|
||||
|
||||
#include <dwarf.h>
|
||||
#include <libdw.h>
|
||||
#include <libdwfl.h>
|
||||
#include <version.h>
|
||||
|
||||
struct probe_finder {
|
||||
struct perf_probe_event *pev; /* Target probe event */
|
||||
struct probe_trace_event *tevs; /* Result trace events */
|
||||
int ntevs; /* Number of trace events */
|
||||
int max_tevs; /* Max number of trace events */
|
||||
|
||||
/* Callback when a probe point is found */
|
||||
int (*callback)(Dwarf_Die *sp_die, struct probe_finder *pf);
|
||||
|
||||
/* For function searching */
|
||||
int lno; /* Line number */
|
||||
@@ -53,6 +60,22 @@ struct probe_finder {
|
||||
struct probe_trace_arg *tvar; /* Current result variable */
|
||||
};
|
||||
|
||||
struct trace_event_finder {
|
||||
struct probe_finder pf;
|
||||
struct probe_trace_event *tevs; /* Found trace events */
|
||||
int ntevs; /* Number of trace events */
|
||||
int max_tevs; /* Max number of trace events */
|
||||
};
|
||||
|
||||
struct available_var_finder {
|
||||
struct probe_finder pf;
|
||||
struct variable_list *vls; /* Found variable lists */
|
||||
int nvls; /* Number of variable lists */
|
||||
int max_vls; /* Max no. of variable lists */
|
||||
bool externs; /* Find external vars too */
|
||||
bool child; /* Search child scopes */
|
||||
};
|
||||
|
||||
struct line_finder {
|
||||
struct line_range *lr; /* Target line range */
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include <slang.h>
|
||||
#include "libslang.h"
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
Reference in New Issue
Block a user