netcore.go 5.3 KB

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