You can subscribe to this list here.
| 2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(32) |
Jun
(66) |
Jul
(102) |
Aug
(78) |
Sep
(106) |
Oct
(137) |
Nov
(147) |
Dec
(147) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2010 |
Jan
(71) |
Feb
(139) |
Mar
(86) |
Apr
(76) |
May
(57) |
Jun
(10) |
Jul
(12) |
Aug
(6) |
Sep
(8) |
Oct
(12) |
Nov
(12) |
Dec
(18) |
| 2011 |
Jan
(16) |
Feb
(19) |
Mar
(3) |
Apr
(1) |
May
(16) |
Jun
(17) |
Jul
(74) |
Aug
(22) |
Sep
(18) |
Oct
(24) |
Nov
(21) |
Dec
(30) |
| 2012 |
Jan
(31) |
Feb
(16) |
Mar
(22) |
Apr
(25) |
May
(18) |
Jun
(13) |
Jul
(83) |
Aug
(49) |
Sep
(20) |
Oct
(60) |
Nov
(35) |
Dec
(28) |
| 2013 |
Jan
(39) |
Feb
(61) |
Mar
(35) |
Apr
(21) |
May
(45) |
Jun
(56) |
Jul
(20) |
Aug
(9) |
Sep
(10) |
Oct
(31) |
Nov
(8) |
Dec
(4) |
| 2014 |
Jan
(6) |
Feb
(7) |
Mar
(7) |
Apr
(6) |
May
(4) |
Jun
(8) |
Jul
(5) |
Aug
(2) |
Sep
(4) |
Oct
(4) |
Nov
(11) |
Dec
(5) |
| 2015 |
Jan
(4) |
Feb
(4) |
Mar
(3) |
Apr
(4) |
May
(9) |
Jun
(4) |
Jul
(15) |
Aug
(8) |
Sep
(16) |
Oct
(18) |
Nov
(15) |
Dec
(7) |
| 2016 |
Jan
(20) |
Feb
(9) |
Mar
(15) |
Apr
(24) |
May
(16) |
Jun
(28) |
Jul
(22) |
Aug
(23) |
Sep
(18) |
Oct
(30) |
Nov
(40) |
Dec
(9) |
| 2017 |
Jan
(1) |
Feb
(8) |
Mar
(37) |
Apr
(26) |
May
(25) |
Jun
(46) |
Jul
(24) |
Aug
(9) |
Sep
|
Oct
|
Nov
|
Dec
|
|
From: Masami H. <mhi...@re...> - 2009-10-17 00:07:55
|
Replace debug() macro with eprintf() and add -v option for showing
those messages in perf-probe.
Signed-off-by: Masami Hiramatsu <mhi...@re...>
Cc: Frederic Weisbecker <fwe...@gm...>
Cc: Ingo Molnar <mi...@el...>
Cc: Thomas Gleixner <tg...@li...>
Cc: Arnaldo Carvalho de Melo <ac...@re...>
Cc: Steven Rostedt <ro...@go...>
Cc: Mike Galbraith <ef...@gm...>
Cc: Paul Mackerras <pa...@sa...>
Cc: Peter Zijlstra <a.p...@ch...>
Cc: Christoph Hellwig <hc...@in...>
Cc: Ananth N Mavinakayanahalli <an...@in...>
Cc: Jim Keniston <jke...@us...>
Cc: Frank Ch. Eigler <fc...@re...>
---
tools/perf/builtin-probe.c | 23 ++++++++++++++---------
tools/perf/util/probe-finder.c | 12 +++++++-----
tools/perf/util/probe-finder.h | 7 -------
3 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index a1467d1..b5ad86a 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -35,6 +35,8 @@
#include "perf.h"
#include "builtin.h"
#include "util/util.h"
+#include "util/event.h"
+#include "util/debug.h"
#include "util/parse-options.h"
#include "util/parse-events.h" /* For debugfs_path */
#include "util/probe-finder.h"
@@ -76,7 +78,7 @@ static int parse_probepoint(const struct option *opt __used,
if (!str) /* The end of probe points */
return 0;
- debug("Probe-define(%d): %s\n", session.nr_probe, str);
+ eprintf("probe-definition(%d): %s\n", session.nr_probe, str);
if (++session.nr_probe == MAX_PROBES)
semantic_error("Too many probes");
@@ -101,7 +103,7 @@ static int parse_probepoint(const struct option *opt __used,
die("strndup");
if (++argc == MAX_PROBE_ARGS)
semantic_error("Too many arguments");
- debug("argv[%d]=%s\n", argc, argv[argc - 1]);
+ eprintf("argv[%d]=%s\n", argc, argv[argc - 1]);
}
} while (*str != '\0');
if (argc < 2)
@@ -131,7 +133,7 @@ static int parse_probepoint(const struct option *opt __used,
pp->line = atoi(ptr);
if (!pp->file || !pp->line)
semantic_error("Failed to parse line.");
- debug("file:%s line:%d\n", pp->file, pp->line);
+ eprintf("file:%s line:%d\n", pp->file, pp->line);
} else {
/* Function name */
ptr = strchr(arg, '+');
@@ -148,7 +150,7 @@ static int parse_probepoint(const struct option *opt __used,
pp->file = strdup(ptr);
}
pp->function = strdup(arg);
- debug("symbol:%s file:%s offset:%d\n",
+ eprintf("symbol:%s file:%s offset:%d\n",
pp->function, pp->file, pp->offset);
}
free(argv[1]);
@@ -173,7 +175,7 @@ static int parse_probepoint(const struct option *opt __used,
session.need_dwarf = 1;
}
- debug("%d arguments\n", pp->nr_args);
+ eprintf("%d arguments\n", pp->nr_args);
return 0;
}
@@ -186,7 +188,7 @@ static int open_default_vmlinux(void)
ret = uname(&uts);
if (ret) {
- debug("uname() failed.\n");
+ eprintf("uname() failed.\n");
return -errno;
}
session.release = uts.release;
@@ -194,11 +196,12 @@ static int open_default_vmlinux(void)
ret = snprintf(fname, MAX_PATH_LEN,
default_search_path[i], session.release);
if (ret >= MAX_PATH_LEN || ret < 0) {
- debug("Filename(%d,%s) is too long.\n", i, uts.release);
+ eprintf("Filename(%d,%s) is too long.\n", i,
+ uts.release);
errno = E2BIG;
return -E2BIG;
}
- debug("try to open %s\n", fname);
+ eprintf("try to open %s\n", fname);
fd = open(fname, O_RDONLY);
if (fd >= 0)
break;
@@ -213,6 +216,8 @@ static const char * const probe_usage[] = {
};
static const struct option options[] = {
+ OPT_BOOLEAN('v', "verbose", &verbose,
+ "be more verbose (show parsed arguments, etc)"),
#ifndef NO_LIBDWARF
OPT_STRING('k', "vmlinux", &session.vmlinux, "file",
"vmlinux/module pathname"),
@@ -336,7 +341,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
ret = find_probepoint(fd, pp);
if (ret <= 0)
die("No probe point found.\n");
- debug("probe event %s found\n", session.events[j]);
+ eprintf("probe event %s found\n", session.events[j]);
}
close(fd);
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 338fdb9..db24c91 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -32,6 +32,8 @@
#include <stdarg.h>
#include <ctype.h>
+#include "event.h"
+#include "debug.h"
#include "util.h"
#include "probe-finder.h"
@@ -134,7 +136,7 @@ static Dwarf_Unsigned die_get_fileno(Dwarf_Die cu_die, const char *fname)
dwarf_dealloc(__dw_debug, srcs, DW_DLA_LIST);
}
if (found)
- debug("found fno: %d\n", (int)found);
+ eprintf("found fno: %d\n", (int)found);
return found;
}
@@ -440,7 +442,7 @@ static void find_variable(Dwarf_Die sp_die, struct probe_finder *pf)
return ;
}
- debug("Searching '%s' variable in context.\n", pf->var);
+ eprintf("Searching '%s' variable in context.\n", pf->var);
/* Search child die for local variables and parameters. */
ret = search_die_from_children(sp_die, variable_callback, pf);
if (!ret)
@@ -550,7 +552,7 @@ static void find_by_line(Dwarf_Die cu_die, struct probe_finder *pf)
ret = dwarf_lineaddr(lines[i], &addr, &__dw_error);
ERR_IF(ret != DW_DLV_OK);
- debug("Probe point found: 0x%llx\n", addr);
+ eprintf("Probe point found: 0x%llx\n", addr);
pf->addr = addr;
/* Search a real subprogram including this line, */
ret = search_die_from_children(cu_die, probeaddr_callback, pf);
@@ -581,7 +583,7 @@ static int probefunc_callback(struct die_link *dlink, void *data)
&pf->inl_offs,
&__dw_error);
ERR_IF(ret != DW_DLV_OK);
- debug("inline definition offset %lld\n",
+ eprintf("inline definition offset %lld\n",
pf->inl_offs);
return 0;
}
@@ -597,7 +599,7 @@ static int probefunc_callback(struct die_link *dlink, void *data)
/* Get probe address */
pf->addr = die_get_entrypc(dlink->die);
pf->addr += pp->offset;
- debug("found inline addr: 0x%llx\n", pf->addr);
+ eprintf("found inline addr: 0x%llx\n", pf->addr);
/* Inlined function. Get a real subprogram */
for (lk = dlink->parent; lk != NULL; lk = lk->parent) {
tag = 0;
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 306810c..6a7cb0c 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -4,13 +4,6 @@
#define _stringify(n) #n
#define stringify(n) _stringify(n)
-#ifdef DEBUG
-#define debug(fmt ...) \
- fprintf(stderr, "DBG(" __FILE__ ":" stringify(__LINE__) "): " fmt)
-#else
-#define debug(fmt ...) do {} while (0)
-#endif
-
#define ERR_IF(cnd) \
do { if (cnd) { \
fprintf(stderr, "Error (" __FILE__ ":" stringify(__LINE__) \
--
Masami Hiramatsu
Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division
e-mail: mhi...@re...
|
|
From: Masami H. <mhi...@re...> - 2009-10-17 00:07:49
|
Use die() for exiting perf-probe with errors. This replaces
perror_exit(), msg_exit() and fprintf()+exit() with die(), and
uses die() in semantic_error().
This also renames 'die' local variables to 'dw_die' for avoiding
name confliction.
Signed-off-by: Masami Hiramatsu <mhi...@re...>
Cc: Frederic Weisbecker <fwe...@gm...>
Cc: Ingo Molnar <mi...@el...>
Cc: Thomas Gleixner <tg...@li...>
Cc: Arnaldo Carvalho de Melo <ac...@re...>
Cc: Steven Rostedt <ro...@go...>
Cc: Mike Galbraith <ef...@gm...>
Cc: Paul Mackerras <pa...@sa...>
Cc: Peter Zijlstra <a.p...@ch...>
Cc: Christoph Hellwig <hc...@in...>
Cc: Ananth N Mavinakayanahalli <an...@in...>
Cc: Jim Keniston <jke...@us...>
Cc: Frank Ch. Eigler <fc...@re...>
---
tools/perf/builtin-probe.c | 47 ++++++++++------------------------
tools/perf/util/probe-finder.c | 55 +++++++++++++++-------------------------
2 files changed, 34 insertions(+), 68 deletions(-)
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 73c883b..a1467d1 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -49,6 +49,7 @@ const char *default_search_path[NR_SEARCH_PATH] = {
#define MAX_PATH_LEN 256
#define MAX_PROBES 128
+#define MAX_PROBE_ARGS 128
/* Session management structure */
static struct {
@@ -60,19 +61,7 @@ static struct {
char *events[MAX_PROBES];
} session;
-static void semantic_error(const char *msg)
-{
- fprintf(stderr, "Semantic error: %s\n", msg);
- exit(1);
-}
-
-static void perror_exit(const char *msg)
-{
- perror(msg);
- exit(1);
-}
-
-#define MAX_PROBE_ARGS 128
+#define semantic_error(msg ...) die("Semantic error :" msg)
static int parse_probepoint(const struct option *opt __used,
const char *str, int unset __used)
@@ -109,7 +98,7 @@ static int parse_probepoint(const struct option *opt __used,
/* Duplicate the argument */
argv[argc] = strndup(s, str - s);
if (argv[argc] == NULL)
- perror_exit("strndup");
+ die("strndup");
if (++argc == MAX_PROBE_ARGS)
semantic_error("Too many arguments");
debug("argv[%d]=%s\n", argc, argv[argc - 1]);
@@ -171,7 +160,7 @@ static int parse_probepoint(const struct option *opt __used,
if (pp->nr_args > 0) {
pp->args = (char **)malloc(sizeof(char *) * pp->nr_args);
if (!pp->args)
- perror_exit("malloc");
+ die("malloc");
memcpy(pp->args, &argv[2], sizeof(char *) * pp->nr_args);
}
@@ -260,7 +249,7 @@ static int write_new_event(int fd, const char *buf)
printf("Adding new event: %s\n", buf);
ret = write(fd, buf, strlen(buf));
if (ret <= 0)
- perror("Error: Failed to create event");
+ die("failed to create event.");
return ret;
}
@@ -273,7 +262,7 @@ static int synthesize_probepoint(struct probe_point *pp)
int i, len, ret;
pp->probes[0] = buf = (char *)calloc(MAX_CMDLEN, sizeof(char));
if (!buf)
- perror_exit("calloc");
+ die("calloc");
ret = snprintf(buf, MAX_CMDLEN, "%s+%d", pp->function, pp->offset);
if (ret <= 0 || ret >= MAX_CMDLEN)
goto error;
@@ -322,10 +311,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
ret = synthesize_probepoint(&session.probes[j]);
if (ret == -E2BIG)
semantic_error("probe point is too long.");
- else if (ret < 0) {
- perror("snprintf");
- return -1;
- }
+ else if (ret < 0)
+ die("snprintf");
}
#ifndef NO_LIBDWARF
@@ -336,10 +323,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
fd = open(session.vmlinux, O_RDONLY);
else
fd = open_default_vmlinux();
- if (fd < 0) {
- perror("vmlinux/module file open");
- return -1;
- }
+ if (fd < 0)
+ die("vmlinux/module file open");
/* Searching probe points */
for (j = 0; j < session.nr_probe; j++) {
@@ -349,10 +334,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
lseek(fd, SEEK_SET, 0);
ret = find_probepoint(fd, pp);
- if (ret <= 0) {
- fprintf(stderr, "Error: No probe point found.\n");
- return -1;
- }
+ if (ret <= 0)
+ die("No probe point found.\n");
debug("probe event %s found\n", session.events[j]);
}
close(fd);
@@ -363,10 +346,8 @@ setup_probes:
/* Settng up probe points */
snprintf(buf, MAX_CMDLEN, "%s/../kprobe_events", debugfs_path);
fd = open(buf, O_WRONLY, O_APPEND);
- if (fd < 0) {
- perror("kprobe_events open");
- return -1;
- }
+ if (fd < 0)
+ die("kprobe_events open");
for (j = 0; j < session.nr_probe; j++) {
pp = &session.probes[j];
if (pp->found == 1) {
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index ec6f53f..338fdb9 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -31,6 +31,8 @@
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
+
+#include "util.h"
#include "probe-finder.h"
@@ -43,20 +45,6 @@ struct die_link {
static Dwarf_Debug __dw_debug;
static Dwarf_Error __dw_error;
-static void msg_exit(int ret, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- fprintf(stderr, "Error: ");
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-
- fprintf(stderr, "\n");
- exit(ret);
-}
-
-
/*
* Generic dwarf analysis helpers
*/
@@ -151,11 +139,11 @@ static Dwarf_Unsigned die_get_fileno(Dwarf_Die cu_die, const char *fname)
}
/* Compare diename and tname */
-static int die_compare_name(Dwarf_Die die, const char *tname)
+static int die_compare_name(Dwarf_Die dw_die, const char *tname)
{
char *name;
int ret;
- ret = dwarf_diename(die, &name, &__dw_error);
+ ret = dwarf_diename(dw_die, &name, &__dw_error);
ERR_IF(ret == DW_DLV_ERROR);
if (ret == DW_DLV_OK) {
ret = strcmp(tname, name);
@@ -187,25 +175,25 @@ static int die_within_subprogram(Dwarf_Die sp_die, Dwarf_Addr addr,
}
/* Check the die is inlined function */
-static Dwarf_Bool die_inlined_subprogram(Dwarf_Die die)
+static Dwarf_Bool die_inlined_subprogram(Dwarf_Die dw_die)
{
/* TODO: check strictly */
Dwarf_Bool inl;
int ret;
- ret = dwarf_hasattr(die, DW_AT_inline, &inl, &__dw_error);
+ ret = dwarf_hasattr(dw_die, DW_AT_inline, &inl, &__dw_error);
ERR_IF(ret == DW_DLV_ERROR);
return inl;
}
/* Get the offset of abstruct_origin */
-static Dwarf_Off die_get_abstract_origin(Dwarf_Die die)
+static Dwarf_Off die_get_abstract_origin(Dwarf_Die dw_die)
{
Dwarf_Attribute attr;
Dwarf_Off cu_offs;
int ret;
- ret = dwarf_attr(die, DW_AT_abstract_origin, &attr, &__dw_error);
+ ret = dwarf_attr(dw_die, DW_AT_abstract_origin, &attr, &__dw_error);
ERR_IF(ret != DW_DLV_OK);
ret = dwarf_formref(attr, &cu_offs, &__dw_error);
ERR_IF(ret != DW_DLV_OK);
@@ -214,7 +202,7 @@ static Dwarf_Off die_get_abstract_origin(Dwarf_Die die)
}
/* Get entry pc(or low pc, 1st entry of ranges) of the die */
-static Dwarf_Addr die_get_entrypc(Dwarf_Die die)
+static Dwarf_Addr die_get_entrypc(Dwarf_Die dw_die)
{
Dwarf_Attribute attr;
Dwarf_Addr addr;
@@ -224,7 +212,7 @@ static Dwarf_Addr die_get_entrypc(Dwarf_Die die)
int ret;
/* Try to get entry pc */
- ret = dwarf_attr(die, DW_AT_entry_pc, &attr, &__dw_error);
+ ret = dwarf_attr(dw_die, DW_AT_entry_pc, &attr, &__dw_error);
ERR_IF(ret == DW_DLV_ERROR);
if (ret == DW_DLV_OK) {
ret = dwarf_formaddr(attr, &addr, &__dw_error);
@@ -234,13 +222,13 @@ static Dwarf_Addr die_get_entrypc(Dwarf_Die die)
}
/* Try to get low pc */
- ret = dwarf_lowpc(die, &addr, &__dw_error);
+ ret = dwarf_lowpc(dw_die, &addr, &__dw_error);
ERR_IF(ret == DW_DLV_ERROR);
if (ret == DW_DLV_OK)
return addr;
/* Try to get ranges */
- ret = dwarf_attr(die, DW_AT_ranges, &attr, &__dw_error);
+ ret = dwarf_attr(dw_die, DW_AT_ranges, &attr, &__dw_error);
ERR_IF(ret != DW_DLV_OK);
ret = dwarf_formref(attr, &offs, &__dw_error);
ERR_IF(ret != DW_DLV_OK);
@@ -382,11 +370,11 @@ static void show_location(Dwarf_Loc *loc, struct probe_finder *pf)
} else if (op == DW_OP_regx) {
regn = loc->lr_number;
} else
- msg_exit(-EINVAL, "Dwarf_OP %d is not supported.\n", op);
+ die("Dwarf_OP %d is not supported.\n", op);
regs = get_arch_regstr(regn);
if (!regs)
- msg_exit(-EINVAL, "%lld exceeds max register number.\n", regn);
+ die("%lld exceeds max register number.\n", regn);
if (deref)
ret = snprintf(pf->buf, pf->len,
@@ -417,8 +405,8 @@ static void show_variable(Dwarf_Die vr_die, struct probe_finder *pf)
dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
return ;
error:
- msg_exit(-1, "Failed to find the location of %s at this address.\n"
- " Perhaps, it was optimized out.\n", pf->var);
+ die("Failed to find the location of %s at this address.\n"
+ " Perhaps, it has been optimized out.\n", pf->var);
}
static int variable_callback(struct die_link *dlink, void *data)
@@ -456,8 +444,7 @@ static void find_variable(Dwarf_Die sp_die, struct probe_finder *pf)
/* Search child die for local variables and parameters. */
ret = search_die_from_children(sp_die, variable_callback, pf);
if (!ret)
- msg_exit(-1, "Failed to find '%s' in this function.\n",
- pf->var);
+ die("Failed to find '%s' in this function.\n", pf->var);
}
/* Get a frame base on the address */
@@ -568,8 +555,7 @@ static void find_by_line(Dwarf_Die cu_die, struct probe_finder *pf)
/* Search a real subprogram including this line, */
ret = search_die_from_children(cu_die, probeaddr_callback, pf);
if (ret == 0)
- msg_exit(-1,
- "Probe point is not found in subprograms.\n");
+ die("Probe point is not found in subprograms.\n");
/* Continuing, because target line might be inlined. */
}
dwarf_srclines_dealloc(__dw_debug, lines, cnt);
@@ -621,7 +607,7 @@ static int probefunc_callback(struct die_link *dlink, void *data)
!die_inlined_subprogram(lk->die))
goto found;
}
- msg_exit(-1, "Failed to find real subprogram.\n");
+ die("Failed to find real subprogram.\n");
found:
/* Get offset from subprogram */
ret = die_within_subprogram(lk->die, pf->addr, &offs);
@@ -649,8 +635,7 @@ int find_probepoint(int fd, struct probe_point *pp)
ret = dwarf_init(fd, DW_DLC_READ, 0, 0, &__dw_debug, &__dw_error);
if (ret != DW_DLV_OK)
- msg_exit(-1, "Failed to call dwarf_init(). "
- "Maybe, not a dwarf file?\n");
+ die("Failed to call dwarf_init(). Maybe, not a dwarf file.\n");
pp->found = 0;
while (++cu_number) {
--
Masami Hiramatsu
Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division
e-mail: mhi...@re...
|
|
From: Masami H. <mhi...@re...> - 2009-10-17 00:07:38
|
Check libdwarf APIs for perf probe in tools/perf/Makefile. Since
dwarf_get_ranges() has been added from libdwarf 20081231 (and it's
the newest function used in probe-finder.c), this just checks
whether the function is defined.
Signed-off-by: Masami Hiramatsu <mhi...@re...>
Cc: Frederic Weisbecker <fwe...@gm...>
Cc: Ingo Molnar <mi...@el...>
Cc: Thomas Gleixner <tg...@li...>
Cc: Arnaldo Carvalho de Melo <ac...@re...>
Cc: Steven Rostedt <ro...@go...>
Cc: Mike Galbraith <ef...@gm...>
Cc: Paul Mackerras <pa...@sa...>
Cc: Peter Zijlstra <a.p...@ch...>
Cc: Christoph Hellwig <hc...@in...>
Cc: Ananth N Mavinakayanahalli <an...@in...>
Cc: Jim Keniston <jke...@us...>
Cc: Frank Ch. Eigler <fc...@re...>
-
---
tools/perf/Makefile | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 52b1f43..03c27b9 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -420,8 +420,8 @@ ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf *
msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel);
endif
-ifneq ($(shell sh -c "(echo '\#include <libdwarf/dwarf.h>'; echo '\#include <libdwarf/libdwarf.h>'; echo 'int main(void) { Dwarf_Debug dbg; Dwarf_Error err; dwarf_init(0, DW_DLC_READ, 0, 0, &dbg, &err); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -ldwarf -lelf -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y)
- msg := $(warning No libdwarf.h found, disables dwarf support. Please install libdwarf-dev/libdwarf-devel);
+ifneq ($(shell sh -c "(echo '\#include <libdwarf/dwarf.h>'; echo '\#include <libdwarf/libdwarf.h>'; echo 'int main(void) { Dwarf_Debug dbg; Dwarf_Error err; Dwarf_Ranges *rng; dwarf_init(0, DW_DLC_READ, 0, 0, &dbg, &err); dwarf_get_ranges(dbg, 0, &rng, 0, 0, &err); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -ldwarf -lelf -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y)
+ msg := $(warning No libdwarf.h found or old libdwarf.h found, disables dwarf support. Please install libdwarf-dev/libdwarf-devel >= 20081231);
BASIC_CFLAGS += -DNO_LIBDWARF
else
EXTLIBS += -lelf -ldwarf
--
Masami Hiramatsu
Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division
e-mail: mhi...@re...
|
|
From: Masami H. <mhi...@re...> - 2009-10-17 00:07:19
|
Add AMD prefetch and 3DNow! opcode including FEMMS. Since 3DNow! uses the last immediate byte as an opcode extension byte, x86 insn just treats the extenstion byte as an immediate byte instead of a part of opcode (insn_get_opcode() decodes first "0x0f 0x0f" bytes.) Users who are interested in analyzing 3DNow! opcode still can decode it by analyzing the immediate byte. Signed-off-by: Masami Hiramatsu <mhi...@re...> Cc: H. Peter Anvin <hp...@zy...> Cc: Frederic Weisbecker <fwe...@gm...> Cc: Ingo Molnar <mi...@el...> Cc: Thomas Gleixner <tg...@li...> Cc: Arnaldo Carvalho de Melo <ac...@re...> Cc: Steven Rostedt <ro...@go...> Cc: Mike Galbraith <ef...@gm...> Cc: Paul Mackerras <pa...@sa...> Cc: Peter Zijlstra <a.p...@ch...> Cc: Christoph Hellwig <hc...@in...> Cc: Ananth N Mavinakayanahalli <an...@in...> Cc: Jim Keniston <jke...@us...> Cc: Frank Ch. Eigler <fc...@re...> --- arch/x86/lib/x86-opcode-map.txt | 13 ++++++++++--- 1 files changed, 10 insertions(+), 3 deletions(-) diff --git a/arch/x86/lib/x86-opcode-map.txt b/arch/x86/lib/x86-opcode-map.txt index e7285d8..894497f 100644 --- a/arch/x86/lib/x86-opcode-map.txt +++ b/arch/x86/lib/x86-opcode-map.txt @@ -306,9 +306,10 @@ Referrer: 2-byte escape 0a: 0b: UD2 (1B) 0c: -0d: NOP Ev -0e: -0f: +0d: NOP Ev | GrpP +0e: FEMMS +# 3DNow! uses the last imm byte as opcode extension. +0f: 3DNow! Pq,Qq,Ib # 0x0f 0x10-0x1f 10: movups Vps,Wps | movss Vss,Wss (F3) | movupd Vpd,Wpd (66) | movsd Vsd,Wsd (F2) 11: movups Wps,Vps | movss Wss,Vss (F3) | movupd Wpd,Vpd (66) | movsd Wsd,Vsd (F2) @@ -813,6 +814,12 @@ GrpTable: Grp16 3: prefetch T2 EndTable +# AMD's Prefetch Group +GrpTable: GrpP +0: PREFETCH +1: PREFETCHW +EndTable + GrpTable: GrpPDLK 0: MONTMUL 1: XSHA1 -- Masami Hiramatsu Software Engineer Hitachi Computer Products (America), Inc. Software Solutions Division e-mail: mhi...@re... |
|
From: Masami H. <mhi...@re...> - 2009-10-17 00:07:19
|
Add missing MMX/SSE opcode groups to x86 opcode map. Signed-off-by: Masami Hiramatsu <mhi...@re...> Cc: H. Peter Anvin <hp...@zy...> Cc: Frederic Weisbecker <fwe...@gm...> Cc: Ingo Molnar <mi...@el...> Cc: Thomas Gleixner <tg...@li...> Cc: Arnaldo Carvalho de Melo <ac...@re...> Cc: Steven Rostedt <ro...@go...> Cc: Mike Galbraith <ef...@gm...> Cc: Paul Mackerras <pa...@sa...> Cc: Peter Zijlstra <a.p...@ch...> Cc: Christoph Hellwig <hc...@in...> Cc: Ananth N Mavinakayanahalli <an...@in...> Cc: Jim Keniston <jke...@us...> Cc: Frank Ch. Eigler <fc...@re...> --- arch/x86/lib/x86-opcode-map.txt | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/arch/x86/lib/x86-opcode-map.txt b/arch/x86/lib/x86-opcode-map.txt index 78a0daf..e7285d8 100644 --- a/arch/x86/lib/x86-opcode-map.txt +++ b/arch/x86/lib/x86-opcode-map.txt @@ -777,12 +777,22 @@ GrpTable: Grp11 EndTable GrpTable: Grp12 +2: psrlw Nq,Ib (11B) | psrlw Udq,Ib (66),(11B) +4: psraw Nq,Ib (11B) | psraw Udq,Ib (66),(11B) +6: psllw Nq,Ib (11B) | psllw Udq,Ib (66),(11B) EndTable GrpTable: Grp13 +2: psrld Nq,Ib (11B) | psrld Udq,Ib (66),(11B) +4: psrad Nq,Ib (11B) | psrad Udq,Ib (66),(11B) +6: pslld Nq,Ib (11B) | pslld Udq,Ib (66),(11B) EndTable GrpTable: Grp14 +2: psrlq Nq,Ib (11B) | psrlq Udq,Ib (66),(11B) +3: psrldq Udq,Ib (66),(11B) +6: psllq Nq,Ib (11B) | psllq Udq,Ib (66),(11B) +7: pslldq Udq,Ib (66),(11B) EndTable GrpTable: Grp15 -- Masami Hiramatsu Software Engineer Hitachi Computer Products (America), Inc. Software Solutions Division e-mail: mhi...@re... |
|
From: Masami H. <mhi...@re...> - 2009-10-17 00:07:13
|
Add vorbose failure messages to kprobe-tracer for debugging.
Signed-off-by: Masami Hiramatsu <mhi...@re...>
Cc: Frederic Weisbecker <fwe...@gm...>
Cc: Ingo Molnar <mi...@el...>
Cc: Thomas Gleixner <tg...@li...>
Cc: Arnaldo Carvalho de Melo <ac...@re...>
Cc: Steven Rostedt <ro...@go...>
Cc: Mike Galbraith <ef...@gm...>
Cc: Paul Mackerras <pa...@sa...>
Cc: Peter Zijlstra <a.p...@ch...>
Cc: Christoph Hellwig <hc...@in...>
Cc: Ananth N Mavinakayanahalli <an...@in...>
Cc: Jim Keniston <jke...@us...>
Cc: Frank Ch. Eigler <fc...@re...>
-
---
kernel/trace/trace_kprobe.c | 35 +++++++++++++++++++++++++++--------
1 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index cdacdab..b8ef707 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -597,15 +597,19 @@ static int create_trace_probe(int argc, char **argv)
void *addr = NULL;
char buf[MAX_EVENT_NAME_LEN];
- if (argc < 2)
+ if (argc < 2) {
+ pr_info("Probe point is not specified.\n");
return -EINVAL;
+ }
if (argv[0][0] == 'p')
is_return = 0;
else if (argv[0][0] == 'r')
is_return = 1;
- else
+ else {
+ pr_info("Probe definition must be started with 'p' or 'r'.\n");
return -EINVAL;
+ }
if (argv[0][1] == ':') {
event = &argv[0][2];
@@ -625,21 +629,29 @@ static int create_trace_probe(int argc, char **argv)
}
if (isdigit(argv[1][0])) {
- if (is_return)
+ if (is_return) {
+ pr_info("Return probe point must be a symbol.\n");
return -EINVAL;
+ }
/* an address specified */
ret = strict_strtoul(&argv[0][2], 0, (unsigned long *)&addr);
- if (ret)
+ if (ret) {
+ pr_info("Failed to parse address.\n");
return ret;
+ }
} else {
/* a symbol specified */
symbol = argv[1];
/* TODO: support .init module functions */
ret = split_symbol_offset(symbol, &offset);
- if (ret)
+ if (ret) {
+ pr_info("Failed to parse symbol.\n");
return ret;
- if (offset && is_return)
+ }
+ if (offset && is_return) {
+ pr_info("Return probe must be used without offset.\n");
return -EINVAL;
+ }
}
argc -= 2; argv += 2;
@@ -658,8 +670,11 @@ static int create_trace_probe(int argc, char **argv)
}
tp = alloc_trace_probe(group, event, addr, symbol, offset, argc,
is_return);
- if (IS_ERR(tp))
+ if (IS_ERR(tp)) {
+ pr_info("Failed to allocate trace_probe.(%d)\n",
+ (int)PTR_ERR(tp));
return PTR_ERR(tp);
+ }
/* parse arguments */
ret = 0;
@@ -672,6 +687,8 @@ static int create_trace_probe(int argc, char **argv)
arg = argv[i];
if (conflict_field_name(argv[i], tp->args, i)) {
+ pr_info("Argument%d name '%s' conflicts with "
+ "another field.\n", i, argv[i]);
ret = -EINVAL;
goto error;
}
@@ -685,8 +702,10 @@ static int create_trace_probe(int argc, char **argv)
goto error;
}
ret = parse_probe_arg(arg, &tp->args[i].fetch, is_return);
- if (ret)
+ if (ret) {
+ pr_info("Parse error at argument%d. (%d)\n", i, ret);
goto error;
+ }
}
tp->nr_args = i;
--
Masami Hiramatsu
Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division
e-mail: mhi...@re...
|
|
From: Masami H. <mhi...@re...> - 2009-10-17 00:07:02
|
Hi Ingo and Frederic,
Here are the bugfix and update (mostly cleanup) patches for
previous patchset.
> I hope it's part of the last family of instruction set we
> are missing.
I added missing SSE opcodes and 3DNow! support too.
However, near future, x86 decoder may need AVX support.
(AFAIK, currently, there are no code using it.)
Thank you,
---
Masami Hiramatsu (9):
perf: Add perf-probe document
perf: Add DIE_IF() macro for error checking
perf: Use eprintf() for debug messages in perf-probe
perf: Use die() for error cases in perf-probe
perf: Check libdwarf APIs for perf probe
x86: Add AMD prefetch and 3DNow! opcodes to opcode map
x86: Add MMX/SSE opcode groups to opcode map
tracing/kprobes: Add failure messages for debugging
tracing/kprobes: Update kprobe-tracer selftest against new syntax
arch/x86/lib/x86-opcode-map.txt | 23 ++++-
kernel/trace/trace_kprobe.c | 39 ++++++--
tools/perf/Documentation/perf-probe.txt | 48 ++++++++++
tools/perf/Makefile | 5 +
tools/perf/builtin-probe.c | 70 ++++++---------
tools/perf/command-list.txt | 1
tools/perf/util/probe-finder.c | 149 ++++++++++++++-----------------
tools/perf/util/probe-finder.h | 17 ----
tools/perf/util/util.h | 9 ++
9 files changed, 206 insertions(+), 155 deletions(-)
create mode 100644 tools/perf/Documentation/perf-probe.txt
--
Masami Hiramatsu
Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division
e-mail: mhi...@re...
|
|
From: Masami H. <mhi...@re...> - 2009-10-17 00:07:01
|
Update kprobe-tracer selftest since command syntax has been changed.
Signed-off-by: Masami Hiramatsu <mhi...@re...>
Cc: Frederic Weisbecker <fwe...@gm...>
Cc: Ingo Molnar <mi...@el...>
Cc: Thomas Gleixner <tg...@li...>
Cc: Arnaldo Carvalho de Melo <ac...@re...>
Cc: Steven Rostedt <ro...@go...>
Cc: Mike Galbraith <ef...@gm...>
Cc: Paul Mackerras <pa...@sa...>
Cc: Peter Zijlstra <a.p...@ch...>
Cc: Christoph Hellwig <hc...@in...>
Cc: Ananth N Mavinakayanahalli <an...@in...>
Cc: Jim Keniston <jke...@us...>
Cc: Frank Ch. Eigler <fc...@re...>
-
---
kernel/trace/trace_kprobe.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 739f70e..cdacdab 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -1438,12 +1438,12 @@ static __init int kprobe_trace_self_tests_init(void)
pr_info("Testing kprobe tracing: ");
ret = command_trace_probe("p:testprobe kprobe_trace_selftest_target "
- "a1 a2 a3 a4 a5 a6");
+ "$arg1 $arg2 $arg3 $arg4 $stack $stack0");
if (WARN_ON_ONCE(ret))
pr_warning("error enabling function entry\n");
ret = command_trace_probe("r:testprobe2 kprobe_trace_selftest_target "
- "ra rv");
+ "$retval");
if (WARN_ON_ONCE(ret))
pr_warning("error enabling function return\n");
--
Masami Hiramatsu
Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division
e-mail: mhi...@re...
|
|
From: Frederic W. <fwe...@gm...> - 2009-10-12 21:34:45
|
On Mon, Oct 12, 2009 at 05:36:56PM -0400, Masami Hiramatsu wrote:
> Frederic Weisbecker wrote:
>> On Mon, Oct 12, 2009 at 05:20:09PM -0400, Masami Hiramatsu wrote:
>>> Masami Hiramatsu wrote:
>>>> @@ -427,28 +427,17 @@ static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return)
>>>> int ret = 0;
>>>> unsigned long param;
>>>>
>>>> - switch (arg[0]) {
>>>> - case 'a': /* argument */
>>>> - ret = strict_strtoul(arg + 1, 10,¶m);
>>>> - if (ret || param> PARAM_MAX_ARGS)
>>>> - ret = -EINVAL;
>>>> - else {
>>>> - ff->func = fetch_argument;
>>>> - ff->data = (void *)param;
>>>> - }
>>>> - break;
>>>> - case 'r': /* retval or retaddr */
>>>> - if (is_return&& arg[1] == 'v') {
>>>> + if (strcmp(arg, "retval") == 0) {
>>>> + if (is_return) {
>>>> ff->func = fetch_retvalue;
>>>> ff->data = NULL;
>>>> } else
>>>> ret = -EINVAL;
>>>> - break;
>>>> - case 's': /* stack */
>>>> - if (arg[1] == 'a') {
>>>> + } else if (strncmp(arg, "stack", 5) == 0) {
>>>> + if (arg[5] == '\0') {
>>>> ff->func = fetch_stack_address;
>>>> ff->data = NULL;
>>>> - } else {
>>>> + } else if (isdigit(arg[5])) {
>>>> ret = strict_strtoul(arg + 1, 10,¶m);
>>> ^^^^^^^ this should be arg + 5.
>>>
>>>> @@ -456,11 +445,18 @@ static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return)
>>>> ff->func = fetch_stack;
>>>> ff->data = (void *)param;
>>>> }
>>>> + } else
>>>> + ret = -EINVAL;
>>>> + } else if (strncmp(arg, "arg", 3) == 0&& isdigit(arg[4])) {
>>
>>
>>
>> And this should be isdigit(arg[3]) actually, what you want to test is the
>> first character after arg, right?
>
> Right. I'll fix it...
>
>
> Thank you,
No need to, I've rebased and pushed to the same tree :-)
|
|
From: Masami H. <mhi...@re...> - 2009-10-12 21:33:27
|
Frederic Weisbecker wrote:
> On Mon, Oct 12, 2009 at 05:20:09PM -0400, Masami Hiramatsu wrote:
>> Masami Hiramatsu wrote:
>>> @@ -427,28 +427,17 @@ static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return)
>>> int ret = 0;
>>> unsigned long param;
>>>
>>> - switch (arg[0]) {
>>> - case 'a': /* argument */
>>> - ret = strict_strtoul(arg + 1, 10,¶m);
>>> - if (ret || param> PARAM_MAX_ARGS)
>>> - ret = -EINVAL;
>>> - else {
>>> - ff->func = fetch_argument;
>>> - ff->data = (void *)param;
>>> - }
>>> - break;
>>> - case 'r': /* retval or retaddr */
>>> - if (is_return&& arg[1] == 'v') {
>>> + if (strcmp(arg, "retval") == 0) {
>>> + if (is_return) {
>>> ff->func = fetch_retvalue;
>>> ff->data = NULL;
>>> } else
>>> ret = -EINVAL;
>>> - break;
>>> - case 's': /* stack */
>>> - if (arg[1] == 'a') {
>>> + } else if (strncmp(arg, "stack", 5) == 0) {
>>> + if (arg[5] == '\0') {
>>> ff->func = fetch_stack_address;
>>> ff->data = NULL;
>>> - } else {
>>> + } else if (isdigit(arg[5])) {
>>> ret = strict_strtoul(arg + 1, 10,¶m);
>> ^^^^^^^ this should be arg + 5.
>>
>>> @@ -456,11 +445,18 @@ static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return)
>>> ff->func = fetch_stack;
>>> ff->data = (void *)param;
>>> }
>>> + } else
>>> + ret = -EINVAL;
>>> + } else if (strncmp(arg, "arg", 3) == 0&& isdigit(arg[4])) {
>
>
>
> And this should be isdigit(arg[3]) actually, what you want to test is the
> first character after arg, right?
Right. I'll fix it...
Thank you,
--
Masami Hiramatsu
Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division
e-mail: mhi...@re...
|
|
From: Frederic W. <fwe...@gm...> - 2009-10-12 21:28:40
|
On Mon, Oct 12, 2009 at 05:20:09PM -0400, Masami Hiramatsu wrote:
> Masami Hiramatsu wrote:
>> @@ -427,28 +427,17 @@ static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return)
>> int ret = 0;
>> unsigned long param;
>>
>> - switch (arg[0]) {
>> - case 'a': /* argument */
>> - ret = strict_strtoul(arg + 1, 10,¶m);
>> - if (ret || param> PARAM_MAX_ARGS)
>> - ret = -EINVAL;
>> - else {
>> - ff->func = fetch_argument;
>> - ff->data = (void *)param;
>> - }
>> - break;
>> - case 'r': /* retval or retaddr */
>> - if (is_return&& arg[1] == 'v') {
>> + if (strcmp(arg, "retval") == 0) {
>> + if (is_return) {
>> ff->func = fetch_retvalue;
>> ff->data = NULL;
>> } else
>> ret = -EINVAL;
>> - break;
>> - case 's': /* stack */
>> - if (arg[1] == 'a') {
>> + } else if (strncmp(arg, "stack", 5) == 0) {
>> + if (arg[5] == '\0') {
>> ff->func = fetch_stack_address;
>> ff->data = NULL;
>> - } else {
>> + } else if (isdigit(arg[5])) {
>> ret = strict_strtoul(arg + 1, 10,¶m);
> ^^^^^^^ this should be arg + 5.
>
>> @@ -456,11 +445,18 @@ static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return)
>> ff->func = fetch_stack;
>> ff->data = (void *)param;
>> }
>> + } else
>> + ret = -EINVAL;
>> + } else if (strncmp(arg, "arg", 3) == 0&& isdigit(arg[4])) {
And this should be isdigit(arg[3]) actually, what you want to test is the
first character after arg, right?
>> + ret = strict_strtoul(arg + 1, 10,¶m);
> ^^^^^^^ here too, arg + 3.
|
|
From: Frederic W. <fwe...@gm...> - 2009-10-12 21:17:03
|
On Mon, Oct 12, 2009 at 04:22:26PM -0400, Masami Hiramatsu wrote: > Frederic Weisbecker wrote: >> On Mon, Oct 12, 2009 at 03:13:51PM -0400, Masami Hiramatsu wrote: >>> Frederic Weisbecker wrote: >>>> The conflict issue might not be obvious for a user desperately trying to set >>>> a kprobe. Even for other failcases, it might not be obvious (blacklisted >>>> symbols, syntax errors...) >>>> >>>> May be should you improve the error granularity and print a KERN_DEBUG >>>> message? >>> >>> Agreed, and kprobes error handling should be improved too (in the most cases, >>> it just returns -EINVAL). >>> >>> Thank you. >>> >> >> >> And btw, I'm enable to create a probe, neither through ftrace nor perf: >> >> $ sudo ./perf probe -P 'p:sys_close sys_close $retval' >> Adding new event: p:sys_close sys_close+0 $retval >> >> Error: Failed to create event: Invalid argument >> >> >> # echo 'p:sys_open sys_open $retval'> /debug/tracing/kprobe_events >> bash: echo: write error : Invalid argument >> >> I suspect I missed something very obvious with the syntax :) > > Ah, only kretprobe events can use $retval :-) > So, you should specify 'r' instead of 'p'. > > -P 'r:sys_close sys_close $retval' > Hehe, I was sure I was doing something silly but couldn't figure out what :-) So that works, at least without libdwarf, I can't test with it for now but this tool looks very promising. I really think it would be great to be able to cut the ./perf probe ./perf record ./perf trace batch into one step through a single ./perf probe -t -P "probe definition" [-a|cmdline] That would do the probe creation, the record, and stop once the given process finishes, or once we Ctrl+C (especially useful in wide tracing with -a, but sometimes also with processes). Not a lot of changes are required to do that. I can already see printk() whining on the horizon... Thanks! |
|
From: Masami H. <mhi...@re...> - 2009-10-12 21:16:44
|
Masami Hiramatsu wrote:
> @@ -427,28 +427,17 @@ static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return)
> int ret = 0;
> unsigned long param;
>
> - switch (arg[0]) {
> - case 'a': /* argument */
> - ret = strict_strtoul(arg + 1, 10,¶m);
> - if (ret || param> PARAM_MAX_ARGS)
> - ret = -EINVAL;
> - else {
> - ff->func = fetch_argument;
> - ff->data = (void *)param;
> - }
> - break;
> - case 'r': /* retval or retaddr */
> - if (is_return&& arg[1] == 'v') {
> + if (strcmp(arg, "retval") == 0) {
> + if (is_return) {
> ff->func = fetch_retvalue;
> ff->data = NULL;
> } else
> ret = -EINVAL;
> - break;
> - case 's': /* stack */
> - if (arg[1] == 'a') {
> + } else if (strncmp(arg, "stack", 5) == 0) {
> + if (arg[5] == '\0') {
> ff->func = fetch_stack_address;
> ff->data = NULL;
> - } else {
> + } else if (isdigit(arg[5])) {
> ret = strict_strtoul(arg + 1, 10,¶m);
^^^^^^^ this should be arg + 5.
> @@ -456,11 +445,18 @@ static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return)
> ff->func = fetch_stack;
> ff->data = (void *)param;
> }
> + } else
> + ret = -EINVAL;
> + } else if (strncmp(arg, "arg", 3) == 0&& isdigit(arg[4])) {
> + ret = strict_strtoul(arg + 1, 10,¶m);
^^^^^^^ here too, arg + 3.
Thank you,
--
Masami Hiramatsu
Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division
e-mail: mhi...@re...
|
|
From: Masami H. <mhi...@re...> - 2009-10-12 20:18:59
|
Frederic Weisbecker wrote: > On Mon, Oct 12, 2009 at 03:13:51PM -0400, Masami Hiramatsu wrote: >> Frederic Weisbecker wrote: >>> The conflict issue might not be obvious for a user desperately trying to set >>> a kprobe. Even for other failcases, it might not be obvious (blacklisted >>> symbols, syntax errors...) >>> >>> May be should you improve the error granularity and print a KERN_DEBUG >>> message? >> >> Agreed, and kprobes error handling should be improved too (in the most cases, >> it just returns -EINVAL). >> >> Thank you. >> > > > And btw, I'm enable to create a probe, neither through ftrace nor perf: > > $ sudo ./perf probe -P 'p:sys_close sys_close $retval' > Adding new event: p:sys_close sys_close+0 $retval > > Error: Failed to create event: Invalid argument > > > # echo 'p:sys_open sys_open $retval'> /debug/tracing/kprobe_events > bash: echo: write error : Invalid argument > > I suspect I missed something very obvious with the syntax :) Ah, only kretprobe events can use $retval :-) So, you should specify 'r' instead of 'p'. -P 'r:sys_close sys_close $retval' > I've applied your patches in: > > git://git.kernel.org/pub/scm/linux/kernel/git/frederic/random-tracing.git > tracing/kprobes > > Thanks. Thank you! -- Masami Hiramatsu Software Engineer Hitachi Computer Products (America), Inc. Software Solutions Division e-mail: mhi...@re... |
|
From: Frederic W. <fwe...@gm...> - 2009-10-12 19:49:09
|
On Mon, Oct 12, 2009 at 03:13:51PM -0400, Masami Hiramatsu wrote: > Frederic Weisbecker wrote: >> The conflict issue might not be obvious for a user desperately trying to set >> a kprobe. Even for other failcases, it might not be obvious (blacklisted >> symbols, syntax errors...) >> >> May be should you improve the error granularity and print a KERN_DEBUG >> message? > > Agreed, and kprobes error handling should be improved too (in the most cases, > it just returns -EINVAL). > > Thank you. > And btw, I'm enable to create a probe, neither through ftrace nor perf: $ sudo ./perf probe -P 'p:sys_close sys_close $retval' Adding new event: p:sys_close sys_close+0 $retval Error: Failed to create event: Invalid argument # echo 'p:sys_open sys_open $retval' > /debug/tracing/kprobe_events bash: echo: write error : Invalid argument I suspect I missed something very obvious with the syntax :) I've applied your patches in: git://git.kernel.org/pub/scm/linux/kernel/git/frederic/random-tracing.git tracing/kprobes Thanks. |
|
From: Masami H. <mhi...@re...> - 2009-10-12 19:29:33
|
Masami Hiramatsu wrote: > Add $ prefix to the special variables(e.g. sa, rv) of kprobe-tracer. > This resolves consistency issue between kprobe_events and perf-kprobe. > > Signed-off-by: Masami Hiramatsu<mhi...@re...> > Cc: Frederic Weisbecker<fwe...@gm...> > Cc: Ingo Molnar<mi...@el...> > Cc: Thomas Gleixner<tg...@li...> > Cc: Arnaldo Carvalho de Melo<ac...@re...> > Cc: Steven Rostedt<ro...@go...> > Cc: Mike Galbraith<ef...@gm...> > Cc: Paul Mackerras<pa...@sa...> > Cc: Peter Zijlstra<a.p...@ch...> > Cc: Christoph Hellwig<hc...@in...> > Cc: Ananth N Mavinakayanahalli<an...@in...> > Cc: Jim Keniston<jke...@us...> > Cc: Frank Ch. Eigler<fc...@re...> > --- > > Documentation/trace/kprobetrace.txt | 20 ++++++------ > kernel/trace/trace_kprobe.c | 60 ++++++++++++++++++++++------------- > 2 files changed, 47 insertions(+), 33 deletions(-) Oops, I've forgotten to update self-test code... -- Masami Hiramatsu Software Engineer Hitachi Computer Products (America), Inc. Software Solutions Division e-mail: mhi...@re... |
|
From: Masami H. <mhi...@re...> - 2009-10-12 19:28:38
|
Ingo Molnar wrote: > > * Frederic Weisbecker<fwe...@gm...> wrote: > >> On Wed, Oct 07, 2009 at 06:28:23PM -0400, Masami Hiramatsu wrote: >>> Add perf probe subcommand for kprobe-event setup helper to perf command. >>> This allows user to define kprobe events by C expressions (C line numbers, >>> C function names, and C local variables). >>> >> >> >> My libdwarf.h and dwarf.h are available through<libdwarf.h> and >> <dwarf.h>, these are in /usr/include >> >> But even by fixing the include path in the makefile and probe-finder.h, >> I get the following build error: >> >> util/probe-finder.c: In function ‘die_get_entrypc’: >> util/probe-finder.c:222: erreur: ‘Dwarf_Ranges’ undeclared (first use in this function) >> util/probe-finder.c:222: erreur: (Each undeclared identifier is reported only once >> util/probe-finder.c:222: erreur: for each function it appears in.) >> util/probe-finder.c:222: erreur: ‘ranges’ undeclared (first use in this function) >> cc1: warnings being treated as errors >> util/probe-finder.c:223: erreur: ISO C90 forbids mixed declarations and code >> util/probe-finder.c:247: erreur: implicit declaration of function ‘dwarf_get_ranges’ >> util/probe-finder.c:247: erreur: nested extern declaration of ‘dwarf_get_ranges’ >> util/probe-finder.c:251: erreur: implicit declaration of function ‘dwarf_ranges_dealloc’ >> util/probe-finder.c:251: erreur: nested extern declaration of ‘dwarf_ranges_dealloc’ >> make: *** [util/probe-finder.o] Erreur 1 >> >> >> I remember we talked about that before, but I don't remember well why it happened. >> This is because of a libdwarf version or something, right? Yeah, you may use an old version. >> >> Which one should I pick? Mine is: >> >> libdwarf.h >> >> $Revision: #9 $ $Date: 2008/01/17 $ AFAICS, the revision tag is not updated :( I'm usually using libdwarf later than 20090324, and dwarf_get_ranges() was introduced from 20081231. > > if it's possible to still have a single set of APIs it would be nice to > auto-detect and massage all these libdwarf versions into a single > backend within perf. Sure, it's not so hard to check APIs. Thank you, -- Masami Hiramatsu Software Engineer Hitachi Computer Products (America), Inc. Software Solutions Division e-mail: mhi...@re... |
|
From: Masami H. <mhi...@re...> - 2009-10-12 19:10:32
|
Frederic Weisbecker wrote: > The conflict issue might not be obvious for a user desperately trying to set > a kprobe. Even for other failcases, it might not be obvious (blacklisted > symbols, syntax errors...) > > May be should you improve the error granularity and print a KERN_DEBUG > message? Agreed, and kprobes error handling should be improved too (in the most cases, it just returns -EINVAL). Thank you. -- Masami Hiramatsu Software Engineer Hitachi Computer Products (America), Inc. Software Solutions Division e-mail: mhi...@re... |
|
From: Ingo M. <mi...@el...> - 2009-10-12 19:08:48
|
* Frederic Weisbecker <fwe...@gm...> wrote: > On Wed, Oct 07, 2009 at 06:28:23PM -0400, Masami Hiramatsu wrote: > > Add perf probe subcommand for kprobe-event setup helper to perf command. > > This allows user to define kprobe events by C expressions (C line numbers, > > C function names, and C local variables). > > > > > My libdwarf.h and dwarf.h are available through <libdwarf.h> and > <dwarf.h>, these are in /usr/include > > But even by fixing the include path in the makefile and probe-finder.h, > I get the following build error: > > util/probe-finder.c: In function ‘die_get_entrypc’: > util/probe-finder.c:222: erreur: ‘Dwarf_Ranges’ undeclared (first use in this function) > util/probe-finder.c:222: erreur: (Each undeclared identifier is reported only once > util/probe-finder.c:222: erreur: for each function it appears in.) > util/probe-finder.c:222: erreur: ‘ranges’ undeclared (first use in this function) > cc1: warnings being treated as errors > util/probe-finder.c:223: erreur: ISO C90 forbids mixed declarations and code > util/probe-finder.c:247: erreur: implicit declaration of function ‘dwarf_get_ranges’ > util/probe-finder.c:247: erreur: nested extern declaration of ‘dwarf_get_ranges’ > util/probe-finder.c:251: erreur: implicit declaration of function ‘dwarf_ranges_dealloc’ > util/probe-finder.c:251: erreur: nested extern declaration of ‘dwarf_ranges_dealloc’ > make: *** [util/probe-finder.o] Erreur 1 > > > I remember we talked about that before, but I don't remember well why it happened. > This is because of a libdwarf version or something, right? > > Which one should I pick? Mine is: > > libdwarf.h > > $Revision: #9 $ $Date: 2008/01/17 $ if it's possible to still have a single set of APIs it would be nice to auto-detect and massage all these libdwarf versions into a single backend within perf. Ingo |
|
From: Frederic W. <fwe...@gm...> - 2009-10-12 19:03:20
|
On Wed, Oct 07, 2009 at 06:28:23PM -0400, Masami Hiramatsu wrote:
> Add perf probe subcommand for kprobe-event setup helper to perf command.
> This allows user to define kprobe events by C expressions (C line numbers,
> C function names, and C local variables).
>
My libdwarf.h and dwarf.h are available through <libdwarf.h> and
<dwarf.h>, these are in /usr/include
But even by fixing the include path in the makefile and probe-finder.h,
I get the following build error:
util/probe-finder.c: In function ‘die_get_entrypc’:
util/probe-finder.c:222: erreur: ‘Dwarf_Ranges’ undeclared (first use in this function)
util/probe-finder.c:222: erreur: (Each undeclared identifier is reported only once
util/probe-finder.c:222: erreur: for each function it appears in.)
util/probe-finder.c:222: erreur: ‘ranges’ undeclared (first use in this function)
cc1: warnings being treated as errors
util/probe-finder.c:223: erreur: ISO C90 forbids mixed declarations and code
util/probe-finder.c:247: erreur: implicit declaration of function ‘dwarf_get_ranges’
util/probe-finder.c:247: erreur: nested extern declaration of ‘dwarf_get_ranges’
util/probe-finder.c:251: erreur: implicit declaration of function ‘dwarf_ranges_dealloc’
util/probe-finder.c:251: erreur: nested extern declaration of ‘dwarf_ranges_dealloc’
make: *** [util/probe-finder.o] Erreur 1
I remember we talked about that before, but I don't remember well why it happened.
This is because of a libdwarf version or something, right?
Which one should I pick? Mine is:
libdwarf.h
$Revision: #9 $ $Date: 2008/01/17 $
|
|
From: Masami H. <mhi...@re...> - 2009-10-12 18:56:43
|
Frederic Weisbecker wrote:
> On Thu, Oct 08, 2009 at 05:17:38PM -0400, Masami Hiramatsu wrote:
>> +#ifdef DEBUG
>> +#define debug(fmt ...) \
>> + fprintf(stderr, "DBG(" __FILE__ ":" stringify(__LINE__) "): " fmt)
>> +#else
>> +#define debug(fmt ...) do {} while (0)
>> +#endif
>
>
>
> We have that too:
>
> int eprintf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
> int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
Thanks, I'll use that.
>> +#define ERR_IF(cnd) \
>> + do { if (cnd) { \
>> + fprintf(stderr, "Error (" __FILE__ ":" stringify(__LINE__) \
>> + "): " stringify(cnd) "\n"); \
>> + exit(1); \
>> + } } while (0)
>
>
> And that would be nice to have in util/debug.h but more
> perhaps more as a DIE_IF()
>
Sure :-)
Thank you,
--
Masami Hiramatsu
Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division
e-mail: mhi...@re...
|
|
From: Frederic W. <fwe...@gm...> - 2009-10-12 18:08:07
|
On Thu, Oct 08, 2009 at 05:17:38PM -0400, Masami Hiramatsu wrote:
> +#ifdef DEBUG
> +#define debug(fmt ...) \
> + fprintf(stderr, "DBG(" __FILE__ ":" stringify(__LINE__) "): " fmt)
> +#else
> +#define debug(fmt ...) do {} while (0)
> +#endif
We have that too:
int eprintf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
> +#define ERR_IF(cnd) \
> + do { if (cnd) { \
> + fprintf(stderr, "Error (" __FILE__ ":" stringify(__LINE__) \
> + "): " stringify(cnd) "\n"); \
> + exit(1); \
> + } } while (0)
And that would be nice to have in util/debug.h but more
perhaps more as a DIE_IF()
|
|
From: Frederic W. <fwe...@gm...> - 2009-10-12 18:03:19
|
On Thu, Oct 08, 2009 at 05:17:38PM -0400, Masami Hiramatsu wrote:
> +static void semantic_error(const char *msg)
> +{
> + fprintf(stderr, "Semantic error: %s\n", msg);
> + exit(1);
> +}
> +
> +static void perror_exit(const char *msg)
> +{
> + perror(msg);
> + exit(1);
> +}
We have that already btw:
tools/perf/util/util.h:
extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
> +static void msg_exit(int ret, const char *fmt, ...)
> +{
> + va_list ap;
> +
> + va_start(ap, fmt);
> + fprintf(stderr, "Error: ");
> + vfprintf(stderr, fmt, ap);
> + va_end(ap);
> +
> + fprintf(stderr, "\n");
> + exit(ret);
> +}
And somehow ditto :)
|
|
From: Frederic W. <fwe...@gm...> - 2009-10-12 17:38:09
|
On Wed, Oct 07, 2009 at 06:28:07PM -0400, Masami Hiramatsu wrote:
> Check whether the argument name is conflict with other field names.
>
> Changes in v3:
> - Check strcmp() == 0 instead of !strcmp().
>
> Changes in v2:
> - Add common_lock_depth to reserved name list.
>
> Signed-off-by: Masami Hiramatsu <mhi...@re...>
> Cc: Frederic Weisbecker <fwe...@gm...>
> Cc: Ingo Molnar <mi...@el...>
> Cc: Thomas Gleixner <tg...@li...>
> Cc: Arnaldo Carvalho de Melo <ac...@re...>
> Cc: Steven Rostedt <ro...@go...>
> Cc: Mike Galbraith <ef...@gm...>
> Cc: Paul Mackerras <pa...@sa...>
> Cc: Peter Zijlstra <a.p...@ch...>
> Cc: Christoph Hellwig <hc...@in...>
> Cc: Ananth N Mavinakayanahalli <an...@in...>
> Cc: Jim Keniston <jke...@us...>
> Cc: Frank Ch. Eigler <fc...@re...>
> ---
>
> kernel/trace/trace_kprobe.c | 65 +++++++++++++++++++++++++++++++++++--------
> 1 files changed, 53 insertions(+), 12 deletions(-)
>
> diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
> index 030f28c..e3b824a 100644
> --- a/kernel/trace/trace_kprobe.c
> +++ b/kernel/trace/trace_kprobe.c
> @@ -38,6 +38,25 @@
> #define MAX_EVENT_NAME_LEN 64
> #define KPROBE_EVENT_SYSTEM "kprobes"
>
> +/* Reserved field names */
> +#define FIELD_STRING_IP "ip"
> +#define FIELD_STRING_NARGS "nargs"
> +#define FIELD_STRING_RETIP "ret_ip"
> +#define FIELD_STRING_FUNC "func"
> +
> +const char *reserved_field_names[] = {
> + "common_type",
> + "common_flags",
> + "common_preempt_count",
> + "common_pid",
> + "common_tgid",
> + "common_lock_depth",
> + FIELD_STRING_IP,
> + FIELD_STRING_NARGS,
> + FIELD_STRING_RETIP,
> + FIELD_STRING_FUNC,
> +};
> +
> /* currently, trace_kprobe only supports X86. */
>
> struct fetch_func {
> @@ -537,6 +556,20 @@ static int parse_probe_arg(char *arg, struct fetch_func *ff, int is_return)
> return ret;
> }
>
> +/* Return 1 if name is reserved or already used by another argument */
> +static int conflict_field_name(const char *name,
> + struct probe_arg *args, int narg)
> +{
> + int i;
> + for (i = 0; i < ARRAY_SIZE(reserved_field_names); i++)
> + if (strcmp(reserved_field_names[i], name) == 0)
> + return 1;
> + for (i = 0; i < narg; i++)
> + if (strcmp(args[i].name, name) == 0)
> + return 1;
> + return 0;
> +}
> +
> static int create_trace_probe(int argc, char **argv)
> {
> /*
> @@ -637,6 +670,12 @@ static int create_trace_probe(int argc, char **argv)
> *arg++ = '\0';
> else
> arg = argv[i];
> +
> + if (conflict_field_name(argv[i], tp->args, i)) {
> + ret = -EINVAL;
The conflict issue might not be obvious for a user desperately trying to set
a kprobe. Even for other failcases, it might not be obvious (blacklisted
symbols, syntax errors...)
May be should you improve the error granularity and print a KERN_DEBUG
message?
Thanks.
|
|
From: Masami H. <mhi...@re...> - 2009-10-12 14:39:20
|
Frédéric Weisbecker wrote:
> 2009/10/8 Masami Hiramatsu <mhi...@re...>:
>> Add perf probe subcommand for kprobe-event setup helper to perf command.
>> This allows user to define kprobe events by C expressions (C line numbers,
>> C function names, and C local variables).
>>
>> Usage
>> -----
>> perf probe [<options>] -P 'PROBEDEF' [-P 'PROBEDEF' ...]
>>
>> -k, --vmlinux <file> vmlinux/module pathname
>> -P, --probe <p|r:[GRP/]NAME FUNC[+OFFS][@SRC]|@SRC:LINE [ARG ...]>
>> probe point definition, where
>> p: kprobe probe
>> r: kretprobe probe
>> GRP: Group name (optional)
>> NAME: Event name
>> FUNC: Function name
>> OFFS: Offset from function entry (in byte)
>> SRC: Source code path
>> LINE: Line number
>> ARG: Probe argument (local variable name or
>> kprobe-tracer argument format is supported.)
>>
>> Changes in v4:
>> - Add _GNU_SOURCE macro for strndup().
>>
>> Changes in v3:
>> - Remove -r option because perf always be used for online kernel.
>> - Check malloc/calloc results.
>>
>> Changes in v2:
>> - Check synthesized string length.
>> - Rename perf kprobe to perf probe.
>> - Use spaces for separator and update usage comment.
>> - Check error paths in parse_probepoint().
>> - Check optimized-out variables.
>>
>> Signed-off-by: Masami Hiramatsu <mhi...@re...>
>> Cc: Frederic Weisbecker <fwe...@gm...>
>> Cc: Ingo Molnar <mi...@el...>
>> Cc: Thomas Gleixner <tg...@li...>
>> Cc: Arnaldo Carvalho de Melo <ac...@re...>
>> Cc: Steven Rostedt <ro...@go...>
>> Cc: Mike Galbraith <ef...@gm...>
>> Cc: Paul Mackerras <pa...@sa...>
>> Cc: Peter Zijlstra <a.p...@ch...>
>> Cc: Christoph Hellwig <hc...@in...>
>> Cc: Ananth N Mavinakayanahalli <an...@in...>
>> Cc: Jim Keniston <jke...@us...>
>> Cc: Frank Ch. Eigler <fc...@re...>
>> ---
>>
> [...]
>> +/* Default vmlinux search paths */
>> +#define NR_SEARCH_PATH 3
>> +const char *default_search_path[NR_SEARCH_PATH] = {
>> +"/lib/modules/%s/build/vmlinux", /* Custom build kernel */
>> +"/usr/lib/debug/lib/modules/%s/vmlinux", /* Red Hat debuginfo */
>> +"/boot/vmlinux-debug-%s", /* Ubuntu */
>> +};
> [...]
>> +static int open_default_vmlinux(void)
>> +{
>> + struct utsname uts;
>> + char fname[MAX_PATH_LEN];
>> + int fd, ret, i;
>> +
>> + ret = uname(&uts);
>> + if (ret) {
>> + debug("uname() failed.\n");
>> + return -errno;
>> + }
>> + session.release = uts.release;
>> + for (i = 0; i < NR_SEARCH_PATH; i++) {
>> + ret = snprintf(fname, MAX_PATH_LEN,
>> + default_search_path[i], session.release);
>> + if (ret >= MAX_PATH_LEN || ret < 0) {
>> + debug("Filename(%d,%s) is too long.\n", i, uts.release);
>> + errno = E2BIG;
>> + return -E2BIG;
>> + }
>> + debug("try to open %s\n", fname);
>> + fd = open(fname, O_RDONLY);
>> + if (fd >= 0)
>> + break;
>> + }
>> + return fd;
>> +}
>
>
> We have a kind of kernel path finder already inside perf. It might be
> encapsulated
> inside the load_kernel() helper, I don't remember exactly.
>
> It would be better to make use of such centralized and already
> existing facility.
Agreed. AFAICS, load_kernel() is currently only for symbol resolver,
and we can make it for dwarf analyzer too.
>
> The patchset looks good. I'll apply and push it soon.
Thanks!
--
Masami Hiramatsu
Software Engineer
Hitachi Computer Products (America), Inc.
Software Solutions Division
e-mail: mhi...@re...
|