Index: tools/lldb-server/lldb-platform.cpp =================================================================== --- tools/lldb-server/lldb-platform.cpp +++ tools/lldb-server/lldb-platform.cpp @@ -20,13 +20,18 @@ #include // C++ Includes +#include // Other libraries and framework includes #include "lldb/Core/Error.h" #include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Host/HostGetOpt.h" #include "lldb/Host/OptionParser.h" #include "lldb/Host/Socket.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/FileUtilities.h" #include "LLDBServerUtilities.h" #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h" #include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h" @@ -56,6 +61,7 @@ { "gdbserver-port", required_argument, NULL, 'P' }, { "min-gdbserver-port", required_argument, NULL, 'm' }, { "max-gdbserver-port", required_argument, NULL, 'M' }, + { "port-file", required_argument, NULL, 'f' }, { "server", no_argument, &g_server, 1 }, { NULL, 0, NULL, 0 } }; @@ -89,10 +95,43 @@ static void display_usage (const char *progname, const char *subcommand) { - fprintf(stderr, "Usage:\n %s %s [--log-file log-file-name] [--log-channels log-channel-list] --server --listen port\n", progname, subcommand); + fprintf(stderr, "Usage:\n %s %s [--log-file log-file-name] [--log-channels log-channel-list] [--port-file port-file-path] --server --listen port\n", progname, subcommand); exit(0); } +static Error +save_port_to_file(const uint16_t port, const FileSpec &port_file_spec) +{ + const ConstString& port_file_dir = port_file_spec.GetDirectory(); + auto error = FileSystem::MakeDirectory( + FileSpec(port_file_dir.AsCString(), false), eFilePermissionsDirectoryDefault); + if (error.Fail()) + return Error("Failed to create directory %s: %s", port_file_dir.AsCString(), error.AsCString()); + + llvm::SmallString temp_file_path; + auto err_code = llvm::sys::fs::createTemporaryFile( + port_file_spec.GetPath().c_str(), "", temp_file_path); + if (err_code) + return Error("Failed to create temp file: %s", err_code.message().c_str()); + + llvm::FileRemover tmp_file_remover(temp_file_path.c_str()); + + { + std::ofstream temp_file(temp_file_path.c_str(), std::ios::out); + if (!temp_file.is_open()) + return Error("Failed to open temp file %s", temp_file_path.c_str()); + temp_file << port; + } + + err_code = llvm::sys::fs::rename(temp_file_path.c_str(), port_file_spec.GetPath().c_str()); + if (err_code) + return Error("Failed to rename file %s to %s: %s", + temp_file_path.c_str(), port_file_spec.GetPath().c_str(), err_code.message().c_str()); + + tmp_file_remover.releaseFile(); + return Error(); +} + //---------------------------------------------------------------------- // main //---------------------------------------------------------------------- @@ -112,12 +151,13 @@ std::string log_file; StringRef log_channels; // e.g. "lldb process threads:gdb-remote default:linux all" - + GDBRemoteCommunicationServerPlatform::PortMap gdbserver_portmap; int min_gdbserver_port = 0; int max_gdbserver_port = 0; uint16_t port_offset = 0; - + + FileSpec port_file; bool show_usage = false; int option_error = 0; int socket_error = -1; @@ -152,6 +192,11 @@ log_channels = StringRef(optarg); break; + case 'f': // Port file + if (optarg && optarg[0]) + port_file.SetFile(optarg, false); + break; + case 'p': { char *end = NULL; @@ -255,6 +300,15 @@ } listening_socket_up.reset(socket); printf ("Listening for a connection from %u...\n", listening_socket_up->GetLocalPortNumber()); + if (port_file) + { + error = save_port_to_file(listening_socket_up->GetLocalPortNumber(), port_file); + if (error.Fail()) + { + fprintf(stderr, "failed to write port to %s: %s", port_file.GetPath().c_str(), error.AsCString()); + return 1; + } + } do { GDBRemoteCommunicationServerPlatform platform;