summaryrefslogtreecommitdiff
path: root/shared/debug.go
blob: 5392f2b7991d58a81ecaf5e78d5d6baaa35a9f4e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package shared

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
	"syscall"
)

var (
	isDebugging bool
)

// Finds the Delve binary to use. Either uses the SOONG_DELVE_PATH environment
// variable or if that is unset, looks at $PATH.
func ResolveDelveBinary() string {
	result := os.Getenv("SOONG_DELVE_PATH")
	if result == "" {
		result, _ = exec.LookPath("dlv")
	}

	return result
}

// Returns whether the current process is running under Delve due to
// ReexecWithDelveMaybe().
func IsDebugging() bool {
	return isDebugging
}

// Re-executes the binary in question under the control of Delve when
// delveListen is not the empty string. delvePath gives the path to the Delve.
func ReexecWithDelveMaybe(delveListen, delvePath string) {
	isDebugging = os.Getenv("SOONG_DELVE_REEXECUTED") == "true"
	if isDebugging || delveListen == "" {
		return
	}

	if delvePath == "" {
		fmt.Fprintln(os.Stderr, "Delve debugging requested but failed to find dlv")
		os.Exit(1)
	}

	soongDelveEnv := []string{}
	for _, env := range os.Environ() {
		idx := strings.IndexRune(env, '=')
		if idx != -1 {
			soongDelveEnv = append(soongDelveEnv, env)
		}
	}

	soongDelveEnv = append(soongDelveEnv, "SOONG_DELVE_REEXECUTED=true")

	dlvArgv := []string{
		delvePath,
		"--listen=:" + delveListen,
		"--headless=true",
		"--api-version=2",
		"exec",
		os.Args[0],
		"--",
	}

	dlvArgv = append(dlvArgv, os.Args[1:]...)
	syscall.Exec(delvePath, dlvArgv, soongDelveEnv)
	fmt.Fprintln(os.Stderr, "exec() failed while trying to reexec with Delve")
	os.Exit(1)
}