javaAot.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. package ebpftracer
  2. import (
  3. "debug/elf"
  4. "errors"
  5. "fmt"
  6. "log"
  7. "os"
  8. "github.com/cilium/ebpf/link"
  9. "github.com/coroot/coroot-node-agent/ebpftracer/tracer/aotinject"
  10. . "github.com/coroot/coroot-node-agent/utils/modelse"
  11. klog "github.com/sirupsen/logrus"
  12. )
  13. func (t *Tracer) AttachJavaAotNioReadUprobes(pid uint32, codeType CodeType, rootfs string) ([]link.Link, error) {
  14. if t.DisableL7Tracing() {
  15. return nil, nil
  16. }
  17. var links []link.Link
  18. var bpath string
  19. // 根据进程 pid 获取进程的可执行文件路径
  20. bpath, err := os.Readlink(fmt.Sprintf("/proc/%d/exe", pid))
  21. if err != nil {
  22. log.Fatalf("Failed to read proc path: %v", err)
  23. }
  24. fmt.Printf("procPath: %s\n", bpath)
  25. //bpath = rootfs + bpath
  26. klog.Infof("[attach] find the nio.so path is %s", bpath)
  27. readInfo, _ := aotinject.GetProcessFunctionInfo(int(pid), bpath, symbolsocketRead0)
  28. if readInfo == nil {
  29. return nil, fmt.Errorf("can not find %s", symbolsocketRead0)
  30. }
  31. // 打印 readInfo
  32. klog.Infof("[attach] AttachJavaAotNioReadUprobes readInfo %v", readInfo)
  33. ef, err := elf.Open(bpath)
  34. if err != nil {
  35. klog.Errorf("[attach] open elf: %v", err)
  36. return nil, err
  37. }
  38. defer ef.Close()
  39. textSection := ef.Section(".text")
  40. if textSection == nil {
  41. return nil, errors.New("can not find .text section")
  42. }
  43. textSectionData, err := textSection.Data()
  44. if err != nil {
  45. return nil, err
  46. }
  47. textSectionLen := uint64(len(textSectionData) - 1)
  48. // 打印 textSectionLen
  49. klog.Infof("[attach] AttachJavaAotNioReadUprobes textSectionLen %d{0x%x}", textSectionLen, textSection.Addr)
  50. sStart := readInfo.Offset - textSection.Addr
  51. sEnd := sStart + readInfo.Size
  52. if sEnd > textSectionLen {
  53. klog.Infof("[attach] AttachJavaAotNioReadUprobes sEnd > textSectionLen %d, %d", textSectionLen, sEnd)
  54. return nil, fmt.Errorf("can not find %s", symbolsocketRead0)
  55. }
  56. sBytes := textSectionData[sStart:sEnd]
  57. // 打印 sBytes
  58. returnOffsets := getCallNextMoveOffsets(ef.Machine, sBytes)
  59. if len(returnOffsets) == 0 {
  60. return nil, fmt.Errorf("failed to find call in uprobe_ret_Java_sun_nio_ch_FileDispatcherImpl_read0")
  61. }
  62. klog.Infof("[attach] java symbol offset is %v", returnOffsets)
  63. for _, offset := range returnOffsets {
  64. klog.Infof("[attach] java symbol offset is %d", offset)
  65. ex, err := link.OpenExecutable(bpath)
  66. if err != nil {
  67. klog.Errorf("[attach] open executable: %v", err)
  68. return nil, err
  69. }
  70. l, err := ex.Uprobe(readInfo.Name, t.uprobes["uprobe_ret_Java_sun_nio_ch_FileDispatcherImpl_read0"], &link.UprobeOptions{Address: readInfo.Offset, Offset: uint64(offset), PID: int(pid)})
  71. if err != nil {
  72. return nil, fmt.Errorf("failed to attach uprobe_ret_Java_sun_nio_ch_FileDispatcherImpl_read0 uprobe")
  73. }
  74. links = append(links, l)
  75. }
  76. if len(links) == 0 {
  77. return nil, fmt.Errorf("no links found for %s", bpath)
  78. }
  79. klog.WithField("pid", pid).Infof("[attach] libnio attached!")
  80. return links, nil
  81. }
  82. func (t *Tracer) AttachJavaAotNetWriteUprobes(pid uint32, rootfs string) ([]link.Link, error) {
  83. if t.DisableL7Tracing() {
  84. return nil, nil
  85. }
  86. // 根据进程 pid 获取进程的可执行文件路径
  87. procPath, err := os.Readlink(fmt.Sprintf("/proc/%d/exe", pid))
  88. if err != nil {
  89. log.Fatalf("Failed to read proc path: %v", err)
  90. }
  91. fmt.Printf("procPath: %s\n", procPath)
  92. sendFunctionName := "NET_Send"
  93. injectFunctionName := "Java_java_net_SocketOutputStream_socketWrite0"
  94. // NETCoreAOTInject
  95. aotInjector := aotinject.AOTInjector{
  96. PID: int(pid),
  97. SendFunctionLibPath: procPath,
  98. SendFunctionName: sendFunctionName,
  99. InjectLibPath: procPath,
  100. InjectFunctionName: injectFunctionName,
  101. CWLibName: "libmylib.so",
  102. CWFunctionName: "asmnop",
  103. CWLibPath: "/data/roger/ebpfdemo/mylib/libmylib.so",
  104. }
  105. // 打印 aotInjector
  106. fmt.Printf("aotInjector: %v\n", aotInjector)
  107. hookOffset, err := aotinject.AotInject(aotInjector)
  108. // 打印 hookOffset
  109. fmt.Printf("hookOffset: %d\n", hookOffset)
  110. if (hookOffset == 0) || (err != nil) {
  111. fmt.Println("failed to inject SystemNative_Send", err)
  112. return nil, err
  113. }
  114. var links []link.Link
  115. ex, err := link.OpenExecutable(aotInjector.CWLibPath)
  116. if err != nil {
  117. return nil, err
  118. }
  119. opt := link.UprobeOptions{
  120. Offset: uint64(hookOffset),
  121. PID: int(pid),
  122. }
  123. upread02, err := ex.Uprobe(aotInjector.CWFunctionName, t.uprobes["javaaot_asmnop"], &opt)
  124. if err != nil {
  125. return nil, err
  126. }
  127. links = append(links, upread02)
  128. if len(links) == 0 {
  129. return nil, nil
  130. }
  131. fmt.Println("netcore client uprobes attached", pid)
  132. return links, nil
  133. }