Browse Source

Fixed #TASK_GK-2944 sys offsets

Carl 2 năm trước cách đây
mục cha
commit
55bb7af9b1

+ 5 - 1
.gitignore

@@ -1,3 +1,7 @@
 .idea
 .vagrant
-ebpftracer/ebpf.go
+ebpftracer/ebpf.go
+CMakeLists.txt
+cmake-build-debug
+*.o
+.DS_Store

+ 2 - 2
containers/registry.go

@@ -289,7 +289,7 @@ func (r *Registry) getOrCreateContainer(pid uint32) *Container {
 	// add ns/workload/podname
 	id, extensionTag := calcId(cg, md, pid)
 
-	klog.Infof("calculated container id %d -> %s -> %s", pid, cg.Id, id)
+	//klog.Infof("calculated container id %d -> %s -> %s", pid, cg.Id, id)
 	if id == "" {
 		if cg.Id == "/init.scope" && pid != 1 {
 			klog.InfoS("ignoring without persisting", "cg", cg.Id, "pid", pid)
@@ -322,7 +322,7 @@ func (r *Registry) getOrCreateContainer(pid uint32) *Container {
 		return nil
 	}
 
-	klog.InfoS("detected a new container", "pid", pid, "cg", cg.Id, "id", id)
+	//klog.InfoS("detected a new container", "pid", pid, "cg", cg.Id, "id", id)
 	// add ns/workload/podname/pid/ctype
 	//sType := fmt.Sprintf("%d", cg.ContainerType)
 

+ 20 - 0
ebpftracer/ebpf/common/load_const.h

@@ -0,0 +1,20 @@
+#ifndef __LOAD_CONST_H
+#define __LOAD_CONST_H
+
+#define LOAD_CONSTANT(param, var) asm("%0 = " param " ll" : "=r"(var))
+
+#endif // !__LOAD_CONST_H
+
+static __always_inline __u64 load_kernel_version()
+{
+    __u64 var = 0;
+    LOAD_CONSTANT("kernel_version", var);
+    return var;
+}
+
+static __always_inline __u32 load_filter_pid()
+{
+    __u32 var = 0;
+    LOAD_CONSTANT("filter_pid", var);
+    return var;
+}

+ 10 - 1
ebpftracer/ebpf/ebpf.c

@@ -8,7 +8,7 @@
 #include "vmlinux.h"
 #include <bpf/bpf_helpers.h>
 #include <bpf/bpf_core_read.h>
-#include <bpf/bpf_tracing.h>
+//#include <bpf/bpf_tracing.h>
 #include <bpf/bpf_endian.h>
 
 #define EVENT_TYPE_PROCESS_START	1
@@ -46,10 +46,19 @@
 })
 #endif
 
+#define debug(fmt, ...)                                 \
+({                                                             \
+    char ____fmt[] = fmt;                                      \
+    bpf_trace_printk(____fmt, sizeof(____fmt), ##__VA_ARGS__); \
+})
+
+#include "common/load_const.h"
 #include "proc.c"
 #include "file.c"
 
+// new main
 #include "socket_trace.c"
+
 #include "tcp/state.c"
 #include "tcp/retransmit.c"
 #include "l7/uprobe_base_bpf.c"

+ 12 - 12
ebpftracer/ebpf/include/bpf_base.h

@@ -94,16 +94,16 @@ struct task_struct;
 #define PT_REGS_SP(x) ((x)->esp)
 #define PT_REGS_IP(x) ((x)->eip)
 #else
-//#define PT_REGS_PARM1(x) ((x)->rdi)
-//#define PT_REGS_PARM2(x) ((x)->rsi)
-//#define PT_REGS_PARM3(x) ((x)->rdx)
-//#define PT_REGS_PARM4(x) ((x)->rcx)
-//#define PT_REGS_PARM5(x) ((x)->r8)
-//#define PT_REGS_RET(x) ((x)->rsp)
-//#define PT_REGS_FP(x) ((x)->rbp)
-//#define PT_REGS_RC(x) ((x)->rax)
-//#define PT_REGS_SP(x) ((x)->rsp)
-//#define PT_REGS_IP(x) ((x)->rip)
+#define PT_REGS_PARM1(x) ((x)->rdi)
+#define PT_REGS_PARM2(x) ((x)->rsi)
+#define PT_REGS_PARM3(x) ((x)->rdx)
+#define PT_REGS_PARM4(x) ((x)->rcx)
+#define PT_REGS_PARM5(x) ((x)->r8)
+#define PT_REGS_RET(x) ((x)->rsp)
+#define PT_REGS_FP(x) ((x)->rbp)
+#define PT_REGS_RC(x) ((x)->rax)
+#define PT_REGS_SP(x) ((x)->rsp)
+#define PT_REGS_IP(x) ((x)->rip)
 #endif
 #endif
 #elif defined(__aarch64__)
@@ -197,8 +197,8 @@ _Pragma("GCC error \"PT_GO_REGS_PARM\"");
 
 #define NAME(N)  __##N
 
-#define PROGTP(F) SEC("prog/tp/"__stringify(F)) int bpf_prog_tp__##F
-#define PROGKP(F) SEC("prog/kp/"__stringify(F)) int bpf_prog_kp__##F
+#define PROGTP(F) SEC("tp/prog/tp/"__stringify(F)) int bpf_prog_tp__##F
+#define PROGKP(F) SEC("tp/prog/kp/"__stringify(F)) int bpf_prog_kp__##F
 #define KRETPROG(F) SEC("kretprobe/"__stringify(F)) int kretprobe__##F
 #define KPROG(F) SEC("kprobe/"__stringify(F)) int kprobe__##F
 #define TPPROG(F) SEC("tracepoint/syscalls/"__stringify(F)) int bpf_func_##F

+ 434 - 497
ebpftracer/ebpf/include/protocol_inference.h

@@ -50,80 +50,80 @@ static __inline bool is_socket_info_valid(struct socket_info_t *sk_info)
     return (sk_info != NULL && sk_info->uid != 0);
 }
 
-//static __inline int is_http_response(const char *data)
-//{
-//    return (data[0] == 'H' && data[1] == 'T' && data[2] == 'T'
-//            && data[3] == 'P' && data[4] == '/' && data[5] == '1'
-//            && data[6] == '.' && data[8] == ' ');
-//}
-
-//static __inline int is_http_request(const char *data, int data_len)
-//{
-//    switch (data[0]) {
-//        /* DELETE */
-//        case 'D':
-//            if ((data[1] != 'E') || (data[2] != 'L') || (data[3] != 'E')
-//                || (data[4] != 'T') || (data[5] != 'E')
-//                || (data[6] != ' ')) {
-//                return 0;
-//            }
-//            break;
-//
-//            /* GET */
-//        case 'G':
-//            if ((data[1] != 'E') || (data[2] != 'T') || (data[3] != ' ')) {
-//                return 0;
-//            }
-//            break;
-//
-//            /* HEAD */
-//        case 'H':
-//            if ((data[1] != 'E') || (data[2] != 'A') || (data[3] != 'D')
-//                || (data[4] != ' ')) {
-//                return 0;
-//            }
-//            break;
-//
-//            /* OPTIONS */
-//        case 'O':
-//            if (data_len < 8 || (data[1] != 'P') || (data[2] != 'T')
-//                || (data[3] != 'I') || (data[4] != 'O') || (data[5] != 'N')
-//                || (data[6] != 'S') || (data[7] != ' ')) {
-//                return 0;
-//            }
-//            break;
-//
-//            /* PATCH/POST/PUT */
-//        case 'P':
-//            switch (data[1]) {
-//                case 'A':
-//                    if ((data[2] != 'T') || (data[3] != 'C')
-//                        || (data[4] != 'H') || (data[5] != ' ')) {
-//                        return 0;
-//                    }
-//                    break;
-//                case 'O':
-//                    if ((data[2] != 'S') || (data[3] != 'T')
-//                        || (data[4] != ' ')) {
-//                        return 0;
-//                    }
-//                    break;
-//                case 'U':
-//                    if ((data[2] != 'T') || (data[3] != ' ')) {
-//                        return 0;
-//                    }
-//                    break;
-//                default:
-//                    return 0;
-//            }
-//            break;
-//
-//        default:
-//            return 0;
-//    }
-//
-//    return 1;
-//}
+static __inline int is_http_response2(const char *data)
+{
+    return (data[0] == 'H' && data[1] == 'T' && data[2] == 'T'
+            && data[3] == 'P' && data[4] == '/' && data[5] == '1'
+            && data[6] == '.' && data[8] == ' ');
+}
+
+static __inline int is_http_request2(const char *data, int data_len)
+{
+    switch (data[0]) {
+        /* DELETE */
+        case 'D':
+            if ((data[1] != 'E') || (data[2] != 'L') || (data[3] != 'E')
+                || (data[4] != 'T') || (data[5] != 'E')
+                || (data[6] != ' ')) {
+                return 0;
+            }
+            break;
+
+            /* GET */
+        case 'G':
+            if ((data[1] != 'E') || (data[2] != 'T') || (data[3] != ' ')) {
+                return 0;
+            }
+            break;
+
+            /* HEAD */
+        case 'H':
+            if ((data[1] != 'E') || (data[2] != 'A') || (data[3] != 'D')
+                || (data[4] != ' ')) {
+                return 0;
+            }
+            break;
+
+            /* OPTIONS */
+        case 'O':
+            if (data_len < 8 || (data[1] != 'P') || (data[2] != 'T')
+                || (data[3] != 'I') || (data[4] != 'O') || (data[5] != 'N')
+                || (data[6] != 'S') || (data[7] != ' ')) {
+                return 0;
+            }
+            break;
+
+            /* PATCH/POST/PUT */
+        case 'P':
+            switch (data[1]) {
+                case 'A':
+                    if ((data[2] != 'T') || (data[3] != 'C')
+                        || (data[4] != 'H') || (data[5] != ' ')) {
+                        return 0;
+                    }
+                    break;
+                case 'O':
+                    if ((data[2] != 'S') || (data[3] != 'T')
+                        || (data[4] != ' ')) {
+                        return 0;
+                    }
+                    break;
+                case 'U':
+                    if ((data[2] != 'T') || (data[3] != ' ')) {
+                        return 0;
+                    }
+                    break;
+                default:
+                    return 0;
+            }
+            break;
+
+        default:
+            return 0;
+    }
+
+    return 1;
+}
 
 static __inline __u8 get_block_fragment_offset(__u8 fix_sz,
                                                __u8 flags_padding,
@@ -350,52 +350,52 @@ static __inline enum message_type parse_http2_headers_frame(const char *buf_src,
     return msg_type;
 }
 
-//static __inline enum message_type infer_http2_message(const char *buf_src,
-//                                                      size_t count,
-//                                                      struct conn_info_t
-//                                                      *conn_info)
-//{
-//    if (!is_protocol_enabled(PROTO_HTTP2)) {
-//        return MSG_UNKNOWN;
-//    }
-//
-//    // When go uprobe http2 cannot be used, use kprobe/tracepoint to collect data
-//    if (skip_http2_kprobe()) {
-//        if (conn_info->direction == T_INGRESS &&
-//            conn_info->tuple.l4_protocol == IPPROTO_TCP) {
-//            struct http2_tcp_seq_key tcp_seq_key = {
-//                    .tgid = bpf_get_current_pid_tgid() >> 32,
-//                    .fd = conn_info->fd,
-//                    .tcp_seq_end =
-//                    get_tcp_read_seq_from_fd(conn_info->fd),
-//            };
-//            // make linux 4.14 validator happy
-//            __u32 tcp_seq = tcp_seq_key.tcp_seq_end - count;
-//            bpf_map_update_elem(&http2_tcp_seq_map, &tcp_seq_key,
-//                                &tcp_seq, BPF_NOEXIST);
-//        }
-//        return MSG_UNKNOWN;
-//    }
-//
-//    if (is_socket_info_valid(conn_info->socket_info_ptr)) {
-//        if (conn_info->socket_info_ptr->l7_proto != PROTO_HTTP2)
-//            return MSG_UNKNOWN;
-//
-//        if (parse_http2_headers_frame(buf_src, count, conn_info, false) !=
-//            MSG_RECONFIRM)
-//            return MSG_UNKNOWN;
-//
-//        if (conn_info->socket_info_ptr->role == ROLE_SERVER)
-//            return (conn_info->direction == T_INGRESS) ?
-//                   MSG_REQUEST : MSG_RESPONSE;
-//
-//        if (conn_info->socket_info_ptr->role == ROLE_CLIENT)
-//            return (conn_info->direction == T_INGRESS) ?
-//                   MSG_RESPONSE: MSG_REQUEST;
-//    }
-//
-//    return parse_http2_headers_frame(buf_src, count, conn_info, true);
-//}
+static __inline enum message_type infer_http2_message(const char *buf_src,
+                                                      size_t count,
+                                                      struct conn_info_t
+                                                      *conn_info)
+{
+    if (!is_protocol_enabled(PROTO_HTTP2)) {
+        return MSG_UNKNOWN;
+    }
+
+    // When go uprobe http2 cannot be used, use kprobe/tracepoint to collect data
+    if (skip_http2_kprobe()) {
+        if (conn_info->direction == T_INGRESS &&
+            conn_info->tuple.l4_protocol == IPPROTO_TCP) {
+            struct http2_tcp_seq_key tcp_seq_key = {
+                    .tgid = bpf_get_current_pid_tgid() >> 32,
+                    .fd = conn_info->fd,
+                    .tcp_seq_end =
+                    get_tcp_read_seq_from_fd(conn_info->fd),
+            };
+            // make linux 4.14 validator happy
+            __u32 tcp_seq = tcp_seq_key.tcp_seq_end - count;
+            bpf_map_update_elem(&http2_tcp_seq_map, &tcp_seq_key,
+                                &tcp_seq, BPF_NOEXIST);
+        }
+        return MSG_UNKNOWN;
+    }
+
+    if (is_socket_info_valid(conn_info->socket_info_ptr)) {
+        if (conn_info->socket_info_ptr->l7_proto != PROTO_HTTP2)
+            return MSG_UNKNOWN;
+
+        if (parse_http2_headers_frame(buf_src, count, conn_info, false) !=
+            MSG_RECONFIRM)
+            return MSG_UNKNOWN;
+
+        if (conn_info->socket_info_ptr->role == ROLE_SERVER)
+            return (conn_info->direction == T_INGRESS) ?
+                   MSG_REQUEST : MSG_RESPONSE;
+
+        if (conn_info->socket_info_ptr->role == ROLE_CLIENT)
+            return (conn_info->direction == T_INGRESS) ?
+                   MSG_RESPONSE: MSG_REQUEST;
+    }
+
+    return parse_http2_headers_frame(buf_src, count, conn_info, true);
+}
 
 static __inline enum message_type infer_http_message(const char *buf,
                                                      size_t count,
@@ -417,13 +417,13 @@ static __inline enum message_type infer_http_message(const char *buf,
         return MSG_UNKNOWN;
     }
 
-//    if (is_http_response(buf)) {
-//        return MSG_RESPONSE;
-//    }
-//
-//    if (is_http_request(buf, count)) {
-//        return MSG_REQUEST;
-//    }
+    if (is_http_response2(buf)) {
+        return MSG_RESPONSE;
+    }
+
+    if (is_http_request2(buf, count)) {
+        return MSG_REQUEST;
+    }
 
     return MSG_UNKNOWN;
 }
@@ -482,9 +482,9 @@ static __inline enum message_type infer_mysql_message(const char *buf,
                                                       struct conn_info_t
                                                       *conn_info)
 {
-//    if (!is_protocol_enabled(PROTO_MYSQL)) {
-//        return MSG_UNKNOWN;
-//    }
+    if (!is_protocol_enabled(PROTO_MYSQL)) {
+        return MSG_UNKNOWN;
+    }
 
     if (count == 4) {
         save_prev_data(buf, conn_info);
@@ -636,198 +636,198 @@ static __inline bool infer_pgsql_startup_message(const char* buf,
     return true;
 }
 
-///*
-// * ref: https://developer.aliyun.com/article/751984
-// * | char tag | int32 len | payload |
-// * tag 的取值参考 src/flow_generator/protocol_logs/sql/postgresql.rs
-// */
-//static __inline enum message_type infer_pgsql_query_message(const char *buf,
-//                                                            const char *s_buf,
-//                                                            size_t count)
-//{
-//    // Only a judgement query.
-//    static const char tag_q = 'Q';
-//    // In the protocol format, the size of the "len" field is 4 bytes,
-//    // and the minimum command length is 4 bytes for "COPY/MOVE",
-//    // The minimal length is therefore 8.
-//    static const __u32 min_payload_len = 8;
-//    // Typical query message size is below an artificial limit.
-//    // 30000 is copied from postgres code base:
-//    // https://github.com/postgres/postgres/tree/master/src/interfaces/libpq/fe-protocol3.c#L94
-//    static const __u32 max_payload_len = 30000;
-//    // Minimum length = tag(char) + len(int32)
-//    static const int min_msg_len = 1 + sizeof(__u32);
-//
-//    // Msg length check
-//    if (count < min_msg_len) {
-//        return MSG_UNKNOWN;
-//    }
-//
-//    // Tag check
-//    if (buf[0] != tag_q) {
-//        return MSG_UNKNOWN;
-//    }
-//
-//    // Payload length check
-//    __u32 length;
-//    bpf_probe_read(&length, sizeof(length), s_buf + 1);
-//    length = __bpf_ntohl(length);
-//    if (length < min_payload_len || length > max_payload_len) {
-//        return MSG_UNKNOWN;
-//    }
-//
-//    // If the input includes a whole message (1 byte tag + length),
-//    // check the last character.
-//    if (length + 1 <= (__u32)count) {
-//        char last_char = ' '; //Non-zero initial value
-//        bpf_probe_read(&last_char, sizeof(last_char), s_buf + length);
-//        if (last_char != '\0')
-//            return MSG_UNKNOWN;
-//    }
-//
-//    return MSG_REQUEST;
-//}
-
-//static __inline enum message_type infer_postgre_message(const char *buf,
-//                                                        size_t count,
-//                                                        struct conn_info_t
-//                                                        *conn_info)
-//{
-//#define POSTGRE_INFER_BUF_SIZE 32
-//
-//    if (!is_protocol_enabled(PROTO_POSTGRESQL)) {
-//        return MSG_UNKNOWN;
-//    }
-//
-//    if (conn_info->tuple.l4_protocol != IPPROTO_TCP){
-//        return MSG_UNKNOWN;
-//    }
-//
-//    char infer_buf[POSTGRE_INFER_BUF_SIZE];
-//    bpf_probe_read(infer_buf, sizeof(infer_buf), buf);
-//
-//    if (is_socket_info_valid(conn_info->socket_info_ptr)) {
-//        if (conn_info->socket_info_ptr->l7_proto != PROTO_POSTGRESQL)
-//            return MSG_UNKNOWN;
-//        char tag = infer_buf[0];
-//        switch (tag) {
-//            // req, common, can not infer msg type, return MSG_REQUEST
-//            case 'Q': case 'P': case 'B': case 'F': case 'X': case 'f':
-//            case 'C': case 'E': case 'S': case 'D': case 'H': case 'd':
-//            case 'c':
-//                return MSG_REQUEST;
-//            case 'Z': case 'I': case '1': case '2': case '3': case 'K':
-//            case 'T': case 'n': case 'N': case 't': case 'G': case 'W':
-//            case 'R':
-//                return MSG_RESPONSE;
-//            default:
-//                return MSG_UNKNOWN;
-//        }
-//    }
-//
-//    if (infer_pgsql_startup_message(infer_buf, count))
-//        return MSG_REQUEST;
-//
-//    return infer_pgsql_query_message(infer_buf, buf, count);
-//}
-
-///*
-// * Request command protocol for v1
-// * 0     1     2           4           6           8          10           12          14         16
-// * +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
-// * |proto| type| cmdcode   |ver2 |   requestId           |codec|        timeout        |  classLen |
-// * +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
-// * |headerLen  | contentLen            |                             ... ...                       |
-// * +-----------+-----------+-----------+                                                           +
-// * |               className + header  + content  bytes                                            |
-// * +                                                                                               +
-// * |                               ... ...                                                         |
-// * +-----------------------------------------------------------------------------------------------+
-// *
-// * Response command protocol for v1
-// * 0     1     2     3     4           6           8          10           12          14         16
-// * +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
-// * |proto| type| cmdcode   |ver2 |   requestId           |codec|respstatus |  classLen |headerLen  |
-// * +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
-// * | contentLen            |                  ... ...                                              |
-// * +-----------------------+                                                                       +
-// * |                         className + header  + content  bytes                                  |
-// * +                                                                                               +
-// * |                               ... ...                                                         |
-// * +-----------------------------------------------------------------------------------------------+
-// *
-// * ref: https://github.com/sofastack/sofa-bolt/blob/42e4e3d756b7655c0d4a058989c66d9eb09591fa/plugins/wireshark/bolt.lua
-// */
-//static __inline enum message_type infer_sofarpc_message(const char *buf,
-//                                                        size_t count,
-//                                                        struct conn_info_t
-//                                                        *conn_info)
-//{
-//    static const __u8 bolt_resp_header_len = 20;
-//    static const __u8 bolt_req_header_len = 22;
-//    static const __u8 bolt_ver_v1 = 0x01;
-//    static const __u8 type_req = 0x01;
-//    static const __u8 type_resp = 0x0;
-//    static const __u16 cmd_code_req = 0x01;
-//    static const __u16 cmd_code_resp = 0x02;
-//    static const __u8 codec_hessian = 0;
-//    static const __u8 codec_hessian2 = 1;
-//    static const __u8 codec_protobuf = 11;
-//    static const __u8 codec_json = 12;
-//
-//    if (count < 20 || !is_protocol_enabled(PROTO_SOFARPC))
-//        return MSG_UNKNOWN;
-//
-//    const __u8 *infer_buf = (const __u8 *)buf;
-//    __u8 ver = infer_buf[0];	//version for protocol
-//    __u8 type = infer_buf[1];	// request/response/request oneway
-//
-//    if (is_socket_info_valid(conn_info->socket_info_ptr)) {
-//        if (conn_info->socket_info_ptr->l7_proto != PROTO_SOFARPC)
-//            return MSG_UNKNOWN;
-//        goto out;
-//    }
-//    // code for remoting command (Heartbeat, RpcRequest, RpcResponse)
-//    __u16 cmdcode = __bpf_ntohs(*(__u16 *) & infer_buf[2]);
-//
-//    // 0 -- "hessian", 1 -- "hessian2", 11 -- "protobuf", 12 -- "json"
-//    __u8 codec = infer_buf[9];
-//
-//    if (!((ver == bolt_ver_v1)
-//          && (type == type_req || type == type_resp)
-//          && (cmdcode == cmd_code_req || cmdcode == cmd_code_resp)
-//          && (codec == codec_hessian || codec == codec_hessian2
-//              || codec == codec_protobuf || codec == codec_json)))
-//        return MSG_UNKNOWN;
-//
-//    // length of request or response class name
-//    // length of header
-//    __u16 class_len, header_len;
-//
-//    // bolt_ver_v1
-//    if (type == type_req) {
-//        class_len = __bpf_ntohs(*(__u16 *) & infer_buf[14]);
-//        header_len = __bpf_ntohs(*(__u16 *) & infer_buf[16]);
-//        if ((bolt_req_header_len + class_len + header_len) > count)
-//            return MSG_UNKNOWN;
-//    }
-//
-//    if (cmdcode == cmd_code_resp) {
-//        // (resp)respStatus: response status
-//        __u16 resp_status = __bpf_ntohl(*(__u16 *) & infer_buf[10]);
-//        if (!(resp_status >= 0 && resp_status <= 18))
-//            return MSG_UNKNOWN;
-//        class_len = __bpf_ntohs(*(__u16 *) & infer_buf[12]);
-//        header_len = __bpf_ntohs(*(__u16 *) & infer_buf[14]);
-//        //content_len = __bpf_ntohl(*(__u32 *)&infer_buf[16]);
-//        if ((bolt_resp_header_len + class_len + header_len) > count)
-//            return MSG_UNKNOWN;
-//
-//    }
-//
-//    out:
-//    return type == type_req ? MSG_REQUEST : MSG_RESPONSE;
-//}
+/*
+ * ref: https://developer.aliyun.com/article/751984
+ * | char tag | int32 len | payload |
+ * tag 的取值参考 src/flow_generator/protocol_logs/sql/postgresql.rs
+ */
+static __inline enum message_type infer_pgsql_query_message(const char *buf,
+                                                            const char *s_buf,
+                                                            size_t count)
+{
+    // Only a judgement query.
+    static const char tag_q = 'Q';
+    // In the protocol format, the size of the "len" field is 4 bytes,
+    // and the minimum command length is 4 bytes for "COPY/MOVE",
+    // The minimal length is therefore 8.
+    static const __u32 min_payload_len = 8;
+    // Typical query message size is below an artificial limit.
+    // 30000 is copied from postgres code base:
+    // https://github.com/postgres/postgres/tree/master/src/interfaces/libpq/fe-protocol3.c#L94
+    static const __u32 max_payload_len = 30000;
+    // Minimum length = tag(char) + len(int32)
+    static const int min_msg_len = 1 + sizeof(__u32);
+
+    // Msg length check
+    if (count < min_msg_len) {
+        return MSG_UNKNOWN;
+    }
+
+    // Tag check
+    if (buf[0] != tag_q) {
+        return MSG_UNKNOWN;
+    }
+
+    // Payload length check
+    __u32 length;
+    bpf_probe_read(&length, sizeof(length), s_buf + 1);
+    length = __bpf_ntohl(length);
+    if (length < min_payload_len || length > max_payload_len) {
+        return MSG_UNKNOWN;
+    }
+
+    // If the input includes a whole message (1 byte tag + length),
+    // check the last character.
+    if (length + 1 <= (__u32)count) {
+        char last_char = ' '; //Non-zero initial value
+        bpf_probe_read(&last_char, sizeof(last_char), s_buf + length);
+        if (last_char != '\0')
+            return MSG_UNKNOWN;
+    }
+
+    return MSG_REQUEST;
+}
+
+static __inline enum message_type infer_postgre_message(const char *buf,
+                                                        size_t count,
+                                                        struct conn_info_t
+                                                        *conn_info)
+{
+#define POSTGRE_INFER_BUF_SIZE 32
+
+    if (!is_protocol_enabled(PROTO_POSTGRESQL)) {
+        return MSG_UNKNOWN;
+    }
+
+    if (conn_info->tuple.l4_protocol != IPPROTO_TCP){
+        return MSG_UNKNOWN;
+    }
+
+    char infer_buf[POSTGRE_INFER_BUF_SIZE];
+    bpf_probe_read(infer_buf, sizeof(infer_buf), buf);
+
+    if (is_socket_info_valid(conn_info->socket_info_ptr)) {
+        if (conn_info->socket_info_ptr->l7_proto != PROTO_POSTGRESQL)
+            return MSG_UNKNOWN;
+        char tag = infer_buf[0];
+        switch (tag) {
+            // req, common, can not infer msg type, return MSG_REQUEST
+            case 'Q': case 'P': case 'B': case 'F': case 'X': case 'f':
+            case 'C': case 'E': case 'S': case 'D': case 'H': case 'd':
+            case 'c':
+                return MSG_REQUEST;
+            case 'Z': case 'I': case '1': case '2': case '3': case 'K':
+            case 'T': case 'n': case 'N': case 't': case 'G': case 'W':
+            case 'R':
+                return MSG_RESPONSE;
+            default:
+                return MSG_UNKNOWN;
+        }
+    }
+
+    if (infer_pgsql_startup_message(infer_buf, count))
+        return MSG_REQUEST;
+
+    return infer_pgsql_query_message(infer_buf, buf, count);
+}
+
+/*
+ * Request command protocol for v1
+ * 0     1     2           4           6           8          10           12          14         16
+ * +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * |proto| type| cmdcode   |ver2 |   requestId           |codec|        timeout        |  classLen |
+ * +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
+ * |headerLen  | contentLen            |                             ... ...                       |
+ * +-----------+-----------+-----------+                                                           +
+ * |               className + header  + content  bytes                                            |
+ * +                                                                                               +
+ * |                               ... ...                                                         |
+ * +-----------------------------------------------------------------------------------------------+
+ *
+ * Response command protocol for v1
+ * 0     1     2     3     4           6           8          10           12          14         16
+ * +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * |proto| type| cmdcode   |ver2 |   requestId           |codec|respstatus |  classLen |headerLen  |
+ * +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
+ * | contentLen            |                  ... ...                                              |
+ * +-----------------------+                                                                       +
+ * |                         className + header  + content  bytes                                  |
+ * +                                                                                               +
+ * |                               ... ...                                                         |
+ * +-----------------------------------------------------------------------------------------------+
+ *
+ * ref: https://github.com/sofastack/sofa-bolt/blob/42e4e3d756b7655c0d4a058989c66d9eb09591fa/plugins/wireshark/bolt.lua
+ */
+static __inline enum message_type infer_sofarpc_message(const char *buf,
+                                                        size_t count,
+                                                        struct conn_info_t
+                                                        *conn_info)
+{
+    static const __u8 bolt_resp_header_len = 20;
+    static const __u8 bolt_req_header_len = 22;
+    static const __u8 bolt_ver_v1 = 0x01;
+    static const __u8 type_req = 0x01;
+    static const __u8 type_resp = 0x0;
+    static const __u16 cmd_code_req = 0x01;
+    static const __u16 cmd_code_resp = 0x02;
+    static const __u8 codec_hessian = 0;
+    static const __u8 codec_hessian2 = 1;
+    static const __u8 codec_protobuf = 11;
+    static const __u8 codec_json = 12;
+
+    if (count < 20 || !is_protocol_enabled(PROTO_SOFARPC))
+        return MSG_UNKNOWN;
+
+    const __u8 *infer_buf = (const __u8 *)buf;
+    __u8 ver = infer_buf[0];	//version for protocol
+    __u8 type = infer_buf[1];	// request/response/request oneway
+
+    if (is_socket_info_valid(conn_info->socket_info_ptr)) {
+        if (conn_info->socket_info_ptr->l7_proto != PROTO_SOFARPC)
+            return MSG_UNKNOWN;
+        goto out;
+    }
+    // code for remoting command (Heartbeat, RpcRequest, RpcResponse)
+    __u16 cmdcode = __bpf_ntohs(*(__u16 *) & infer_buf[2]);
+
+    // 0 -- "hessian", 1 -- "hessian2", 11 -- "protobuf", 12 -- "json"
+    __u8 codec = infer_buf[9];
+
+    if (!((ver == bolt_ver_v1)
+          && (type == type_req || type == type_resp)
+          && (cmdcode == cmd_code_req || cmdcode == cmd_code_resp)
+          && (codec == codec_hessian || codec == codec_hessian2
+              || codec == codec_protobuf || codec == codec_json)))
+        return MSG_UNKNOWN;
+
+    // length of request or response class name
+    // length of header
+    __u16 class_len, header_len;
+
+    // bolt_ver_v1
+    if (type == type_req) {
+        class_len = __bpf_ntohs(*(__u16 *) & infer_buf[14]);
+        header_len = __bpf_ntohs(*(__u16 *) & infer_buf[16]);
+        if ((bolt_req_header_len + class_len + header_len) > count)
+            return MSG_UNKNOWN;
+    }
+
+    if (cmdcode == cmd_code_resp) {
+        // (resp)respStatus: response status
+        __u16 resp_status = __bpf_ntohl(*(__u16 *) & infer_buf[10]);
+        if (!(resp_status >= 0 && resp_status <= 18))
+            return MSG_UNKNOWN;
+        class_len = __bpf_ntohs(*(__u16 *) & infer_buf[12]);
+        header_len = __bpf_ntohs(*(__u16 *) & infer_buf[14]);
+        //content_len = __bpf_ntohl(*(__u32 *)&infer_buf[16]);
+        if ((bolt_resp_header_len + class_len + header_len) > count)
+            return MSG_UNKNOWN;
+
+    }
+
+    out:
+    return type == type_req ? MSG_REQUEST : MSG_RESPONSE;
+}
 
 /*
 0                   15 16                     31
@@ -868,7 +868,7 @@ static __inline enum message_type infer_dns_message(const char *buf,
 //    if (!is_protocol_enabled(PROTO_DNS)) {
 //        return MSG_UNKNOWN;
 //    }
-
+bpf_printk("dns msg");
     if (is_socket_info_valid(conn_info->socket_info_ptr)) {
         if (conn_info->socket_info_ptr->l7_proto != PROTO_DNS)
             return MSG_UNKNOWN;
@@ -904,6 +904,23 @@ static __inline enum message_type infer_dns_message(const char *buf,
     bool qr = dns->qr;	// QR(Response):查询请求/响应的标志信息。查询请求时,值为 0;响应时,值为 1。
     __u8 opcode = dns->opcode;	// 操作码。其中,0 表示标准查询;1 表示反向查询;2 表示服务器状态请求。
     __u8 zero = dns->z;	// Z:保留字段,在所有的请求和应答报文中,它的值必须为 0。
+
+// 打印每个字段
+//    bpf_printk("id: %x", dns->id);
+//    bpf_printk("rd: %hhu", dns->rd);
+//    bpf_printk("tc: %hhu", dns->tc);
+//    bpf_printk("aa: %hhu", dns->aa);
+//    bpf_printk("opcode: %hhu", dns->opcode);
+//    bpf_printk("qr: %hhu", dns->qr);
+//    bpf_printk("rcode: %hhu", dns->rcode);
+//    bpf_printk("cd: %hhu", dns->cd);
+//    bpf_printk("ad: %hhu", dns->ad);
+//    bpf_printk("z: %hhu", dns->z);
+//    bpf_printk("ra: %hhu", dns->ra);
+//    bpf_printk("q_count: %hu", dns->q_count);
+//    bpf_printk("ans_count: %hu", dns->ans_count);
+//    bpf_printk("auth_count: %hu", dns->auth_count);
+//    bpf_printk("add_count: %hu", dns->add_count);
     if (zero != 0) {
         return MSG_UNKNOWN;
     }
@@ -933,6 +950,11 @@ static __inline enum message_type infer_dns_message(const char *buf,
         }
     }
 
+    if (conn_info->dns_q_type == 0x1c) {
+
+        bpf_printk("[dns] conn_info->dns_q_type %x AAAA",conn_info->dns_q_type);
+    }
+
     return (qr == 0) ? MSG_REQUEST : MSG_RESPONSE;
 }
 
@@ -1321,94 +1343,94 @@ static __inline bool kafka_data_check_len(size_t count,
     return true;
 }
 
-//static __inline enum message_type infer_kafka_message(const char *buf,
-//                                                      size_t count,
-//                                                      struct conn_info_t
-//                                                      *conn_info)
-//{
-//    if (!is_protocol_enabled(PROTO_KAFKA)) {
-//        return MSG_UNKNOWN;
-//    }
-//
-//    if (count == 4) {
-//        save_prev_data(buf, conn_info);
-//        return MSG_PRESTORE;
-//    }
-//
-//    bool is_first = true, use_prev_buf;
-//    if (!kafka_data_check_len(count, buf, conn_info, &use_prev_buf))
-//        return MSG_UNKNOWN;
-//
-//    if (is_socket_info_valid(conn_info->socket_info_ptr)) {
-//        if (conn_info->socket_info_ptr->l7_proto != PROTO_KAFKA)
-//            return MSG_UNKNOWN;
-//
-//        conn_info->need_reconfirm =
-//                conn_info->socket_info_ptr->need_reconfirm;
-//
-//        if (!conn_info->need_reconfirm) {
-//            if ((conn_info->role == ROLE_CLIENT
-//                 && conn_info->direction == T_EGRESS)
-//                || (conn_info->role == ROLE_SERVER
-//                    && conn_info->direction == T_INGRESS)) {
-//                return MSG_REQUEST;
-//            }
-//
-//            return MSG_RESPONSE;
-//        }
-//
-//        conn_info->correlation_id =
-//                conn_info->socket_info_ptr->correlation_id;
-//        conn_info->role = conn_info->socket_info_ptr->role;
-//        is_first = false;
-//    } else
-//        conn_info->need_reconfirm = true;
-//
-//    const char *msg_buf = use_prev_buf ? buf : buf + 4;
-//    enum message_type msg_type =
-//            infer_kafka_request(msg_buf, is_first, conn_info);
-//    if (msg_type == MSG_REQUEST) {
-//        // 首次需要在socket_info_map新建socket
-//        if (is_first) {
-//            return MSG_RECONFIRM;
-//        }
-//
-//        /*
-//         * socket_info_map已经存在并且需要确认(需要response的数据进一步),
-//         * 这里的request的数据直接丢弃。
-//         */
-//        return MSG_UNKNOWN;
-//    }
-//    // 推断的第一个包必须是请求包,否则直接丢弃
-//    if (is_first)
-//        return MSG_UNKNOWN;
-//
-//    // is response ?
-//    // Response Header v0 => correlation_id
-//    //  correlation_id => INT32
-//    const __s32 correlation_id = __bpf_ntohl(*(__s32 *) msg_buf);
-//    if (correlation_id < 0)
-//        return MSG_UNKNOWN;
-//
-//    if (correlation_id == conn_info->correlation_id) {
-//        // 完成确认
-//        if (is_socket_info_valid(conn_info->socket_info_ptr)) {
-//            conn_info->socket_info_ptr->need_reconfirm = false;
-//            // 角色确认
-//            if (conn_info->direction == T_EGRESS)
-//                conn_info->socket_info_ptr->role = ROLE_SERVER;
-//            else
-//                conn_info->socket_info_ptr->role = ROLE_CLIENT;
-//        }
-//    } else {
-//        // 再次确认失败直接删除socket记录。
-//        return MSG_CLEAR;
-//    }
-//
-//    // kafka长连接的形式存在,数据开始捕获从类型推断完成开始进行。
-//    // 此处数据(用于确认协议类型)丢弃不要,避免发给用户产生混乱。
-//    return MSG_UNKNOWN;
-//}
+static __inline enum message_type infer_kafka_message(const char *buf,
+                                                      size_t count,
+                                                      struct conn_info_t
+                                                      *conn_info)
+{
+    if (!is_protocol_enabled(PROTO_KAFKA)) {
+        return MSG_UNKNOWN;
+    }
+
+    if (count == 4) {
+        save_prev_data(buf, conn_info);
+        return MSG_PRESTORE;
+    }
+
+    bool is_first = true, use_prev_buf;
+    if (!kafka_data_check_len(count, buf, conn_info, &use_prev_buf))
+        return MSG_UNKNOWN;
+
+    if (is_socket_info_valid(conn_info->socket_info_ptr)) {
+        if (conn_info->socket_info_ptr->l7_proto != PROTO_KAFKA)
+            return MSG_UNKNOWN;
+
+        conn_info->need_reconfirm =
+                conn_info->socket_info_ptr->need_reconfirm;
+
+        if (!conn_info->need_reconfirm) {
+            if ((conn_info->role == ROLE_CLIENT
+                 && conn_info->direction == T_EGRESS)
+                || (conn_info->role == ROLE_SERVER
+                    && conn_info->direction == T_INGRESS)) {
+                return MSG_REQUEST;
+            }
+
+            return MSG_RESPONSE;
+        }
+
+        conn_info->correlation_id =
+                conn_info->socket_info_ptr->correlation_id;
+        conn_info->role = conn_info->socket_info_ptr->role;
+        is_first = false;
+    } else
+        conn_info->need_reconfirm = true;
+
+    const char *msg_buf = use_prev_buf ? buf : buf + 4;
+    enum message_type msg_type =
+            infer_kafka_request(msg_buf, is_first, conn_info);
+    if (msg_type == MSG_REQUEST) {
+        // 首次需要在socket_info_map新建socket
+        if (is_first) {
+            return MSG_RECONFIRM;
+        }
+
+        /*
+         * socket_info_map已经存在并且需要确认(需要response的数据进一步),
+         * 这里的request的数据直接丢弃。
+         */
+        return MSG_UNKNOWN;
+    }
+    // 推断的第一个包必须是请求包,否则直接丢弃
+    if (is_first)
+        return MSG_UNKNOWN;
+
+    // is response ?
+    // Response Header v0 => correlation_id
+    //  correlation_id => INT32
+    const __s32 correlation_id = __bpf_ntohl(*(__s32 *) msg_buf);
+    if (correlation_id < 0)
+        return MSG_UNKNOWN;
+
+    if (correlation_id == conn_info->correlation_id) {
+        // 完成确认
+        if (is_socket_info_valid(conn_info->socket_info_ptr)) {
+            conn_info->socket_info_ptr->need_reconfirm = false;
+            // 角色确认
+            if (conn_info->direction == T_EGRESS)
+                conn_info->socket_info_ptr->role = ROLE_SERVER;
+            else
+                conn_info->socket_info_ptr->role = ROLE_CLIENT;
+        }
+    } else {
+        // 再次确认失败直接删除socket记录。
+        return MSG_CLEAR;
+    }
+
+    // kafka长连接的形式存在,数据开始捕获从类型推断完成开始进行。
+    // 此处数据(用于确认协议类型)丢弃不要,避免发给用户产生混乱。
+    return MSG_UNKNOWN;
+}
 
 static __inline bool drop_msg_by_comm(void)
 {
@@ -1649,97 +1671,12 @@ infer_protocol(struct ctx_info_s *ctx,
      *     ... ...
      *   进行快速判断。
      */
-#ifdef LINUX_VER_5_2_PLUS
-    if (skip_proto != PROTO_HTTP1 && (inferred_message.type =
-#else
-    if ((inferred_message.type =
-#endif
-                 infer_http_message(infer_buf, count, conn_info)) != MSG_UNKNOWN) {
-        conn_info->infer_reliable = 1;
-        inferred_message.protocol = PROTO_HTTP1;
-#ifdef LINUX_VER_5_2_PLUS
-        } else if (skip_proto != PROTO_REDIS && (inferred_message.type =
-#else
-    } else if ((inferred_message.type =
-#endif
-                        infer_redis_message(infer_buf, count,
-                                            conn_info)) != MSG_UNKNOWN) {
-        inferred_message.protocol = PROTO_REDIS;
-#ifdef LINUX_VER_5_2_PLUS
-        } else if (skip_proto != PROTO_MQTT && (inferred_message.type =
-#else
-    } else if ((inferred_message.type =
-#endif
-                        infer_mqtt_message(infer_buf, count,
-                                           conn_info)) != MSG_UNKNOWN) {
-        inferred_message.protocol = PROTO_MQTT;
-#ifdef LINUX_VER_5_2_PLUS
-        } else if (skip_proto != PROTO_DUBBO && (inferred_message.type =
-#else
-    } else if ((inferred_message.type =
-#endif
-                        infer_dubbo_message(infer_buf, count,
-                                            conn_info)) != MSG_UNKNOWN) {
-        inferred_message.protocol = PROTO_DUBBO;
-#ifdef LINUX_VER_5_2_PLUS
-        } else if (skip_proto != PROTO_DNS && (inferred_message.type =
-#else
-    } else if ((inferred_message.type =
-#endif
-                        infer_dns_message(infer_buf, count,
+   if ((inferred_message.type = infer_dns_message(infer_buf, count,
                                           conn_info)) != MSG_UNKNOWN) {
         inferred_message.protocol = PROTO_DNS;
     }
-
     if (inferred_message.protocol != MSG_UNKNOWN)
         return inferred_message;
-
-#ifdef LINUX_VER_5_2_PLUS
-    if (skip_proto != PROTO_MYSQL && (inferred_message.type =
-#else
-    if ((inferred_message.type =
-#endif
-                 infer_mysql_message(infer_buf, count,
-                                     conn_info)) != MSG_UNKNOWN) {
-        if (inferred_message.type == MSG_PRESTORE)
-            return inferred_message;
-        inferred_message.protocol = PROTO_MYSQL;
-#ifdef LINUX_VER_5_2_PLUS
-        } else if (skip_proto != PROTO_KAFKA && (inferred_message.type =
-#else
-//    } else if ((inferred_message.type =
-#endif
-//                        infer_kafka_message(infer_buf, count,
-//                                            conn_info)) != MSG_UNKNOWN) {
-//        if (inferred_message.type == MSG_PRESTORE)
-//            return inferred_message;
-//        inferred_message.protocol = PROTO_KAFKA;
-#ifdef LINUX_VER_5_2_PLUS
-        } else if (skip_proto != PROTO_SOFARPC && (inferred_message.type =
-#else
-//    } else if ((inferred_message.type =
-#endif
-//                        infer_sofarpc_message(infer_buf, count,
-//                                              conn_info)) != MSG_UNKNOWN){
-//        inferred_message.protocol = PROTO_SOFARPC;
-#ifdef LINUX_VER_5_2_PLUS
-        } else if (skip_proto != PROTO_HTTP2 && (inferred_message.type =
-#else
-//    } else if ((inferred_message.type =
-#endif
-//                        infer_http2_message(syscall_infer_buf, syscall_infer_len,
-//                                            conn_info)) != MSG_UNKNOWN) {
-//        inferred_message.protocol = PROTO_HTTP2;
-#ifdef LINUX_VER_5_2_PLUS
-        } else if (skip_proto != PROTO_POSTGRESQL && (inferred_message.type =
-#else
-//    } else if ((inferred_message.type =
-#endif
-//                        infer_postgre_message(syscall_infer_buf, syscall_infer_len,
-//                                              conn_info)) != MSG_UNKNOWN){
-//        inferred_message.protocol = PROTO_POSTGRESQL;
-    }
-
     return inferred_message;
 }
 

+ 6 - 5
ebpftracer/ebpf/include/socket_trace.h

@@ -79,7 +79,7 @@ struct mmsghdr {
 #include "socket_trace_common.h"
 
 struct member_fields_offset {
-	__u8 ready;
+    __u32 ready;
 	__u32 task__files_offset;
 	__u32 sock__flags_offset;
 	__u32 tcp_sock__copied_seq_offset;
@@ -296,11 +296,12 @@ static __inline __u64 gen_conn_key_id(__u64 param_1, __u64 param_2)
 }
 
 //#define MAX_SYSTEM_THREADS 40960
+#define MAX_SYSTEM_THREADS 40960
 
-//struct go_interface {
-//	unsigned long long type;
-//	void *ptr;
-//};
+struct go_interface {
+	unsigned long long type;
+	void *ptr;
+};
 
 struct go_slice {
 	void *ptr;

+ 3 - 3
ebpftracer/ebpf/include/socket_trace_common.h

@@ -67,9 +67,9 @@ struct trace_conf_t {
 	__u64 socket_id;       // 会话标识
 	__u64 coroutine_trace_id;  // 同一协程的数据转发关联
 	__u64 thread_trace_id; // 同一进程/线程的数据转发关联,用于多事务流转场景
-	__u32 data_limit_max;  // Maximum number of data transfers
-	__u32 go_tracing_timeout;
-	__u32 io_event_collect_mode;
+	__u64 data_limit_max;  // Maximum number of data transfers
+	__u64 go_tracing_timeout;
+	__u64 io_event_collect_mode;
 	__u64 io_event_minimal_duration;
 };
 

+ 2 - 2
ebpftracer/ebpf/l7/gotls.c

@@ -16,14 +16,14 @@
 
 #define IS_TLS_READ_ID 0x8000000000000000
 
-struct go_interface {
+struct go_interface_tls {
     __s64 type;
     void* ptr;
 };
 
 static inline __attribute__((__always_inline__))
 int go_crypto_tls_get_fd_from_conn(struct pt_regs *ctx, __u32 *fd) {
-    struct go_interface conn;
+    struct go_interface_tls conn;
     if (bpf_probe_read(&conn, sizeof(conn), (void*)GO_PARAM1(ctx))) {
         return 1;
     };

+ 29 - 4
ebpftracer/ebpf/l7/l7.c

@@ -1,5 +1,3 @@
-__u32 filterPid = 27433;
-
 #define PROTOCOL_UNKNOWN    0
 #define PROTOCOL_HTTP	    1
 #define PROTOCOL_POSTGRES	2
@@ -73,9 +71,14 @@ struct l7_event {
     __u64 trace_id;
     __u32 trace_start;
     __u32 trace_end;
+//    __u32 test_id;
     char payload[MAX_PAYLOAD_SIZE];
 };
 
+struct test_t {
+    __u32 test_id;
+};
+
 struct {
      __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
      __type(key, int);
@@ -83,6 +86,13 @@ struct {
      __uint(max_entries, 1);
 } l7_event_heap SEC(".maps");
 
+struct {
+    __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
+    __type(key, int);
+    __type(value, struct test_t);
+    __uint(max_entries, 1);
+} test_heap SEC(".maps");
+
 struct {
     __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
     __uint(key_size, sizeof(int));
@@ -226,7 +236,7 @@ int trace_enter_write(void *ctx, __u64 fd, __u16 is_tls, char *buf, __u64 size,
 
     pid = id >> 32;
     tid =  (__u32)id;
-    if (pid != filterPid) {
+    if (load_filter_pid() != 0 && pid != load_filter_pid()) {
         return 0;
     }
     char* payload = buf;
@@ -298,6 +308,21 @@ int trace_enter_write(void *ctx, __u64 fd, __u16 is_tls, char *buf, __u64 size,
         bpf_map_delete_elem(&active_l7_requests, &k);
         bpf_perf_event_output(ctx, &l7_events, BPF_F_CURRENT_CPU, e, sizeof(*e));
         // 发送事件到用户空间 end
+        __u64 k_version = load_filter_pid();
+        cw_bpf_debug("filter_pid:%d", k_version);
+
+        struct test_t *ttt = bpf_map_lookup_elem(&test_heap, &zero);
+        if (!ttt) {
+            return 0;
+        }
+
+//        struct member_fields_offset *off = bpf_map_lookup_elem(&__members_offset, &zero);
+//        if (!off) {
+//            return 0;
+//        }
+
+//        cw_bpf_debug("off->task__files_offset:%x", off->task__files_offset);
+        cw_bpf_debug("e->test_id:%d", ttt->test_id);
         cw_bpf_debug("HTTP_END");
         return 0;
     }
@@ -410,7 +435,7 @@ static inline __attribute__((__always_inline__))
 int trace_exit_read(void *ctx, __u64 id, __u32 pid, __u16 is_tls, long int ret) {
     __u32 tid =  (__u32)id;
 
-    if (pid != filterPid) {
+    if (load_filter_pid() != 0 && pid != load_filter_pid()) {
         return 0;
     }
 

+ 255 - 255
ebpftracer/ebpf/l7/uprobe_base_bpf.c

@@ -1,269 +1,269 @@
 #define GOROUTINE(x) ((x)->r14)
-#define MAX_SYSTEM_THREADS 40960
-#define HASH_ENTRIES_MAX 40960
-
-struct go_key {
-    __u32 tgid;
-    __u64 goid;
-} __attribute__((packed));
-
-struct bpf_map_def SEC("maps") go_ancerstor_map = {
-        .type = BPF_MAP_TYPE_LRU_HASH,
-        .key_size = sizeof(struct go_key),
-        .value_size = sizeof(__u64),
-        .max_entries = HASH_ENTRIES_MAX,
-};
-
-struct bpf_map_def SEC("maps") go_rw_ts_map = {
-        .type = BPF_MAP_TYPE_LRU_HASH,
-        .key_size = sizeof(struct go_key),
-        .value_size = sizeof(__u64),
-        .max_entries = HASH_ENTRIES_MAX,
-};
-
-struct bpf_map_def SEC("maps") goroutines_map = {
-        .type = BPF_MAP_TYPE_HASH,
-        .key_size = sizeof(__u64),
-        .value_size = sizeof(__u64),
-        .max_entries = MAX_SYSTEM_THREADS,
-};
-
-// Pass data between coroutine entry and exit functions
-struct go_newproc_caller {
-    __u64 goid;
-    void *sp; // stack pointer
-} __attribute__((packed));
-
-struct bpf_map_def SEC("maps") pid_tgid_callerid_map = {
-        .type = BPF_MAP_TYPE_HASH,
-        .key_size = sizeof(__u64),
-        .value_size = sizeof(struct go_newproc_caller),
-        .max_entries = MAX_SYSTEM_THREADS,
-};
-
-
-static __inline __u64 get_current_goroutine(void)
-{
-    __u64 current_thread = bpf_get_current_pid_tgid();
-    __u64 *goid_ptr = bpf_map_lookup_elem(&goroutines_map, &current_thread);
-    if (goid_ptr) {
-        return *goid_ptr;
-    }
-
-    return 0;
-}
-
-static __inline int is_final_ancestor(__u32 tgid, __u64 goid, __u64 now,
-                                      __u64 timeout)
-{
-    struct go_key key = { .tgid = tgid, .goid = goid };
-
-    __u64 *ts = bpf_map_lookup_elem(&go_rw_ts_map, &key);
-    if (!ts) {
-        return 0;
-    }
-
-    return now < *ts + timeout;
-}
-
-
-static __inline __u64 get_rw_goid(__u64 timeout, int is_socket_io)
-{
-    __u32 tgid = (__u32)(bpf_get_current_pid_tgid() >> 32);
-    __u64 ts = bpf_ktime_get_ns();
-    __u64 goid = get_current_goroutine();
-    if (goid == 0) {
-        return 0;
-    }
-
-    __u64 ancestor = goid;
-
-    int idx = 0;
-#pragma unroll
-    for (idx = 0; idx < 6; ++idx) {
-        if (is_final_ancestor(tgid, ancestor, ts, timeout)) {
-            return ancestor;
-        }
-        struct go_key key = { .tgid = tgid, .goid = ancestor };
-        __u64 *newancestor =
-                bpf_map_lookup_elem(&go_ancerstor_map, &key);
-        if (!newancestor) {
-            break;
-        }
-        ancestor = *newancestor;
-    }
-
-//    if (!is_socket_io) {
-//        return 0;
-//    }
-
-    struct go_key key = { .tgid = tgid, .goid = goid };
-    bpf_map_update_elem(&go_rw_ts_map, &key, &ts, BPF_ANY);
-    return goid;
-}
-
-
-
-SEC("uprobe/runtime.execute")
-int runtime_execute(struct pt_regs *ctx)// ok
-{
-    __u64 pid_tgid = bpf_get_current_pid_tgid();
-    __u32 tgid = pid_tgid >> 32;
-    __u32 tid = (__u32) pid_tgid;
-
-//    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);
-
-    int offset_g_goid = 152;
-
-//    __s64 goid = 0;
-//    bpf_probe_read(&goid, sizeof(goid), g_ptr + offset_g_goid);
-
-    __s64 goroutine_id = GOROUTINE(ctx);
-
-    bpf_map_update_elem(&goroutines_map, &pid_tgid, &goroutine_id, BPF_ANY);
-    bpf_printk("[GO] [runtime.execute] thread_id:%d|goid:%d", tid, goroutine_id);
-
-    return 0;
-}
-
-SEC("uprobe/enter_runtime.newproc1")
-int enter_runtime_newproc1(struct pt_regs *ctx)
-{
-    __s64 goroutine_id = GOROUTINE(ctx);
-//    __u64 goroutine_id2 = GOROUTINE(ctx);
-
-
-    __u64 pid_tgid = bpf_get_current_pid_tgid();
-    bpf_printk("[GO] [runtime.newproc1] [enter] pid_tgid:%llu | goid:%d", pid_tgid, goroutine_id);
-//    bpf_printk("[GO] [runtime.newproc1] [enter] pid_tgid:%llu | goid:%d", pid_tgid, goroutine_id2);
-    __u32 tgid = pid_tgid >> 32;
-
-//    struct ebpf_proc_info *info =
-//            bpf_map_lookup_elem(&proc_info_map, &tgid);
-//    if (!info) {
-//        return 0;
+//#define MAX_SYSTEM_THREADS 40960
+//#define HASH_ENTRIES_MAX 40960
+//
+//struct go_key {
+//    __u32 tgid;
+//    __u64 goid;
+//} __attribute__((packed));
+//
+//struct bpf_map_def SEC("maps") go_ancerstor_map = {
+//        .type = BPF_MAP_TYPE_LRU_HASH,
+//        .key_size = sizeof(struct go_key),
+//        .value_size = sizeof(__u64),
+//        .max_entries = HASH_ENTRIES_MAX,
+//};
+//
+//struct bpf_map_def SEC("maps") go_rw_ts_map = {
+//        .type = BPF_MAP_TYPE_LRU_HASH,
+//        .key_size = sizeof(struct go_key),
+//        .value_size = sizeof(__u64),
+//        .max_entries = HASH_ENTRIES_MAX,
+//};
+//
+//struct bpf_map_def SEC("maps") goroutines_map = {
+//        .type = BPF_MAP_TYPE_HASH,
+//        .key_size = sizeof(__u64),
+//        .value_size = sizeof(__u64),
+//        .max_entries = MAX_SYSTEM_THREADS,
+//};
+//
+//// Pass data between coroutine entry and exit functions
+//struct go_newproc_caller {
+//    __u64 goid;
+//    void *sp; // stack pointer
+//} __attribute__((packed));
+//
+//struct bpf_map_def SEC("maps") pid_tgid_callerid_map = {
+//        .type = BPF_MAP_TYPE_HASH,
+//        .key_size = sizeof(__u64),
+//        .value_size = sizeof(struct go_newproc_caller),
+//        .max_entries = MAX_SYSTEM_THREADS,
+//};
+//
+//
+//static __inline __u64 get_current_goroutine(void)
+//{
+//    __u64 current_thread = bpf_get_current_pid_tgid();
+//    __u64 *goid_ptr = bpf_map_lookup_elem(&goroutines_map, &current_thread);
+//    if (goid_ptr) {
+//        return *goid_ptr;
 //    }
-
-    // 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;
+//}
+//
+//static __inline int is_final_ancestor(__u32 tgid, __u64 goid, __u64 now,
+//                                      __u64 timeout)
+//{
+//    struct go_key key = { .tgid = tgid, .goid = goid };
+//
+//    __u64 *ts = bpf_map_lookup_elem(&go_rw_ts_map, &key);
+//    if (!ts) {
 //        return 0;
 //    }
-
-    int offset_g_goid = 152;
-//    if (offset_g_goid < 0)
-//    {
+//
+//    return now < *ts + timeout;
+//}
+//
+//
+//static __inline __u64 get_rw_goid(__u64 timeout, int is_socket_io)
+//{
+//    __u32 tgid = (__u32)(bpf_get_current_pid_tgid() >> 32);
+//    __u64 ts = bpf_ktime_get_ns();
+//    __u64 goid = get_current_goroutine();
+//    if (goid == 0) {
 //        return 0;
 //    }
-
-//    void *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);
+//
+//    __u64 ancestor = goid;
+//
+//    int idx = 0;
+//#pragma unroll
+//    for (idx = 0; idx < 6; ++idx) {
+//        if (is_final_ancestor(tgid, ancestor, ts, timeout)) {
+//            return ancestor;
 //        }
-//    } 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));
+//        struct go_key key = { .tgid = tgid, .goid = ancestor };
+//        __u64 *newancestor =
+//                bpf_map_lookup_elem(&go_ancerstor_map, &key);
+//        if (!newancestor) {
+//            break;
 //        }
-//    }
-
-//    __s64 goid = 0;
-//    bpf_probe_read(&goid, sizeof(goid), g_ptr + offset_g_goid);
-//    bpf_printk("[GO] [runtime.newproc1] [enter] pid_tgid:%llu | goid:%llu", pid_tgid, goid);
-
-//    if (!goid)
-//    {
-//        bpf_printk("[GO] [runtime.newproc1] [enter] pid_tgid:%llu | goid:%llu", pid_tgid, goid);
-//        return 0;
-//    }
-
-    struct go_newproc_caller caller = {
-            .goid = goroutine_id,
-//            .sp = (void *) PT_REGS_SP(ctx),
-    };
-//    if (!caller.sp) {
-    bpf_map_update_elem(&pid_tgid_callerid_map, &pid_tgid, &caller, BPF_ANY);
-//    }
-//    bpf_printk("[GO] [runtime.newproc1] [enter] pid_tgid:%llu | goid:%llu", pid_tgid);
-    return 0;
-}
-
-//
-SEC("uprobe/exit_runtime.newproc1")
-int exit_runtime_newproc1(struct pt_regs *ctx)
-{
-    __u64 pid_tgid = bpf_get_current_pid_tgid();
-    __u32 tgid = pid_tgid >> 32;
-    __u32 tid = (__u32) pid_tgid;
-
-//    struct ebpf_proc_info *info =
-//            bpf_map_lookup_elem(&proc_info_map, &tgid);
-//    if (!info) {
-//        return 0;
+//        ancestor = *newancestor;
 //    }
 //
-//    if(info->version < GO_VERSION(1, 15, 0)){
-//        return 0;
-//    }
-
+////    if (!is_socket_io) {
+////        return 0;
+////    }
+//
+//    struct go_key key = { .tgid = tgid, .goid = goid };
+//    bpf_map_update_elem(&go_rw_ts_map, &key, &ts, BPF_ANY);
+//    return goid;
+//}
+//
+//
+//
+//SEC("uprobe/runtime.execute")
+//int runtime_execute(struct pt_regs *ctx)// ok
+//{
+//    __u64 pid_tgid = bpf_get_current_pid_tgid();
+//    __u32 tgid = pid_tgid >> 32;
+//    __u32 tid = (__u32) pid_tgid;
+//
+////    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);
+//
 //    int offset_g_goid = 152;
-//    if (offset_g_goid < 0)
-//    {
-//        return 0;
-//    }
-
-    struct go_newproc_caller *caller =
-            bpf_map_lookup_elem(&pid_tgid_callerid_map, &pid_tgid);
-    if (!caller)
-    {
-        bpf_printk("[GO] [runtime.newproc1] [exit] has no caller thread_id:%d", tid);
-
-        return 0;
-    }
-
-//    void *g_ptr;
-//    g_ptr = (void *) PT_GO_REGS_PARM1(ctx);
-//    if (is_register_based_call(info)) {
-//    } 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);
-//        }
-//    }
-
-    __s64 goid = GOROUTINE(ctx);
-//    bpf_probe_read(&goid, sizeof(goid), g_ptr + offset_g_goid);
-//    if (!goid)
+//
+////    __s64 goid = 0;
+////    bpf_probe_read(&goid, sizeof(goid), g_ptr + offset_g_goid);
+//
+//    __s64 goroutine_id = GOROUTINE(ctx);
+//
+//    bpf_map_update_elem(&goroutines_map, &pid_tgid, &goroutine_id, BPF_ANY);
+//    bpf_printk("[GO] [runtime.execute] thread_id:%d|goid:%d", tid, goroutine_id);
+//
+//    return 0;
+//}
+//
+//SEC("uprobe/enter_runtime.newproc1")
+//int enter_runtime_newproc1(struct pt_regs *ctx)
+//{
+//    __s64 goroutine_id = GOROUTINE(ctx);
+////    __u64 goroutine_id2 = GOROUTINE(ctx);
+//
+//
+//    __u64 pid_tgid = bpf_get_current_pid_tgid();
+//    bpf_printk("[GO] [runtime.newproc1] [enter] pid_tgid:%llu | goid:%d", pid_tgid, goroutine_id);
+////    bpf_printk("[GO] [runtime.newproc1] [enter] pid_tgid:%llu | goid:%d", pid_tgid, goroutine_id2);
+//    __u32 tgid = pid_tgid >> 32;
+//
+////    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 = 152;
+////    if (offset_g_goid < 0)
+////    {
+////        return 0;
+////    }
+//
+////    void *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);
+////    bpf_printk("[GO] [runtime.newproc1] [enter] pid_tgid:%llu | goid:%llu", pid_tgid, goid);
+//
+////    if (!goid)
+////    {
+////        bpf_printk("[GO] [runtime.newproc1] [enter] pid_tgid:%llu | goid:%llu", pid_tgid, goid);
+////        return 0;
+////    }
+//
+//    struct go_newproc_caller caller = {
+//            .goid = goroutine_id,
+////            .sp = (void *) PT_REGS_SP(ctx),
+//    };
+////    if (!caller.sp) {
+//    bpf_map_update_elem(&pid_tgid_callerid_map, &pid_tgid, &caller, BPF_ANY);
+////    }
+////    bpf_printk("[GO] [runtime.newproc1] [enter] pid_tgid:%llu | goid:%llu", pid_tgid);
+//    return 0;
+//}
+//
+////
+//SEC("uprobe/exit_runtime.newproc1")
+//int exit_runtime_newproc1(struct pt_regs *ctx)
+//{
+//    __u64 pid_tgid = bpf_get_current_pid_tgid();
+//    __u32 tgid = pid_tgid >> 32;
+//    __u32 tid = (__u32) pid_tgid;
+//
+////    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 = 152;
+////    if (offset_g_goid < 0)
+////    {
+////        return 0;
+////    }
+//
+//    struct go_newproc_caller *caller =
+//            bpf_map_lookup_elem(&pid_tgid_callerid_map, &pid_tgid);
+//    if (!caller)
 //    {
-//        bpf_map_delete_elem(&pid_tgid_callerid_map, &pid_tgid);
+//        bpf_printk("[GO] [runtime.newproc1] [exit] has no caller thread_id:%d", tid);
+//
 //        return 0;
 //    }
-
-    struct go_key key = {.tgid = tgid, .goid = goid};
-    __u64 callergoid = caller->goid;
-    bpf_map_update_elem(&go_ancerstor_map, &key, &callergoid, BPF_ANY);
-
-    bpf_map_delete_elem(&pid_tgid_callerid_map, &pid_tgid);
-    bpf_printk("[GO] [runtime.newproc1] [exit] thread_id:%d|current_goid:%d|caller_goid:%d\n", tid, goid, callergoid);
-
-    return 0;
-}
+//
+////    void *g_ptr;
+////    g_ptr = (void *) PT_GO_REGS_PARM1(ctx);
+////    if (is_register_based_call(info)) {
+////    } 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);
+////        }
+////    }
+//
+//    __s64 goid = GOROUTINE(ctx);
+////    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;
+////    }
+//
+//    struct go_key key = {.tgid = tgid, .goid = goid};
+//    __u64 callergoid = caller->goid;
+//    bpf_map_update_elem(&go_ancerstor_map, &key, &callergoid, BPF_ANY);
+//
+//    bpf_map_delete_elem(&pid_tgid_callerid_map, &pid_tgid);
+//    bpf_printk("[GO] [runtime.newproc1] [exit] thread_id:%d|current_goid:%d|caller_goid:%d\n", tid, goid, callergoid);
+//
+//    return 0;
+//}

+ 14 - 5
ebpftracer/ebpf/socket_trace.c

@@ -307,7 +307,7 @@ static __inline int infer_iovecs_copy(struct infer_data_s *infer_buf,
 	return bytes_copy;
 }
 
-//#include "uprobe_base_bpf.c"
+#include "uprobe_base_bpf.c"
 #include "include/protocol_inference.h"
 #define EVENT_BURST_NUM            16
 #define CONN_PERSIST_TIME_MAX_NS   100000000000ULL
@@ -766,7 +766,7 @@ static __inline int infer_offset_retry(int fd)
 		__u64 *adapt_uid = adapt_kern_uid_map__lookup(&k0);
 		if (!adapt_uid)
 			return OFFSET_NO_READY;
-
+        debug("adapt_uid:%llu",adapt_uid);
 		// Only a preset uid can be adapted to the kernel
 		if (*adapt_uid != bpf_get_current_pid_tgid())
 			return OFFSET_NO_READY;
@@ -1263,6 +1263,11 @@ static __inline int process_data(struct pt_regs *ctx, __u64 id,
 		return -1;
 
 	// TODO : 此处可以根据配置对进程号进行过滤
+    __u32 pid = id >> 32;
+
+    if (load_filter_pid() != 0 && pid != load_filter_pid()) {
+        return -1;
+    }
 
 	__u32 k0 = 0;
 	struct member_fields_offset *offset = members_offset__lookup(&k0);
@@ -1295,6 +1300,7 @@ static __inline int process_data(struct pt_regs *ctx, __u64 id,
 	if (bp) {
 		if (is_set_bitmap(bp->bitmap, conn_info->tuple.dport) ||
 		    is_set_bitmap(bp->bitmap, conn_info->tuple.num)) {
+            debug("data_submit_dircet = true");
 			data_submit_dircet = true;
 		}
 	}
@@ -1334,6 +1340,7 @@ static __inline void process_syscall_data(struct pt_regs* ctx, __u64 id,
 	};
 
 	if (!process_data(ctx, id, direction, args, bytes_count, &extra)) {
+        bpf_printk("process_syscall_data");
 		bpf_tail_call(ctx, &NAME(progs_jmp_tp_map),
 			      PROG_DATA_SUBMIT_TP_IDX);
 	} else {
@@ -1770,7 +1777,6 @@ TPPROG(sys_enter_close) (struct syscall_comm_enter_ctx *ctx) {
 		return 0;
 
 	CHECK_OFFSET_READY(fd);
-
 	__u64 sock_addr = (__u64)get_socket_from_fd(fd, offset);
 	if (sock_addr) {
 		__u64 conn_key = gen_conn_key_id(bpf_get_current_pid_tgid() >> 32, (__u64)fd);
@@ -1861,7 +1867,7 @@ static __inline int output_data_common(void *ctx) {
 	int max_size = 0;
 	__u32 k0 = 0;
 	char *buffer = NULL;
-
+    bpf_printk("output_data_common");
 	struct __socket_data_buffer *v_buff = bpf_map_lookup_elem(&NAME(data_buf), &k0);
 	if (!v_buff)
 		goto clear_args_map_2;
@@ -2019,7 +2025,9 @@ static __inline int data_submit(void *ctx)
 }
 
 PROGTP(data_submit) (void *ctx)
-{	int ret;
+{
+    bpf_printk("TP(data_submit)");
+    int ret;
 	ret = data_submit(ctx);
 	if (ret == SUBMIT_OK) {
 		bpf_tail_call(ctx, &NAME(progs_jmp_tp_map),
@@ -2036,6 +2044,7 @@ PROGTP(data_submit) (void *ctx)
 
 PROGKP(data_submit) (void *ctx)
 {
+    bpf_printk("KP(data_submit)");
 	int ret;
 	ret = data_submit(ctx);
 	if (ret == SUBMIT_OK) {

+ 576 - 0
ebpftracer/ebpf/uprobe_base_bpf.c

@@ -0,0 +1,576 @@
+/*
+ * Copyright (c) 2022 Yunshan Networks
+ *
+ * Licensed 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.
+ */
+
+#define HASH_ENTRIES_MAX 40960
+
+struct http2_tcp_seq_key {
+	int tgid;
+	int fd;
+	__u32 tcp_seq_end;
+};
+
+/*
+ * In uprobe_go_tls_read_exit()
+ * Save the TCP sequence number before the syscall(read())
+ * 
+ * In uprobe http2 read() (after syscall read()), lookup TCP sequence number recorded previously on the map.
+ * e.g.: In uprobe_go_http2serverConn_processHeaders(), get TCP sequence before syscall read(). 
+ * 
+ * Note:  Use for after uprobe read() only.
+ */
+struct bpf_map_def SEC("maps") http2_tcp_seq_map = {
+	.type = BPF_MAP_TYPE_LRU_HASH,
+	.key_size = sizeof(struct http2_tcp_seq_key),
+	.value_size = sizeof(__u32),
+	.max_entries = HASH_ENTRIES_MAX,
+};
+
+/*
+ * The binary executable file offset of the GO process
+ * key: pid
+ * value: struct ebpf_proc_info
+ */
+struct bpf_map_def SEC("maps") proc_info_map = {
+	.type = BPF_MAP_TYPE_HASH,
+	.key_size = sizeof(int),
+	.value_size = sizeof(struct ebpf_proc_info),
+	.max_entries = HASH_ENTRIES_MAX,
+};
+
+// Process ID and coroutine ID, marking the coroutine in the system
+struct go_key {
+	__u32 tgid;
+	__u64 goid;
+} __attribute__((packed));
+
+// The mapping of coroutines to ancestors, the map is updated when a new
+// coroutine is created
+// key : current gorouting (struct go_key)
+// value : ancerstor goid
+struct bpf_map_def SEC("maps") go_ancerstor_map = {
+	.type = BPF_MAP_TYPE_LRU_HASH,
+	.key_size = sizeof(struct go_key),
+	.value_size = sizeof(__u64),
+	.max_entries = HASH_ENTRIES_MAX,
+};
+
+// Used to determine the timeout, as a termination condition for finding
+// ancestors.
+// key : current gorouting (struct go_key)
+// value: timestamp when the data was inserted into the map
+struct bpf_map_def SEC("maps") go_rw_ts_map = {
+	.type = BPF_MAP_TYPE_LRU_HASH,
+	.key_size = sizeof(struct go_key),
+	.value_size = sizeof(__u64),
+	.max_entries = HASH_ENTRIES_MAX,
+};
+
+// Pass data between coroutine entry and exit functions
+struct go_newproc_caller {
+	__u64 goid;
+	void *sp; // stack pointer
+} __attribute__((packed));
+
+struct bpf_map_def SEC("maps") pid_tgid_callerid_map = {
+	.type = BPF_MAP_TYPE_HASH,
+	.key_size = sizeof(__u64),
+	.value_size = sizeof(struct go_newproc_caller),
+	.max_entries = HASH_ENTRIES_MAX,
+};
+
+/*
+ * Goroutines Map
+ * key: {tgid, pid}
+ * value: goroutine ID
+ */
+struct bpf_map_def SEC("maps") goroutines_map = {
+	.type = BPF_MAP_TYPE_HASH,
+	.key_size = sizeof(__u64),
+	.value_size = sizeof(__u64),
+	.max_entries = MAX_SYSTEM_THREADS,
+};
+
+// The first 16 bytes are fixed headers,
+// and the total reported buffer does not exceed 1k
+#define HTTP2_BUFFER_INFO_SIZE (CAP_DATA_SIZE - 16)
+// Make the eBPF validator happy
+#define HTTP2_BUFFER_UESLESS (CAP_DATA_SIZE)
+
+struct __http2_buffer {
+	__u32 fd;
+	__u32 stream_id;
+	__u32 header_len;
+	__u32 value_len;
+	char info[HTTP2_BUFFER_INFO_SIZE + HTTP2_BUFFER_UESLESS];
+};
+
+#define SOCKET_DATA_HEADER offsetof(typeof(struct __socket_data), data)
+
+struct __http2_stack {
+	union {
+		union {
+			char __raw[sizeof(struct __socket_data) + 8];
+			struct {
+				__u32 __unused_events_num;
+				__u32 __unused_len;
+				char __unused_header[SOCKET_DATA_HEADER];
+				struct __http2_buffer http2_buffer;
+			} __attribute__((packed));
+		};
+		struct {
+			__u32 events_num;
+			__u32 len;
+			struct __socket_data send_buffer;
+		} __attribute__((packed));
+	};
+	bool tls;
+} __attribute__((packed));
+
+MAP_PERARRAY(http2_stack, __u32, struct __http2_stack, 1)
+
+static __inline struct __http2_stack *get_http2_stack()
+{
+	int k0 = 0;
+	return bpf_map_lookup_elem(&NAME(http2_stack), &k0);
+}
+
+static __inline struct __http2_buffer *get_http2_buffer()
+{
+	struct __http2_stack *stack = get_http2_stack();
+	return stack ? (&(stack->http2_buffer)) : NULL;
+}
+
+static __inline struct __socket_data *get_http2_send_buffer()
+{
+	struct __http2_stack *stack = get_http2_stack();
+	return stack ? (&(stack->send_buffer)) : NULL;
+}
+
+static __inline void update_http2_tls(bool tls)
+{
+	struct __http2_stack *stack = get_http2_stack();
+	if (stack)
+		stack->tls = tls;
+}
+
+static __inline bool is_http2_tls()
+{
+	struct __http2_stack *stack = get_http2_stack();
+	if (stack)
+		return stack->tls;
+	return false;
+}
+
+// The function address is used to set the hook point. itab is used for http2
+// to obtain fd. After directly parsing the Go ELF file, the address of the
+// function must be obtained, but the itab may not be obtained.
+// 函数地址用于设置 hook 点. itab 用于 http2 获取 fd. 在直接解析 Go ELF 文件后,
+// 一定能获取到函数的地址,但是不一定能获取 itab.
+static __inline bool skip_http2_kprobe(void)
+{
+	__u64 id;
+	pid_t pid;
+
+	id = bpf_get_current_pid_tgid();
+	pid = id >> 32;
+	struct ebpf_proc_info *info;
+	info = bpf_map_lookup_elem(&proc_info_map, &pid);
+	if (!info) {
+		return false;
+	}
+	// must have net_TCPConn_itab
+	if (!info->net_TCPConn_itab) {
+		return false;
+	}
+	// HTTP2
+	if (info->crypto_tls_Conn_itab) {
+		return true;
+	}
+	// gRPC
+	if (info->credentials_syscallConn_itab) {
+		return true;
+	}
+	return false;
+}
+
+static __inline __u64 get_current_goroutine(void)
+{
+	__u64 current_thread = bpf_get_current_pid_tgid();
+	__u64 *goid_ptr = bpf_map_lookup_elem(&goroutines_map, &current_thread);
+	if (goid_ptr) {
+		return *goid_ptr;
+	}
+
+	return 0;
+}
+
+static __inline bool is_final_ancestor(__u32 tgid, __u64 goid, __u64 now,
+				       __u64 timeout)
+{
+	struct go_key key = { .tgid = tgid, .goid = goid };
+
+	__u64 *ts = bpf_map_lookup_elem(&go_rw_ts_map, &key);
+	if (!ts) {
+		return false;
+	}
+
+	return now < *ts + timeout;
+}
+
+// Try to find an ancestor coroutine that can represent this request.
+// The ancestor coroutine needs to meet two conditions:
+//  1. There have been socket read or write operations in the recent period of time
+//  2. All of its ancestor coroutines do not satisfy condition 1
+// If no such coroutine exists, mark itself as a coroutine that can represent the request and return.
+static __inline __u64 get_rw_goid(__u64 timeout, bool is_socket_io)
+{
+	__u32 tgid = (__u32)(bpf_get_current_pid_tgid() >> 32);
+	__u64 ts = bpf_ktime_get_ns();
+	__u64 goid = get_current_goroutine();
+	if (goid == 0) {
+		return 0;
+	}
+
+	__u64 ancestor = goid;
+
+	int idx = 0;
+#pragma unroll
+	for (idx = 0; idx < 6; ++idx) {
+		if (is_final_ancestor(tgid, ancestor, ts, timeout)) {
+			return ancestor;
+		}
+		struct go_key key = { .tgid = tgid, .goid = ancestor };
+		__u64 *newancestor =
+			bpf_map_lookup_elem(&go_ancerstor_map, &key);
+		if (!newancestor) {
+			break;
+		}
+		ancestor = *newancestor;
+	}
+
+	if (!is_socket_io) {
+		return 0;
+	}
+
+	struct go_key key = { .tgid = tgid, .goid = goid };
+	bpf_map_update_elem(&go_rw_ts_map, &key, &ts, BPF_ANY);
+	return goid;
+}
+
+static __inline bool is_current_go_process(void)
+{
+	__u32 tgid = (__u32)(bpf_get_current_pid_tgid() >> 32);
+	struct ebpf_proc_info *info =
+		bpf_map_lookup_elem(&proc_info_map, &tgid);
+	if (info && info->version) {
+		return true;
+	} else {
+		return false;
+	}
+}
+
+static __inline bool is_tcp_conn_interface(void *conn,
+					   struct ebpf_proc_info *info)
+{
+	struct go_interface i;
+	bpf_probe_read(&i, sizeof(i), conn);
+	return info ? i.type == info->net_TCPConn_itab : false;
+}
+
+static __inline int get_fd_from_tcp_conn_interface(void *conn,
+						   struct ebpf_proc_info *info)
+{
+	if (!is_tcp_conn_interface(conn, info)) {
+		return -1;
+	}
+
+	int offset_fd_sysfd = info->offsets[OFFSET_IDX_SYSFD_POLL_FD];
+	if (offset_fd_sysfd < 0)
+		return -1;
+
+	struct go_interface i = {};
+	void *ptr;
+	int fd;
+
+	bpf_probe_read(&i, sizeof(i), conn);
+	bpf_probe_read(&ptr, sizeof(ptr), i.ptr);
+	bpf_probe_read(&fd, sizeof(fd), ptr + offset_fd_sysfd);
+	return fd;
+}
+
+static __inline int get_fd_from_tls_conn_struct(void *conn,
+						struct ebpf_proc_info *info)
+{
+	int offset_conn_conn = info->offsets[OFFSET_IDX_CONN_TLS_CONN];
+	if (offset_conn_conn < 0)
+		return -1;
+
+	return get_fd_from_tcp_conn_interface(conn + offset_conn_conn, info);
+}
+
+static __inline bool is_tls_conn_interface(void *conn,
+					   struct ebpf_proc_info *info)
+{
+	struct go_interface i;
+	bpf_probe_read(&i, sizeof(i), conn);
+	return info ? i.type == info->crypto_tls_Conn_itab : false;
+}
+
+static __inline int get_fd_from_tls_conn_interface(void *conn,
+						   struct ebpf_proc_info *info)
+{
+	if (!is_tls_conn_interface(conn, info)) {
+		return -1;
+	}
+	struct go_interface i = {};
+
+	bpf_probe_read(&i, sizeof(i), conn);
+	return get_fd_from_tls_conn_struct(i.ptr, info);
+}
+
+static __inline int
+get_fd_from_tcp_or_tls_conn_interface(void *conn, struct ebpf_proc_info *info)
+{
+	int fd;
+	fd = get_fd_from_tls_conn_interface(conn, info);
+	if (fd > 0) {
+		update_http2_tls(true);
+		return fd;
+	}
+	fd = get_fd_from_tcp_conn_interface(conn, info);
+	if (fd > 0) {
+		return fd;
+	}
+	return -1;
+}
+
+// Go implements a new way of passing function arguments and results using 
+// registers instead of the stack. We need the go version and the computer
+// architecture to determine the parameter locations
+static __inline bool is_register_based_call(struct ebpf_proc_info *info)
+{
+#if defined(__x86_64__)
+	// https://go.dev/doc/go1.17
+	return info->version >= GO_VERSION(1, 17, 0);
+#elif defined(__aarch64__)
+	// https://groups.google.com/g/golang-checkins/c/SO9OmZYkOXU
+	return info->version >= GO_VERSION(1, 18, 0);
+#else
+_Pragma("error \"Must specify a BPF target arch\"");
+#endif
+}
+
+//SEC("uprobe/runtime.execute")
+//int runtime_execute(struct pt_regs *ctx)
+//{
+//	__u64 pid_tgid = bpf_get_current_pid_tgid();
+//	__u32 tgid = pid_tgid >> 32;
+//
+//	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;
+//
+//	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);
+//	bpf_map_update_elem(&goroutines_map, &pid_tgid, &goid, BPF_ANY);
+//
+//	return 0;
+//}
+
+// This function creates a new go coroutine, and the parent and child
+// coroutine numbers are in the parameters and return values ​​respectively.
+// Pass the function parameters through pid_tgid_callerid_map
+//
+// go 1.15 ~ 1.17: func newproc1(fn *funcval, argp unsafe.Pointer, narg int32, callergp *g, callerpc uintptr) *g
+// go1.18+ :func newproc1(fn *funcval, callergp *g, callerpc uintptr) *g
+//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;
+//
+//	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;
+//	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;
+//	}
+//
+//	struct go_newproc_caller caller = {
+//		.goid = goid,
+//		.sp = (void *)PT_REGS_SP(ctx),
+//	};
+//	bpf_map_update_elem(&pid_tgid_callerid_map, &pid_tgid, &caller,
+//			    BPF_ANY);
+//	return 0;
+//}
+//
+//// The mapping relationship between parent and child coroutines is stored in go_ancerstor_map
+////
+//// go 1.15 ~ 1.17: func newproc1(fn *funcval, argp unsafe.Pointer, narg int32, callergp *g, callerpc uintptr) *g
+//// go1.18+ :func newproc1(fn *funcval, callergp *g, callerpc uintptr) *g
+//SEC("uprobe/exit_runtime.newproc1")
+//int exit_runtime_newproc1(struct pt_regs *ctx)
+//{
+//	__u64 pid_tgid = bpf_get_current_pid_tgid();
+//	__u32 tgid = pid_tgid >> 32;
+//
+//	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);
+//	if (!caller) {
+//		return 0;
+//	}
+//
+//	void *g_ptr;
+//	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);
+//		}
+//	}
+//
+//	__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;
+//	}
+//
+//	struct go_key key = { .tgid = tgid, .goid = 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);
+//	return 0;
+//}
+//
+//// /sys/kernel/debug/tracing/events/sched/sched_process_exit/format
+//SEC("tracepoint/sched/sched_process_exit")
+//int bpf_func_sched_process_exit(struct sched_comm_exit_ctx *ctx)
+//{
+//	pid_t pid, tid;
+//	__u64 id;
+//
+//	id = bpf_get_current_pid_tgid();
+//	pid = id >> 32;
+//	tid = (__u32)id;
+//
+//	// If is a process, clear proc_info_map element and submit event.
+//	if (pid == tid) {
+//		bpf_map_delete_elem(&proc_info_map, &pid);
+//		struct process_event_t data;
+//		data.pid = pid;
+//		data.meta.event_type = EVENT_TYPE_PROC_EXIT;
+//		bpf_get_current_comm(data.name, sizeof(data.name));
+//		int ret = bpf_perf_event_output(ctx, &NAME(socket_data),
+//						BPF_F_CURRENT_CPU, &data,
+//						sizeof(data));
+//
+//		if (ret) {
+//			bpf_debug
+//			    ("bpf_func_sched_process_exit event output failed: %d\n",
+//			     ret);
+//		}
+//	}
+//
+//	bpf_map_delete_elem(&goroutines_map, &id);
+//	return 0;
+//}
+//
+//// /sys/kernel/debug/tracing/events/sched/sched_process_fork/format
+//SEC("tracepoint/sched/sched_process_fork")
+//int bpf_func_sched_process_fork(struct sched_comm_fork_ctx *ctx)
+//{
+//	struct process_event_t data;
+//
+//	data.meta.event_type = EVENT_TYPE_PROC_EXEC;
+//	data.pid = ctx->child_pid;
+//	bpf_get_current_comm(data.name, sizeof(data.name));
+//	int ret = bpf_perf_event_output(ctx, &NAME(socket_data),
+//					BPF_F_CURRENT_CPU, &data, sizeof(data));
+//
+//	if (ret) {
+//		bpf_debug(
+//			"bpf_func_sys_exit_execve event output() failed: %d\n",
+//			ret);
+//	}
+//	return 0;
+//}

+ 6 - 0
ebpftracer/ebpf/vmlinux.h

@@ -11,6 +11,12 @@ struct pt_regs {
 	long unsigned int bx;
     long unsigned  rax;
     long unsigned  rbx;
+
+    long unsigned rcx;
+    long unsigned rdx;
+    long unsigned rsi;
+    long unsigned rdi;
+
 	long unsigned int r11;
 	long unsigned int r10;
 	long unsigned int r9;

+ 27 - 11
ebpftracer/tracer.go

@@ -5,22 +5,22 @@ import (
 	"encoding/binary"
 	"errors"
 	"fmt"
-	"os"
-	"runtime"
-	"strconv"
-	"strings"
-	"time"
-
 	"github.com/cilium/ebpf"
 	"github.com/cilium/ebpf/link"
 	"github.com/cilium/ebpf/perf"
 	"github.com/coroot/coroot-node-agent/common"
 	"github.com/coroot/coroot-node-agent/ebpftracer/l7"
+	"github.com/coroot/coroot-node-agent/ebpftracer/tracer"
 	"github.com/coroot/coroot-node-agent/proc"
 	"golang.org/x/mod/semver"
 	"golang.org/x/sys/unix"
 	"inet.af/netaddr"
 	"k8s.io/klog/v2"
+	"os"
+	"runtime"
+	"strconv"
+	"strings"
+	"time"
 )
 
 const MaxPayloadSize = 1024
@@ -180,9 +180,15 @@ func (t *Tracer) ebpf(ch chan<- Event) error {
 		return fmt.Errorf("failed to load collection spec: %w", err)
 	}
 	_ = unix.Setrlimit(unix.RLIMIT_MEMLOCK, &unix.Rlimit{Cur: unix.RLIM_INFINITY, Max: unix.RLIM_INFINITY})
-	c, err := ebpf.NewCollectionWithOptions(collectionSpec, ebpf.CollectionOptions{
-		//Programs: ebpf.ProgramOptions{LogLevel: 2, LogSize: 20 * 1024 * 1024},
-	})
+	tracer.PidFilter(collectionSpec)
+	opts := &ebpf.CollectionOptions{MapReplacements: make(map[string]*ebpf.Map)}
+	//for _, spec := range collectionSpec.Maps {
+	//	fmt.Println("s:", spec.Name)
+	//}
+	//os.Exit(1)
+	tracer.MapInit(collectionSpec, opts)
+
+	c, err := ebpf.NewCollectionWithOptions(collectionSpec, *opts)
 	if err != nil {
 		var verr *ebpf.VerifierError
 		if errors.As(err, &verr) {
@@ -190,6 +196,8 @@ func (t *Tracer) ebpf(ch chan<- Event) error {
 		}
 		return fmt.Errorf("failed to load collection: %w", err)
 	}
+	tracer.Offset()
+
 	t.collection = c
 
 	perfMaps := []perfMap{
@@ -199,12 +207,16 @@ func (t *Tracer) ebpf(ch chan<- Event) error {
 		{name: "tcp_retransmit_events", typ: perfMapTypeTCPEvents, perCPUBufferSizePages: 4},
 		{name: "file_events", typ: perfMapTypeFileEvents, perCPUBufferSizePages: 4},
 	}
-
+	fmt.Println(len(collectionSpec.Programs))
+	fmt.Println(len(c.Programs))
+	tracer.MapInsert(c)
+	//os.Exit(1)
 	if !t.disableL7Tracing {
 		perfMaps = append(perfMaps, perfMap{name: "l7_events", typ: perfMapTypeL7Events, perCPUBufferSizePages: 32})
 	}
-
+	fmt.Println("perfMaps start --")
 	for _, pm := range perfMaps {
+		fmt.Println(pm.name)
 		r, err := perf.NewReader(t.collection.Maps[pm.name], pm.perCPUBufferSizePages*os.Getpagesize())
 		if err != nil {
 			t.Close()
@@ -214,6 +226,7 @@ func (t *Tracer) ebpf(ch chan<- Event) error {
 		// event监听
 		go runEventsReader(pm.name, r, ch, pm.typ)
 	}
+	fmt.Println("perfMaps end --")
 
 	for _, programSpec := range collectionSpec.Programs {
 		program := t.collection.Programs[programSpec.Name]
@@ -231,6 +244,9 @@ func (t *Tracer) ebpf(ch chan<- Event) error {
 		var l link.Link
 		switch programSpec.Type {
 		case ebpf.TracePoint:
+			if strings.Contains(programSpec.SectionName, "prog") {
+				continue
+			}
 			parts := strings.SplitN(programSpec.AttachTo, "/", 2)
 			l, err = link.Tracepoint(parts[0], parts[1], program, nil)
 		case ebpf.Kprobe:

+ 137 - 0
ebpftracer/tracer/btf_vmlinux.go

@@ -0,0 +1,137 @@
+package tracer
+
+import (
+	"encoding/binary"
+	"fmt"
+	"github.com/cilium/ebpf"
+	"github.com/cilium/ebpf/btf"
+	"runtime"
+)
+
+func kernel_struct_field_offset(btfSpec *btf.Spec, member string, field string) int32 {
+	typ, err := btfSpec.AnyTypeByName(member)
+	if err != nil {
+		return ETR_NOTSUPP
+	}
+	return kernel_struct_field_offset_helper(btfSpec, typ, field)
+}
+
+func kernel_struct_field_offset_helper(btfSpec *btf.Spec, typ btf.Type, field string) int32 {
+	//var offset btf.Bits
+	switch typ.(type) {
+	case *btf.Struct, *btf.Union:
+		var membersT []btf.Member
+		switch t := typ.(type) {
+		case *btf.Struct:
+			membersT = t.Members
+		case *btf.Union:
+			membersT = t.Members
+		}
+		for _, member := range membersT {
+			if member.Name == field {
+				//fmt.Printf("Struct:%s,0x%x\n", member.Name, member.Offset.Bytes())
+				return int32(member.Offset.Bytes())
+			}
+			if member.Name == "" {
+				//fmt.Printf("下钻:%s,0x%x\n", member.Type, member.Offset/8)
+				retval := kernel_struct_field_offset_helper(btfSpec, member.Type, field)
+				if retval >= 0 {
+					return int32(member.Offset.Bytes()) + retval
+				}
+			}
+		}
+	}
+	return ETR_NOTEXIST
+}
+
+func bpf_table_pre_set_value(collectionSpec *ebpf.CollectionSpec, opts *ebpf.CollectionOptions, mapName string, data any) int {
+	m, ok := collectionSpec.Maps[mapName]
+	if ok {
+		newMap, err := ebpf.NewMap(&ebpf.MapSpec{
+			Type:       m.Type,
+			KeySize:    m.KeySize,
+			ValueSize:  m.ValueSize,
+			MaxEntries: m.MaxEntries,
+		})
+		if err != nil {
+			return ETR_UPDATE_MAP_FAILD
+		}
+
+		//// Convert test_t to slice
+		//numCPU := runtime.NumCPU()
+		//off := make([]interface{}, numCPU)
+		//for i := range off {
+		//	off[i] = data
+		//}
+
+		key := make([]byte, 4)                // Assuming int key size is 4 bytes
+		binary.LittleEndian.PutUint32(key, 0) // Assuming the key is an integer
+		if err = newMap.Update(key, data, ebpf.UpdateAny); err != nil {
+			return ETR_UPDATE_MAP_FAILD
+		}
+		opts.MapReplacements[mapName] = newMap
+		//opts.MapReplacements = map[string]*ebpf.Map{
+		//	mapName: newMap,
+		//}
+	} else {
+		return ETR_UPDATE_MAP_FAILD
+	}
+	return ETR_OK
+
+}
+
+func bpf_table_set_value(collection *ebpf.Collection, mapName string, key uint32, data any) int {
+	m, ok := collection.Maps[mapName]
+	//for s, m2 := range collection.Maps {
+	//	fmt.Println(s, m2.String())
+	//}
+	//fmt.Println("bpf_table_set_value", m, mapName, data)
+	if ok {
+		k := make([]byte, 4)                  // Assuming int k size is 4 bytes
+		binary.LittleEndian.PutUint32(k, key) // Assuming the key is an integer
+		if err := m.Update(k, data, ebpf.UpdateAny); err != nil {
+			return ETR_UPDATE_MAP_FAILD
+		}
+	} else {
+		return ETR_UPDATE_MAP_FAILD
+	}
+	return ETR_OK
+}
+
+func test(collectionSpec *ebpf.CollectionSpec, opts *ebpf.CollectionOptions) {
+	fmt.Println("collectionSpec.Maps start --")
+	var newMap *ebpf.Map
+	var err error
+	m, ok := collectionSpec.Maps["test_heap"]
+	if ok {
+		newMap, err = ebpf.NewMap(&ebpf.MapSpec{
+			Type:       m.Type,       // 设置 Map 的类型
+			KeySize:    m.KeySize,    // 设置 Key 的大小
+			ValueSize:  m.ValueSize,  // 设置 Value 的大小
+			MaxEntries: m.MaxEntries, // 设置最大条目数
+		})
+		if err != nil {
+			fmt.Println("Failed to create map:", err)
+		}
+		data := &testStruct{
+			test_id: 123123123,
+		}
+		// Convert test_t to slice
+		numCPU := runtime.NumCPU()
+		value := make([]testStruct, numCPU)
+		for i := range value {
+			value[i] = *data
+		}
+
+		key := make([]byte, 4)                // Assuming int key size is 4 bytes
+		binary.LittleEndian.PutUint32(key, 0) // Assuming the key is an integer
+		if err := newMap.Update(key, value, 0); err != nil {
+			panic(err)
+		}
+
+		opts.MapReplacements["test_heap"] = newMap
+		//opts.MapReplacements = map[string]*ebpf.Map{
+		//	"test_heap": newMap,
+		//}
+	}
+}

+ 107 - 0
ebpftracer/tracer/common.go

@@ -0,0 +1,107 @@
+package tracer
+
+const (
+	ETR_OK               = 0
+	ETR_NOTEXIST         = -4
+	ETR_UPDATE_MAP_FAILD = -9 /* update map failed */
+	ETR_NOTSUPP          = -14
+)
+
+const (
+	// eBPF Map Name
+	MAP_MEMBERS_OFFSET_NAME    = "__members_offset"
+	MAP_SOCKET_INFO_NAME       = "__socket_info_map"
+	MAP_TRACE_NAME             = "__trace_map"
+	MAP_PERF_SOCKET_DATA_NAME  = "__socket_data"
+	MAP_TRACE_CONF_NAME        = "__trace_conf_map"
+	MAP_TRACE_STATS_NAME       = "__trace_stats_map"
+	MAP_PROTO_FILTER_NAME      = "__protocol_filter"
+	MAP_ALLOW_PORT_BITMAP_NAME = "__allow_port_bitmap"
+	MAP_ADAPT_KERN_UID_NAME    = "__adapt_kern_uid_map"
+
+	//Program jmp tables
+	MAP_PROGS_JMP_KP_NAME = "__progs_jmp_kp_map"
+	MAP_PROGS_JMP_TP_NAME = "__progs_jmp_tp_map"
+
+	// This prog is designed to handle data transfer
+	PROG_DATA_SUBMIT_NAME_FOR_KP = "bpf_prog_kp__data_submit"
+	PROG_DATA_SUBMIT_NAME_FOR_TP = "bpf_prog_tp__data_submit"
+	PROG_OUTPUT_DATA_NAME_FOR_KP = "bpf_prog_kp__output_data"
+	PROG_OUTPUT_DATA_NAME_FOR_TP = "bpf_prog_tp__output_data"
+	PROG_IO_EVENT_NAME_FOR_TP    = "bpf_prog_tp__io_event"
+)
+
+const (
+	PROG_DATA_SUBMIT_TP_IDX = iota
+	PROG_OUTPUT_DATA_TP_IDX
+	PROG_IO_EVENT_TP_IDX
+	PROG_TP_NUM
+)
+
+const (
+	PROG_DATA_SUBMIT_KP_IDX = iota
+	PROG_OUTPUT_DATA_KP_IDX
+	PROG_KP_NUM
+)
+
+// 数据协议
+const (
+	PROTO_UNKNOWN    = 0
+	PROTO_ORTHER     = 1
+	PROTO_HTTP1      = 20
+	PROTO_HTTP2      = 21
+	PROTO_TLS_HTTP1  = 22
+	PROTO_TLS_HTTP2  = 23
+	PROTO_DUBBO      = 40
+	PROTO_SOFARPC    = 43
+	PROTO_MYSQL      = 60
+	PROTO_POSTGRESQL = 61
+	PROTO_REDIS      = 80
+	PROTO_KAFKA      = 100
+	PROTO_MQTT       = 101
+	PROTO_DNS        = 120
+	PROTO_NUM        = 130
+)
+
+var EbpfConfigProtocolFilter [PROTO_NUM]uint32
+
+type testStruct struct {
+	test_id uint32
+}
+
+type bpfOffsetParam struct {
+	Ready                          uint32 `json:"ready"`
+	TaskFilesOffset                uint32 `json:"task__files_offset"`
+	SockFlagsOffset                uint32 `json:"sock__flags_offset"`
+	TcpSockCopiedSeqOffset         uint32 `json:"tcp_sock__copied_seq_offset"`
+	TcpSockWriteSeqOffset          uint32 `json:"tcp_sock__write_seq_offset"`
+	StructFilesStructFdtOffset     uint32 `json:"struct_files_struct_fdt_offset"`
+	StructFilesPrivateDataOffset   uint32 `json:"struct_files_private_data_offset"`
+	StructFileFInodeOffset         uint32 `json:"struct_file_f_inode_offset"`
+	StructInodeIModeOffset         uint32 `json:"struct_inode_i_mode_offset"`
+	StructFileDentryOffset         uint32 `json:"struct_file_dentry_offset"`
+	StructDentryNameOffset         uint32 `json:"struct_dentry_name_offset"`
+	StructSockFamilyOffset         uint32 `json:"struct_sock_family_offset"`
+	StructSockSaddrOffset          uint32 `json:"struct_sock_saddr_offset"`
+	StructSockDaddrOffset          uint32 `json:"struct_sock_daddr_offset"`
+	StructSockIp6saddrOffset       uint32 `json:"struct_sock_ip6saddr_offset"`
+	StructSockIp6daddrOffset       uint32 `json:"struct_sock_ip6daddr_offset"`
+	StructSockDportOffset          uint32 `json:"struct_sock_dport_offset"`
+	StructSockSportOffset          uint32 `json:"struct_sock_sport_offset"`
+	StructSockSkcStateOffset       uint32 `json:"struct_sock_skc_state_offset"`
+	StructSockCommonIpv6onlyOffset uint32 `json:"struct_sock_common_ipv6only_offset"`
+}
+
+type traceConf struct {
+	SocketID               uint64 // 会话标识
+	CoroutineTraceID       uint64 // 同一协程的数据转发关联
+	ThreadTraceID          uint64 // 同一进程/线程的数据转发关联,用于多事务流转场景
+	DataLimitMax           uint64 // Maximum number of data transfers
+	GoTracingTimeout       uint64
+	IOEventCollectMode     uint64
+	IOEventMinimalDuartion uint64
+}
+
+type allowPortBitmap struct {
+	Bitmap [65536 / 8]uint8
+}

+ 41 - 0
ebpftracer/tracer/filter.go

@@ -0,0 +1,41 @@
+package tracer
+
+import (
+	"fmt"
+	"github.com/cilium/ebpf"
+	"github.com/cilium/ebpf/asm"
+	"os"
+	"strconv"
+)
+
+func PidFilter(collectionSpec *ebpf.CollectionSpec) {
+	ENV_PID := os.Getenv("FILTER_PID")
+	if ENV_PID != "" {
+		filterPid, _ := strconv.ParseInt(ENV_PID, 10, 64)
+		type Editor struct {
+			instructions     *asm.Instructions
+			ReferenceOffsets map[string][]int
+		}
+		for _, prog := range collectionSpec.Programs {
+			fmt.Println("collectionSpec.Program:", prog.Name, prog.SectionName, prog.Type)
+			insns := &prog.Instructions
+			refs := insns.ReferenceOffsets()
+
+			edit := &Editor{insns, refs}
+			indices := edit.ReferenceOffsets["filter_pid"]
+			//fmt.Println("len(indices):", len(indices))
+			if len(indices) == 0 {
+				continue
+			}
+			ldDWImm := asm.LoadImmOp(asm.DWord)
+			for _, index := range indices {
+				load := &(*edit.instructions)[index]
+				if load.OpCode != ldDWImm {
+					continue
+					//return errors.Errorf("symbol %v: load: found %v instead of %v", symbol, load.OpCode, ldDWImm)
+				}
+				load.Constant = filterPid
+			}
+		}
+	}
+}

+ 103 - 0
ebpftracer/tracer/offset.go

@@ -0,0 +1,103 @@
+package tracer
+
+import (
+	"fmt"
+	"io"
+	"net"
+	"strings"
+)
+
+const (
+	offsetInferServerAddr = "127.0.0.1"
+	offsetInferServerPort = 54583
+	bufferSize            = 16
+)
+
+func kernelOffsetInferServer(listener net.Listener) error {
+
+	fmt.Println("[eBPF Kernel Adapt] kernel_offset_infer_server started.")
+
+	//cpuOnlineCount := runtime.NumCPU()
+
+	go func() {
+		for {
+			conn, err := listener.Accept()
+			if err != nil {
+				fmt.Printf("[eBPF Kernel Adapt] Fail to accept client request: %v\n", err)
+				return
+			}
+			go handleConnection(conn)
+		}
+	}()
+
+	return nil
+}
+
+func handleConnection(conn net.Conn) {
+	defer conn.Close()
+
+	buffer := make([]byte, bufferSize)
+	for {
+		n, err := conn.Read(buffer)
+		if err != nil {
+			if err == io.EOF {
+				fmt.Printf("[eBPF Kernel Adapt] client connection closed: %v\n", err)
+				return
+			}
+			fmt.Printf("[eBPF Kernel Adapt] Error reading from connection: %v\n", err)
+			return
+		}
+		//if n == 0 {
+		//	*clientCount++
+		//	break
+		//}
+
+		request := strings.TrimSpace(string(buffer[:n]))
+		fmt.Println(request)
+		if request == "hello" {
+			_, err := conn.Write([]byte("OK"))
+			if err != nil {
+				fmt.Printf("[eBPF Kernel Adapt] Error writing response: %v\n", err)
+				break
+			}
+		}
+	}
+}
+
+func kernelOffsetInferClient() error {
+	conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", offsetInferServerAddr, offsetInferServerPort))
+	if err != nil {
+		return fmt.Errorf("failed to connect to server: %v", err)
+	}
+	defer conn.Close()
+
+	fmt.Println("[eBPF Kernel Adapt] kernel_offset_infer_client started.")
+
+	request := "hello"
+	_, err = conn.Write([]byte(request))
+	if err != nil {
+		return fmt.Errorf("failed to send request to server: %v", err)
+	}
+
+	buffer := make([]byte, bufferSize)
+	for {
+		n, err := conn.Read(buffer)
+		if err != nil {
+			fmt.Printf("[eBPF Kernel Adapt] Error reading response from server: %v\n", err)
+			break
+		}
+		if n == 0 {
+			break
+		}
+
+		response := strings.TrimSpace(string(buffer[:n]))
+		fmt.Println(response)
+
+		if response == "OK" {
+			break
+		}
+	}
+
+	fmt.Println("[eBPF Kernel Adapt] kernel_offset_infer_client finished.")
+	return nil
+}

+ 314 - 0
ebpftracer/tracer/socket.go

@@ -0,0 +1,314 @@
+package tracer
+
+import (
+	"fmt"
+	"github.com/cilium/ebpf"
+	"github.com/cilium/ebpf/btf"
+	"k8s.io/klog/v2"
+	"net"
+	"os"
+	"runtime"
+	"syscall"
+	"time"
+)
+
+func init() {
+	enable_ebpf_protocol(PROTO_HTTP1)
+	enable_ebpf_protocol(PROTO_HTTP2)
+	enable_ebpf_protocol(PROTO_TLS_HTTP1)
+	enable_ebpf_protocol(PROTO_TLS_HTTP2)
+	enable_ebpf_protocol(PROTO_DUBBO)
+	enable_ebpf_protocol(PROTO_SOFARPC)
+	enable_ebpf_protocol(PROTO_MYSQL)
+	enable_ebpf_protocol(PROTO_POSTGRESQL)
+	enable_ebpf_protocol(PROTO_REDIS)
+	enable_ebpf_protocol(PROTO_KAFKA)
+	enable_ebpf_protocol(PROTO_MQTT)
+	enable_ebpf_protocol(PROTO_DNS)
+}
+
+func MapInit(collectionSpec *ebpf.CollectionSpec, opts *ebpf.CollectionOptions) {
+	set_offset_map(collectionSpec, opts)
+	set_conf_map_default(collectionSpec, opts)
+
+	//offsetData := make([]any, runtime.NumCPU())
+	//for i := range offsetData {
+	//	offsetData[i] = testStruct{
+	//		test_id: 99999,
+	//	}
+	//}
+	//if bpf_table_set_value(collectionSpec, opts, "test_heap", offsetData) != ETR_OK {}
+	//insert_output_prog_to_map(collectionSpec, opts)
+}
+
+func MapInsert(collection *ebpf.Collection) {
+	insert_output_prog_to_map(collection)
+	insert_adapt_kern_uid_to_map(collection)
+
+	// Update protocol filter array
+	update_protocol_filter_array(collection)
+
+}
+
+func insert_output_prog_to_map(collection *ebpf.Collection) {
+	// jmp for tracepoints
+	__insert_output_prog_to_map(collection, MAP_PROGS_JMP_TP_NAME, PROG_DATA_SUBMIT_NAME_FOR_TP, PROG_DATA_SUBMIT_TP_IDX)
+	__insert_output_prog_to_map(collection, MAP_PROGS_JMP_TP_NAME, PROG_OUTPUT_DATA_NAME_FOR_TP, PROG_OUTPUT_DATA_TP_IDX)
+	__insert_output_prog_to_map(collection, MAP_PROGS_JMP_TP_NAME, PROG_IO_EVENT_NAME_FOR_TP, PROG_IO_EVENT_TP_IDX)
+
+	// jmp for kprobe/uprobe
+	__insert_output_prog_to_map(collection, MAP_PROGS_JMP_KP_NAME, PROG_DATA_SUBMIT_NAME_FOR_KP, PROG_DATA_SUBMIT_KP_IDX)
+	__insert_output_prog_to_map(collection, MAP_PROGS_JMP_KP_NAME, PROG_OUTPUT_DATA_NAME_FOR_KP, PROG_OUTPUT_DATA_KP_IDX)
+}
+
+func __insert_output_prog_to_map(collection *ebpf.Collection, mapName string, progName string, key uint32) {
+	// find in programs
+	prog, ok := collection.Programs[progName]
+	fmt.Println(prog, ok)
+	if ok {
+		progFd := prog.FD()
+		fmt.Println("progFd", progFd)
+		if bpf_table_set_value(collection, mapName, key, uint32(progFd)) != ETR_OK {
+			fmt.Println("no")
+		} else {
+			fmt.Println("ok")
+		}
+	}
+}
+
+func update_protocol_filter_array(collection *ebpf.Collection) {
+	for i := 0; i < PROTO_NUM; i++ {
+		if bpf_table_set_value(collection, MAP_PROTO_FILTER_NAME, uint32(i), EbpfConfigProtocolFilter[i]) != ETR_OK {
+			fmt.Println("no")
+		} else {
+			fmt.Println("ok")
+		}
+	}
+}
+
+//func update_allow_port_bitmap(collection *ebpf.Collection) {
+//	for i := 0; i < PROTO_NUM; i++ {
+//		if bpf_table_set_value(collection, MAP_ALLOW_PORT_BITMAP_NAME, 0, &allow_port_bitmap) != ETR_OK {
+//			fmt.Println("no")
+//		} else {
+//			fmt.Println("ok")
+//		}
+//	}
+//}
+
+func insert_adapt_kern_uid_to_map(collection *ebpf.Collection) {
+	pid := os.Getpid()
+	tid := syscall.Gettid()
+	adaptKernUID := uint64(pid)<<32 | uint64(tid)
+	if bpf_table_set_value(collection, MAP_ADAPT_KERN_UID_NAME, 0, uint32(adaptKernUID)) != ETR_OK {
+		fmt.Println("no")
+	} else {
+		fmt.Println("ok")
+	}
+}
+
+func enable_ebpf_protocol(protocol int) {
+	if protocol < PROTO_NUM {
+		EbpfConfigProtocolFilter[protocol] = 1
+	}
+}
+
+func Offset() {
+	listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", offsetInferServerAddr, offsetInferServerPort))
+	if err != nil {
+		fmt.Errorf("failed to create server listener: %v", err)
+		return
+	}
+	if err := kernelOffsetInferServer(listener); err != nil {
+		fmt.Printf("Error in kernel_offset_infer_server: %v\n", err)
+	}
+	if err := kernelOffsetInferClient(); err != nil {
+		fmt.Printf("Error in kernel_offset_infer_client: %v\n", err)
+	}
+	defer listener.Close()
+}
+
+func set_offset_map(collectionSpec *ebpf.CollectionSpec, opts *ebpf.CollectionOptions) {
+	// 解析BTF数据
+	if update_offset_map_from_btf_vmlinux(collectionSpec, opts) != ETR_OK {
+		klog.Infof("[eBPF Kernel Adapt] Set offsets map from btf_vmlinux, not support.\n")
+		if update_offset_map_default(collectionSpec, opts) != ETR_OK {
+			klog.Infof("Fatal error, failed to update default offset\n")
+		}
+	} else {
+		klog.Infof("[eBPF Kernel Adapt] Set offsets map from btf_vmlinux, success.\n")
+	}
+}
+
+func set_conf_map_default(collectionSpec *ebpf.CollectionSpec, opts *ebpf.CollectionOptions) {
+	uidBase := uint64(time.Now().UnixNano()/int64(time.Millisecond)) & 0xffffffffffffff
+	numCPU := runtime.NumCPU()
+	tConf := make([]any, numCPU)
+	for i := range tConf {
+		socketID := uint64(i)<<56 | uint64(uidBase)
+		tracerConf := traceConf{
+			SocketID:               socketID,
+			CoroutineTraceID:       socketID,
+			ThreadTraceID:          socketID,
+			DataLimitMax:           4096,
+			GoTracingTimeout:       120,
+			IOEventCollectMode:     1,
+			IOEventMinimalDuartion: 1000000,
+		}
+		tConf[i] = tracerConf
+	}
+	if bpf_table_pre_set_value(collectionSpec, opts, MAP_TRACE_CONF_NAME, tConf) != ETR_OK {
+		klog.Infof("[eBPF Kernel Adapt] Set config map from btf_vmlinux, not support.\n")
+	} else {
+		klog.Infof("[eBPF Kernel Adapt] Set config map from btf_vmlinux, success.\n")
+	}
+}
+
+// 解析BTF数据
+func update_offset_map_from_btf_vmlinux(collectionSpec *ebpf.CollectionSpec, opts *ebpf.CollectionOptions) int {
+	btfSpec, err := btf.LoadKernelSpec()
+	if err != nil || btfSpec == nil {
+		return ETR_NOTSUPP
+	}
+
+	copied_seq_offs := kernel_struct_field_offset(btfSpec, "tcp_sock", "copied_seq")
+	write_seq_offs := kernel_struct_field_offset(btfSpec, "tcp_sock", "write_seq")
+	files_offs := kernel_struct_field_offset(btfSpec, "task_struct", "files")
+	sk_flags_offs := kernel_struct_field_offset(btfSpec, "sock", "__sk_flags_offset")
+
+	if sk_flags_offs == ETR_NOTEXIST {
+		sk_flags_offs = kernel_struct_field_offset(btfSpec, "sock", "sk_pacing_shift")
+		if sk_flags_offs > 0 {
+			sk_flags_offs -= 1
+		}
+	}
+
+	struct_files_struct_fdt_offset := kernel_struct_field_offset(btfSpec, "files_struct", "fdt")
+	struct_files_private_data_offset := kernel_struct_field_offset(btfSpec, "file", "private_data")
+	struct_file_f_inode_offset := kernel_struct_field_offset(btfSpec, "file", "f_inode")
+	struct_inode_i_mode_offset := kernel_struct_field_offset(btfSpec, "inode", "i_mode")
+	struct_file_dentry_offset_1 := kernel_struct_field_offset(btfSpec, "file", "f_path")
+	struct_file_dentry_offset_2 := kernel_struct_field_offset(btfSpec, "path", "dentry")
+	if struct_file_dentry_offset_1 < 0 ||
+		struct_file_dentry_offset_2 < 0 {
+		return ETR_NOTSUPP
+	}
+
+	struct_file_dentry_offset := struct_file_dentry_offset_1 + struct_file_dentry_offset_2
+	struct_dentry_name_offset_1 := kernel_struct_field_offset(btfSpec, "dentry", "d_name")
+	struct_dentry_name_offset_2 := kernel_struct_field_offset(btfSpec, "qstr", "name")
+	if struct_dentry_name_offset_1 < 0 ||
+		struct_dentry_name_offset_2 < 0 {
+		return ETR_NOTSUPP
+	}
+
+	struct_dentry_name_offset := struct_dentry_name_offset_1 + struct_dentry_name_offset_2
+	struct_sock_family_offset := kernel_struct_field_offset(btfSpec, "sock_common", "skc_family")
+	struct_sock_saddr_offset := kernel_struct_field_offset(btfSpec, "sock_common", "skc_rcv_saddr")
+	struct_sock_daddr_offset := kernel_struct_field_offset(btfSpec, "sock_common", "skc_daddr")
+	struct_sock_ip6saddr_offset := kernel_struct_field_offset(btfSpec, "sock_common", "skc_v6_rcv_saddr")
+	struct_sock_ip6daddr_offset := kernel_struct_field_offset(btfSpec, "sock_common", "skc_v6_daddr")
+	struct_sock_dport_offset := kernel_struct_field_offset(btfSpec, "sock_common", "skc_dport")
+	struct_sock_sport_offset := kernel_struct_field_offset(btfSpec, "sock_common", "skc_num")
+	struct_sock_skc_state_offset := kernel_struct_field_offset(btfSpec, "sock_common", "skc_state")
+	struct_sock_common_ipv6only_offset := kernel_struct_field_offset(btfSpec, "sock_common", "skc_flags")
+
+	klog.Infof("Offsets from BTF vmlinux:\n")
+	klog.Infof("    copied_seq_offs: 0x%x\n", copied_seq_offs)
+	klog.Infof("    write_seq_offs: 0x%x\n", write_seq_offs)
+	klog.Infof("    files_offs: 0x%x\n", files_offs)
+	klog.Infof("    sk_flags_offs: 0x%x\n", sk_flags_offs)
+	klog.Infof("    struct_files_struct_fdt_offset: 0x%x\n", struct_files_struct_fdt_offset)
+	klog.Infof("    struct_files_private_data_offset: 0x%x\n", struct_files_private_data_offset)
+	klog.Infof("    struct_file_f_inode_offset: 0x%x\n", struct_file_f_inode_offset)
+	klog.Infof("    struct_inode_i_mode_offset: 0x%x\n", struct_inode_i_mode_offset)
+	klog.Infof("    struct_file_dentry_offset: 0x%x\n", struct_file_dentry_offset)
+	klog.Infof("    struct_dentry_name_offset: 0x%x\n", struct_dentry_name_offset)
+	klog.Infof("    struct_sock_family_offset: 0x%x\n", struct_sock_family_offset)
+	klog.Infof("    struct_sock_saddr_offset: 0x%x\n", struct_sock_saddr_offset)
+	klog.Infof("    struct_sock_daddr_offset: 0x%x\n", struct_sock_daddr_offset)
+	klog.Infof("    struct_sock_ip6saddr_offset: 0x%x\n", struct_sock_ip6saddr_offset)
+	klog.Infof("    struct_sock_ip6daddr_offset: 0x%x\n", struct_sock_ip6daddr_offset)
+	klog.Infof("    struct_sock_dport_offset: 0x%x\n", struct_sock_dport_offset)
+	klog.Infof("    struct_sock_sport_offset: 0x%x\n", struct_sock_sport_offset)
+	klog.Infof("    struct_sock_skc_state_offset: 0x%x\n", struct_sock_skc_state_offset)
+	klog.Infof("    struct_sock_common_ipv6only_offset: 0x%x\n", struct_sock_common_ipv6only_offset)
+
+	if copied_seq_offs < 0 || write_seq_offs < 0 || files_offs < 0 ||
+		sk_flags_offs < 0 || struct_files_struct_fdt_offset < 0 ||
+		struct_files_private_data_offset < 0 ||
+		struct_file_f_inode_offset < 0 || struct_inode_i_mode_offset < 0 ||
+		struct_inode_i_mode_offset < 0 || struct_file_dentry_offset < 0 ||
+		struct_dentry_name_offset < 0 || struct_sock_family_offset < 0 ||
+		struct_sock_saddr_offset < 0 || struct_sock_daddr_offset < 0 ||
+		struct_sock_ip6saddr_offset < 0 ||
+		struct_sock_ip6daddr_offset < 0 || struct_sock_dport_offset < 0 ||
+		struct_sock_sport_offset < 0 || struct_sock_skc_state_offset < 0 ||
+		struct_sock_common_ipv6only_offset < 0 {
+		return ETR_NOTSUPP
+	}
+
+	offset := bpfOffsetParam{}
+	offset.Ready = 1
+	offset.TaskFilesOffset = uint32(files_offs)
+	offset.SockFlagsOffset = uint32(sk_flags_offs)
+	offset.TcpSockCopiedSeqOffset = uint32(copied_seq_offs)
+	offset.TcpSockWriteSeqOffset = uint32(write_seq_offs)
+	offset.StructFilesStructFdtOffset = uint32(struct_files_struct_fdt_offset)
+	offset.StructFilesPrivateDataOffset = uint32(struct_files_private_data_offset)
+	offset.StructFileFInodeOffset = uint32(struct_file_f_inode_offset)
+	offset.StructInodeIModeOffset = uint32(struct_inode_i_mode_offset)
+	offset.StructFileDentryOffset = uint32(struct_file_dentry_offset)
+	offset.StructDentryNameOffset = uint32(struct_dentry_name_offset)
+	offset.StructSockFamilyOffset = uint32(struct_sock_family_offset)
+	offset.StructSockSaddrOffset = uint32(struct_sock_saddr_offset)
+	offset.StructSockDaddrOffset = uint32(struct_sock_daddr_offset)
+	offset.StructSockIp6saddrOffset = uint32(struct_sock_ip6saddr_offset)
+	offset.StructSockIp6daddrOffset = uint32(struct_sock_ip6daddr_offset)
+	offset.StructSockDportOffset = uint32(struct_sock_dport_offset)
+	offset.StructSockSportOffset = uint32(struct_sock_sport_offset)
+	offset.StructSockSkcStateOffset = uint32(struct_sock_skc_state_offset)
+	offset.StructSockCommonIpv6onlyOffset = uint32(struct_sock_common_ipv6only_offset)
+
+	if update_offsets_table(collectionSpec, opts, offset) != ETR_OK {
+		return ETR_UPDATE_MAP_FAILD
+	}
+	return ETR_OK
+}
+
+func update_offset_map_default(collectionSpec *ebpf.CollectionSpec, opts *ebpf.CollectionOptions) int {
+	offset := bpfOffsetParam{}
+
+	offset.StructFilesStructFdtOffset = 0x20
+	offset.StructFilesPrivateDataOffset = 0xc8
+	offset.StructFileFInodeOffset = 0x20
+	offset.StructInodeIModeOffset = 0x00
+	offset.StructFileDentryOffset = 0x18
+	offset.StructDentryNameOffset = 0x28
+	offset.StructSockFamilyOffset = 0x10
+	offset.StructSockSaddrOffset = 0x4
+	offset.StructSockDaddrOffset = 0x0
+	offset.StructSockIp6saddrOffset = 0x48
+	offset.StructSockIp6daddrOffset = 0x38
+	offset.StructSockDportOffset = 0xc
+	offset.StructSockSportOffset = 0xe
+	offset.StructSockSkcStateOffset = 0x12
+	offset.StructSockCommonIpv6onlyOffset = 0x13
+
+	if update_offsets_table(collectionSpec, opts, offset) != ETR_OK {
+		return ETR_UPDATE_MAP_FAILD
+	}
+	return ETR_OK
+}
+
+func update_offsets_table(collectionSpec *ebpf.CollectionSpec, opts *ebpf.CollectionOptions, offset bpfOffsetParam) int {
+	numCPU := runtime.NumCPU()
+	offsetData := make([]any, numCPU)
+	for i := range offsetData {
+		offsetData[i] = offset
+	}
+	if bpf_table_pre_set_value(collectionSpec, opts, MAP_MEMBERS_OFFSET_NAME, offsetData) != ETR_OK {
+		return ETR_UPDATE_MAP_FAILD
+	}
+	return ETR_OK
+}

+ 6 - 5
main.go

@@ -17,7 +17,6 @@ import (
 	"github.com/coroot/coroot-node-agent/flags"
 	"github.com/coroot/coroot-node-agent/logs"
 	"github.com/coroot/coroot-node-agent/node"
-	"github.com/coroot/coroot-node-agent/profiling"
 	"github.com/coroot/coroot-node-agent/prom"
 	"github.com/coroot/coroot-node-agent/tracing"
 	"github.com/prometheus/client_golang/prometheus"
@@ -144,16 +143,18 @@ func main() {
 		klog.Exitln(err)
 	}
 
-	processInfoCh := profiling.Init(machineId, hostname)
+	//processInfoCh := profiling.Init(machineId, hostname)
+
+	cr, err := containers.NewRegistry(registerer, kv, nil)
 
-	cr, err := containers.NewRegistry(registerer, kv, processInfoCh)
 	if err != nil {
 		klog.Exitln(err)
 	}
 	defer cr.Close()
+	klog.Infoln("START_TRACE")
 
-	profiling.Start()
-	defer profiling.Stop()
+	//profiling.Start()
+	//defer profiling.Stop()
 	// 创建一个/metrics路由处理函数
 	metricsHandler := func(w http.ResponseWriter, r *http.Request) {
 		// 从注册表中获取指标数据