Skip to content

Commit 39e7efe

Browse files
authored
[lldb] Respect LaunchInfo::SetExecutable in ProcessLauncherPosixFork (#133093)
Using argv[0] for this was incorrect. I'm ignoring LaunchInfo::SetArg0, as that's what darwin and windows launchers do (they use the first element of the args vector instead). I picked up the funny unit test re-exec method from the llvm unit tests.
1 parent a967251 commit 39e7efe

File tree

2 files changed

+48
-3
lines changed

2 files changed

+48
-3
lines changed

lldb/source/Host/posix/ProcessLauncherPosixFork.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ struct ForkLaunchInfo {
9494
bool debug;
9595
bool disable_aslr;
9696
std::string wd;
97+
std::string executable;
9798
const char **argv;
9899
Environment::Envp envp;
99100
std::vector<ForkFileAction> actions;
@@ -194,7 +195,8 @@ struct ForkLaunchInfo {
194195
}
195196

196197
// Execute. We should never return...
197-
execve(info.argv[0], const_cast<char *const *>(info.argv), info.envp);
198+
execve(info.executable.c_str(), const_cast<char *const *>(info.argv),
199+
info.envp);
198200

199201
#if defined(__linux__)
200202
if (errno == ETXTBSY) {
@@ -207,7 +209,8 @@ struct ForkLaunchInfo {
207209
// Since this state should clear up quickly, wait a while and then give it
208210
// one more go.
209211
usleep(50000);
210-
execve(info.argv[0], const_cast<char *const *>(info.argv), info.envp);
212+
execve(info.executable.c_str(), const_cast<char *const *>(info.argv),
213+
info.envp);
211214
}
212215
#endif
213216

@@ -236,6 +239,7 @@ ForkLaunchInfo::ForkLaunchInfo(const ProcessLaunchInfo &info)
236239
debug(info.GetFlags().Test(eLaunchFlagDebug)),
237240
disable_aslr(info.GetFlags().Test(eLaunchFlagDisableASLR)),
238241
wd(info.GetWorkingDirectory().GetPath()),
242+
executable(info.GetExecutableFile().GetPath()),
239243
argv(info.GetArguments().GetConstArgumentVector()),
240244
envp(info.GetEnvironment().getEnvp()), actions(MakeForkActions(info)) {}
241245

lldb/unittests/Host/HostTest.cpp

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,24 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "lldb/Host/Host.h"
10+
#include "TestingSupport/SubsystemRAII.h"
11+
#include "lldb/Host/FileSystem.h"
12+
#include "lldb/Host/ProcessLaunchInfo.h"
1013
#include "lldb/Utility/ProcessInfo.h"
14+
#include "llvm/Support/CommandLine.h"
15+
#include "llvm/Support/FileSystem.h"
16+
#include "llvm/Testing/Support/Error.h"
1117
#include "gtest/gtest.h"
18+
#include <future>
1219

1320
using namespace lldb_private;
1421
using namespace llvm;
1522

23+
// From TestMain.cpp.
24+
extern const char *TestMainArgv0;
25+
26+
static cl::opt<uint64_t> test_arg("test-arg");
27+
1628
TEST(Host, WaitStatusFormat) {
1729
EXPECT_EQ("W01", formatv("{0:g}", WaitStatus{WaitStatus::Exit, 1}).str());
1830
EXPECT_EQ("X02", formatv("{0:g}", WaitStatus{WaitStatus::Signal, 2}).str());
@@ -45,4 +57,33 @@ TEST(Host, ProcessInstanceInfoCumulativeSystemTimeIsValid) {
4557
EXPECT_TRUE(info.CumulativeSystemTimeIsValid());
4658
info.SetCumulativeSystemTime(ProcessInstanceInfo::timespec{1, 0});
4759
EXPECT_TRUE(info.CumulativeSystemTimeIsValid());
48-
}
60+
}
61+
62+
TEST(Host, LaunchProcessSetsArgv0) {
63+
SubsystemRAII<FileSystem> subsystems;
64+
65+
static constexpr StringLiteral TestArgv0 = "HelloArgv0";
66+
if (test_arg != 0) {
67+
// In subprocess
68+
if (TestMainArgv0 != TestArgv0) {
69+
errs() << formatv("Got '{0}' for argv[0]\n", TestMainArgv0);
70+
exit(1);
71+
}
72+
exit(0);
73+
}
74+
75+
ProcessLaunchInfo info;
76+
info.SetExecutableFile(
77+
FileSpec(llvm::sys::fs::getMainExecutable(TestMainArgv0, &test_arg)),
78+
/*add_exe_file_as_first_arg=*/false);
79+
info.GetArguments().AppendArgument("HelloArgv0");
80+
info.GetArguments().AppendArgument(
81+
"--gtest_filter=Host.LaunchProcessSetsArgv0");
82+
info.GetArguments().AppendArgument("--test-arg=47");
83+
std::promise<int> exit_status;
84+
info.SetMonitorProcessCallback([&](lldb::pid_t pid, int signal, int status) {
85+
exit_status.set_value(status);
86+
});
87+
ASSERT_THAT_ERROR(Host::LaunchProcess(info).takeError(), Succeeded());
88+
ASSERT_THAT(exit_status.get_future().get(), 0);
89+
}

0 commit comments

Comments
 (0)