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 
42   FileSpec &GetExecutableFile() { return m_executable; }
43 
44   void SetExecutableFile(const FileSpec &exe_file,
45                          bool add_exe_file_as_first_arg);
46 
47   const FileSpec &GetExecutableFile() const { return m_executable; }
48 
49   uint32_t GetUserID() const { return m_uid; }
50 
51   uint32_t GetGroupID() const { return m_gid; }
52 
53   bool UserIDIsValid() const { return m_uid != UINT32_MAX; }
54 
55   bool GroupIDIsValid() const { return m_gid != UINT32_MAX; }
56 
57   void SetUserID(uint32_t uid) { m_uid = uid; }
58 
59   void SetGroupID(uint32_t gid) { m_gid = gid; }
60 
61   ArchSpec &GetArchitecture() { return m_arch; }
62 
63   const ArchSpec &GetArchitecture() const { return m_arch; }
64 
65   void SetArchitecture(const ArchSpec &arch) { m_arch = arch; }
66 
67   lldb::pid_t GetProcessID() const { return m_pid; }
68 
69   void SetProcessID(lldb::pid_t pid) { m_pid = pid; }
70 
71   bool ProcessIDIsValid() const { return m_pid != LLDB_INVALID_PROCESS_ID; }
72 
73   void Dump(Stream &s, Platform *platform) const;
74 
75   Args &GetArguments() { return m_arguments; }
76 
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 
87   Environment &GetEnvironment() { return m_environment; }
88   const Environment &GetEnvironment() const { return m_environment; }
89 
90   bool IsScriptedProcess() const;
91 
92   lldb::ScriptedMetadataSP GetScriptedMetadata() const {
93     return m_scripted_metadata_sp;
94   }
95 
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
101   lldb::ListenerSP GetListener() const { return m_listener_sp; }
102 
103   void SetListener(const lldb::ListenerSP &listener_sp) {
104     m_listener_sp = listener_sp;
105   }
106 
107   lldb::ListenerSP GetHijackListener() const { return m_hijack_listener_sp; }
108 
109   void SetHijackListener(const lldb::ListenerSP &listener_sp) {
110     m_hijack_listener_sp = listener_sp;
111   }
112 
113   lldb::ListenerSP GetShadowListener() const { return m_shadow_listener_sp; }
114 
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   ProcessInstanceInfo() = default;
143 
144   ProcessInstanceInfo(const char *name, const ArchSpec &arch, lldb::pid_t pid)
145       : ProcessInfo(name, arch, pid), m_euid(UINT32_MAX), m_egid(UINT32_MAX),
146         m_parent_pid(LLDB_INVALID_PROCESS_ID) {}
147 
148   void Clear() {
149     ProcessInfo::Clear();
150     m_euid = UINT32_MAX;
151     m_egid = UINT32_MAX;
152     m_parent_pid = LLDB_INVALID_PROCESS_ID;
153   }
154 
155   uint32_t GetEffectiveUserID() const { return m_euid; }
156 
157   uint32_t GetEffectiveGroupID() const { return m_egid; }
158 
159   bool EffectiveUserIDIsValid() const { return m_euid != UINT32_MAX; }
160 
161   bool EffectiveGroupIDIsValid() const { return m_egid != UINT32_MAX; }
162 
163   void SetEffectiveUserID(uint32_t uid) { m_euid = uid; }
164 
165   void SetEffectiveGroupID(uint32_t gid) { m_egid = gid; }
166 
167   lldb::pid_t GetParentProcessID() const { return m_parent_pid; }
168 
169   void SetParentProcessID(lldb::pid_t pid) { m_parent_pid = pid; }
170 
171   bool ParentProcessIDIsValid() const {
172     return m_parent_pid != LLDB_INVALID_PROCESS_ID;
173   }
174 
175   void Dump(Stream &s, UserIDResolver &resolver) const;
176 
177   static void DumpTableHeader(Stream &s, bool show_args, bool verbose);
178 
179   void DumpAsTableRow(Stream &s, UserIDResolver &resolver, bool show_args,
180                       bool verbose) const;
181 
182 protected:
183   uint32_t m_euid = UINT32_MAX;
184   uint32_t m_egid = UINT32_MAX;
185   lldb::pid_t m_parent_pid = LLDB_INVALID_PROCESS_ID;
186 };
187 
188 typedef std::vector<ProcessInstanceInfo> ProcessInstanceInfoList;
189 
190 class ProcessInfoList {
191 public:
192   ProcessInfoList(const ProcessInstanceInfoList &list) : m_list(list) {}
193 
194   uint32_t GetSize() const { return m_list.size(); }
195 
196   bool GetProcessInfoAtIndex(uint32_t idx, ProcessInstanceInfo &info) {
197     if (idx < m_list.size()) {
198       info = m_list[idx];
199       return true;
200     }
201     return false;
202   }
203 
204   void Clear() { return m_list.clear(); }
205 
206 private:
207   ProcessInstanceInfoList m_list;
208 };
209 
210 // ProcessInstanceInfoMatch
211 //
212 // A class to help matching one ProcessInstanceInfo to another.
213 
214 class ProcessInstanceInfoMatch {
215 public:
216   ProcessInstanceInfoMatch() = default;
217 
218   ProcessInstanceInfoMatch(const char *process_name,
219                            NameMatch process_name_match_type)
220       : m_name_match_type(process_name_match_type), m_match_all_users(false) {
221     m_match_info.GetExecutableFile().SetFile(process_name,
222                                              FileSpec::Style::native);
223   }
224 
225   ProcessInstanceInfo &GetProcessInfo() { return m_match_info; }
226 
227   const ProcessInstanceInfo &GetProcessInfo() const { return m_match_info; }
228 
229   bool GetMatchAllUsers() const { return m_match_all_users; }
230 
231   void SetMatchAllUsers(bool b) { m_match_all_users = b; }
232 
233   NameMatch GetNameMatchType() const { return m_name_match_type; }
234 
235   void SetNameMatchType(NameMatch name_match_type) {
236     m_name_match_type = name_match_type;
237   }
238 
239   /// Return true iff the architecture in this object matches arch_spec.
240   bool ArchitectureMatches(const ArchSpec &arch_spec) const;
241 
242   /// Return true iff the process name in this object matches process_name.
243   bool NameMatches(const char *process_name) const;
244 
245   /// Return true iff the process ID and parent process IDs in this object match
246   /// the ones in proc_info.
247   bool ProcessIDsMatch(const ProcessInstanceInfo &proc_info) const;
248 
249   /// Return true iff the (both effective and real) user and group IDs in this
250   /// object match the ones in proc_info.
251   bool UserIDsMatch(const ProcessInstanceInfo &proc_info) const;
252 
253   bool Matches(const ProcessInstanceInfo &proc_info) const;
254 
255   bool MatchAllProcesses() const;
256   void Clear();
257 
258 protected:
259   ProcessInstanceInfo m_match_info;
260   NameMatch m_name_match_type = NameMatch::Ignore;
261   bool m_match_all_users = false;
262 };
263 
264 } // namespace lldb_private
265 
266 #endif // LLDB_UTILITY_PROCESSINFO_H
267