]> sourceware.org Git - systemtap.git/commitdiff
Add support for external tls variables
authorStan Cox <scox@redhat.com>
Wed, 21 Oct 2020 23:57:47 +0000 (19:57 -0400)
committerStan Cox <scox@redhat.com>
Wed, 21 Oct 2020 23:57:47 +0000 (19:57 -0400)
Add tls_module parameter to __push_tls_address to locate external tls variable.
Add errno test.

loc2stap.cxx
tapset/linux/errno.stpm [new file with mode: 0644]
tapset/linux/tls.stp
testsuite/systemtap.base/tls.exp
testsuite/systemtap.base/tls1.c
testsuite/systemtap.base/tls1.stp
testsuite/systemtap.base/tls1_.c
testsuite/systemtap.base/tls2_.c [new file with mode: 0644]
testsuite/systemtap.base/tlserrno.c [new file with mode: 0644]

index 6e6069dcfb294ac2195cab8dc87b4f221437a8cf..a99b5c71041fc66afc99f7bdaaf3480133e8c1a5 100644 (file)
@@ -698,6 +698,7 @@ location_context::translate (const Dwarf_Op *expr, const size_t len,
               fc->function = std::string("__push_tls_address");
               fc->synthetic = true;
               fc->args.push_back(addr);
+              fc->args.push_back(new literal_string(this->dw->module_name));
              PUSH(fc);
             }
             break;
diff --git a/tapset/linux/errno.stpm b/tapset/linux/errno.stpm
new file mode 100644 (file)
index 0000000..7d41b15
--- /dev/null
@@ -0,0 +1,3 @@
+@define errno() %(
+    @var("errno","/lib64/libc.so.6")
+%)
index 7e973399daa377ebf820bf5106df95ce54744ccf..bce9b3011ad68e43508962493fdfdf47f74da151 100644 (file)
@@ -162,23 +162,17 @@ private global tls_module = 0
 
 // Find the module by matching the probe name to the link_map name
 
