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 <vector>
19 
20 namespace lldb_private {
21 
22 class UserIDResolver;
23 
24 // ProcessInfo
25 //
26 // A base class for information for a process. This can be used to fill
27 // out information for a process prior to launching it, or it can be used for
28 // an instance of a process and can be filled in with the existing values for
29 // that process.
30 class ProcessInfo {
31 public:
32   ProcessInfo();
33 
34   ProcessInfo(const char *name, const ArchSpec &arch, lldb::pid_t pid);
35 
36   void Clear();
37 
38   const char *GetName() const;
39 
40   llvm::StringRef GetNameAsStringRef() const;
41 
GetExecutableFile()42   FileSpec &GetExecutableFile() { return m_executable; }
43 
44   void SetExecutableFile(const FileSpec &exe_file,
45                          bool add_exe_file_as_first_arg);
46 
GetExecutableFile()47   const FileSpec &GetExecutableFile() const { return m_executable; }
48 
GetUserID()49   uint32_t GetUserID() const { return m_uid; }
50 
GetGroupID()51   uint32_t GetGroupID() const { return m_gid; }
52 
UserIDIsValid()53   bool UserIDIsValid() const { return m_uid != UINT32_MAX; }
54 
GroupIDIsValid()55   bool GroupIDIsValid() const { return m_gid != UINT32_MAX; }
56 
SetUserID(uint32_t uid)57   void SetUserID(uint32_t uid) { m_uid = uid; }
58 
SetGroupID(uint32_t gid)59   void SetGroupID(uint32_t gid) { m_gid = gid; }
60 
GetArchitecture()61   ArchSpec &GetArchitecture() { return m_arch; }
62 
GetArchitecture()63   const ArchSpec &GetArchitecture() const { return m_arch; }
64 
SetArchitecture(const ArchSpec & arch)65   void SetArchitecture(const ArchSpec &arch) { m_arch = arch; }
66 
GetProcessID()67   lldb::pid_t GetProcessID() const { return m_pid; }
68 
SetProcessID(lldb::pid_t pid)69   void SetProcessID(lldb::pid_t pid) { m_pid = pid; }
70 
ProcessIDIsValid()71   bool ProcessIDIsValid() const { return m_pid != LLDB_INVALID_PROCESS_ID; }
72 
73   void Dump(Stream &s, Platform *platform) const;
74 
GetArguments()75   Args &GetArguments() { return m_arguments; }
76 
GetArguments()77   const Args &GetArguments() const { return m_arguments; }
78 
79   llvm::StringRef GetArg0() const;
80 
81   void SetArg0(llvm::StringRef arg);
82 
83   void SetArguments(const Args &args, bool first_arg_is_executable);
84 
85   void SetArguments(char const **argv, bool first_arg_is_executable);
86 
GetEnvironment()87   Environment &GetEnvironment() { return m_environment; }
GetEnvironment()88   const Environment &GetEnvironment() const { return m_environment; }
89 
90   bool IsScriptedProcess() const;
91 
GetScriptedMetadata()92   lldb::ScriptedMetadataSP GetScriptedMetadata() const {
93     return m_scripted_metadata_sp;
94   }
95 
SetScriptedMetadata(lldb::ScriptedMetadataSP metadata_sp)96   void SetScriptedMetadata(lldb::ScriptedMetadataSP metadata_sp) {
97     m_scripted_metadata_sp = metadata_sp;
98   }
99 
100   // Get and set the actual listener that will be used for the process events
GetListener()101   lldb::ListenerSP GetListener() const { return m_listener_sp; }
102 
SetListener(const lldb::ListenerSP & listener_sp)103   void SetListener(const lldb::ListenerSP &listener_sp) {
104     m_listener_sp = listener_sp;
105   }
106 
GetHijackListener()107   lldb::ListenerSP GetHijackListener() const { return m_hijack_listener_sp; }
108 
SetHijackListener(const lldb::ListenerSP & listener_sp)109   void SetHijackListener(const lldb::ListenerSP &listener_sp) {
110     m_hijack_listener_sp = listener_sp;
111   }
112 
GetShadowListener()113   lldb::ListenerSP GetShadowListener() const { return m_shadow_listener_sp; }
114 
SetShadowListener(const lldb::ListenerSP & listener_sp)115   void SetShadowListener(const lldb::ListenerSP &listener_sp) {
116     m_shadow_listener_sp = listener_sp;
117   }
118 
119 protected:
120   FileSpec m_executable;
121   std::string m_arg0; // argv[0] if supported. If empty, then use m_executable.
122   // Not all process plug-ins support specifying an argv[0] that differs from
123   // the resolved platform executable (which is in m_executable)
124   Args m_arguments; // All program arguments except argv[0]
125   Environment m_environment;
126   uint32_t m_uid = UINT32_MAX;
127   uint32_t m_gid = UINT32_MAX;
128   ArchSpec m_arch;
129   lldb::pid_t m_pid = LLDB_INVALID_PROCESS_ID;
130   lldb::ScriptedMetadataSP m_scripted_metadata_sp = nullptr;
131   lldb::ListenerSP m_listener_sp = nullptr;
132   lldb::ListenerSP m_hijack_listener_sp = nullptr;
133   lldb::ListenerSP m_shadow_listener_sp = nullptr;
134 };
135 
136 // ProcessInstanceInfo
137 //
138 // Describes an existing process and any discoverable information that pertains
139 // to that process.
140 class ProcessInstanceInfo : public ProcessInfo {
141 public:
142   struct timespec {
143     time_t tv_sec = 0;
144     long int tv_usec = 0;
145   };
146 
147   ProcessInstanceInfo() = default;
148 
ProcessInstanceInfo(const char * name,const ArchSpec & arch,lldb::pid_t pid)149   ProcessInstanceInfo(const char *name, const ArchSpec &arch, lldb::pid_t pid)
150       : ProcessInfo(name, arch, pid), m_euid(UINT32_MAX), m_egid(UINT32_MAX),
151         m_parent_pid(LLDB_INVALID_PROCESS_ID) {}
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 
240   void Dump(Stream &s, UserIDResolver &resolver) const;
241 
242   static void DumpTableHeader(Stream &s, bool show_args, bool verbose);
243 
244   void DumpAsTableRow(Stream &s, UserIDResolver &resolver, bool show_args,
245                       bool verbose) const;
246 
247 protected:
248   uint32_t m_euid = UINT32_MAX;
249   uint32_t m_egid = UINT32_MAX;
250   lldb::pid_t m_parent_pid = LLDB_INVALID_PROCESS_ID;
251   lldb::pid_t m_process_group_id = LLDB_INVALID_PROCESS_ID;
252   lldb::pid_t m_process_session_id = LLDB_INVALID_PROCESS_ID;
253   struct timespec m_user_time {};
254   struct timespec m_system_time {};
255   struct timespec m_cumulative_user_time {};
256   struct timespec m_cumulative_system_time {};
257 };
258 
259 typedef std::vector<ProcessInstanceInfo> ProcessInstanceInfoList;
260 
261 class ProcessInfoList {
262 public:
ProcessInfoList(const ProcessInstanceInfoList & list)263   ProcessInfoList(const ProcessInstanceInfoList &list) : m_list(list) {}
264 
GetSize()265   uint32_t GetSize() const { return m_list.size(); }
266 
GetProcessInfoAtIndex(uint32_t idx,ProcessInstanceInfo & info)267   bool GetProcessInfoAtIndex(uint32_t idx, ProcessInstanceInfo &info) {
268     if (idx < m_list.size()) {
269       info = m_list[idx];
270       return true;
271     }
272     return false;
273   }
274 
Clear()275   void Clear() { return m_list.clear(); }
276 
277 private:
278   ProcessInstanceInfoList m_list;
279 };
280 
281 // ProcessInstanceInfoMatch
282 //
283 // A class to help matching one ProcessInstanceInfo to another.
284 
285 class ProcessInstanceInfoMatch {
286 public:
287   ProcessInstanceInfoMatch() = default;
288 
ProcessInstanceInfoMatch(const char * process_name,NameMatch process_name_match_type)289   ProcessInstanceInfoMatch(const char *process_name,
290                            NameMatch process_name_match_type)
291       : m_name_match_type(process_name_match_type), m_match_all_users(false) {
292     m_match_info.GetExecutableFile().SetFile(process_name,
293                                              FileSpec::Style::native);
294   }
295 
GetProcessInfo()296   ProcessInstanceInfo &GetProcessInfo() { return m_match_info; }
297 
GetProcessInfo()298   const ProcessInstanceInfo &GetProcessInfo() const { return m_match_info; }
299 
GetMatchAllUsers()300   bool GetMatchAllUsers() const { return m_match_all_users; }
301 
SetMatchAllUsers(bool b)302   void SetMatchAllUsers(bool b) { m_match_all_users = b; }
303 
GetNameMatchType()304   NameMatch GetNameMatchType() const { return m_name_match_type; }
305 
SetNameMatchType(NameMatch name_match_type)306   void SetNameMatchType(NameMatch name_match_type) {
307     m_name_match_type = name_match_type;
308   }
309 
310   /// Return true iff the architecture in this object matches arch_spec.
311   bool ArchitectureMatches(const ArchSpec &arch_spec) const;
312 
313   /// Return true iff the process name in this object matches process_name.
314   bool NameMatches(const char *process_name) const;
315 
316   /// Return true iff the process ID and parent process IDs in this object match
317   /// the ones in proc_info.
318   bool ProcessIDsMatch(const ProcessInstanceInfo &proc_info) const;
319 
320   /// Return true iff the (both effective and real) user and group IDs in this
321   /// object match the ones in proc_info.
322   bool UserIDsMatch(const ProcessInstanceInfo &proc_info) const;
323 
324   bool Matches(const ProcessInstanceInfo &proc_info) const;
325 
326   bool MatchAllProcesses() const;
327   void Clear();
328 
329 protected:
330   ProcessInstanceInfo m_match_info;
331   NameMatch m_name_match_type = NameMatch::Ignore;
332   bool m_match_all_users = false;
333 };
334 
335 } // namespace lldb_private
336 
337 #endif // LLDB_UTILITY_PROCESSINFO_H
338