1package shared 2 3import ( 4 "fmt" 5 "os" 6 "os/exec" 7 "strings" 8 "syscall" 9) 10 11var ( 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. 17func 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(). 28func 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. 34func 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