|
@@ -54,6 +54,7 @@ const char *default_search_path[NR_SEARCH_PATH] = {
|
|
static struct {
|
|
static struct {
|
|
char *vmlinux;
|
|
char *vmlinux;
|
|
char *release;
|
|
char *release;
|
|
|
|
+ int need_dwarf;
|
|
int nr_probe;
|
|
int nr_probe;
|
|
struct probe_point probes[MAX_PROBES];
|
|
struct probe_point probes[MAX_PROBES];
|
|
char *events[MAX_PROBES];
|
|
char *events[MAX_PROBES];
|
|
@@ -162,6 +163,8 @@ static int parse_probepoint(const struct option *opt __used,
|
|
pp->function, pp->file, pp->offset);
|
|
pp->function, pp->file, pp->offset);
|
|
}
|
|
}
|
|
free(argv[1]);
|
|
free(argv[1]);
|
|
|
|
+ if (pp->file)
|
|
|
|
+ session.need_dwarf = 1;
|
|
|
|
|
|
/* Copy arguments */
|
|
/* Copy arguments */
|
|
pp->nr_args = argc - 2;
|
|
pp->nr_args = argc - 2;
|
|
@@ -173,15 +176,19 @@ static int parse_probepoint(const struct option *opt __used,
|
|
}
|
|
}
|
|
|
|
|
|
/* Ensure return probe has no C argument */
|
|
/* Ensure return probe has no C argument */
|
|
- if (retp)
|
|
|
|
- for (i = 0; i < pp->nr_args; i++)
|
|
|
|
- if (is_c_varname(pp->args[i]))
|
|
|
|
|
|
+ for (i = 0; i < pp->nr_args; i++)
|
|
|
|
+ if (is_c_varname(pp->args[i])) {
|
|
|
|
+ if (retp)
|
|
semantic_error("You can't specify local"
|
|
semantic_error("You can't specify local"
|
|
" variable for kretprobe");
|
|
" variable for kretprobe");
|
|
|
|
+ session.need_dwarf = 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
debug("%d arguments\n", pp->nr_args);
|
|
debug("%d arguments\n", pp->nr_args);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifndef NO_LIBDWARF
|
|
static int open_default_vmlinux(void)
|
|
static int open_default_vmlinux(void)
|
|
{
|
|
{
|
|
struct utsname uts;
|
|
struct utsname uts;
|
|
@@ -209,6 +216,7 @@ static int open_default_vmlinux(void)
|
|
}
|
|
}
|
|
return fd;
|
|
return fd;
|
|
}
|
|
}
|
|
|
|
+#endif
|
|
|
|
|
|
static const char * const probe_usage[] = {
|
|
static const char * const probe_usage[] = {
|
|
"perf probe [<options>] -P 'PROBEDEF' [-P 'PROBEDEF' ...]",
|
|
"perf probe [<options>] -P 'PROBEDEF' [-P 'PROBEDEF' ...]",
|
|
@@ -216,10 +224,16 @@ static const char * const probe_usage[] = {
|
|
};
|
|
};
|
|
|
|
|
|
static const struct option options[] = {
|
|
static const struct option options[] = {
|
|
|
|
+#ifndef NO_LIBDWARF
|
|
OPT_STRING('k', "vmlinux", &session.vmlinux, "file",
|
|
OPT_STRING('k', "vmlinux", &session.vmlinux, "file",
|
|
"vmlinux/module pathname"),
|
|
"vmlinux/module pathname"),
|
|
|
|
+#endif
|
|
OPT_CALLBACK('P', "probe", NULL,
|
|
OPT_CALLBACK('P', "probe", NULL,
|
|
|
|
+#ifdef NO_LIBDWARF
|
|
|
|
+ "p|r:[GRP/]NAME FUNC[+OFFS] [ARG ...]",
|
|
|
|
+#else
|
|
"p|r:[GRP/]NAME FUNC[+OFFS][@SRC]|@SRC:LINE [ARG ...]",
|
|
"p|r:[GRP/]NAME FUNC[+OFFS][@SRC]|@SRC:LINE [ARG ...]",
|
|
|
|
+#endif
|
|
"probe point definition, where\n"
|
|
"probe point definition, where\n"
|
|
"\t\tp:\tkprobe probe\n"
|
|
"\t\tp:\tkprobe probe\n"
|
|
"\t\tr:\tkretprobe probe\n"
|
|
"\t\tr:\tkretprobe probe\n"
|
|
@@ -227,9 +241,13 @@ static const struct option options[] = {
|
|
"\t\tNAME:\tEvent name\n"
|
|
"\t\tNAME:\tEvent name\n"
|
|
"\t\tFUNC:\tFunction name\n"
|
|
"\t\tFUNC:\tFunction name\n"
|
|
"\t\tOFFS:\tOffset from function entry (in byte)\n"
|
|
"\t\tOFFS:\tOffset from function entry (in byte)\n"
|
|
|
|
+#ifdef NO_LIBDWARF
|
|
|
|
+ "\t\tARG:\tProbe argument (only \n"
|
|
|
|
+#else
|
|
"\t\tSRC:\tSource code path\n"
|
|
"\t\tSRC:\tSource code path\n"
|
|
"\t\tLINE:\tLine number\n"
|
|
"\t\tLINE:\tLine number\n"
|
|
"\t\tARG:\tProbe argument (local variable name or\n"
|
|
"\t\tARG:\tProbe argument (local variable name or\n"
|
|
|
|
+#endif
|
|
"\t\t\tkprobe-tracer argument format is supported.)\n",
|
|
"\t\t\tkprobe-tracer argument format is supported.)\n",
|
|
parse_probepoint),
|
|
parse_probepoint),
|
|
OPT_END()
|
|
OPT_END()
|
|
@@ -279,7 +297,7 @@ error:
|
|
|
|
|
|
int cmd_probe(int argc, const char **argv, const char *prefix __used)
|
|
int cmd_probe(int argc, const char **argv, const char *prefix __used)
|
|
{
|
|
{
|
|
- int i, j, fd, ret, need_dwarf = 0;
|
|
|
|
|
|
+ int i, j, fd, ret;
|
|
struct probe_point *pp;
|
|
struct probe_point *pp;
|
|
char buf[MAX_CMDLEN];
|
|
char buf[MAX_CMDLEN];
|
|
|
|
|
|
@@ -288,12 +306,19 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
|
|
if (argc || session.nr_probe == 0)
|
|
if (argc || session.nr_probe == 0)
|
|
usage_with_options(probe_usage, options);
|
|
usage_with_options(probe_usage, options);
|
|
|
|
|
|
- /* Synthesize return probes */
|
|
|
|
|
|
+#ifdef NO_LIBDWARF
|
|
|
|
+ if (session.need_dwarf)
|
|
|
|
+ semantic_error("Dwarf-analysis is not supported");
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ /* Synthesize probes without dwarf */
|
|
for (j = 0; j < session.nr_probe; j++) {
|
|
for (j = 0; j < session.nr_probe; j++) {
|
|
|
|
+#ifndef NO_LIBDWARF
|
|
if (session.events[j][0] != 'r') {
|
|
if (session.events[j][0] != 'r') {
|
|
- need_dwarf = 1;
|
|
|
|
|
|
+ session.need_dwarf = 1;
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
+#endif
|
|
ret = synthesize_probepoint(&session.probes[j]);
|
|
ret = synthesize_probepoint(&session.probes[j]);
|
|
if (ret == -E2BIG)
|
|
if (ret == -E2BIG)
|
|
semantic_error("probe point is too long.");
|
|
semantic_error("probe point is too long.");
|
|
@@ -303,7 +328,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- if (!need_dwarf)
|
|
|
|
|
|
+#ifndef NO_LIBDWARF
|
|
|
|
+ if (!session.need_dwarf)
|
|
goto setup_probes;
|
|
goto setup_probes;
|
|
|
|
|
|
if (session.vmlinux)
|
|
if (session.vmlinux)
|
|
@@ -332,6 +358,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
|
|
close(fd);
|
|
close(fd);
|
|
|
|
|
|
setup_probes:
|
|
setup_probes:
|
|
|
|
+#endif /* !NO_LIBDWARF */
|
|
|
|
+
|
|
/* Settng up probe points */
|
|
/* Settng up probe points */
|
|
snprintf(buf, MAX_CMDLEN, "%s/../kprobe_events", debugfs_path);
|
|
snprintf(buf, MAX_CMDLEN, "%s/../kprobe_events", debugfs_path);
|
|
fd = open(buf, O_WRONLY, O_APPEND);
|
|
fd = open(buf, O_WRONLY, O_APPEND);
|