diff --git a/examples/uprobe_example.txt b/examples/uprobe_example.txt index 830ebfa..4384a93 100644 --- a/examples/uprobe_example.txt +++ b/examples/uprobe_example.txt @@ -286,12 +286,13 @@ a different method of stack walking. Use -h to print the USAGE message: # ./uprobe -h -USAGE: uprobe [-FhHsv] [-d secs] [-p PID] {-l target | +USAGE: uprobe [-FhHsv] [-d secs] [-p PID] [-L TID] {-l target | uprobe_definition [filter]} -F # force. trace despite warnings. -d seconds # trace duration, and use buffers -l target # list functions from this executable - -p PID # PID to match on I/O issue + -p PID # PID to match on events + -L TID # thread id to match on events -v # view format file (don't trace) -H # include column headers -s # show user stack traces diff --git a/man/man8/uprobe.8 b/man/man8/uprobe.8 index 807c77e..67f4675 100644 --- a/man/man8/uprobe.8 +++ b/man/man8/uprobe.8 @@ -3,7 +3,7 @@ uprobe \- trace a given uprobe definition. User-level dynamic tracing. Uses Linux ftrace. EXPERIMENTAL. .SH SYNOPSIS .B uprobe -[\-FhHsv] [\-d secs] [\-p PID] {\-l target | uprobe_definition [filter]} +[\-FhHsv] [\-d secs] [\-p PID] [\-L TID] {\-l target | uprobe_definition [filter]} .SH DESCRIPTION This will create, trace, then destroy a given uprobe definition. See Documentation/trace/uprobetracer.txt in the Linux kernel source for the @@ -70,6 +70,9 @@ for use in a custom filter. \-p PID Only trace user-level functions when this process ID is on-CPU. .TP +\-L TID +Only trace user-level functions when this thread ID is on-CPU. +.TP uprobe_definition A full uprobe definition, as documented by Documentation/trace/uprobetracer.txt in the Linux kernel source. Note that the probe alias name is optional with diff --git a/user/uprobe b/user/uprobe index baa11ee..ff407ec 100755 --- a/user/uprobe +++ b/user/uprobe @@ -8,7 +8,7 @@ # syntax of a uprobe definition, and "uprobe -h" for examples. With this tool, # the probe alias is optional (it will default to something meaningful). # -# USAGE: ./uprobe [-FhHsv] [-d secs] [-p pid] {-l target | +# USAGE: ./uprobe [-FhHsv] [-d secs] [-p pid] [-L tid] {-l target | # uprobe_definition [filter]} # # Run "uprobe -h" for full usage. @@ -63,20 +63,21 @@ ### default variables tracing=/sys/kernel/debug/tracing flock=/var/tmp/.ftrace-lock; wroteflock=0 -opt_duration=0; duration=; opt_pid=0; pid=; opt_filter=0; filter= -opt_view=0; opt_headers=0; opt_stack=0; dmesg=2; debug=0; opt_force=0 -opt_list=0; target= +opt_duration=0; duration=; opt_pid=0; pid=; opt_tid=0; tid= +opt_filter=0; filter=; opt_view=0; opt_headers=0; opt_stack=0; dmesg=2 +debug=0; opt_force=0; opt_list=0; target= PATH=$PATH:/usr/bin:/sbin # ensure we find objdump, ldconfig trap ':' INT QUIT TERM PIPE HUP # sends execution to end tracing section function usage { cat <<-END >&2 - USAGE: uprobe [-FhHsv] [-d secs] [-p PID] {-l target | + USAGE: uprobe [-FhHsv] [-d secs] [-p PID] [-L TID] {-l target | uprobe_definition [filter]} -F # force. trace despite warnings. -d seconds # trace duration, and use buffers -l target # list functions from this executable -p PID # PID to match on events + -L TID # thread id to match on events -v # view format file (don't trace) -H # include column headers -s # show user stack traces @@ -192,12 +193,13 @@ function set_addr { } ### process options -while getopts Fd:hHl:p:sv opt +while getopts Fd:hHl:p:L:sv opt do case $opt in F) opt_force=1 ;; d) opt_duration=1; duration=$OPTARG ;; p) opt_pid=1; pid=$OPTARG ;; + L) opt_tid=1; tid=$OPTARG ;; l) opt_list=1; target=$OPTARG ;; H) opt_headers=1 ;; s) opt_stack=1 ;; @@ -248,12 +250,21 @@ done ### option logic [[ "$uprobe" == "" ]] && usage -(( opt_pid && opt_filter )) && die "ERROR: use either -p or a filter." +(( opt_pid + opt_filter + opt_tid > 1 )) && \ + die "ERROR: use at most one of -p, -L, or filter." (( opt_duration && opt_view )) && die "ERROR: use either -d or -v." if (( opt_pid )); then # convert to filter opt_filter=1 - filter="common_pid == $pid" + # ftrace common_pid is thread id from user's perspective + for tid in /proc/$pid/task/*; do + filter="$filter || common_pid == ${tid##*/}" + done + filter=${filter:3} # trim leading ' || ' (four characters) +fi +if (( opt_tid )); then + opt_filter=1 + filter="common_pid == $tid" fi if [[ "$uprobe" != p:* && "$uprobe" != r:* ]]; then echo >&2 "ERROR: invalid uprobe definition (should start with p: or r:)"