offset.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. package tracer
  2. import (
  3. "debug/dwarf"
  4. "debug/elf"
  5. "errors"
  6. "fmt"
  7. "github.com/cilium/ebpf"
  8. "io"
  9. "net"
  10. "os"
  11. "strings"
  12. )
  13. const (
  14. offsetInferServerAddr = "127.0.0.1"
  15. offsetInferServerPort = 54583
  16. bufferSize = 16
  17. )
  18. type ID struct {
  19. // ModPath is the module path containing the struct field package.
  20. //
  21. // If set to "std", the struct field belongs to the standard Go library.
  22. ModPath string
  23. // PkgPath package import path containing the struct field.
  24. PkgPath string
  25. // Struct is the name of the struct containing the field.
  26. Struct string
  27. // Field is the field name.
  28. Field string
  29. }
  30. func kernelOffsetInferServer(listener net.Listener) error {
  31. fmt.Println("[eBPF Kernel Adapt] kernel_offset_infer_server started.")
  32. //cpuOnlineCount := runtime.NumCPU()
  33. go func() {
  34. for {
  35. conn, err := listener.Accept()
  36. if err != nil {
  37. fmt.Printf("[eBPF Kernel Adapt] Fail to accept client request: %v\n", err)
  38. return
  39. }
  40. go handleConnection(conn)
  41. }
  42. }()
  43. return nil
  44. }
  45. func handleConnection(conn net.Conn) {
  46. defer conn.Close()
  47. buffer := make([]byte, bufferSize)
  48. for {
  49. n, err := conn.Read(buffer)
  50. if err != nil {
  51. if err == io.EOF {
  52. fmt.Printf("[eBPF Kernel Adapt] client connection closed: %v\n", err)
  53. return
  54. }
  55. fmt.Printf("[eBPF Kernel Adapt] Error reading from connection: %v\n", err)
  56. return
  57. }
  58. //if n == 0 {
  59. // *clientCount++
  60. // break
  61. //}
  62. request := strings.TrimSpace(string(buffer[:n]))
  63. fmt.Println(request)
  64. if request == "hello" {
  65. _, err := conn.Write([]byte("OK"))
  66. if err != nil {
  67. fmt.Printf("[eBPF Kernel Adapt] Error writing response: %v\n", err)
  68. break
  69. }
  70. }
  71. }
  72. }
  73. func kernelOffsetInferClient() error {
  74. conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", offsetInferServerAddr, offsetInferServerPort))
  75. if err != nil {
  76. return fmt.Errorf("failed to connect to server: %v", err)
  77. }
  78. defer conn.Close()
  79. fmt.Println("[eBPF Kernel Adapt] kernel_offset_infer_client started.")
  80. request := "hello"
  81. _, err = conn.Write([]byte(request))
  82. if err != nil {
  83. return fmt.Errorf("failed to send request to server: %v", err)
  84. }
  85. buffer := make([]byte, bufferSize)
  86. for {
  87. n, err := conn.Read(buffer)
  88. if err != nil {
  89. fmt.Printf("[eBPF Kernel Adapt] Error reading response from server: %v\n", err)
  90. break
  91. }
  92. if n == 0 {
  93. break
  94. }
  95. response := strings.TrimSpace(string(buffer[:n]))
  96. fmt.Println(response)
  97. if response == "OK" {
  98. break
  99. }
  100. }
  101. fmt.Println("[eBPF Kernel Adapt] kernel_offset_infer_client finished.")
  102. return nil
  103. }
  104. func NewID(mod, pkg, strct, field string) ID {
  105. return ID{ModPath: mod, PkgPath: pkg, Struct: strct, Field: field}
  106. }
  107. func gotoEntry(r *dwarf.Reader, tag dwarf.Tag, name string) bool {
  108. _, err := findEntry(r, tag, name)
  109. return err == nil
  110. }
  111. // findEntry returns the DWARF entry with a tag equal to name read from r. An
  112. // error is returned if the entry cannot be found.
  113. func findEntry(r *dwarf.Reader, tag dwarf.Tag, name string) (*dwarf.Entry, error) {
  114. for {
  115. entry, err := r.Next()
  116. if err == io.EOF || entry == nil {
  117. break
  118. }
  119. if entry.Tag == tag {
  120. if f, ok := entryField(entry, dwarf.AttrName); ok {
  121. if name == f.Val.(string) {
  122. return entry, nil
  123. }
  124. }
  125. }
  126. }
  127. return nil, errors.New("not found")
  128. }
  129. // entryField returns the DWARF field from DWARF entry e that has the passed
  130. // DWARF attribute a.
  131. func entryField(e *dwarf.Entry, a dwarf.Attr) (dwarf.Field, bool) {
  132. for _, f := range e.Field {
  133. if f.Attr == a {
  134. return f, true
  135. }
  136. }
  137. return dwarf.Field{}, false
  138. }
  139. func GetOffset(id ID, path string) (uint64, bool) {
  140. strct := fmt.Sprintf("%s.%s", id.PkgPath, id.Struct)
  141. elfF, err := elf.Open(path)
  142. if err != nil {
  143. os.Exit(1)
  144. }
  145. defer elfF.Close()
  146. data, err := elfF.DWARF()
  147. fmt.Println(err)
  148. r := data.Reader()
  149. if !gotoEntry(r, dwarf.TagStructType, strct) {
  150. return 0, false
  151. }
  152. e, err := findEntry(r, dwarf.TagMember, id.Field)
  153. if err != nil {
  154. return 0, false
  155. }
  156. f, ok := entryField(e, dwarf.AttrDataMemberLoc)
  157. if !ok {
  158. return 0, false
  159. }
  160. return uint64(f.Val.(int64)), true
  161. }
  162. func UpdateProcInfoToMap(collection *ebpf.Collection, pid uint32, proc any) (int, error) {
  163. return bpf_table_set_value(collection, MAP_PROC_INFO_MAP_NAME, pid, proc)
  164. }