-@__private30 function set_tls_module_by_name ()
+@__private30 function set_tls_module_by_name (tls_module:string)
 {
-  tls_pp = pp()
-  probe_addr = addr()
-  proc = strpos(tls_pp, "process(\"") + 9;
-  for (lpp = proc; lpp > 8 && lpp < strlen (tls_pp); lpp++)
-     if (stringat(tls_pp, lpp) == 0x22) {  // '"'
-       matched_proc = basename(substr(tls_pp, proc, lpp - 9))
-       break;
-     }
+  matched_proc = basename(tls_module);
 
+  if (tls_debug)
+    printf("Looking for %s in link_map\n", matched_proc);
   foreach (lm in tls_link_map_name) {
     if (lm==0) continue;
     if (regex_module_compare (matched_proc, tls_link_map_name[lm])) {
        if (tls_debug)
-         printf("Name Match: %s probe_address=%#lx\n",
-                tls_link_map_name[lm], probe_addr)
+        printf("Name Match: %s \n", tls_link_map_name[lm]);
        return lm;
     }
   }
@@ -192,7 +186,7 @@ private global tls_module = 0
  * Description: Called for DW_OP_GNU_push_tls_address relocation from loc2stap.css::location_context::translate
  */
 
-function __push_tls_address (tls_var_offset:long) 
+function __push_tls_address (tls_var_offset:long, tls_module:string
 {
 %( arch == "powerpc" %?
    // It seems the value of r13 cannot be dependably relied on in get_thread_context_pointer
@@ -204,7 +198,7 @@ function __push_tls_address (tls_var_offset:long)
   if (tls_debug > 1)
     printf ("tcbhead=%#lx/%d\n", tcbhead, tcbhead);
   setup_link_map ();
-  module = set_tls_module_by_name ();
+  module = set_tls_module_by_name (tls_module);
   if (module >= 0) 
     {
       // dtv[-1] is module count
index c03d0b2d02a6aff490021099e1778a67e0919e8c..07fb5904838f20751b914ed4f2b7ec6190203a35 100644 (file)
@@ -1,23 +1,64 @@
 set test "tls"
 set stap_path $env(SYSTEMTAP_PATH)/stap
 
-# Check tls use in .exe and .so
+# exp_internal 1
 
 set so_flags "additional_flags=-shared"
 set so_flags "$so_flags additional_flags=-g"
 set so_flags "$so_flags additional_flags=-fPIC"
-set so_flags "$so_flags additional_flags=-DNO_MAIN"
-set so_sopath "[pwd]/libtls1.so"
-set so_exepath "[pwd]/tls1.x"
-set res0 [target_compile $srcdir/$subdir/tls1_.c $so_sopath \
-             executable $so_flags ]
 set x_flags "additional_flags=-Wl,-rpath,[pwd]"
 set x_flags "$x_flags additional_flags=-g"
-set x_flags "$x_flags additional_flags=-L[pwd] additional_flags=-ltls1"
+set x_flags "$x_flags additional_flags=-fPIC"
 set x_flags "$x_flags additional_flags=-lpthread"
-set x_flags "$x_flags additional_flags=-DONLY_MAIN"
-set res [target_compile $srcdir/$subdir/tls1.c $so_exepath \
-            executable $x_flags ]
+
+# static tls variables
+
+set so1_sopath "[pwd]/libtls1.so"
+set res0 [target_compile $srcdir/$subdir/tls1_.c $so1_sopath \
+             executable $so_flags ]
+set x1_flags "$x_flags additional_flags=-L[pwd] additional_flags=-ltls1"
+set x1_exepath "[pwd]/tls1.x"
+set res [target_compile $srcdir/$subdir/tls1.c $x1_exepath \
+            executable $x1_flags ]
+if {$res0 != "" || $res != ""} {
+    fail "$test compiling tls1"
+    return
+} else {
+    pass "$test compiling tls1"
+}
+
+set ok 0
+spawn $stap_path -g -c $x1_exepath $srcdir/$subdir/tls1.stp $so1_sopath IGNORE
+expect {
+    -timeout 180
+    -re {In Stap.*: tls1=0x2 tls2=0x3} { incr ok; exp_continue }
+    -re {In Stap.*: tls1=0x3 tls2=0x4} { incr ok; exp_continue }
+    -re {In Stap.*: tls=99} { incr ok; exp_continue }
+    eof { }
+    }
+    catch {close}; catch {wait}
+if {$ok == 3} {
+    pass "$test local tls vars"
+} else {
+    fail "$test local tls vars ($ok)"
+}
+
+# extern tls variables
+
+set so2_sopath "[pwd]/libtls2.so"
+set so3_sopath "[pwd]/libtls3.so"
+set so2_flags "$so_flags additional_flags=-DEXTERN_TLS"
+
+set res0 [target_compile $srcdir/$subdir/tls1_.c $so2_sopath \
+             executable $so2_flags ]
+set res1 [target_compile $srcdir/$subdir/tls2_.c $so3_sopath \
+             executable $so2_flags ]
+set x2_flags "$x_flags additional_flags=-L[pwd] additional_flags=-ltls2"
+set x2_flags "$x2_flags additional_flags=-ltls3"
+set x2_flags "$x2_flags additional_flags=-DEXTERN_TLS"
+set x2_exepath "[pwd]/tls2.x"
+set res [target_compile $srcdir/$subdir/tls1.c $x2_exepath \
+        executable $x2_flags ]
 if { $res0 != "" || $res != "" } {
     fail "$test compiling -shared"
     return
@@ -26,30 +67,55 @@ if { $res0 != "" || $res != "" } {
 }
 
 set ok 0
-spawn $stap_path -g -c $so_exepath $srcdir/$subdir/tls1.stp $so_sopath
+spawn $stap_path -g -c $x2_exepath $srcdir/$subdir/tls1.stp $so2_sopath $so3_sopath
 expect {
-    -re {In Stap: tls1=0x2 tls2=0x3} { incr ok; exp_continue }
-    -re {In Stap: tls1=0x3 tls2=0x4} { incr ok; exp_continue }
-    -re {In Stap: tls=99} { incr ok; exp_continue }
+    -timeout 180
+    -re {In Stap worker: tls1=0x2 tls2=0x3\r\n} { incr ok; exp_continue }
+    -re {In Stap worker: tls1=0x3 tls2=0x4\r\n} { incr ok; exp_continue }
+    -re {In Stap increase_tls: tls1=0x2 tls2=0x3\r\n} { incr ok; exp_continue }
+    -re {In Stap increase_tls: tls1=0x3 tls2=0x4\r\n} { incr ok; exp_continue }
     eof { }
     }
     catch {close}; catch {wait}
-if {$ok == 3} {
-    pass "$test tls vars"
+if {$ok == 4} {
+    pass "$test ext tls vars"
 } else {
-    fail "$test tls vars ($ok)"
+    fail "$test ext tls vars ($ok)"
 }
 
 # Check errno
 
-spawn $stap_path  -e "probe process(\"/lib64/libc.so.6\").function(\"*stat*\").return { printf(\"errno=%d %s\n\", @var(\"errno@errno.c\"),errno_str(@var(\"errno@errno.c\"))) }" -c "/usr/bin/ls /file/does/not/exist"
+set errno_exepath "[pwd]/tlserrno.x"
+set res [target_compile $srcdir/$subdir/tlserrno.c $errno_exepath \
+            executable "-g" ]
+if {$res != ""} {
+    fail "$test compiling tlserrno"
+    return
+} else {
+    pass "$test compiling tls1errno"
+}
+
+spawn $stap_path  -e "probe process(\"/lib64/libc.so.6\").function(\"*stat*\").return { printf(\"errno=%d %s\\n\", @var(\"errno@errno.c\"),errno_str(@var(\"errno@errno.c\"))) }" -c "/usr/bin/ls /file/does/not/exist"
 expect {
+    -timeout 180
     -re {errno=2 (ENOENT)} { incr ok; exp_continue }
     eof { }
     }
     catch {close}; catch {wait}
-if {$ok == 3} {
+if {$ok >= 1} {
     pass "$test errno"
 } else {
     fail "$test errno ($ok)"
 }
+
+spawn $stap_path -e "probe process(\"tlserrno.x\").function(\"main\").return {println (\"In Stap errno=\",@errno)" -c $errno_exepath {
+    -timeout 180
+    -re {In Stap errno=2} { incr ok; exp_continue }
+    eof { }
+    }
+    catch {close}; catch {wait}
+if {$ok >= 1} {
+    pass "$test @errno"
+} else {
+    fail "$test @errno ($ok)"
+}
index 70ab7083bebb3247f738e5a3084182f44159fcf7..7a05cb7fd38c6981d4396879f1b294902217c27f 100644 (file)
@@ -3,7 +3,11 @@
 #include <stdlib.h>
 #include <alloca.h>
 
+#if defined EXTERN_TLS
+__thread unsigned long tls = 99; 
+#else
 static __thread unsigned long tls = 99; 
+#endif
 
 void *increase_tls(void *arg);
 
index cd6f8b9ecc375b6dcc708c4ac77bf79acd0a8670..6a1f3c417b3f7ceb7bfe9d34249b61c28de70736 100644 (file)
@@ -1,7 +1,16 @@
-probe process(@1).statement("increase_tls@*:11")
+global probe_itw=0
+
+probe process(@1).function("increase_tls").label("stp_probe")
+{
+  printf("In Stap increase_tls: tls1=%#lx tls2=%#lx\n", @var("tls1"), @var("tls2")) 
+}
+
+%(@2 != "IGNORE" %?
+probe process(@2).function("increase_tls_worker").label("stp_probe")
 {
-  printf("In Stap: tls1=%#lx tls2=%#lx\n", @var("tls1"), @var("tls2")) 
+  printf("In Stap worker: tls1=%#lx tls2=%#lx\n", @var("tls1",@1), @var("tls2",@1)) 
 }
+%)
 
 probe process("tls1.x").function("main").return
 {
index cdf8607a44d95a05d2f53d6983b591e1dea2f26d..0fc87a9c6fc9b76de5c80991cf7ae7bb35e0daa3 100644 (file)
@@ -1,12 +1,24 @@
 #include <stdio.h>
 
+#if defined EXTERN_TLS
+ __thread unsigned long tls1 = 1; 
+ __thread unsigned long tls2 = 2;
+#else
 static __thread unsigned long tls1 = 1; 
 static __thread unsigned long tls2 = 2;
+#endif
+
+void* increase_tls_worker ();
+
 
 void*
 increase_tls (void *arg)
 {
   tls1 = tls1 + (unsigned long)(*((char*)arg) - '0');
   tls2 = tls2 + (unsigned long)(*((char*)arg) - '0');
+#if defined EXTERN_TLS
+  increase_tls_worker();
+#endif
+stp_probe:
   printf ("tls counter for %c: %d/%d\n", (char)*((char*)arg), tls1, tls2);
 }
diff --git a/testsuite/systemtap.base/tls2_.c b/testsuite/systemtap.base/tls2_.c
new file mode 100644 (file)
index 0000000..fe2a9de
--- /dev/null
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+extern __thread unsigned long tls1;
+extern __thread unsigned long tls2;
+extern __thread unsigned long tls;
+
+void*
+increase_tls_worker ()
+{
+ stp_probe:
+  printf ("tls: %d/%d/%d\n", tls, tls1, tls2);
+}
diff --git a/testsuite/systemtap.base/tlserrno.c b/testsuite/systemtap.base/tlserrno.c
new file mode 100644 (file)
index 0000000..d0854c6
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+
+int
+main ()
+{
+  FILE *infile;
+  char *input_file = "No_such_file";
+  infile = fopen (input_file, "r");
+  if (infile == NULL) 
+    printf ("tlserrno: %s: %s\n", strerror(errno), input_file);
+}
This page took 0.047427 seconds and 5 git commands to generate.