|
|
@@ -378,33 +378,29 @@ SEC("uprobe/runtime.execute")
|
|
|
int runtime_execute(struct pt_regs *ctx)
|
|
|
{
|
|
|
__u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
|
-// __u32 tgid = pid_tgid >> 32;
|
|
|
-// __u64 goroutine_id2 = GOROUTINE(ctx);
|
|
|
-// debug("[Go] [runtime.execute]%llu",goroutine_id2);
|
|
|
-
|
|
|
-// struct ebpf_proc_info *info = bpf_map_lookup_elem(&proc_info_map, &tgid);
|
|
|
-// if (!info) {
|
|
|
-// return 0;
|
|
|
-// }
|
|
|
-// debug("[Go] [runtime.execute] has info");
|
|
|
+ __u32 tgid = pid_tgid >> 32;
|
|
|
|
|
|
- int offset_g_goid = 152;
|
|
|
-// if (offset_g_goid < 0) {
|
|
|
-// return 0;
|
|
|
-// }
|
|
|
+ struct ebpf_proc_info *info = bpf_map_lookup_elem(&proc_info_map, &tgid);
|
|
|
+ if (!info) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ int offset_g_goid = info->offsets[OFFSET_IDX_GOID_RUNTIME_G];
|
|
|
+ if (offset_g_goid < 0) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
void *g_ptr;
|
|
|
- g_ptr = (void *)PT_GO_REGS_PARM1(ctx);
|
|
|
|
|
|
-// if (is_register_based_call(info)) {
|
|
|
-// g_ptr = (void *)PT_GO_REGS_PARM1(ctx);
|
|
|
-// } else {
|
|
|
-// bpf_probe_read(&g_ptr, sizeof(g_ptr), (void *)(PT_REGS_SP(ctx) + 8));
|
|
|
-// }
|
|
|
+ if (is_register_based_call(info)) {
|
|
|
+ g_ptr = (void *)PT_GO_REGS_PARM1(ctx);
|
|
|
+ } else {
|
|
|
+ bpf_probe_read(&g_ptr, sizeof(g_ptr), (void *)(PT_REGS_SP(ctx) + 8));
|
|
|
+ }
|
|
|
|
|
|
__s64 goid = 0;
|
|
|
bpf_probe_read(&goid, sizeof(goid), g_ptr + offset_g_goid);
|
|
|
- debug("[Go] [runtime.execute] goid:%llu",goid);
|
|
|
+ debug("[Go] [runtime.execute] goid:%llu",goid);
|
|
|
+
|
|
|
bpf_map_update_elem(&goroutines_map, &pid_tgid, &goid, BPF_ANY);
|
|
|
|
|
|
return 0;
|
|
|
@@ -420,26 +416,56 @@ SEC("uprobe/enter_runtime.newproc1")
|
|
|
int enter_runtime_newproc1(struct pt_regs *ctx)
|
|
|
{
|
|
|
__u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
|
+ __u32 tgid = pid_tgid >> 32;
|
|
|
|
|
|
- int offset_g_goid = 152;
|
|
|
+ struct ebpf_proc_info *info =
|
|
|
+ bpf_map_lookup_elem(&proc_info_map, &tgid);
|
|
|
+ if (!info) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ // go less than 1.15 cannot get parent-child coroutine relationship
|
|
|
+ // ~ go1.14: func newproc1(fn *funcval, argp unsafe.Pointer, narg int32, callergp *g, callerpc uintptr)
|
|
|
+ if (info->version < GO_VERSION(1, 15, 0)) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
+ int offset_g_goid = info->offsets[OFFSET_IDX_GOID_RUNTIME_G];
|
|
|
+ if (offset_g_goid < 0) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
void *g_ptr;
|
|
|
- g_ptr = (void *)PT_GO_REGS_PARM2(ctx);
|
|
|
+ if (is_register_based_call(info)) {
|
|
|
+ // https://github.com/golang/go/commit/8e5304f7298a0eef48e4796017c51b4d9aeb52b5
|
|
|
+ if (info->version >= GO_VERSION(1, 18, 0)) {
|
|
|
+ g_ptr = (void *)PT_GO_REGS_PARM2(ctx);
|
|
|
+ } else {
|
|
|
+ g_ptr = (void *)PT_GO_REGS_PARM4(ctx);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (info->version >= GO_VERSION(1, 18, 0)) {
|
|
|
+ bpf_probe_read(&g_ptr, sizeof(g_ptr),
|
|
|
+ (void *)(PT_REGS_SP(ctx) + 16));
|
|
|
+ } else {
|
|
|
+ bpf_probe_read(&g_ptr, sizeof(g_ptr),
|
|
|
+ (void *)(PT_REGS_SP(ctx) + 32));
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
__s64 goid = 0;
|
|
|
bpf_probe_read(&goid, sizeof(goid), g_ptr + offset_g_goid);
|
|
|
-
|
|
|
if (!goid) {
|
|
|
return 0;
|
|
|
}
|
|
|
- debug("[Go] [runtime.newproc1] goid:%llu",goid);
|
|
|
+ debug("[Go] [runtime.newproc1] goid:%llu",goid);
|
|
|
+
|
|
|
struct go_newproc_caller caller = {
|
|
|
- .goid = goid,
|
|
|
- .sp = (void *)PT_REGS_SP(ctx),
|
|
|
+ .goid = goid,
|
|
|
+ .sp = (void *)PT_REGS_SP(ctx),
|
|
|
};
|
|
|
bpf_map_update_elem(&pid_tgid_callerid_map, &pid_tgid, &caller,
|
|
|
- BPF_ANY);
|
|
|
+ BPF_ANY);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
@@ -453,30 +479,49 @@ int exit_runtime_newproc1(struct pt_regs *ctx)
|
|
|
__u64 pid_tgid = bpf_get_current_pid_tgid();
|
|
|
__u32 tgid = pid_tgid >> 32;
|
|
|
|
|
|
- int offset_g_goid = 152;
|
|
|
+ struct ebpf_proc_info *info =
|
|
|
+ bpf_map_lookup_elem(&proc_info_map, &tgid);
|
|
|
+ if (!info) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(info->version < GO_VERSION(1, 15, 0)){
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ int offset_g_goid = info->offsets[OFFSET_IDX_GOID_RUNTIME_G];
|
|
|
+ if (offset_g_goid < 0) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
struct go_newproc_caller *caller =
|
|
|
- bpf_map_lookup_elem(&pid_tgid_callerid_map, &pid_tgid);
|
|
|
+ bpf_map_lookup_elem(&pid_tgid_callerid_map, &pid_tgid);
|
|
|
if (!caller) {
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
void *g_ptr;
|
|
|
- g_ptr = (void *)PT_GO_REGS_PARM1(ctx);
|
|
|
+ if (is_register_based_call(info)) {
|
|
|
+ g_ptr = (void *)PT_GO_REGS_PARM1(ctx);
|
|
|
+ } else {
|
|
|
+ if (info->version >= GO_VERSION(1, 18, 0)) {
|
|
|
+ bpf_probe_read(&g_ptr, sizeof(g_ptr), caller->sp + 32);
|
|
|
+ } else {
|
|
|
+ bpf_probe_read(&g_ptr, sizeof(g_ptr), caller->sp + 48);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- // 获取当前协程id
|
|
|
__s64 goid = 0;
|
|
|
bpf_probe_read(&goid, sizeof(goid), g_ptr + offset_g_goid);
|
|
|
if (!goid) {
|
|
|
bpf_map_delete_elem(&pid_tgid_callerid_map, &pid_tgid);
|
|
|
return 0;
|
|
|
}
|
|
|
- debug("[Go] [runtime.newproc1.exit] current->goid:%llu",goid);
|
|
|
- // 生成当前协程key
|
|
|
- struct go_key key = { .tgid = tgid, .goid = goid };
|
|
|
- goid = caller->goid;
|
|
|
- debug("[Go] [runtime.newproc1.exit] caller->goid:%llu",goid);
|
|
|
-
|
|
|
+ debug("[Go] [runtime.newproc1.exit] current->goid:%llu",goid);
|
|
|
+ // 生成当前协程key
|
|
|
+ struct go_key key = { .tgid = tgid, .goid = goid };
|
|
|
+ goid = caller->goid;
|
|
|
+ debug("[Go] [runtime.newproc1.exit] caller->goid:%llu",goid); goid = caller->goid;
|
|
|
bpf_map_update_elem(&go_ancerstor_map, &key, &goid, BPF_ANY);
|
|
|
|
|
|
bpf_map_delete_elem(&pid_tgid_callerid_map, &pid_tgid);
|