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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
| struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__uint(key_size, sizeof(u64)); // pid_tgid
__uint(value_size, sizeof(u64)); // parent goid
__uint(max_entries, MAX_ENTRIES);
} go_goid_map SEC(".maps"); // 用来获取 goid 状态
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(key_size, sizeof(u64));
__uint(value_size, sizeof(u8) * 5);
__uint(max_entries, 100);
} info_map SEC(".maps"); // 用来存储 goid->info
struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
} events SEC(".maps");
static __always_inline u64 get_goid(u32 tgid, u32 pid) {
unsigned long task_addr = (unsigned long)bpf_get_current_task();
unsigned long fsbase = 0;
unsigned long g = 0;
u64 goid = 0;
// 直接基于 偏移量进行处理了
// offset(task_struct, thread) = 4992
// offset(thread_struct, fsbase) = 40
bpf_probe_read(&fsbase, sizeof(fsbase),
(void *)(task_addr + OFF_TASK_THRD + OFF_THRD_FSBASE));
bpf_probe_read(&g, sizeof(g), (void *)(fsbase - 8));
bpf_probe_read(&goid, sizeof(goid), (void *)(g + GOID_OFFSET));
return goid;
}
SEC("uprobe/main_set")
int uprobe__main_set(struct pt_regs *ctx) {
uintptr_t info_p = 0;
u8 info[5];
u64 pid_tgid = bpf_get_current_pid_tgid();
u32 pid = (u32)(pid_tgid & 0x00FF);
u32 tgid = (u32)(pid_tgid >> 32);
u64 goid = 0;
goid = get_goid(tgid, pid);
SARG(ctx, 0, info_p);
bpf_probe_read(&info, sizeof(info), (const void *)info_p);
bpf_map_update_elem(&info_map, &goid, &info, BPF_ANY);
event_t event = {};
event.pid_tgid = pid_tgid;
memcpy(event.info, info, sizeof(info));
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &event, sizeof(event));
return 0;
}
SEC("uprobe/main_get")
int uprobe__main_get(struct pt_regs *ctx) {
uintptr_t info_p = 0;
u64 pid_tgid = bpf_get_current_pid_tgid();
u32 pid = (u32)(pid_tgid & 0x00FF);
u32 tgid = (u32)(pid_tgid >> 32);
u64 goid = 0;
goid = get_goid(tgid, pid);
void *r_info_p = NULL;
r_info_p = bpf_map_lookup_elem(&info_map, &goid);
if (r_info_p == NULL) {
return 0;
}
event_t event = {};
event.pid_tgid = pid_tgid;
SARG(ctx, 0, info_p);
u8 info[5];
memcpy(info, r_info_p, sizeof(info));
memcpy(event.info, info, sizeof(event.info));
event.res = bpf_probe_write_user((u8 *)info_p, info, sizeof(info));
event.addr = info_p;
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &event, sizeof(event));
return 0;
}
/* golang_runtime_newproc1
func newproc1(fn *funcval, argp unsafe.Pointer, narg int32, callergp *g,
callerpc uintptr) *g {
*/
SEC("uprobe/golang_runtime_newproc1")
int uprobe__golang_runtime_newproc1(struct pt_regs *ctx) {
u64 pid_tgid = bpf_get_current_pid_tgid();
uintptr_t g_addr = 0;
u64 cur_goid = 0;
SARG(ctx, 3, g_addr);
bpf_probe_read(&cur_goid, sizeof(cur_goid), (void *)(g_addr + GOID_OFFSET));
bpf_map_update_elem(&go_goid_map, &pid_tgid, &cur_goid, BPF_ANY);
return 0;
}
SEC("uprobe/golang_runtime_runqput")
int uprobe__golang_runtime_runqput(struct pt_regs *ctx) {
u64 pid_tgid = bpf_get_current_pid_tgid();
uintptr_t g_addr = 0;
u64 *parent_goid = NULL;
u64 child_goid = 0;
void *v_p = NULL;
parent_goid = bpf_map_lookup_elem(&go_goid_map, &pid_tgid);
if (parent_goid == NULL) {
return 0;
}
// 1. 获取新 goroutine 的 goid
SARG(ctx, 1, g_addr);
bpf_probe_read(&child_goid, sizeof(child_goid),
(void *)(g_addr + GOID_OFFSET));
// 2. 设置新 goid 绑定的 caller 信息
v_p = bpf_map_lookup_elem(&info_map, parent_goid);
if (v_p == NULL) {
return 0;
}
// 设置子 goid 绑定 caller 为 父 goid 信息
bpf_map_update_elem(&info_map, &child_goid, v_p, BPF_ANY);
bpf_map_delete_elem(&go_goid_map, &pid_tgid);
return 0;
}
|