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//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//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 }