2017-07-09 11:42:39 +00:00
|
|
|
From: Tom Zanussi <tom.zanussi@linux.intel.com>
|
2017-11-20 14:16:49 +00:00
|
|
|
Date: Fri, 22 Sep 2017 14:58:20 -0500
|
|
|
|
Subject: [PATCH 06/42] tracing: Make traceprobe parsing code reusable
|
2018-01-31 19:59:07 +00:00
|
|
|
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.14/older/patches-4.14.15-rt13.tar.xz
|
2017-07-09 11:42:39 +00:00
|
|
|
|
|
|
|
traceprobe_probes_write() and traceprobe_command() actually contain
|
|
|
|
nothing that ties them to kprobes - the code is generically useful for
|
|
|
|
similar types of parsing elsewhere, so separate it out and move it to
|
|
|
|
trace.c/trace.h.
|
|
|
|
|
|
|
|
Other than moving it, the only change is in naming:
|
|
|
|
traceprobe_probes_write() becomes trace_parse_run_command() and
|
|
|
|
traceprobe_command() becomes trace_run_command().
|
|
|
|
|
|
|
|
Signed-off-by: Tom Zanussi <tom.zanussi@linux.intel.com>
|
|
|
|
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
|
|
---
|
|
|
|
kernel/trace/trace.c | 86 ++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
kernel/trace/trace.h | 7 +++
|
|
|
|
kernel/trace/trace_kprobe.c | 18 ++++-----
|
|
|
|
kernel/trace/trace_probe.c | 86 --------------------------------------------
|
|
|
|
kernel/trace/trace_probe.h | 7 ---
|
|
|
|
kernel/trace/trace_uprobe.c | 2 -
|
|
|
|
6 files changed, 103 insertions(+), 103 deletions(-)
|
|
|
|
|
|
|
|
--- a/kernel/trace/trace.c
|
|
|
|
+++ b/kernel/trace/trace.c
|
2018-01-28 14:46:47 +00:00
|
|
|
@@ -8265,6 +8265,92 @@ void ftrace_dump(enum ftrace_dump_mode o
|
2017-07-09 11:42:39 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(ftrace_dump);
|
|
|
|
|
|
|
|
+int trace_run_command(const char *buf, int (*createfn)(int, char **))
|
|
|
|
+{
|
|
|
|
+ char **argv;
|
|
|
|
+ int argc, ret;
|
|
|
|
+
|
|
|
|
+ argc = 0;
|
|
|
|
+ ret = 0;
|
|
|
|
+ argv = argv_split(GFP_KERNEL, buf, &argc);
|
|
|
|
+ if (!argv)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
|
|
+ if (argc)
|
|
|
|
+ ret = createfn(argc, argv);
|
|
|
|
+
|
|
|
|
+ argv_free(argv);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#define WRITE_BUFSIZE 4096
|
|
|
|
+
|
|
|
|
+ssize_t trace_parse_run_command(struct file *file, const char __user *buffer,
|
|
|
|
+ size_t count, loff_t *ppos,
|
|
|
|
+ int (*createfn)(int, char **))
|
|
|
|
+{
|
|
|
|
+ char *kbuf, *buf, *tmp;
|
|
|
|
+ int ret = 0;
|
|
|
|
+ size_t done = 0;
|
|
|
|
+ size_t size;
|
|
|
|
+
|
|
|
|
+ kbuf = kmalloc(WRITE_BUFSIZE, GFP_KERNEL);
|
|
|
|
+ if (!kbuf)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
|
|
+ while (done < count) {
|
|
|
|
+ size = count - done;
|
|
|
|
+
|
|
|
|
+ if (size >= WRITE_BUFSIZE)
|
|
|
|
+ size = WRITE_BUFSIZE - 1;
|
|
|
|
+
|
|
|
|
+ if (copy_from_user(kbuf, buffer + done, size)) {
|
|
|
|
+ ret = -EFAULT;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ kbuf[size] = '\0';
|
|
|
|
+ buf = kbuf;
|
|
|
|
+ do {
|
|
|
|
+ tmp = strchr(buf, '\n');
|
|
|
|
+ if (tmp) {
|
|
|
|
+ *tmp = '\0';
|
|
|
|
+ size = tmp - buf + 1;
|
|
|
|
+ } else {
|
|
|
|
+ size = strlen(buf);
|
|
|
|
+ if (done + size < count) {
|
|
|
|
+ if (buf != kbuf)
|
|
|
|
+ break;
|
|
|
|
+ /* This can accept WRITE_BUFSIZE - 2 ('\n' + '\0') */
|
|
|
|
+ pr_warn("Line length is too long: Should be less than %d\n",
|
|
|
|
+ WRITE_BUFSIZE - 2);
|
|
|
|
+ ret = -EINVAL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ done += size;
|
|
|
|
+
|
|
|
|
+ /* Remove comments */
|
|
|
|
+ tmp = strchr(buf, '#');
|
|
|
|
+
|
|
|
|
+ if (tmp)
|
|
|
|
+ *tmp = '\0';
|
|
|
|
+
|
|
|
|
+ ret = trace_run_command(buf, createfn);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto out;
|
|
|
|
+ buf += size;
|
|
|
|
+
|
|
|
|
+ } while (done < count);
|
|
|
|
+ }
|
|
|
|
+ ret = done;
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ kfree(kbuf);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
__init static int tracer_alloc_buffers(void)
|
|
|
|
{
|
|
|
|
int ring_buf_size;
|
|
|
|
--- a/kernel/trace/trace.h
|
|
|
|
+++ b/kernel/trace/trace.h
|
2017-11-20 14:16:49 +00:00
|
|
|
@@ -1755,6 +1755,13 @@ void trace_printk_start_comm(void);
|
2017-07-09 11:42:39 +00:00
|
|
|
int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set);
|
|
|
|
int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled);
|
|
|
|
|
|
|
|
+#define MAX_EVENT_NAME_LEN 64
|
|
|
|
+
|
|
|
|
+extern int trace_run_command(const char *buf, int (*createfn)(int, char**));
|
|
|
|
+extern ssize_t trace_parse_run_command(struct file *file,
|
|
|
|
+ const char __user *buffer, size_t count, loff_t *ppos,
|
|
|
|
+ int (*createfn)(int, char**));
|
|
|
|
+
|
|
|
|
/*
|
|
|
|
* Normal trace_printk() and friends allocates special buffers
|
|
|
|
* to do the manipulation, as well as saves the print formats
|
|
|
|
--- a/kernel/trace/trace_kprobe.c
|
|
|
|
+++ b/kernel/trace/trace_kprobe.c
|
2017-11-20 14:16:49 +00:00
|
|
|
@@ -907,8 +907,8 @@ static int probes_open(struct inode *ino
|
2017-07-09 11:42:39 +00:00
|
|
|
static ssize_t probes_write(struct file *file, const char __user *buffer,
|
|
|
|
size_t count, loff_t *ppos)
|
|
|
|
{
|
|
|
|
- return traceprobe_probes_write(file, buffer, count, ppos,
|
|
|
|
- create_trace_kprobe);
|
|
|
|
+ return trace_parse_run_command(file, buffer, count, ppos,
|
|
|
|
+ create_trace_kprobe);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct file_operations kprobe_events_ops = {
|
2017-11-20 14:16:49 +00:00
|
|
|
@@ -1433,9 +1433,9 @@ static __init int kprobe_trace_self_test
|
2017-07-09 11:42:39 +00:00
|
|
|
|
|
|
|
pr_info("Testing kprobe tracing: ");
|
|
|
|
|
|
|
|
- ret = traceprobe_command("p:testprobe kprobe_trace_selftest_target "
|
|
|
|
- "$stack $stack0 +0($stack)",
|
|
|
|
- create_trace_kprobe);
|
|
|
|
+ ret = trace_run_command("p:testprobe kprobe_trace_selftest_target "
|
|
|
|
+ "$stack $stack0 +0($stack)",
|
|
|
|
+ create_trace_kprobe);
|
|
|
|
if (WARN_ON_ONCE(ret)) {
|
|
|
|
pr_warn("error on probing function entry.\n");
|
|
|
|
warn++;
|
2017-11-20 14:16:49 +00:00
|
|
|
@@ -1455,8 +1455,8 @@ static __init int kprobe_trace_self_test
|
2017-07-09 11:42:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- ret = traceprobe_command("r:testprobe2 kprobe_trace_selftest_target "
|
|
|
|
- "$retval", create_trace_kprobe);
|
|
|
|
+ ret = trace_run_command("r:testprobe2 kprobe_trace_selftest_target "
|
|
|
|
+ "$retval", create_trace_kprobe);
|
|
|
|
if (WARN_ON_ONCE(ret)) {
|
|
|
|
pr_warn("error on probing function return.\n");
|
|
|
|
warn++;
|
2017-11-20 14:16:49 +00:00
|
|
|
@@ -1526,13 +1526,13 @@ static __init int kprobe_trace_self_test
|
2017-07-09 11:42:39 +00:00
|
|
|
disable_trace_kprobe(tk, file);
|
|
|
|
}
|
|
|
|
|
|
|
|
- ret = traceprobe_command("-:testprobe", create_trace_kprobe);
|
|
|
|
+ ret = trace_run_command("-:testprobe", create_trace_kprobe);
|
|
|
|
if (WARN_ON_ONCE(ret)) {
|
|
|
|
pr_warn("error on deleting a probe.\n");
|
|
|
|
warn++;
|
|
|
|
}
|
|
|
|
|
|
|
|
- ret = traceprobe_command("-:testprobe2", create_trace_kprobe);
|
|
|
|
+ ret = trace_run_command("-:testprobe2", create_trace_kprobe);
|
|
|
|
if (WARN_ON_ONCE(ret)) {
|
|
|
|
pr_warn("error on deleting a probe.\n");
|
|
|
|
warn++;
|
|
|
|
--- a/kernel/trace/trace_probe.c
|
|
|
|
+++ b/kernel/trace/trace_probe.c
|
|
|
|
@@ -623,92 +623,6 @@ void traceprobe_free_probe_arg(struct pr
|
|
|
|
kfree(arg->comm);
|
|
|
|
}
|
|
|
|
|
|
|
|
-int traceprobe_command(const char *buf, int (*createfn)(int, char **))
|
|
|
|
-{
|
|
|
|
- char **argv;
|
|
|
|
- int argc, ret;
|
|
|
|
-
|
|
|
|
- argc = 0;
|
|
|
|
- ret = 0;
|
|
|
|
- argv = argv_split(GFP_KERNEL, buf, &argc);
|
|
|
|
- if (!argv)
|
|
|
|
- return -ENOMEM;
|
|
|
|
-
|
|
|
|
- if (argc)
|
|
|
|
- ret = createfn(argc, argv);
|
|
|
|
-
|
|
|
|
- argv_free(argv);
|
|
|
|
-
|
|
|
|
- return ret;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-#define WRITE_BUFSIZE 4096
|
|
|
|
-
|
|
|
|
-ssize_t traceprobe_probes_write(struct file *file, const char __user *buffer,
|
|
|
|
- size_t count, loff_t *ppos,
|
|
|
|
- int (*createfn)(int, char **))
|
|
|
|
-{
|
|
|
|
- char *kbuf, *buf, *tmp;
|
|
|
|
- int ret = 0;
|
|
|
|
- size_t done = 0;
|
|
|
|
- size_t size;
|
|
|
|
-
|
|
|
|
- kbuf = kmalloc(WRITE_BUFSIZE, GFP_KERNEL);
|
|
|
|
- if (!kbuf)
|
|
|
|
- return -ENOMEM;
|
|
|
|
-
|
|
|
|
- while (done < count) {
|
|
|
|
- size = count - done;
|
|
|
|
-
|
|
|
|
- if (size >= WRITE_BUFSIZE)
|
|
|
|
- size = WRITE_BUFSIZE - 1;
|
|
|
|
-
|
|
|
|
- if (copy_from_user(kbuf, buffer + done, size)) {
|
|
|
|
- ret = -EFAULT;
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
- kbuf[size] = '\0';
|
|
|
|
- buf = kbuf;
|
|
|
|
- do {
|
|
|
|
- tmp = strchr(buf, '\n');
|
|
|
|
- if (tmp) {
|
|
|
|
- *tmp = '\0';
|
|
|
|
- size = tmp - buf + 1;
|
|
|
|
- } else {
|
|
|
|
- size = strlen(buf);
|
|
|
|
- if (done + size < count) {
|
|
|
|
- if (buf != kbuf)
|
|
|
|
- break;
|
|
|
|
- /* This can accept WRITE_BUFSIZE - 2 ('\n' + '\0') */
|
|
|
|
- pr_warn("Line length is too long: Should be less than %d\n",
|
|
|
|
- WRITE_BUFSIZE - 2);
|
|
|
|
- ret = -EINVAL;
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- done += size;
|
|
|
|
-
|
|
|
|
- /* Remove comments */
|
|
|
|
- tmp = strchr(buf, '#');
|
|
|
|
-
|
|
|
|
- if (tmp)
|
|
|
|
- *tmp = '\0';
|
|
|
|
-
|
|
|
|
- ret = traceprobe_command(buf, createfn);
|
|
|
|
- if (ret)
|
|
|
|
- goto out;
|
|
|
|
- buf += size;
|
|
|
|
-
|
|
|
|
- } while (done < count);
|
|
|
|
- }
|
|
|
|
- ret = done;
|
|
|
|
-
|
|
|
|
-out:
|
|
|
|
- kfree(kbuf);
|
|
|
|
-
|
|
|
|
- return ret;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static int __set_print_fmt(struct trace_probe *tp, char *buf, int len,
|
|
|
|
bool is_return)
|
|
|
|
{
|
|
|
|
--- a/kernel/trace/trace_probe.h
|
|
|
|
+++ b/kernel/trace/trace_probe.h
|
|
|
|
@@ -42,7 +42,6 @@
|
|
|
|
|
|
|
|
#define MAX_TRACE_ARGS 128
|
|
|
|
#define MAX_ARGSTR_LEN 63
|
|
|
|
-#define MAX_EVENT_NAME_LEN 64
|
|
|
|
#define MAX_STRING_SIZE PATH_MAX
|
|
|
|
|
|
|
|
/* Reserved field names */
|
|
|
|
@@ -356,12 +355,6 @@ extern void traceprobe_free_probe_arg(st
|
|
|
|
|
|
|
|
extern int traceprobe_split_symbol_offset(char *symbol, unsigned long *offset);
|
|
|
|
|
|
|
|
-extern ssize_t traceprobe_probes_write(struct file *file,
|
|
|
|
- const char __user *buffer, size_t count, loff_t *ppos,
|
|
|
|
- int (*createfn)(int, char**));
|
|
|
|
-
|
|
|
|
-extern int traceprobe_command(const char *buf, int (*createfn)(int, char**));
|
|
|
|
-
|
|
|
|
/* Sum up total data length for dynamic arraies (strings) */
|
|
|
|
static nokprobe_inline int
|
|
|
|
__get_data_size(struct trace_probe *tp, struct pt_regs *regs)
|
|
|
|
--- a/kernel/trace/trace_uprobe.c
|
|
|
|
+++ b/kernel/trace/trace_uprobe.c
|
|
|
|
@@ -651,7 +651,7 @@ static int probes_open(struct inode *ino
|
|
|
|
static ssize_t probes_write(struct file *file, const char __user *buffer,
|
|
|
|
size_t count, loff_t *ppos)
|
|
|
|
{
|
|
|
|
- return traceprobe_probes_write(file, buffer, count, ppos, create_trace_uprobe);
|
|
|
|
+ return trace_parse_run_command(file, buffer, count, ppos, create_trace_uprobe);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct file_operations uprobe_events_ops = {
|