xref: /freebsd/contrib/llvm-project/lldb/include/lldb/Utility/ProcessInfo.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===-- ProcessInfo.h -------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_UTILITY_PROCESSINFO_H
10 #define LLDB_UTILITY_PROCESSINFO_H
11 
12 #include "lldb/Utility/ArchSpec.h"
13 #include "lldb/Utility/Args.h"
14 #include "lldb/Utility/Environment.h"
15 #include "lldb/Utility/FileSpec.h"
16 #include "lldb/Utility/NameMatches.h"
17 #include "lldb/Utility/StructuredData.h"
18 #include <optional>
19 #include <vector>
20 
21 namespace lldb_private {
22 
23 class UserIDResolver;
24 
25 // ProcessInfo
26 //
27 // A base class for information for a process. This can be used to fill
28 // out information for a process prior to launching it, or it can be used for
29 // an instance of a process and can be filled in with the existing values for
30 // that process.
31 class ProcessInfo {
32 public:
33   ProcessInfo();
34 
35   ProcessInfo(const char *name, const ArchSpec &arch, lldb::pid_t pid);
36 
37   void Clear();
38 
39   const char *GetName() const;
40 
41   llvm::StringRef GetNameAsStringRef() const;
42 
GetExecutableFile()43   FileSpec &GetExecutableFile() { return m_executable; }
44 
45   void SetExecutableFile(const FileSpec &exe_file,
46                          bool add_exe_file_as_first_arg);
47 
GetExecutableFile()48   const FileSpec &GetExecutableFile() const { return m_executable; }
49 
GetUserID()50   uint32_t GetUserID() const { return m_uid; }
51 
GetGroupID()52   uint32_t GetGroupID() const { return m_gid; }
53 
UserIDIsValid()54   bool UserIDIsValid() const { return m_uid != UINT32_MAX; }
55 
GroupIDIsValid()56   bool GroupIDIsValid() const { return m_gid != UINT32_MAX; }
57 
SetUserID(uint32_t uid)58   void SetUserID(uint32_t uid) { m_uid = uid; }
59 
SetGroupID(uint32_t gid)60   void SetGroupID(uint32_t gid) { m_gid = gid; }
61 
GetArchitecture()62   ArchSpec &GetArchitecture() { return m_arch; }
63 
GetArchitecture()64   const ArchSpec &GetArchitecture() const { return m_arch; }
65 
SetArchitecture(const ArchSpec & arch)66   void SetArchitecture(const ArchSpec &arch) { m_arch = arch; }
67 
GetProcessID()68   lldb::pid_t GetProcessID() const { return m_pid; }
69 
SetProcessID(lldb::pid_t pid)70   void SetProcessID(lldb::pid_t pid) { m_pid = pid; }
71 
ProcessIDIsValid()72   bool ProcessIDIsValid() const { return m_pid != LLDB_INVALID_PROCESS_ID; }
73 
74   void Dump(Stream &s, Platform *platform) const;
75 
GetArguments()76   Args &GetArguments() { return m_arguments; }
77 
GetArguments()78   const Args &GetArguments() const { return m_arguments; }
79 
80   llvm::StringRef GetArg0() const;
81 
82   void SetArg0(llvm::StringRef arg);
83 
84   void SetArguments(const Args &args, bool first_arg_is_executable);
85 
86   void SetArguments(char const **argv, bool first_arg_is_executable);
87 
GetEnvironment()88   Environment &GetEnvironment() { return m_environment; }
GetEnvironment()89   const Environment &GetEnvironment() const { return m_environment; }
90 
91   bool IsScriptedProcess() const;
92 
GetScriptedMetadata()93   lldb::ScriptedMetadataSP GetScriptedMetadata() const {
94     return m_scripted_metadata_sp;
95   }
96 
SetScriptedMetadata(lldb::ScriptedMetadataSP metadata_sp)97   void SetScriptedMetadata(lldb::ScriptedMetadataSP metadata_sp) {
98     m_scripted_metadata_sp = metadata_sp;
99   }
100 
101   // Get and set the actual listener that will be used for the process events
GetListener()102   lldb::ListenerSP GetListener() const { return m_listener_sp; }
103 
SetListener(const lldb::ListenerSP & listener_sp)104   void SetListener(const lldb::ListenerSP &listener_sp) {
105     m_listener_sp = listener_sp;
106   }
107 
GetHijackListener()108   lldb::ListenerSP GetHijackListener() const { return m_hijack_listener_sp; }
109 
SetHijackListener(const lldb::ListenerSP & listener_sp)110   void SetHijackListener(const lldb::ListenerSP &listener_sp) {
111     m_hijack_listener_sp = listener_sp;
112   }
113 
GetShadowListener()114   lldb::ListenerSP GetShadowListener() const { return m_shadow_listener_sp; }
115 
SetShadowListener(const lldb::ListenerSP & listener_sp)116   void SetShadowListener(const lldb::ListenerSP &listener_sp) {
117     m_shadow_listener_sp = listener_sp;
118   }
119 
120 protected:
121   FileSpec m_executable;
122   std::string m_arg0; // argv[0] if supported. If empty, then use m_executable.
123   // Not all process plug-ins support specifying an argv[0] that differs from
124   // the resolved platform executable (which is in m_executable)
125   Args m_arguments; // All program arguments except argv[0]
126   Environment m_environment;
127   uint32_t m_uid = UINT32_MAX;
128   uint32_t m_gid = UINT32_MAX;
129   ArchSpec m_arch;
130   lldb::pid_t m_pid = LLDB_INVALID_PROCESS_ID;
131   lldb::ScriptedMetadataSP m_scripted_metadata_sp = nullptr;
132   lldb::ListenerSP m_listener_sp = nullptr;
133   lldb::ListenerSP m_hijack_listener_sp = nullptr;
134   lldb::ListenerSP m_shadow_listener_sp = nullptr;
135 };
136 
137 // ProcessInstanceInfo
138 //
139 // Describes an existing process and any discoverable information that pertains
140 // to that process.
141 class ProcessInstanceInfo : public ProcessInfo {
142 public:
143   struct timespec {
144     time_t tv_sec = 0;
145     long int tv_usec = 0;
146   };
147 
148   ProcessInstanceInfo() = default;
149 
ProcessInstanceInfo(const char * name,const ArchSpec & arch,lldb::pid_t pid)150   ProcessInstanceInfo(const char *name, const ArchSpec &arch, lldb::pid_t pid)
151       : ProcessInfo(name, arch, pid) {}
152 
Clear()153   void Clear() {
154     ProcessInfo::Clear();
155     m_euid = UINT32_MAX;
156     m_egid = UINT32_MAX;
157     m_parent_pid = LLDB_INVALID_PROCESS_ID;
158   }
159 
GetEffectiveUserID()160   uint32_t GetEffectiveUserID() const { return m_euid; }
161 
GetEffectiveGroupID()162   uint32_t GetEffectiveGroupID() const { return m_egid; }
163 
EffectiveUserIDIsValid()164   bool EffectiveUserIDIsValid() const { return m_euid != UINT32_MAX; }
165 
EffectiveGroupIDIsValid()166   bool EffectiveGroupIDIsValid() const { return m_egid != UINT32_MAX; }
167 
SetEffectiveUserID(uint32_t uid)168   void SetEffectiveUserID(uint32_t uid) { m_euid = uid; }
169 
SetEffectiveGroupID(uint32_t gid)170   void SetEffectiveGroupID(uint32_t gid) { m_egid = gid; }
171 
GetParentProcessID()172   lldb::pid_t GetParentProcessID() const { return m_parent_pid; }
173 
SetParentProcessID(lldb::pid_t pid)174   void SetParentProcessID(lldb::pid_t pid) { m_parent_pid = pid; }
175 
ParentProcessIDIsValid()176   bool ParentProcessIDIsValid() const {
177     return m_parent_pid != LLDB_INVALID_PROCESS_ID;
178   }
179 
GetProcessGroupID()180   lldb::pid_t GetProcessGroupID() const { return m_process_group_id; }
181 
SetProcessGroupID(lldb::pid_t pgrp)182   void SetProcessGroupID(lldb::pid_t pgrp) { m_process_group_id = pgrp; }
183 
ProcessGroupIDIsValid()184   bool ProcessGroupIDIsValid() const {
185     return m_process_group_id != LLDB_INVALID_PROCESS_ID;
186   }
187 
GetProcessSessionID()188   lldb::pid_t GetProcessSessionID() const { return m_process_session_id; }
189 
SetProcessSessionID(lldb::pid_t session)190   void SetProcessSessionID(lldb::pid_t session) {
191     m_process_session_id = session;
192   }
193 
ProcessSessionIDIsValid()194   bool ProcessSessionIDIsValid() const {
195     return m_process_session_id != LLDB_INVALID_PROCESS_ID;
196   }
197 
GetUserTime()198   struct timespec GetUserTime() const { return m_user_time; }
199 
SetUserTime(struct timespec utime)200   void SetUserTime(struct timespec utime) { m_user_time = utime; }
201 
UserTimeIsValid()202   bool UserTimeIsValid() const {
203     return m_user_time.tv_sec > 0 || m_user_time.tv_usec > 0;
204   }
205 
GetSystemTime()206   struct timespec GetSystemTime() const { return m_system_time; }
207 
SetSystemTime(struct timespec stime)208   void SetSystemTime(struct timespec stime) { m_system_time = stime; }
209 
SystemTimeIsValid()210   bool SystemTimeIsValid() const {
211     return m_system_time.tv_sec > 0 || m_system_time.tv_usec > 0;
212   }
213 
GetCumulativeUserTime()214   struct timespec GetCumulativeUserTime() const {
215     return m_cumulative_user_time;
216   }
217 
SetCumulativeUserTime(struct timespec cutime)218   void SetCumulativeUserTime(struct timespec cutime) {
219     m_cumulative_user_time = cutime;
220   }
221 
CumulativeUserTimeIsValid()222   bool CumulativeUserTimeIsValid() const {
223     return m_cumulative_user_time.tv_sec > 0 ||
224            m_cumulative_user_time.tv_usec > 0;
225   }
226 
GetCumulativeSystemTime()227   struct timespec GetCumulativeSystemTime() const {
228     return m_cumulative_system_time;
229   }
230 
SetCumulativeSystemTime(struct timespec cstime)231   void SetCumulativeSystemTime(struct timespec cstime) {
232     m_cumulative_system_time = cstime;
233   }
234 
CumulativeSystemTimeIsValid()235   bool CumulativeSystemTimeIsValid() const {
236     return m_cumulative_system_time.tv_sec > 0 ||
237            m_cumulative_system_time.tv_usec > 0;
238   }
239 
GetPriorityValue()240   std::optional<int8_t> GetPriorityValue() const { return m_priority_value; }
241 
SetPriorityValue(int8_t priority_value)242   void SetPriorityValue(int8_t priority_value) {
243     m_priority_value = priority_value;
244   }
245 
SetIsZombie(bool is_zombie)246   void SetIsZombie(bool is_zombie) { m_zombie = is_zombie; }
247 
IsZombie()248   std::optional<bool> IsZombie() const { return m_zombie; }
249 
250   void Dump(Stream &s, UserIDResolver &resolver) const;
251 
252   static void DumpTableHeader(Stream &s, bool show_args, bool verbose);
253 
254   void DumpAsTableRow(Stream &s, UserIDResolver &resolver, bool show_args,
255                       bool verbose) const;
256 
257 protected:
258   uint32_t m_euid = UINT32_MAX;
259   uint32_t m_egid = UINT32_MAX;
260   lldb::pid_t m_parent_pid = LLDB_INVALID_PROCESS_ID;
261   lldb::pid_t m_process_group_id = LLDB_INVALID_PROCESS_ID;
262   lldb::pid_t m_process_session_id = LLDB_INVALID_PROCESS_ID;
263   struct timespec m_user_time;
264   struct timespec m_system_time;
265   struct timespec m_cumulative_user_time;
266   struct timespec m_cumulative_system_time;
267   std::optional<int8_t> m_priority_value = std::nullopt;
268   std::optional<bool> m_zombie = std::nullopt;
269 };
270 
271 typedef std::vector<ProcessInstanceInfo> ProcessInstanceInfoList;
272 
273 class ProcessInfoList {
274 public:
ProcessInfoList(const ProcessInstanceInfoList & list)275   ProcessInfoList(const ProcessInstanceInfoList &list) : m_list(list) {}
276 
GetSize()277   uint32_t GetSize() const { return m_list.size(); }
278 
GetProcessInfoAtIndex(uint32_t idx,ProcessInstanceInfo & info)279   bool GetProcessInfoAtIndex(uint32_t idx, ProcessInstanceInfo &info) {
280     if (idx < m_list.size()) {
281       info = m_list[idx];
282       return true;
283     }
284     return false;
285   }
286 
Clear()287   void Clear() { return m_list.clear(); }
288 
289 private:
290   ProcessInstanceInfoList m_list;
291 };
292 
293 // ProcessInstanceInfoMatch
294 //
295 // A class to help matching one ProcessInstanceInfo to another.
296 
297 class ProcessInstanceInfoMatch {
298 public:
299   ProcessInstanceInfoMatch() = default;
300 
ProcessInstanceInfoMatch(const char * process_name,NameMatch process_name_match_type)301   ProcessInstanceInfoMatch(const char *process_name,
302                            NameMatch process_name_match_type)
303       : m_name_match_type(process_name_match_type), m_match_all_users(false) {
304     m_match_info.GetExecutableFile().SetFile(process_name,
305                                              FileSpec::Style::native);
306   }
307 
GetProcessInfo()308   ProcessInstanceInfo &GetProcessInfo() { return m_match_info; }
309 
GetProcessInfo()310   const ProcessInstanceInfo &GetProcessInfo() const { return m_match_info; }
311 
GetMatchAllUsers()312   bool GetMatchAllUsers() const { return m_match_all_users; }
313 
SetMatchAllUsers(bool b)314   void SetMatchAllUsers(bool b) { m_match_all_users = b; }
315 
GetNameMatchType()316   NameMatch GetNameMatchType() const { return m_name_match_type; }
317 
SetNameMatchType(NameMatch name_match_type)318   void SetNameMatchType(NameMatch name_match_type) {
319     m_name_match_type = name_match_type;
320   }
321 
322   /// Return true iff the architecture in this object matches arch_spec.
323   bool ArchitectureMatches(const ArchSpec &arch_spec) const;
324 
325   /// Return true iff the process name in this object matches process_name.
326   bool NameMatches(const char *process_name) const;
327 
328   /// Return true iff the process ID and parent process IDs in this object match
329   /// the ones in proc_info.
330   bool ProcessIDsMatch(const ProcessInstanceInfo &proc_info) const;
331 
332   /// Return true iff the (both effective and real) user and group IDs in this
333   /// object match the ones in proc_info.
334   bool UserIDsMatch(const ProcessInstanceInfo &proc_info) const;
335 
336   bool Matches(const ProcessInstanceInfo &proc_info) const;
337 
338   bool MatchAllProcesses() const;
339   void Clear();
340 
341 protected:
342   ProcessInstanceInfo m_match_info;
343   NameMatch m_name_match_type = NameMatch::Ignore;
344   bool m_match_all_users = false;
345 };
346 
347 } // namespace lldb_private
348 
349 #endif // LLDB_UTILITY_PROCESSINFO_H
350