Skip to content

Commit dbfc5dc

Browse files
committed
Fix LookupTlsSymbolOffset to use the phdr
1 parent 1c79f49 commit dbfc5dc

1 file changed

Lines changed: 22 additions & 15 deletions

File tree

libpf/pfelf/file.go

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ var ErrNoTbss = errors.New("no thread-local uninitialized data section (tbss)")
6060
// ErrNoTdata is returned when the tdata section cannot be found
6161
var ErrNoTdata = errors.New("no thread-local initialized data section (tdata)")
6262

63+
var ErrNoTls = errors.New("no TLS program header")
64+
6365
// File represents an open ELF file
6466
type File struct {
6567
// closer is called internally when resources for this File are to be released
@@ -451,6 +453,16 @@ func (f *File) Tdata() (*Section, error) {
451453
return nil, ErrNoTdata
452454
}
453455

456+
// Tls gets the TLS segment (program header)
457+
func (f *File) Tls() (*Prog, error) {
458+
for _, seg := range f.Progs {
459+
if seg.Type == elf.PT_TLS {
460+
return &seg, nil
461+
}
462+
}
463+
return nil, ErrNoTls
464+
}
465+
454466
// ReadVirtualMemory reads bytes from given virtual address
455467
func (f *File) ReadVirtualMemory(p []byte, addr int64) (int, error) {
456468
if len(p) == 0 {
@@ -840,25 +852,20 @@ func (f *File) LookupTlsSymbolOffset(symbol libpf.SymbolName) (int64, error) {
840852
// of the image. So we need to find the size of the image in order to know where the
841853
// beginning is.
842854
//
843-
// The image is just .tdata followed by .tbss,
844-
// but we also have to respect the alignment.
845-
tbss, err := f.Tbss()
855+
// Furthermore, the thread pointer (fs-base) respects the TLS segment's alignment
856+
// (which is a bit weird given that offsets are negative, but it is in fact true).
857+
//
858+
// So if the segment is 32-byte aligned, and some object is at byte 4 in the segment,
859+
// it will be at offset -28 from fs-base.
860+
//
861+
// See "ELF Handling For Thread-Local Storage" (https://www.uclibc.org/docs/tls.pdf),
862+
// pp. 8 ("Variant II"), 11 ("IA-32 Specific"), 14 ("x86-64 Specific").
863+
tls, err := f.Tls()
846864
if err != nil {
847865
return 0, err
848866
}
849-
tdata, err := f.Tdata()
850-
var tdataSize uint64
851-
if err != nil {
852-
// No Tdata is ok, it's the same as size 0
853-
if err != ErrNoTdata {
854-
return 0, err
855-
}
856-
} else {
857-
tdataSize = tdata.Size
858-
}
867+
offset := int64(tlsSym.Address) - int64(roundUp(tls.Align, tls.Memsz))
859868

860-
imageSize := roundUp(tbss.Addralign, tdataSize) + tbss.Size
861-
offset := int64(tlsSym.Address) - int64(imageSize)
862869
return offset, nil
863870
}
864871
return 0, fmt.Errorf("unrecognized machine: %s", f.Machine.String())

0 commit comments

Comments
 (0)