xref: /aosp_15_r20/build/soong/shared/debug.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1 package shared
2 
3 import (
4 	"fmt"
5 	"os"
6 	"os/exec"
7 	"strings"
8 	"syscall"
9 )
10 
11 var (
12 	isDebugging bool
13 )
14 
15 // Finds the Delve binary to use. Either uses the SOONG_DELVE_PATH environment
16 // variable or if that is unset, looks at $PATH.
17 func ResolveDelveBinary() string {
18 	result := os.Getenv("SOONG_DELVE_PATH")
19 	if result == "" {
20 		result, _ = exec.LookPath("dlv")
21 	}
22 
23 	return result
24 }
25 
26 // Returns whether the current process is running under Delve due to
27 // ReexecWithDelveMaybe().
28 func IsDebugging() bool {
29 	return isDebugging
30 }
31 
32 // Re-executes the binary in question under the control of Delve when
33 // delveListen is not the empty string. delvePath gives the path to the Delve.
34 func ReexecWithDelveMaybe(delveListen, delvePath string) {
35 	isDebugging = os.Getenv("SOONG_DELVE_REEXECUTED") == "true"
36 	if isDebugging || delveListen == "" {
37 		return
38 	}
39 
40 	if delvePath == "" {
41 		fmt.Fprintln(os.Stderr, "Delve debugging requested but failed to find dlv")
42 		os.Exit(1)
43 	}
44 
45 	soongDelveEnv := []string{}
46 	for _, env := range os.Environ() {
47 		idx := strings.IndexRune(env, '=')
48 		if idx != -1 {
49 			soongDelveEnv = append(soongDelveEnv, env)
50 		}
51 	}
52 
53 	soongDelveEnv = append(soongDelveEnv, "SOONG_DELVE_REEXECUTED=true")
54 
55 	dlvArgv := []string{
56 		delvePath,
57 		"--listen=:" + delveListen,
58 		"--headless=true",
59 		"--api-version=2",
60 		"exec",
61 		os.Args[0],
62 		"--",
63 	}
64 
65 	dlvArgv = append(dlvArgv, os.Args[1:]...)
66 	syscall.Exec(delvePath, dlvArgv, soongDelveEnv)
67 	fmt.Fprintln(os.Stderr, "exec() failed while trying to reexec with Delve")
68 	os.Exit(1)
69 }
70