Ver código fonte

Feature #TASK_QT-31492 go1.24-server调整 server.probe.bpf.c

Feature #TASK_QT-31498 kyV10 4.19.98-23.54.v2101.ky10.x86_64适配
Carl 6 meses atrás
pai
commit
c8c4f70e79
2 arquivos alterados com 80 adições e 6 exclusões
  1. 54 5
      ebpftracer/ebpf/utrace/go/net/server.probe.bpf.c
  2. 26 1
      ebpftracer/tls.go

+ 54 - 5
ebpftracer/ebpf/utrace/go/net/server.probe.bpf.c

@@ -103,6 +103,12 @@ struct {
 	__uint(max_entries, 8);
 } header_keys_map SEC(".maps");
 
+struct {
+	__uint(type, BPF_MAP_TYPE_LRU_HASH);
+	__uint(key_size, sizeof(u64));
+	__uint(value_size, sizeof(char [CW_HEADER_VAL_LENGTH]));
+	__uint(max_entries, MAX_CONCURRENT);
+} http_server_context_headers SEC(".maps");
 
 // Injected in init
 // volatile const u64 ctx_ptr_pos;
@@ -118,7 +124,7 @@ struct {
 //}
 //}
 
-static __always_inline struct span_context *extract_context_from_req_headers(void *headers_ptr_ptr) {
+static __always_inline struct span_context *extract_context_from_req_headers_del(void *headers_ptr_ptr) {
 	void *headers_ptr;
 	long res;
 	res = bpf_probe_read(&headers_ptr, sizeof(headers_ptr), headers_ptr_ptr);
@@ -304,6 +310,17 @@ static __always_inline struct map_bucket *get_map_bucket(void *headers_ptr_ptr)
 
 MAP_BUCKET_DEFINITION(go_string_ot,  go_slice_ot)
 
+static __always_inline char *
+extract_context_from_req_headers_pre_parsed(void *key) {
+	char *header_val =
+			bpf_map_lookup_elem(&http_server_context_headers, &key);
+	if (!header_val) {
+		return NULL;
+	}
+
+	return header_val;
+}
+
 static __always_inline char *extract_context_from_req_headers_go_map(void *headers_ptr_ptr)
 {
 	void *headers_ptr;
@@ -407,6 +424,15 @@ static __always_inline char *extract_context_from_req_headers_go_map(void *heade
 	}
 	return NULL;
 }
+
+static __always_inline char *
+extract_context_from_req_headers(void *key, void *headers_ptr_ptr) {
+	return extract_context_from_req_headers_pre_parsed(key);
+//	if (use_swiss == 1) {
+//	}
+//	return extract_context_from_req_headers_go_map(headers_ptr_ptr);
+}
+
 // 获取 header_val
 static __always_inline char *get_header_val(struct map_bucket *map_value,u32 off,u32 count) {
 	for (u32 i = off; i < count; i++) {
@@ -495,8 +521,9 @@ int uprobe_HandlerFunc_ServeHTTP(struct pt_regs *ctx) {
 	void *req_ptr = get_argument(ctx, 4);
 //	struct map_bucket * map_bucket_p = get_map_bucket((void *) (req_ptr + proc_info->headers_ptr_pos));
 
-	char *traceparent_header_value = extract_context_from_req_headers_go_map(
-			(void *) (req_ptr + proc_info->headers_ptr_pos));
+	char *traceparent_header_value = extract_context_from_req_headers(key,
+	                                                                  (void *) (req_ptr + proc_info->headers_ptr_pos));
+
 //	bpf_printk("111 %s",traceparent_header_value);
 
 //	char * traceparent_header_value = get_header_val_off(map_bucket_p);
@@ -581,10 +608,11 @@ int uprobe_HandlerFunc_ServeHTTP_Returns(struct pt_regs *ctx) {
 	struct uprobe_data_t *uprobe_data = bpf_map_lookup_elem(&http_server_uprobes, &key);
 	if (uprobe_data == NULL) {
 		cw_bpf_debug("uprobe/HandlerFunc_ServeHTTP_Returns: entry_state is NULL");
+		bpf_map_delete_elem(&http_server_context_headers, &key);
 		return 0;
 	}
 	bpf_map_delete_elem(&http_server_uprobes, &key);
-
+	bpf_map_delete_elem(&http_server_context_headers, &key);
 	struct http_server_span_t *http_server_span = &uprobe_data->span;
 //	void *resp_ptr = (void *) uprobe_data->resp_ptr;
 //	void *req_ptr = NULL;
@@ -616,4 +644,25 @@ int uprobe_HandlerFunc_ServeHTTP_Returns(struct pt_regs *ctx) {
 	clear_parent_span_context();
 	cw_bpf_debug("HTTP_END");
 	return 0;
-}
+}
+
+// This instrumentation attaches uprobe to the following function:
+// func (r *Reader) readContinuedLineSlice(lim int64, validateFirstLine func([]byte) error) ([]byte, error) {
+SEC("uprobe/textproto_Reader_readContinuedLineSlice")
+int uprobe_textproto_Reader_readContinuedLineSlice_Returns(struct pt_regs *ctx) {
+	void *key = (void *) GOROUTINE(ctx);
+	u64 len = (u64) GO_PARAM2(ctx);
+	u8 *buf = (u8 *) GO_PARAM1(ctx);
+	if (len == (CW_HEADER_KEY_LENGTH + CW_HEADER_VAL_LENGTH + 2)) {
+		long cw_header_native = 0x3A65636172747763LL; // 小端序下的 "cwtrace:"
+		__u64 key64 = 0;
+		bpf_probe_read_user(&key64, sizeof(key64), buf);
+		if (key64 == cw_header_native) {
+			char header_val[CW_HEADER_VAL_LENGTH] = {};
+			bpf_probe_read_user(header_val, sizeof(header_val), buf + CW_HEADER_KEY_LENGTH + 2);
+			cw_bpf_debug("Swiss Map:%s", header_val);
+			bpf_map_update_elem(&http_server_context_headers, &key, &header_val, BPF_ANY);
+		}
+	}
+	return 0;
+}

+ 26 - 1
ebpftracer/tls.go

@@ -38,6 +38,7 @@ const (
 	goGrpcClientConnInvoke         = "google.golang.org/grpc.(*ClientConn).Invoke"
 	goGrpcClientLoopyHeaderHandler = "google.golang.org/grpc/internal/transport.(*loopyWriter).headerHandler"
 	goGrpcHttp2ClientNewStream     = "google.golang.org/grpc/internal/transport.(*http2Client).NewStream"
+	goReadContinuedLineSlice       = "net/textproto.(*Reader).readContinuedLineSlice"
 )
 
 var (
@@ -351,7 +352,7 @@ func (t *Tracer) AttachGoTlsUprobes(pid uint32, appInfo *AppInfo, codeType uint1
 		}
 		switch s.Name {
 		case goTlsWriteSymbol, goTlsReadSymbol:
-		case goExecute, goNewproc1, goRunqget, goServeHTTP, goTransport, goHeaderWriteSubset, goGrpcHttp2OperateHeader, goGrpcServerHandleStream, goGrpcServerWritestatus, goGrpcClientConnInvoke, goGrpcClientLoopyHeaderHandler, goGrpcHttp2ClientNewStream:
+		case goExecute, goNewproc1, goRunqget, goServeHTTP, goTransport, goHeaderWriteSubset, goGrpcHttp2OperateHeader, goGrpcServerHandleStream, goGrpcServerWritestatus, goGrpcClientConnInvoke, goGrpcClientLoopyHeaderHandler, goGrpcHttp2ClientNewStream, goReadContinuedLineSlice:
 		default:
 			continue
 		}
@@ -642,6 +643,30 @@ func (t *Tracer) AttachGoTlsUprobes(pid uint32, appInfo *AppInfo, codeType uint1
 				}
 				links = append(links, l)
 			}
+		case goReadContinuedLineSlice:
+			klog.Infoln("net/textproto.(*Reader).readContinuedLineSlice uprobe attaching")
+			sStart := s.Value - textSection.Addr
+			sEnd := sStart + s.Size
+			if sEnd > textSectionLen {
+				klog.Warnln("net/textproto.(*Reader).readContinuedLineSlice: sEnd > textSectionLen")
+				continue
+			}
+			sBytes := textSectionData[sStart:sEnd]
+			returnOffsets := getReturnOffsets(ef.Machine, sBytes)
+			if len(returnOffsets) == 0 {
+				err = fmt.Errorf("failed to attach uprobe_textproto_Reader_readContinuedLineSlice_Returns: no return offsets found")
+				klog.Errorln(err)
+				return nil, err
+			}
+			for _, offset := range returnOffsets {
+				l, err := exe.Uprobe(s.Name, t.uprobes["uprobe_textproto_Reader_readContinuedLineSlice_Returns"], &link.UprobeOptions{Address: address, Offset: uint64(offset)})
+				if err != nil {
+					klog.WithError(err).Errorln("failed to attach uprobe_textproto_Reader_readContinuedLineSlice_Returns uprobe")
+					return nil, err
+				}
+				klog.Infof("net/textproto.(*Reader).readContinuedLineSlice uprobe attached at offset %d", offset)
+				links = append(links, l)
+			}
 		}
 	}
 	if len(links) == 0 {