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/Reproducer.h"
18 #include "llvm/Support/YAMLTraits.h"
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 
43   FileSpec &GetExecutableFile() { return m_executable; }
44 
45   void SetExecutableFile(const FileSpec &exe_file,
46                          bool add_exe_file_as_first_arg);
47 
48   const FileSpec &GetExecutableFile() const { return m_executable; }
49 
50   uint32_t GetUserID() const { return m_uid; }
51 
52   uint32_t GetGroupID() const { return m_gid; }
53 
54   bool UserIDIsValid() const { return m_uid != UINT32_MAX; }
55 
56   bool GroupIDIsValid() const { return m_gid != UINT32_MAX; }
57 
58   void SetUserID(uint32_t uid) { m_uid = uid; }
59 
60   void SetGroupID(uint32_t gid) { m_gid = gid; }
61 
62   ArchSpec &GetArchitecture() { return m_arch; }
63 
64   const ArchSpec &GetArchitecture() const { return m_arch; }
65 
66   void SetArchitecture(const ArchSpec &arch) { m_arch = arch; }
67 
68   lldb::pid_t GetProcessID() const { return m_pid; }
69 
70   void SetProcessID(lldb::pid_t pid) { m_pid = pid; }
71 
72   bool ProcessIDIsValid() const { return m_pid != LLDB_INVALID_PROCESS_ID; }
73 
74   void Dump(Stream &s, Platform *platform) const;
75 
76   Args &GetArguments() { return m_arguments; }
77 
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 
88   Environment &GetEnvironment() { return m_environment; }
89   const Environment &GetEnvironment() const { return m_environment; }
90 
91 protected:
92   template <class T> friend struct llvm::yaml::MappingTraits;
93   FileSpec m_executable;
94   std::string m_arg0; // argv[0] if supported. If empty, then use m_executable.
95   // Not all process plug-ins support specifying an argv[0] that differs from
96   // the resolved platform executable (which is in m_executable)
97   Args m_arguments; // All program arguments except argv[0]
98   Environment m_environment;
99   uint32_t m_uid;
100   uint32_t m_gid;
101   ArchSpec m_arch;
102   lldb::pid_t m_pid;
103 };
104 
105 // ProcessInstanceInfo
106 //
107 // Describes an existing process and any discoverable information that pertains
108 // to that process.
109 class ProcessInstanceInfo : public ProcessInfo {
110 public:
111   ProcessInstanceInfo()
112       : ProcessInfo(), m_euid(UINT32_MAX), m_egid(UINT32_MAX),
113         m_parent_pid(LLDB_INVALID_PROCESS_ID) {}
114 
115   ProcessInstanceInfo(const char *name, const ArchSpec &arch, lldb::pid_t pid)
116       : ProcessInfo(name, arch, pid), m_euid(UINT32_MAX), m_egid(UINT32_MAX),
117         m_parent_pid(LLDB_INVALID_PROCESS_ID) {}
118 
119   void Clear() {
120     ProcessInfo::Clear();
121     m_euid = UINT32_MAX;
122     m_egid = UINT32_MAX;
123     m_parent_pid = LLDB_INVALID_PROCESS_ID;
124   }
125 
126   uint32_t GetEffectiveUserID() const { return m_euid; }
127 
128   uint32_t GetEffectiveGroupID() const { return m_egid; }
129 
130   bool EffectiveUserIDIsValid() const { return m_euid != UINT32_MAX; }
131 
132   bool EffectiveGroupIDIsValid() const { return m_egid != UINT32_MAX; }
133 
134   void SetEffectiveUserID(uint32_t uid) { m_euid = uid; }
135 
136   void SetEffectiveGroupID(uint32_t gid) { m_egid = gid; }
137 
138   lldb::pid_t GetParentProcessID() const { return m_parent_pid; }
139 
140   void SetParentProcessID(lldb::pid_t pid) { m_parent_pid = pid; }
141 
142   bool ParentProcessIDIsValid() const {
143     return m_parent_pid != LLDB_INVALID_PROCESS_ID;
144   }
145 
146   void Dump(Stream &s, UserIDResolver &resolver) const;
147 
148   static void DumpTableHeader(Stream &s, bool show_args, bool verbose);
149 
150   void DumpAsTableRow(Stream &s, UserIDResolver &resolver, bool show_args,
151                       bool verbose) const;
152 
153 protected:
154   friend struct llvm::yaml::MappingTraits<ProcessInstanceInfo>;
155   uint32_t m_euid;
156   uint32_t m_egid;
157   lldb::pid_t m_parent_pid;
158 };
159 
160 typedef std::vector<ProcessInstanceInfo> ProcessInstanceInfoList;
161 
162 // ProcessInstanceInfoMatch
163 //
164 // A class to help matching one ProcessInstanceInfo to another.
165 
166 class ProcessInstanceInfoMatch {
167 public:
168   ProcessInstanceInfoMatch()
169       : m_match_info(), m_name_match_type(NameMatch::Ignore),
170         m_match_all_users(false) {}
171 
172   ProcessInstanceInfoMatch(const char *process_name,
173                            NameMatch process_name_match_type)
174       : m_match_info(), m_name_match_type(process_name_match_type),
175         m_match_all_users(false) {
176     m_match_info.GetExecutableFile().SetFile(process_name,
177                                              FileSpec::Style::native);
178   }
179 
180   ProcessInstanceInfo &GetProcessInfo() { return m_match_info; }
181 
182   const ProcessInstanceInfo &GetProcessInfo() const { return m_match_info; }
183 
184   bool GetMatchAllUsers() const { return m_match_all_users; }
185 
186   void SetMatchAllUsers(bool b) { m_match_all_users = b; }
187 
188   NameMatch GetNameMatchType() const { return m_name_match_type; }
189 
190   void SetNameMatchType(NameMatch name_match_type) {
191     m_name_match_type = name_match_type;
192   }
193 
194   /// Return true iff the architecture in this object matches arch_spec.
195   bool ArchitectureMatches(const ArchSpec &arch_spec) const;
196 
197   /// Return true iff the process name in this object matches process_name.
198   bool NameMatches(const char *process_name) const;
199 
200   /// Return true iff the process ID and parent process IDs in this object match
201   /// the ones in proc_info.
202   bool ProcessIDsMatch(const ProcessInstanceInfo &proc_info) const;
203 
204   /// Return true iff the (both effective and real) user and group IDs in this
205   /// object match the ones in proc_info.
206   bool UserIDsMatch(const ProcessInstanceInfo &proc_info) const;
207 
208   bool Matches(const ProcessInstanceInfo &proc_info) const;
209 
210   bool MatchAllProcesses() const;
211   void Clear();
212 
213 protected:
214   ProcessInstanceInfo m_match_info;
215   NameMatch m_name_match_type;
216   bool m_match_all_users;
217 };
218 
219 namespace repro {
220 class ProcessInfoRecorder : public AbstractRecorder {
221 public:
222   ProcessInfoRecorder(const FileSpec &filename, std::error_code &ec)
223       : AbstractRecorder(filename, ec) {}
224 
225   static llvm::Expected<std::unique_ptr<ProcessInfoRecorder>>
226   Create(const FileSpec &filename);
227 
228   void Record(const ProcessInstanceInfoList &process_infos);
229 };
230 
231 class ProcessInfoProvider : public repro::Provider<ProcessInfoProvider> {
232 public:
233   struct Info {
234     static const char *name;
235     static const char *file;
236   };
237 
238   ProcessInfoProvider(const FileSpec &directory) : Provider(directory) {}
239 
240   ProcessInfoRecorder *GetNewProcessInfoRecorder();
241 
242   void Keep() override;
243   void Discard() override;
244 
245   static char ID;
246 
247 private:
248   std::unique_ptr<llvm::raw_fd_ostream> m_stream_up;
249   std::vector<std::unique_ptr<ProcessInfoRecorder>> m_process_info_recorders;
250 };
251 
252 llvm::Optional<ProcessInstanceInfoList> GetReplayProcessInstanceInfoList();
253 
254 } // namespace repro
255 } // namespace lldb_private
256 
257 LLVM_YAML_IS_SEQUENCE_VECTOR(lldb_private::ProcessInstanceInfo)
258 
259 namespace llvm {
260 namespace yaml {
261 template <> struct MappingTraits<lldb_private::ProcessInstanceInfo> {
262   static void mapping(IO &io, lldb_private::ProcessInstanceInfo &PII);
263 };
264 } // namespace yaml
265 } // namespace llvm
266 
267 #endif // LLDB_UTILITY_PROCESSINFO_H
268