netcore.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. package ebpftracer
  2. import (
  3. "bufio"
  4. "errors"
  5. "io"
  6. "log"
  7. "os"
  8. "strconv"
  9. "strings"
  10. "debug/dwarf"
  11. "debug/elf"
  12. "fmt"
  13. "github.com/coroot/coroot-node-agent/utils"
  14. "github.com/cilium/ebpf/link"
  15. )
  16. const (
  17. // goServeHTTP = "net/http.serverHandler.ServeHTTP"
  18. // binPath = "/root/code/jdk8u/build/linux-x86_64-normal-server-release/jdk/lib/amd64/libnio.so"
  19. libPath = "/data/roger/NET8/CoreAoT/bin/Release/net8.0/linux-x64/publish/CoreAoT"
  20. netcoresymbolsocketRead0 = "SystemNative_Receive"
  21. )
  22. type MemoryMap struct {
  23. Start, End uint64
  24. }
  25. func ReadFirstLineOfMapsFile(pid string) (*MemoryMap, error) {
  26. file, err := os.Open(fmt.Sprintf("/proc/%s/maps", pid))
  27. if err != nil {
  28. return nil, err
  29. }
  30. defer file.Close()
  31. scanner := bufio.NewScanner(file)
  32. if scanner.Scan() {
  33. fields := strings.Fields(scanner.Text())
  34. addresses := strings.Split(fields[0], "-")
  35. if len(addresses) != 2 {
  36. return nil, errors.New("unexpected format in /proc/<pid>/maps")
  37. }
  38. start, err := strconv.ParseUint(addresses[0], 16, 64)
  39. if err != nil {
  40. return nil, err
  41. }
  42. end, err := strconv.ParseUint(addresses[1], 16, 64)
  43. if err != nil {
  44. return nil, err
  45. }
  46. return &MemoryMap{
  47. Start: start,
  48. End: end,
  49. }, nil
  50. }
  51. if err := scanner.Err(); err != nil {
  52. return nil, err
  53. }
  54. return nil, errors.New("empty /proc/<pid>/maps")
  55. }
  56. func (t *Tracer) getFunctionOffsetDBG(libPath, functionName string) (elf.Symbol, error) {
  57. dwarfFile, err := elf.Open(libPath)
  58. dwarfData, err := dwarfFile.DWARF()
  59. if err != nil {
  60. log.Fatal(err)
  61. }
  62. type uprobesDef struct {
  63. Name string
  64. Offset uint64
  65. EntAddress uint64
  66. RetAddress uint64
  67. }
  68. listEntry := make(map[dwarf.Offset]uprobesDef)
  69. SpecListEntry := []dwarf.Entry{}
  70. entryReader := dwarfData.Reader()
  71. for {
  72. entry, err := entryReader.Next()
  73. if err == io.EOF {
  74. // We've reached the end of DWARF entries
  75. break
  76. }
  77. if err != nil {
  78. log.Fatalf("Error reading entry: %v", err)
  79. }
  80. if entry == nil {
  81. log.Println("Warning: a nil entry was returned with no error")
  82. break
  83. }
  84. if entry.Tag == dwarf.TagSubprogram {
  85. // fmt.Printf("entry address: %x, %d\n", entry.Offset, entry.Children)
  86. funName, _ := entry.Val(dwarf.AttrName).(string)
  87. if functionName == funName {
  88. entAddress, _ := entry.Val(dwarf.AttrLowpc).(uint64)
  89. retAddress, _ := entry.Val(dwarf.AttrHighpc).(uint64)
  90. fmt.Printf("Function %s address: %x, %x, %x\n", funName, entAddress, entry.Offset, retAddress)
  91. uprobes := uprobesDef{}
  92. uprobes.EntAddress = entAddress
  93. uprobes.RetAddress = retAddress
  94. uprobes.Offset = uint64(entry.Offset)
  95. uprobes.Name = funName
  96. listEntry[entry.Offset] = uprobes
  97. }
  98. specAddr, _ := entry.Val(dwarf.AttrSpecification).(dwarf.Offset)
  99. lowpc := entry.Val(dwarf.AttrLowpc)
  100. if lowpc != nil && specAddr > 0 && lowpc.(uint64) > 0 {
  101. // fmt.Printf("AttrSpecification address: %x, %x\n", specAddr, entry.Offset)
  102. SpecListEntry = append(SpecListEntry, *entry)
  103. }
  104. }
  105. }
  106. for _, v := range SpecListEntry {
  107. specAddr, _ := v.Val(dwarf.AttrSpecification).(dwarf.Offset)
  108. // fmt.Printf("SpecListEntrySpecListEntrySpecListEntry Attach Function: %x\n", specAddr)
  109. _, ok := listEntry[specAddr]
  110. if ok {
  111. vv := listEntry[specAddr]
  112. entAddr := v.Val(dwarf.AttrLowpc)
  113. if entAddr != nil {
  114. vv.EntAddress = entAddr.(uint64)
  115. }
  116. retAddr := v.Val(dwarf.AttrHighpc)
  117. if retAddr != nil {
  118. switch retAddr.(type) {
  119. case uint64:
  120. vv.RetAddress = uint64(retAddr.(uint64))
  121. case int64:
  122. vv.RetAddress = uint64(retAddr.(int64))
  123. default:
  124. fmt.Println("Unknown type")
  125. }
  126. }
  127. listEntry[specAddr] = vv
  128. }
  129. }
  130. for _, v := range listEntry {
  131. sSize := v.RetAddress
  132. if v.RetAddress > v.EntAddress {
  133. sSize = v.RetAddress - v.EntAddress
  134. }
  135. symbol := elf.Symbol{}
  136. symbol.Name = v.Name
  137. symbol.Value = v.EntAddress
  138. symbol.Size = 180
  139. fmt.Printf("Need Attach Function %s address: %x, %x, %d\n", v.Name, v.EntAddress, v.RetAddress, sSize)
  140. return symbol, nil
  141. }
  142. return elf.Symbol{}, fmt.Errorf("function %s not found", functionName)
  143. }
  144. func (t *Tracer) AttachNetCoreNetReadUprobes(pid uint32, insID utils.ID) []link.Link {
  145. if t.disableL7Tracing {
  146. return nil
  147. }
  148. var links []link.Link
  149. ex, err := link.OpenExecutable(libPath)
  150. // 获取函数的偏移量
  151. functionSym, err := t.getFunctionOffsetDBG(libPath+".dbg", netcoresymbolsocketRead0)
  152. l, err := ex.Uprobe(functionSym.Name, t.uprobes["SystemNative_Receive"], &link.UprobeOptions{Address: functionSym.Value, Offset: 113})
  153. if err != nil {
  154. fmt.Println("failed to attach SystemNative_Receive uprobe", err, functionSym)
  155. return nil
  156. }
  157. links = append(links, l)
  158. if len(links) == 0 {
  159. return nil
  160. }
  161. fmt.Println("netcore uprobes attached, pid is ", pid)
  162. return links
  163. }
  164. func (t *Tracer) AttachNetCoreNetWriteUprobes(pid uint32, insID utils.ID) []link.Link {
  165. if t.disableL7Tracing {
  166. return nil
  167. }
  168. //
  169. //if pid != 251719 {
  170. // return nil
  171. //}
  172. var libnetSo = "/data/roger/han/libmylib.so"
  173. var sys = "asmnop"
  174. var links []link.Link
  175. ex, err := link.OpenExecutable(libnetSo)
  176. if err != nil {
  177. return nil
  178. }
  179. opt := link.UprobeOptions{
  180. Offset: 16,
  181. PID: int(pid),
  182. }
  183. upread02, err := ex.Uprobe(sys, t.uprobes["netcore_asmnop"], &opt)
  184. if err != nil {
  185. return nil
  186. }
  187. links = append(links, upread02)
  188. if len(links) == 0 {
  189. return nil
  190. }
  191. fmt.Println("netcore client uprobes attached", pid)
  192. return links
  193. }