@@ -8,13 +8,17 @@ import (
88 "fmt"
99 "regexp"
1010
11+ "go.opentelemetry.io/ebpf-profiler/internal/log"
12+
1113 "go.opentelemetry.io/ebpf-profiler/libpf/pfelf"
1214)
1315
1416// LibcInfo contains introspection information extracted from the C-library
1517type LibcInfo struct {
1618 // TSDInfo is the TSDInfo extracted for this C-library
1719 TSDInfo TSDInfo
20+ // TODO comment
21+ DTVInfo DTVInfo
1822}
1923
2024// TSDInfo contains information to access C-library's Thread Specific Data from eBPF
@@ -35,6 +39,16 @@ type TSDInfo struct {
3539 Indirect uint8
3640}
3741
42+ // TODO comment
43+ type DTVInfo struct {
44+ // Offset is the offset of DTV from FS base (or from thread pointer)
45+ Offset int64
46+ // EntryWidth is the size of each DTV entry in bytes
47+ EntryWidth uint32
48+ // Indirect is 0 if DTV is at FS+offset, 1 if at [FS+0]+offset
49+ Indirect uint8
50+ }
51+
3852// This code analyzes the C-library provided POSIX defined function which is used
3953// to read thread-specific data (TSD):
4054// void *pthread_getspecific(pthread_key_t key);
@@ -96,8 +110,14 @@ func ExtractLibcInfo(ef *pfelf.File) (*LibcInfo, error) {
96110 return nil , err
97111 }
98112
113+ dtvinfo , err := extractDTVInfo (ef )
114+ if err != nil {
115+ return & LibcInfo {}, err
116+ }
117+
99118 return & LibcInfo {
100119 TSDInfo : * tsdinfo ,
120+ DTVInfo : * dtvinfo ,
101121 }, nil
102122}
103123
@@ -128,3 +148,33 @@ func extractTSDInfo(ef *pfelf.File) (*TSDInfo, error) {
128148 }
129149 return & info , nil
130150}
151+
152+ // extractDTVInfo extracts the introspection data for the DTV to access TLS vars
153+ func extractDTVInfo (ef * pfelf.File ) (* DTVInfo , error ) {
154+ var info DTVInfo
155+ _ , code , err := ef .SymbolData ("__tls_get_addr" , 2048 )
156+ if err != nil {
157+ // Only error out reading DTV if we have the symbol, but fail to parse it
158+ // if the symbol is not exported, failing to read it is not a critical error
159+ // and empty DTV introspection data is returned
160+ log .Warnf ("unable to read '__tls_get_addr': %s, libc DTV introspection data is unavailable" , err )
161+ return & info , nil
162+ }
163+
164+ if len (code ) < 8 {
165+ return nil , fmt .Errorf ("__tls_get_addr function size is %d" , len (code ))
166+ }
167+
168+ switch ef .Machine {
169+ case elf .EM_AARCH64 :
170+ info , err = extractDTVInfoARM (code )
171+ case elf .EM_X86_64 :
172+ info , err = extractDTVInfoX86 (code )
173+ default :
174+ return & info , fmt .Errorf ("unsupported arch %s" , ef .Machine .String ())
175+ }
176+ if err != nil {
177+ return & info , fmt .Errorf ("failed to extract DTV data: %s" , err )
178+ }
179+ return & info , nil
180+ }
0 commit comments