Skip to content

thread context 6/n: locate thread-local variables - #1853

Draft
nsavoire wants to merge 3 commits into
open-telemetry:mainfrom
DataDog:nsavoire/threadctx-tls
Draft

thread context 6/n: locate thread-local variables#1853
nsavoire wants to merge 3 commits into
open-telemetry:mainfrom
DataDog:nsavoire/threadctx-tls

Conversation

@nsavoire

@nsavoire nsavoire commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Part of the PR #1229 split. Stacked on #1843, whose commit is included here.

Adds a tls package that locates a thread-local variable of a running process, given the ELF that defines it.

What's here

Process address of TLS variable is computed in 2 steps:

  • Resolve classifies how a variable is accessed based only on ELF file.

  • Locate turns that into a TLSVarInfo by reading runtime relocations.

  • Resolve(ef, sym) (Var, error) determine the TLS access model from the relocation type that references the symbol (RelTLSDESC, RelDTPMOD64, RelTPOFF64, from pfelf: add RelTPOFF64 and pass matched RelocType to relocation visitor #1838), and falls back to local-exec for a symbol no relocation references in an executable.

  • Var.Locate(rm, bias) (VarInfo, error) reads the GOT slot holding TP-relative offset, tls_index {module_id, offset} or TLS descriptor depending on the TLS access model, and returns either a resolved static descriptor or a dynamic one awaiting its DTV layout (completed by SetDTVInfo).

  • pfelf.File.StaticTLSOffset computes the TP-relative offset of a local-exec variable from PT_TLS, for both TLS variants, matching LLD's getTlsTpOffset and glibc's _dl_determine_tlsoffset. Purely ELF-static, so it belongs next to ProgByType/VisitRelocations rather than in tls.

  • tlsdesc_aarch64.go: on aarch64 a resolved descriptor's argument is positive whether it is a TP offset or a tls_index pointer. Magnitude settles the common small offset, and above that bound the resolver body does: glibc, musl, bionic and uClibc-ng all write the static resolver as ldr x0, [x0, #8]; ret in hand-written assembly, so recognizing it is what makes the argument an offset. x86-64 settles the same question by sign.

The four access models are covered across both gnu and gnu2 TLS dialects.

Tests

  • locate_test.go: cases over synthetic process memory, one per access model and TLS variant plus the unresolved and malformed shapes.
  • tls_integration_test.go, behind the host_integration: fixtures over glibc and musl, every access model, both dialects, startup linkage and dlopen. Each fixture reports where its own thread-locals live, and the descriptor produced for them must resolve to the same address.

Where this sits in the stack

Locates a thread-local variable at unwind time: TP-relative when module_id is
0, else an offset within that module's TLS block, completed once libc
introspection supplies the DTV layout. resolved is explicit because a zeroed
TLSVarInfo is otherwise a valid static descriptor.

Fields are private to ensure callers go through the constructors: generate.sh
lowercases them after godefs, which exports every field name.
Computes the TP-relative offset of a local-exec thread-local from PT_TLS.
Purely ELF-static, so it belongs next to ProgByType rather than in the
caller that classifies TLS access models.
Resolve classifies how a thread-local is accessed, once per ELF, covering both
TLS dialects and all four access models. Locate then turns that into a
TLSVarInfo for one process: resolved for static TLS, awaiting the DTV layout
for dynamic TLS.

Locate is tested against synthetic process memory per access model, Resolve
against purpose-built fixtures for each relocation shape.
@nsavoire
nsavoire force-pushed the nsavoire/threadctx-tls branch from 160e8c0 to 8689e73 Compare September 11, 2026 15:13
@opentelemetry-pr-dashboard

Copy link
Copy Markdown

Pull request dashboard status

Waiting on the author · refreshed 2026-09-11 17:23 UTC

Move out of draft to request review.

Status above doesn't look right?
  • Just replied or pushed? Anything around or after the refresh time above may not be picked up yet — give it a few minutes.
  • Anything look wrong? Report it with what you expected; it helps us improve the dashboard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant