Skip to content

Commit

Permalink
Merge pull request open-telemetry#11 from umanwizard/x86_tdata
Browse files Browse the repository at this point in the history
Look at .tdata when computing TLS image size
  • Loading branch information
umanwizard authored Sep 18, 2024
2 parents 8488625 + cf9610e commit 0220589
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
27 changes: 26 additions & 1 deletion interpreter/customlabels/customlabels.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ type data struct {

var _ interpreter.Data = &data{}

func roundUp(multiple, value uint64) uint64 {
if multiple == 0 {
return value
}
return (value + multiple - 1) / multiple * multiple
}

func Loader(_ interpreter.EbpfHandler, info *interpreter.LoaderInfo) (interpreter.Data, error) {
ef, err := info.GetELF()
if err != nil {
Expand Down Expand Up @@ -75,11 +82,29 @@ func Loader(_ interpreter.EbpfHandler, info *interpreter.LoaderInfo) (interprete
if ef.Machine == elf.EM_AARCH64 {
tlsAddr = libpf.Address(tlsSym.Address + 16)
} else if ef.Machine == elf.EM_X86_64 {
// Symbol addresses are relative to the start of the
// thread-local storage image, but the thread pointer points to the _end_
// of the image. So we need to find the size of the image in order to know where the
// beginning is.
//
// The image is just .tdata followed by .tbss,
// but we also have to respect the alignment.
tbss, err := ef.Tbss()
if err != nil {
return nil, err
}
tlsAddr = libpf.Address(int64(tlsSym.Address) - int64(tbss.Size))
tdata, err := ef.Tdata()
var tdataSize uint64
if err != nil {
// No Tdata is ok, it's the same as size 0
if err != pfelf.ErrNoTdata {
return nil, err
}
} else {
tdataSize = tdata.Size
}
imageSize := roundUp(tbss.Addralign, tdataSize) + tbss.Size
tlsAddr = libpf.Address(int64(tlsSym.Address) - int64(imageSize))
} else {
return nil, fmt.Errorf("unrecognized machine: %s", ef.Machine.String())
}
Expand Down
21 changes: 20 additions & 1 deletion libpf/pfelf/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ var ErrSymbolNotFound = errors.New("symbol not found")
// ErrNotELF is returned when the file is not an ELF
var ErrNotELF = errors.New("not an ELF file")

// ErrNoTbss is returned when the tbss section cannot be found
var ErrNoTbss = errors.New("no thread-local uninitialized data section (tbss)")

// ErrNoTdata is returned when the tdata section cannot be found
var ErrNoTdata = errors.New("no thread-local initialized data section (tdata)")

// File represents an open ELF file
type File struct {
// closer is called internally when resources for this File are to be released
Expand Down Expand Up @@ -426,7 +432,20 @@ func (f *File) Tbss() (*Section, error) {
return &sec, nil
}
}
return nil, errors.New("no thread-local uninitialized data section (tbss)")
return nil, ErrNoTbss
}

// Tdata gets the thread-local initialized data section
func (f *File) Tdata() (*Section, error) {
if err := f.LoadSections(); err != nil {
return nil, err
}
for _, sec := range f.Sections {
if sec.Type == elf.SHT_PROGBITS && sec.Flags&elf.SHF_TLS != 0 {
return &sec, nil
}
}
return nil, ErrNoTdata
}

// ReadVirtualMemory reads bytes from given virtual address
Expand Down

0 comments on commit 0220589

Please sign in to comment.