stack.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. package ebpftracer
  2. import (
  3. "bufio"
  4. "fmt"
  5. "github.com/cilium/ebpf"
  6. "github.com/cilium/ebpf/link"
  7. "github.com/coroot/coroot-node-agent/ebpftracer/tracer"
  8. "github.com/coroot/coroot-node-agent/ebpftracer/tracer/jattach"
  9. "github.com/coroot/coroot-node-agent/utils"
  10. . "github.com/coroot/coroot-node-agent/utils/modelse"
  11. klog "github.com/sirupsen/logrus"
  12. "os"
  13. "path/filepath"
  14. "strings"
  15. )
  16. // AttachStackUprobes
  17. // default process stack
  18. func (t *Tracer) AttachStackUprobes(path string, uprobes []tracer.Uprobe) []link.Link {
  19. var links []link.Link
  20. ex, err := link.OpenExecutable(path)
  21. if err != nil {
  22. return nil
  23. }
  24. klog.Infoln("[stack] Attach Start", path)
  25. for i, up := range uprobes {
  26. klog.Debugf("[stack] attaching %d -> %d -> %s -> 0x%x -> 0x%x -> 0x%x", i, len(uprobes), up.Funcname, up.AbsOffset, up.Address, up.AbsOffset+up.Address)
  27. var prog *ebpf.Program
  28. switch up.Location {
  29. case tracer.AtEntry:
  30. prog = t.uprobes["ent"]
  31. case tracer.AtRet:
  32. prog = t.uprobes["ret"]
  33. case tracer.AtDotNetEntry:
  34. prog = t.uprobes["dotnetent"]
  35. }
  36. uplink, err := ex.Uprobe(up.Funcname, prog, &link.UprobeOptions{Address: up.Address, Offset: up.AbsOffset})
  37. if err != nil {
  38. klog.Errorf("[stack] attachingERROR:%v, %v, %v", err, up, uplink)
  39. // return nil
  40. } else {
  41. links = append(links, uplink)
  42. }
  43. }
  44. return links
  45. }
  46. // JVM process stack
  47. func (t *Tracer) AttachJVMStackUprobes(pid uint32, appInfo AppInfo) ([]link.Link, error) {
  48. klog.Infoln("[Jvm stack uprobe] Attach Start AttachJVMStackUprobes", pid)
  49. // TODO tiny Agent 注入
  50. //argkv := "/opt/github/euspace/dist/package_dir/agents/NativeAgent/lib/apmAgent.jar=/opt/github/euspace/dist/package_dir/agents/NativeAgent"
  51. nativeBasePath := utils.GetDefaultAgentsPath("NativeAgent")
  52. kvPairs := []string{
  53. fmt.Sprintf("%s=%s", filepath.Join(nativeBasePath, "lib", "apmAgent.jar"), nativeBasePath),
  54. fmt.Sprintf("%s=%d", "appId", appInfo.AppIdHash.IntVal),
  55. fmt.Sprintf("%s=%d", "agentId", appInfo.AgentId),
  56. fmt.Sprintf("%s=%d", "hostId", utils.GetIntHostID()),
  57. fmt.Sprintf("%s=%d", "accountId", utils.GetAccountID()),
  58. }
  59. argkv := strings.Join(kvPairs, ",")
  60. klog.Infof("[Jvm stack uprobe] params:[%s]", argkv)
  61. args := []string{"load", "instrument", "false", argkv}
  62. jattacher := jattach.JvmJattacher{
  63. Pid: pid,
  64. Args: args,
  65. PrintOutput: 1,
  66. }
  67. res, err := jattacher.JAttach()
  68. klog.Infof("[Jvm stack uprobe] JAttach Result: %d", res)
  69. if err != nil {
  70. return nil, err
  71. }
  72. //path = utils.GetDefaultAgentsPath("NativeAgent", "libnativeAgent.so")
  73. //tmp/NativeAgentSo2297066477572820801.tmp
  74. path, err := FindNativeSoFromMapped(pid, "NativeAgentSo", ".tmp")
  75. if err != nil {
  76. klog.Error(err)
  77. return nil, err
  78. }
  79. setNodeEnter := "Java_com_cloudwise_agent_common_natives_TraceNative_setNodeEnter"
  80. setNodeReturn := "Java_com_cloudwise_agent_common_natives_TraceNative_setNodeReturn"
  81. klog.Infoln("[Jvm stack uprobe] Attach Start AttachJVMStackUprobes", path)
  82. var links []link.Link
  83. ex, err := link.OpenExecutable(path)
  84. if err != nil {
  85. klog.Error(err)
  86. return nil, err
  87. }
  88. klog.Infof("[Jvm stack uprobe] Attach Start [%s] [%s] ", setNodeEnter, setNodeReturn)
  89. uplink, err := ex.Uprobe(setNodeEnter, t.uprobes["setNodeEnter"], &link.UprobeOptions{Offset: 0x0, PID: int(pid)})
  90. if err != nil {
  91. klog.Errorf("[Jvm stack uprobe] Attaching ERROR: %v, %v, %v\n", err, setNodeEnter, uplink)
  92. return nil, err
  93. } else {
  94. links = append(links, uplink)
  95. }
  96. klog.Infoln("Attach Start " + setNodeReturn)
  97. uplink, err = ex.Uprobe(setNodeReturn, t.uprobes["setNodeReturn"], &link.UprobeOptions{Offset: 0x0})
  98. if err != nil {
  99. klog.Errorf("[Jvm stack uprobe] Attaching ERROR: %v, %v, %v\n", err, setNodeReturn, uplink)
  100. return nil, err
  101. } else {
  102. links = append(links, uplink)
  103. }
  104. return links, nil
  105. }
  106. func FindNativeSoFromMapped(pid uint32, prefix, suffix string) (string, error) {
  107. // todo rootfs
  108. mapsFile := fmt.Sprintf("/proc/%d/maps", pid)
  109. tmpFile, err := os.Open(mapsFile)
  110. if err != nil {
  111. return "", fmt.Errorf("error opening maps file: %v", err)
  112. }
  113. defer tmpFile.Close()
  114. // 使用 bufio.Scanner 逐行读取文件内容
  115. scanner := bufio.NewScanner(tmpFile)
  116. for scanner.Scan() {
  117. line := scanner.Text()
  118. // 检查路径部分是否包含 "NativeAgentSo" 且以 ".tmp" 结尾
  119. if strings.Contains(line, prefix) && strings.HasSuffix(line, suffix) {
  120. parts := strings.Fields(line)
  121. if len(parts) > 5 {
  122. return parts[len(parts)-1], nil // 返回路径
  123. }
  124. }
  125. }
  126. if err = scanner.Err(); err != nil {
  127. return "", fmt.Errorf("error reading maps file: %v", err)
  128. }
  129. return "", fmt.Errorf("no matching path found")
  130. }