Skip to content

Commit d9b1522

Browse files
Ye Binmhiramat
authored andcommitted
tracing/probes: support '%pd' type for print struct dentry's name
During fault locating, the file name needs to be printed based on the dentry address. The offset needs to be calculated each time, which is troublesome. Similar to printk, kprobe support print type '%pd' for print dentry's name. For example "name=$arg1:%pd" casts the `$arg1` as (struct dentry *), dereferences the "d_name.name" field and stores it to "name" argument as a kernel string. Here is an example: [tracing]# echo 'p:testprobe dput name=$arg1:%pd' > kprobe_events [tracing]# echo 1 > events/kprobes/testprobe/enable [tracing]# grep -q "1" events/kprobes/testprobe/enable [tracing]# echo 0 > events/kprobes/testprobe/enable [tracing]# cat trace | grep "enable" bash-14844 [002] ..... 16912.889543: testprobe: (dput+0x4/0x30) name="enable" grep-15389 [003] ..... 16922.834182: testprobe: (dput+0x4/0x30) name="enable" grep-15389 [003] ..... 16922.836103: testprobe: (dput+0x4/0x30) name="enable" bash-14844 [001] ..... 16931.820909: testprobe: (dput+0x4/0x30) name="enable" Note that this expects the given argument (e.g. $arg1) is an address of struct dentry. User must ensure it. Link: https://lore.kernel.org/all/[email protected]/ Signed-off-by: Ye Bin <[email protected]> Acked-by: Masami Hiramatsu (Google) <[email protected]> Signed-off-by: Masami Hiramatsu (Google) <[email protected]>
1 parent cdf355c commit d9b1522

File tree

5 files changed

+65
-1
lines changed

5 files changed

+65
-1
lines changed

kernel/trace/trace.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5540,7 +5540,7 @@ static const char readme_msg[] =
55405540
"\t kernel return probes support: $retval, $arg<N>, $comm\n"
55415541
"\t type: s8/16/32/64, u8/16/32/64, x8/16/32/64, char, string, symbol,\n"
55425542
"\t b<bit-width>@<bit-offset>/<container-size>, ustring,\n"
5543-
"\t symstr, <type>\\[<array-size>\\]\n"
5543+
"\t symstr, %pd, <type>\\[<array-size>\\]\n"
55445544
#ifdef CONFIG_HIST_TRIGGERS
55455545
"\t field: <stype> <name>;\n"
55465546
"\t stype: u8/u16/u32/u64, s8/s16/s32/s64, pid_t,\n"

kernel/trace/trace_fprobe.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,7 @@ static int __trace_fprobe_create(int argc, const char *argv[])
994994
char gbuf[MAX_EVENT_NAME_LEN];
995995
char sbuf[KSYM_NAME_LEN];
996996
char abuf[MAX_BTF_ARGS_LEN];
997+
char *dbuf = NULL;
997998
bool is_tracepoint = false;
998999
struct tracepoint *tpoint = NULL;
9991000
struct traceprobe_parse_context ctx = {
@@ -1104,6 +1105,10 @@ static int __trace_fprobe_create(int argc, const char *argv[])
11041105
argv = new_argv;
11051106
}
11061107

1108+
ret = traceprobe_expand_dentry_args(argc, argv, &dbuf);
1109+
if (ret)
1110+
goto out;
1111+
11071112
/* setup a probe */
11081113
tf = alloc_trace_fprobe(group, event, symbol, tpoint, maxactive,
11091114
argc, is_return);
@@ -1154,6 +1159,7 @@ static int __trace_fprobe_create(int argc, const char *argv[])
11541159
trace_probe_log_clear();
11551160
kfree(new_argv);
11561161
kfree(symbol);
1162+
kfree(dbuf);
11571163
return ret;
11581164

11591165
parse_error:

kernel/trace/trace_kprobe.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
782782
char buf[MAX_EVENT_NAME_LEN];
783783
char gbuf[MAX_EVENT_NAME_LEN];
784784
char abuf[MAX_BTF_ARGS_LEN];
785+
char *dbuf = NULL;
785786
struct traceprobe_parse_context ctx = { .flags = TPARG_FL_KERNEL };
786787

