Skip to content

Instantly share code, notes, and snippets.

@agentzh

agentzh/a.patch Secret

Last active June 7, 2020 20:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save agentzh/57f48008ded119aef94e02ccb2f1dadf to your computer and use it in GitHub Desktop.
Save agentzh/57f48008ded119aef94e02ccb2f1dadf to your computer and use it in GitHub Desktop.
diff --git a/tapset-utrace.cxx b/tapset-utrace.cxx
index a13048ce2..940188b47 100644
--- a/tapset-utrace.cxx
+++ b/tapset-utrace.cxx
@@ -869,6 +869,11 @@ utrace_derived_probe_group::emit_module_linux_decls (systemtap_session& s)
"p->probe",
"stp_probe_type_utrace");
+ // make sure tapset funcs like register() work in probe process.begin
+ // and etc.
+ s.op->newline() << "c->uregs = _stp_current_pt_regs();";
+ s.op->newline() << "c->user_mode_p = 1;";
+
// call probe function
s.op->newline() << "dbug_task(2, \"calling UDPF probe function\");";
s.op->newline() << "(*p->probe->ph) (c);";
diff --git a/testsuite/lib/test_simple.exp b/testsuite/lib/test_simple.exp
index ef3661278..589f92239 100644
--- a/testsuite/lib/test_simple.exp
+++ b/testsuite/lib/test_simple.exp
@@ -138,3 +138,86 @@ proc nok { test_name result } {
pass "${test_name}: sould NOT be ok: $result"
return 1
}
+
+# process_template_file TEMPLATE_FILE OUT_FILE BIN_FILE ERR_VAR
+# Processes the template file specified by the TEMPLATE_FILE argument,
+# expands special macro variables in the template file, and genetates the final
+# .stp file specified by the OUT_FILE argument.
+# The following macro variables are supported:
+# * $^PWD for the current working directory
+# * $^ADDR_NAME for the hex address (without the 0x prefix) for the symbol
+# named NAME by inspecting the binary target program file BIN_FILE via the
+# nm utility.
+# Returns 1 when all macro variables are expanded successfully; 0 otherwise.
+# In case of error, the error message will be returned in the variable with
+# the name specified by the 4th argument.
+
+proc process_template_file { template_file out_file bin_file err_var } {
+ upvar 1 $err_var err
+
+ set in [open $template_file r]
+ set src [read $in]
+ close $in
+
+ set cwd [pwd]
+ regsub -all -- {\$\^PWD\y} $src $cwd src
+
+ set matches [regexp -all -inline -- {\$\^ADDR_([_a-zA-Z]\w*)} $src]
+
+ set nsyms 0
+ if {[llength $matches] > 0} {
+ array set names {}
+ foreach {match, name} $matches {
+ if {! [info exists names($name)]} {
+ incr nsyms
+ set names($name) 1
+ }
+ }
+
+ set nm_fh [open "| nm --defined-only ./a.out" r]
+ set hits 0
+ while {[gets $nm_fh line] >= 0} {
+ if {[regexp -- {^\s*([0-9a-f]+)\s+[DT]\s+([_a-zA-Z]\w*)\s*$} $line \
+ match addr name]} {
+ if {! [info exists names($name)]} {
+ continue
+ }
+ unset names($name)
+ send_log "found symbol '$name' at addr $addr in the nm output\n"
+ regsub -all -- "\\$\\^ADDR_$name\\y" $src $addr src
+ if {[incr hits] == $nsyms} {
+ break
+ }
+ }
+ }
+
+ if {[catch {close $nm_fh} nm_err] != 0} {
+ global errorCode
+ if {[lindex $errorCode 0] eq "CHILDSTATUS"} {
+ if {[lindex $errorCode 2] != 0} {
+ set err "failed to run nm: $nm_err"
+ return 0
+ }
+ }
+ }
+
+ if {$hits < $nsyms} {
+ set unmatched_names [array names names]
+ if {[llength $unmatched_names] == 1} {
+ set sym [lindex $unmatched_names 0]
+ set err "symbol '$sym' not found in binary file $bin_file"
+ return 0
+ }
+
+ set sym_list [join [lmap e [array names names] { expr {"'$e'"} }] ", "]
+ set err "symbols $sym_list not found in binary file $bin_file"
+ return 0
+ }
+ }
+
+ set out [open $out_file w+]
+ puts -nonewline $out $src
+ close $out
+
+ return 1
+}
diff --git a/testsuite/systemtap.base/process-begin-user.exp b/testsuite/systemtap.base/process-begin-user.exp
new file mode 100644
index 000000000..66c9e8b0e
--- /dev/null
+++ b/testsuite/systemtap.base/process-begin-user.exp
@@ -0,0 +1,97 @@
+set test "process-begin-user"
+set testpath "$srcdir/$subdir"
+
+if {! [installtest_p]} { untested $test; return }
+if {! [uretprobes_p]} { untested $test; return }
+
+# --- TEST 1 ---
+
+set subtest1 "TEST 1: register() in probe process.begin"
+
+set res [target_compile ${testpath}/${test}_1.c ./a.out executable \
+ "additional_flags=-O additional_flags=-g"]
+if {$res ne ""} {
+ verbose "target_compile failed: $res" 2
+ fail "$test: $subtest1: unable to compile ${test}_1.c"
+} else {
+ if {! [process_template_file "$srcdir/$subdir/${test}_1.stp" \
+ "./${test}_1.stp" "./a.out" nm_err]} {
+ fail "$test: $subtest1: $nm_err"
+ } else {
+ foreach runtime [get_runtime_list] {
+ if {$runtime eq ""} {
+ set runtime "kernel"
+ }
+ set test_name "$test: $subtest1 ($runtime)"
+ set cmd "stap --runtime=$runtime -c ./a.out './${test}_1.stp'"
+ set exit_code [run_cmd_2way $cmd out stderr]
+ set out_pat "\\Arip: 0x\[1-9a-f\]\[0-9a-f\]*\\nsame uaddr\\n\\Z"
+ like "${test_name}: stdout" $out $out_pat "-lineanchor"
+ is "${test_name}: exit code" $exit_code 0
+ if {$stderr ne ""} {
+ send_log "stderr:\n$stderr"
+ }
+ }
+ }
+}
+
+# --- TEST 2 ---
+
+set subtest2 "TEST 2: register() in probe process.end"
+
+set res [target_compile ${testpath}/${test}_1.c ./a.out executable \
+ "additional_flags=-O additional_flags=-g"]
+if {$res ne ""} {
+ verbose "target_compile failed: $res" 2
+ fail "$test: $subtest2: unable to compile ${test}_1.c"
+} else {
+ if {! [process_template_file "$srcdir/$subdir/${test}_2.stp" \
+ "./${test}_2.stp" "./a.out" nm_err]} {
+ fail "$test: $subtest2: $nm_err"
+ } else {
+ foreach runtime [get_runtime_list] {
+ if {$runtime eq ""} {
+ set runtime "kernel"
+ }
+ set test_name "$test: $subtest2 ($runtime)"
+ set cmd "stap --runtime=$runtime -c ./a.out './${test}_2.stp'"
+ set exit_code [run_cmd_2way $cmd out stderr]
+ set exp_out ""
+ is "${test_name}: stdout" $out $exp_out
+ isnt "${test_name}: exit code" $exit_code 0
+ set stderr_pat "ERROR: cannot access CPU registers in this context"
+ like "${test_name}: stderr" $stderr $stderr_pat "-linestop"
+ }
+ }
+}
+
+# --- TEST 3 ---
+
+set subtest3 "TEST 3: @var() in probe process.begin (with vma tracker)"
+
+set res [target_compile ${testpath}/${test}_3.c ./a.out executable \
+ "additional_flags=-O additional_flags=-g additional_flags=-pie additional_flags=-fpic"]
+if {$res ne ""} {
+ verbose "target_compile failed: $res" 2
+ fail "$test: $subtest3: unable to compile ${test}_3.c"
+} else {
+ if {! [process_template_file "$srcdir/$subdir/${test}_3.stp" \
+ "./${test}_3.stp" "./a.out" nm_err]} {
+ fail "$test: $subtest3: $nm_err"
+ } else {
+ foreach runtime [get_runtime_list] {
+ if {$runtime eq ""} {
+ set runtime "kernel"
+ }
+ set test_name "$test: $subtest3 ($runtime)"
+ set cmd "stap --runtime=$runtime -c ./a.out './${test}_3.stp'"
+ set exit_code [run_cmd_2way $cmd out stderr]
+ set exp_out "a: 32\n"
+ is "${test_name}: stdout" $out $exp_out
+ is "${test_name}: exit code" $exit_code 0
+ if {$stderr ne ""} {
+ send_log "stderr:\n$stderr"
+ }
+ }
+ }
+}
diff --git a/testsuite/systemtap.base/process-begin-user_1.c b/testsuite/systemtap.base/process-begin-user_1.c
new file mode 100644
index 000000000..9b6bdc2ec
--- /dev/null
+++ b/testsuite/systemtap.base/process-begin-user_1.c
@@ -0,0 +1,3 @@
+int main(void) {
+ return 0;
+}
diff --git a/testsuite/systemtap.base/process-begin-user_1.stp b/testsuite/systemtap.base/process-begin-user_1.stp
new file mode 100644
index 000000000..3e8e27b59
--- /dev/null
+++ b/testsuite/systemtap.base/process-begin-user_1.stp
@@ -0,0 +1,8 @@
+probe process("$^PWD/a.out").begin {
+ printf("rip: 0x%x\n", register("rip"));
+ if (register("rip") != uaddr()) {
+ printf("different uaddr: 0x%x\n", uaddr())
+ } else {
+ printf("same uaddr\n");
+ }
+}
diff --git a/testsuite/systemtap.base/process-begin-user_2.c b/testsuite/systemtap.base/process-begin-user_2.c
new file mode 100644
index 000000000..ac0d771b3
--- /dev/null
+++ b/testsuite/systemtap.base/process-begin-user_2.c
@@ -0,0 +1,5 @@
+int a = 32;
+
+int main(void) {
+ return 0;
+}
diff --git a/testsuite/systemtap.base/process-begin-user_2.stp b/testsuite/systemtap.base/process-begin-user_2.stp
new file mode 100644
index 000000000..bb90a8aeb
--- /dev/null
+++ b/testsuite/systemtap.base/process-begin-user_2.stp
@@ -0,0 +1,8 @@
+probe process("$^PWD/a.out").end {
+ printf("rip: 0x%x\n", register("rip"));
+ if (register("rip") != uaddr()) {
+ printf("different uaddr: 0x%x\n", uaddr())
+ } else {
+ printf("same uaddr\n");
+ }
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment