Skip to content

Commit b1017b5

Browse files
committed
Correctly find TLS block in aarch64.
Previously, we were just hardcoding the assumption that the TLS block for the main binary starts 16 bytes after the thread control block. This is _usually_ true, but not always, so let's follow the spec more carefully by actually chasing the required pointers to get the correct address.
1 parent 398dd62 commit b1017b5

2 files changed

Lines changed: 26 additions & 5 deletions

File tree

interpreter/customlabels/customlabels.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func Loader(_ interpreter.EbpfHandler, info *interpreter.LoaderInfo) (interprete
8080
return nil, err
8181
}
8282
if ef.Machine == elf.EM_AARCH64 {
83-
tlsAddr = libpf.Address(tlsSym.Address + 16)
83+
tlsAddr = libpf.Address(tlsSym.Address)
8484
} else if ef.Machine == elf.EM_X86_64 {
8585
// Symbol addresses are relative to the start of the
8686
// thread-local storage image, but the thread pointer points to the _end_

support/ebpf/interpreter_dispatcher.ebpf.c

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,12 +212,33 @@ get_native_custom_labels(PerCPURecord *record, NativeCustomLabelsProcInfo *proc)
212212
return false;
213213
}
214214

215-
u64 offset = tsd_base + proc->tls_offset;
216-
DEBUG_PRINT("cl: native custom labels data at 0x%llx", offset);
215+
int err;
216+
#if defined(__aarch64__)
217+
// ELF Handling For Thread-Local Storage, p.5.
218+
// The thread register points to a "TCB" (Thread Control Block)
219+
// whose first element is a pointer to a "DTV" (Dynamic Thread Vector)...
220+
u64 dtv_addr;
221+
if ((err = bpf_probe_read_user(&dtv_addr, sizeof(void *), (void *)(tsd_base)))) {
222+
increment_metric(metricID_UnwindNativeCustomLabelsErrReadData);
223+
DEBUG_PRINT("Failed to read TLS DTV addr: %d", err);
224+
return false;
225+
}
226+
// ... and at offsite 16 in the DTV, there is a pointer to the TLS block.
227+
u64 addr;
228+
if ((err = bpf_probe_read_user(&addr, sizeof(void *), (void *)(dtv_addr + 16)))) {
229+
increment_metric(metricID_UnwindNativeCustomLabelsErrReadData);
230+
DEBUG_PRINT("Failed to read main TLS block addr: %d", err);
231+
return false;
232+
}
233+
addr += proc->tls_offset;
234+
#else
235+
u64 addr = tsd_base + proc->tls_offset;
236+
#endif
237+
238+
DEBUG_PRINT("cl: native custom labels data at 0x%llx", addr);
217239

218240
NativeCustomLabelsSet *p_current_set;
219-
int err;
220-
if ((err = bpf_probe_read_user(&p_current_set, sizeof(void *), (void *)(offset)))) {
241+
if ((err = bpf_probe_read_user(&p_current_set, sizeof(void *), (void *)(addr)))) {
221242
increment_metric(metricID_UnwindNativeCustomLabelsErrReadData);
222243
DEBUG_PRINT("Failed to read custom labels current set pointer: %d", err);
223244
return false;

0 commit comments

Comments
 (0)