* What's new in version 2.6
+- process("PATH").library("PATH").plt("NAME").return probes are now supported.
+
- SystemTap now supports SDT probes with operands that refer to symbols.
- While in listing mode (-l/-L), probes printed are now more consistent
process("PATH").function("foo").callees(DEPTH)
process(PID).function("NAME")
process(PID).function("myfun").label("foo")
-process(PID).plt("NAME)
+process(PID).plt("NAME")
+process(PID).plt("NAME").return
process(PID).statement("*@FILE.c:123")
process(PID).statement(ADDRESS).absolute
.ESAMPLE
process("PATH").function("*").return
process("PATH").function("myfun").label("foo")
process("PATH").function("foo").callee("bar")
+process("PATH").plt("NAME").return
process(PID).function("NAME")
process(PID).statement("*@FILE.c:123")
process(PID).plt("NAME")
corresponding to the rest of the probe point. .plt can be specified
as a shorthand for .plt("*"). The symbol name is available as a
$$name context variable; function arguments are not available, since
-PLTs are processed without debuginfo.
+PLTs are processed without debuginfo. A .plt.return probe places a
+probe at the moment \fBafter\fR the return from the named
+function.
.PP
If the PATH string contains wildcards as in the MPATTERN case, then
string e = string(entry);
plt_expanding_visitor pltv (e);
pltv.replace (new_base->body);
- derive_probes(dw.sess, new_base, results);
+
+ literal_map_t params;
+ for (unsigned i = 0; i < derived_loc->components.size(); ++i)
+ {
+ probe_point::component *c = derived_loc->components[i];
+ params[c->functor] = c->arg;
+ }
+ dwarf_query derived_q(new_base, derived_loc, dw, params, results, "", "");
+ dw.iterate_over_modules<base_query>(&query_module, &derived_q);
}
root->bind_str(TOK_PLT)
->bind_privilege(pr_all)
->bind(dw);
- root->bind(TOK_PLT)->bind_num(TOK_STATEMENT)
+
+ root->bind(TOK_PLT)
+ ->bind(TOK_RETURN)
->bind_privilege(pr_all)
->bind(dw);
- root->bind_str(TOK_PLT)->bind_num(TOK_STATEMENT)
+ root->bind_str(TOK_PLT)
+ ->bind(TOK_RETURN)
->bind_privilege(pr_all)
->bind(dw);
}
# PR14297-related testing
-set stap_path $env(SYSTEMTAP_PATH)/stap
+set stap_path [file normalize $env(SYSTEMTAP_PATH)/stap]
proc test_list { test input output_re } {
spawn stap -l $input
test_plt_list plt-non-glob {process("stap").plt("read")} \
"^process\\\(\"$stap_path\"\\\)\\\.plt\\\(\"read\"\\\)\r\n$"
+test_plt_list plt-glob-ret {process("stap").plt("re??").return} \
+ "^process\\\(\"$stap_path\"\\\)\\\.plt\\\(\"read\"\\\).return\r\n$"
+
+test_plt_list plt-glob2-ret {process("stap").plt("re*").return} \
+ "^process\\\(\"$stap_path\"\\\)\\\.plt\\\(\"re\[a-zA-Z0-9_\]*\"\\\).return\r\n"
+
+test_plt_list plt-non-glob-ret {process("stap").plt("read").return} \
+ "^process\\\(\"$stap_path\"\\\)\\\.plt\\\(\"read\"\\\).return\r\n$"
+
test_uprobes_list mark-non-glob {process("stap").mark("pass5__end")} \
"^process\\\(\"$stap_path\"\\\)\\\.mark\\\(\"pass5__end\"\\\)\r\n$"
}
process.library(string).plt -
- process.library(string).plt.statement(number) -
+ process.library(string).plt.return -
process.library(string).plt(string) -
- process.library(string).plt(string).statement(number) -
+ process.library(string).plt(string.return) -
process(string).library(string).plt -
- process(string).library(string).plt.statement(number) -
+ process(string).library(string).plt.return -
process(string).library(string).plt(string) -
- process(string).library(string).plt(string).statement(number) -
+ process(string).library(string).plt(string.return) -
process.plt -
- process.plt.statement(number) -
+ process.plt.return -
process.plt(string) -
- process.plt(string).statement(number) -
+ process.plt(string).return -
process(string).plt -
- process(string).plt.statement(number) -
+ process(string).plt.return -
process(string).plt(string) -
- process(string).plt(string).statement(number)
+ process(string).plt(string).return
{
if {![plt_probes_p]} {
setup_kfail PLT *-*-*
stap_list_cmd_lib "process.library(\"sopath\").plt" \
"re:process\\\(\"$exefullpath\"\\\)\\\.library\\\(\"$sofullpath\"\\\)\\\.plt\\\(\"\[^\"\]+\"\\\)" {-1}
- testing_probe {process.library(string).plt.statement(number)}
+ testing_probe {process.library(string).plt.return}
- stap_list_cmd_lib "process.library(\"sopath\").plt.statement(0x123)" \
- "re:process\\\(\"$exefullpath\"\\\)\\\.library\\\(\"$sofullpath\"\\\)\\\.statement\\\(0x\[a-f0-9\]+\\\)"
+ stap_list_cmd_lib "process.library(\"sopath\").plt.return" \
+ "re:process\\\(\"$exefullpath\"\\\)\\\.library\\\(\"$sofullpath\"\\\)\\\.plt\\\(\"\[^\"\]+\"\\\).return" {-1}
testing_probe {process.library(string).plt(string)}
stap_list_cmd_lib "process.library(\"sopath\").plt(\"\\\[lp\\\]*\")" \
"re:process\\\(\"$exefullpath\"\\\)\\\.library\\\(\"$sofullpath\"\\\)\\\.plt\\\(\"(libbar|printf)\"\\\)" {-1}
- testing_probe {process.library(string).plt(string).statement(number)}
+ testing_probe {process.library(string).plt(string).return}
- stap_list_cmd_lib "process.library(\"sopath\").plt(\"libbar\").statement(0x123)" \
- "re:process\\\(\"$exefullpath\"\\\)\\\.library\\\(\"$sofullpath\"\\\)\\\.statement\\\(0x\[a-f0-9\]+\\\)"
+ stap_list_cmd_lib "process.library(\"sopath\").plt(\"libbar\").return" \
+ "re:process\\\(\"$exefullpath\"\\\)\\\.library\\\(\"$sofullpath\"\\\)\\\.plt\\\(\"libbar\"\\\).return"
- stap_list_cmd_lib "process.library(\"sopath\").plt(\"libba?\").statement(0x123)" \
- "re:process\\\(\"$exefullpath\"\\\)\\\.library\\\(\"$sofullpath\"\\\)\\\.statement\\\(0x\[a-f0-9\]+\\\)"
+ stap_list_cmd_lib "process.library(\"sopath\").plt(\"libba?\").return" \
+ "re:process\\\(\"$exefullpath\"\\\)\\\.library\\\(\"$sofullpath\"\\\)\\\.plt\\\(\"libbar\"\\\).return"
- stap_list_cmd_lib "process.library(\"sopath\").plt(\"\\\[lp\\\]*\").statement(0x123)" \
- "re:process\\\(\"$exefullpath\"\\\)\\\.library\\\(\"$sofullpath\"\\\)\\\.statement\\\(0x\[a-f0-9\]+\\\)"
+ stap_list_cmd_lib "process.library(\"sopath\").plt(\"\\\[lp\\\]*\").return" \
+ "re:process\\\(\"$exefullpath\"\\\)\\\.library\\\(\"$sofullpath\"\\\)\\\.plt\\\(\"(libbar|printf)\"\\\).return" {-1}
}
testing_probe {process.library(string).provider(string).mark(string)}
stap_list_cmd "process.plt" \
"re:process\\\(\"$exefullpath\"\\\)\\\.plt\\\(\"\[^\"\]+\"\\\)" {-1}
- testing_probe {process.plt.statement(number)}
- stap_list_cmd "process.plt.statement(0x123)" \
- "re:process\\\(\"$exefullpath\"\\\)\\\.statement\\\(0x\[a-f0-9\]+\\\)"
+ testing_probe {process.plt.return}
+
+ stap_list_cmd "process.plt.return" \
+ "re:process\\\(\"$exefullpath\"\\\)\\\.plt\\\(\"\[^\"\]+\"\\\).return" {-1}
testing_probe {process.plt(string)}
stap_list_cmd "process.plt(\"libfo?\")" \
"re:process\\\(\"$exefullpath\"\\\)\\\.plt\\\(\"libfoo\"\\\)"
- stap_list_cmd "process.plt(\"\\\[lp\\\]*\")" \
- "re:process\\\(\"$exefullpath\"\\\)\\\.plt\\\(\"(libfoo|printf)\"\\\)" {-1}
-
- testing_probe {process.plt(string).statement(number)}
+ testing_probe {process.plt(string).return}
- stap_list_cmd "process.plt(\"libfoo\").statement(0x123)" \
- "re:process\\\(\"$exefullpath\"\\\)\\\.statement\\\(0x\[a-f0-9\]+\\\)"
+ stap_list_cmd "process.plt(\"libfoo\").return" \
+ "re:process\\\(\"$exefullpath\"\\\)\\\.plt\\\(\"libfoo\"\\\).return"
- stap_list_cmd "process.plt(\"libfo?\").statement(0x123)" \
- "re:process\\\(\"$exefullpath\"\\\)\\\.statement\\\(0x\[a-f0-9\]+\\\)"
+ stap_list_cmd "process.plt(\"libfo?\").return" \
+ "re:process\\\(\"$exefullpath\"\\\)\\\.plt\\\(\"libfoo\"\\\).return"
- stap_list_cmd "process.plt(\"\\\[lp\\\]*\").statement(0x123)" \
- "re:process\\\(\"$exefullpath\"\\\)\\\.statement\\\(0x\[a-f0-9\]+\\\)"
+ stap_list_cmd "process.plt(\"\\\[lp\\\]*\").return" \
+ "re:process\\\(\"$exefullpath\"\\\)\\\.plt\\\(\"(libfoo|printf)\"\\\).return" {-1}
}
testing_probe {process.provider(string).mark(string)}
stap_list "process($valid_pid).plt" \
"re:process\\\(\"$exefullpath\"\\\)\\\.plt\\\(\"\[^\"\]+\"\\\)" {-1}
- testing_probe {process(number).plt.statement(number)}
+ testing_probe {process(number).plt.return}
- stap_list "process($valid_pid).plt.statement(0x123)" \
- "re:process\\\(\"$exefullpath\"\\\)\\\.statement\\\(0x\[a-f0-9\]+\\\)"
+ stap_list "process($valid_pid).plt.return" \
+ "re:process\\\(\"$exefullpath\"\\\)\\\.plt\\\(\"\[^\"\]+\"\\\).return" {-1}
testing_probe {process(number).plt(string)}
stap_list "process($valid_pid).plt(\"\\\[lp\\\]*\")" \
"re:process\\\(\"$exefullpath\"\\\)\\\.plt\\\(\"(libfoo|printf)\"\\\)" {-1}
- testing_probe {process(number).plt(string).statement(number)}
+ testing_probe {process(number).plt(string).return}
- stap_list "process($valid_pid).plt(\"libfoo\").statement(0x123)" \
- "re:process\\\(\"$exefullpath\"\\\)\\\.statement\\\(0x\[a-f0-9\]+\\\)"
+ stap_list "process($valid_pid).plt(\"libfoo\").return" \
+ "re:process\\\(\"$exefullpath\"\\\)\\\.plt\\\(\"libfoo\"\\\).return"
- stap_list "process($valid_pid).plt(\"libfo?\").statement(0x123)" \
- "re:process\\\(\"$exefullpath\"\\\)\\\.statement\\\(0x\[a-f0-9\]+\\\)"
+ stap_list "process($valid_pid).plt(\"libfo?\").return" \
+ "re:process\\\(\"$exefullpath\"\\\)\\\.plt\\\(\"libfoo\"\\\).return"
- stap_list "process($valid_pid).plt(\"\\\[lp\\\]*\").statement(0x123)" \
- "re:process\\\(\"$exefullpath\"\\\)\\\.statement\\\(0x\[a-f0-9\]+\\\)"
+ stap_list "process($valid_pid).plt(\"\\\[lp\\\]*\").return" \
+ "re:process\\\(\"$exefullpath\"\\\)\\\.plt\\\(\"(libfoo|printf)\"\\\).return" {-1}
}
testing_probe {process(number).provider(string).mark(string)}
#process(string).library(string).function(string).return
#process(string).library(string).mark(string)
#process(string).library(string).plt
- #process(string).library(string).plt.statement(number)
#process(string).library(string).plt(string)
- #process(string).library(string).plt(string).statement(number)
#process(string).library(string).provider(string).mark(string)
#process(string).library(string).statement(number)
#process(string).library(string).statement(string)
#process(string).mark(string)
#process(string).plt
- #process(string).plt.statement(number)
#process(string).plt(string)
- #process(string).plt(string).statement(number)
#process(string).provider(string).mark(string)
#process(string).statement(number)
#process(string).statement(string)
# test process.plt
set pp {process("./plt.x").plt, process("./libplt1.so").plt, process("./libplt2.so").plt}
-stap_run3 "plt" "$script" "$pp" -c "$exepath >/dev/null"
+stap_run3 "plt" "$script" "$pp" "noreturn" -c "$exepath >/dev/null"
# test process.library.plt
set pp {process("./plt.x").plt, process("./plt.x").library("libplt*").plt}
-stap_run3 "plt library" "$script" "$pp" -c "$exepath >/dev/null"
+stap_run3 "plt library" "$script" "$pp" "noreturn" -c "$exepath >/dev/null"
# test process.library.plt prelinked
} else {
pass "plt prelink libplt1.so"
set pp {process("./plt.x").plt, process("./plt.x").library("libplt*").plt}
- stap_run3 "plt prelinked library" "$script" "$pp" -c "$exepath >/dev/null"
+ stap_run3 "plt prelinked library" "$script" "$pp" "noreturn" -c "$exepath >/dev/null"
}
} else {
untested "plt prelink libplt1.so"
untested "plt prelinked library"
}
+# test .plt.return: .plt/.plt.return should cancel out
+set ::result_string \
+{__cxa_finalize 0
+__libc_start_main 0
+__xpg_basename 0
+asctime 0
+asprintf 0
+basename2 0
+bsearch 0
+critters 0
+datetime 0
+find_critter 0
+fprintf 0
+fputs 0
+free 0
+localtime 0
+malloc 0
+memcpy 0
+open 0
+open2 0
+open3 0
+print_critter 0
+printf 0
+qsort 0
+register_printf_function 0
+savestring 0
+stpcpy 0
+strcmp 0
+strftime 0
+strlen 0
+time 0
+widgets 0
+xmalloc 0
+zenme 0}
+
+# test process.plt.return
+
+set pp {process("./plt.x").plt, process("./libplt1.so").plt, process("./libplt2.so").plt}
+stap_run3 "plt.return" "$script" "$pp" "return" -c "$exepath >/dev/null"
+
+# test process.library.plt.return
+
+set pp {process("./plt.x").plt, process("./plt.x").library("libplt*").plt}
+stap_run3 "plt.return library" "$script" "$pp" "return" -c "$exepath >/dev/null"
+
+
+
# test process.plt("glob")
set ok 0
set ::result_string {strcmp 51}
set pp {process("./libplt2.so").plt("strcmp")}
-stap_run3 "plt glob" "$script" "$pp" -c "$exepath >/dev/null"
+stap_run3 "plt glob" "$script" "$pp" "noreturn" -c "$exepath >/dev/null"
cleanup_handler $verbose
global calls
+
probe $1 {
calls[$$name] += 1
}
+
+%( @2 == "return" %?
+probe $1.return {
+ calls[$$name] -= 1
+}
+%)
+
+
probe end {
foreach (x+ in calls)
printf ("%s %d\n", x, calls[x])
"process.function(string).callees" \
"process.function(string).callees(number)" \
"process.plt" \
- "process.plt.statement(number)" \
+ "process.plt.return" \
"process.plt(string)" \
- "process.plt(string).statement(number)" \
+ "process.plt(string).return" \
"process.library(string).function(number)" \
"process.library(string).function(number).call" \
"process.library(string).function(number).inline" \
"process.library(string).function(string).callees" \
"process.library(string).function(string).callees(number)" \
"process.library(string).plt" \
- "process.library(string).plt.statement(number)" \
+ "process.library(string).plt.return" \
"process.library(string).plt(string)" \
- "process.library(string).plt(string).statement(number)" \
+ "process.library(string).plt(string).return" \
"process.library(string).mark(string)" \
"process.library(string).provider(string).mark(string)" \
"process.library(string).statement(number)" \
"process(number).function(string).return" \
"process(number).mark(string)" \
"process(number).plt" \
- "process(number).plt.statement(number)" \
+ "process(number).plt.return" \
"process(number).plt(string)" \
- "process(number).plt(string).statement(number)" \
+ "process(number).plt(string).return" \
"process(number).provider(string).mark(string)" \
"process(number).statement(number)" \
"process(number).statement(string)" \
"process(string).library(string).statement(number)" \
"process(string).library(string).statement(string)" \
"process(string).library(string).plt" \
- "process(string).library(string).plt.statement(number)" \
+ "process(string).library(string).plt.return" \
"process(string).library(string).plt(string)" \
- "process(string).library(string).plt(string).statement(number)" \
+ "process(string).library(string).plt(string).return" \
"process(string).mark(string)" \
"process(string).provider(string).mark(string)" \
"process(string).statement(number)" \
"process(string).statement(string)" \
"process(string).plt" \
- "process(string).plt.statement(number)" \
+ "process(string).plt.return" \
"process(string).plt(string)" \
- "process(string).plt(string).statement(number)" \
+ "process(string).plt(string).return" \
"process(string).syscall" \
"process(string).syscall.return" \
"process(string).thread.begin" \
# Replace "library(string).statement(string)" with "library(string).statement("libloopfunc@libloop.c:*")"
regsub -all "library\\(string\\).statement\\(string\\)" $probe "library(string).statement(\"libloopfunc@libloop.c:*\")" probe
- # Replace "library(string).plt.statement(number)" with
- # "library(string).plt.statement($addr_of_libloopfunc)"
- regsub -all "library\\(string\\).plt.statement\\(number\\)" $probe "library(string).plt.statement($addr_of_libloopfunc)" probe
- # Replace "library(string).plt(string).statement(number)" with
- # "library(string).plt(string).statement($addr_of_libloopfunc)"
- regsub -all "library\\(string\\).plt\\(string\\).statement\\(number\\)" $probe "library(string).plt(string).statement($addr_of_libloopfunc)" probe
-
# Replace "statement(number)" with "statement($addr_of_bar)"
regsub -all "statement\\(number\\)" $probe "statement($addr_of_bar)" probe
# Replace "statement(string)" with "statement("bar@loop.c:*")"
"process.function(string).callees" \
"process.function(string).callees(number)" \
"process.plt" \
- "process.plt.statement(number)" \
+ "process.plt.return" \
"process.plt(string)" \
- "process.plt(string).statement(number)" \
+ "process.plt(string).return" \
"process.library(string).function(number)" \
"process.library(string).function(number).call" \
"process.library(string).function(number).inline" \
"process.library(string).function(string).callees" \
"process.library(string).function(string).callees(number)" \
"process.library(string).plt" \
- "process.library(string).plt.statement(number)" \
+ "process.library(string).plt.return" \
"process.library(string).plt(string)" \
- "process.library(string).plt(string).statement(number)" \
+ "process.library(string).plt(string).return" \
"process.library(string).mark(string)" \
"process.library(string).provider(string).mark(string)" \
"process.library(string).statement(number)" \
"process(number).function(string).return" \
"process(number).mark(string)" \
"process(number).plt" \
- "process(number).plt.statement(number)" \
+ "process(number).plt.return" \
"process(number).plt(string)" \
- "process(number).plt(string).statement(number)" \
+ "process(number).plt(string).return" \
"process(number).provider(string).mark(string)" \
"process(number).statement(number)" \
"process(number).statement(string)" \
"process(string).library(string).statement(number)" \
"process(string).library(string).statement(string)" \
"process(string).library(string).plt" \
- "process(string).library(string).plt.statement(number)" \
+ "process(string).library(string).plt.return" \
"process(string).library(string).plt(string)" \
- "process(string).library(string).plt(string).statement(number)" \
+ "process(string).library(string).plt(string).return" \
"process(string).mark(string)" \
"process(string).provider(string).mark(string)" \
"process(string).statement(number)" \
"process(string).statement(string)" \
"process(string).plt" \
- "process(string).plt.statement(number)" \
+ "process(string).plt.return" \
"process(string).plt(string)" \
- "process(string).plt(string).statement(number)" \
+ "process(string).plt(string).return" \
"process(string).syscall" \
"process(string).syscall.return" \
"process(string).thread.begin" \