|
@@ -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;
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+
|
|
|
tp->args[i].name = kstrdup(argv[i], GFP_KERNEL);
|
|
|
|
|
|
/* Parse fetch argument */
|
|
@@ -1039,8 +1078,8 @@ static int kprobe_event_define_fields(struct ftrace_event_call *event_call)
|
|
|
if (!ret)
|
|
|
return ret;
|
|
|
|
|
|
- DEFINE_FIELD(unsigned long, ip, "ip", 0);
|
|
|
- DEFINE_FIELD(int, nargs, "nargs", 1);
|
|
|
+ DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0);
|
|
|
+ DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1);
|
|
|
/* Set argument names as fields */
|
|
|
for (i = 0; i < tp->nr_args; i++)
|
|
|
DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0);
|
|
@@ -1057,9 +1096,9 @@ static int kretprobe_event_define_fields(struct ftrace_event_call *event_call)
|
|
|
if (!ret)
|
|
|
return ret;
|
|
|
|
|
|
- DEFINE_FIELD(unsigned long, func, "func", 0);
|
|
|
- DEFINE_FIELD(unsigned long, ret_ip, "ret_ip", 0);
|
|
|
- DEFINE_FIELD(int, nargs, "nargs", 1);
|
|
|
+ DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0);
|
|
|
+ DEFINE_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP, 0);
|
|
|
+ DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1);
|
|
|
/* Set argument names as fields */
|
|
|
for (i = 0; i < tp->nr_args; i++)
|
|
|
DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0);
|
|
@@ -1108,15 +1147,16 @@ static int kprobe_event_show_format(struct ftrace_event_call *call,
|
|
|
int ret, i;
|
|
|
struct trace_probe *tp = (struct trace_probe *)call->data;
|
|
|
|
|
|
- SHOW_FIELD(unsigned long, ip, "ip");
|
|
|
- SHOW_FIELD(int, nargs, "nargs");
|
|
|
+ SHOW_FIELD(unsigned long, ip, FIELD_STRING_IP);
|
|
|
+ SHOW_FIELD(int, nargs, FIELD_STRING_NARGS);
|
|
|
|
|
|
/* Show fields */
|
|
|
for (i = 0; i < tp->nr_args; i++)
|
|
|
SHOW_FIELD(unsigned long, args[i], tp->args[i].name);
|
|
|
trace_seq_puts(s, "\n");
|
|
|
|
|
|
- return __probe_event_show_format(s, tp, "(%lx)", "REC->ip");
|
|
|
+ return __probe_event_show_format(s, tp, "(%lx)",
|
|
|
+ "REC->" FIELD_STRING_IP);
|
|
|
}
|
|
|
|
|
|
static int kretprobe_event_show_format(struct ftrace_event_call *call,
|
|
@@ -1126,9 +1166,9 @@ static int kretprobe_event_show_format(struct ftrace_event_call *call,
|
|
|
int ret, i;
|
|
|
struct trace_probe *tp = (struct trace_probe *)call->data;
|
|
|
|
|
|
- SHOW_FIELD(unsigned long, func, "func");
|
|
|
- SHOW_FIELD(unsigned long, ret_ip, "ret_ip");
|
|
|
- SHOW_FIELD(int, nargs, "nargs");
|
|
|
+ SHOW_FIELD(unsigned long, func, FIELD_STRING_FUNC);
|
|
|
+ SHOW_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP);
|
|
|
+ SHOW_FIELD(int, nargs, FIELD_STRING_NARGS);
|
|
|
|
|
|
/* Show fields */
|
|
|
for (i = 0; i < tp->nr_args; i++)
|
|
@@ -1136,7 +1176,8 @@ static int kretprobe_event_show_format(struct ftrace_event_call *call,
|
|
|
trace_seq_puts(s, "\n");
|
|
|
|
|
|
return __probe_event_show_format(s, tp, "(%lx <- %lx)",
|
|
|
- "REC->func, REC->ret_ip");
|
|
|
+ "REC->" FIELD_STRING_FUNC
|
|
|
+ ", REC->" FIELD_STRING_RETIP);
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_EVENT_PROFILE
|