Merge branch 'perf' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
This commit is contained in:
@@ -62,6 +62,9 @@ OPTIONS
|
|||||||
Dry run. With this option, --add and --del doesn't execute actual
|
Dry run. With this option, --add and --del doesn't execute actual
|
||||||
adding and removal operations.
|
adding and removal operations.
|
||||||
|
|
||||||
|
--max-probes::
|
||||||
|
Set the maximum number of probe points for an event. Default is 128.
|
||||||
|
|
||||||
PROBE SYNTAX
|
PROBE SYNTAX
|
||||||
------------
|
------------
|
||||||
Probe points are defined by following syntax.
|
Probe points are defined by following syntax.
|
||||||
|
@@ -504,7 +504,7 @@ PERFLIBS = $(LIB_FILE)
|
|||||||
|
|
||||||
ifndef NO_DWARF
|
ifndef NO_DWARF
|
||||||
ifneq ($(shell sh -c "(echo '\#include <dwarf.h>'; echo '\#include <libdw.h>'; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
|
ifneq ($(shell sh -c "(echo '\#include <dwarf.h>'; echo '\#include <libdw.h>'; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
|
||||||
msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/elfutils-dev);
|
msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/libdw-dev);
|
||||||
NO_DWARF := 1
|
NO_DWARF := 1
|
||||||
endif # Dwarf support
|
endif # Dwarf support
|
||||||
endif # NO_DWARF
|
endif # NO_DWARF
|
||||||
|
@@ -54,6 +54,7 @@ static struct {
|
|||||||
struct perf_probe_event events[MAX_PROBES];
|
struct perf_probe_event events[MAX_PROBES];
|
||||||
struct strlist *dellist;
|
struct strlist *dellist;
|
||||||
struct line_range line_range;
|
struct line_range line_range;
|
||||||
|
int max_probe_points;
|
||||||
} params;
|
} params;
|
||||||
|
|
||||||
|
|
||||||
@@ -179,6 +180,8 @@ static const struct option options[] = {
|
|||||||
"file", "vmlinux pathname"),
|
"file", "vmlinux pathname"),
|
||||||
#endif
|
#endif
|
||||||
OPT__DRY_RUN(&probe_event_dry_run),
|
OPT__DRY_RUN(&probe_event_dry_run),
|
||||||
|
OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points,
|
||||||
|
"Set how many probe points can be found for a probe."),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -200,6 +203,9 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (params.max_probe_points == 0)
|
||||||
|
params.max_probe_points = MAX_PROBES;
|
||||||
|
|
||||||
if ((!params.nevents && !params.dellist && !params.list_events &&
|
if ((!params.nevents && !params.dellist && !params.list_events &&
|
||||||
!params.show_lines))
|
!params.show_lines))
|
||||||
usage_with_options(probe_usage, options);
|
usage_with_options(probe_usage, options);
|
||||||
@@ -246,7 +252,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
|
|||||||
|
|
||||||
if (params.nevents) {
|
if (params.nevents) {
|
||||||
ret = add_perf_probe_events(params.events, params.nevents,
|
ret = add_perf_probe_events(params.events, params.nevents,
|
||||||
params.force_add);
|
params.force_add,
|
||||||
|
params.max_probe_points);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
pr_err(" Error: Failed to add events. (%d)\n", ret);
|
pr_err(" Error: Failed to add events. (%d)\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
@@ -150,7 +150,8 @@ static int convert_to_perf_probe_point(struct kprobe_trace_point *tp,
|
|||||||
|
|
||||||
/* Try to find perf_probe_event with debuginfo */
|
/* Try to find perf_probe_event with debuginfo */
|
||||||
static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
|
static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
|
||||||
struct kprobe_trace_event **tevs)
|
struct kprobe_trace_event **tevs,
|
||||||
|
int max_tevs)
|
||||||
{
|
{
|
||||||
bool need_dwarf = perf_probe_event_need_dwarf(pev);
|
bool need_dwarf = perf_probe_event_need_dwarf(pev);
|
||||||
int fd, ntevs;
|
int fd, ntevs;
|
||||||
@@ -166,7 +167,7 @@ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Searching trace events corresponding to probe event */
|
/* Searching trace events corresponding to probe event */
|
||||||
ntevs = find_kprobe_trace_events(fd, pev, tevs);
|
ntevs = find_kprobe_trace_events(fd, pev, tevs, max_tevs);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
if (ntevs > 0) { /* Succeeded to find trace events */
|
if (ntevs > 0) { /* Succeeded to find trace events */
|
||||||
@@ -180,15 +181,16 @@ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
|
|||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
/* Error path : ntevs < 0 */
|
/* Error path : ntevs < 0 */
|
||||||
if (need_dwarf) {
|
pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
|
||||||
if (ntevs == -EBADF)
|
if (ntevs == -EBADF) {
|
||||||
pr_warning("No dwarf info found in the vmlinux - "
|
pr_warning("Warning: No dwarf info found in the vmlinux - "
|
||||||
"please rebuild with CONFIG_DEBUG_INFO=y.\n");
|
"please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
|
||||||
return ntevs;
|
if (!need_dwarf) {
|
||||||
|
pr_debug("Trying to use symbols.\nn");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pr_debug("An error occurred in debuginfo analysis."
|
return ntevs;
|
||||||
" Try to use symbols.\n");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LINEBUF_SIZE 256
|
#define LINEBUF_SIZE 256
|
||||||
@@ -317,7 +319,8 @@ static int convert_to_perf_probe_point(struct kprobe_trace_point *tp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
|
static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
|
||||||
struct kprobe_trace_event **tevs __unused)
|
struct kprobe_trace_event **tevs __unused,
|
||||||
|
int max_tevs __unused)
|
||||||
{
|
{
|
||||||
if (perf_probe_event_need_dwarf(pev)) {
|
if (perf_probe_event_need_dwarf(pev)) {
|
||||||
pr_warning("Debuginfo-analysis is not supported.\n");
|
pr_warning("Debuginfo-analysis is not supported.\n");
|
||||||
@@ -1407,14 +1410,15 @@ static int __add_kprobe_trace_events(struct perf_probe_event *pev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int convert_to_kprobe_trace_events(struct perf_probe_event *pev,
|
static int convert_to_kprobe_trace_events(struct perf_probe_event *pev,
|
||||||
struct kprobe_trace_event **tevs)
|
struct kprobe_trace_event **tevs,
|
||||||
|
int max_tevs)
|
||||||
{
|
{
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
int ret = 0, i;
|
int ret = 0, i;
|
||||||
struct kprobe_trace_event *tev;
|
struct kprobe_trace_event *tev;
|
||||||
|
|
||||||
/* Convert perf_probe_event with debuginfo */
|
/* Convert perf_probe_event with debuginfo */
|
||||||
ret = try_to_find_kprobe_trace_events(pev, tevs);
|
ret = try_to_find_kprobe_trace_events(pev, tevs, max_tevs);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@@ -1486,7 +1490,7 @@ struct __event_package {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
|
int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
|
||||||
bool force_add)
|
bool force_add, int max_tevs)
|
||||||
{
|
{
|
||||||
int i, j, ret;
|
int i, j, ret;
|
||||||
struct __event_package *pkgs;
|
struct __event_package *pkgs;
|
||||||
@@ -1505,7 +1509,7 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
|
|||||||
pkgs[i].pev = &pevs[i];
|
pkgs[i].pev = &pevs[i];
|
||||||
/* Convert with or without debuginfo */
|
/* Convert with or without debuginfo */
|
||||||
ret = convert_to_kprobe_trace_events(pkgs[i].pev,
|
ret = convert_to_kprobe_trace_events(pkgs[i].pev,
|
||||||
&pkgs[i].tevs);
|
&pkgs[i].tevs, max_tevs);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto end;
|
goto end;
|
||||||
pkgs[i].ntevs = ret;
|
pkgs[i].ntevs = ret;
|
||||||
|
@@ -115,8 +115,8 @@ extern void clear_kprobe_trace_event(struct kprobe_trace_event *tev);
|
|||||||
extern int parse_line_range_desc(const char *cmd, struct line_range *lr);
|
extern int parse_line_range_desc(const char *cmd, struct line_range *lr);
|
||||||
|
|
||||||
|
|
||||||
extern int add_perf_probe_events(struct perf_probe_event *pevs, int ntevs,
|
extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
|
||||||
bool force_add);
|
bool force_add, int max_probe_points);
|
||||||
extern int del_perf_probe_events(struct strlist *dellist);
|
extern int del_perf_probe_events(struct strlist *dellist);
|
||||||
extern int show_perf_probe_events(void);
|
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);
|
||||||
|
@@ -626,8 +626,9 @@ static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
|
|||||||
Dwarf_Attribute fb_attr;
|
Dwarf_Attribute fb_attr;
|
||||||
size_t nops;
|
size_t nops;
|
||||||
|
|
||||||
if (pf->ntevs == MAX_PROBES) {
|
if (pf->ntevs == pf->max_tevs) {
|
||||||
pr_warning("Too many( > %d) probe point found.\n", MAX_PROBES);
|
pr_warning("Too many( > %d) probe point found.\n",
|
||||||
|
pf->max_tevs);
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
}
|
}
|
||||||
tev = &pf->tevs[pf->ntevs++];
|
tev = &pf->tevs[pf->ntevs++];
|
||||||
@@ -871,6 +872,8 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
|
|||||||
(uintmax_t)pf->addr);
|
(uintmax_t)pf->addr);
|
||||||
|
|
||||||
param->retval = convert_probe_point(in_die, pf);
|
param->retval = convert_probe_point(in_die, pf);
|
||||||
|
if (param->retval < 0)
|
||||||
|
return DWARF_CB_ABORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DWARF_CB_OK;
|
return DWARF_CB_OK;
|
||||||
@@ -930,9 +933,9 @@ static int find_probe_point_by_func(struct probe_finder *pf)
|
|||||||
|
|
||||||
/* Find kprobe_trace_events specified by perf_probe_event from debuginfo */
|
/* Find kprobe_trace_events specified by perf_probe_event from debuginfo */
|
||||||
int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
|
int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
|
||||||
struct kprobe_trace_event **tevs)
|
struct kprobe_trace_event **tevs, int max_tevs)
|
||||||
{
|
{
|
||||||
struct probe_finder pf = {.pev = pev};
|
struct probe_finder pf = {.pev = pev, .max_tevs = max_tevs};
|
||||||
struct perf_probe_point *pp = &pev->point;
|
struct perf_probe_point *pp = &pev->point;
|
||||||
Dwarf_Off off, noff;
|
Dwarf_Off off, noff;
|
||||||
size_t cuhl;
|
size_t cuhl;
|
||||||
@@ -940,7 +943,7 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
|
|||||||
Dwarf *dbg;
|
Dwarf *dbg;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
pf.tevs = zalloc(sizeof(struct kprobe_trace_event) * MAX_PROBES);
|
pf.tevs = zalloc(sizeof(struct kprobe_trace_event) * max_tevs);
|
||||||
if (pf.tevs == NULL)
|
if (pf.tevs == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
*tevs = pf.tevs;
|
*tevs = pf.tevs;
|
||||||
@@ -1106,6 +1109,8 @@ static int line_range_funcdecl_cb(Dwarf_Die *sp_die, void *data)
|
|||||||
return DWARF_CB_OK;
|
return DWARF_CB_OK;
|
||||||
|
|
||||||
param->retval = line_range_add_line(src, lineno, lf->lr);
|
param->retval = line_range_add_line(src, lineno, lf->lr);
|
||||||
|
if (param->retval < 0)
|
||||||
|
return DWARF_CB_ABORT;
|
||||||
return DWARF_CB_OK;
|
return DWARF_CB_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,7 +18,8 @@ static inline int is_c_varname(const char *name)
|
|||||||
#ifdef DWARF_SUPPORT
|
#ifdef DWARF_SUPPORT
|
||||||
/* Find kprobe_trace_events specified by perf_probe_event from debuginfo */
|
/* Find kprobe_trace_events specified by perf_probe_event from debuginfo */
|
||||||
extern int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
|
extern int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
|
||||||
struct kprobe_trace_event **tevs);
|
struct kprobe_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(int fd, unsigned long addr,
|
extern int find_perf_probe_point(int fd, unsigned long addr,
|
||||||
@@ -32,7 +33,8 @@ extern int find_line_range(int fd, struct line_range *lr);
|
|||||||
struct probe_finder {
|
struct probe_finder {
|
||||||
struct perf_probe_event *pev; /* Target probe event */
|
struct perf_probe_event *pev; /* Target probe event */
|
||||||
struct kprobe_trace_event *tevs; /* Result trace events */
|
struct kprobe_trace_event *tevs; /* Result trace events */
|
||||||
int ntevs; /* number of trace events */
|
int ntevs; /* Number of trace events */
|
||||||
|
int max_tevs; /* Max number of trace events */
|
||||||
|
|
||||||
/* For function searching */
|
/* For function searching */
|
||||||
int lno; /* Line number */
|
int lno; /* Line number */
|
||||||
|
@@ -189,6 +189,7 @@ struct dso *dso__new(const char *name)
|
|||||||
self->sorted_by_name = 0;
|
self->sorted_by_name = 0;
|
||||||
self->has_build_id = 0;
|
self->has_build_id = 0;
|
||||||
self->kernel = DSO_TYPE_USER;
|
self->kernel = DSO_TYPE_USER;
|
||||||
|
INIT_LIST_HEAD(&self->node);
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
Reference in New Issue
Block a user