Преглед изворни кода

python: search for `pthread_cond_timedwait` in both libc.so and libpthread.so

Nikolay Sivko пре 1 година
родитељ
комит
4c54df0c81
1 измењених фајлова са 38 додато и 36 уклоњено
  1. 38 36
      ebpftracer/python.go

+ 38 - 36
ebpftracer/python.go

@@ -8,6 +8,7 @@ import (
 
 	"github.com/cilium/ebpf/link"
 	"github.com/coroot/coroot-node-agent/proc"
+	"golang.org/x/exp/maps"
 	"k8s.io/klog/v2"
 )
 
@@ -17,68 +18,69 @@ var (
 )
 
 func (t *Tracer) AttachPythonThreadLockProbes(pid uint32) []link.Link {
-	exePath := getPthreadLib(pid)
-	if exePath == "" {
-		return nil
-	}
-
-	log := func(msg string, err error) {
+	log := func(libPath, msg string, err error) {
 		if err != nil {
 			for _, s := range []string{"no such file or directory", "no such process", "permission denied"} {
 				if strings.HasSuffix(err.Error(), s) {
 					return
 				}
 			}
-			klog.ErrorfDepth(1, "pid=%d lib=%s: %s: %s", pid, exePath, msg, err)
+			klog.ErrorfDepth(1, "pid=%d lib=%s: %s: %s", pid, libPath, msg, err)
 			return
 		}
-		klog.InfofDepth(1, "pid=%d lib=%s: %s", pid, exePath, msg)
-	}
-	exe, err := link.OpenExecutable(exePath)
-	if err != nil {
-		log("failed to open executable", err)
-		return nil
+		klog.InfofDepth(1, "pid=%d lib=%s: %s", pid, libPath, msg)
 	}
-	var links []link.Link
-	uprobe, err := exe.Uprobe("pthread_cond_timedwait", t.uprobes["pthread_cond_timedwait_enter"], nil)
-	if err != nil {
-		log("failed to attach uprobe", err)
-		return nil
+
+	var (
+		lastErr error
+		links   []link.Link
+		libPath string
+	)
+
+	for _, libPath = range getPthreadLibs(pid) {
+		exe, err := link.OpenExecutable(libPath)
+		if err != nil {
+			log(libPath, "failed to open executable", err)
+			return nil
+		}
+		var uprobe, uretprobe link.Link
+		uprobe, lastErr = exe.Uprobe("pthread_cond_timedwait", t.uprobes["pthread_cond_timedwait_enter"], nil)
+		if lastErr != nil {
+			continue
+		}
+		links = append(links, uprobe)
+		uretprobe, lastErr = exe.Uretprobe("pthread_cond_timedwait", t.uprobes["pthread_cond_timedwait_exit"], nil)
+		if lastErr != nil {
+			continue
+		}
+		links = append(links, uretprobe)
+		log(libPath, "python uprobes attached", nil)
+		break
 	}
-	links = append(links, uprobe)
-	uretprobe, err := exe.Uretprobe("pthread_cond_timedwait", t.uprobes["pthread_cond_timedwait_exit"], nil)
-	if err != nil {
-		log("failed to attach uretprobe", err)
-		return nil
+	if lastErr != nil {
+		log(libPath, "failed to attach uprobe", lastErr)
 	}
-	links = append(links, uretprobe)
-	log("python uprobes attached", nil)
 	return links
 }
 
-func getPthreadLib(pid uint32) string {
+func getPthreadLibs(pid uint32) []string {
 	f, err := os.Open(proc.Path(pid, "maps"))
 	if err != nil {
-		return ""
+		return nil
 	}
 	defer f.Close()
 	scanner := bufio.NewScanner(f)
 	scanner.Split(bufio.ScanLines)
-	libc := ""
+	libs := map[string]bool{}
 	for scanner.Scan() {
 		parts := strings.Fields(scanner.Text())
 		if len(parts) <= 5 {
 			continue
 		}
 		libPath := parts[5]
-		switch {
-		case libcRegexp.MatchString(libPath):
-			libc = proc.Path(pid, "root", libPath)
-		case muslRegexp.MatchString(libPath):
-			return proc.Path(pid, "root", libPath)
-		case strings.Contains(libPath, "libpthread"):
-			return proc.Path(pid, "root", libPath)
+		if libcRegexp.MatchString(libPath) || muslRegexp.MatchString(libPath) || strings.Contains(libPath, "libpthread") {
+			libs[proc.Path(pid, "root", libPath)] = true
 		}
 	}
-	return libc
+	return maps.Keys(libs)
 }