787788
switch (argv[0][0]) {
@@ -933,6 +934,10 @@ static int __trace_kprobe_create(int argc, const char *argv[])
933934
argv = new_argv;
934935
}
935936

937+
ret = traceprobe_expand_dentry_args(argc, argv, &dbuf);
938+
if (ret)
939+
goto out;
940+
936941
/* setup a probe */
937942
tk = alloc_trace_kprobe(group, event, addr, symbol, offset, maxactive,
938943
argc, is_return);
@@ -979,6 +984,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
979984
trace_probe_log_clear();
980985
kfree(new_argv);
981986
kfree(symbol);
987+
kfree(dbuf);
982988
return ret;
983989

984990
parse_error:

kernel/trace/trace_probe.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1739,6 +1739,56 @@ const char **traceprobe_expand_meta_args(int argc, const char *argv[],
17391739
return ERR_PTR(ret);
17401740
}
17411741

1742+
/* @buf: *buf must be equal to NULL. Caller must to free *buf */
1743+
int traceprobe_expand_dentry_args(int argc, const char *argv[], char **buf)
1744+
{
1745+
int i, used, ret;
1746+
const int bufsize = MAX_DENTRY_ARGS_LEN;
1747+
char *tmpbuf = NULL;
1748+
1749+
if (*buf)
1750+
return -EINVAL;
1751+
1752+
used = 0;
1753+
for (i = 0; i < argc; i++) {
1754+
if (glob_match("*:%pd", argv[i])) {
1755+
char *tmp;
1756+
char *equal;
1757+
1758+
if (!tmpbuf) {
1759+
tmpbuf = kmalloc(bufsize, GFP_KERNEL);
1760+
if (!tmpbuf)
1761+
return -ENOMEM;
1762+
}
1763+
1764+
tmp = kstrdup(argv[i], GFP_KERNEL);
1765+
if (!tmp)
1766+
goto nomem;
1767+
1768+
equal = strchr(tmp, '=');
1769+
if (equal)
1770+
*equal = '\0';
1771+
tmp[strlen(argv[i]) - 4] = '\0';
1772+
ret = snprintf(tmpbuf + used, bufsize - used,
1773+
"%s%s+0x0(+0x%zx(%s)):string",
1774+
equal ? tmp : "", equal ? "=" : "",
1775+
offsetof(struct dentry, d_name.name),
1776+
equal ? equal + 1 : tmp);
1777+
kfree(tmp);
1778+
if (ret >= bufsize - used)
1779+
goto nomem;
1780+
argv[i] = tmpbuf + used;
1781+
used += ret + 1;
1782+
}
1783+
}
1784+
1785+
*buf = tmpbuf;
1786+
return 0;
1787+
nomem:
1788+
kfree(tmpbuf);
1789+
return -ENOMEM;
1790+
}
1791+
17421792
void traceprobe_finish_parse(struct traceprobe_parse_context *ctx)
17431793
{
17441794
clear_btf_context(ctx);

kernel/trace/trace_probe.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#define MAX_ARRAY_LEN 64
3535
#define MAX_ARG_NAME_LEN 32
3636
#define MAX_BTF_ARGS_LEN 128
37+
#define MAX_DENTRY_ARGS_LEN 256
3738
#define MAX_STRING_SIZE PATH_MAX
3839
#define MAX_ARG_BUF_LEN (MAX_TRACE_ARGS * MAX_ARG_NAME_LEN)
3940

@@ -428,6 +429,7 @@ extern int traceprobe_parse_probe_arg(struct trace_probe *tp, int i,
428429
const char **traceprobe_expand_meta_args(int argc, const char *argv[],
429430
int *new_argc, char *buf, int bufsize,
430431
struct traceprobe_parse_context *ctx);
432+
extern int traceprobe_expand_dentry_args(int argc, const char *argv[], char **buf);
431433

432434
extern int traceprobe_update_arg(struct probe_arg *arg);
433435
extern void traceprobe_free_probe_arg(struct probe_arg *arg);

0 commit comments

Comments
 (0)