Переглянути джерело

Fixed #TASK_QT-9810 [arm适配/4.18适配]go client修正

Carl 1 рік тому
батько
коміт
65fb4353f1

+ 3 - 3
ebpftracer/ebpf/utrace/go/include/alloc.h

@@ -156,7 +156,7 @@ static __always_inline void *write_target_data(void *data, s32 size)
     }
 }
 
-static __always_inline void *write_target_data2(void *data, s32 size, struct ebpf_proc_info* info)
+static __always_inline void *cw_write_target_data(void *data, s32 size, struct ebpf_proc_info* info)
 {
     if (data == NULL)
     {
@@ -176,7 +176,7 @@ static __always_inline void *write_target_data2(void *data, s32 size, struct ebp
     u64 end = get_area_end(start,start_from_proc,end_from_proc);
     if (end - start < size)
     {
-        bpf_printk("reached end of CPU memory block, going to the start again");
+        cw_bpf_debug("reached end of CPU memory block, going to the start again");
         s32 start_index = 0;
         bpf_map_delete_elem(&alloc_map, &start_index);
         start = get_area_start(start_from_proc, end_from_proc);
@@ -192,7 +192,7 @@ static __always_inline void *write_target_data2(void *data, s32 size, struct ebp
     }
     u64 target_u = (u64)target;
     if (target_u > end_from_proc || target_u < start_from_proc) {
-        bpf_printk("TARGET ADDRESS IS OUT OF BOUNDS: 0x%llx", target);
+	    cw_bpf_debug("TARGET ADDRESS IS OUT OF BOUNDS: 0x%llx", target);
         return NULL;
     }
 

+ 19 - 7
ebpftracer/ebpf/utrace/go/include/go_common.h

@@ -150,11 +150,23 @@ typedef __u32 __wsum;
 //
 //#endif /* __VMLINUX_H__ */
 
-// 定义一个大小为 65536 字节的 Map
-#define GO_MAX_BUFFER_SIZE 1024
 struct {
-	__uint(type, BPF_MAP_TYPE_ARRAY);
-	__type(key, int); // 键类型为int
-	__uint(value_size, GO_MAX_BUFFER_SIZE); // 数组的每个值的大小
-	__uint(max_entries, 2); // 最大条目数为2
-} go_large_array_map SEC(".maps");
+	__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
+	__uint(key_size, 4);
+	__uint(value_size, 4);
+	__uint(max_entries, 1);
+} jmp_table2 SEC(".maps");
+
+struct tail_client_ctx_t {
+	void *header_value_str_p;
+	void *headers_ptr;
+	void *bucket_ptr;
+	u64 curr_keyvalue_count;
+};
+
+struct {
+	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
+	__type(key, u32);
+	__type(value, struct tail_client_ctx_t);
+	__uint(max_entries, 1);
+} tail_client_ctx_heap SEC(".maps");

+ 7 - 0
ebpftracer/ebpf/utrace/go/include/go_types.h

@@ -47,6 +47,13 @@ struct map_bucket {
     struct go_string_ot keys[8];
     struct go_slice_ot values[8];
     void *overflow;
+
+	void *header_value_str_p;
+	void *headers_ptr;
+	void *bucket_ptr;
+	u64 curr_keyvalue_count;
+	u8 bucket_index;
+
 };
 
 struct slice_array_buff

+ 100 - 18
ebpftracer/ebpf/utrace/go/net/client.probe.bpf.c

@@ -432,7 +432,7 @@ static __always_inline long cw_inject_header3(void* headers_ptr, char * header_s
 
     if (curr_keyvalue_count == 0) {
         // No key-value pairs in the Go map, need to "allocate" memory for the user
-        bucket_ptr = write_target_data2(bucket_map_value, sizeof(struct map_bucket),proc_info);
+        bucket_ptr = cw_write_target_data(bucket_map_value, sizeof(struct map_bucket),proc_info);
         if (bucket_ptr == NULL) {
             cw_bpf_debug("inject_header: Failed to write bucket to user");
             return -1;
@@ -446,7 +446,7 @@ static __always_inline long cw_inject_header3(void* headers_ptr, char * header_s
     } else {
         // There is at least 1 key-value pair, hence the bucket pointer from the user is valid
         // Read the bucket pointer
-        res = bpf_probe_read_user(&bucket_ptr, sizeof(bucket_ptr), buckets_ptr_ptr);
+        bpf_probe_read_user(&bucket_ptr, sizeof(bucket_ptr), buckets_ptr_ptr);
         // Read the user's bucket to the eBPF map entry
         bpf_probe_read_user(bucket_map_value, sizeof(struct map_bucket), bucket_ptr);
     }
@@ -458,7 +458,7 @@ static __always_inline long cw_inject_header3(void* headers_ptr, char * header_s
 
     // Prepare the key string for the user
     char key[CW_HEADER_KEY_LENGTH] = CW_HEADER_KEY_VAL;
-    void *ptr = write_target_data2(key, CW_HEADER_KEY_LENGTH,proc_info);
+    void *ptr = cw_write_target_data(key, CW_HEADER_KEY_LENGTH,proc_info);
     if (ptr == NULL) {
         cw_bpf_debug("inject_header: Failed to write key to user");
         return -1;
@@ -469,20 +469,32 @@ static __always_inline long cw_inject_header3(void* headers_ptr, char * header_s
 	bucket_map_value->tophash[bucket_index] = traceparent_tophash;
 	bucket_map_value->keys[bucket_index] = (struct go_string_ot) {.len = CW_HEADER_KEY_LENGTH, .str = ptr};
 
+//	u32 k0;
+//	struct tail_client_ctx_t *tail_calls_context = bpf_map_lookup_elem(&tail_client_ctx_heap, &k0);
+//	if (!tail_calls_context){
+//		return -1;
+//	}
 
     // Prepare the value string slice
     // First the value string which constains the span context
 //    char val[CW_HEADER_VAL_LENGTH];
 //	span_context_to_cw_string(propagated_ctx, val);
-    ptr = write_target_data2(header_str, CW_HEADER_VAL_LENGTH,proc_info);
+    ptr = cw_write_target_data(header_str, CW_HEADER_VAL_LENGTH,proc_info);
     if(ptr == NULL) {
         cw_bpf_debug("inject_header: Failed to write value to user");
         return -1;
     }
+	bucket_map_value->header_value_str_p = ptr;
+
+	bucket_map_value->curr_keyvalue_count = curr_keyvalue_count;
+	bucket_map_value->bucket_index = bucket_index;
+	bucket_map_value->headers_ptr = headers_ptr;
+	bucket_map_value->bucket_ptr = bucket_ptr;
 
+	return 0;
     // The go string pointing to the above val
     struct go_string_ot header_value = {.len = CW_HEADER_VAL_LENGTH, .str = ptr};
-    ptr = write_target_data2((void*)&header_value, sizeof(header_value),proc_info);
+    ptr = cw_write_target_data((void*)&header_value, sizeof(header_value),proc_info);
     if(ptr == NULL) {
         cw_bpf_debug("inject_header: Failed to write go_string to user");
         return -1;
@@ -584,18 +596,18 @@ int uprobe_Transport_roundTrip(struct pt_regs *ctx) {
 //			generate_random_bytes(httpReq->sc.SpanID, SPAN_ID_SIZE);
 		}
 //    }
-    if (!get_go_string_from_user_ptr((void *)(req_ptr+proc_info->method_ptr_pos), httpReq->method, sizeof(httpReq->method))) {
-        cw_bpf_debug("uprobe_Transport_roundTrip: Failed to get method from request");
-        return 0;
-    }
+//    if (!get_go_string_from_user_ptr((void *)(req_ptr+proc_info->method_ptr_pos), httpReq->method, sizeof(httpReq->method))) {
+//        cw_bpf_debug("uprobe_Transport_roundTrip: Failed to get method from request");
+//        return 0;
+//    }
 
     // get path from Request.URL
-    void *url_ptr = 0;
-    bpf_probe_read(&url_ptr, sizeof(url_ptr), (void *)(req_ptr+proc_info->url_ptr_pos));
-    if (!get_go_string_from_user_ptr((void *)(url_ptr+proc_info->path_ptr_pos), httpReq->path, sizeof(httpReq->path))) {
-        cw_bpf_debug("uprobe_Transport_roundTrip: Failed to get path from Request.URL");
-        return 0;
-    }
+//    void *url_ptr = 0;
+//    bpf_probe_read(&url_ptr, sizeof(url_ptr), (void *)(req_ptr+proc_info->url_ptr_pos));
+//    if (!get_go_string_from_user_ptr((void *)(url_ptr+proc_info->path_ptr_pos), httpReq->path, sizeof(httpReq->path))) {
+//        cw_bpf_debug("uprobe_Transport_roundTrip: Failed to get path from Request.URL");
+//        return 0;
+//    }
 
     // get host from Request
     if (!get_go_string_from_user_ptr((void *)(req_ptr+proc_info->request_host_pos), httpReq->host, sizeof(httpReq->host))) {
@@ -638,9 +650,9 @@ int uprobe_Transport_roundTrip(struct pt_regs *ctx) {
 	set_assumed_app_id_arrays(httpReq->host, httpReq->apm_sc.assumed_app_id, APM_ASSUMED_APP_ID_STRING_SIZE);
 	cw_save_current_tracking_span(&httpReq->apm_sc);
 	// get proto from Request
-    if (!get_go_string_from_user_ptr((void *)(req_ptr+proc_info->request_proto_pos), httpReq->proto, sizeof(httpReq->proto))) {
-        cw_bpf_debug("uprobe_Transport_roundTrip: Failed to get proto from Request");
-    }
+//    if (!get_go_string_from_user_ptr((void *)(req_ptr+proc_info->request_proto_pos), httpReq->proto, sizeof(httpReq->proto))) {
+//        cw_bpf_debug("uprobe_Transport_roundTrip: Failed to get proto from Request");
+//    }
 
     // get headers from Request
     void *headers_ptr = 0;
@@ -656,14 +668,84 @@ int uprobe_Transport_roundTrip(struct pt_regs *ctx) {
 	long res2 = cw_inject_header3(headers_ptr, val,proc_info);
 	if (res2 < 0) {
 		cw_bpf_debug("uprobe_Transport_roundTrip: Failed to inject header");
+		return -1;
 	}
 
+	bpf_tail_call(ctx, &jmp_table2, 0);
+
     // Write event
 //    bpf_map_update_elem(&http_events, &key, httpReq, 0);
 //    start_tracking_span(context_ptr_val, &httpReq->sc);
+
     return 0;
 }
 
+PROGUP(go_update_header)(struct pt_regs *ctx) {
+//	return 1;
+
+	__u64 pid_tgid = bpf_get_current_pid_tgid();
+	__u32 tgid = pid_tgid >> 32;
+	struct ebpf_proc_info *proc_info =
+			bpf_map_lookup_elem(&proc_info_map, &tgid);
+	if(!proc_info)
+	{
+		return 0;
+	}
+//	__u32 k0;
+//	struct tail_client_ctx_t *tail_calls_context =
+//			bpf_map_lookup_elem(&tail_client_ctx_heap, &k0);
+//	if (!tail_calls_context){
+//		return -1;
+//	}
+	u32 map_id = 0;
+
+	struct map_bucket *bucket_map_value = bpf_map_lookup_elem(&golang_mapbucket_storage_map, &map_id);
+	if (!bucket_map_value) {
+		return -1;
+	}
+	if (!bucket_map_value->header_value_str_p){
+		return -1;
+	}
+	if (!bucket_map_value->headers_ptr){
+		return -1;
+	}
+	if (!bucket_map_value->bucket_ptr){
+		return -1;
+	}
+
+	// The go string pointing to the above val
+	struct go_string_ot header_value = {.len = CW_HEADER_VAL_LENGTH, .str = bucket_map_value->header_value_str_p};
+	void * ptr = cw_write_target_data((void*)&header_value, sizeof(header_value),proc_info);
+	if(ptr == NULL) {
+		cw_bpf_debug("inject_header: Failed to write go_string to user");
+		return -1;
+	}
+
+	// Last, go_slice pointing to the above go_string
+	if (bucket_map_value->bucket_index >=8) {
+		return -1;
+	}
+	bucket_map_value->values[bucket_map_value->bucket_index] = (struct go_slice_ot) {.array = ptr, .cap = 1, .len = 1};
+
+	// Update the map header count field
+	bucket_map_value->curr_keyvalue_count += 1;
+	long res = bpf_probe_write_user(bucket_map_value->headers_ptr, &bucket_map_value->curr_keyvalue_count, sizeof(bucket_map_value->curr_keyvalue_count));
+	if (res < 0) {
+		cw_bpf_debug("Failed to update key-value count in map header");
+		return -1;
+	}
+
+	// Update the bucket
+	res = bpf_probe_write_user(bucket_map_value->bucket_ptr, bucket_map_value, sizeof(struct map_bucket));
+	if (res < 0) {
+		cw_bpf_debug("Failed to update bucket content");
+		return -1;
+	}
+
+	bpf_memset((unsigned char *)bucket_map_value, sizeof(struct map_bucket), 0);
+	return 0;
+}
+
 // This instrumentation attaches uretprobe to the following function:
 // func net/http/transport.roundTrip(req *Request) (*Response, error)
 SEC("uprobe/Transport_roundTrip")

+ 1 - 0
ebpftracer/tracer/socket.go

@@ -65,6 +65,7 @@ func insert_output_prog_to_map(collection *ebpf.Collection) {
 
 	__insert_output_prog_to_map(collection, "jmp_table1", "bpf_prog_up__save_sc", 0)
 	__insert_output_prog_to_map(collection, "jmp_table1", "bpf_prog_up__update_header", 1)
+	__insert_output_prog_to_map(collection, "jmp_table2", "bpf_prog_up__go_update_header", 0)
 }
 
 func __insert_output_prog_to_map(collection *ebpf.Collection, mapName string, progName string, key uint32) {