linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Steven Rostedt <rostedt@goodmis.org>
To: linux-kernel@vger.kernel.org
Cc: Ingo Molnar <mingo@kernel.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Masami Hiramatsu <mhiramat@kernel.org>
Subject: [for-next][PATCH 15/18] tracing/kprobes: Allow kprobe-events to record module symbol
Date: Sun, 28 Oct 2018 03:30:03 -0400	[thread overview]
Message-ID: <20181028073135.762987515@goodmis.org> (raw)
In-Reply-To: 20181028072948.693267247@goodmis.org

From: Masami Hiramatsu <mhiramat@kernel.org>

Allow kprobe-events to record module symbols.

Since data symbols in a non-loaded module doesn't exist, it fails to
define such symbol as an argument of kprobe-event. But if the kprobe
event is defined on that module, we can defer to resolve the symbol
address.

Note that if given symbol is not found, the event is kept unavailable.
User can enable it but the event is not recorded.

Link: http://lkml.kernel.org/r/153547312336.26502.11432902826345374463.stgit@devbox

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 kernel/trace/trace_kprobe.c | 12 ++++++-
 kernel/trace/trace_probe.c  | 62 ++++++++++++++++++++++++++++++++-----
 kernel/trace/trace_probe.h  |  4 ++-
 3 files changed, 68 insertions(+), 10 deletions(-)

diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 4727a13824f0..fec67188c4d2 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -366,7 +366,7 @@ static bool within_notrace_func(struct trace_kprobe *tk)
 /* Internal register function - just handle k*probes and flags */
 static int __register_trace_kprobe(struct trace_kprobe *tk)
 {
-	int ret;
+	int i, ret;
 
 	if (trace_probe_is_registered(&tk->tp))
 		return -EINVAL;
@@ -377,6 +377,12 @@ static int __register_trace_kprobe(struct trace_kprobe *tk)
 		return -EINVAL;
 	}
 
+	for (i = 0; i < tk->tp.nr_args; i++) {
+		ret = traceprobe_update_arg(&tk->tp.args[i]);
+		if (ret)
+			return ret;
+	}
+
 	/* Set/clear disabled flag according to tp->flag */
 	if (trace_probe_is_enabled(&tk->tp))
 		tk->rp.kp.flags &= ~KPROBE_FLAG_DISABLED;
@@ -928,6 +934,7 @@ process_fetch_insn(struct fetch_insn *code, struct pt_regs *regs, void *dest,
 {
 	unsigned long val;
 
+retry:
 	/* 1st stage: get value from context */
 	switch (code->op) {
 	case FETCH_OP_REG:
@@ -953,6 +960,9 @@ process_fetch_insn(struct fetch_insn *code, struct pt_regs *regs, void *dest,
 		val = regs_get_kernel_argument(regs, code->param);
 		break;
 #endif
+	case FETCH_NOP_SYMBOL:	/* Ignore a place holder */
+		code++;
+		goto retry;
 	default:
 		return -EILSEQ;
 	}
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
index 333cda6d2633..5b3d573b3dcf 100644
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -251,16 +251,16 @@ parse_probe_arg(char *arg, const struct fetch_type *type,
 			if (!(flags & TPARG_FL_KERNEL))
 				return -EINVAL;
 
-			ret = traceprobe_split_symbol_offset(arg + 1, &offset);
-			if (ret)
-				break;
+			/* Preserve symbol for updating */
+			code->op = FETCH_NOP_SYMBOL;
+			code->data = kstrdup(arg + 1, GFP_KERNEL);
+			if (!code->data)
+				return -ENOMEM;
+			if (++code == end)
+				return -E2BIG;
 
 			code->op = FETCH_OP_IMM;
-			code->immediate =
-				(unsigned long)kallsyms_lookup_name(arg + 1);
-			if (!code->immediate)
-				return -ENOENT;
-			code->immediate += offset;
+			code->immediate = 0;
 		}
 		/* These are fetching from memory */
 		if (++code == end)
@@ -480,6 +480,11 @@ int traceprobe_parse_probe_arg(char *arg, ssize_t *size,
 		memcpy(parg->code, tmp, sizeof(*code) * (code - tmp + 1));
 
 fail:
+	if (ret) {
+		for (code = tmp; code < tmp + FETCH_INSN_MAX; code++)
+			if (code->op == FETCH_NOP_SYMBOL)
+				kfree(code->data);
+	}
 	kfree(tmp);
 
 	return ret;
@@ -504,12 +509,53 @@ int traceprobe_conflict_field_name(const char *name,
 
 void traceprobe_free_probe_arg(struct probe_arg *arg)
 {
+	struct fetch_insn *code = arg->code;
+
+	while (code && code->op != FETCH_OP_END) {
+		if (code->op == FETCH_NOP_SYMBOL)
+			kfree(code->data);
+		code++;
+	}
 	kfree(arg->code);
 	kfree(arg->name);
 	kfree(arg->comm);
 	kfree(arg->fmt);
 }
 
+int traceprobe_update_arg(struct probe_arg *arg)
+{
+	struct fetch_insn *code = arg->code;
+	long offset;
+	char *tmp;
+	char c;
+	int ret = 0;
+
+	while (code && code->op != FETCH_OP_END) {
+		if (code->op == FETCH_NOP_SYMBOL) {
+			if (code[1].op != FETCH_OP_IMM)
+				return -EINVAL;
+
+			tmp = strpbrk("+-", code->data);
+			if (tmp)
+				c = *tmp;
+			ret = traceprobe_split_symbol_offset(code->data,
+							     &offset);
+			if (ret)
+				return ret;
+
+			code[1].immediate =
+				(unsigned long)kallsyms_lookup_name(code->data);
+			if (tmp)
+				*tmp = c;
+			if (!code[1].immediate)
+				return -ENOENT;
+			code[1].immediate += offset;
+		}
+		code++;
+	}
+	return 0;
+}
+
 /* When len=0, we just calculate the needed length */
 #define LEN_OR_ZERO (len ? len - pos : 0)
 static int __set_print_fmt(struct trace_probe *tp, char *buf, int len,
diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h
index 09f62171cc23..974afc1a3e73 100644
--- a/kernel/trace/trace_probe.h
+++ b/kernel/trace/trace_probe.h
@@ -100,6 +100,7 @@ enum fetch_op {
 	// Stage 5 (loop) op
 	FETCH_OP_LP_ARRAY,	/* Array: .param = loop count */
 	FETCH_OP_END,
+	FETCH_NOP_SYMBOL,	/* Unresolved Symbol holder */
 };
 
 struct fetch_insn {
@@ -116,6 +117,7 @@ struct fetch_insn {
 			unsigned char rshift;
 		};
 		unsigned long immediate;
+		void *data;
 	};
 };
 
@@ -276,7 +278,7 @@ extern int traceprobe_parse_probe_arg(char *arg, ssize_t *size,
 extern int traceprobe_conflict_field_name(const char *name,
 			       struct probe_arg *args, int narg);
 
-extern void traceprobe_update_arg(struct probe_arg *arg);
+extern int traceprobe_update_arg(struct probe_arg *arg);
 extern void traceprobe_free_probe_arg(struct probe_arg *arg);
 
 extern int traceprobe_split_symbol_offset(char *symbol, long *offset);
-- 
2.19.0



  parent reply	other threads:[~2018-10-28  7:31 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-10-28  7:29 [for-next][PATCH 00/18] tracing: For this merge window Steven Rostedt
2018-10-28  7:29 ` [for-next][PATCH 01/18] tracing: probeevent: Cleanup print argument functions Steven Rostedt
2018-10-28  7:29 ` [for-next][PATCH 02/18] tracing: probeevent: Cleanup argument field definition Steven Rostedt
2018-10-28  7:29 ` [for-next][PATCH 03/18] tracing: probeevent: Remove NOKPROBE_SYMBOL from print functions Steven Rostedt
2018-10-28  7:29 ` [for-next][PATCH 04/18] tracing: probeevent: Introduce new argument fetching code Steven Rostedt
2018-10-28  7:29 ` [for-next][PATCH 05/18] tracing: probeevent: Unify fetch type tables Steven Rostedt
2018-10-28  7:29 ` [for-next][PATCH 06/18] tracing: probeevent: Return consumed bytes of dynamic area Steven Rostedt
2018-10-28  7:29 ` [for-next][PATCH 07/18] tracing: probeevent: Append traceprobe_ for exported function Steven Rostedt
2018-10-28  7:29 ` [for-next][PATCH 08/18] tracing: probeevent: Unify fetch_insn processing common part Steven Rostedt
2018-10-28  7:29 ` [for-next][PATCH 09/18] tracing: probeevent: Add symbol type Steven Rostedt
2018-10-28  7:29 ` [for-next][PATCH 10/18] tracing: probeevent: Add array type support Steven Rostedt
2018-10-28  7:29 ` [for-next][PATCH 11/18] x86: ptrace: Add function argument access API Steven Rostedt
2018-10-28  7:30 ` [for-next][PATCH 12/18] tracing: probeevent: Add $argN for accessing function args Steven Rostedt
2018-10-28  7:30 ` [for-next][PATCH 13/18] tracing/uprobes: Fix to return -EFAULT if copy_from_user failed Steven Rostedt
2018-10-28  7:30 ` [for-next][PATCH 14/18] tracing/kprobes: Check the probe on unloaded module correctly Steven Rostedt
2018-10-28  7:30 ` Steven Rostedt [this message]
2018-10-28  7:30 ` [for-next][PATCH 16/18] tracing: probeevent: Fix uninitialized used of offset in parse args Steven Rostedt
2018-10-28  7:30 ` [for-next][PATCH 17/18] tracing: Export trace_dump_stack to modules Steven Rostedt
2018-10-28  7:30 ` [for-next][PATCH 18/18] tracing: Have stack tracer trace full stack Steven Rostedt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181028073135.762987515@goodmis.org \
    --to=rostedt@goodmis.org \
    --cc=akpm@linux-foundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mhiramat@kernel.org \
    --cc=mingo@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).