gdbserial/gdbserver: Dynamically resolve debugserver binary (#1994)

* gdbserial/gdbserver: Dynamically resolve debugserver binary

Instead of hardcoding the absolute path to the Command Line
Tools (CLT) binary, will attempt to resolve the path at the
$PATH, or at the Xcode bundle. If none are available, will
fallback to the default CLT location.

Fixes #986

* gdbserial/gdbserver: Log outgoing executed commands

Add logging to capture the executable and associated arguments used
in LLDBLaunch and LLDBAttach

Related to #986

* gdbserial/gdbserver: Add unit tests for helper function

Define unit tests for helper function. Setup each test to temporarily make
PATH variable, and file system changes, and subsequently revert them.

Related to #986

* gdbserial/gdbserver: Lazily load function

Lazily obtain absolute path to avoid increasing load times.

Remove flaky tests.

Related to #986
This commit is contained in:
Darren Rambaud 2020-04-09 15:48:38 -05:00 committed by GitHub
parent 0c9846c0a4
commit bc30b53926
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -299,7 +299,31 @@ func unusedPort() string {
return fmt.Sprintf(":%d", port)
}
const debugserverExecutable = "/Library/Developer/CommandLineTools/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/debugserver"
// Helper function to resolve path of "debugserver"
//
// Returns a string of the absolute path to the debugserver binary IFF it is
// found in the system path ($PATH) or in the Xcode bundle. Otherwise will
// return the path to the standalone CLT location
func GetDebugServerAbsolutePath() string {
if path, err := exec.LookPath("debugserver"); err == nil {
return path
}
if xcodePath, e := exec.LookPath("/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/Resources/debugserver"); e == nil {
return xcodePath
}
return "/Library/Developer/CommandLineTools/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/debugserver"
}
// Process logger function
//
// A wrapper around the exec.Command() function to log the arguments prior to
// starting the process
func commandLogger(binary string, arguments ...string) *exec.Cmd {
logflags.GdbWireLogger().Debugf("executing %s %v", binary, arguments)
return exec.Command(binary, arguments...)
}
// ErrUnsupportedOS is returned when trying to use the lldb backend on Windows.
var ErrUnsupportedOS = errors.New("lldb backend not supported on Windows")
@ -339,7 +363,7 @@ func LLDBLaunch(cmd []string, wd string, foreground bool, debugInfoDirs []string
var listener net.Listener
var port string
var process *exec.Cmd
if _, err := os.Stat(debugserverExecutable); err == nil {
if _, err := os.Stat(GetDebugServerAbsolutePath()); err == nil {
listener, err = net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return nil, err
@ -358,7 +382,7 @@ func LLDBLaunch(cmd []string, wd string, foreground bool, debugInfoDirs []string
isDebugserver = true
process = exec.Command(debugserverExecutable, args...)
process = commandLogger(GetDebugServerAbsolutePath(), args...)
} else {
if _, err := exec.LookPath("lldb-server"); err != nil {
return nil, &ErrBackendUnavailable{}
@ -368,7 +392,7 @@ func LLDBLaunch(cmd []string, wd string, foreground bool, debugInfoDirs []string
args = append(args, "gdbserver", port, "--")
args = append(args, cmd...)
process = exec.Command("lldb-server", args...)
process = commandLogger("lldb-server", args...)
}
if logflags.LLDBServerOutput() || logflags.GdbWire() || foreground {
@ -420,19 +444,19 @@ func LLDBAttach(pid int, path string, debugInfoDirs []string) (*proc.Target, err
var process *exec.Cmd
var listener net.Listener
var port string
if _, err := os.Stat(debugserverExecutable); err == nil {
if _, err := os.Stat(GetDebugServerAbsolutePath()); err == nil {
isDebugserver = true
listener, err = net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return nil, err
}
process = exec.Command(debugserverExecutable, "-R", fmt.Sprintf("127.0.0.1:%d", listener.Addr().(*net.TCPAddr).Port), "--attach="+strconv.Itoa(pid))
process = commandLogger(GetDebugServerAbsolutePath(), "-R", fmt.Sprintf("127.0.0.1:%d", listener.Addr().(*net.TCPAddr).Port), "--attach="+strconv.Itoa(pid))
} else {
if _, err := exec.LookPath("lldb-server"); err != nil {
return nil, &ErrBackendUnavailable{}
}
port = unusedPort()
process = exec.Command("lldb-server", "gdbserver", "--attach", strconv.Itoa(pid), port)
process = commandLogger("lldb-server", "gdbserver", "--attach", strconv.Itoa(pid), port)
}
process.Stdout = os.Stdout