فهرست منبع

Fixed #TASK_QT-9810 [arm适配]java-client arm适配

Carl 1 سال پیش
والد
کامیت
5e885e618d

+ 16 - 2
containers/container.go

@@ -1091,6 +1091,9 @@ func (c *Container) revalidateListens(now time.Time, actualListens map[netaddr.I
 }
 
 func (c *Container) attachUprobes(tracer *ebpftracer.Tracer, pid uint32) {
+	if tracer.DisableL7Tracing() {
+		return
+	}
 	codeType := c.GetCodeTypeFromCache(pid)
 	if codeType.IsUnknownCode() {
 		return
@@ -1149,8 +1152,19 @@ func (c *Container) attachJVMUprobes(tracer *ebpftracer.Tracer, pid uint32) {
 	if !p.jvmUprobesChecked {
 		codeType := c.GetCodeTypeFromCache(pid)
 		tracer.InitKProcInfo(pid, c.instanceID, uint16(codeType))
-		p.uprobes = append(p.uprobes, tracer.AttachJavaNioReadUprobes(pid, c.instanceID, (codeType))...)
-		p.uprobes = append(p.uprobes, tracer.AttachJavaNetWriteUprobes(pid, c.instanceID)...)
+
+		libNioProbes, err := tracer.AttachJavaNioReadUprobes(pid, codeType)
+		if err == nil {
+			p.uprobes = append(p.uprobes, libNioProbes...)
+		} else {
+			klog.Error(err)
+		}
+		libNetProbes, err := tracer.AttachJavaNetWriteUprobes(pid)
+		if err == nil {
+			p.uprobes = append(p.uprobes, libNetProbes...)
+		} else {
+			klog.Error(err)
+		}
 		p.jvmUprobesChecked = true
 	}
 }

+ 2 - 2
containers/registry.go

@@ -111,7 +111,7 @@ func NewRegistry(reg prometheus.Registerer, kernelVersion string, processInfoCh
 
 		processInfoCh: processInfoCh,
 
-		tracer: ebpftracer.NewTracer(kernelVersion, *flags.DisableL7Tracing),
+		tracer: ebpftracer.NewTracer(kernelVersion, *flags.DisableL7Tracing, *flags.DisableE2ETracing, *flags.DisableStackTracing),
 	}
 	if err = reg.Register(r); err != nil {
 		return nil, err
@@ -245,7 +245,7 @@ func (r *Registry) handleEvents(ch <-chan ebpftracer.Event) {
 					c.attachUprobes(r.tracer, e.Pid)
 					err := c.stackTrace(r.tracer, e.Pid)
 					if err != nil {
-
+						klog.Errorf("Stack trace error", err)
 					}
 				} else {
 					klog.Infoln("TCP listen open from unknown container", e)

+ 4 - 0
containers/stack.go

@@ -28,6 +28,10 @@ type uprobesDef struct {
 }
 
 func (c *Container) stackTrace(tracer *ebpftracer.Tracer, pid uint32) error {
+	// 禁用stack
+	if tracer.DisableStackTracing() {
+		return nil
+	}
 	ENV_PID := os.Getenv("FILTER_PID")
 	if ENV_PID != "" {
 		filterPid, _ := strconv.ParseInt(ENV_PID, 10, 64)

+ 4 - 0
ebpftracer/ebpf/ebpf.c

@@ -58,6 +58,10 @@
 #include "utrace/java/net/server.probe.bpf.c"
 #include "utrace/java/net/client.probe.bpf.c"
 
+// 支持arm64后打开
+#if defined(__x86_64__)
 #include "utrace/netcore/net/server.probe.bpf.c"
 #include "utrace/netcore/net/client.probe.bpf.c"
+#endif
+
 char _license[] SEC("license") = "GPL";

+ 18 - 0
ebpftracer/ebpf/include/common.h

@@ -59,4 +59,22 @@ struct protocol_message_t {
 //	TASK_COMM_LEN = 16,
 //};
 
+enum code_type {
+	CodeTypeUnknown    = -1,
+	CodeTypeWaitCheck  = 0,
+	CodeTypePHP        = 1001,
+	CodeTypeJava       = 1002,
+	CodeTypeJavaAot    = 1102,
+	CodeTypePython     = 1003,
+	CodeTypeDotNet     = 1004,
+	CodeTypeNode       = 1005,
+	CodeTypeGo         = 1006,
+	CodeTypeC          = 1007,
+	CodeTypeNetCore    = 1008,
+	CodeTypeNetCoreAot = 1108,
+	CodeTypeLua        = 1009,
+	CodeTypeJavaC      = 1010,
+	CodeTypeRuby       = 1012
+};
+
 #endif /* DF_BPF_COMMON_H */

+ 0 - 212
ebpftracer/ebpf/l7/l7.c

@@ -248,218 +248,6 @@ __u64 read_iovec(char *l7_iovec, __u64 iovlen, __u64 ret, char *buf) {
     return offset;
 }
 
-static inline __attribute__((__always_inline__))
-int rock_trace_enter_write(void *ctx, char *buf, __u64 size, __u64 iovlen) {
-    __u64 id = bpf_get_current_pid_tgid();
-    __u32 zero = 0;
-    __u32 pid, tid;
-    __u32 http_status;
-    struct trace_event_raw_sys_enter_rw__stub* tctx = (struct trace_event_raw_sys_enter_rw__stub*)ctx;
-    __u64 fd = tctx->fd;
-
-    pid = id >> 32;
-    tid =  (__u32)id;
-    if (load_filter_pid() != 0 && pid != load_filter_pid()) {
-        return 0;
-    }
-    char* payload = buf;
-    if (iovlen) {
-        payload = bpf_map_lookup_elem(&iovec_buf_heap, &zero);
-        if (!payload) {
-            return 0;
-        }
-        size = read_iovec(buf, iovlen, 0, payload);
-    }
-    if (!size) {
-        return 0;
-    }
-
-    struct l7_request *req = bpf_map_lookup_elem(&l7_request_heap, &zero);
-    if (!req) {
-        return 0;
-    }
-    req->protocol = PROTOCOL_UNKNOWN;
-    req->partial = 0;
-    req->request_id = 0;
-    req->ns = 0;
-    req->payload_size = size;
-    struct l7_request_key k = {};
-    k.pid = id >> 32;
-    k.fd = fd;
-    k.is_tls = 0;
-    k.stream_id = -1;
-
-//    cw_bpf_debug("enter-payload:%s|type:%s|FD:%d\n",payload,"type",k.fd);
-
-    if (is_http_response(payload, &http_status))
-    {
-//        __u64 trace_id = get_apm_trace_id(pid, fd);
-        __u64 trace_id = get_fd_trace_id(pid, fd);
-        cw_bpf_debug("[Trace End in l7][Response][HTTP] pid:%d,fd:%d,trace_id:%llu", tid, fd, trace_id);
-        // 清除trace信息
-        cw_clear_trace(pid, tid, fd);
-        // 发送事件到用户空间 start
-        struct l7_event *e = bpf_map_lookup_elem(&l7_event_heap, &zero);
-        if (!e) {
-            return 0;
-        }
-        struct l7_request *req = bpf_map_lookup_elem(&active_l7_requests, &k);
-        if (!req)
-        {
-//            cw_bpf_debug("[Response][HTTP]:no req-----------");
-//            cw_bpf_debug("[Response][HTTP]:pid:%d|tid:%d",k.pid,k.fd);
-//            cw_bpf_debug("[Response][HTTP]:is_tls:%d|tid:%d",k.is_tls,k.stream_id);
-            return 0;
-        }
-
-        e->duration = bpf_ktime_get_ns() - req->ns;
-//        cw_bpf_debug("[Response][HTTP]:duration->ns:%d\n",e->duration);
-        e->protocol = PROTOCOL_TRACE;
-        e->status = http_status;
-        e->pid = k.pid;
-        e->fd = k.fd;
-        // e->connection_timestamp = get_connection_timestamp(k.pid, k.fd);
-        e->trace_start = 0;
-        e->trace_end = 1;
-        e->trace_id = trace_id;
-        e->payload_size = size;
-        COPY_PAYLOAD(e->payload, size, payload);
-		// psc
-	    struct apm_span_context *cw_psc = cw_get_parent_tracking_span();
-	    if(cw_psc){
-		    cw_copy_byte_arrays(cw_psc->trace_id, e->trace_id_from, APM_TRACE_ID_SIZE);
-		    cw_copy_byte_arrays(cw_psc->assumed_app_id, e->called_id, APM_ASSUMED_APP_ID_SIZE);
-		    cw_copy_byte_arrays(cw_psc->instance_id, e->instance_id_from, APM_INSTANCE_ID_SIZE);
-		    cw_copy_byte_arrays(cw_psc->app_id, e->app_id_from, APM_APP_ID_SIZE);
-		    cw_copy_byte_arrays(cw_psc->span_id, e->span_id_from, APM_SPAN_ID_SIZE);
-//		    for (int i = 0; i < APM_TRACE_ID_SIZE; i++) {
-//			    bpf_printk("trace_enter_write - trace_id = %02x", e->trace_id_from[i]);
-//		    }
-	    }
-        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_id1111:%d", ttt->test_id);
-        cw_bpf_debug("HTTP_END");
-        return 0;
-    }
-
-    if (is_http_request(payload)) {
-	    cw_bpf_debug("");
-	    cw_bpf_debug("-----[Kernel Enter][HTTP]:pid:[%d]|CURRENT-GOID:[%llu]|FD:[%d]", tid, get_current_goroutine(), k.fd);
-
-	    req->protocol = PROTOCOL_HTTP;
-//        struct apm_trace_key_t trace_key = {0};
-//        trace_key = get_apm_trace_key(120 * NS_PER_SEC, true);
-//        cw_bpf_debug("[Enter] [HTTP]:goid:%llu",trace_key.goid);
-
-
-    } else if (is_postgres_query(payload, size, &req->request_type)) {
-        if (req->request_type == POSTGRES_FRAME_CLOSE) {
-            struct l7_event *e = bpf_map_lookup_elem(&l7_event_heap, &zero);
-            if (!e) {
-                return 0;
-            }
-            e->protocol = PROTOCOL_POSTGRES;
-            e->method = METHOD_STATEMENT_CLOSE;
-            e->payload_size = size;
-            COPY_PAYLOAD(e->payload, size, payload);
-            send_event(ctx, e, k.pid, k.fd);
-            return 0;
-        }
-        req->protocol = PROTOCOL_POSTGRES;
-    } else if (is_redis_query(payload, size)) {
-        cw_bpf_debug("[Enter][Redis]:TGID:%d|type:%s|FD:%d\n",k.pid,"type",k.fd);
-        req->protocol = PROTOCOL_REDIS;
-    } else if (is_memcached_query(payload, size)) {
-        req->protocol = PROTOCOL_MEMCACHED;
-    } else if (is_mysql_query(payload, size, &req->request_type)) {
-        cw_bpf_debug("[Enter][Mysql]:thread_id:%d\n",tid);
-        if (req->request_type == MYSQL_COM_STMT_CLOSE) {
-            struct l7_event *e = bpf_map_lookup_elem(&l7_event_heap, &zero);
-            if (!e) {
-                return 0;
-            }
-            e->protocol = PROTOCOL_MYSQL;
-            e->method = METHOD_STATEMENT_CLOSE;
-            e->payload_size = size;
-            COPY_PAYLOAD(e->payload, size, payload);
-	        cw_bpf_debug("[Enter][Mysql][Send]:thread_id:%d\n",tid);
-            send_event(ctx, e, k.pid, k.fd);
-            return 0;
-        }
-        req->protocol = PROTOCOL_MYSQL;
-    } else if (is_mongo_query(payload, size)) {
-        req->protocol = PROTOCOL_MONGO;
-    } else if (is_rabbitmq_produce(payload, size)) {
-        struct l7_event *e = bpf_map_lookup_elem(&l7_event_heap, &zero);
-        if (!e) {
-            return 0;
-        }
-        e->protocol = PROTOCOL_RABBITMQ;
-        e->method = METHOD_PRODUCE;
-        send_event(ctx, e, k.pid, k.fd);
-        return 0;
-    } else if (nats_method(payload, size) == METHOD_PRODUCE) {
-        struct l7_event *e = bpf_map_lookup_elem(&l7_event_heap, &zero);
-        if (!e) {
-            return 0;
-        }
-        e->protocol = PROTOCOL_NATS;
-        e->method = METHOD_PRODUCE;
-        send_event(ctx, e, k.pid, k.fd);
-        return 0;
-    } else if (is_cassandra_request(payload, size, &k.stream_id)) {
-        req->protocol = PROTOCOL_CASSANDRA;
-    } else if (is_kafka_request(payload, size, &req->request_id)) {
-        req->protocol = PROTOCOL_KAFKA;
-        struct l7_request *prev_req = bpf_map_lookup_elem(&active_l7_requests, &k);
-        if (prev_req && prev_req->protocol == PROTOCOL_KAFKA) {
-            req->ns = prev_req->ns;
-        }
-    } else if (looks_like_http2_frame(payload, size, METHOD_HTTP2_CLIENT_FRAMES)) {
-        struct l7_event *e = bpf_map_lookup_elem(&l7_event_heap, &zero);
-        if (!e) {
-            return 0;
-        }
-        e->protocol = PROTOCOL_HTTP2;
-        e->method = METHOD_HTTP2_CLIENT_FRAMES;
-        e->duration = bpf_ktime_get_ns();
-        e->payload_size = size;
-        COPY_PAYLOAD(e->payload, size, payload);
-        send_event(ctx, e, k.pid, k.fd);
-        return 0;
-    } else if (is_dubbo2_request(payload, size)) {
-        req->protocol = PROTOCOL_DUBBO2;
-    } else if (is_dns_request(payload, size, &k.stream_id)) {
-        req->protocol = PROTOCOL_DNS;
-    }
-
-    if (req->protocol == PROTOCOL_UNKNOWN) {
-        return 0;
-    }
-    if (req->ns == 0) {
-        req->ns = bpf_ktime_get_ns();
-    }
-    COPY_PAYLOAD(req->payload, size, payload);
-    bpf_map_update_elem(&active_l7_requests, &k, req, BPF_NOEXIST);
-    return 0;
-}
-
 static inline __attribute__((__always_inline__))
 int trace_enter_write(void *ctx, __u64 fd, __u16 is_tls, char *buf, __u64 size, __u64 iovlen) {
     __u64 id = bpf_get_current_pid_tgid();

+ 12 - 0
ebpftracer/ebpf/utrace/java/include/java_common.h

@@ -8,8 +8,19 @@
 
 #if defined(__x86_64__)
 #define PT_LEN_REGS(x) (PT_REGS_RBP(x) - 0x10058);
+#define PT_HTTP_RESP_REGS(x) PT_REGS_PARM2(x)
 #elif defined(__aarch64__)
 #define PT_LEN_REGS(x) PT_REGS_SP(x);
+#define PT_HTTP_RESP_REGS(ctx) ({                \
+	unsigned long res = 0;                       \
+    long err = bpf_probe_read(&res, sizeof(res), \
+            (void *) (PT_REGS_SP(ctx) - 48));    \
+    if (err < 0) {                               \
+        bpf_printk("bpf_probe_read failed with return code: %ld\n", err); \
+        res = 0;                                 \
+    }                                            \
+    res;                                         \
+})
 #endif
 
 
@@ -34,6 +45,7 @@
 struct sock_t {
 	u32 size;
 	u32 header_offset_idx;
+	u32 host_offset_idx;
 	u32 end_str_len;
 	void * payload_char_p;
 	void * payload_len_p;

+ 40 - 29
ebpftracer/ebpf/utrace/java/net/client.probe.bpf.c

@@ -66,7 +66,7 @@ static __inline int updataSocket(struct sock_t *map_data_res,void * jbytechar_pt
 	return 0;
 }
 
-static __inline struct apm_span_context* build_sc(struct ebpf_proc_info *proc_info) {
+static __inline struct apm_span_context *build_sc(struct ebpf_proc_info *proc_info, char *host) {
 	u32 key = 0;
 	struct apm_span_context *cw_sc = bpf_map_lookup_elem(&apm_span_context_heap, &key);
 
@@ -77,9 +77,9 @@ static __inline struct apm_span_context* build_sc(struct ebpf_proc_info *proc_in
 	struct apm_span_context *cw_psc = cw_get_parent_tracking_span();
 	if(cw_psc){
 		copy_byte_arrays(cw_psc->trace_id, cw_sc->trace_id, APM_TRACE_ID_SIZE);
-		// new spanid
-		generate_random_bytes(cw_sc->span_id, APM_SPAN_ID_SIZE);
 	}
+	// new spanid
+	generate_random_bytes(cw_sc->span_id, APM_SPAN_ID_SIZE);
 
 	// set host_id/appid
 	u32 k0 = 0;
@@ -101,7 +101,7 @@ static __inline struct apm_span_context* build_sc(struct ebpf_proc_info *proc_in
 	}
 
 	// set assumed_app_id
-	set_assumed_app_id_arrays("111", cw_sc->assumed_app_id, APM_ASSUMED_APP_ID_STRING_SIZE);
+	set_assumed_app_id_arrays(host, cw_sc->assumed_app_id, APM_ASSUMED_APP_ID_STRING_SIZE);
 	cw_save_current_tracking_span(cw_sc);
 	return cw_sc;
 //	char header[CW_STREAM_HEADER_LEN];
@@ -251,17 +251,17 @@ int uprobe_Java_java_net_SocketOutputStream_socketWrite0(struct pt_regs *ctx) {
 
 //	long res;
 	void *len_ptr = 0;
-	cw_bpf_debug("address: len_from_rbp_ptr<0x%lx>\n", len_from_rbp_ptr);
+	cw_bpf_debug("[java client] address: len_from_rbp_ptr<0x%lx>\n", len_from_rbp_ptr);
 //	bpf_printk("len_from_rsp_ptr address: 0x%lx\n", len_from_rsp_ptr);
 
 	bpf_probe_read(&len_ptr, sizeof(len_ptr), (void *) len_from_rbp_ptr);
-	cw_bpf_debug("[len_ptr] before addr<0x%lx>, %d \n", len_from_rbp_ptr, len_ptr);
+	cw_bpf_debug("[java client] [len_ptr] before addr<0x%lx>, %d \n", len_from_rbp_ptr, len_ptr);
 
 //	bpf_probe_read(&len_ptr, sizeof(len_ptr), (void *) len_from_rbp_ptr);
 //	cw_bpf_debug("[len_ptr]after  addr<0x%lx>, %d \n", len_from_rbp_ptr, len_ptr);
 
 	if ( (long) len_ptr != data_count ){
-		cw_bpf_debug("[len_ptr] check error.");
+		cw_bpf_debug("[java client] [len_ptr] check error.");
 		return 0;
 	}
 
@@ -272,7 +272,7 @@ int uprobe_Java_java_net_SocketOutputStream_socketWrite0(struct pt_regs *ctx) {
 		return 0;
 	}
 
-	cw_bpf_debug("[Java] code_type:%d\n", proc_info->code_type);
+	cw_bpf_debug("[java client] code_type:%d\n", proc_info->code_type);
 	void *jbytearray_ptr = NULL;
 	// 1003 是 javaAOT 的
 	if (proc_info->code_type == CodeTypeJavaAot) {
@@ -281,21 +281,21 @@ int uprobe_Java_java_net_SocketOutputStream_socketWrite0(struct pt_regs *ctx) {
 		jbytearray_ptr = (void *) PT_REGS_PARM4(ctx);
 	}
 	
-	cw_bpf_debug("jbytechar_ptr_from_rcx <0x%lx>", jbytearray_ptr);
+	cw_bpf_debug("[java client] jbytechar_ptr_from_rcx <0x%lx>", jbytearray_ptr);
 
 	unsigned long jbytechar_head_ptr;
 	// 读取一级指针
 	long ret = bpf_probe_read_user(&jbytechar_head_ptr, sizeof(unsigned long), (void *) jbytearray_ptr);
-	cw_bpf_debug("[jbytechar_head_ptr] <0x%lx>", jbytechar_head_ptr);
+	cw_bpf_debug("[java client] [jbytechar_head_ptr] <0x%lx>", jbytechar_head_ptr);
 
 	if (ret != 0) {
-		cw_bpf_debug("Failed to read first level ptr: %d\n", ret);
+		cw_bpf_debug("[java client] Failed to read first level ptr: %d\n", ret);
 		return 0;
 	}
 
 	// 检查一级指针是否有效
 	if (!jbytechar_head_ptr) {
-		cw_bpf_debug("First level pointer is null.\n");
+		cw_bpf_debug("[java client] First level pointer is null.\n");
 		return 0;
 	}
 
@@ -303,17 +303,17 @@ int uprobe_Java_java_net_SocketOutputStream_socketWrite0(struct pt_regs *ctx) {
 	int key = 0;
 	struct sock_t *map_data = bpf_map_lookup_elem(&socket_heap, &key);
 	if (!map_data) {
-		cw_bpf_debug("Failed to lookup socket_heap\n");
+		cw_bpf_debug("[java client] Failed to lookup socket_heap\n");
 		return 1;
 	}
 //	__builtin_memset(map_data, 0, sizeof(struct sock_t));
 	// 读取用户空间数据到 map_data->payload
 	void *jbytechar_ptr = (void *) (jbytechar_head_ptr + 16);
-	cw_bpf_debug("[jbytechar_ptr] <0x%lx>", jbytechar_ptr);
+	cw_bpf_debug("[java client] [jbytechar_ptr] <0x%lx>", jbytechar_ptr);
 	long err = bpf_probe_read_user_str(map_data->payload, sizeof(map_data->payload), jbytechar_ptr);
 
 	if (err < 0) {
-		cw_bpf_debug("bpf_probe_read_user failed with return code: %d\n", err);
+		cw_bpf_debug("[java client] bpf_probe_read_user failed with return code: %d\n", err);
 		return 0;
 	}
 	map_data->size = data_count;
@@ -325,15 +325,22 @@ int uprobe_Java_java_net_SocketOutputStream_socketWrite0(struct pt_regs *ctx) {
 		return -1;
 	}
 
+	long host_native = 0x203a74736f480a0dLL; // 小端序下的 "\r\nHost:" ('0d' '0a' '48' '6f' '73' '74' '3a' '20')
 	// 查找 Header 开始位置
 #pragma clang loop unroll(full)
 	for (int i = 0; i < 200 - 5; i++) {
-		if (map_data->payload[i] == '1' &&
-		    map_data->payload[i + 1] == '.' &&
-		    map_data->payload[i + 2] == '1' &&
-		    map_data->payload[i + 3] == '\r' &&
-		    map_data->payload[i + 4] == '\n') {
-			map_data->header_offset_idx = i + 5;
+//		if (map_data->payload[i] == '1' &&
+//		    map_data->payload[i + 1] == '.' &&
+//		    map_data->payload[i + 2] == '1' &&
+//		    map_data->payload[i + 3] == '\r' &&
+//		    map_data->payload[i + 4] == '\n') {
+//			map_data->header_offset_idx = i + 5;
+//			break;
+//		}
+		long data = *(long long *)(map_data->payload + i);
+		if(data == host_native) {
+			map_data->host_offset_idx = i + 8;
+			map_data->header_offset_idx = i + 2;
 			break;
 		}
 	}
@@ -349,26 +356,26 @@ int uprobe_Java_java_net_SocketOutputStream_socketWrite0(struct pt_regs *ctx) {
 		return -1;
 	// 读取完整http
 	bpf_probe_read_user_str(full_payload, JAVA_MAX_BUFFER_SIZE, jbytechar_ptr);
-	cw_bpf_debug("origin full_payload %s\n", full_payload);
+	cw_bpf_debug("[java client]origin full_payload %s\n", full_payload);
 
 
 	// 尾部payload
 	u32 key2 = 1;
 	char *tail_payload = bpf_map_lookup_elem(&large_array_map, &key2);
 	if (!tail_payload) {
-		cw_bpf_debug("header ->end %s\n", tail_payload);
+		cw_bpf_debug("[java client ]header ->end %s\n", tail_payload);
 		return -1;
 	}
 
 	u32 copy_size = L7_IOVEC_BUF_SIZE;
 	long end_str_len = bpf_probe_read_user_str(tail_payload, JAVA_MAX_BUFFER_SIZE,
 	                                           (void *) (jbytechar_ptr + map_data->header_offset_idx));
-	cw_bpf_debug("end_str_len %d\n", end_str_len);
+	cw_bpf_debug("[java client] end_str_len %d\n", end_str_len);
 	map_data->end_str_len = end_str_len;
 	if (end_str_len > copy_size) {
 		u32 chunk = (u32) end_str_len / copy_size;
 		if (chunk > MAX_CHUNK) {
-			cw_bpf_debug("Exceeding the max_chunk:%d need_chunk:%d\n", MAX_CHUNK, chunk);
+			cw_bpf_debug("[java client] Exceeding the max_chunk:%d need_chunk:%d\n", MAX_CHUNK, chunk);
 			return -1;
 		}
 	}
@@ -396,9 +403,13 @@ int uprobe_Java_java_net_SocketOutputStream_socketWrite0(struct pt_regs *ctx) {
 
 
 
+	char host[30];
+	bpf_probe_read(&host,sizeof host,map_data->payload + map_data->host_offset_idx);
+	host[29]='\0';
+	cw_bpf_debug("[java client] http host %s\n", host);
 
 	char tmp_header[CW_STREAM_HEADER_LEN];
-	struct apm_span_context *cw_sc = build_sc(proc_info);
+	struct apm_span_context *cw_sc = build_sc(proc_info, host);
 	if (cw_sc == NULL){
 		return 0;
 	}
@@ -423,7 +434,7 @@ int uprobe_Java_java_net_SocketOutputStream_socketWrite0(struct pt_regs *ctx) {
 
 	long res = bpf_probe_write_user((void *) len_from_rbp_ptr, &new_val, sizeof(new_val));
 	if (res < 0) {
-		cw_bpf_debug("Failed to write value to user address: %p, error: %ld\n", len_from_rbp_ptr, res);
+		cw_bpf_debug("[java client] Failed to write value to user address: %p, error: %ld\n", len_from_rbp_ptr, res);
 //		cw_bpf_debug("Failed to write len to user address: %p\n", len_from_rbp_ptr);
 		return -1;
 	}
@@ -454,13 +465,13 @@ PROGUP(java_update_header)(struct pt_regs *ctx) {
 	u32 k1 = 1;
 	char *tail_payload = bpf_map_lookup_elem(&large_array_map, &k1);
 	if (!tail_payload) {
-		cw_bpf_debug("header ->end %s\n", tail_payload);
+		cw_bpf_debug("[java client] header ->end %s\n", tail_payload);
 		return -1;
 	}
 
 	struct sock_t *map_data = bpf_map_lookup_elem(&socket_heap, &k0);
 	if (!map_data) {
-		cw_bpf_debug("Failed to lookup socket_heap\n");
+		cw_bpf_debug("[java client] Failed to lookup socket_heap\n");
 		return -1;
 	}
 

+ 1 - 4
ebpftracer/ebpf/utrace/java/net/server.probe.bpf.c

@@ -157,7 +157,7 @@ int uprobe_ret_Java_sun_nio_ch_FileDispatcherImpl_read0(struct pt_regs *ctx) {
 //	cw_bpf_debug("enter the ret uprobe_Java_sun_nio_ch_FileDispatcherImpl_read0\n");
 	unsigned long jhttpdata_ptr;
 	// jhttpdata_ptr = (ctx)->rsi;
-	jhttpdata_ptr = PT_REGS_PARM2(ctx);
+	jhttpdata_ptr = PT_HTTP_RESP_REGS(ctx);
 //	cw_bpf_debug("enter rsi is %llx.\n", jhttpdata_ptr);
 	
 	//x/s addr
@@ -193,21 +193,18 @@ int uprobe_ret_Java_sun_nio_ch_FileDispatcherImpl_read0(struct pt_regs *ctx) {
 
 
 //	bpf_tail_call(ctx, &jmp_table1, 0);
-	bpf_printk("java tail call\n");
 	bpf_tail_call(ctx, &NAME(progs_jmp_up_map), PROG_DATA_SAVE_UP_IDX);
 	return 0;
 }
 
 // bpf_prog_up__save_sc
  PROGUP(java_save_sc)(struct pt_regs *ctx) {
-	 bpf_printk("tail call save_sc\n");
 	 u32 key = 0;
 
 	 struct sock_t *map_data = bpf_map_lookup_elem(&socket_heap, &key);
 	 if (!map_data) {
 		 return 0;
 	 }
-	 bpf_printk("tail call save_sc %s\n", map_data->payload);
 
 	 struct apm_span_context *cw_parent_span_context = bpf_map_lookup_elem(&apm_span_context_heap, &key);
 	 if (cw_parent_span_context == NULL) {

+ 77 - 40
ebpftracer/jvm.go

@@ -3,6 +3,7 @@ package ebpftracer
 import (
 	"errors"
 	"github.com/coroot/coroot-node-agent/common"
+	"github.com/coroot/coroot-node-agent/ebpftracer/tracer/inject"
 	"io/ioutil"
 	"runtime"
 	"strings"
@@ -11,10 +12,8 @@ import (
 	"fmt"
 	"path/filepath"
 
-	"github.com/coroot/coroot-node-agent/proc"
-	"github.com/coroot/coroot-node-agent/utils"
-
 	"github.com/cilium/ebpf/link"
+	"github.com/coroot/coroot-node-agent/proc"
 	"golang.org/x/arch/arm64/arm64asm"
 	"golang.org/x/arch/x86/x86asm"
 )
@@ -25,9 +24,9 @@ const (
 	symbolsocketRead0 = "Java_sun_nio_ch_FileDispatcherImpl_read0"
 )
 
-func (t *Tracer) AttachJavaNioReadUprobes(pid uint32, insID utils.ID, codeType common.CodeType) []link.Link {
-	if t.disableL7Tracing {
-		return nil
+func (t *Tracer) AttachJavaNioReadUprobes(pid uint32, codeType common.CodeType) ([]link.Link, error) {
+	if t.DisableL7Tracing() {
+		return nil, nil
 	}
 	var links []link.Link
 	var bpath = ""
@@ -41,38 +40,37 @@ func (t *Tracer) AttachJavaNioReadUprobes(pid uint32, insID utils.ID, codeType c
 
 		bpath = getSoPath(pid, "libnio.so")
 		if bpath == "" {
-			fmt.Println("can,t find the nio.so")
-			return nil
+			return nil, errors.New("can not find nio.so")
 		}
 	}
 
 	fmt.Println("find the nio.so path is ", bpath)
 	ex, err := link.OpenExecutable(bpath)
 	if err != nil {
-		return nil
+		return nil, err
 	}
 	ef, err := elf.Open(bpath)
 	if err != nil {
-		return nil
+		return nil, err
 		//PID:    int(pid),
 	}
 	defer ef.Close()
 
-	symbols, err := ef.Symbols()
+	symbols, err := ef.DynamicSymbols()
 	if err != nil {
 		if errors.Is(err, elf.ErrNoSymbols) {
-			return nil
+			return nil, err
 		}
-		return nil
+		return nil, err
 	}
 
 	textSection := ef.Section(".text")
 	if textSection == nil {
-		return nil
+		return nil, errors.New("can not find .text section")
 	}
 	textSectionData, err := textSection.Data()
 	if err != nil {
-		return nil
+		return nil, err
 	}
 	textSectionLen := uint64(len(textSectionData) - 1)
 
@@ -115,13 +113,12 @@ func (t *Tracer) AttachJavaNioReadUprobes(pid uint32, insID utils.ID, codeType c
 			sBytes := textSectionData[sStart:sEnd]
 			returnOffsets := getCallNextMoveOffsets(ef.Machine, sBytes)
 			if len(returnOffsets) == 0 {
-				return nil
+				return nil, fmt.Errorf("failed to attach uprobe_ret_Java_sun_nio_ch_FileDispatcherImpl_read0 uprobe")
 			}
 			for _, offset := range returnOffsets {
 				l, err := ex.Uprobe(s.Name, t.uprobes["uprobe_ret_Java_sun_nio_ch_FileDispatcherImpl_read0"], &link.UprobeOptions{Address: address, Offset: uint64(offset), PID: int(pid)})
 				if err != nil {
-					fmt.Println("failed to attach uprobe_ret_Java_sun_nio_ch_FileDispatcherImpl_read0 uprobe")
-					return nil
+					return nil, fmt.Errorf("failed to attach uprobe_ret_Java_sun_nio_ch_FileDispatcherImpl_read0 uprobe")
 				}
 				links = append(links, l)
 			}
@@ -129,45 +126,85 @@ func (t *Tracer) AttachJavaNioReadUprobes(pid uint32, insID utils.ID, codeType c
 	}
 
 	if len(links) == 0 {
-		return nil
+		return nil, fmt.Errorf("no links found for %s", bpath)
 	}
-	fmt.Println("jvm uprobes attached, pid is ", pid)
-	return links
+	fmt.Println("[jvm] libnio attached, pid is ", pid)
+	return links, nil
 }
 
-func (t *Tracer) AttachJavaNetWriteUprobes(pid uint32, insID utils.ID) []link.Link {
-	if t.disableL7Tracing {
-		return nil
+func (t *Tracer) AttachJavaNetWriteUprobes(pid uint32) ([]link.Link, error) {
+	if t.DisableL7Tracing() {
+		return nil, nil
+	}
+	// 关闭横向串联
+	if t.DisableE2ETracing() {
+		return nil, nil
+	}
+	//inject
+	originFunc := "Java_java_net_SocketOutputStream_socketWrite0"
+
+	uProbeData := inject.UprobeData{
+		Offset:  53,
+		Func:    originFunc,
+		ELFPath: "/root/cwlibnet.so",
 	}
-	var libnetSo = "/data/roger/graalvm/lib/libnet.so"
-	var sys = "Java_java_net_SocketOutputStream_socketWrite0"
-	var offset = 53
+
 	if runtime.GOARCH == "arm64" {
-		libnetSo = "/root/cwlibnet.so"
-		sys = "CW_Java_java_net_SocketOutputStream_socketWrite0"
-		offset = 0
+		uProbeData = inject.UprobeData{
+			Offset:  8,
+			Func:    "CW_" + originFunc,
+			ELFPath: "/root/cwlibnet.so",
+		}
 	}
+
+	jvmInjector := &inject.JvmInjector{
+		Pid: int(pid),
+		ReleaseLibNetInfo: inject.LibNetInfo{
+			LibName: "libnet.so",
+			FuncSymbol: inject.InstInfo{
+				SymName: originFunc,
+			},
+		},
+		DebugLibNetInfo: inject.LibNetInfo{
+			// TODO 根据版本设置
+			LibName: filepath.Base(uProbeData.ELFPath),
+			// TODO 根据版本设置
+			LibPath: uProbeData.ELFPath,
+			FuncSymbol: inject.InstInfo{
+				SymName: uProbeData.Func,
+			},
+		},
+		RecodeInfo: inject.LibNetInfo{FuncSymbol: inject.InstInfo{SymName: "CW_RECODE_" + originFunc}},
+		Uprobe:     uProbeData,
+	}
+
+	err := inject.JvmInject(jvmInjector)
+	fmt.Println("AttachJavaNetWriteUprobes:", err)
+	if err != nil {
+		return nil, err
+	}
+
 	var links []link.Link
-	ex, err := link.OpenExecutable(libnetSo)
+	ex, err := link.OpenExecutable(jvmInjector.Uprobe.ELFPath)
 	if err != nil {
-		return nil
+		return nil, err
 	}
 	opt := link.UprobeOptions{
-		Offset: uint64(offset),
+		Offset: uint64(jvmInjector.Uprobe.Offset),
 		PID:    int(pid),
 	}
-	upread02, err := ex.Uprobe(sys, t.uprobes["uprobe_Java_java_net_SocketOutputStream_socketWrite0"], &opt)
+	upread02, err := ex.Uprobe(jvmInjector.Uprobe.Func, t.uprobes["uprobe_Java_java_net_SocketOutputStream_socketWrite0"], &opt)
 	if err != nil {
-		return nil
+		return nil, err
 	}
+
 	links = append(links, upread02)
 
 	if len(links) == 0 {
-		return nil
+		return nil, errors.New("can not find uprobe_Java_net_SocketOutputStream_socketWrite0")
 	}
-	fmt.Println("jvm client uprobes attached", pid)
-
-	return links
+	fmt.Println("[jvm] libnet attached", pid)
+	return links, nil
 }
 
 func getCallNextMoveOffsets(machine elf.Machine, instructions []byte) []int {
@@ -213,7 +250,7 @@ func getSoPath(pid uint32, soname string) string {
 	// 读取maps文件内容
 	mapsData, err := ioutil.ReadFile(mapsPath)
 	if err != nil {
-		fmt.Println("无法读取maps文件")
+		fmt.Println("lookup so error.")
 		return ""
 	}
 

+ 2 - 2
ebpftracer/netcore.go

@@ -165,7 +165,7 @@ func (t *Tracer) getFunctionOffsetDBG(libPath, functionName string) (elf.Symbol,
 }
 
 func (t *Tracer) AttachNetCoreNetReadUprobes(pid uint32, insID utils.ID) []link.Link {
-	if t.disableL7Tracing {
+	if t.DisableL7Tracing() {
 		return nil
 	}
 
@@ -191,7 +191,7 @@ func (t *Tracer) AttachNetCoreNetReadUprobes(pid uint32, insID utils.ID) []link.
 }
 
 func (t *Tracer) AttachNetCoreNetWriteUprobes(pid uint32, insID utils.ID) []link.Link {
-	if t.disableL7Tracing {
+	if t.DisableL7Tracing() {
 		return nil
 	}
 	//

+ 5 - 2
ebpftracer/tls.go

@@ -37,7 +37,7 @@ var (
 )
 
 func (t *Tracer) AttachOpenSslUprobes(pid uint32) []link.Link {
-	if t.disableL7Tracing {
+	if t.DisableL7Tracing() {
 		return nil
 	}
 	libPath, version := getSslLibPathAndVersion(pid)
@@ -116,7 +116,7 @@ func (t *Tracer) AttachOpenSslUprobes(pid uint32) []link.Link {
 }
 
 func (t *Tracer) AttachGoTlsUprobes(pid uint32, insID utils.ID, codeType uint16) []link.Link {
-	if t.disableL7Tracing {
+	if t.DisableL7Tracing() {
 		return nil
 	}
 
@@ -341,6 +341,9 @@ func (t *Tracer) AttachGoTlsUprobes(pid uint32, insID utils.ID, codeType uint16)
 			}
 
 		case goTransport:
+			if t.DisableE2ETracing() {
+				continue
+			}
 			l, err := exe.Uprobe(s.Name, t.uprobes["uprobe_Transport_roundTrip"], &link.UprobeOptions{Address: address})
 			if err != nil {
 				log("failed to attach write_enter uprobe", err)

+ 36 - 13
ebpftracer/tracer.go

@@ -124,8 +124,10 @@ const (
 )
 
 type Tracer struct {
-	kernelVersion    string
-	disableL7Tracing bool
+	kernelVersion       string
+	disableL7Tracing    bool
+	disableE2ETracing   bool
+	disableStackTracing bool
 
 	collection *ebpf.Collection
 	readers    map[string]*perf.Reader
@@ -136,13 +138,21 @@ type Tracer struct {
 	UprobesMap map[string]tracer.Uprobe
 }
 
-func NewTracer(kernelVersion string, disableL7Tracing bool) *Tracer {
+func NewTracer(kernelVersion string, disableL7Tracing, disableE2ETracing, disableStackTracing bool) *Tracer {
 	if disableL7Tracing {
 		klog.Infoln("L7 tracing is disabled")
 	}
+	if disableE2ETracing {
+		klog.Infoln("L7 tracing is disabled")
+	}
+	if disableStackTracing {
+		klog.Infoln("L7 stack is disabled")
+	}
 	return &Tracer{
-		kernelVersion:    kernelVersion,
-		disableL7Tracing: disableL7Tracing,
+		kernelVersion:       kernelVersion,
+		disableL7Tracing:    disableL7Tracing,
+		disableE2ETracing:   disableE2ETracing,
+		disableStackTracing: disableStackTracing,
 
 		readers: map[string]*perf.Reader{},
 		uprobes: map[string]*ebpf.Program{},
@@ -267,7 +277,7 @@ func (t *Tracer) ebpf(ch chan<- Event) error {
 	fmt.Println(len(collectionSpec.Programs))
 	fmt.Println(len(c.Programs))
 	tracer.MapInsert(c)
-	if !t.disableL7Tracing {
+	if !t.DisableL7Tracing() {
 		perfMaps = append(perfMaps, perfMap{name: "l7_events", typ: perfMapTypeL7Events, perCPUBufferSizePages: 32})
 	}
 	perfMaps = append(perfMaps, perfMap{name: tracer.MAP_PERF_SOCKET_DATA_NAME, typ: perfMapTypeSocketEvents, perCPUBufferSizePages: 64})
@@ -291,7 +301,7 @@ func (t *Tracer) ebpf(ch chan<- Event) error {
 	for _, programSpec := range collectionSpec.Programs {
 		program := t.collection.Programs[programSpec.Name]
 		fmt.Println("programSpecprogramSpec:--:", programSpec.Name, programSpec.SectionName, programSpec.Type)
-		if t.disableL7Tracing {
+		if t.DisableL7Tracing() {
 			switch programSpec.Name {
 			case "sys_enter_writev", "sys_enter_write", "sys_enter_sendto", "sys_enter_sendmsg", "sys_enter_sendmmsg":
 				continue
@@ -704,15 +714,15 @@ func ipPort(ip [16]byte, port uint16) netaddr.IPPort {
 }
 
 func (t *Tracer) InitKProcInfo(pid uint32, insID utils.ID, codeType uint16) error {
-
+	var err error
 	info := tracer.EbpfProcInfo{}
 	info.InstanceId = insID.HashtVal
 	// 获取内存地址
-	allocDetails, err := tracer.Allocate(int(pid))
-	if err == nil && allocDetails != nil {
-		info.StartAddr = allocDetails.StartAddr
-		info.EndAddr = allocDetails.EndAddr
-	}
+	//allocDetails, err := tracer.Allocate(int(pid))
+	//if err == nil && allocDetails != nil {
+	//	info.StartAddr = allocDetails.StartAddr
+	//	info.EndAddr = allocDetails.EndAddr
+	//}
 
 	info.CodeType = codeType
 	//klog.Infoln("Major:", major)
@@ -727,3 +737,16 @@ func (t *Tracer) InitKProcInfo(pid uint32, insID utils.ID, codeType uint16) erro
 	}
 	return err
 }
+
+// TODO check language
+func (t *Tracer) DisableL7Tracing() bool {
+	return t.disableL7Tracing
+}
+
+func (t *Tracer) DisableE2ETracing() bool {
+	return t.disableE2ETracing
+}
+
+func (t *Tracer) DisableStackTracing() bool {
+	return t.disableStackTracing
+}

+ 19 - 6
ebpftracer/tracer/inject/inject_linux_amd64.go

@@ -51,22 +51,30 @@ type LibNetInfo struct {
 	InnerSymbol InnerSymbolInfo
 }
 
+type UprobeData struct {
+	Offset  int
+	Func    string
+	ELFPath string
+}
+
 type JvmInjector struct {
 	Pid               int
 	ReleaseLibNetInfo LibNetInfo
 	DebugLibNetInfo   LibNetInfo
+	RecodeInfo        LibNetInfo
 	// 原方法首个指令不为jmp | ReleaseLibNetInfo 读取无异常
 	PreCheck struct {
 		NeedInjectionCheck bool // 原指令校验 true表示可以继续执行注入
 		LoadingCheck       bool // true 表示加载成功
 		IoFdCheck          bool // fd地址校验
 		NetSendFuncCheck   bool // netsend校验
-		EbpfCanInjection   bool
+		EbpfCanInjection   bool // 满足则注入ebpf
 	}
 	AfterCheck struct {
 		IoFdCheck        bool
 		NetSendFuncCheck bool
 	}
+	Uprobe UprobeData
 }
 
 func (j *JvmInjector) findReleaseAddressInfoFromMem() error {
@@ -98,7 +106,9 @@ func (j *JvmInjector) findReleaseAddressInfoFromMem() error {
 		}
 		if pc == 0 && inst.Op == x86asm.JMP {
 			// 已经被修改过的首指令
-			return fmt.Errorf("Inst already modified. <%s>", x86asm.IntelSyntax(inst, 0, nil))
+			j.PreCheck.EbpfCanInjection = true
+			fmt.Printf("Inst already modified. <%s>\n", x86asm.IntelSyntax(inst, 0, nil))
+			return nil
 		}
 		if pc == 0 {
 			j.ReleaseLibNetInfo.FuncSymbol.PC = currentData.PC
@@ -111,6 +121,7 @@ func (j *JvmInjector) findReleaseAddressInfoFromMem() error {
 				if dst.Base == x86asm.RBP {
 					if src, okSrc := inst.Args[1].(x86asm.Reg); okSrc {
 						if src == x86asm.R9L {
+							// debug so
 							j.PreCheck.EbpfCanInjection = true
 							return fmt.Errorf("MOV from register %v to memory %v\n", src, dst)
 						}
@@ -558,12 +569,12 @@ func (j *JvmInjector) findDebugFuncContextFromLibPath() error {
 	}
 	fmt.Printf("Actual memory address of %s at base 0x%x: 0x%x\n", functionName, baseAddress, j.DebugLibNetInfo.FuncSymbol.SymAddr)
 
-	callAddress, err := j.findDebugAddressInfoFromMem()
-	if err != nil || callAddress == 0 {
+	_, err = j.findDebugAddressInfoFromMem()
+	if err != nil {
 		log.Printf("Error finding first CALL instuction: %v", err)
 		return err
 	}
-	fmt.Printf("First CALL instuction o1f %s at base 0x%x: 0x%x\n", functionName, baseAddress, callAddress)
+	fmt.Printf("First CALL instuction o1f %s at base 0x%x\n", functionName, baseAddress)
 	return nil
 }
 
@@ -739,13 +750,15 @@ func JvmInject(jvmInjector *JvmInjector) error {
 	err = jvmInjector.findReleaseFuncContextFromLibPath()
 
 	// Debug版本无需修改寄存器
+	// 已经加载so并指令修改正确的
 	if jvmInjector.PreCheck.EbpfCanInjection {
-		fmt.Println("Debug version loaded.")
+		fmt.Println("eBPF can injection.")
 		return nil
 	}
 
 	if err != nil {
 		log.Fatalf("Error message during release phase: %v", err)
+		return err
 	}
 
 	// 原指令校验通过

+ 97 - 153
ebpftracer/tracer/inject/inject_linux_arm64.go

@@ -11,11 +11,11 @@ import "C"
 
 import (
 	"bufio"
+	"bytes"
 	"debug/elf"
 	"fmt"
 	"golang.org/x/arch/arm64/arm64asm"
 	"golang.org/x/arch/x86/x86asm"
-	"log"
 	"os"
 	"strings"
 	"syscall"
@@ -64,10 +64,17 @@ type LibNetInfo struct {
 	InnerSymbol InnerSymbolInfo
 }
 
+type UprobeData struct {
+	Offset  int
+	Func    string
+	ELFPath string
+}
+
 type JvmInjector struct {
 	Pid               int
 	ReleaseLibNetInfo LibNetInfo
 	DebugLibNetInfo   LibNetInfo
+	RecodeInfo        LibNetInfo
 	// 原方法首个指令不为jmp | ReleaseLibNetInfo 读取无异常
 	PreCheck struct {
 		NeedInjectionCheck bool // 原指令校验 true表示可以继续执行注入
@@ -80,6 +87,7 @@ type JvmInjector struct {
 		IoFdCheck        bool
 		NetSendFuncCheck bool
 	}
+	Uprobe UprobeData
 }
 
 func (j *JvmInjector) checkEnc(code []byte, start, len uint64, enc uint32) error {
@@ -102,12 +110,31 @@ func (j *JvmInjector) findReleaseAddressInfoFromMem() error {
 	if err != nil {
 		return err
 	}
-	//pc := uint64(0)
-	//add := 0
-	//bl := 0
-	//callCount := 0
-	//preContext := InstInfo{}
 	fmt.Println(j.ReleaseLibNetInfo.FuncSymbol.SymSize)
+	// cwso是否载入,载入则从recode判断指令
+	baseAddress, libPath, err := j.findLibBaseFromProcMaps(j.DebugLibNetInfo.LibName)
+	if err == nil {
+		j.PreCheck.LoadingCheck = true
+		fmt.Println("so already loaded check enc...")
+		// 获取recode地址
+		fmt.Println(baseAddress)
+
+		recodeFunctionSym, err := j.getFunctionOffset(libPath, j.RecodeInfo.FuncSymbol.SymName)
+		if err != nil {
+			return err
+		}
+		j.RecodeInfo.FuncSymbol.SymAddr = baseAddress + recodeFunctionSym.Value
+		recode, err := j.readMemory(j.RecodeInfo.FuncSymbol.SymAddr, 20)
+		if err != nil {
+			return err
+		}
+		if bytes.Equal(recode, code[56:56+20]) {
+			j.PreCheck.EbpfCanInjection = true
+			fmt.Println("successful...")
+			return nil
+		}
+		fmt.Println("so already loaded. check failed.")
+	}
 	/*
 		0x0000fffbdc0ef24c <+56>:	str	x2, [x6,#120]
 		0x0000fffbdc0ef250 <+60>:	str	x3, [x29,#96]
@@ -136,113 +163,6 @@ func (j *JvmInjector) findReleaseAddressInfoFromMem() error {
 		return err
 	}
 
-	/*	for pc < j.ReleaseLibNetInfo.FuncSymbol.SymSize {
-
-			inst, err := arm64asm.Decode(code[pc:])
-			if err != nil {
-				fmt.Printf("Decode error at offset 0x%x: %v\n", pc, err)
-				pc++ // Skip this byte and try to decode again
-				continue
-			}
-			fmt.Printf("Decoded instuction at 0x%x: %v\n", funcAbsAddress+pc, inst)
-			//fmt.Printf("Decoded x86 instuction at 0x%x: %v\n", funcAbsAddress+pc, x86asm.IntelSyntax(inst, 0, nil))
-			//fmt.Printf("Decoded GNU instuction at 0x%x: %v\n", funcAbsAddress+pc, x86asm.GNUSyntax(Inst, 0, nil))
-			currentData := InstInfo{
-				PC:      pc,
-				SymAddr: funcAbsAddress + pc,
-				Inst:    inst,
-				//IntelInst: x86asm.IntelSyntax(inst, 0, nil),
-			}
-			if pc == 0 && (inst.Op == arm64asm.B || inst.Op == arm64asm.BL) {
-				// 已经被修改过的首指令
-				return fmt.Errorf("Inst already modified. <%s>", arm64asm.GNUSyntax(inst))
-			}
-			if pc == 0 {
-				j.ReleaseLibNetInfo.FuncSymbol.PC = currentData.PC
-				j.ReleaseLibNetInfo.FuncSymbol.Inst = currentData.Inst
-				j.ReleaseLibNetInfo.FuncSymbol.OriginInst = currentData.Inst
-			}
-
-			if pc == 88 && inst.Op == arm64asm.STR {
-				fmt.Println(inst.Args[0])
-				fmt.Println(inst.Args[1], inst.Args[1].(arm64asm.MemImmediate).Base, inst.Args[1].(arm64asm.MemImmediate).Mode)
-				fmt.Println("inst.Args[0]", inst.Args[0])
-				fmt.Println("arm64asm.W5", arm64asm.W5)
-				fmt.Println(inst.Args[0] == arm64asm.W5)
-				if inst.Args[0].String() == arm64asm.W5.String() {
-					if src, okSrc := inst.Args[1].(arm64asm.MemImmediate); okSrc {
-						base := arm64asm.Reg(src.Base)
-						if base == arm64asm.X0 {
-							j.PreCheck.EbpfCanInjection = true
-							return nil
-						}
-					}
-				}
-			}
-
-			// IO_fd_fdID
-			if inst.Op == arm64asm.ADD {
-				if add == 1 && preContext.Inst.Op == arm64asm.ADRP && inst.Args[0].String() == arm64asm.X2.String() {
-					fmt.Println("inst.Args[0]", inst.Args[0])
-					fmt.Println("arm64asm.X2", arm64asm.X2)
-
-					if pcRelAddr, okAddr := preContext.Inst.Args[1].(arm64asm.PCRel); okAddr {
-
-						fmt.Println("preContext.Inst", preContext.Inst)
-						fmt.Println("preContext.Inst.args", preContext.Inst.Args)
-						// 掩码:高位全1,低12位为0
-						clearedAddress := preContext.SymAddr & 0xFFFFFFFFFFFFF000
-
-						fmt.Printf("preContext.Inst.args %d \n", clearedAddress+uint64(pcRelAddr))
-						fmt.Println("inst", inst)
-						fmt.Println("inst.Args", inst.Args[2].(arm64asm.ImmShift))
-
-						// 去掉前缀 "#",并提取十六进制部分
-						hexStr := strings.TrimPrefix(inst.Args[2].(arm64asm.ImmShift).String(), "#0x")
-						// 将十六进制字符串转换为整数
-						decimalValue, err := strconv.ParseUint(hexStr, 16, 32)
-						if err != nil {
-							return fmt.Errorf("Error parsing hex string: %v\n", err)
-						}
-						// 打印十进制值
-						fmt.Printf("Decimal value: %d\n", decimalValue)
-						fmt.Printf("preContext.Inst.args %d \n", clearedAddress+uint64(pcRelAddr)+decimalValue)
-						targetAddress := clearedAddress + uint64(pcRelAddr) + decimalValue
-						releaseFuncSym.IO_fd_fdID_ADRP = preContext
-						releaseFuncSym.IO_fd_fdID_ADRP.SymName = "<IO_fd_fdID ADRP>(Release)"
-						releaseFuncSym.IO_fd_fdID_ADRP.TargetAddr = targetAddress
-
-						releaseFuncSym.IO_fd_fdID_ADD = currentData
-						releaseFuncSym.IO_fd_fdID_ADD.SymName = "<IO_fd_fdID ADD>(Release)"
-						releaseFuncSym.IO_fd_fdID_ADD.TargetEnc = currentData.Inst.Enc
-					}
-				}
-				add++
-			}
-
-			if inst.Op == arm64asm.BL {
-
-				//offset = ( target- pc ) / 4
-				// enc = offset +0x94000000
-
-				if bl == 0 {
-					if pcRelAddr, okAddr := inst.Args[0].(arm64asm.PCRel); okAddr {
-						releaseFuncSym.NET_Send = currentData
-						releaseFuncSym.NET_Send.SymName = "<NET_Send>(Release)"
-						targetAddress := currentData.SymAddr + uint64(pcRelAddr)
-						releaseFuncSym.NET_Send.TargetAddr = targetAddress
-					}
-				}
-				bl++
-			}
-			preContext = InstInfo{
-				PC:      pc,
-				SymAddr: funcAbsAddress + pc,
-				Inst:    inst,
-			}
-			pc += 4
-		}
-	*/
 	j.ReleaseLibNetInfo.InnerSymbol = releaseFuncSym
 	j.ReleaseLibNetInfo.FuncSymbol.OriginCode = code[0:4]
 	return nil
@@ -550,7 +470,6 @@ func (j *JvmInjector) getFunctionOffset(libPath, functionName string) (elf.Symbo
 
 	for _, sym := range symbols {
 		if sym.Name == functionName {
-			fmt.Println("size:", sym.Size)
 			return sym, nil
 		}
 	}
@@ -579,8 +498,7 @@ func (j *JvmInjector) findReleaseFuncContextFromLibPath() error {
 	j.ReleaseLibNetInfo.LibPath = libPath
 	libName := j.ReleaseLibNetInfo.LibName
 	if err != nil {
-		log.Fatalf("Error finding base addresses: %v", err)
-		return err
+		return fmt.Errorf("Error finding base addresses: %v", err)
 	}
 	fmt.Printf("Base address of (%s)%s: %x\n", "", libName, baseAddress)
 
@@ -591,8 +509,7 @@ func (j *JvmInjector) findReleaseFuncContextFromLibPath() error {
 	j.ReleaseLibNetInfo.FuncSymbol.SymAddr = baseAddress + functionSym.Value
 	j.ReleaseLibNetInfo.FuncSymbol.SymSize = functionSym.Size
 	if err != nil {
-		log.Fatalf("Error getting function offset: %v", err)
-		return err
+		return fmt.Errorf("Error getting function offset: %v", err)
 	}
 	fmt.Printf("Actual memory address of %s at base 0x%x: 0x%x\n", functionName, baseAddress, j.ReleaseLibNetInfo.FuncSymbol.SymAddr)
 	err = j.findReleaseAddressInfoFromMem()
@@ -615,8 +532,7 @@ func (j *JvmInjector) findDebugFuncContextFromLibPath() error {
 	functionName := j.DebugLibNetInfo.FuncSymbol.SymName
 	j.DebugLibNetInfo.LibPath = libPath
 	if err != nil {
-		log.Fatalf("Error finding base addresses: %v", err)
-		return err
+		return fmt.Errorf("Error finding base addresses: %v", err)
 	}
 
 	// 获取函数的偏移量
@@ -626,17 +542,22 @@ func (j *JvmInjector) findDebugFuncContextFromLibPath() error {
 	j.DebugLibNetInfo.FuncSymbol.SymSize = functionSym.Size
 
 	if err != nil {
-		log.Fatalf("Error getting function offset: %v", err)
-		return err
+		return fmt.Errorf("Error getting function offset: %v", err)
 	}
-	fmt.Printf("Actual memory address of %s at base 0x%x: 0x%x\n", functionName, baseAddress, j.DebugLibNetInfo.FuncSymbol.SymAddr)
+
+	// 计算recode内存地址
+	recodeFunctionSym, err := j.getFunctionOffset(libPath, j.RecodeInfo.FuncSymbol.SymName)
+	j.RecodeInfo.FuncSymbol.SymAddr = baseAddress + recodeFunctionSym.Value
+	if err != nil {
+		return fmt.Errorf("Error getting function offset: %v", err)
+	}
+	fmt.Printf("DEBUG Actual memory address of %s at base 0x%x: 0x%x\n", functionName, baseAddress, j.DebugLibNetInfo.FuncSymbol.SymAddr)
+	fmt.Printf("DEBUG Actual memory address of %s at base 0x%x: 0x%x\n", j.RecodeInfo.FuncSymbol.SymName, baseAddress, j.RecodeInfo.FuncSymbol.SymAddr)
 
 	_, err = j.findDebugAddressInfoFromMem()
 	if err != nil {
-		//log.Printf("Error finding first CALL instuction: %v", err)
 		return err
 	}
-	//fmt.Printf("First CALL instuction o1f %s at base 0x%x: 0x%x\n", functionName, baseAddress, callAddress)
 	return nil
 }
 
@@ -798,14 +719,14 @@ func buildNopEnc(pid int, nopAddr, originAddr uintptr) error {
 	return nil
 }
 
-func setEncByAddr(pid int, soAddr, originAddr uintptr) error {
+func setEncByAddr(pid int, currentAddr, targetAddr uintptr) error {
 	// 获取目标地址处的数据
-	originalData, err := readData(pid, originAddr)
+	originalData, err := readData(pid, targetAddr)
 	if err != nil {
 		return err
 	}
 	// 更新数据中的目标偏移
-	err = writeData(pid, soAddr, originalData)
+	err = writeData(pid, currentAddr, originalData)
 	if err != nil {
 		return err
 	}
@@ -829,17 +750,19 @@ set *(unsigned int*)($origin+68) = 0xf2e00012
 # blr x18
 set *(unsigned int*)($origin+72) = 0xd63f0240
 */
-func modifyOriginEnc(pid int, nopAddr uint64, origin uintptr) error {
+func modifyOriginEnc(pid int, nopAddr uint64, origin uintptr, recode uintptr) error {
+	var err error
+
 	// Original 64-bit address
 	blrAddr := nopAddr
-	// 拆分四段地址
+	// 拆分四段16位地址
 	// Extract the 16-bit chunks
 	part1 := blrAddr & 0xFFFF         // Lower 16 bits
 	part2 := (blrAddr >> 16) & 0xFFFF // Next 16 bits
 	part3 := (blrAddr >> 32) & 0xFFFF // Upper 16 bits
 	part4 := (blrAddr >> 48) & 0xFFFF // MAXUpper 16 bits
 
-	err := setEnc(pid, origin+56, buildArm64Enc(part1, OFFSET_0))
+	err = setEnc(pid, origin+56, buildArm64Enc(part1, OFFSET_0))
 	if err != nil {
 		return err
 	}
@@ -860,6 +783,29 @@ func modifyOriginEnc(pid int, nopAddr uint64, origin uintptr) error {
 	if err != nil {
 		return err
 	}
+
+	// save change
+	err = setEncByAddr(pid, recode, origin+56)
+	if err != nil {
+		return err
+	}
+	err = setEncByAddr(pid, recode+4, origin+60)
+	if err != nil {
+		return err
+	}
+	err = setEncByAddr(pid, recode+8, origin+64)
+	if err != nil {
+		return err
+	}
+	err = setEncByAddr(pid, recode+12, origin+68)
+	if err != nil {
+		return err
+	}
+	err = setEncByAddr(pid, recode+16, origin+72)
+	if err != nil {
+		return err
+	}
+
 	fmt.Printf("# blr x18 \nset *(unsigned int*)($origin+%d) = 0x%08x\n", PC_START+4*4, 0xD63F0240)
 	return nil
 }
@@ -973,13 +919,14 @@ func restoreOriginalInstructions(pid int, addr uintptr, instructions []byte) err
 func JvmInject(jvmInjector *JvmInjector) error {
 	jvmInjector.DebugLibNetInfo.FuncSymbol.SymName = "CW_Java_java_net_SocketOutputStream_socketWrite0"
 	pid := jvmInjector.Pid
+
 	var err error
 	err = jvmInjector.findReleaseFuncContextFromLibPath()
 
 	fmt.Println(err)
-	// Debug版本无需修改寄存器 TODO 直接使用原函数 需要在ebpf层适配
+	// Debug版本无需修改寄存器  TODO 直接使用原函数 需要在ebpf层适配
+	// 已经加载so并指令修改正确的
 	if jvmInjector.PreCheck.EbpfCanInjection {
-		fmt.Println("Debug version loaded.")
 		return nil
 	}
 
@@ -991,7 +938,9 @@ func JvmInject(jvmInjector *JvmInjector) error {
 	if !jvmInjector.PreCheck.NeedInjectionCheck {
 		return err
 	}
+
 	printCodeData(jvmInjector.ReleaseLibNetInfo)
+
 	_type, _, err := jvmInjector.findLibBaseFromProcMaps(jvmInjector.DebugLibNetInfo.LibName)
 	if err != nil {
 		// load so
@@ -1004,36 +953,31 @@ func JvmInject(jvmInjector *JvmInjector) error {
 			}
 		}
 	} else {
-		jvmInjector.PreCheck.LoadingCheck = true
-		fmt.Println(err, "So already loaded.")
-		// TODO 指令校验成功后 return nil
-		return fmt.Errorf("So already loaded.")
+		if jvmInjector.jvmInjectLib() == 0 {
+			jvmInjector.PreCheck.LoadingCheck = true
+		} else {
+			return err
+		}
+		//jvmInjector.PreCheck.LoadingCheck = true
+		//fmt.Println(err, "So already loaded.")
+		//TODO 指令校验成功后 return nil
+		//return fmt.Errorf("So already loaded.")
 	}
 
 	if !jvmInjector.PreCheck.LoadingCheck {
-		fmt.Println("Failed load so")
-		return err
+		return fmt.Errorf("Failed load so")
 	}
 
 	err = jvmInjector.findDebugFuncContextFromLibPath()
 	if err != nil {
-		log.Fatalf("Failed to find debug Context: %v", err)
+		return fmt.Errorf("Failed to find debug Context: %v", err)
 	}
 	printCodeData(jvmInjector.DebugLibNetInfo)
 
-	//if !jvmInjector.validateAllPreCheck() {
-	//	fmt.Println("failed validateAllPreCheck ")
-	//	return err
-	//}
 	//// 修改
 	debugFuncEnterAddr := uintptr(jvmInjector.DebugLibNetInfo.FuncSymbol.SymAddr)
-	//debugIoFdAddr := uintptr(jvmInjector.DebugLibNetInfo.InnerSymbol.IO_fd_fdID.SymAddr)
-	//debugNetSendAddr := uintptr(jvmInjector.DebugLibNetInfo.InnerSymbol.NET_Send.SymAddr)
-	//
 	originFuncEnterAddr := uintptr(jvmInjector.ReleaseLibNetInfo.FuncSymbol.SymAddr)
-	//ioFdReleaseTargetAddr := uintptr(jvmInjector.ReleaseLibNetInfo.InnerSymbol.IO_fd_fdID.TargetAddr)
-	//netSendReleaseTargetAddr := uintptr(jvmInjector.ReleaseLibNetInfo.InnerSymbol.NET_Send.TargetAddr)
-	//
+	recodeFuncEnterAddr := uintptr(jvmInjector.RecodeInfo.FuncSymbol.SymAddr)
 	//fmt.Printf("<0x%x> -> <0x%x>\n", originFuncEnterAddr, debugFuncEnterAddr)
 	//fmt.Printf("<0x%x> -> <0x%x>\n", debugIoFdAddr, ioFdReleaseTargetAddr)
 	//fmt.Printf("<0x%x> -> <0x%x>\n", debugNetSendAddr, netSendReleaseTargetAddr)
@@ -1049,7 +993,7 @@ func JvmInject(jvmInjector *JvmInjector) error {
 		fmt.Printf("wait4: %v", err)
 		return err
 	}
-	// 保存原始指令并扩充新指令
+	// 保存原始指令并扩充新指令
 	err = buildNopEnc(pid, debugFuncEnterAddr, originFuncEnterAddr)
 	if err != nil {
 		fmt.Println(err)
@@ -1073,8 +1017,8 @@ func JvmInject(jvmInjector *JvmInjector) error {
 	//	return err
 	//}
 
-	//变更原指令 长跳转到新地址
-	err = modifyOriginEnc(pid, uint64(debugFuncEnterAddr), originFuncEnterAddr)
+	//变更原指令 长跳转到新地址 保存到recode
+	err = modifyOriginEnc(pid, uint64(debugFuncEnterAddr), originFuncEnterAddr, recodeFuncEnterAddr)
 
 	//// 更新函数入口
 	//err = modifyReleaseFuncEnter(pid, originFuncEnterAddr, debugFuncEnterAddr)

+ 1 - 1
ebpftracer/tracer_test.go

@@ -324,7 +324,7 @@ func runTracer(t *testing.T, verbose bool) (func() *Event, func()) {
 	assert.NoError(t, unix.Uname(&uname))
 
 	go func() {
-		tt := NewTracer(string(bytes.Split(uname.Release[:], []byte{0})[0]), false)
+		tt := NewTracer(string(bytes.Split(uname.Release[:], []byte{0})[0]), false, false)
 		err := tt.Run(events)
 		require.NoError(t, err)
 		<-done

+ 7 - 5
flags/flags.go

@@ -8,11 +8,13 @@ import (
 )
 
 var (
-	ListenAddress     = kingpin.Flag("listen", "Listen address - ip:port or :port").Default("0.0.0.0:80").Envar("LISTEN").String()
-	CgroupRoot        = kingpin.Flag("cgroupfs-root", "The mount point of the host cgroupfs root").Default("/sys/fs/cgroup").Envar("CGROUPFS_ROOT").String()
-	DisableLogParsing = kingpin.Flag("disable-log-parsing", "Disable container log parsing").Default("false").Envar("DISABLE_LOG_PARSING").Bool()
-	DisablePinger     = kingpin.Flag("disable-pinger", "Don't ping upstreams").Default("false").Envar("DISABLE_PINGER").Bool()
-	DisableL7Tracing  = kingpin.Flag("disable-l7-tracing", "Disable L7 tracing").Default("false").Envar("DISABLE_L7_TRACING").Bool()
+	ListenAddress       = kingpin.Flag("listen", "Listen address - ip:port or :port").Default("0.0.0.0:80").Envar("LISTEN").String()
+	CgroupRoot          = kingpin.Flag("cgroupfs-root", "The mount point of the host cgroupfs root").Default("/sys/fs/cgroup").Envar("CGROUPFS_ROOT").String()
+	DisableLogParsing   = kingpin.Flag("disable-log-parsing", "Disable container log parsing").Default("false").Envar("DISABLE_LOG_PARSING").Bool()
+	DisablePinger       = kingpin.Flag("disable-pinger", "Don't ping upstreams").Default("false").Envar("DISABLE_PINGER").Bool()
+	DisableL7Tracing    = kingpin.Flag("disable-l7-tracing", "Disable L7 tracing").Default("false").Envar("DISABLE_L7_TRACING").Bool()
+	DisableStackTracing = kingpin.Flag("disable-stack-tracing", "Disable stack tracing").Default("false").Envar("DISABLE_STACK_TRACING").Bool()
+	DisableE2ETracing   = kingpin.Flag("disable-e2e-tracing", "Disable e2e tracing").Default("false").Envar("DISABLE_E2E_TRACING").Bool()
 
 	ExternalNetworksWhitelist = kingpin.Flag("track-public-network", "Allow track connections to the specified IP networks, all private networks are allowed by default (e.g., Y.Y.Y.Y/mask)").Envar("TRACK_PUBLIC_NETWORK").Strings()
 	EphemeralPortRange        = kingpin.Flag("ephemeral-port-range", "Destination and Listen TCP ports from this range will be skipped").Default("32768-60999").Envar("EPHEMERAL_PORT_RANGE").String()