Browse Source

Fixed #TASK_QT-9810 解决多版本场景下正确获取数据。

rock 1 year ago
parent
commit
07178581d8
2 changed files with 112 additions and 39 deletions
  1. 12 34
      ebpftracer/ebpf/utrace/java/net/server.probe.bpf.c
  2. 100 5
      ebpftracer/jvm.go

+ 12 - 34
ebpftracer/ebpf/utrace/java/net/server.probe.bpf.c

@@ -72,31 +72,12 @@ static __inline int is_http_header(const char *data)
 }
 
 SEC("uprobe/Java_sun_nio_ch_FileDispatcherImpl_read0")
-int uprobe_Java_sun_nio_ch_FileDispatcherImpl_read0(struct pt_regs *ctx) {
+int uprobe_ret_Java_sun_nio_ch_FileDispatcherImpl_read0(struct pt_regs *ctx) {
 	//计算 rbp-0x30
-    // bpf_printk("enter the uprobe_Java_sun_nio_ch_FileDispatcherImpl_read0\n");
+    bpf_printk("enter the ret uprobe_Java_sun_nio_ch_FileDispatcherImpl_read0\n");
 	unsigned long jhttpdata_ptr;
-	jhttpdata_ptr = (ctx)->rbp;
-	jhttpdata_ptr = jhttpdata_ptr - 0x70;
-	// bpf_printk("enter rbp is %llx.\n", jhttpdata_ptr);
-	jhttpdata_ptr = jhttpdata_ptr - 0x30;
-	//p rbp - 0x30
-	// bpf_printk("enter rbp -0x30 to rcx is %llx.\n", jhttpdata_ptr);
-
-	// x/1gx (p rbp-0x30)
-	unsigned long jbytechar_ptr;
-	long ret = bpf_probe_read_user(&jbytechar_ptr, sizeof(unsigned long), (void *) jhttpdata_ptr);
-	// bpf_printk("x/1gx (p rbp-0x30) value is %llx.\n", jbytechar_ptr);
-    // bpf_printk("enter the uprobe_Java_sun_nio_ch_FileDispatcherImpl_read0 ------22222222\n");
-	if (ret != 0) {
-		// bpf_printk("Failed to read first level ptr: %d\n", ret);
-		return 0;
-	}
-	if (!jbytechar_ptr) {
-		// bpf_printk("First level pointer is null.\n");
-		return 0;
-	}
-    // bpf_printk("enter the uprobe_Java_sun_nio_ch_FileDispatcherImpl_read0 ----111111111\n");
+	jhttpdata_ptr = (ctx)->rsi;
+	bpf_printk("enter rsi is %llx.\n", jhttpdata_ptr);
 	
 	//x/s addr
 	int key = 0;
@@ -104,32 +85,29 @@ int uprobe_Java_sun_nio_ch_FileDispatcherImpl_read0(struct pt_regs *ctx) {
 	if (!map_data) {
 		return 0;
 	}
-	long err = bpf_probe_read_user_str(map_data->payload, sizeof(map_data->payload), (void *) (jbytechar_ptr));
+	long err = bpf_probe_read_user_str(map_data->payload, sizeof(map_data->payload), (void *) (jhttpdata_ptr));
 	if (err < 0) {
-		// bpf_printk("bpf_probe_read_user failed with return code: %d\n", err);
+		bpf_printk("bpf_probe_read_user failed with return code: %d\n", err);
 		return 0;
 	}
 
-	// bpf_printk("read data is : %s\n", map_data->payload);
-	// if (!is_http_request2(httpdata, 1024))
-	// {
-	// 	bpf_printk("not a http request\n");
-	// 	return 0;
-	// }
+	bpf_printk("read data is : %s\n", map_data->payload);
 
 
 	int offset = is_http_header(map_data->payload);
-	// bpf_printk("found the header, %d\n", offset);
+	bpf_printk("found the header, %d\n", offset);
 	char *data;
 	data = bpf_map_lookup_elem(&large_array_map, &key);
 	if (!data)
 		return 0;
 	// struct apm_span_context cw_parent_span_context = {};
 	struct apm_span_context *cw_parent_span_context = bpf_map_lookup_elem(&apm_span_context_heap, &key);
-    if(offset > 0 && offset < 512 - 123)
+    if (!cw_parent_span_context)
+		return 0;
+	if(offset > 0 && offset < 512 - 123)
 	{
         __builtin_memcpy(data, &(map_data->payload[offset]), 123);
-		// bpf_printk("found the data, %s\n", data);
+		bpf_printk("found the data, %s\n", data);
 
 		cw_string_to_span_context(data, cw_parent_span_context);
 	}

+ 100 - 5
ebpftracer/jvm.go

@@ -1,16 +1,21 @@
 package ebpftracer
 
 import (
+	"errors"
+
+
 	"fmt"
+	"debug/elf"
 
 	"github.com/coroot/coroot-node-agent/utils"
 
 	"github.com/cilium/ebpf/link"
+	"golang.org/x/arch/x86/x86asm"
 )
 
 const (
 	// goServeHTTP           = "net/http.serverHandler.ServeHTTP"
-	binPath           = "/home/cloudwise/rock/code/jdk8u/build/linux-x86_64-normal-server-slowdebug/jdk/lib/amd64/libnio.so"
+	binPath           = "/root/code/jdk8u/build/linux-x86_64-normal-server-release/jdk/lib/amd64/libnio.so"
 	symbolsocketRead0 = "Java_sun_nio_ch_FileDispatcherImpl_read0"
 )
 
@@ -23,14 +28,82 @@ func (t *Tracer) AttachJavaNioReadUprobes(pid uint32, insID utils.ID) []link.Lin
 	if err != nil {
 		return nil
 	}
-	opt := link.UprobeOptions{
-		Offset: 103,
+
+	ef, err := elf.Open(binPath)
+	if err != nil {
+		return nil
+	}
+	defer ef.Close()
+
+	symbols, err := ef.Symbols()
+	if err != nil {
+		if errors.Is(err, elf.ErrNoSymbols) {
+			return nil
+		}
+		return nil
+	}
+
+	textSection := ef.Section(".text")
+	if textSection == nil {
+		return nil
 	}
-	upread02, err := ex.Uprobe(symbolsocketRead0, t.uprobes["uprobe_Java_sun_nio_ch_FileDispatcherImpl_read0"], &opt)
+	textSectionData, err := textSection.Data()
 	if err != nil {
 		return nil
 	}
-	links = append(links, upread02)
+	textSectionLen := uint64(len(textSectionData) - 1)
+
+	// opt := link.UprobeOptions{
+	// 	Offset: 61,
+	// }
+	// upread02, err := ex.Uprobe(symbolsocketRead0, t.uprobes["uprobe_ret_Java_sun_nio_ch_FileDispatcherImpl_read0"], &opt)
+	// if err != nil {
+	// 	return nil
+	// }
+	// links = append(links, upread01)
+	for _, s := range symbols {
+		if elf.ST_TYPE(s.Info) != elf.STT_FUNC || s.Size == 0 {
+			continue
+		}
+		switch s.Name {
+		case symbolsocketRead0:
+		default:
+			continue
+		}
+		address := s.Value
+		for _, p := range ef.Progs {
+			if p.Type != elf.PT_LOAD || (p.Flags&elf.PF_X) == 0 {
+				continue
+			}
+
+			if p.Vaddr <= s.Value && s.Value < (p.Vaddr+p.Memsz) {
+				address = s.Value - p.Vaddr + p.Off
+				break
+			}
+		}
+		fmt.Println("s.Name-----:", s.Name)
+		switch s.Name {
+		case symbolsocketRead0:
+			sStart := s.Value - textSection.Addr
+			sEnd := sStart + s.Size
+			if sEnd > textSectionLen {
+				continue
+			}
+			sBytes := textSectionData[sStart:sEnd]
+			returnOffsets := getCallNextMoveOffsets(ef.Machine, sBytes)
+			if len(returnOffsets) == 0 {
+				return nil
+			}
+			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)})
+				if err != nil {
+					fmt.Println("failed to attach uprobe_ret_Java_sun_nio_ch_FileDispatcherImpl_read0 uprobe")
+					return nil
+				}
+				links = append(links, l)
+			}
+		}
+	}
 
 	if len(links) == 0 {
 		return nil
@@ -38,3 +111,25 @@ func (t *Tracer) AttachJavaNioReadUprobes(pid uint32, insID utils.ID) []link.Lin
 	fmt.Println("jvm uprobes attached")
 	return links
 }
+
+func getCallNextMoveOffsets(machine elf.Machine, instructions []byte) []int {
+	var res []int
+	firstCall := 0
+	switch machine {
+	case elf.EM_X86_64:
+		for i := 0; i < len(instructions); {
+			ins, err := x86asm.Decode(instructions[i:], 64)
+			if err == nil && ins.Op == x86asm.CALL {
+				if firstCall == 0{
+					firstCall = 1
+				}else{
+					i += ins.Len
+					res = append(res, i)
+					return res
+				}
+			}
+			i += ins.Len
+		}
+	}
+	return res
+}