Skip to content

Commit 24438aa

Browse files
authored
[lldb] Use Socket::CreatePair for launching debugserver (#145017)
This lets get rid of platform-specific code in ProcessGDBRemote and use the same code path (module differences in socket types) everywhere. It also unlocks further cleanups in the debugserver launching code. The main effect of this change is that lldb on windows will now use the `--fd` lldb-server argument for "local remote" debug sessions instead of having lldb-server connect back to lldb. This is the same method used by lldb on non-windows platforms (for many years) and "lldb-server platform" on windows for truly remote debug sessions (for ~one year). Depends on #145015.
1 parent 371f12f commit 24438aa

File tree

1 file changed

+55
-90
lines changed

1 file changed

+55
-90
lines changed

lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp

Lines changed: 55 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -3447,115 +3447,80 @@ ProcessGDBRemote::EstablishConnectionIfNeeded(const ProcessInfo &process_info) {
34473447
}
34483448
return error;
34493449
}
3450-
#if !defined(_WIN32)
3451-
#define USE_SOCKETPAIR_FOR_LOCAL_CONNECTION 1
3452-
#endif
3453-
3454-
#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
3455-
static bool SetCloexecFlag(int fd) {
3456-
#if defined(FD_CLOEXEC)
3457-
int flags = ::fcntl(fd, F_GETFD);
3458-
if (flags == -1)
3459-
return false;
3460-
return (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0);
3461-
#else
3462-
return false;
3463-
#endif
3464-
}
3465-
#endif
34663450

34673451
Status ProcessGDBRemote::LaunchAndConnectToDebugserver(
34683452
const ProcessInfo &process_info) {
34693453
using namespace std::placeholders; // For _1, _2, etc.
34703454

3471-
Status error;
3472-
if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID) {
3473-
// If we locate debugserver, keep that located version around
3474-
static FileSpec g_debugserver_file_spec;
3455+
if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
3456+
return Status();
34753457

3476-
ProcessLaunchInfo debugserver_launch_info;
3477-
// Make debugserver run in its own session so signals generated by special
3478-
// terminal key sequences (^C) don't affect debugserver.
3479-
debugserver_launch_info.SetLaunchInSeparateProcessGroup(true);
3458+
ProcessLaunchInfo debugserver_launch_info;
3459+
// Make debugserver run in its own session so signals generated by special
3460+
// terminal key sequences (^C) don't affect debugserver.
3461+
debugserver_launch_info.SetLaunchInSeparateProcessGroup(true);
34803462

3481-
const std::weak_ptr<ProcessGDBRemote> this_wp =
3482-
std::static_pointer_cast<ProcessGDBRemote>(shared_from_this());
3483-
debugserver_launch_info.SetMonitorProcessCallback(
3484-
std::bind(MonitorDebugserverProcess, this_wp, _1, _2, _3));
3485-
debugserver_launch_info.SetUserID(process_info.GetUserID());
3463+
const std::weak_ptr<ProcessGDBRemote> this_wp =
3464+
std::static_pointer_cast<ProcessGDBRemote>(shared_from_this());
3465+
debugserver_launch_info.SetMonitorProcessCallback(
3466+
std::bind(MonitorDebugserverProcess, this_wp, _1, _2, _3));
3467+
debugserver_launch_info.SetUserID(process_info.GetUserID());
34863468

34873469
#if defined(__APPLE__)
3488-
// On macOS 11, we need to support x86_64 applications translated to
3489-
// arm64. We check whether a binary is translated and spawn the correct
3490-
// debugserver accordingly.
3491-
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID,
3492-
static_cast<int>(process_info.GetProcessID()) };
3493-
struct kinfo_proc processInfo;
3494-
size_t bufsize = sizeof(processInfo);
3495-
if (sysctl(mib, (unsigned)(sizeof(mib)/sizeof(int)), &processInfo,
3496-
&bufsize, NULL, 0) == 0 && bufsize > 0) {
3497-
if (processInfo.kp_proc.p_flag & P_TRANSLATED) {
3498-
FileSpec rosetta_debugserver("/Library/Apple/usr/libexec/oah/debugserver");
3499-
debugserver_launch_info.SetExecutableFile(rosetta_debugserver, false);
3500-
}
3470+
// On macOS 11, we need to support x86_64 applications translated to
3471+
// arm64. We check whether a binary is translated and spawn the correct
3472+
// debugserver accordingly.
3473+
int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID,
3474+
static_cast<int>(process_info.GetProcessID())};
3475+
struct kinfo_proc processInfo;
3476+
size_t bufsize = sizeof(processInfo);
3477+
if (sysctl(mib, (unsigned)(sizeof(mib) / sizeof(int)), &processInfo, &bufsize,
3478+
NULL, 0) == 0 &&
3479+
bufsize > 0) {
3480+
if (processInfo.kp_proc.p_flag & P_TRANSLATED) {
3481+
FileSpec rosetta_debugserver(
3482+
"/Library/Apple/usr/libexec/oah/debugserver");
3483+
debugserver_launch_info.SetExecutableFile(rosetta_debugserver, false);
35013484
}
3485+
}
35023486
#endif
35033487

