tracing, kprobes: Fix kprobe symbol offset (for minus)
Subsystems (3)
Steven Rostedt
maintainerLinus,
The documentation for kprobe events says that symbol offets can take both a + and - sign to get to before and after the symbol address. But in actuality, the code does not support the minus. This fixes that issue, and adds a few more selftests to kprobe events.
Please pull the latest trace-v4.16-rc4 tree, which can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
trace-v4.16-rc4
Tag SHA1: d92df88947baacdf2ebfe80871fb1c6f9211aa80 Head SHA1: dfa453bc90eca0febff33c8d292a656e53702158
Masami Hiramatsu (4):
tracing: probeevent: Fix to support minus offset from symbol
selftests: ftrace: Add probe event argument syntax testcase
selftests: ftrace: Add a testcase for string type with kprobe_event
selftests: ftrace: Add a testcase for probepoint
----
kernel/trace/trace_kprobe.c | 4 +- kernel/trace/trace_probe.c | 8 +- kernel/trace/trace_probe.h | 2 +- .../ftrace/test.d/kprobe/kprobe_args_string.tc | 46 ++++++++++ .../ftrace/test.d/kprobe/kprobe_args_syntax.tc | 97 ++++++++++++++++++++++ .../selftests/ftrace/test.d/kprobe/probepoint.tc | 43 ++++++++++ 6 files changed, 192 insertions(+), 8 deletions(-) create mode 100644 tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc create mode 100644 tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_syntax.tc create mode 100644 tools/testing/selftests/ftrace/test.d/kprobe/probepoint.tc
Steven Rostedt
maintainerPATCH 1/4 tracing: probeevent: Fix to support minus offset from symbol
From: Masami Hiramatsu <[email protected]>
In Documentation/trace/kprobetrace.txt, it says
@SYM[+|-offs] : Fetch memory at SYM +|- offs (SYM should be a data symbol)
However, the parser doesn't parse minus offset correctly, since commit 2fba0c8867af ("tracing/kprobes: Fix probe offset to be unsigned") drops minus ("-") offset support for kprobe probe address usage.
This fixes the traceprobe_split_symbol_offset() to parse minus offset again with checking the offset range, and add a minus offset check in kprobe probe address usage.
--- kernel/trace/trace_kprobe.c | 4 ++-- kernel/trace/trace_probe.c | 8 +++----- kernel/trace/trace_probe.h | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-)
kernel/trace/trace_kprobe.c +2 -2
@@ -659,7 +659,7 @@ static int create_trace_kprobe(int argc, char **argv)char *symbol =NULL , *event =NULL , *group =NULL ;int maxactive =0 ;char *arg; -unsigned long offset =0 ; +long offset =0 ;void *addr =NULL ;char buf[MAX_EVENT_NAME_LEN ];
@@ -747,7 +747,7 @@ static int create_trace_kprobe(int argc, char **argv) symbol = argv[1 ];/* TODO: support .init module functions */ ret =traceprobe_split_symbol_offset (symbol, &offset); -if (ret) { +if (ret || offset <0 || offset >UINT_MAX ) {pr_info ("Failed to parse either an address or a symbol.\n" );return ret; }
kernel/trace/trace_probe.c +3 -5
@@ -320,7 +320,7 @@ static fetch_func_t get_fetch_size_function(const struct fetch_type *type, }/* Split symbol and offset. */ -int traceprobe_split_symbol_offset (char *symbol,unsigned long *offset) +int traceprobe_split_symbol_offset (char *symbol,long *offset) {char *tmp;int ret;
@@ -328,13 +328,11 @@ int traceprobe_split_symbol_offset(char *symbol, unsigned long *offset)if (!offset)return -EINVAL ; - tmp =strchr (symbol,'+' ); + tmp =strpbrk (symbol,"+-" );if (tmp) { -/* skip sign because kstrtoul doesn't accept '+' */ - ret =kstrtoul (tmp +1 ,0 , offset); + ret =kstrtol (tmp,0 , offset);if (ret)return ret; - *tmp ='\0' ; }else *offset =0 ;
kernel/trace/trace_probe.h +1 -1
@@ -365,7 +365,7 @@ extern int traceprobe_conflict_field_name(const char *name,extern void 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,unsigned long *offset); +extern int traceprobe_split_symbol_offset (char *symbol,long *offset);/* Sum up total data length for dynamic arraies (strings) */ static nokprobe_inline int
Signature · 1 line
2.15.1
Steven Rostedt
maintainerPATCH 2/4 selftests: ftrace: Add probe event argument syntax testcase
In reply to Steven RostedtFrom: Masami Hiramatsu <[email protected]>
Add a testcase for probe event argument syntax which ensures the kprobe_events interface correctly parses given event arguments.
--- .../ftrace/test.d/kprobe/kprobe_args_syntax.tc | 97 ++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_syntax.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_syntax.tc new file +97 -0
@@ -0,0 +1,97 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Kprobe event argument syntax + +[ -f kprobe_events ] || exit_unsupported # this is configurable + +grep "x8/16/32/64" README > /dev/null || exit_unsupported # version issue + +echo 0 > events/enable +echo > kprobe_events + +PROBEFUNC="vfs_read" +GOODREG= +BADREG= +GOODSYM="_sdata" +if ! grep -qw ${GOODSYM} /proc/kallsyms ; then + GOODSYM=$PROBEFUNC +fi +BADSYM="deaqswdefr" +SYMADDR=0x`grep -w ${GOODSYM} /proc/kallsyms | cut -f 1 -d " "` +GOODTYPE="x16" +BADTYPE="y16" + +case `uname -m` in +x86_64|i[3456]86) + GOODREG=%ax + BADREG=%ex +;; +aarch64) + GOODREG=%x0 + BADREG=%ax +;; +arm*) + GOODREG=%r0 + BADREG=%ax +;; +esac + +test_goodarg() # Good-args +{ + while [ "$1" ]; do + echo "p ${PROBEFUNC} $1" > kprobe_events + shift 1 + done; +} + +test_badarg() # Bad-args +{ + while [ "$1" ]; do + ! echo "p ${PROBEFUNC} $1" > kprobe_events + shift 1 + done; +} + +echo > kprobe_events + +: "Register access" +test_goodarg ${GOODREG} +test_badarg ${BADREG} + +: "Symbol access" +test_goodarg "@${GOODSYM}" "@${SYMADDR}" "@${GOODSYM}+10" "@${GOODSYM}-10" +test_badarg "@" "@${BADSYM}" "@${GOODSYM}*10" "@${GOODSYM}/10" \ + "@${GOODSYM}%10" "@${GOODSYM}&10" "@${GOODSYM}|10" + +: "Stack access" +test_goodarg "\$stack" "\$stack0" "\$stack1" +test_badarg "\$stackp" "\$stack0+10" "\$stack1-10" + +: "Retval access" +echo "r ${PROBEFUNC} \$retval" > kprobe_events +! echo "p ${PROBEFUNC} \$retval" > kprobe_events + +: "Comm access" +test_goodarg "\$comm" + +: "Indirect memory access" +test_goodarg "+0(${GOODREG})" "-0(${GOODREG})" "+10(\$stack)" \ + "+0(\$stack1)" "+10(@${GOODSYM}-10)" "+0(+10(+20(\$stack)))" +test_badarg "+(${GOODREG})" "(${GOODREG}+10)" "-(${GOODREG})" "(${GOODREG})" \ + "+10(\$comm)" "+0(${GOODREG})+10" + +: "Name assignment" +test_goodarg "varname=${GOODREG}" +test_badarg "varname=varname2=${GOODREG}" + +: "Type syntax" +test_goodarg "${GOODREG}:${GOODTYPE}" +test_badarg "${GOODREG}::${GOODTYPE}" "${GOODREG}:${BADTYPE}" \ + "${GOODTYPE}:${GOODREG}" + +: "Combination check" + +test_goodarg "\$comm:string" "+0(\$stack):string" +test_badarg "\$comm:x64" "\$stack:string" "${GOODREG}:string" + +echo > kprobe_events
Signature · 1 line
2.15.1
Steven Rostedt
maintainerPATCH 3/4 selftests: ftrace: Add a testcase for string type with kprobe_event
In reply to Steven RostedtFrom: Masami Hiramatsu <[email protected]>
Add a testcase for string type with kprobe event.
This tests good/bad syntax combinations and also
the traced data is correct in several way.
--- .../ftrace/test.d/kprobe/kprobe_args_string.tc | 46 ++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc new file +46 -0
@@ -0,0 +1,46 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Kprobe event string type argument + +[ -f kprobe_events ] || exit_unsupported # this is configurable + +echo 0 > events/enable +echo > kprobe_events + +case `uname -m` in +x86_64) + ARG2=%si + OFFS=8 +;; +i[3456]86) + ARG2=%cx + OFFS=4 +;; +aarch64) + ARG2=%x1 + OFFS=8 +;; +arm*) + ARG2=%r1 + OFFS=4 +;; +*) + echo "Please implement other architecture here" + exit_untested +esac + +: "Test get argument (1)" +echo "p:testprobe create_trace_kprobe arg1=+0(+0(${ARG2})):string" > kprobe_events +echo 1 > events/kprobes/testprobe/enable +! echo test >> kprobe_events +tail -n 1 trace | grep -qe "testprobe.* arg1=\"test\"" + +echo 0 > events/kprobes/testprobe/enable +: "Test get argument (2)" +echo "p:testprobe create_trace_kprobe arg1=+0(+0(${ARG2})):string arg2=+0(+${OFFS}(${ARG2})):string" > kprobe_events +echo 1 > events/kprobes/testprobe/enable +! echo test1 test2 >> kprobe_events +tail -n 1 trace | grep -qe "testprobe.* arg1=\"test1\" arg2=\"test2\"" + +echo 0 > events/enable +echo > kprobe_events
Signature · 1 line
2.15.1
Steven Rostedt
maintainerPATCH 4/4 selftests: ftrace: Add a testcase for probepoint
In reply to Steven RostedtFrom: Masami Hiramatsu <[email protected]>
Add a testcase for probe point definition. This tests symbol, address and symbol+offset syntax. The offset must be positive and smaller than UINT_MAX.
--- .../selftests/ftrace/test.d/kprobe/probepoint.tc | 43 ++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tools/testing/selftests/ftrace/test.d/kprobe/probepoint.tc
tools/testing/selftests/ftrace/test.d/kprobe/probepoint.tc new file +43 -0
@@ -0,0 +1,43 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Kprobe events - probe points + +[ -f kprobe_events ] || exit_unsupported # this is configurable + +TARGET_FUNC=create_trace_kprobe + +dec_addr() { # hexaddr + printf "%d" "0x"`echo $1 | tail -c 8` +} + +set_offs() { # prev target next + A1=`dec_addr $1` + A2=`dec_addr $2` + A3=`dec_addr $3` + TARGET="0x$2" # an address + PREV=`expr $A1 - $A2` # offset to previous symbol + NEXT=+`expr $A3 - $A2` # offset to next symbol + OVERFLOW=+`printf "0x%x" ${PREV}` # overflow offset to previous symbol +} + +# We have to decode symbol addresses to get correct offsets. +# If the offset is not an instruction boundary, it cause -EILSEQ. +set_offs `grep -A1 -B1 ${TARGET_FUNC} /proc/kallsyms | cut -f 1 -d " " | xargs` + +UINT_TEST=no +# printf "%x" -1 returns (unsigned long)-1. +if [ `printf "%x" -1 | wc -c` != 9 ]; then + UINT_TEST=yes +fi + +echo 0 > events/enable +echo > kprobe_events +echo "p:testprobe ${TARGET_FUNC}" > kprobe_events +echo "p:testprobe ${TARGET}" > kprobe_events +echo "p:testprobe ${TARGET_FUNC}${NEXT}" > kprobe_events +! echo "p:testprobe ${TARGET_FUNC}${PREV}" > kprobe_events +if [ "${UINT_TEST}" = yes ]; then +! echo "p:testprobe ${TARGET_FUNC}${OVERFLOW}" > kprobe_events +fi +echo > kprobe_events +clear_trace
Signature · 1 line
2.15.1