소스 검색

Fixed #TASK_QT-9810 javaAOT and NetCore 横向串联

roger.wang 1 년 전
부모
커밋
ac82764d27

+ 1 - 1
Makefile2

@@ -17,7 +17,7 @@ build:
 	CGO_ENABLED=1 go build -gcflags="all=-N -l" -buildvcs=false -o euspace
 c:
 	#docker exec -it 9d928d96d4d0 sh -c 'cd /opt/github/euspace/ebpftracer && sh build.sh${PARAMS}'
-	docker exec -it 3c1a4817a7ed sh -c 'cd /opt/github/euspace/ebpftracer && sh build_linux.sh ${PARAMS}'
+	docker exec -it 3c1a4817a7ed sh -c 'cd /opt/github/euspace/ebpftracer && make all ${PARAMS}'
 c-build: c
 
 go-build:

+ 33 - 2
containers/container.go

@@ -1,6 +1,7 @@
 package containers
 
 import (
+	debugelf "debug/elf"
 	"os"
 	"strconv"
 	"strings"
@@ -13,6 +14,7 @@ import (
 	"github.com/coroot/coroot-node-agent/common"
 	"github.com/coroot/coroot-node-agent/ebpftracer"
 	"github.com/coroot/coroot-node-agent/ebpftracer/l7"
+	"github.com/coroot/coroot-node-agent/ebpftracer/tracer"
 	"github.com/coroot/coroot-node-agent/flags"
 	"github.com/coroot/coroot-node-agent/logs"
 	"github.com/coroot/coroot-node-agent/node"
@@ -148,6 +150,9 @@ type Container struct {
 
 	traceMap   map[uint64]*tracing.Trace
 	instanceID utils.ID
+	Symbols    []debugelf.Symbol
+	Uprobes    []tracer.Uprobe
+	UprobesMap map[string]tracer.Uprobe
 }
 
 func NewContainer(id ContainerID, cg *cgroup.Cgroup, md *ContainerMetadata, hostConntrack *Conntrack, pid uint32) (*Container, error) {
@@ -1093,8 +1098,12 @@ func (c *Container) attachUprobes(tracer *ebpftracer.Tracer, pid uint32) {
 	switch codeType {
 	case CodeTypeJava:
 		c.attachJVMUprobes(tracer, pid)
+	case CodeTypeJavaAot:
+		c.attachJVMUprobes(tracer, pid)
 	case CodeTypeGo:
 		c.attachTlsUprobes(tracer, pid)
+	case CodeTypeNetCore:
+		c.attachNetCoreUprobes(tracer, pid)
 	}
 }
 
@@ -1137,13 +1146,35 @@ func (c *Container) attachJVMUprobes(tracer *ebpftracer.Tracer, pid uint32) {
 		return
 	}
 	if !p.jvmUprobesChecked {
-		tracer.InitKProcInfo(pid, c.instanceID)
-		p.uprobes = append(p.uprobes, tracer.AttachJavaNioReadUprobes(pid, c.instanceID)...)
+		codeType := c.GetCodeTypeFromCache(pid)
+		tracer.InitKProcInfo(pid, c.instanceID, uint16(codeType))
+		p.uprobes = append(p.uprobes, tracer.AttachJavaNioReadUprobes(pid, c.instanceID, int32(codeType))...)
 		p.uprobes = append(p.uprobes, tracer.AttachJavaNetWriteUprobes(pid, c.instanceID)...)
 		p.jvmUprobesChecked = true
 	}
 }
 
+func (c *Container) attachNetCoreUprobes(tracer *ebpftracer.Tracer, pid uint32) {
+	ENV_PID := os.Getenv("FILTER_PID")
+	if ENV_PID != "" {
+		filterPid, _ := strconv.ParseInt(ENV_PID, 10, 64)
+		if filterPid != int64(pid) {
+			return
+		}
+	}
+	p := c.processes[pid]
+	if p == nil {
+		return
+	}
+	if !p.jvmUprobesChecked {
+		codeType := c.GetCodeTypeFromCache(pid)
+		tracer.InitKProcInfo(pid, c.instanceID, uint16(codeType))
+		p.uprobes = append(p.uprobes, tracer.AttachNetCoreNetReadUprobes(pid, c.instanceID)...)
+		p.uprobes = append(p.uprobes, tracer.AttachNetCoreNetWriteUprobes(pid, c.instanceID)...)
+		p.jvmUprobesChecked = true
+	}
+}
+
 func resolveFd(pid uint32, fd uint64) (mntId string, logPath string) {
 	info := proc.GetFdInfo(pid, fd)
 	if info == nil {

+ 6 - 3
containers/container_apm.go

@@ -25,6 +25,8 @@ const (
 	CodeTypeWaitCheck CodeType = 0
 	CodeTypeGo        CodeType = 1006
 	CodeTypeJava      CodeType = 1002
+	CodeTypeJavaAot   CodeType = 1003
+	CodeTypeNetCore   CodeType = 1005
 )
 
 func (p CodeType) String() string {
@@ -78,7 +80,8 @@ func (c *Container) InitTrace(traceId uint64, r *l7.RequestData) error {
 	method, path, hostIp, port := l7.ParseHttpHost(r.Payload)
 	ip, err := netaddr.ParseIP(hostIp)
 	if err != nil {
-		return fmt.Errorf("host ip error")
+		fmt.Println("host ip error")
+		hostIp = "127.0.0.1"
 	}
 	addr := netaddr.IPPortFrom(ip, port)
 	trace := tracing.NewTrace(string(c.id), addr)
@@ -408,11 +411,11 @@ func (c *Container) GetUprobe(event ebpftracer.StackEvent, tracer *ebpftracer.Tr
 	Address := event.Ip - memoryMap.Start
 	// fmt.Printf("memoryMap.Start: %x, event.Ip: %x, Address: %x\n", memoryMap.Start, event.Ip, Address)
 
-	for _, fun := range tracer.UprobesMap {
+	for _, fun := range c.UprobesMap {
 		funAddress := fun.Address + fun.AbsOffset
 		// fmt.Printf("GetUprobeGetUprobeGetUprobe:fun.Address %x, fun.AbsOffset: %x\n", fun.Address, fun.AbsOffset)
 		if funAddress == Address {
-			// fmt.Printf("---GetUprobeGetUprobeGetUprobe: %x, event.Ip: %x\n", memoryMap.Start, event.Ip)
+			// fmt.Printf("---GetUprobeGetUprobeGetUprobe: %x, event.Ip: %x ---- %s--%x\n", memoryMap.Start, event.Ip, fun.Funcname, fun.Address)
 			return fun, nil
 		}
 	}

+ 1 - 0
containers/process.go

@@ -26,6 +26,7 @@ type Process struct {
 	goTlsUprobesChecked   bool
 	openSslUprobesChecked bool
 	jvmUprobesChecked     bool
+	stackUprobesChecked   bool
 
 	codeType CodeType
 }

+ 2 - 2
containers/registry.go

@@ -243,6 +243,7 @@ func (r *Registry) handleEvents(ch <-chan ebpftracer.Event) {
 					//c.attachTlsUprobes(r.tracer, e.Pid)
 					// c.attachJVMUprobes(r.tracer, e.Pid)
 					c.attachUprobes(r.tracer, e.Pid)
+					c.stackTrace(r.tracer, e.Pid)
 				} else {
 					klog.Infoln("TCP listen open from unknown container", e)
 				}
@@ -301,8 +302,7 @@ func (r *Registry) handleEvents(ch <-chan ebpftracer.Event) {
 				}
 
 				if c := r.containersByPid[uint32(e.StackEvent.Pid)]; c != nil {
-					// fmt.Printf("e.EventTypeFunEnt: TraceId:%lld, Pid:%d, Location:%d, Goid:%lld, TimeNs:%d, Ip:%x, CallerIp:%x, Bp:%x, CallerBp:%x\n", e.StackEvent.TraceId, e.StackEvent.Pid, e.StackEvent.Location, e.StackEvent.Goid, e.StackEvent.TimeNsStart, e.StackEvent.Ip, e.StackEvent.CallerIp, e.StackEvent.Bp, e.StackEvent.CallerBp)
-					// fmt.Printf("e.EventTypeFunEnt: FPid:%x, Nid:%x, Level:%d\n", e.StackEvent.Fpid, e.StackEvent.Nid, e.StackEvent.Level)
+					fmt.Printf("e.EventTypeFunEnt: TraceId:%d, Pid:%d, Location:%d, Goid:%d, TimeNs:%d, Ip:%X, CallerIp:%x, Bp:%x, CallerBp:%x\n", e.StackEvent.TraceId, e.StackEvent.Pid, e.StackEvent.Location, e.StackEvent.Goid, e.StackEvent.TimeNsStart, e.StackEvent.Ip, e.StackEvent.CallerIp, e.StackEvent.Bp, e.StackEvent.CallerBp)
 					c.StackProcess2(*e.StackEvent, r.tracer)
 				} else {
 					// fmt.Printf("e.EventTypeFunEnt ErrorError: TraceId:%d, Pid:%d, Location:%d, Goid:%d, TimeNs:%d, Ip:%X, CallerIp:%x, Bp:%x, CallerBp:%x", e.StackEvent.TraceId, e.StackEvent.Pid, e.StackEvent.Location, e.StackEvent.Goid, e.StackEvent.TimeNsStart, e.StackEvent.Ip, e.StackEvent.CallerIp, e.StackEvent.Bp, e.StackEvent.CallerBp)

+ 391 - 0
containers/stack.go

@@ -0,0 +1,391 @@
+package containers
+
+import (
+	"debug/dwarf"
+	"debug/elf"
+	debugelf "debug/elf"
+	"fmt"
+	"io"
+	"log"
+	"os"
+	"regexp"
+	"sort"
+	"strconv"
+
+	"github.com/coroot/coroot-node-agent/ebpftracer"
+	"github.com/coroot/coroot-node-agent/ebpftracer/tracer"
+	tracerelf "github.com/coroot/coroot-node-agent/ebpftracer/tracer"
+	"github.com/coroot/coroot-node-agent/proc"
+	"golang.org/x/arch/arm64/arm64asm"
+	"golang.org/x/arch/x86/x86asm"
+)
+
+type uprobesDef struct {
+	Name       string
+	Offset     uint64
+	EntAddress uint64
+	RetAddress uint64
+}
+
+func (c *Container) stackTrace(tracer *ebpftracer.Tracer, pid uint32) error {
+	ENV_PID := os.Getenv("FILTER_PID")
+	if ENV_PID != "" {
+		filterPid, _ := strconv.ParseInt(ENV_PID, 10, 64)
+		if filterPid != int64(pid) {
+			return nil
+		}
+	}
+	binType := "dotnet"
+	MatchString := ".*HandleFunc|.*main.*|testfun.*|.*serverHandler.*|.*ServeHTTP.*"
+	dbgpath := ""
+
+	WHITE_LIST := os.Getenv("WHITE_LIST")
+	BIN_TYPE := os.Getenv("BIN_TYPE")
+	DBG_PATH := os.Getenv("DBG_PATH")
+	if WHITE_LIST != "" {
+		MatchString = WHITE_LIST
+	}
+
+	if DBG_PATH != "" {
+		dbgpath = DBG_PATH
+	}
+
+	if BIN_TYPE != "" {
+		binType = BIN_TYPE
+	}
+
+	fmt.Println("UprobesMatchString:::init", MatchString)
+	path := proc.Path(uint32(pid), "exe")
+
+	if dbgpath != "" {
+		c.Uprobes, _ = c.getJavaAOTUprobes(binType, path, dbgpath, MatchString)
+	} else {
+		c.Uprobes, _ = c.getUprobes(path, MatchString)
+	}
+
+	p := c.processes[uint32(pid)]
+	if p == nil {
+		return nil
+	}
+
+	if p.stackUprobesChecked {
+		return nil
+	}
+
+	c.UprobesMap = map[string]tracerelf.Uprobe{}
+	fmt.Println("UprobesMap:::init")
+	for _, up := range c.Uprobes {
+		fmt.Println("UprobesMap:::", up.Funcname, up.Address, up.AbsOffset)
+		c.UprobesMap[fmt.Sprintf("%s-%s", up.Funcname, up.Address+up.AbsOffset)] = up
+	}
+	codeType := c.GetCodeTypeFromCache(pid)
+	tracer.InitKProcInfo(pid, c.instanceID, uint16(codeType))
+	p.uprobes = append(p.uprobes, tracer.AttachStackUprobes(path, c.Uprobes)...)
+	p.stackUprobesChecked = true
+
+	return nil
+}
+
+func (c *Container) getJavaAOTUprobes(binType, path string, dbgpath string, MatchString string) ([]tracer.Uprobe, error) {
+	uprobes := []tracer.Uprobe{}
+
+	elfFile, err := elf.Open(path)
+
+	funSection := ".text"
+
+	if binType == "dotnet" {
+		funSection = "__managedcode"
+	}
+
+	textSection := elfFile.Section(funSection)
+	if textSection == nil {
+		fmt.Println("no text section", nil)
+		return nil, nil
+	}
+	textSectionData, err := textSection.Data()
+	if err != nil {
+		fmt.Println("failed to read text section", err)
+		return nil, nil
+	}
+	textSectionLen := uint64(len(textSectionData) - 1)
+
+	dwarfFile, err := elf.Open(dbgpath)
+
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	dwarfData, err := dwarfFile.DWARF()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	entryReader := dwarfData.Reader()
+
+	// var targetAddress uint64
+
+	listEntry := make(map[dwarf.Offset]uprobesDef)
+	SpecListEntry := []dwarf.Entry{}
+
+	for {
+		entry, err := entryReader.Next()
+		if err == io.EOF {
+			// We've reached the end of DWARF entries
+			break
+		}
+		if err != nil {
+			log.Fatalf("Error reading entry: %v", err)
+		}
+		if entry == nil {
+			log.Println("Warning: a nil entry was returned with no error")
+			break
+		}
+		if entry.Tag == dwarf.TagSubprogram {
+			// fmt.Printf("entry address: %x, %d\n", entry.Offset, entry.Children)
+			funName, _ := entry.Val(dwarf.AttrName).(string)
+			found, _ := regexp.MatchString(MatchString, funName)
+			if found {
+				entAddress, _ := entry.Val(dwarf.AttrLowpc).(uint64)
+				retAddress, _ := entry.Val(dwarf.AttrHighpc).(uint64)
+				// fmt.Printf("Function %s address: %x, %x\n", funName, address, entry.Offset)
+				uprobes := uprobesDef{}
+				uprobes.EntAddress = entAddress
+				uprobes.RetAddress = retAddress
+				uprobes.Offset = uint64(entry.Offset)
+				uprobes.Name = funName
+
+				listEntry[entry.Offset] = uprobes
+			}
+
+			specAddr, _ := entry.Val(dwarf.AttrSpecification).(dwarf.Offset)
+			lowpc := entry.Val(dwarf.AttrLowpc)
+			if lowpc != nil && specAddr > 0 && lowpc.(uint64) > 0 {
+				// fmt.Printf("AttrSpecification address: %x, %x\n", specAddr, entry.Offset)
+				SpecListEntry = append(SpecListEntry, *entry)
+			}
+		}
+	}
+
+	for _, v := range SpecListEntry {
+		specAddr, _ := v.Val(dwarf.AttrSpecification).(dwarf.Offset)
+		// fmt.Printf("SpecListEntrySpecListEntrySpecListEntry Attach Function: %x\n", specAddr)
+		_, ok := listEntry[specAddr]
+		if ok {
+			vv := listEntry[specAddr]
+			entAddr := v.Val(dwarf.AttrLowpc)
+			if entAddr != nil {
+				vv.EntAddress = entAddr.(uint64)
+			}
+			retAddr := v.Val(dwarf.AttrHighpc)
+			if retAddr != nil {
+				switch retAddr.(type) {
+				case uint64:
+					vv.RetAddress = uint64(retAddr.(uint64))
+				case int64:
+					vv.RetAddress = uint64(retAddr.(int64))
+				default:
+					fmt.Println("Unknown type")
+				}
+			}
+			listEntry[specAddr] = vv
+		}
+	}
+
+	for _, v := range listEntry {
+		fmt.Printf("Need Attach Function %s address: %x, %x\n", v.Name, v.EntAddress, v.RetAddress)
+
+		sStart := v.EntAddress - textSection.Addr
+		sSize := v.RetAddress
+		if v.RetAddress > v.EntAddress {
+			sSize = v.RetAddress - v.EntAddress
+		}
+		sEnd := sStart + sSize
+		if sEnd > textSectionLen {
+			continue
+		}
+		sBytes := textSectionData[sStart:sEnd]
+		rbpOffsets := getRbpEnterOffsets(elfFile.Machine, sBytes)
+		returnOffsets := getReturnOffsets(elfFile.Machine, sBytes)
+
+		if rbpOffsets != 0 {
+			uprobes = append(uprobes, tracer.Uprobe{
+				Funcname:  v.Name,               // 函数名
+				Location:  tracer.AtDotNetEntry, // 入口
+				Address:   v.EntAddress,         // 函数地址
+				AbsOffset: uint64(rbpOffsets),   // 函数相对 ELF 偏移
+				RelOffset: 0,                    // 函数真实偏移
+			})
+		} else {
+			// 函数入口加入待 attach 列表
+			uprobes = append(uprobes, tracer.Uprobe{
+				Funcname:  v.Name,         // 函数名
+				Location:  tracer.AtEntry, // 入口
+				Address:   v.EntAddress,   // 函数地址
+				AbsOffset: 0,              // 函数相对 ELF 偏移
+				RelOffset: 0,              // 函数真实偏移
+			})
+		}
+
+		for _, offset := range returnOffsets {
+			uprobes = append(uprobes, tracer.Uprobe{
+				Funcname:  v.Name,
+				Location:  tracer.AtRet,
+				Address:   v.EntAddress,
+				AbsOffset: uint64(offset),
+				RelOffset: 0,
+			})
+		}
+	}
+	return uprobes, nil
+}
+
+func (c *Container) getUprobes(path string, MatchString string) ([]tracer.Uprobe, error) {
+	uprobes := []tracer.Uprobe{}
+
+	binFile, err := os.Open(path)
+	if err != nil {
+		return nil, err
+	}
+
+	// cache := map[string]interface{}{}
+	// 解析 elf 文件
+	elfFile, _ := debugelf.NewFile(binFile)
+	// 获取所有符号表
+	symbols, _ := elfFile.Symbols()
+
+	sort.Slice(symbols, func(i, j int) bool { return symbols[i].Value < symbols[j].Value })
+
+	c.Symbols = symbols
+	// 符号表组装成键值 map,方便使用
+	symnames := map[string]debugelf.Symbol{}
+	for _, symbol := range symbols {
+		fmt.Println(symbol.Name, symbol)
+		symnames[symbol.Name] = symbol
+	}
+
+	textSection := elfFile.Section(".text")
+	if textSection == nil {
+		fmt.Println("no text section", nil)
+		return nil, nil
+	}
+	textSectionData, err := textSection.Data()
+	if err != nil {
+		fmt.Println("failed to read text section", err)
+		return nil, nil
+	}
+	textSectionLen := uint64(len(textSectionData) - 1)
+
+	//  遍历符号表
+	for _, symbol := range symbols {
+		if debugelf.ST_TYPE(symbol.Info) != debugelf.STT_FUNC {
+			continue
+		}
+		// fmt.Println("Hello FunName: ", symbol.Name)
+		// 使用正则表达式匹配函数白名单列表
+		found, err := regexp.MatchString(MatchString, symbol.Name)
+		// found, err := regexp.MatchString("main.*", symbol.Name)
+
+		if err != nil {
+			log.Fatal(err)
+		}
+
+		if found {
+			// 匹配到了加入 attachFuncs 列表
+			fmt.Printf("Fuck This: %s, %x\n", symbol.Name, symbol.Value)
+			// attachFuncs = append(attachFuncs, symbol.Name)
+			// 根据函数名拿到当前函数的符号结构体
+			sym := symnames[symbol.Name]
+			if err != nil {
+				fmt.Printf("symnames[symbol.Name]", symbol.Name, err)
+				return nil, err
+			}
+
+			address := sym.Value
+			for _, p := range elfFile.Progs {
+				if p.Type != elf.PT_LOAD || (p.Flags&elf.PF_X) == 0 {
+					continue
+				}
+
+				if p.Vaddr <= sym.Value && sym.Value < (p.Vaddr+p.Memsz) {
+					address = sym.Value - p.Vaddr + p.Off
+					break
+				}
+			}
+
+			// 函数入口加入待 attach 列表
+			uprobes = append(uprobes, tracer.Uprobe{
+				Funcname:  symbol.Name,    // 函数名
+				Location:  tracer.AtEntry, // 入口
+				Address:   address,        // 函数地址
+				AbsOffset: 0,              // 函数相对 ELF 偏移
+				RelOffset: 0,              // 函数真实偏移
+				Wanted:    true,
+			})
+
+			sStart := sym.Value - textSection.Addr
+			sEnd := sStart + sym.Size
+			if sEnd > textSectionLen {
+				continue
+			}
+			sBytes := textSectionData[sStart:sEnd]
+			returnOffsets := getReturnOffsets(elfFile.Machine, sBytes)
+
+			for _, offset := range returnOffsets {
+				uprobes = append(uprobes, tracer.Uprobe{
+					Funcname:  symbol.Name,
+					Location:  tracer.AtRet,
+					Address:   address,
+					AbsOffset: uint64(offset),
+					RelOffset: 0,
+				})
+			}
+		}
+	}
+	return uprobes, nil
+}
+
+func getRbpEnterOffsets(machine elf.Machine, instructions []byte) int {
+	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.LEA && ins.Args[0].String() == "RBP" {
+				fmt.Printf("getRbpEnterOffsets: %v, %s, %s\n", ins, ins.Args[0].String(), ins.Args[1].String())
+				return i
+			}
+			i += ins.Len
+		}
+	case elf.EM_AARCH64:
+		for i := 0; i < len(instructions); {
+			ins, err := arm64asm.Decode(instructions[i:])
+			if err == nil && ins.Op == arm64asm.RET {
+				return i
+			}
+			i += 4
+		}
+	}
+	return 0
+}
+
+func getReturnOffsets(machine elf.Machine, instructions []byte) []int {
+	var res []int
+	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.RET {
+				res = append(res, i)
+			}
+			i += ins.Len
+		}
+	case elf.EM_AARCH64:
+		for i := 0; i < len(instructions); {
+			ins, err := arm64asm.Decode(instructions[i:])
+			if err == nil && ins.Op == arm64asm.RET {
+				res = append(res, i)
+			}
+			i += 4
+		}
+	}
+	return res
+}

+ 56 - 0
containers/util.go

@@ -9,6 +9,7 @@ import (
 	"os/exec"
 	"regexp"
 	"runtime"
+	"strings"
 )
 
 var libjvmRegex = regexp.MustCompile(`.*/libjvm\.so`)
@@ -25,14 +26,69 @@ func GetExeType(pid uint32) CodeType {
 
 	if libjvmRegex.MatchString(content) {
 		fmt.Println("is java process")
+		if isJavaAotProcess(pid) {
+			fmt.Println("is javaAot process")
+			return CodeTypeJavaAot
+		}
 		return CodeTypeJava
+	} else if isJavaAotProcess(pid) {
+		fmt.Println("is javaAot process")
+		return CodeTypeJavaAot
 	} else if isGoProcess(pid) {
 		return CodeTypeGo
 		fmt.Println("is go process")
+	} else if isNetCoreProcess(pid) {
+		fmt.Println("is netcore process")
+		return CodeTypeNetCore
 	}
 	return CodeTypeUnknown
 }
 
+// isJavaAotProcess checks if the process with the given PID is a GraalVM native image
+func isJavaAotProcess(pid uint32) bool {
+	// Get the executable path for the given PID
+	exePath, err := os.Readlink(fmt.Sprintf("/proc/%d/exe", pid))
+	if err != nil {
+		fmt.Printf("Error reading executable path for PID %d: %v\n", pid, err)
+		return false
+	}
+
+	// Read the content of the executable file
+	content, err := ioutil.ReadFile(exePath)
+	if err != nil {
+		fmt.Printf("Error reading executable file for PID %d: %v\n", pid, err)
+		return false
+	}
+
+	// Check if the file contains the "graal_attach_thread" string
+	if strings.Contains(string(content), "graal_attach_thread") {
+		return true
+	}
+
+	return false
+}
+
+func isNetCoreProcess(pid uint32) bool {
+	path, err := getProcessPath(pid)
+	if err != nil {
+		fmt.Printf("无法获取进程路径:%s\n", err)
+		return false
+	}
+	ef, err := elf.Open(path)
+	if err != nil {
+		fmt.Println("failed to open as elf binary", err)
+		return false
+	}
+	defer ef.Close()
+
+	__managedcode := ef.Section("__managedcode")
+	if __managedcode != nil {
+		fmt.Println("is a netcore process")
+		return true
+	}
+	return false
+}
+
 func isGoProcess(pid uint32) bool {
 	path, err := getProcessPath(pid)
 	if err != nil {

+ 1 - 1
ebpftracer/Makefile

@@ -42,7 +42,7 @@ endif
 OBJ_DIR = ebpf/bin/$(MACHINE_ARCH)
 
 # Define flags
-CFLAGS = -I. -Ivmlinux -Iinclude -Iebpf/include -Iebpf/utrace/go/include -Iebpf/utrace/java/include \
+CFLAGS = -I. -Ivmlinux -Iinclude -Iebpf/include -Iebpf/utrace/go/include -Iebpf/utrace/java/include -Iebpf/utrace/netcore/include \
 	-D__BPF_TRACING__ -D GROUP_LEADER_OFFSET_OVERRIDE=0 -DSTART_BOOTTIME_OFFSET_OVERRIDE=0 \
 	-DSTART_BOOTTIME_VARNAME=real_start_time -std=gnu99 -Wimplicit-function-declaration \
 	-ffreestanding -fno-builtin -Wall -Wno-deprecated-declarations \

+ 1 - 1
ebpftracer/build_linux.sh

@@ -28,7 +28,7 @@ echo "debug: $debug"
 #clang -g -O2 -target bpf -D__KERNEL_FROM=512 -D__TARGET_ARCH_x86 -D__x86_64__ $debug $TAG -c ./ebpf/ebpf.c -o ebpf512x86.o && llvm-strip --strip-debug ebpf512x86.o
 #llvm-strip --strip-debug ./ebpf512x86.o
 #chown 501:dialout ./ebpf512x86.o
-/usr/bin/clang -I. -Ivmlinux -Iinclude -Iebpf/include -Iebpf/utrace/go/include -Iebpf/utrace/java/include  -D__BPF_TRACING__ -D GROUP_LEADER_OFFSET_OVERRIDE=0 -DSTART_BOOTTIME_OFFSET_OVERRIDE=0 -DSTART_BOOTTIME_VARNAME=real_start_time  -std=gnu99 -Wimplicit-function-declaration \
+/usr/bin/clang -I. -Ivmlinux -Iinclude -Iebpf/include -Iebpf/utrace/go/include -Iebpf/utrace/java/include -Iebpf/utrace/netcore/include -D__BPF_TRACING__ -D GROUP_LEADER_OFFSET_OVERRIDE=0 -DSTART_BOOTTIME_OFFSET_OVERRIDE=0 -DSTART_BOOTTIME_VARNAME=real_start_time  -std=gnu99 -Wimplicit-function-declaration \
 	-ffreestanding -fno-builtin -Wall \
 	-Wno-deprecated-declarations \
 	-Wno-gnu-variable-sized-type-not-at-end \

+ 3 - 0
ebpftracer/ebpf/ebpf.c

@@ -57,4 +57,7 @@
 
 #include "utrace/java/net/server.probe.bpf.c"
 #include "utrace/java/net/client.probe.bpf.c"
+
+#include "utrace/netcore/net/server.probe.bpf.c"
+#include "utrace/netcore/net/client.probe.bpf.c"
 char _license[] SEC("license") = "GPL";

+ 2 - 0
ebpftracer/ebpf/include/socket_trace_common.h

@@ -191,6 +191,8 @@ struct ebpf_proc_info {
 	__u64 start_addr;
 	__u64 end_addr;
 	unsigned char instance_id[APM_INSTANCE_ID_SIZE];
+	__u16 code_type;
+
 	__u64 method_ptr_pos;
 	__u64 url_ptr_pos;
 	__u64 path_ptr_pos;

+ 20 - 0
ebpftracer/ebpf/utrace/go/net/stack.probe.bpf.c

@@ -65,8 +65,18 @@ int ent(struct pt_regs *ctx)
 	__u64 pid_tgid = bpf_get_current_pid_tgid();
     __u64 pid = pid_tgid >> 32;
 
+	struct ebpf_proc_info *info =
+			bpf_map_lookup_elem(&proc_info_map, &pid);
+	if (!info) {
+		return 0;
+	}
+
+	cw_bpf_debug("[Go] [uprobe/ent]: proc_info_map::%ld, %d, %d\n", info->code_type);
+
 	__u64 trace_id = get_apm_trace_id(pid, pid_tgid);
 
+	cw_bpf_debug("[Go] [uprobe/ent]: get_apm_trace_id::%ld, %d, %d\n", trace_id, pid, pid_tgid);
+
 	__u32 key = 0;
 	struct event *e = bpf_map_lookup_elem(&event_stack, &key);
 	if (!e)
@@ -236,7 +246,17 @@ int dotnetent(struct pt_regs *ctx)
 	__u64 pid_tgid = bpf_get_current_pid_tgid();
     __u64 pid = pid_tgid >> 32;
 
+	struct ebpf_proc_info *info =
+			bpf_map_lookup_elem(&proc_info_map, &pid);
+	if (!info) {
+		return 0;
+	}
+
+	cw_bpf_debug("[Go] [uprobe/ent]: proc_info_map::%ld, %d, %d\n", info->code_type);
+
 	__u64 trace_id = get_apm_trace_id(pid, pid_tgid);
+	
+	cw_bpf_debug("[Go] [uprobe/ent]: get_apm_trace_id::%ld, %d, %d\n", trace_id, pid, pid_tgid);
 
 	__u32 key = 0;
 	struct event *e = bpf_map_lookup_elem(&event_stack, &key);

+ 15 - 1
ebpftracer/ebpf/utrace/java/net/client.probe.bpf.c

@@ -261,7 +261,21 @@ int uprobe_Java_java_net_SocketOutputStream_socketWrite0(struct pt_regs *ctx) {
 	cw_bpf_debug("[len_ptr]after  addr<0x%lx>, %d \n", len_from_rbp_ptr, len_ptr);
 
 	// 获取jbytearray
-	void *jbytearray_ptr = (void *) PT_REGS_PARM4(ctx);
+	__u32 tgid = (__u32)(bpf_get_current_pid_tgid() >> 32);
+	struct ebpf_proc_info *info = bpf_map_lookup_elem(&proc_info_map, &tgid);
+	if (!info) {
+		return 0;
+	}
+
+	cw_bpf_debug("[Go] [uprobe/ent]: proc_info_map::%ld, %d, %d\n", info->code_type);
+	void *jbytearray_ptr = NULL;
+	// 1003 是 javaAOT 的
+	if (info->code_type == 1003) {
+		jbytearray_ptr = (void *) (PT_REGS_SP(ctx)) + 0x8 + 0x10060+0x20;
+	} else{
+		jbytearray_ptr = (void *) PT_REGS_PARM4(ctx);
+	}
+	
 	cw_bpf_debug("jbytechar_ptr_from_rcx <0x%lx>", jbytearray_ptr);
 
 	unsigned long jbytechar_head_ptr;

+ 133 - 0
ebpftracer/ebpf/utrace/netcore/include/netcore_common.h

@@ -0,0 +1,133 @@
+//
+// Created by Carl.Guo on 2024/6/28.
+//
+
+#ifndef EUSPACES_JAVA_COMMON_H
+#define EUSPACES_JAVA_COMMON_H
+
+
+
+#define MIN_LEN 13
+#define MAX_LEN 1022
+//#define MAX_BUFFER_SIZE 65536
+
+/**
+ * key  :  7
+ * ': ' :  2
+ * val  : 123
+ * \r\n :  2
+ */
+#define HEADER_LEN 134
+
+
+struct sock_t {
+	int size;
+	int header_offset_idx;
+	char payload[MAX_LEN];
+};
+
+struct {
+	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
+	__type(key, int);
+	__type(value, struct sock_t);
+	__uint(max_entries, 1);
+} socket_heap SEC(".maps");
+
+// 定义一个大小为 65536 字节的 Map
+struct {
+	__uint(type, BPF_MAP_TYPE_ARRAY);
+	__type(key, int); // 键类型为int
+	__uint(value_size, MAX_BUFFER_SIZE); // 数组的每个值的大小
+	__uint(max_entries, 2); // 最大条目数为2
+} large_array_map SEC(".maps");
+
+struct {
+	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
+	__type(key, int);
+	__type(value, struct sock_t);
+	__uint(max_entries, 1);
+} socket_res SEC(".maps");
+
+
+static __always_inline void span_context_to_cw_string_stream(struct apm_span_context *ctx, char *buff, char type_from) {
+	// W3C format: version (2 chars) - trace id (32 chars) - span id (16 chars) - sampled (2 chars)
+	//	[type_from]:[sample]:[host_id]:[app_id]:[instance_id]:[trace_id]:[assumed_app_i d]:[span_id]
+	//	2           2         16        16      16            32         16                16
+	char *out = buff;
+	*out++ = 'c';
+	*out++ = 'w';
+	*out++ = 't';
+	*out++ = 'r';
+	*out++ = 'a';
+	*out++ = 'c';
+	*out++ = 'e';
+	*out++ = ':';
+	*out++ = ' ';
+
+	// Write type_from
+	*out++ = '0';
+	*out++ = type_from;
+	*out++ = ':';
+
+	// Write sample
+	*out++ = '0';
+	*out++ = '0';
+	*out++ = ':';
+
+	// Write host_id
+	bytes_to_hex_string(ctx->host_id, APM_HOST_ID_SIZE, out);
+	out += APM_HOST_ID_STRING_SIZE;
+	*out++ = ':';
+
+	// Write app_id
+	bytes_to_hex_string(ctx->app_id, APM_APP_ID_SIZE, out);
+	out += APM_APP_ID_STRING_SIZE;
+	*out++ = ':';
+
+
+	// Write instance_id
+	bytes_to_hex_string(ctx->instance_id, APM_INSTANCE_ID_SIZE, out);
+	out += APM_INSTANCE_ID_STRING_SIZE;
+	*out++ = ':';
+
+	// Write trace_id
+	bytes_to_hex_string(ctx->trace_id, APM_TRACE_ID_SIZE, out);
+	out += APM_TRACE_ID_STRING_SIZE;
+	*out++ = ':';
+	// Write assumed_app_id
+	bytes_to_hex_string(ctx->assumed_app_id, APM_ASSUMED_APP_ID_SIZE, out);
+	out += APM_ASSUMED_APP_ID_STRING_SIZE;
+	*out++ = ':';
+
+	// Write span_id
+	bytes_to_hex_string(ctx->span_id, APM_SPAN_ID_SIZE, out);
+	out += APM_SPAN_ID_STRING_SIZE;
+
+	*out++ = '\r';
+	*out++ = '\n';
+	out += 2;
+
+//	// Write trace id
+//	bytes_to_hex_string(ctx->TraceID, TRACE_ID_SIZE, out);
+//	out += TRACE_ID_STRING_SIZE;
+//	*out++ = '-';
+//	// Write trace id
+//	bytes_to_hex_string(ctx->TraceID, TRACE_ID_SIZE, out);
+//	out += TRACE_ID_STRING_SIZE;
+//	*out++ = '-';
+//	// Write trace id
+//	bytes_to_hex_string(ctx->TraceID, TRACE_ID_SIZE, out);
+//	out += TRACE_ID_STRING_SIZE;
+//	*out++ = '-';
+//
+//	// Write span id
+//	bytes_to_hex_string(ctx->SpanID, SPAN_ID_SIZE, out);
+//	out += SPAN_ID_STRING_SIZE;
+//	*out++ = '-';
+
+	// Write sampled
+//	*out++ = '0';
+//	*out = '1';
+}
+
+#endif //EUSPACES_JAVA_COMMON_H

+ 227 - 0
ebpftracer/ebpf/utrace/netcore/net/client.probe.bpf.c

@@ -0,0 +1,227 @@
+// Copyright The CW Authors
+
+
+#include "netcore_common.h"
+static __inline int updataSocket3(struct sock_t *map_data_res, char * payload,int len,void * jbytechar_ptr,void * len_from_rbp_ptr) {
+
+	long res = bpf_probe_write_user((void *) jbytechar_ptr,  &map_data_res->payload, sizeof(map_data_res->payload));
+	bpf_printk("sizeof(map_data_res->payload) %d\n", sizeof(map_data_res->payload));
+	bpf_printk("sizeof(payload) %d\n", sizeof(payload));
+	bpf_printk("&payload 0x%lx\n", &payload);
+
+	if (res == 0) {
+		bpf_printk("Successfully wrote value to user address: 0x%lx\n", jbytechar_ptr);
+	} else {
+		bpf_printk("Failed to write value to user address: %p, error: %ld\n", jbytechar_ptr, res);
+	}
+
+	unsigned long new_val;
+	new_val = len;
+	res = bpf_probe_write_user((void *) len_from_rbp_ptr, &new_val, sizeof(new_val));
+	if (res == 0) {
+		bpf_printk("Successfully wrote value to user address: 0x%lx\n", len_from_rbp_ptr);
+	} else {
+		bpf_printk("Failed to write value to user address: %p, error: %ld\n", len_from_rbp_ptr, res);
+	}
+
+	bpf_printk("len %d\n", len);
+
+//	bpf_printk("payload %s\n", payload);
+//	for (int i = 270; i < len; ++i) {
+//		bpf_printk("data[%d]=%c", i,payload[i]);
+//		if(payload[i]=='\0'){
+//			break;
+//		}
+//	}
+	return 0;
+}
+
+static __inline int updataSocket4(struct sock_t *map_data_res,void * jbytechar_ptr,void * len_from_rbp_ptr) {
+
+	long res = bpf_probe_write_user((void *) jbytechar_ptr, &map_data_res->payload, sizeof(map_data_res->payload));
+	if (res == 0) {
+		bpf_printk("Successfully wrote value to user address: 0x%lx\n", jbytechar_ptr);
+	} else {
+		bpf_printk("Failed to write value to user address: %p, error: %ld\n", jbytechar_ptr, res);
+	}
+
+	unsigned long new_val;
+	new_val = map_data_res->size;
+	res = bpf_probe_write_user((void *) len_from_rbp_ptr, &new_val, sizeof(new_val));
+	if (res == 0) {
+		bpf_printk("Successfully wrote value to user address: 0x%lx\n", len_from_rbp_ptr);
+	} else {
+		bpf_printk("Failed to write value to user address: %p, error: %ld\n", len_from_rbp_ptr, res);
+	}
+
+	bpf_printk("Successfully %d\n", map_data_res->size);
+
+	bpf_printk("Successfully %s\n", map_data_res->payload);
+//	for (int i = 270; i < 290; ++i) {
+//		bpf_printk("data[%d]=%c", i,map_data_res->payload[i]);
+//		if(map_data_res->payload[i]=='\0'){
+//			break;
+//		}
+//	}
+	return 0;
+}
+
+static __inline struct sock_t* buildHeader2(struct sock_t *map_data) {
+
+	int key = 0;
+	struct sock_t *map_data_res = bpf_map_lookup_elem(&socket_res, &key);
+
+	if (!map_data_res) {
+		bpf_printk("Failed to lookup socket_heap");
+		return NULL;
+	}
+
+//	__builtin_memset(map_data_res, 0, sizeof(struct sock_t));
+//	char header[5] = "cwt\r\n";
+
+//	char header[CW_STREAM_HEADER_LEN] = "cwtrace: 00:00:1015481350055581:5450531005555981:5610250100539899:304775019cd3218a304775019cd3218a:1001025098564810:140acc88cde8773f\r\n";
+	struct apm_span_context *cw_span_context = bpf_map_lookup_elem(&apm_span_context_heap, &key);
+
+	if (cw_span_context == NULL){
+		return NULL;
+	}
+
+	struct apm_span_context *cw_psc = cw_get_parent_tracking_span();
+	if(cw_psc){
+		copy_byte_arrays(cw_psc->trace_id, cw_span_context->trace_id, APM_TRACE_ID_SIZE);
+		// new spanid
+		generate_random_bytes(cw_span_context->span_id, APM_SPAN_ID_SIZE);
+	}
+
+	// set host_id/appid
+	u32 k0 = 0;
+	struct trace_conf_t *trace_conf = trace_conf_map__lookup(&k0);
+	if (trace_conf) {
+		for (int i = 0; i < 8; ++i) {
+//			cw_bpf_debug("[Client] host_id:%02x", trace_conf->host_id[i]);
+		}
+		copy_byte_arrays(trace_conf->host_id, cw_span_context->host_id, APM_HOST_ID_SIZE);
+		copy_byte_arrays(trace_conf->app_id, cw_span_context->app_id, APM_APP_ID_SIZE);
+	}
+
+	__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) {
+		for (int i = 0; i < 8; ++i) {
+//			cw_bpf_debug("[Client] instance_id:%02x", proc_info->instance_id[i]);
+		}
+		copy_byte_arrays(proc_info->instance_id, cw_span_context->instance_id, APM_APP_ID_SIZE);
+	}
+
+	// set assumed_app_id
+	set_assumed_app_id_arrays("111", cw_span_context->assumed_app_id, APM_ASSUMED_APP_ID_STRING_SIZE);
+	cw_save_current_tracking_span(cw_span_context);
+
+	char header[CW_STREAM_HEADER_LEN];
+	span_context_to_cw_string_stream(cw_span_context, header, '1');
+	bpf_printk("Successfully HEADER  %s\n", header);
+
+//	bpf_probe_read(map_data_res->payload, map_data->header_offset_idx, map_data->payload);
+//	bpf_printk("Successfully %s\n", data);
+//	return 1;
+#pragma unroll
+	for (int i = 0; i < MAX_LEN; i++) {
+		if (i < map_data->header_offset_idx) {
+			map_data_res->payload[i] = map_data->payload[i];
+		} else {
+			if (i == map_data->header_offset_idx) {
+#pragma unroll
+				for (int k = 0; k < CW_STREAM_HEADER_LEN; k++) {
+					int tmp_len = i + k;
+					if (tmp_len < MAX_LEN) {
+						map_data_res->payload[tmp_len] = header[k];
+					}
+				}
+			}
+			int tmp_len = i + CW_STREAM_HEADER_LEN;
+			if (tmp_len < MAX_LEN) {
+				map_data_res->payload[tmp_len] = map_data->payload[i];
+				if (map_data->payload[i] == '\0')
+					break;
+//				bpf_printk("map_data->payload: %c->i=%d, offindex %d", map_data_res->payload[i], i, map_data->header_offset_idx);
+			}
+		}
+	}
+	map_data_res->size = map_data->size + CW_STREAM_HEADER_LEN;
+
+	return map_data_res;
+}
+
+static __inline int insertHeader2(struct sock_t *map_data,void * jbytechar_ptr,void * len_from_rbp_ptr) {
+
+	struct sock_t *map_data_res= buildHeader2(map_data);
+	if (map_data_res == NULL) {
+		bpf_printk("Failed to lookup socket_heap");
+		return -1;
+	}
+
+	/*修改部分*/
+	return updataSocket3(map_data_res, map_data_res->payload, map_data_res->size, jbytechar_ptr, len_from_rbp_ptr);
+}
+
+
+SEC("uprobe/netcore_asmnop")
+int netcore_asmnop(struct pt_regs *ctx) {
+	bpf_printk("enter the ret netcore_asmnop\n");
+	unsigned long jhttpdata_ptr;
+	jhttpdata_ptr = (ctx)->rsi;
+	unsigned long len_from_rbp_ptr = (ctx)->rsp-0x8;
+	bpf_printk("[len_from_rbp_ptr] <0x%lx>", len_from_rbp_ptr);
+
+	// 定义 Map 键值和 Map 数据结构
+	int key = 0;
+	struct sock_t *map_data = bpf_map_lookup_elem(&socket_heap, &key);
+	if (!map_data) {
+		bpf_printk("Failed to lookup socket_heap\n");
+		return 1;
+	}
+
+	void *jbytechar_ptr = (void *) jhttpdata_ptr;
+	bpf_printk("[jbytechar_ptr] <0x%lx>", jbytechar_ptr);
+
+	unsigned long len_from_rbp;
+	bpf_probe_read_user(&len_from_rbp, sizeof(len_from_rbp), (void*)len_from_rbp_ptr);
+
+	bpf_printk("bpf_probe_read_user len_from_rbp: %ld\n", len_from_rbp);
+
+	long err = bpf_probe_read_user_str(map_data->payload, sizeof(map_data->payload), jbytechar_ptr);
+
+	if (err < 0) {
+		bpf_printk("bpf_probe_read_user failed with return code: %d\n", err);
+		return 0;
+	}
+
+	bpf_printk("bpf_probe_read_user to lookup socket_heap: %s\n----------\n", map_data->payload);
+	map_data->size = len_from_rbp;
+
+	// 查找 Header 开始位置
+	for (int i = 0; i < MAX_LEN - 9; 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;
+			break;
+		}
+	}
+
+	if (map_data->header_offset_idx == 0) {
+		return -1;
+	}
+
+	// http协议过滤
+	if (!is_http_request2(map_data->payload, map_data->size)) {
+		return -1;
+	}
+
+	insertHeader2(map_data,jbytechar_ptr,(void *)len_from_rbp_ptr);
+	return 0;
+}

+ 116 - 0
ebpftracer/ebpf/utrace/netcore/net/server.probe.bpf.c

@@ -0,0 +1,116 @@
+
+#include <stdio.h>  
+#include "netcore_common.h"
+
+// #include "bpf_tracing.h"
+// #include "bpf_helpers.h"
+// #include <asm/ptrace.h>
+// #include "bpf_base.h"
+// #define ROCK_MAX_BUFFER_SIZE 65536
+
+#define ROCK_MAX_LEN 1022
+
+//struct sock_t {
+//	int size;
+//	int header_offset_idx;
+//	char payload[ROCK_MAX_LEN];
+//};
+//
+//struct {
+//	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
+//	__type(key, int);
+//	__type(value, struct sock_t);
+//	__uint(max_entries, 1);
+//} socket_heap SEC(".maps");
+
+struct {
+	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
+	__type(key, int);
+	__type(value, struct apm_span_context);
+	__uint(max_entries, 1);
+} apm_span_context_heap2 SEC(".maps");
+
+//struct {
+//	__uint(type, BPF_MAP_TYPE_ARRAY);
+//	__type(key, int); // 键类型为int
+//	__uint(value_size, 124); // 数组的值的大小
+//	__uint(max_entries, 1);
+//} large_array_map SEC(".maps");
+
+static __inline int is_http_header2(const char *data)
+{
+	for (int i = 0; i < 512; i++)
+	{
+		if (data[i] == '\r' &&
+		    data[i + 1] == '\n' &&
+		    data[i + 2] == 'c' &&
+		    data[i + 3] == 'w' &&
+		    data[i + 4] == 't' &&
+		    data[i + 5] == 'r' &&
+		    data[i + 6] == 'a' &&
+		    data[i + 7] == 'c' &&
+		    data[i + 8] == 'e' &&
+			data[i + 9] == ':' &&
+			data[i + 10] == ' ') {
+			return i + 11;
+		}
+	}
+	return 0;
+}
+
+SEC("uprobe/SystemNative_Receive")
+int SystemNative_Receive(struct pt_regs *ctx) {
+	//计算 rbp-0x30
+	bpf_printk("enter the ret uprobe_Java_sun_nio_ch_FileDispatcherImpl_read0\n");
+	unsigned long jhttpdata_ptr;
+	jhttpdata_ptr = (ctx)->rsi;
+	bpf_printk("enter rsi is %llx.\n", jhttpdata_ptr);
+	
+	//x/s addr
+	int key = 0;
+	struct sock_t *map_data = bpf_map_lookup_elem(&socket_heap, &key);
+	if (!map_data) {
+		return 0;
+	}
+	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);
+		return 0;
+	}
+
+	bpf_printk("read data is : %s\n", map_data->payload);
+
+	int ishttp = is_http_request2(map_data->payload, sizeof(map_data->payload));
+	if (!ishttp)
+		return 0;
+
+	int offset = is_http_header2(map_data->payload);
+	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_heap2, &key);
+	if (cw_parent_span_context == NULL){
+		return -1;
+	}
+	if(offset > 0 && offset < 512 - 123)
+	{
+		__builtin_memcpy(data, &(map_data->payload[offset]), 123);
+		bpf_printk("found the data, %s\n", data);
+
+		cw_string_to_span_context(data, cw_parent_span_context);
+		bpf_printk("found the data, %s\n", cw_parent_span_context->trace_id);
+	}
+	else
+	{
+		generate_random_bytes(cw_parent_span_context->trace_id, TRACE_ID_SIZE);
+		bpf_printk("error found the data, %s\n", cw_parent_span_context->trace_id);
+	}
+	// 保存 trace_id 到psc
+	cw_save_parent_tracking_span(cw_parent_span_context);
+	return 0;
+}
+
+// char __license[] SEC("license") = "Dual MIT/GPL";

+ 18 - 15
ebpftracer/jvm.go

@@ -9,6 +9,7 @@ import (
 	"fmt"
 	"path/filepath"
 
+	"github.com/coroot/coroot-node-agent/proc"
 	"github.com/coroot/coroot-node-agent/utils"
 
 	"github.com/cilium/ebpf/link"
@@ -22,18 +23,27 @@ const (
 	symbolsocketRead0 = "Java_sun_nio_ch_FileDispatcherImpl_read0"
 )
 
-func (t *Tracer) AttachJavaNioReadUprobes(pid uint32, insID utils.ID) []link.Link {
+func (t *Tracer) AttachJavaNioReadUprobes(pid uint32, insID utils.ID, codeType int32) []link.Link {
 	if t.disableL7Tracing {
 		return nil
 	}
-	version := UsePIDToGetJDKVersion(pid)
-	fmt.Println("java version is ", version)
 	var links []link.Link
-	bpath := getSoPath(pid, "libnio.so")
-	if bpath == "" {
-		fmt.Println("can,t find the nio.so")
-		return nil
+	var bpath = ""
+
+	// JavaAOT 逻辑
+	if codeType == 1003 {
+		bpath = proc.Path(uint32(pid), "exe")
+	} else {
+		version := UsePIDToGetJDKVersion(pid)
+		fmt.Println("java version is ", version)
+
+		bpath = getSoPath(pid, "libnio.so")
+		if bpath == "" {
+			fmt.Println("can,t find the nio.so")
+			return nil
+		}
 	}
+
 	fmt.Println("find the nio.so path is ", bpath)
 	ex, err := link.OpenExecutable(bpath)
 	if err != nil {
@@ -132,14 +142,7 @@ func (t *Tracer) AttachJavaNetWriteUprobes(pid uint32, insID utils.ID) []link.Li
 	//	return nil
 	//}
 
-	//var libnetSo = "/opt/github/jdk8u/build/linux-x86_64-normal-server-slowdebug/jdk/lib/amd64/libnet.so"
-	var libnetSo = getSoPath(pid, "libnet.so")
-	// TODO 融合私有so
-	//var libnetSo = getSoPath(pid, "cwlibnet.so")
-	if libnetSo == "" {
-		return nil
-	}
-
+	var libnetSo = "/data/roger/graalvm/lib/libnet.so"
 	var sys = "Java_java_net_SocketOutputStream_socketWrite0"
 	var links []link.Link
 	ex, err := link.OpenExecutable(libnetSo)

+ 225 - 0
ebpftracer/netcore.go

@@ -0,0 +1,225 @@
+package ebpftracer
+
+import (
+	"bufio"
+	"errors"
+	"io"
+	"log"
+	"os"
+	"strconv"
+	"strings"
+
+	"debug/dwarf"
+	"debug/elf"
+	"fmt"
+
+	"github.com/coroot/coroot-node-agent/utils"
+
+	"github.com/cilium/ebpf/link"
+)
+
+const (
+	// goServeHTTP           = "net/http.serverHandler.ServeHTTP"
+	// binPath           = "/root/code/jdk8u/build/linux-x86_64-normal-server-release/jdk/lib/amd64/libnio.so"
+	libPath                  = "/data/roger/NET8/CoreAoT/bin/Release/net8.0/linux-x64/publish/CoreAoT"
+	netcoresymbolsocketRead0 = "SystemNative_Receive"
+)
+
+type MemoryMap struct {
+	Start, End uint64
+}
+
+func ReadFirstLineOfMapsFile(pid string) (*MemoryMap, error) {
+	file, err := os.Open(fmt.Sprintf("/proc/%s/maps", pid))
+	if err != nil {
+		return nil, err
+	}
+	defer file.Close()
+
+	scanner := bufio.NewScanner(file)
+	if scanner.Scan() {
+		fields := strings.Fields(scanner.Text())
+		addresses := strings.Split(fields[0], "-")
+		if len(addresses) != 2 {
+			return nil, errors.New("unexpected format in /proc/<pid>/maps")
+		}
+
+		start, err := strconv.ParseUint(addresses[0], 16, 64)
+		if err != nil {
+			return nil, err
+		}
+
+		end, err := strconv.ParseUint(addresses[1], 16, 64)
+		if err != nil {
+			return nil, err
+		}
+
+		return &MemoryMap{
+			Start: start,
+			End:   end,
+		}, nil
+	}
+
+	if err := scanner.Err(); err != nil {
+		return nil, err
+	}
+
+	return nil, errors.New("empty /proc/<pid>/maps")
+}
+
+func (t *Tracer) getFunctionOffsetDBG(libPath, functionName string) (elf.Symbol, error) {
+	dwarfFile, err := elf.Open(libPath)
+	dwarfData, err := dwarfFile.DWARF()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	type uprobesDef struct {
+		Name       string
+		Offset     uint64
+		EntAddress uint64
+		RetAddress uint64
+	}
+
+	listEntry := make(map[dwarf.Offset]uprobesDef)
+	SpecListEntry := []dwarf.Entry{}
+
+	entryReader := dwarfData.Reader()
+
+	for {
+		entry, err := entryReader.Next()
+		if err == io.EOF {
+			// We've reached the end of DWARF entries
+			break
+		}
+		if err != nil {
+			log.Fatalf("Error reading entry: %v", err)
+		}
+		if entry == nil {
+			log.Println("Warning: a nil entry was returned with no error")
+			break
+		}
+		if entry.Tag == dwarf.TagSubprogram {
+			// fmt.Printf("entry address: %x, %d\n", entry.Offset, entry.Children)
+			funName, _ := entry.Val(dwarf.AttrName).(string)
+			if functionName == funName {
+				entAddress, _ := entry.Val(dwarf.AttrLowpc).(uint64)
+				retAddress, _ := entry.Val(dwarf.AttrHighpc).(uint64)
+				fmt.Printf("Function %s address: %x, %x, %x\n", funName, entAddress, entry.Offset, retAddress)
+				uprobes := uprobesDef{}
+				uprobes.EntAddress = entAddress
+				uprobes.RetAddress = retAddress
+				uprobes.Offset = uint64(entry.Offset)
+				uprobes.Name = funName
+
+				listEntry[entry.Offset] = uprobes
+			}
+
+			specAddr, _ := entry.Val(dwarf.AttrSpecification).(dwarf.Offset)
+			lowpc := entry.Val(dwarf.AttrLowpc)
+			if lowpc != nil && specAddr > 0 && lowpc.(uint64) > 0 {
+				// fmt.Printf("AttrSpecification address: %x, %x\n", specAddr, entry.Offset)
+				SpecListEntry = append(SpecListEntry, *entry)
+			}
+		}
+	}
+
+	for _, v := range SpecListEntry {
+		specAddr, _ := v.Val(dwarf.AttrSpecification).(dwarf.Offset)
+		// fmt.Printf("SpecListEntrySpecListEntrySpecListEntry Attach Function: %x\n", specAddr)
+		_, ok := listEntry[specAddr]
+		if ok {
+			vv := listEntry[specAddr]
+			entAddr := v.Val(dwarf.AttrLowpc)
+			if entAddr != nil {
+				vv.EntAddress = entAddr.(uint64)
+			}
+			retAddr := v.Val(dwarf.AttrHighpc)
+			if retAddr != nil {
+				switch retAddr.(type) {
+				case uint64:
+					vv.RetAddress = uint64(retAddr.(uint64))
+				case int64:
+					vv.RetAddress = uint64(retAddr.(int64))
+				default:
+					fmt.Println("Unknown type")
+				}
+			}
+			listEntry[specAddr] = vv
+		}
+	}
+
+	for _, v := range listEntry {
+		sSize := v.RetAddress
+		if v.RetAddress > v.EntAddress {
+			sSize = v.RetAddress - v.EntAddress
+		}
+		symbol := elf.Symbol{}
+		symbol.Name = v.Name
+		symbol.Value = v.EntAddress
+		symbol.Size = 180
+		fmt.Printf("Need Attach Function %s address: %x, %x, %d\n", v.Name, v.EntAddress, v.RetAddress, sSize)
+		return symbol, nil
+	}
+	return elf.Symbol{}, fmt.Errorf("function %s not found", functionName)
+}
+
+func (t *Tracer) AttachNetCoreNetReadUprobes(pid uint32, insID utils.ID) []link.Link {
+	if t.disableL7Tracing {
+		return nil
+	}
+
+	var links []link.Link
+	ex, err := link.OpenExecutable(libPath)
+
+	// 获取函数的偏移量
+	functionSym, err := t.getFunctionOffsetDBG(libPath+".dbg", netcoresymbolsocketRead0)
+
+	l, err := ex.Uprobe(functionSym.Name, t.uprobes["SystemNative_Receive"], &link.UprobeOptions{Address: functionSym.Value, Offset: 113})
+	if err != nil {
+		fmt.Println("failed to attach SystemNative_Receive uprobe", err, functionSym)
+		return nil
+	}
+
+	links = append(links, l)
+
+	if len(links) == 0 {
+		return nil
+	}
+	fmt.Println("netcore uprobes attached, pid is ", pid)
+	return links
+}
+
+func (t *Tracer) AttachNetCoreNetWriteUprobes(pid uint32, insID utils.ID) []link.Link {
+	if t.disableL7Tracing {
+		return nil
+	}
+	//
+	//if pid != 251719 {
+	//	return nil
+	//}
+
+	var libnetSo = "/data/roger/han/libmylib.so"
+	var sys = "asmnop"
+	var links []link.Link
+	ex, err := link.OpenExecutable(libnetSo)
+	if err != nil {
+		return nil
+	}
+	opt := link.UprobeOptions{
+		Offset: 16,
+		PID:    int(pid),
+	}
+	upread02, err := ex.Uprobe(sys, t.uprobes["netcore_asmnop"], &opt)
+	if err != nil {
+		return nil
+	}
+	links = append(links, upread02)
+
+	if len(links) == 0 {
+		return nil
+	}
+	fmt.Println("netcore client uprobes attached", pid)
+
+	return links
+}

+ 1 - 370
ebpftracer/stack.go

@@ -1,347 +1,14 @@
 package ebpftracer
 
 import (
-	"context"
-	"debug/dwarf"
-	"debug/elf"
-	debugelf "debug/elf"
 	"fmt"
-	"io"
-	"log"
-	"os"
-	"regexp"
-	"sort"
-	"strconv"
 
 	"github.com/cilium/ebpf"
 	"github.com/cilium/ebpf/link"
 	"github.com/coroot/coroot-node-agent/ebpftracer/tracer"
-	"github.com/coroot/coroot-node-agent/proc"
-	"golang.org/x/arch/arm64/arm64asm"
-	"golang.org/x/arch/x86/x86asm"
-	"golang.org/x/sync/semaphore"
 )
 
-type uprobesDef struct {
-	Name       string
-	Offset     uint64
-	EntAddress uint64
-	RetAddress uint64
-}
-
-func (t *Tracer) stack() error {
-	if t.disableL7Tracing {
-		return nil
-	}
-
-	binType := "dotnet"
-	MatchString := ".*HandleFunc|.*main.*|testfun.*|.*serverHandler.*|.*ServeHTTP.*|.*database.*|.*redis.*"
-	dbgpath := ""
-
-	ENV_PID := os.Getenv("FILTER_PID")
-	WHITE_LIST := os.Getenv("WHITE_LIST")
-	BIN_TYPE := os.Getenv("BIN_TYPE")
-	DBG_PATH := os.Getenv("DBG_PATH")
-
-	if ENV_PID == "" {
-		return nil
-	}
-
-	if WHITE_LIST != "" {
-		MatchString = WHITE_LIST
-	}
-
-	if DBG_PATH != "" {
-		dbgpath = DBG_PATH
-	}
-
-	if BIN_TYPE != "" {
-		binType = BIN_TYPE
-	}
-
-	fmt.Println("UprobesMatchString:::init", MatchString)
-
-	pid, _ := strconv.ParseInt(ENV_PID, 10, 32)
-	path := proc.Path(uint32(pid), "exe")
-
-	if dbgpath != "" {
-		t.Uprobes, _ = t.getJavaAOTUprobes(binType, path, dbgpath, MatchString)
-	} else {
-		t.Uprobes, _ = t.getUprobes(path, MatchString)
-	}
-
-	t.UprobesMap = map[string]tracer.Uprobe{}
-	fmt.Println("UprobesMap:::init")
-	for _, up := range t.Uprobes {
-		fmt.Println("UprobesMap:::", up.Funcname, up.Address, up.AbsOffset)
-		t.UprobesMap[fmt.Sprintf("%s-%s", up.Funcname, up.Address+up.AbsOffset)] = up
-	}
-	links := t.attachUprobes(path, t.Uprobes)
-	t.links = append(t.links, links...)
-
-	// defer t.detachUprobes(links)
-	return nil
-}
-
-func (t *Tracer) getJavaAOTUprobes(binType, path string, dbgpath string, MatchString string) ([]tracer.Uprobe, error) {
-	uprobes := []tracer.Uprobe{}
-
-	elfFile, err := elf.Open(path)
-
-	funSection := ".text"
-
-	if binType == "dotnet" {
-		funSection = "__managedcode"
-	}
-
-	textSection := elfFile.Section(funSection)
-	if textSection == nil {
-		fmt.Println("no text section", nil)
-		return nil, nil
-	}
-	textSectionData, err := textSection.Data()
-	if err != nil {
-		fmt.Println("failed to read text section", err)
-		return nil, nil
-	}
-	textSectionLen := uint64(len(textSectionData) - 1)
-
-	dwarfFile, err := elf.Open(dbgpath)
-
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	dwarfData, err := dwarfFile.DWARF()
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	entryReader := dwarfData.Reader()
-
-	// var targetAddress uint64
-
-	listEntry := make(map[dwarf.Offset]uprobesDef)
-	SpecListEntry := []dwarf.Entry{}
-
-	for {
-		entry, err := entryReader.Next()
-		if err == io.EOF {
-			// We've reached the end of DWARF entries
-			break
-		}
-		if err != nil {
-			log.Fatalf("Error reading entry: %v", err)
-		}
-		if entry == nil {
-			log.Println("Warning: a nil entry was returned with no error")
-			break
-		}
-		if entry.Tag == dwarf.TagSubprogram {
-			// fmt.Printf("entry address: %x, %d\n", entry.Offset, entry.Children)
-			funName, _ := entry.Val(dwarf.AttrName).(string)
-			found, _ := regexp.MatchString(MatchString, funName)
-			if found {
-				entAddress, _ := entry.Val(dwarf.AttrLowpc).(uint64)
-				retAddress, _ := entry.Val(dwarf.AttrHighpc).(uint64)
-				// fmt.Printf("Function %s address: %x, %x\n", funName, address, entry.Offset)
-				uprobes := uprobesDef{}
-				uprobes.EntAddress = entAddress
-				uprobes.RetAddress = retAddress
-				uprobes.Offset = uint64(entry.Offset)
-				uprobes.Name = funName
-
-				listEntry[entry.Offset] = uprobes
-			}
-
-			specAddr, _ := entry.Val(dwarf.AttrSpecification).(dwarf.Offset)
-			lowpc := entry.Val(dwarf.AttrLowpc)
-			if lowpc != nil && specAddr > 0 && lowpc.(uint64) > 0 {
-				// fmt.Printf("AttrSpecification address: %x, %x\n", specAddr, entry.Offset)
-				SpecListEntry = append(SpecListEntry, *entry)
-			}
-		}
-	}
-
-	for _, v := range SpecListEntry {
-		specAddr, _ := v.Val(dwarf.AttrSpecification).(dwarf.Offset)
-		// fmt.Printf("SpecListEntrySpecListEntrySpecListEntry Attach Function: %x\n", specAddr)
-		_, ok := listEntry[specAddr]
-		if ok {
-			vv := listEntry[specAddr]
-			entAddr := v.Val(dwarf.AttrLowpc)
-			if entAddr != nil {
-				vv.EntAddress = entAddr.(uint64)
-			}
-			retAddr := v.Val(dwarf.AttrHighpc)
-			if retAddr != nil {
-				switch retAddr.(type) {
-				case uint64:
-					vv.RetAddress = uint64(retAddr.(uint64))
-				case int64:
-					vv.RetAddress = uint64(retAddr.(int64))
-				default:
-					fmt.Println("Unknown type")
-				}
-			}
-			listEntry[specAddr] = vv
-		}
-	}
-
-	for _, v := range listEntry {
-		fmt.Printf("Need Attach Function %s address: %x, %x\n", v.Name, v.EntAddress, v.RetAddress)
-
-		sStart := v.EntAddress - textSection.Addr
-		sSize := v.RetAddress
-		if v.RetAddress > v.EntAddress {
-			sSize = v.RetAddress - v.EntAddress
-		}
-		sEnd := sStart + sSize
-		if sEnd > textSectionLen {
-			continue
-		}
-		sBytes := textSectionData[sStart:sEnd]
-		rbpOffsets := getRbpEnterOffsets(elfFile.Machine, sBytes)
-		returnOffsets := getReturnOffsets(elfFile.Machine, sBytes)
-
-		if rbpOffsets != 0 {
-			uprobes = append(uprobes, tracer.Uprobe{
-				Funcname:  v.Name,               // 函数名
-				Location:  tracer.AtDotNetEntry, // 入口
-				Address:   v.EntAddress,         // 函数地址
-				AbsOffset: uint64(rbpOffsets),   // 函数相对 ELF 偏移
-				RelOffset: 0,                    // 函数真实偏移
-			})
-		} else {
-			// 函数入口加入待 attach 列表
-			uprobes = append(uprobes, tracer.Uprobe{
-				Funcname:  v.Name,         // 函数名
-				Location:  tracer.AtEntry, // 入口
-				Address:   v.EntAddress,   // 函数地址
-				AbsOffset: 0,              // 函数相对 ELF 偏移
-				RelOffset: 0,              // 函数真实偏移
-			})
-		}
-
-		for _, offset := range returnOffsets {
-			uprobes = append(uprobes, tracer.Uprobe{
-				Funcname:  v.Name,
-				Location:  tracer.AtRet,
-				Address:   v.EntAddress,
-				AbsOffset: uint64(offset),
-				RelOffset: 0,
-			})
-		}
-	}
-	return uprobes, nil
-}
-
-func (t *Tracer) getUprobes(path string, MatchString string) ([]tracer.Uprobe, error) {
-	uprobes := []tracer.Uprobe{}
-
-	binFile, err := os.Open(path)
-	if err != nil {
-		return nil, err
-	}
-
-	// cache := map[string]interface{}{}
-	// 解析 elf 文件
-	elfFile, _ := debugelf.NewFile(binFile)
-	// 获取所有符号表
-	symbols, _ := elfFile.Symbols()
-
-	sort.Slice(symbols, func(i, j int) bool { return symbols[i].Value < symbols[j].Value })
-
-	t.Symbols = symbols
-	// 符号表组装成键值 map,方便使用
-	symnames := map[string]debugelf.Symbol{}
-	for _, symbol := range symbols {
-		fmt.Println(symbol.Name, symbol)
-		symnames[symbol.Name] = symbol
-	}
-
-	textSection := elfFile.Section(".text")
-	if textSection == nil {
-		fmt.Println("no text section", nil)
-		return nil, nil
-	}
-	textSectionData, err := textSection.Data()
-	if err != nil {
-		fmt.Println("failed to read text section", err)
-		return nil, nil
-	}
-	textSectionLen := uint64(len(textSectionData) - 1)
-
-	//  遍历符号表
-	for _, symbol := range symbols {
-		if debugelf.ST_TYPE(symbol.Info) != debugelf.STT_FUNC {
-			continue
-		}
-		// fmt.Println("Hello FunName: ", symbol.Name)
-		// 使用正则表达式匹配函数白名单列表
-		found, err := regexp.MatchString(MatchString, symbol.Name)
-		// found, err := regexp.MatchString("main.*", symbol.Name)
-
-		if err != nil {
-			log.Fatal(err)
-		}
-
-		if found {
-			// 匹配到了加入 attachFuncs 列表
-			fmt.Printf("Fuck This: %s, %x\n", symbol.Name, symbol.Value)
-			// attachFuncs = append(attachFuncs, symbol.Name)
-			// 根据函数名拿到当前函数的符号结构体
-			sym := symnames[symbol.Name]
-			if err != nil {
-				fmt.Printf("symnames[symbol.Name]", symbol.Name, err)
-				return nil, err
-			}
-
-			address := sym.Value
-			for _, p := range elfFile.Progs {
-				if p.Type != elf.PT_LOAD || (p.Flags&elf.PF_X) == 0 {
-					continue
-				}
-
-				if p.Vaddr <= sym.Value && sym.Value < (p.Vaddr+p.Memsz) {
-					address = sym.Value - p.Vaddr + p.Off
-					break
-				}
-			}
-
-			// 函数入口加入待 attach 列表
-			uprobes = append(uprobes, tracer.Uprobe{
-				Funcname:  symbol.Name,    // 函数名
-				Location:  tracer.AtEntry, // 入口
-				Address:   address,        // 函数地址
-				AbsOffset: 0,              // 函数相对 ELF 偏移
-				RelOffset: 0,              // 函数真实偏移
-				Wanted:    true,
-			})
-
-			sStart := sym.Value - textSection.Addr
-			sEnd := sStart + sym.Size
-			if sEnd > textSectionLen {
-				continue
-			}
-			sBytes := textSectionData[sStart:sEnd]
-			returnOffsets := getReturnOffsets(elfFile.Machine, sBytes)
-
-			for _, offset := range returnOffsets {
-				uprobes = append(uprobes, tracer.Uprobe{
-					Funcname:  symbol.Name,
-					Location:  tracer.AtRet,
-					Address:   address,
-					AbsOffset: uint64(offset),
-					RelOffset: 0,
-				})
-			}
-		}
-	}
-	return uprobes, nil
-}
-
-func (t *Tracer) attachUprobes(path string, uprobes []tracer.Uprobe) []link.Link {
+func (t *Tracer) AttachStackUprobes(path string, uprobes []tracer.Uprobe) []link.Link {
 	var links []link.Link
 
 	ex, err := link.OpenExecutable(path)
@@ -371,39 +38,3 @@ func (t *Tracer) attachUprobes(path string, uprobes []tracer.Uprobe) []link.Link
 	}
 	return links
 }
-
-func (t *Tracer) detachUprobes(links []link.Link) {
-	sem := semaphore.NewWeighted(10)
-	for i, closer := range links {
-		fmt.Printf("detaching %d/%d\r", i+1, len(links))
-		sem.Acquire(context.Background(), 1)
-		go func(closer io.Closer) {
-			defer sem.Release(1)
-			closer.Close()
-		}(closer)
-	}
-	fmt.Println()
-}
-
-func getRbpEnterOffsets(machine elf.Machine, instructions []byte) int {
-	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.LEA && ins.Args[0].String() == "RBP" {
-				fmt.Printf("getRbpEnterOffsets: %v, %s, %s\n", ins, ins.Args[0].String(), ins.Args[1].String())
-				return i
-			}
-			i += ins.Len
-		}
-	case elf.EM_AARCH64:
-		for i := 0; i < len(instructions); {
-			ins, err := arm64asm.Decode(instructions[i:])
-			if err == nil && ins.Op == arm64asm.RET {
-				return i
-			}
-			i += 4
-		}
-	}
-	return 0
-}

+ 3 - 4
ebpftracer/tracer.go

@@ -153,9 +153,6 @@ func (t *Tracer) Run(events chan<- Event) error {
 	if err := t.ebpf(events); err != nil {
 		return err
 	}
-	if err := t.stack(); err != nil {
-		return err
-	}
 	if err := t.init(events); err != nil {
 		return err
 	}
@@ -706,7 +703,7 @@ func ipPort(ip [16]byte, port uint16) netaddr.IPPort {
 	return netaddr.IPPortFrom(i, port)
 }
 
-func (t *Tracer) InitKProcInfo(pid uint32, insID utils.ID) error {
+func (t *Tracer) InitKProcInfo(pid uint32, insID utils.ID, codeType uint16) error {
 
 	info := tracer.EbpfProcInfo{}
 	info.InstanceId = insID.HashtVal
@@ -716,6 +713,8 @@ func (t *Tracer) InitKProcInfo(pid uint32, insID utils.ID) error {
 		info.StartAddr = allocDetails.StartAddr
 		info.EndAddr = allocDetails.EndAddr
 	}
+
+	info.CodeType = codeType
 	//klog.Infoln("Major:", major)
 	//klog.Infoln("Minor:", minor)
 	//klog.Infoln("Revision:", revision)

+ 1 - 0
ebpftracer/tracer/common.go

@@ -182,6 +182,7 @@ type EbpfProcInfo struct {
 	StartAddr                  uint64
 	EndAddr                    uint64
 	InstanceId                 utils.HashByte
+	CodeType                   uint16
 	// go http
 	MethodPtrPos   uint64
 	UrlPtrPos      uint64