offset.go 4.2 KB

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