|
@@ -25,6 +25,7 @@
|
|
|
#include "trace_probe.h"
|
|
|
|
|
|
#define KPROBE_EVENT_SYSTEM "kprobes"
|
|
|
+#define KRETPROBE_MAXACTIVE_MAX 4096
|
|
|
|
|
|
/**
|
|
|
* Kprobe event core functions
|
|
@@ -282,6 +283,7 @@ static struct trace_kprobe *alloc_trace_kprobe(const char *group,
|
|
|
void *addr,
|
|
|
const char *symbol,
|
|
|
unsigned long offs,
|
|
|
+ int maxactive,
|
|
|
int nargs, bool is_return)
|
|
|
{
|
|
|
struct trace_kprobe *tk;
|
|
@@ -309,6 +311,8 @@ static struct trace_kprobe *alloc_trace_kprobe(const char *group,
|
|
|
else
|
|
|
tk->rp.kp.pre_handler = kprobe_dispatcher;
|
|
|
|
|
|
+ tk->rp.maxactive = maxactive;
|
|
|
+
|
|
|
if (!event || !is_good_name(event)) {
|
|
|
ret = -EINVAL;
|
|
|
goto error;
|
|
@@ -598,8 +602,10 @@ static int create_trace_kprobe(int argc, char **argv)
|
|
|
{
|
|
|
/*
|
|
|
* Argument syntax:
|
|
|
- * - Add kprobe: p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR [FETCHARGS]
|
|
|
- * - Add kretprobe: r[:[GRP/]EVENT] [MOD:]KSYM[+0] [FETCHARGS]
|
|
|
+ * - Add kprobe:
|
|
|
+ * p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR [FETCHARGS]
|
|
|
+ * - Add kretprobe:
|
|
|
+ * r[MAXACTIVE][:[GRP/]EVENT] [MOD:]KSYM[+0] [FETCHARGS]
|
|
|
* Fetch args:
|
|
|
* $retval : fetch return value
|
|
|
* $stack : fetch stack address
|
|
@@ -619,6 +625,7 @@ static int create_trace_kprobe(int argc, char **argv)
|
|
|
int i, ret = 0;
|
|
|
bool is_return = false, is_delete = false;
|
|
|
char *symbol = NULL, *event = NULL, *group = NULL;
|
|
|
+ int maxactive = 0;
|
|
|
char *arg;
|
|
|
unsigned long offset = 0;
|
|
|
void *addr = NULL;
|
|
@@ -637,8 +644,28 @@ static int create_trace_kprobe(int argc, char **argv)
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- if (argv[0][1] == ':') {
|
|
|
- event = &argv[0][2];
|
|
|
+ event = strchr(&argv[0][1], ':');
|
|
|
+ if (event) {
|
|
|
+ event[0] = '\0';
|
|
|
+ event++;
|
|
|
+ }
|
|
|
+ if (is_return && isdigit(argv[0][1])) {
|
|
|
+ ret = kstrtouint(&argv[0][1], 0, &maxactive);
|
|
|
+ if (ret) {
|
|
|
+ pr_info("Failed to parse maxactive.\n");
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ /* kretprobes instances are iterated over via a list. The
|
|
|
+ * maximum should stay reasonable.
|
|
|
+ */
|
|
|
+ if (maxactive > KRETPROBE_MAXACTIVE_MAX) {
|
|
|
+ pr_info("Maxactive is too big (%d > %d).\n",
|
|
|
+ maxactive, KRETPROBE_MAXACTIVE_MAX);
|
|
|
+ return -E2BIG;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (event) {
|
|
|
if (strchr(event, '/')) {
|
|
|
group = event;
|
|
|
event = strchr(group, '/') + 1;
|
|
@@ -718,8 +745,8 @@ static int create_trace_kprobe(int argc, char **argv)
|
|
|
is_return ? 'r' : 'p', addr);
|
|
|
event = buf;
|
|
|
}
|
|
|
- tk = alloc_trace_kprobe(group, event, addr, symbol, offset, argc,
|
|
|
- is_return);
|
|
|
+ tk = alloc_trace_kprobe(group, event, addr, symbol, offset, maxactive,
|
|
|
+ argc, is_return);
|
|
|
if (IS_ERR(tk)) {
|
|
|
pr_info("Failed to allocate trace_probe.(%d)\n",
|
|
|
(int)PTR_ERR(tk));
|