diff --git a/lldb/source/Host/aix/Host.cpp b/lldb/source/Host/aix/Host.cpp index a812e061ccae2..b5572b93d93a9 100644 --- a/lldb/source/Host/aix/Host.cpp +++ b/lldb/source/Host/aix/Host.cpp @@ -13,6 +13,7 @@ #include "lldb/Utility/ProcessInfo.h" #include "lldb/Utility/Status.h" #include "llvm/BinaryFormat/XCOFF.h" +#include #include #include @@ -133,7 +134,44 @@ static bool GetProcessAndStatInfo(::pid_t pid, uint32_t Host::FindProcessesImpl(const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) { - return 0; + static const char procdir[] = "/proc/"; + + DIR *dirproc = opendir(procdir); + if (dirproc) { + struct dirent *direntry = nullptr; + const uid_t our_uid = getuid(); + const lldb::pid_t our_pid = getpid(); + bool all_users = match_info.GetMatchAllUsers(); + + while ((direntry = readdir(dirproc)) != nullptr) { + lldb::pid_t pid; + // Skip non-numeric name directories + if (!llvm::to_integer(direntry->d_name, pid)) + continue; + // Skip this process. + if (pid == our_pid) + continue; + + ProcessState State; + ProcessInstanceInfo process_info; + if (!GetProcessAndStatInfo(pid, process_info, State)) + continue; + + if (State == ProcessState::Zombie || + State == ProcessState::TracedOrStopped) + continue; + + // Check for user match if we're not matching all users and not running + // as root. + if (!all_users && (our_uid != 0) && (process_info.GetUserID() != our_uid)) + continue; + + if (match_info.Matches(process_info)) + process_infos.push_back(process_info); + } + closedir(dirproc); + } + return process_infos.size(); } bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) { diff --git a/lldb/source/Host/aix/HostInfoAIX.cpp b/lldb/source/Host/aix/HostInfoAIX.cpp index 61b47462dd647..aab3bf62a635f 100644 --- a/lldb/source/Host/aix/HostInfoAIX.cpp +++ b/lldb/source/Host/aix/HostInfoAIX.cpp @@ -7,6 +7,8 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/aix/HostInfoAIX.h" +#include "lldb/Host/posix/Support.h" +#include using namespace lldb_private; @@ -18,5 +20,17 @@ void HostInfoAIX::Terminate() { HostInfoBase::Terminate(); } FileSpec HostInfoAIX::GetProgramFileSpec() { static FileSpec g_program_filespec; + struct psinfo psinfoData; + auto BufferOrError = getProcFile(getpid(), "psinfo"); + if (BufferOrError) { + std::unique_ptr PsinfoBuffer = + std::move(*BufferOrError); + memcpy(&psinfoData, PsinfoBuffer->getBufferStart(), sizeof(psinfoData)); + llvm::StringRef exe_path( + psinfoData.pr_psargs, + strnlen(psinfoData.pr_psargs, sizeof(psinfoData.pr_psargs))); + if (!exe_path.empty()) + g_program_filespec.SetFile(exe_path, FileSpec::Style::native); + } return g_program_filespec; } diff --git a/lldb/unittests/Host/HostInfoTest.cpp b/lldb/unittests/Host/HostInfoTest.cpp index 14941ee5a94b2..0b3bae5c56f2f 100644 --- a/lldb/unittests/Host/HostInfoTest.cpp +++ b/lldb/unittests/Host/HostInfoTest.cpp @@ -54,6 +54,11 @@ TEST_F(HostInfoTest, GetHostname) { EXPECT_TRUE(HostInfo::GetHostname(s)); } +TEST_F(HostInfoTest, GetProgramFileSpec) { + FileSpec filespec = HostInfo::GetProgramFileSpec(); + EXPECT_TRUE(FileSystem::Instance().Exists(filespec)); +} + #if defined(__APPLE__) TEST_F(HostInfoTest, GetXcodeSDK) { auto get_sdk = [](std::string sdk, bool error = false) -> llvm::StringRef { diff --git a/lldb/unittests/Host/HostTest.cpp b/lldb/unittests/Host/HostTest.cpp index 52224bfd28e61..dca32c7547cf7 100644 --- a/lldb/unittests/Host/HostTest.cpp +++ b/lldb/unittests/Host/HostTest.cpp @@ -9,15 +9,18 @@ #include "lldb/Host/Host.h" #include "TestingSupport/SubsystemRAII.h" #include "lldb/Host/FileSystem.h" +#include "lldb/Host/HostInfo.h" #include "lldb/Host/Pipe.h" #include "lldb/Host/ProcessLaunchInfo.h" #include "lldb/Utility/ProcessInfo.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Testing/Support/Error.h" #include "gtest/gtest.h" #include +#include using namespace lldb_private; using namespace llvm; @@ -90,6 +93,44 @@ TEST(Host, LaunchProcessSetsArgv0) { ASSERT_THAT(exit_status.get_future().get(), 0); } +TEST(Host, FindProcesses) { + SubsystemRAII subsystems; + + if (test_arg != 0) { + // Give the parent time to retrieve information about self. + // It will kill self when it is done. + std::this_thread::sleep_for(std::chrono::seconds(10)); + exit(0); + } + + bool foundPID = false; + ProcessLaunchInfo info; + ProcessInstanceInfoList processes; + ProcessInstanceInfoMatch match(TestMainArgv0, NameMatch::Equals); + info.SetExecutableFile(FileSpec(TestMainArgv0), + /*add_exe_file_as_first_arg=*/true); + info.GetArguments().AppendArgument("--gtest_filter=Host.FindProcesses"); + info.GetArguments().AppendArgument("--test-arg=48"); + std::promise exit_status; + info.SetMonitorProcessCallback([&](lldb::pid_t pid, int signal, int status) { + exit_status.set_value(status); + }); + ASSERT_THAT_ERROR(Host::LaunchProcess(info).takeError(), Succeeded()); + ASSERT_TRUE(Host::FindProcesses(match, processes)); + for (const auto &process : processes) { + if (process.GetProcessID() == info.GetProcessID()) { + ASSERT_EQ(process.GetExecutableFile().GetFilename(), + info.GetExecutableFile().GetFilename()); + foundPID = true; + } + } + ASSERT_TRUE(foundPID); + auto clean_up = llvm::make_scope_exit([&] { + Host::Kill(info.GetProcessID(), SIGKILL); + exit_status.get_future().get(); + }); +} + TEST(Host, LaunchProcessDuplicatesHandle) { static constexpr llvm::StringLiteral test_msg("Hello subprocess!");