Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -43,32 +43,7 @@ MainLoop &mainloop, const NativeProcessProtocol::Factory &process_factory); - //------------------------------------------------------------------ - /// Specify the program to launch and its arguments. - /// - /// @param[in] args - /// The command line to launch. - /// - /// @param[in] argc - /// The number of elements in the args array of cstring pointers. - /// - /// @return - /// An Status object indicating the success or failure of making - /// the setting. - //------------------------------------------------------------------ - Status SetLaunchArguments(const char *const args[], int argc); - - //------------------------------------------------------------------ - /// Specify the launch flags for the process. - /// - /// @param[in] launch_flags - /// The launch flags to use when launching this process. - /// - /// @return - /// An Status object indicating the success or failure of making - /// the setting. - //------------------------------------------------------------------ - Status SetLaunchFlags(unsigned int launch_flags); + void SetLaunchInfo(const ProcessLaunchInfo &info); //------------------------------------------------------------------ /// Launch a process with the current launch settings. Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -204,21 +204,8 @@ }); } -Status -GDBRemoteCommunicationServerLLGS::SetLaunchArguments(const char *const args[], - int argc) { - if ((argc < 1) || !args || !args[0] || !args[0][0]) - return Status("%s: no process command line specified to launch", - __FUNCTION__); - - m_process_launch_info.SetArguments(const_cast(args), true); - return Status(); -} - -Status -GDBRemoteCommunicationServerLLGS::SetLaunchFlags(unsigned int launch_flags) { - m_process_launch_info.GetFlags().Set(launch_flags); - return Status(); +void GDBRemoteCommunicationServerLLGS::SetLaunchInfo(const ProcessLaunchInfo &info) { + m_process_launch_info = info; } Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { Index: lldb/trunk/tools/lldb-server/lldb-gdbserver.cpp =================================================================== --- lldb/trunk/tools/lldb-server/lldb-gdbserver.cpp +++ lldb/trunk/tools/lldb-server/lldb-gdbserver.cpp @@ -177,27 +177,28 @@ void handle_launch(GDBRemoteCommunicationServerLLGS &gdb_server, int argc, const char *const argv[]) { - Status error; - error = gdb_server.SetLaunchArguments(argv, argc); - if (error.Fail()) { - fprintf(stderr, "error: failed to set launch args for '%s': %s\n", argv[0], - error.AsCString()); + ProcessLaunchInfo info; + info.GetFlags().Set(eLaunchFlagStopAtEntry | eLaunchFlagDebug | + eLaunchFlagDisableASLR); + info.SetArguments(const_cast(argv), true); + + llvm::SmallString<64> cwd; + if (std::error_code ec = llvm::sys::fs::current_path(cwd)) { + llvm::errs() << "Error getting current directory: " << ec.message() << "\n"; exit(1); } + info.SetWorkingDirectory(FileSpec(cwd, true)); - unsigned int launch_flags = eLaunchFlagStopAtEntry | eLaunchFlagDebug; + StringList env; + Host::GetEnvironment(env); + info.GetEnvironmentEntries() = Args(env); - error = gdb_server.SetLaunchFlags(launch_flags); - if (error.Fail()) { - fprintf(stderr, "error: failed to set launch flags for '%s': %s\n", argv[0], - error.AsCString()); - exit(1); - } + gdb_server.SetLaunchInfo(info); - error = gdb_server.LaunchProcess(); + Status error = gdb_server.LaunchProcess(); if (error.Fail()) { - fprintf(stderr, "error: failed to launch '%s': %s\n", argv[0], - error.AsCString()); + llvm::errs() << llvm::formatv("error: failed to launch '{0}': {1}\n", + argv[0], error); exit(1); } } Index: lldb/trunk/unittests/tools/lldb-server/CMakeLists.txt =================================================================== --- lldb/trunk/unittests/tools/lldb-server/CMakeLists.txt +++ lldb/trunk/unittests/tools/lldb-server/CMakeLists.txt @@ -10,6 +10,7 @@ endfunction() add_lldb_test_executable(thread_inferior inferior/thread_inferior.cpp) +add_lldb_test_executable(environment_check inferior/environment_check.cpp) if (CMAKE_SYSTEM_NAME MATCHES "Darwin") add_definitions(-DLLDB_SERVER="$") Index: lldb/trunk/unittests/tools/lldb-server/inferior/environment_check.cpp =================================================================== --- lldb/trunk/unittests/tools/lldb-server/inferior/environment_check.cpp +++ lldb/trunk/unittests/tools/lldb-server/inferior/environment_check.cpp @@ -0,0 +1,20 @@ +//===-- thread_inferior.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include +#include + +int main() { + const char *value = std::getenv("LLDB_TEST_MAGIC_VARIABLE"); + if (!value) + return 1; + if (std::string(value) != "LLDB_TEST_MAGIC_VALUE") + return 2; + return 0; +} Index: lldb/trunk/unittests/tools/lldb-server/tests/CMakeLists.txt =================================================================== --- lldb/trunk/unittests/tools/lldb-server/tests/CMakeLists.txt +++ lldb/trunk/unittests/tools/lldb-server/tests/CMakeLists.txt @@ -1,7 +1,8 @@ add_lldb_unittest(LLDBServerTests + LLGSTest.cpp + MessageObjects.cpp TestBase.cpp TestClient.cpp - MessageObjects.cpp ThreadIdsInJstopinfoTest.cpp LINK_LIBS Index: lldb/trunk/unittests/tools/lldb-server/tests/LLGSTest.cpp =================================================================== --- lldb/trunk/unittests/tools/lldb-server/tests/LLGSTest.cpp +++ lldb/trunk/unittests/tools/lldb-server/tests/LLGSTest.cpp @@ -0,0 +1,36 @@ +//===-- LLGSTest.cpp --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "TestBase.h" +#include "lldb/Host/Host.h" +#include "llvm/Testing/Support/Error.h" + +using namespace llgs_tests; +using namespace lldb_private; +using namespace llvm; + +TEST_F(TestBase, LaunchModePreservesEnvironment) { + if (TestClient::IsDebugServer()) { + GTEST_LOG_(WARNING) << "Test fails with debugserver: llvm.org/pr35671"; + return; + } + + putenv(const_cast("LLDB_TEST_MAGIC_VARIABLE=LLDB_TEST_MAGIC_VALUE")); + + auto ClientOr = TestClient::launch(getLogFileName(), + {getInferiorPath("environment_check")}); + ASSERT_THAT_EXPECTED(ClientOr, Succeeded()); + auto &Client = **ClientOr; + + ASSERT_THAT_ERROR(Client.ContinueAll(), Succeeded()); + ASSERT_THAT_EXPECTED( + Client.GetLatestStopReplyAs(), + HasValue(testing::Property(&StopReply::getKind, + WaitStatus{WaitStatus::Exit, 0}))); +} Index: lldb/trunk/unittests/tools/lldb-server/tests/TestClient.cpp =================================================================== --- lldb/trunk/unittests/tools/lldb-server/tests/TestClient.cpp +++ lldb/trunk/unittests/tools/lldb-server/tests/TestClient.cpp @@ -89,6 +89,11 @@ ProcessLaunchInfo Info; Info.SetArchitecture(arch_spec); Info.SetArguments(args, true); + + StringList Env; + Host::GetEnvironment(Env); + Info.GetEnvironmentEntries() = Args(Env); + status = Host::LaunchProcess(Info); if (status.Fail()) return status.ToError(); @@ -96,7 +101,14 @@ Socket *accept_socket; listen_socket.Accept(accept_socket); auto Conn = llvm::make_unique(accept_socket); - return std::unique_ptr(new TestClient(std::move(Conn))); + auto Client = std::unique_ptr(new TestClient(std::move(Conn))); + + if (!InferiorArgs.empty()) { + if (Error E = Client->QueryProcessInfo()) + return std::move(E); + } + + return std::move(Client); } Error TestClient::SetInferior(llvm::ArrayRef inferior_args) {