1 //===-- ProcessInfo.cpp -----------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Utility/ProcessInfo.h"
11 #include "lldb/Utility/ArchSpec.h"
12 #include "lldb/Utility/Stream.h"
13 #include "lldb/Utility/StreamString.h"
14 #include "lldb/Utility/UserIDResolver.h"
15 #include "llvm/ADT/SmallString.h"
20 using namespace lldb_private;
22 ProcessInfo::ProcessInfo()
23 : m_executable(), m_arguments(), m_environment(), m_uid(UINT32_MAX),
24 m_gid(UINT32_MAX), m_arch(), m_pid(LLDB_INVALID_PROCESS_ID) {}
26 ProcessInfo::ProcessInfo(const char *name, const ArchSpec &arch,
28 : m_executable(name), m_arguments(), m_environment(), m_uid(UINT32_MAX),
29 m_gid(UINT32_MAX), m_arch(arch), m_pid(pid) {}
31 void ProcessInfo::Clear() {
34 m_environment.clear();
38 m_pid = LLDB_INVALID_PROCESS_ID;
41 const char *ProcessInfo::GetName() const {
42 return m_executable.GetFilename().GetCString();
45 size_t ProcessInfo::GetNameLength() const {
46 return m_executable.GetFilename().GetLength();
49 void ProcessInfo::Dump(Stream &s, Platform *platform) const {
50 s << "Executable: " << GetName() << "\n";
58 s.Format("Environment:\n{0}", m_environment);
61 void ProcessInfo::SetExecutableFile(const FileSpec &exe_file,
62 bool add_exe_file_as_first_arg) {
64 m_executable = exe_file;
65 if (add_exe_file_as_first_arg) {
66 llvm::SmallString<128> filename;
67 exe_file.GetPath(filename);
68 if (!filename.empty())
69 m_arguments.InsertArgumentAtIndex(0, filename);
76 llvm::StringRef ProcessInfo::GetArg0() const { return m_arg0; }
78 void ProcessInfo::SetArg0(llvm::StringRef arg) { m_arg0 = arg; }
80 void ProcessInfo::SetArguments(char const **argv,
81 bool first_arg_is_executable) {
82 m_arguments.SetArguments(argv);
84 // Is the first argument the executable?
85 if (first_arg_is_executable) {
86 const char *first_arg = m_arguments.GetArgumentAtIndex(0);
88 // Yes the first argument is an executable, set it as the executable in
89 // the launch options. Don't resolve the file path as the path could be a
90 // remote platform path
91 m_executable.SetFile(first_arg, FileSpec::Style::native);
96 void ProcessInfo::SetArguments(const Args &args, bool first_arg_is_executable) {
100 // Is the first argument the executable?
101 if (first_arg_is_executable) {
102 const char *first_arg = m_arguments.GetArgumentAtIndex(0);
104 // Yes the first argument is an executable, set it as the executable in
105 // the launch options. Don't resolve the file path as the path could be a
106 // remote platform path
107 m_executable.SetFile(first_arg, FileSpec::Style::native);
112 void ProcessInstanceInfo::Dump(Stream &s, UserIDResolver &resolver) const {
113 if (m_pid != LLDB_INVALID_PROCESS_ID)
114 s.Printf(" pid = %" PRIu64 "\n", m_pid);
116 if (m_parent_pid != LLDB_INVALID_PROCESS_ID)
117 s.Printf(" parent = %" PRIu64 "\n", m_parent_pid);
120 s.Printf(" name = %s\n", m_executable.GetFilename().GetCString());
121 s.PutCString(" file = ");
122 m_executable.Dump(&s);
125 const uint32_t argc = m_arguments.GetArgumentCount();
127 for (uint32_t i = 0; i < argc; i++) {
128 const char *arg = m_arguments.GetArgumentAtIndex(i);
130 s.Printf(" arg[%u] = %s\n", i, arg);
132 s.Printf("arg[%u] = %s\n", i, arg);
136 s.Format("{0}", m_environment);
138 if (m_arch.IsValid()) {
139 s.Printf(" arch = ");
140 m_arch.DumpTriple(s);
144 if (UserIDIsValid()) {
145 s.Format(" uid = {0,-5} ({1})\n", GetUserID(),
146 resolver.GetUserName(GetUserID()).getValueOr(""));
148 if (GroupIDIsValid()) {
149 s.Format(" gid = {0,-5} ({1})\n", GetGroupID(),
150 resolver.GetGroupName(GetGroupID()).getValueOr(""));
152 if (EffectiveUserIDIsValid()) {
153 s.Format(" euid = {0,-5} ({1})\n", GetEffectiveUserID(),
154 resolver.GetUserName(GetEffectiveUserID()).getValueOr(""));
156 if (EffectiveGroupIDIsValid()) {
157 s.Format(" egid = {0,-5} ({1})\n", GetEffectiveGroupID(),
158 resolver.GetGroupName(GetEffectiveGroupID()).getValueOr(""));
162 void ProcessInstanceInfo::DumpTableHeader(Stream &s, bool show_args,
165 if (show_args || verbose)
171 s.Printf("PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE "
174 s.PutCString("====== ====== ========== ========== ========== ========== "
175 "======================== ============================\n");
177 s.Printf("PID PARENT USER TRIPLE %s\n", label);
178 s.PutCString("====== ====== ========== ======================== "
179 "============================\n");
183 void ProcessInstanceInfo::DumpAsTableRow(Stream &s, UserIDResolver &resolver,
184 bool show_args, bool verbose) const {
185 if (m_pid != LLDB_INVALID_PROCESS_ID) {
186 s.Printf("%-6" PRIu64 " %-6" PRIu64 " ", m_pid, m_parent_pid);
188 StreamString arch_strm;
189 if (m_arch.IsValid())
190 m_arch.DumpTriple(arch_strm);
192 auto print = [&](UserIDResolver::id_t id,
193 llvm::Optional<llvm::StringRef> (UserIDResolver::*get)(
194 UserIDResolver::id_t id)) {
195 if (auto name = (resolver.*get)(id))
196 s.Format("{0,-10} ", *name);
198 s.Format("{0,-10} ", id);
201 print(m_uid, &UserIDResolver::GetUserName);
202 print(m_gid, &UserIDResolver::GetGroupName);
203 print(m_euid, &UserIDResolver::GetUserName);
204 print(m_egid, &UserIDResolver::GetGroupName);
206 s.Printf("%-24s ", arch_strm.GetData());
208 print(m_euid, &UserIDResolver::GetUserName);
209 s.Printf(" %-24s ", arch_strm.GetData());
212 if (verbose || show_args) {
213 const uint32_t argc = m_arguments.GetArgumentCount();
215 for (uint32_t i = 0; i < argc; i++) {
218 s.PutCString(m_arguments.GetArgumentAtIndex(i));
222 s.PutCString(GetName());
229 bool ProcessInstanceInfoMatch::NameMatches(const char *process_name) const {
230 if (m_name_match_type == NameMatch::Ignore || process_name == nullptr)
232 const char *match_name = m_match_info.GetName();
236 return lldb_private::NameMatches(process_name, m_name_match_type, match_name);
239 bool ProcessInstanceInfoMatch::Matches(
240 const ProcessInstanceInfo &proc_info) const {
241 if (!NameMatches(proc_info.GetName()))
244 if (m_match_info.ProcessIDIsValid() &&
245 m_match_info.GetProcessID() != proc_info.GetProcessID())
248 if (m_match_info.ParentProcessIDIsValid() &&
249 m_match_info.GetParentProcessID() != proc_info.GetParentProcessID())
252 if (m_match_info.UserIDIsValid() &&
253 m_match_info.GetUserID() != proc_info.GetUserID())
256 if (m_match_info.GroupIDIsValid() &&
257 m_match_info.GetGroupID() != proc_info.GetGroupID())
260 if (m_match_info.EffectiveUserIDIsValid() &&
261 m_match_info.GetEffectiveUserID() != proc_info.GetEffectiveUserID())
264 if (m_match_info.EffectiveGroupIDIsValid() &&
265 m_match_info.GetEffectiveGroupID() != proc_info.GetEffectiveGroupID())
268 if (m_match_info.GetArchitecture().IsValid() &&
269 !m_match_info.GetArchitecture().IsCompatibleMatch(
270 proc_info.GetArchitecture()))
275 bool ProcessInstanceInfoMatch::MatchAllProcesses() const {
276 if (m_name_match_type != NameMatch::Ignore)
279 if (m_match_info.ProcessIDIsValid())
282 if (m_match_info.ParentProcessIDIsValid())
285 if (m_match_info.UserIDIsValid())
288 if (m_match_info.GroupIDIsValid())
291 if (m_match_info.EffectiveUserIDIsValid())
294 if (m_match_info.EffectiveGroupIDIsValid())
297 if (m_match_info.GetArchitecture().IsValid())
300 if (m_match_all_users)
306 void ProcessInstanceInfoMatch::Clear() {
307 m_match_info.Clear();
308 m_name_match_type = NameMatch::Ignore;
309 m_match_all_users = false;