https://github.com/feg208 updated https://github.com/llvm/llvm-project/pull/88995
>From 9b8ec4d0c31ad1b228add56bc27cd79457e515c7 Mon Sep 17 00:00:00 2001 From: Fred Grim <fg...@apple.com> Date: Tue, 16 Apr 2024 14:46:37 -0700 Subject: [PATCH 1/3] adds additional information to the ProcessInfo object for elf processes --- lldb/include/lldb/Utility/ProcessInfo.h | 71 ++++++++++++++ lldb/source/Host/linux/Host.cpp | 125 ++++++++++++++++++++---- lldb/unittests/Host/linux/HostTest.cpp | 6 ++ 3 files changed, 182 insertions(+), 20 deletions(-) diff --git a/lldb/include/lldb/Utility/ProcessInfo.h b/lldb/include/lldb/Utility/ProcessInfo.h index 7fb5b37be0f48f..e9fe71e1b851d1 100644 --- a/lldb/include/lldb/Utility/ProcessInfo.h +++ b/lldb/include/lldb/Utility/ProcessInfo.h @@ -139,6 +139,11 @@ class ProcessInfo { // to that process. class ProcessInstanceInfo : public ProcessInfo { public: + struct timespec { + time_t tv_sec = 0; + long int tv_usec = 0; + }; + ProcessInstanceInfo() = default; ProcessInstanceInfo(const char *name, const ArchSpec &arch, lldb::pid_t pid) @@ -172,6 +177,66 @@ class ProcessInstanceInfo : public ProcessInfo { return m_parent_pid != LLDB_INVALID_PROCESS_ID; } + lldb::pid_t GetProcessGroupID() const { return m_process_group_id; } + + void SetProcessGroupID(lldb::pid_t pgrp) { m_process_group_id = pgrp; } + + bool ProcessGroupIDIsValid() const { + return m_process_group_id != LLDB_INVALID_PROCESS_ID; + } + + lldb::pid_t GetProcessSessionID() const { return m_process_session_id; } + + void SetProcessSessionID(lldb::pid_t session) { + m_process_session_id = session; + } + + bool ProcessSessionIDIsValid() const { + return m_process_session_id != LLDB_INVALID_PROCESS_ID; + } + + struct timespec GetUserTime() const { return m_user_time; } + + void SetUserTime(struct timespec utime) { m_user_time = utime; } + + bool UserTimeIsValid() const { + return m_user_time.tv_sec > 0 || m_user_time.tv_usec > 0; + } + + struct timespec GetSystemTime() const { return m_system_time; } + + void SetSystemTime(struct timespec stime) { m_system_time = stime; } + + bool SystemTimeIsValid() const { + return m_system_time.tv_sec > 0 || m_system_time.tv_usec > 0; + } + + struct timespec GetCumulativeUserTime() const { + return m_cumulative_user_time; + } + + void SetCumulativeUserTime(struct timespec cutime) { + m_cumulative_user_time = cutime; + } + + bool CumulativeUserTimeIsValid() const { + return m_cumulative_user_time.tv_sec > 0 || + m_cumulative_user_time.tv_usec > 0; + } + + struct timespec GetCumulativeSystemTime() const { + return m_cumulative_system_time; + } + + void SetCumulativeSystemTime(struct timespec cstime) { + m_cumulative_system_time = cstime; + } + + bool CumulativeSystemTimeIsValid() const { + return m_cumulative_system_time.tv_sec > 0 || + m_cumulative_system_time.tv_sec > 0; + } + void Dump(Stream &s, UserIDResolver &resolver) const; static void DumpTableHeader(Stream &s, bool show_args, bool verbose); @@ -183,6 +248,12 @@ class ProcessInstanceInfo : public ProcessInfo { uint32_t m_euid = UINT32_MAX; uint32_t m_egid = UINT32_MAX; lldb::pid_t m_parent_pid = LLDB_INVALID_PROCESS_ID; + lldb::pid_t m_process_group_id = LLDB_INVALID_PROCESS_ID; + lldb::pid_t m_process_session_id = LLDB_INVALID_PROCESS_ID; + struct timespec m_user_time {}; + struct timespec m_system_time {}; + struct timespec m_cumulative_user_time {}; + struct timespec m_cumulative_system_time {}; }; typedef std::vector<ProcessInstanceInfo> ProcessInstanceInfoList; diff --git a/lldb/source/Host/linux/Host.cpp b/lldb/source/Host/linux/Host.cpp index 6c57384aa38a13..c6490f2fc9e2f5 100644 --- a/lldb/source/Host/linux/Host.cpp +++ b/lldb/source/Host/linux/Host.cpp @@ -49,6 +49,29 @@ enum class ProcessState { TracedOrStopped, Zombie, }; + +constexpr int task_comm_len = 16; + +struct StatFields { + ::pid_t pid = LLDB_INVALID_PROCESS_ID; + char comm[task_comm_len]; + char state; + ::pid_t ppid = LLDB_INVALID_PROCESS_ID; + ::pid_t pgrp = LLDB_INVALID_PROCESS_ID; + ::pid_t session = LLDB_INVALID_PROCESS_ID; + int tty_nr; + int tpgid; + unsigned flags; + long unsigned minflt; + long unsigned cminflt; + long unsigned majflt; + long unsigned cmajflt; + long unsigned utime; + long unsigned stime; + long cutime; + long cstime; + // .... other things. We don't need them below +}; } namespace lldb_private { @@ -60,11 +83,92 @@ static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo, ::pid_t &Tgid) { Log *log = GetLog(LLDBLog::Host); - auto BufferOrError = getProcFile(Pid, "status"); + auto BufferOrError = getProcFile(Pid, "stat"); if (!BufferOrError) return false; llvm::StringRef Rest = BufferOrError.get()->getBuffer(); + if (Rest.empty()) + return false; + StatFields stat_fields; + if (sscanf(Rest.data(), + "%d %s %c %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu %ld %ld", + &stat_fields.pid, stat_fields.comm, &stat_fields.state, + &stat_fields.ppid, &stat_fields.pgrp, &stat_fields.session, + &stat_fields.tty_nr, &stat_fields.tpgid, &stat_fields.flags, + &stat_fields.minflt, &stat_fields.cminflt, &stat_fields.majflt, + &stat_fields.cmajflt, &stat_fields.utime, &stat_fields.stime, + &stat_fields.cutime, &stat_fields.cstime) < 0) { + return false; + } + + auto convert = [sc_clk_ticks = sysconf(_SC_CLK_TCK)](auto time_in_ticks) { + ProcessInstanceInfo::timespec ts; + if (sc_clk_ticks <= 0) { + return ts; + } + ts.tv_sec = time_in_ticks / sc_clk_ticks; + double remainder = + (static_cast<double>(time_in_ticks) / sc_clk_ticks) - ts.tv_sec; + ts.tv_usec = + std::chrono::microseconds{std::lround(1e+6 * remainder)}.count(); + return ts; + }; + + ProcessInfo.SetParentProcessID(stat_fields.ppid); + ProcessInfo.SetProcessGroupID(stat_fields.pgrp); + ProcessInfo.SetProcessSessionID(stat_fields.session); + ProcessInfo.SetUserTime(convert(stat_fields.utime)); + ProcessInfo.SetSystemTime(convert(stat_fields.stime)); + ProcessInfo.SetCumulativeUserTime(convert(stat_fields.cutime)); + ProcessInfo.SetCumulativeSystemTime(convert(stat_fields.cstime)); + switch (stat_fields.state) { + case 'R': + State = ProcessState::Running; + break; + case 'S': + State = ProcessState::Sleeping; + break; + case 'D': + State = ProcessState::DiskSleep; + break; + case 'Z': + State = ProcessState::Zombie; + break; + case 'X': + State = ProcessState::Dead; + break; + case 'P': + State = ProcessState::Parked; + break; + case 'W': + State = ProcessState::Paging; + break; + case 'I': + State = ProcessState::Idle; + break; + case 'T': // Stopped on a signal or (before Linux 2.6.33) trace stopped + [[fallthrough]]; + case 't': + State = ProcessState::TracedOrStopped; + break; + default: + State = ProcessState::Unknown; + break; + } + + if (State == ProcessState::Unknown) { + LLDB_LOG(log, "Unknown process state {0}", stat_fields.state); + } + + BufferOrError = getProcFile(Pid, "status"); + if (!BufferOrError) + return false; + + Rest = BufferOrError.get()->getBuffer(); + if (Rest.empty()) + return false; + while (!Rest.empty()) { llvm::StringRef Line; std::tie(Line, Rest) = Rest.split('\n'); @@ -89,25 +193,6 @@ static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo, ProcessInfo.SetUserID(RUid); ProcessInfo.SetEffectiveUserID(EUid); - } else if (Line.consume_front("PPid:")) { - ::pid_t PPid; - Line.ltrim().consumeInteger(10, PPid); - ProcessInfo.SetParentProcessID(PPid); - } else if (Line.consume_front("State:")) { - State = llvm::StringSwitch<ProcessState>(Line.ltrim().take_front(1)) - .Case("D", ProcessState::DiskSleep) - .Case("I", ProcessState::Idle) - .Case("R", ProcessState::Running) - .Case("S", ProcessState::Sleeping) - .CaseLower("T", ProcessState::TracedOrStopped) - .Case("W", ProcessState::Paging) - .Case("P", ProcessState::Parked) - .Case("X", ProcessState::Dead) - .Case("Z", ProcessState::Zombie) - .Default(ProcessState::Unknown); - if (State == ProcessState::Unknown) { - LLDB_LOG(log, "Unknown process state {0}", Line); - } } else if (Line.consume_front("TracerPid:")) { Line = Line.ltrim(); Line.consumeInteger(10, TracerPid); diff --git a/lldb/unittests/Host/linux/HostTest.cpp b/lldb/unittests/Host/linux/HostTest.cpp index 78bbe470d69531..32b1a3678e1fa4 100644 --- a/lldb/unittests/Host/linux/HostTest.cpp +++ b/lldb/unittests/Host/linux/HostTest.cpp @@ -40,6 +40,12 @@ TEST_F(HostTest, GetProcessInfo) { ASSERT_TRUE(Info.ParentProcessIDIsValid()); EXPECT_EQ(lldb::pid_t(getppid()), Info.GetParentProcessID()); + ASSERT_TRUE(Info.ProcessGroupIDIsValid()); + EXPECT_EQ(lldb::pid_t(getpgrp()), Info.GetProcessGroupID()); + + ASSERT_TRUE(Info.ProcessSessionIDIsValid()); + EXPECT_EQ(lldb::pid_t(getsid(getpid())), Info.GetProcessSessionID()); + ASSERT_TRUE(Info.EffectiveUserIDIsValid()); EXPECT_EQ(geteuid(), Info.GetEffectiveUserID()); >From 31c582a069f396badc3baf0948845d773644a948 Mon Sep 17 00:00:00 2001 From: Fred Grim <fg...@apple.com> Date: Wed, 17 Apr 2024 10:09:16 -0700 Subject: [PATCH 2/3] adds a test for the user time --- lldb/unittests/Host/linux/HostTest.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lldb/unittests/Host/linux/HostTest.cpp b/lldb/unittests/Host/linux/HostTest.cpp index 32b1a3678e1fa4..045f2ba88411b5 100644 --- a/lldb/unittests/Host/linux/HostTest.cpp +++ b/lldb/unittests/Host/linux/HostTest.cpp @@ -61,4 +61,14 @@ TEST_F(HostTest, GetProcessInfo) { EXPECT_TRUE(Info.GetArchitecture().IsValid()); EXPECT_EQ(HostInfo::GetArchitecture(HostInfo::eArchKindDefault), Info.GetArchitecture()); + // Test timings + ASSERT_TRUE(Host::GetProcessInfo(getpid(), Info)); + ProcessInstanceInfo::timespec user_time = Info.GetUserTime(); + for (unsigned i = 0; i < 10'000'000; i++) { + __asm__ __volatile__("" : "+g"(i) : :); + } + ASSERT_TRUE(Host::GetProcessInfo(getpid(), Info)); + ProcessInstanceInfo::timespec next_user_time = Info.GetUserTime(); + ASSERT_TRUE(user_time.tv_sec < next_user_time.tv_sec || + user_time.tv_usec < next_user_time.tv_usec); } >From b0e65c8fd1a970c69213ba3b77131288f5b9b607 Mon Sep 17 00:00:00 2001 From: Fred Grim <fg...@apple.com> Date: Wed, 17 Apr 2024 12:49:38 -0700 Subject: [PATCH 3/3] adds a linux only guard --- lldb/unittests/Host/linux/HostTest.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lldb/unittests/Host/linux/HostTest.cpp b/lldb/unittests/Host/linux/HostTest.cpp index 045f2ba88411b5..046736dce18d7a 100644 --- a/lldb/unittests/Host/linux/HostTest.cpp +++ b/lldb/unittests/Host/linux/HostTest.cpp @@ -29,6 +29,13 @@ class HostTest : public testing::Test { } // namespace TEST_F(HostTest, GetProcessInfo) { + llvm::Triple triple = HostInfo::GetTargetTriple(); + + ASSERT_TRUE( + (triple.getOS() == llvm::Triple::OSType::Linux) || + (triple.hasEnvironment() && + triple.getEnvironment() == llvm::Triple::EnvironmentType::Android)); + ProcessInstanceInfo Info; ASSERT_FALSE(Host::GetProcessInfo(0, Info)); _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits