Unverified Commit 7a5c3dc8 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!11207 kprobe support %pd/%pD type

Merge Pull Request from: @ci-robot 
 
PR sync from: Ye Bin <yebin10@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/J22ELT2FMYM2H2B4DOYTDROF72E36JLO/ 
Ye Bin (4):
  tracing/probes: support '%pd' type for print struct dentry's name
  tracing/probes: support '%pD' type for print struct file's name
  Documentation: tracing: add new type '%pd' and '%pD' for kprobe
  selftests/ftrace: add kprobe test cases for VFS type "%pd" and "%pD"


-- 
2.34.1
 
https://gitee.com/openeuler/kernel/issues/IAMXDU 
 
Link:https://gitee.com/openeuler/kernel/pulls/11207

 

Reviewed-by: default avatarYe Weihua <yeweihua4@huawei.com>
Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
parents fe66df0f 60a19550
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -58,8 +58,8 @@ Synopsis of kprobe_events
  NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
  FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
		  (u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types
		  (x8/x16/x32/x64), "string", "ustring" and bitfield
		  are supported.
		  (x8/x16/x32/x64), VFS layer common type(%pd/%pD),
		  "string", "ustring" and bitfield are supported.

  (\*1) only for the probe on function entry (offs == 0).
  (\*2) only for return probe.
@@ -98,6 +98,9 @@ Symbol type('symbol') is an alias of u32 or u64 type (depends on BITS_PER_LONG)
which shows given pointer in "symbol+offset" style.
For $comm, the default type is "string"; any other type is invalid.

VFS layer common type(%pd/%pD) is a special type, which fetches dentry's or
file's name from struct dentry's address or struct file's address.

.. _user_mem_access:

User Memory Access
+1 −1
Original line number Diff line number Diff line
@@ -5284,7 +5284,7 @@ static const char readme_msg[] =
	"\t           +|-[u]<offset>(<fetcharg>), \\imm-value, \\\"imm-string\"\n"
	"\t     type: s8/16/32/64, u8/16/32/64, x8/16/32/64, string, symbol,\n"
	"\t           b<bit-width>@<bit-offset>/<container-size>, ustring,\n"
	"\t           <type>\\[<array-size>\\]\n"
	"\t           %pd/%pD, <type>\\[<array-size>\\]\n"
#ifdef CONFIG_HIST_TRIGGERS
	"\t    field: <stype> <name>;\n"
	"\t    stype: u8/u16/u32/u64, s8/s16/s32/s64, pid_t,\n"
+6 −0
Original line number Diff line number Diff line
@@ -750,6 +750,7 @@ static int trace_kprobe_create(int argc, const char *argv[])
	long offset = 0;
	void *addr = NULL;
	char buf[MAX_EVENT_NAME_LEN];
	char *dbuf = NULL;
	unsigned int flags = TPARG_FL_KERNEL;

	switch (argv[0][0]) {
@@ -860,6 +861,10 @@ static int trace_kprobe_create(int argc, const char *argv[])
		event = buf;
	}

	ret = traceprobe_expand_dentry_args(argc, argv, &dbuf);
	if (ret)
		goto out;

	/* setup a probe */
	tk = alloc_trace_kprobe(group, event, addr, symbol, offset, maxactive,
			       argc - 2, is_return);
@@ -905,6 +910,7 @@ static int trace_kprobe_create(int argc, const char *argv[])
out:
	trace_probe_log_clear();
	kfree(symbol);
	kfree(dbuf);
	return ret;

parse_error:
+64 −0
Original line number Diff line number Diff line
@@ -11,6 +11,8 @@
 */
#define pr_fmt(fmt)	"trace_probe: " fmt

#include <linux/fs.h>

#include "trace_probe.h"

#undef C
@@ -803,6 +805,68 @@ void traceprobe_free_probe_arg(struct probe_arg *arg)
	kfree(arg->fmt);
}

/* @buf: *buf must be equal to NULL. Caller must to free *buf */
int traceprobe_expand_dentry_args(int argc, const char *argv[], char **buf)
{
	int i, used, ret;
	const int bufsize = MAX_DENTRY_ARGS_LEN;
	char *tmpbuf = NULL;

	if (*buf)
		return -EINVAL;

	used = 0;
	for (i = 0; i < argc; i++) {
		char *tmp;
		char *equal;
		size_t arg_len;

		if (!glob_match("*:%p[dD]", argv[i]))
			continue;

		if (!tmpbuf) {
			tmpbuf = kmalloc(bufsize, GFP_KERNEL);
			if (!tmpbuf)
				return -ENOMEM;
		}

		tmp = kstrdup(argv[i], GFP_KERNEL);
		if (!tmp)
			goto nomem;

		equal = strchr(tmp, '=');
		if (equal)
			*equal = '\0';
		arg_len = strlen(argv[i]);
		tmp[arg_len - 4] = '\0';
		if (argv[i][arg_len - 1] == 'd')
			ret = snprintf(tmpbuf + used, bufsize - used,
				       "%s%s+0x0(+0x%zx(%s)):string",
				       equal ? tmp : "", equal ? "=" : "",
				       offsetof(struct dentry, d_name.name),
				       equal ? equal + 1 : tmp);
		else
			ret = snprintf(tmpbuf + used, bufsize - used,
				       "%s%s+0x0(+0x%zx(+0x%zx(%s))):string",
				       equal ? tmp : "", equal ? "=" : "",
				       offsetof(struct dentry, d_name.name),
				       offsetof(struct file, f_path.dentry),
				       equal ? equal + 1 : tmp);

		kfree(tmp);
		if (ret >= bufsize - used)
			goto nomem;
		argv[i] = tmpbuf + used;
		used += ret + 1;
	}

	*buf = tmpbuf;
	return 0;
nomem:
	kfree(tmpbuf);
	return -ENOMEM;
}

int traceprobe_update_arg(struct probe_arg *arg)
{
	struct fetch_insn *code = arg->code;
+2 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#define MAX_ARGSTR_LEN		63
#define MAX_ARRAY_LEN		64
#define MAX_ARG_NAME_LEN	32
#define MAX_DENTRY_ARGS_LEN	256
#define MAX_STRING_SIZE		PATH_MAX

/* Reserved field names */
@@ -355,6 +356,7 @@ bool trace_probe_match_command_args(struct trace_probe *tp,
extern int traceprobe_parse_probe_arg(struct trace_probe *tp, int i,
				char *arg, unsigned int flags);

extern int traceprobe_expand_dentry_args(int argc, const char *argv[], char **buf);
extern int traceprobe_update_arg(struct probe_arg *arg);
extern void traceprobe_free_probe_arg(struct probe_arg *arg);

Loading