3504-
shared_fd_t communication_fd = SharedSocket::kInvalidFD;
3505-
#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
3506-
// Use a socketpair on non-Windows systems for security and performance
3507-
// reasons.
3508-
int sockets[2]; /* the pair of socket descriptors */
3509-
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) {
3510-
error = Status::FromErrno();
3511-
return error;
3512-
}
3488+
llvm::Expected<Socket::Pair> socket_pair = Socket::CreatePair();
3489+
if (!socket_pair)
3490+
return Status::FromError(socket_pair.takeError());
35133491

3514-
int our_socket = sockets[0];
3515-
int gdb_socket = sockets[1];
3516-
auto cleanup_our = llvm::make_scope_exit([&]() { close(our_socket); });
3517-
auto cleanup_gdb = llvm::make_scope_exit([&]() { close(gdb_socket); });
3492+
Status error;
3493+
SharedSocket shared_socket(socket_pair->first.get(), error);
3494+
if (error.Fail())
3495+
return error;
35183496

3519-
// Don't let any child processes inherit our communication socket
3520-
SetCloexecFlag(our_socket);
3521-
communication_fd = gdb_socket;
3522-
#endif
3497+
error = m_gdb_comm.StartDebugserverProcess(
3498+
nullptr, GetTarget().GetPlatform().get(), debugserver_launch_info,
3499+
nullptr, nullptr, shared_socket.GetSendableFD());
35233500

3524-
error = m_gdb_comm.StartDebugserverProcess(
3525-
nullptr, GetTarget().GetPlatform().get(), debugserver_launch_info,
3526-
nullptr, nullptr, communication_fd);
3501+
if (error.Fail()) {
3502+
Log *log = GetLog(GDBRLog::Process);
35273503

3528-
if (error.Success())
3529-
m_debugserver_pid = debugserver_launch_info.GetProcessID();
3530-
else
3531-
m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
3532-
3533-
if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) {
3534-
#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
3535-
// Our process spawned correctly, we can now set our connection to use
3536-
// our end of the socket pair
3537-
cleanup_our.release();
3538-
m_gdb_comm.SetConnection(
3539-
std::make_unique<ConnectionFileDescriptor>(our_socket, true));
3540-
#endif
3541-
StartAsyncThread();
3542-
}
3504+
LLDB_LOGF(log, "failed to start debugserver process: %s",
3505+
error.AsCString());
3506+
return error;
3507+
}
35433508

3544-
if (error.Fail()) {
3545-
Log *log = GetLog(GDBRLog::Process);
3509+
m_debugserver_pid = debugserver_launch_info.GetProcessID();
3510+
shared_socket.CompleteSending(m_debugserver_pid);
35463511

3547-
LLDB_LOGF(log, "failed to start debugserver process: %s",
3548-
error.AsCString());
3549-
return error;
3550-
}
3512+
// Our process spawned correctly, we can now set our connection to use
3513+
// our end of the socket pair
3514+
m_gdb_comm.SetConnection(std::make_unique<ConnectionFileDescriptor>(
3515+
socket_pair->second.release()));
3516+
StartAsyncThread();
35513517

3552-
if (m_gdb_comm.IsConnected()) {
3553-
// Finish the connection process by doing the handshake without
3554-
// connecting (send NULL URL)
3555-
error = ConnectToDebugserver("");
3556-
} else {
3557-
error = Status::FromErrorString("connection failed");
3558-
}
3518+
if (m_gdb_comm.IsConnected()) {
3519+
// Finish the connection process by doing the handshake without
3520+
// connecting (send NULL URL)
3521+
error = ConnectToDebugserver("");
3522+
} else {
3523+
error = Status::FromErrorString("connection failed");
35593524
}
35603525
return error;
35613526
}

0 commit comments

Comments
 (0)