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
20namespace lldb_private {
21
22class 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.
30class ProcessInfo {
31public:
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
119protected:
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.
140class ProcessInstanceInfo : public ProcessInfo {
141public:
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
182protected:
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
188typedef std::vector<ProcessInstanceInfo> ProcessInstanceInfoList;
189
190class ProcessInfoList {
191public:
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
206private:
207  ProcessInstanceInfoList m_list;
208};
209
210// ProcessInstanceInfoMatch
211//
212// A class to help matching one ProcessInstanceInfo to another.
213
214class ProcessInstanceInfoMatch {
215public:
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
258protected:
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