3131#include < climits>
3232#include < cstring>
3333#include < sys/stat.h>
34+ #include < variant>
3435
3536#if defined(__APPLE__)
3637#define DEBUGSERVER_BASENAME " debugserver"
@@ -894,11 +895,9 @@ FileSpec GDBRemoteCommunication::GetDebugserverPath(Platform *platform) {
894895}
895896
896897Status GDBRemoteCommunication::StartDebugserverProcess (
897- const char *url , Platform *platform, ProcessLaunchInfo &launch_info ,
898- uint16_t *port , const Args *inferior_args, shared_fd_t pass_comm_fd ) {
898+ std::variant<llvm::StringRef, shared_fd_t > comm , Platform *platform,
899+ ProcessLaunchInfo &launch_info , const Args *inferior_args) {
899900 Log *log = GetLog (GDBRLog::Process);
900- LLDB_LOG (log, " Starting debug server: url={0}, port={1}" ,
901- url ? url : " <empty>" , port ? *port : uint16_t (0 ));
902901
903902 FileSpec debugserver_file_spec = GetDebugserverPath (platform);
904903 if (!debugserver_file_spec)
@@ -911,89 +910,58 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
911910
912911#if !defined(__APPLE__)
913912 // First argument to lldb-server must be mode in which to run.
914- debugserver_args.AppendArgument (llvm::StringRef ( " gdbserver" ) );
913+ debugserver_args.AppendArgument (" gdbserver" );
915914#endif
916915
917- // If a url is supplied then use it
918- if (url && url[0 ])
919- debugserver_args.AppendArgument (llvm::StringRef (url));
920-
921- if (pass_comm_fd != SharedSocket::kInvalidFD ) {
922- StreamString fd_arg;
923- fd_arg.Printf (" --fd=%" PRIi64, (int64_t )pass_comm_fd);
924- debugserver_args.AppendArgument (fd_arg.GetString ());
925- // Send "pass_comm_fd" down to the inferior so it can use it to
926- // communicate back with this process. Ignored on Windows.
927- launch_info.AppendDuplicateFileAction ((int64_t )pass_comm_fd,
928- (int64_t )pass_comm_fd);
929- }
930-
931916 // use native registers, not the GDB registers
932- debugserver_args.AppendArgument (llvm::StringRef ( " --native-regs" ) );
917+ debugserver_args.AppendArgument (" --native-regs" );
933918
934919 if (launch_info.GetLaunchInSeparateProcessGroup ())
935- debugserver_args.AppendArgument (llvm::StringRef ( " --setsid" ) );
920+ debugserver_args.AppendArgument (" --setsid" );
936921
937922 llvm::SmallString<128 > named_pipe_path;
938923 // socket_pipe is used by debug server to communicate back either
939- // TCP port or domain socket name which it listens on.
940- // The second purpose of the pipe to serve as a synchronization point -
924+ // TCP port or domain socket name which it listens on. However, we're not
925+ // interested in the actualy value here.
926+ // The only reason for using the pipe is to serve as a synchronization point -
941927 // once data is written to the pipe, debug server is up and running.
942928 Pipe socket_pipe;
943929
944- std::unique_ptr<TCPSocket> sock_up;
930+ // If a url is supplied then use it
931+ if (shared_fd_t *comm_fd = std::get_if<shared_fd_t >(&comm)) {
932+ LLDB_LOG (log, " debugserver communicates over fd {0}" , comm_fd);
933+ assert (*comm_fd != SharedSocket::kInvalidFD );
934+ debugserver_args.AppendArgument (llvm::formatv (" --fd={0}" , *comm_fd).str ());
935+ // Send "comm_fd" down to the inferior so it can use it to communicate back
936+ // with this process.
937+ launch_info.AppendDuplicateFileAction ((int64_t )*comm_fd, (int64_t )*comm_fd);
938+ } else {
939+ llvm::StringRef url = std::get<llvm::StringRef>(comm);
940+ LLDB_LOG (log, " debugserver listens on: {0}" , url);
941+ debugserver_args.AppendArgument (url);
945942
946- // port is null when debug server should listen on domain socket - we're
947- // not interested in port value but rather waiting for debug server to
948- // become available.
949- if (pass_comm_fd == SharedSocket::kInvalidFD ) {
950- if (url) {
951- // Create a temporary file to get the stdout/stderr and redirect the output of
952- // the command into this file. We will later read this file if all goes well
953- // and fill the data into "command_output_ptr"
954943#if defined(__APPLE__)
955- // Binding to port zero, we need to figure out what port it ends up
956- // using using a named pipe...
957- Status error = socket_pipe.CreateWithUniqueName (" debugserver-named-pipe" ,
958- false , named_pipe_path);
959- if (error.Fail ()) {
960- LLDB_LOG (log, " named pipe creation failed: {0}" , error);
961- return error;
962- }
963- debugserver_args.AppendArgument (llvm::StringRef (" --named-pipe" ));
964- debugserver_args.AppendArgument (named_pipe_path);
944+ // Using a named pipe as debugserver does not support --pipe.
945+ Status error = socket_pipe.CreateWithUniqueName (" debugserver-named-pipe" ,
946+ false , named_pipe_path);
947+ if (error.Fail ()) {
948+ LLDB_LOG (log, " named pipe creation failed: {0}" , error);
949+ return error;
950+ }
951+ debugserver_args.AppendArgument (llvm::StringRef (" --named-pipe" ));
952+ debugserver_args.AppendArgument (named_pipe_path);
965953#else
966- // Binding to port zero, we need to figure out what port it ends up
967- // using using an unnamed pipe...
968- Status error = socket_pipe.CreateNew (true );
969- if (error.Fail ()) {
970- LLDB_LOG (log, " unnamed pipe creation failed: {0}" , error);
971- return error;
972- }
973- pipe_t write = socket_pipe.GetWritePipe ();
974- debugserver_args.AppendArgument (llvm::StringRef (" --pipe" ));
975- debugserver_args.AppendArgument (llvm::to_string (write));
976- launch_info.AppendCloseFileAction (socket_pipe.GetReadFileDescriptor ());
977- #endif
978- } else {
979- // No host and port given, so lets listen on our end and make the
980- // debugserver connect to us..
981- if (llvm::Expected<std::unique_ptr<TCPSocket>> expected_sock =
982- Socket::TcpListen (" 127.0.0.1:0" ))
983- sock_up = std::move (*expected_sock);
984- else
985- return Status::FromError (expected_sock.takeError ());
986-
987- uint16_t port_ = sock_up->GetLocalPortNumber ();
988- // Send the host and port down that debugserver and specify an option
989- // so that it connects back to the port we are listening to in this
990- // process
991- debugserver_args.AppendArgument (llvm::StringRef (" --reverse-connect" ));
992- debugserver_args.AppendArgument (
993- llvm::formatv (" 127.0.0.1:{0}" , port_).str ());
994- if (port)
995- *port = port_;
954+ // Using an unnamed pipe as it's simpler.
955+ Status error = socket_pipe.CreateNew (true );
956+ if (error.Fail ()) {
957+ LLDB_LOG (log, " unnamed pipe creation failed: {0}" , error);
958+ return error;
996959 }
960+ pipe_t write = socket_pipe.GetWritePipe ();
961+ debugserver_args.AppendArgument (llvm::StringRef (" --pipe" ));
962+ debugserver_args.AppendArgument (llvm::to_string (write));
963+ launch_info.AppendCloseFileAction (socket_pipe.GetReadFileDescriptor ());
964+ #endif
997965 }
998966
999967 Environment host_env = Host::GetEnvironment ();
@@ -1070,7 +1038,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
10701038 return error;
10711039 }
10721040
1073- if (pass_comm_fd != SharedSocket:: kInvalidFD )
1041+ if (std::holds_alternative< shared_fd_t >(comm) )
10741042 return Status ();
10751043
10761044 Status error;
@@ -1084,55 +1052,30 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
10841052
10851053 if (socket_pipe.CanWrite ())
10861054 socket_pipe.CloseWriteFileDescriptor ();
1087- if (socket_pipe.CanRead ()) {
1088- // Read port from pipe with 10 second timeout.
1089- std::string port_str;
1090- while (error.Success ()) {
1091- char buf[10 ];
1092- if (llvm::Expected<size_t > num_bytes =
1093- socket_pipe.Read (buf, std::size (buf), std::chrono::seconds (10 ))) {
1094- if (*num_bytes == 0 )
1095- break ;
1096- port_str.append (buf, *num_bytes);
1097- } else {
1098- error = Status::FromError (num_bytes.takeError ());
1099- }
1100- }
1101- if (error.Success () && (port != nullptr )) {
1102- // NB: Deliberately using .c_str() to stop at embedded '\0's
1103- llvm::StringRef port_ref = port_str.c_str ();
1104- uint16_t child_port = 0 ;
1105- // FIXME: improve error handling
1106- llvm::to_integer (port_ref, child_port);
1107- if (*port == 0 || *port == child_port) {
1108- *port = child_port;
1109- LLDB_LOG (log, " debugserver listens on port {0}" , *port);
1110- } else {
1111- LLDB_LOG (log,
1112- " debugserver listening on port {0} but requested port was {1}" ,
1113- child_port, (*port));
1114- }
1055+ assert (socket_pipe.CanRead ());
1056+
1057+ // Read data from the pipe -- and ignore it (see comment above).
1058+ while (error.Success ()) {
1059+ char buf[10 ];
1060+ if (llvm::Expected<size_t > num_bytes =
1061+ socket_pipe.Read (buf, std::size (buf), std::chrono::seconds (10 ))) {
1062+ if (*num_bytes == 0 )
1063+ break ;
11151064 } else {
1116- LLDB_LOG (log, " failed to read a port value from pipe {0}: {1}" ,
1117- named_pipe_path, error);
1065+ error = Status::FromError (num_bytes.takeError ());
11181066 }
1119- socket_pipe.Close ();
11201067 }
1068+ if (error.Fail ()) {
1069+ LLDB_LOG (log, " failed to synchronize on pipe {0}: {1}" , named_pipe_path,
1070+ error);
1071+ }
1072+ socket_pipe.Close ();
11211073
11221074 if (named_pipe_path.size () > 0 ) {
11231075 if (Status err = socket_pipe.Delete (named_pipe_path); err.Fail ())
11241076 LLDB_LOG (log, " failed to delete pipe {0}: {1}" , named_pipe_path, err);
11251077 }
11261078
1127- if (error.Success () && sock_up) {
1128- Socket *accepted_socket = nullptr ;
1129- error = sock_up->Accept (/* timeout=*/ std::nullopt , accepted_socket);
1130- if (accepted_socket) {
1131- SetConnection (std::make_unique<ConnectionFileDescriptor>(
1132- std::unique_ptr<Socket>(accepted_socket)));
1133- }
1134- }
1135-
11361079 return error;
11371080}
11381081
0 commit comments