/
usr
/
share
/
systemtap
/
tapset
/
/usr/share/systemtap/tapset
mkdir
upload
Name
Size
Mode
Actions
arm/
-
0755
rm
arm64/
-
0755
rm
bpf/
-
0755
rm
dyninst/
-
0755
rm
i386/
-
0755
rm
ia64/
-
0755
rm
linux/
-
0755
rm
mips/
-
0755
rm
powerpc/
-
0755
rm
riscv/
-
0755
rm
s390/
-
0755
rm
x86_64/
-
0755
rm
ansi.stp
4178
0644
edit
dl
rm
argv.stp
2721
0644
edit
dl
rm
choose_defined.stpm
208
0644
edit
dl
rm
container_of.stpm
235
0644
edit
dl
rm
context.stp
6103
0644
edit
dl
rm
errno.stp
9118
0644
edit
dl
rm
floatingpoint.stp
6936
0644
edit
dl
rm
indent-default.stp
59
0644
edit
dl
rm
indent.stp
4590
0644
edit
dl
rm
init.stp
269
0644
edit
dl
rm
input.stp
263
0644
edit
dl
rm
java.stp
1346
0644
edit
dl
rm
libperl5.26.3-64.stp
1339
0644
edit
dl
rm
libpython2.7-64.stp
522
0644
edit
dl
rm
livepatch.stp
3006
0644
edit
dl
rm
logging.stp
4132
0644
edit
dl
rm
macros.stpm
562
0644
edit
dl
rm
null.stp
17
0644
edit
dl
rm
offsetof.stpm
183
0644
edit
dl
rm
oneshot.stp
38
0644
edit
dl
rm
pn.stp
1588
0644
edit
dl
rm
print_stats.stpm
1719
0644
edit
dl
rm
private30.stpm
80
0644
edit
dl
rm
prometheus.stp
129
0644
edit
dl
rm
prometheus.stpm
8380
0644
edit
dl
rm
python.stp
474
0644
edit
dl
rm
python2.stp
29435
0644
edit
dl
rm
python3.stp
36655
0644
edit
dl
rm
queue_stats.stp
9487
0644
edit
dl
rm
random.stp
432
0644
edit
dl
rm
README
371
0644
edit
dl
rm
regex.stp
4107
0644
edit
dl
rm
registers.stp
11081
0644
edit
dl
rm
sizeof.stpm
212
0644
edit
dl
rm
speculative.stp
1746
0644
edit
dl
rm
sreg_arch.stpm
263
0644
edit
dl
rm
stap_staticmarkers.stp
9670
0644
edit
dl
rm
stopwatch.stp
3063
0644
edit
dl
rm
string.stp
7514
0644
edit
dl
rm
switchfile.stp
612
0644
edit
dl
rm
system.stp
593
0644
edit
dl
rm
this.stp
160
0644
edit
dl
rm
timers.stp
924
0644
edit
dl
rm
tls.stp
8099
0644
edit
dl
rm
tokenize.stp
2124
0644
edit
dl
rm
try_assign.stpm
768
0644
edit
dl
rm
type_defined.stpm
374
0644
edit
dl
rm
tzinfo.stp
930
0644
edit
dl
rm
uconversions-guru.stp
6078
0644
edit
dl
rm
uconversions.stp
36640
0644
edit
dl
rm
Edit:
/usr/share/systemtap/tapset/tls.stp
(8099B)
# Implicit Thread Local Storage tapset # Copyright (C) 2020, 2021 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. # Reference: "ELF Handling For Thread-Local Storage" by Ulrich Drepper /* * TCB Pointer points to the thread control block. dtv points to the DTV * array. DTV[1]-DTV[N] point to tls entries for module I from the link * map. DTV[1] is the main executable. The dtv val points to the tls * entry where the tls variable value is located. The tls variable value * is also located a fixed offset from the tcbhead so if relocations are * simple enough a compiler can generate a direct load. Complicated * relocations may result in a compiler calling a runtime routine * __tls_get_addr which uses the DTV. * * TCB Pointer * | * V * TLS struct tcbhead * +---------------------+ +----------------+ * |OFFSET|OFFSET|OFFSET | | void *tcb | * | 2 | 1 | 0 | | dtv_t *dtv | --+ * +---------------------+ +----------------+ | * ^-------------------+ | * v----------------------------------------+ * +----------------------------+ | * DTV |length|gen|dtv[1]|dtv[2]|...| | * +----------------------------+ | * dtv[n] | | * +---------------------+ | * |unsigned long counter| | * |struct dtv_pointer { | | * | void *val |->------+ * | void *to_free} | * +---------------------| */ global tls_debug = 0 private global tls_link_map_name private global tls_module = 0 %{ # if defined(__DYNINST__) # if defined(__i386) || defined(__x86_64) # include <asm/prctl.h> # include <sys/prctl.h> # endif # endif %} // Get the thread context pointer that points to the tls thread control block @__private30 function get_thread_context_pointer (tls_thread_reg_val:long) %{ # ifdef __i386 { unsigned long gs; # if defined(__KERNEL__) rdmsrl(MSR_FS_BASE, gs); # elif defined(__DYNINST__) int arch_prctl(int code, unsigned long *addr); arch_prctl(ARCH_GET_FS, &gs); # endif STAP_RETVALUE = gs; } # elif defined __x86_64 { unsigned long fs; #if defined(__KERNEL__) rdmsrl(MSR_FS_BASE, fs); # elif defined(__DYNINST__) int arch_prctl(int code, unsigned long *addr); arch_prctl(ARCH_GET_FS, &fs); # endif STAP_RETVALUE = fs; } # elif defined __s390x__ { unsigned long tlsval; asm volatile ("ear %0,%%a0" : "=r" (tlsval)); asm volatile ("sllg %0,%0,32" : "=r" (tlsval)); asm volatile ("ear %0,%%a1" : "=r" (tlsval)); STAP_RETVALUE = tlsval; } # elif defined __aarch64__ { unsigned long tlsval; asm("mrs %0,tpidr_el0" : "=r" (tlsval)); STAP_RETVALUE = tlsval; } # elif defined __powerpc64__ { unsigned long tcb; asm("subi %0,%1,28688," : "=r" (tcb) : "r" (STAP_ARG_tls_thread_reg_val)); // -0x7010 STAP_RETVALUE = tcb; } # endif %} // Get inode of followed link // TODO Does not follow symbolic links, e.g. to follow /lib64/libc.so.6 // The idea was to do 'inode = get_inode_from_path (l_name); name = inode_path(inode);' @__private30 function get_inode_from_path:long (tls_module_name) %{ struct inode *tls_inode; struct path tls_path; int code; code = kern_path(/* string */ STAP_ARG_tls_module_name, LOOKUP_FOLLOW, &tls_path); if (code == 0) STAP_RETVALUE = (int64_t)tls_path.dentry->d_inode; else STAP_RETVALUE = 0; %} // Return basename of a path @__private30 function basename (l_name:string) { for (lni = 0; lni < strlen (l_name); lni++) { if (stringat(l_name, lni) == 0x2f) // '/' slash = lni; } if (slash > 0) { slash += 1; return substr (l_name, slash, strlen(l_name)-slash); } else return l_name; } // Setup the link_map module/l_name mapping @__private30 function setup_link_map () { delete tls_link_map_name %( arch == "x86_64" %? l_map_count = @var("_rtld_global","/usr/lib64/ld-linux-x86-64.so.2")->_dl_nns // TODO Do namespaces need to be supported? assume [0] l_map = @var("_rtld_global","/usr/lib64/ld-linux-x86-64.so.2")->_dl_ns[0]->_ns_loaded; if (tls_debug > 1) println ("l_map=", @var("_rtld_global","/usr/lib64/ld-linux-x86-64.so.2")->_dl_ns[0]->_ns_loaded$); %) %( arch == "powerpc" %? l_map_count = @var("_rtld_global","/usr/lib64/ld64.so.2")->_dl_nns l_map = @var("_rtld_global","/usr/lib64/ld64.so.2")->_dl_ns[0]->_ns_loaded; if (tls_debug > 1) println ("l_map=", @var("_rtld_global","/usr/lib64/ld64.so.2")->_dl_ns[0]->_ns_loaded$); %) %( arch == "s390" %? l_map_count = @var("_rtld_global","/usr/lib/ld64.so.1")->_dl_nns l_map = @var("_rtld_global","/usr/lib/ld64.so.1")->_dl_ns[0]->_ns_loaded; if (tls_debug > 1) println ("l_map=", @var("_rtld_global","/usr/lib/ld64.so.1")->_dl_ns[0]->_ns_loaded$); %) while (l_map) { l_name = user_string(l_map->l_name); if (l_name == "") { l_map = l_map->l_next continue } l_addr = user_uint64(l_map->l_addr); l_tls_modid = l_map->l_tls_modid name_base = basename (l_name); if (l_tls_modid != 0) { tls_link_map_name[l_tls_modid] = name_base; if (tls_debug) printf("link_map: %s l_addr=%#lx modid=%d\n", tls_link_map_name[l_tls_modid], l_addr, l_tls_modid); } l_map = l_map->l_next } } // Compare module names. // sonames, real sonames, and linker sonames should compare equal @__private30 function regex_module_compare (stap_mod:string, map_mod:string) { // Not an soname if (stap_mod !~ "^lib.*$") return stap_mod == map_mod; // Most common case libMATCH-1.soMATCH-2 // MATCH-1 is the soname minus lib prefix and .so* suffix if (stap_mod !~ "lib([-\._\+a-zA-Z0-9]+)\.so([\.0-9]*)") return 0; stap_lib = matched(1); if (map_mod !~ "lib([-\._\+a-zA-Z0-9]+)\.so([\.0-9]*)") return 0; map_lib = matched(1); if (stap_lib == map_lib) return 1; // The above will miss e.g. libc.so.6/libc-2.31.so // MATCH-1 is the soname minus lib prefix and -version.so suffix if (stap_mod !~ "lib([_\+a-zA-Z0-9]+)([-\.0-9]*)\.so([\.0-9]*)") return 0; stap_lib = matched(1); if (map_mod !~ "lib([_\+a-zA-Z0-9]+)([-\.0-9]*)\.so([\.0-9]*)") return 0; map_lib = matched(1); if (stap_lib == map_lib) return 1; else return 0; } // Find the module by matching the probe name to the link_map name @__private30 function set_tls_module_by_name (tls_module:string) { 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 \n", tls_link_map_name[lm]); return lm; } } return 1; } /** * sfunction __push_tls_address - Handle implicit tls variable relocation * * Description: Called for DW_OP_GNU_push_tls_address relocation from loc2stap.css::location_context::translate */ 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 r13 = register("r13") %: r13 = 0 %) tcbhead = get_thread_context_pointer (r13); if (tls_debug > 1) printf ("tls_module=%s tcbhead=%#lx/%d\n", tls_module, tcbhead, tcbhead); setup_link_map (); module = set_tls_module_by_name (tls_module); if (module >= 0) { // dtv[-1] is module count // dtv[0] is generation count // dtv[1] is module[0] info, the main executable // dtv[2..n] is module info for dependent shared objects dtv$pointer$val = @cast(tcbhead, "tcbhead", "<linux/stp_tls.h>")->dtv[module]->pointer->val; if (tls_debug > 1) printf ("dtv$pointer$val=%#lx, tls_var_offset=%#lx, module=%d\n", dtv$pointer$val, tls_var_offset, module); return dtv$pointer$val + tls_var_offset; } else return 0; }
Save
cmd:
run