Improve the performance of getting the goid in the Golang (#82)
diff --git a/CHANGES.md b/CHANGES.md
index 6955adb..82cc739 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -10,6 +10,7 @@
* Support OpenSSL 3.0.x.
* Optimized the data structure in BPF.
* Support continuous profiling.
+* Improve the performance when getting `goid` in eBPF.
#### Bug Fixes
* Fix HTTP method name in protocol analyzer
diff --git a/bpf/include/api.h b/bpf/include/api.h
index aac5cca..fa4aa16 100644
--- a/bpf/include/api.h
+++ b/bpf/include/api.h
@@ -45,4 +45,14 @@
{
true=1, false=0
} bool;
+
+struct thread_struct {
+ long unsigned int fsbase;
+} __attribute__((preserve_access_index));
+
+struct task_struct {
+ __u32 pid;
+ __u32 tgid;
+ struct thread_struct thread;
+} __attribute__((preserve_access_index));
#endif
\ No newline at end of file
diff --git a/bpf/include/goid.c b/bpf/include/goid.c
deleted file mode 100644
index 80c0813..0000000
--- a/bpf/include/goid.c
+++ /dev/null
@@ -1,70 +0,0 @@
-// Licensed to Apache Software Foundation (ASF) under one or more contributor
-// license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright
-// ownership. Apache Software Foundation (ASF) licenses this file to you under
-// the Apache License, Version 2.0 (the "License"); you may
-// not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-#include "symbol_offsets.h"
-
-struct {
- __uint(type, BPF_MAP_TYPE_HASH);
- __uint(max_entries, 1024);
- __type(key, __u64);
- __type(value, __u64);
-} go_tgid_goid_map SEC(".maps");
-static __inline __u64 get_goid(__u64 id) {
- __u64 *val;
- val = bpf_map_lookup_elem(&go_tgid_goid_map, &id);
- return !val ? 0 : *val;
-}
-static __inline void set_goid(__u64 id, __u64 goid) {
- bpf_map_update_elem(&go_tgid_goid_map, &id, &goid, 0);
-}
-
-SEC("uprobe/casgstatus")
-int go_casgstatus(struct pt_regs* ctx) {
- const void* sp = (const void*)PT_REGS_SP(ctx);
- __u64* regs = go_regabi_regs(ctx);
- if (regs == NULL) {
- return 0;
- }
-
- __u64 id = bpf_get_current_pid_tgid();
- __u32 tgid = id >> 32;
- struct go_tls_args_symaddr_t* symaddrs = get_go_tls_args_symaddr(tgid);
- if (symaddrs == NULL) {
- return 0;
- }
-
- // get runtime.g
- void* gptr = NULL;
- assign_go_tls_arg(&gptr, sizeof(gptr), symaddrs->casg_status_gp_loc, sp, regs);
- if (gptr == NULL) {
- return 0;
- }
-
- // get goid in runtime.g
- int64_t goid;
- bpf_probe_read(&goid, sizeof(goid), gptr + symaddrs->gid_offset);
-
- // newval in runtime.g
- __u32 status;
- assign_go_tls_arg(&status, sizeof(status), symaddrs->casg_status_new_val_loc, sp, regs);
-
- // check the status is running
- if (status == 2) {
- set_goid(id, goid);
- }
- return 0;
-}
\ No newline at end of file
diff --git a/bpf/include/goid.h b/bpf/include/goid.h
new file mode 100644
index 0000000..92f0598
--- /dev/null
+++ b/bpf/include/goid.h
@@ -0,0 +1,55 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include "api.h"
+#include "symbol_offsets.h"
+
+struct {
+ __uint(type, BPF_MAP_TYPE_HASH);
+ __uint(max_entries, 1024);
+ __type(key, __u64);
+ __type(value, __u64);
+} go_tgid_goid_map SEC(".maps");
+static __inline __u64 get_goid(__u64 id) {
+ __u32 tgid = id >> 32;
+ struct go_tls_args_symaddr_t* symaddrs = get_go_tls_args_symaddr(tgid);
+ if (symaddrs == NULL) {
+ return 0;
+ }
+
+ // Get fsbase from `struct task_struct`.
+ const struct task_struct* task_ptr = (struct task_struct*)bpf_get_current_task();
+ if (!task_ptr) {
+ return 0;
+ }
+
+ // thread local storage
+ const void* fs_base;
+ bpf_probe_read_kernel(&fs_base, sizeof(fs_base), &(task_ptr->thread.fsbase));
+
+ __u64 g_addr;
+ // struct g location
+ int32_t g_addr_offset = -8;
+ bpf_probe_read_user(&g_addr, sizeof(void*), (void*)(fs_base + g_addr_offset));
+
+ // goid in struct g
+ __u64 goid;
+ bpf_probe_read_user(&goid, sizeof(void*), (void*)(g_addr + symaddrs->gid_offset));
+ return goid;
+}
\ No newline at end of file
diff --git a/bpf/include/symbol_offsets.h b/bpf/include/symbol_offsets.h
index 33b19ef..798b40c 100644
--- a/bpf/include/symbol_offsets.h
+++ b/bpf/include/symbol_offsets.h
@@ -84,10 +84,6 @@
__u64 tcp_conn_offset;
__u64 is_client_offset;
- // casg
- struct go_tls_arg_location_t casg_status_gp_loc;
- struct go_tls_arg_location_t casg_status_new_val_loc;
-
// read
struct go_tls_arg_location_t read_connection_loc;
struct go_tls_arg_location_t read_buffer_loc;
diff --git a/bpf/profiling/continuous/go_tls.c b/bpf/profiling/continuous/go_tls.c
index 60ed538..87325ac 100644
--- a/bpf/profiling/continuous/go_tls.c
+++ b/bpf/profiling/continuous/go_tls.c
@@ -16,7 +16,7 @@
// under the License.
#include "go_tls.h"
-#include "goid.c"
+#include "goid.h"
SEC("uprobe/go_tls_write")
int go_tls_write(struct pt_regs* ctx) {
diff --git a/bpf/profiling/network/go_tls.c b/bpf/profiling/network/go_tls.c
index 3fde4a5..5dbaa59 100644
--- a/bpf/profiling/network/go_tls.c
+++ b/bpf/profiling/network/go_tls.c
@@ -16,7 +16,7 @@
// under the License.
#include "go_tls.h"
-#include "goid.c"
+#include "goid.h"
SEC("uprobe/go_tls_write")
int go_tls_write(struct pt_regs* ctx) {
diff --git a/bpf/profiling/offcpu.h b/bpf/profiling/offcpu.h
index cc5a73b..95332c1 100644
--- a/bpf/profiling/offcpu.h
+++ b/bpf/profiling/offcpu.h
@@ -44,9 +44,4 @@
__type(key, struct key_t);
__type(value, struct value_t);
__uint(max_entries, 10000);
-} counts SEC(".maps");
-
-struct task_struct {
- __u32 pid;
- __u32 tgid;
-} __attribute__((preserve_access_index));
\ No newline at end of file
+} counts SEC(".maps");
\ No newline at end of file
diff --git a/pkg/profiling/continuous/checker/bpf/network/ssl.go b/pkg/profiling/continuous/checker/bpf/network/ssl.go
index 50261f4..747a95a 100644
--- a/pkg/profiling/continuous/checker/bpf/network/ssl.go
+++ b/pkg/profiling/continuous/checker/bpf/network/ssl.go
@@ -29,7 +29,7 @@
register.Envoy(bpf.EnvoyTlsArgsSymaddrMap, bpf.OpensslWrite, bpf.OpensslWriteRet, bpf.OpensslRead, bpf.OpensslReadRet)
- register.GoTLS(bpf.GoTlsArgsSymaddrMap, bpf.GoCasgstatus, bpf.GoTlsWrite, bpf.GoTlsWriteRet, bpf.GoTlsRead, bpf.GoTlsReadRet)
+ register.GoTLS(bpf.GoTlsArgsSymaddrMap, bpf.GoTlsWrite, bpf.GoTlsWriteRet, bpf.GoTlsRead, bpf.GoTlsReadRet)
register.Node(bpf.OpensslSymaddrMap, nil, bpf.OpensslWrite, bpf.OpensslWriteRet, bpf.OpensslRead, bpf.OpensslReadRet,
nil, nil, nil)
diff --git a/pkg/profiling/task/network/ssl.go b/pkg/profiling/task/network/ssl.go
index d3fd33e..0e23e7e 100644
--- a/pkg/profiling/task/network/ssl.go
+++ b/pkg/profiling/task/network/ssl.go
@@ -29,7 +29,7 @@
register.Envoy(nil, loader.OpensslWrite, loader.OpensslWriteRet, loader.OpensslRead, loader.OpensslReadRet)
- register.GoTLS(loader.GoTlsArgsSymaddrMap, loader.GoCasgstatus, loader.GoTlsWrite, loader.GoTlsWriteRet, loader.GoTlsRead, loader.GoTlsReadRet)
+ register.GoTLS(loader.GoTlsArgsSymaddrMap, loader.GoTlsWrite, loader.GoTlsWriteRet, loader.GoTlsRead, loader.GoTlsReadRet)
register.Node(nil, loader.NodeTlsSymaddrMap, loader.OpensslWrite, loader.OpensslWriteRet, loader.OpensslRead, loader.OpensslReadRet,
loader.NodeTlsRetSsl, loader.NodeTlsWrap, loader.NodeTlsWrapRet)
diff --git a/pkg/tools/ssl/gotls.go b/pkg/tools/ssl/gotls.go
index 2a88498..8a52ba8 100644
--- a/pkg/tools/ssl/gotls.go
+++ b/pkg/tools/ssl/gotls.go
@@ -62,10 +62,6 @@
TCPConnOffset uint64
IsClientOffset uint64
- // casgstatus(goroutine status change) function relate locations
- CasgStatusGPLoc GoSymbolLocation
- CasgStatusNEWValLoc GoSymbolLocation
-
// write function relate locations
WriteConnectionLoc GoSymbolLocation
WriteBufferLoc GoSymbolLocation
@@ -79,7 +75,7 @@
ReadRet1Loc GoSymbolLocation
}
-func (r *Register) GoTLS(symbolAddrMap *ebpf.Map, goIDChange, write, writeRet, read, readRet *ebpf.Program) {
+func (r *Register) GoTLS(symbolAddrMap *ebpf.Map, write, writeRet, read, readRet *ebpf.Program) {
r.addHandler("goTLS", func() (bool, error) {
buildVersionSymbol := r.searchSymbolInModules(r.modules, func(a, b string) bool {
return a == b
@@ -113,7 +109,6 @@
}
exeFile := r.linker.OpenUProbeExeFile(pidExeFile)
- exeFile.AddLinkWithType("runtime.casgstatus", true, goIDChange)
exeFile.AddGoLink(goTLSWriteSymbol, write, writeRet, elfFile)
exeFile.AddGoLink(goTLSReadSymbol, read, readRet, elfFile)
if e := r.linker.HasError(); e != nil {
@@ -201,10 +196,6 @@
assignError = r.assignGoTLSStructureOffset(assignError, reader, goTLSRuntimeG, "goid", &symbolAddresses.GIDOffset)
assignError = r.assignGoTLSStructureOffset(assignError, reader, goTLSConnSymbol, "isClient", &symbolAddresses.IsClientOffset)
- // gid status change
- assignError = r.assignGoTLSArgsLocation(assignError, gidStatusFunction, "gp", &symbolAddresses.CasgStatusGPLoc)
- assignError = r.assignGoTLSArgsLocation(assignError, gidStatusFunction, "newval", &symbolAddresses.CasgStatusNEWValLoc)
-
// write
assignError = r.assignGoTLSArgsLocation(assignError, writeFunction, "c", &symbolAddresses.WriteConnectionLoc)
assignError = r.assignGoTLSArgsLocation(assignError, writeFunction, "b", &symbolAddresses.WriteBufferLoc)