forked from open-telemetry/opentelemetry-ebpf-profiler
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tsd.h
63 lines (53 loc) · 1.96 KB
/
tsd.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#ifndef OPTI_TSD_H
#define OPTI_TSD_H
#include "bpfdefs.h"
// tsd_read reads from the Thread Specific Data location associated with the provided key.
static inline __attribute__((__always_inline__))
int tsd_read(const TSDInfo *tsi, const void *tsd_base, int key, void **out) {
const void *tsd_addr = tsd_base + tsi->offset;
if (tsi->indirect) {
// Read the memory pointer that contains the per-TSD key data
if (bpf_probe_read_user(&tsd_addr, sizeof(tsd_addr), tsd_addr)) {
goto err;
}
}
tsd_addr += key * tsi->multiplier;
DEBUG_PRINT("readTSD key %d from address 0x%lx", key, (unsigned long) tsd_addr);
if (bpf_probe_read_user(out, sizeof(*out), tsd_addr)) {
goto err;
}
return 0;
err:
DEBUG_PRINT("Failed to read TSD from 0x%lx", (unsigned long) tsd_addr);
increment_metric(metricID_UnwindErrBadTSDAddr);
return -1;
}
// tsd_get_base looks up the base address for TSD variables (TPBASE).
static inline __attribute__((__always_inline__))
int tsd_get_base(void **tsd_base) {
#ifdef TESTING_COREDUMP
*tsd_base = (void *) __cgo_ctx->tp_base;
return 0;
#else
u32 key = 0;
SystemConfig* syscfg = bpf_map_lookup_elem(&system_config, &key);
if (!syscfg) {
// Unreachable: array maps are always fully initialized.
return -1;
}
struct task_struct *task = (struct task_struct *)bpf_get_current_task();
// We need to read task->thread.fsbase (on x86_64), but we can't do so because
// we might have been compiled with different kernel headers, so the struct layout
// is likely to be different.
// syscfg->tpbase_offset is populated with the offset of `fsbase` or equivalent field
// relative to a `task_struct`, so we use that instead.
void *tpbase_ptr = ((char *)task) + syscfg->tpbase_offset;
if (bpf_probe_read_kernel(tsd_base, sizeof(void *), tpbase_ptr)) {
DEBUG_PRINT("Failed to read tpbase value");
increment_metric(metricID_UnwindErrBadTPBaseAddr);
return -1;
}
return 0;
#endif
}
#endif // OPTI_TSD_H