1 //===-- ProcessInfo.cpp ---------------------------------------------------===//
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/ScriptedMetadata.h"
13 #include "lldb/Utility/Stream.h"
14 #include "lldb/Utility/StreamString.h"
15 #include "lldb/Utility/UserIDResolver.h"
16 #include "llvm/ADT/SmallString.h"
22 using namespace lldb_private
;
24 ProcessInfo::ProcessInfo()
25 : m_executable(), m_arguments(), m_environment(), m_arch(), m_listener_sp(),
26 m_hijack_listener_sp(), m_shadow_listener_sp() {}
28 ProcessInfo::ProcessInfo(const char *name
, const ArchSpec
&arch
,
30 : m_executable(name
), m_arguments(), m_environment(), m_arch(arch
),
31 m_pid(pid
), m_listener_sp(), m_hijack_listener_sp(),
32 m_shadow_listener_sp() {}
34 void ProcessInfo::Clear() {
37 m_environment
.clear();
41 m_pid
= LLDB_INVALID_PROCESS_ID
;
42 m_scripted_metadata_sp
.reset();
45 const char *ProcessInfo::GetName() const {
46 return m_executable
.GetFilename().GetCString();
49 llvm::StringRef
ProcessInfo::GetNameAsStringRef() const {
50 return m_executable
.GetFilename().GetStringRef();
53 void ProcessInfo::Dump(Stream
&s
, Platform
*platform
) const {
54 s
<< "Executable: " << GetName() << "\n";
56 m_arch
.DumpTriple(s
.AsRawOstream());
62 s
.Format("Environment:\n{0}", m_environment
);
65 void ProcessInfo::SetExecutableFile(const FileSpec
&exe_file
,
66 bool add_exe_file_as_first_arg
) {
68 m_executable
= exe_file
;
69 if (add_exe_file_as_first_arg
) {
70 llvm::SmallString
<128> filename
;
71 exe_file
.GetPath(filename
);
72 if (!filename
.empty())
73 m_arguments
.InsertArgumentAtIndex(0, filename
);
80 llvm::StringRef
ProcessInfo::GetArg0() const { return m_arg0
; }
82 void ProcessInfo::SetArg0(llvm::StringRef arg
) { m_arg0
= std::string(arg
); }
84 void ProcessInfo::SetArguments(char const **argv
,
85 bool first_arg_is_executable
) {
86 m_arguments
.SetArguments(argv
);
88 // Is the first argument the executable?
89 if (first_arg_is_executable
) {
90 const char *first_arg
= m_arguments
.GetArgumentAtIndex(0);
92 // Yes the first argument is an executable, set it as the executable in
93 // the launch options. Don't resolve the file path as the path could be a
94 // remote platform path
95 m_executable
.SetFile(first_arg
, FileSpec::Style::native
);
100 void ProcessInfo::SetArguments(const Args
&args
, bool first_arg_is_executable
) {
101 // Copy all arguments
104 // Is the first argument the executable?
105 if (first_arg_is_executable
) {
106 const char *first_arg
= m_arguments
.GetArgumentAtIndex(0);
108 // Yes the first argument is an executable, set it as the executable in
109 // the launch options. Don't resolve the file path as the path could be a
110 // remote platform path
111 m_executable
.SetFile(first_arg
, FileSpec::Style::native
);
116 bool ProcessInfo::IsScriptedProcess() const {
117 return m_scripted_metadata_sp
&& *m_scripted_metadata_sp
;
120 void ProcessInstanceInfo::Dump(Stream
&s
, UserIDResolver
&resolver
) const {
121 if (m_pid
!= LLDB_INVALID_PROCESS_ID
)
122 s
.Printf(" pid = %" PRIu64
"\n", m_pid
);
124 if (m_parent_pid
!= LLDB_INVALID_PROCESS_ID
)
125 s
.Printf(" parent = %" PRIu64
"\n", m_parent_pid
);
128 s
.Printf(" name = %s\n", m_executable
.GetFilename().GetCString());
129 s
.PutCString(" file = ");
130 m_executable
.Dump(s
.AsRawOstream());
133 const uint32_t argc
= m_arguments
.GetArgumentCount();
135 for (uint32_t i
= 0; i
< argc
; i
++) {
136 const char *arg
= m_arguments
.GetArgumentAtIndex(i
);
138 s
.Printf(" arg[%u] = %s\n", i
, arg
);
140 s
.Printf("arg[%u] = %s\n", i
, arg
);
144 s
.Format("{0}", m_environment
);
146 if (m_arch
.IsValid()) {
147 s
.Printf(" arch = ");
148 m_arch
.DumpTriple(s
.AsRawOstream());
152 if (UserIDIsValid()) {
153 s
.Format(" uid = {0,-5} ({1})\n", GetUserID(),
154 resolver
.GetUserName(GetUserID()).value_or(""));
156 if (GroupIDIsValid()) {
157 s
.Format(" gid = {0,-5} ({1})\n", GetGroupID(),
158 resolver
.GetGroupName(GetGroupID()).value_or(""));
160 if (EffectiveUserIDIsValid()) {
161 s
.Format(" euid = {0,-5} ({1})\n", GetEffectiveUserID(),
162 resolver
.GetUserName(GetEffectiveUserID()).value_or(""));
164 if (EffectiveGroupIDIsValid()) {
165 s
.Format(" egid = {0,-5} ({1})\n", GetEffectiveGroupID(),
166 resolver
.GetGroupName(GetEffectiveGroupID()).value_or(""));
170 void ProcessInstanceInfo::DumpTableHeader(Stream
&s
, bool show_args
,
173 if (show_args
|| verbose
)
179 s
.Printf("PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE "
183 "====== ====== ========== ========== ========== ========== "
184 "============================== ============================\n");
186 s
.Printf("PID PARENT USER TRIPLE %s\n",
188 s
.PutCString("====== ====== ========== ============================== "
189 "============================\n");
193 void ProcessInstanceInfo::DumpAsTableRow(Stream
&s
, UserIDResolver
&resolver
,
194 bool show_args
, bool verbose
) const {
195 if (m_pid
!= LLDB_INVALID_PROCESS_ID
) {
196 s
.Printf("%-6" PRIu64
" %-6" PRIu64
" ", m_pid
, m_parent_pid
);
198 StreamString arch_strm
;
199 if (m_arch
.IsValid())
200 m_arch
.DumpTriple(arch_strm
.AsRawOstream());
202 auto print
= [&](bool (ProcessInstanceInfo::*isValid
)() const,
203 uint32_t (ProcessInstanceInfo::*getID
)() const,
204 std::optional
<llvm::StringRef
> (UserIDResolver::*getName
)(
205 UserIDResolver::id_t id
)) {
206 const char *format
= "{0,-10} ";
207 if (!(this->*isValid
)()) {
208 s
.Format(format
, "");
211 uint32_t id
= (this->*getID
)();
212 if (auto name
= (resolver
.*getName
)(id
))
213 s
.Format(format
, *name
);
215 s
.Format(format
, id
);
218 print(&ProcessInstanceInfo::UserIDIsValid
,
219 &ProcessInstanceInfo::GetUserID
, &UserIDResolver::GetUserName
);
220 print(&ProcessInstanceInfo::GroupIDIsValid
,
221 &ProcessInstanceInfo::GetGroupID
, &UserIDResolver::GetGroupName
);
222 print(&ProcessInstanceInfo::EffectiveUserIDIsValid
,
223 &ProcessInstanceInfo::GetEffectiveUserID
,
224 &UserIDResolver::GetUserName
);
225 print(&ProcessInstanceInfo::EffectiveGroupIDIsValid
,
226 &ProcessInstanceInfo::GetEffectiveGroupID
,
227 &UserIDResolver::GetGroupName
);
229 s
.Printf("%-30s ", arch_strm
.GetData());
231 print(&ProcessInstanceInfo::EffectiveUserIDIsValid
,
232 &ProcessInstanceInfo::GetEffectiveUserID
,
233 &UserIDResolver::GetUserName
);
234 s
.Printf("%-30s ", arch_strm
.GetData());
237 if (verbose
|| show_args
) {
238 s
.PutCString(m_arg0
);
239 const uint32_t argc
= m_arguments
.GetArgumentCount();
240 for (uint32_t i
= 0; i
< argc
; i
++) {
242 s
.PutCString(m_arguments
.GetArgumentAtIndex(i
));
245 s
.PutCString(GetName());
252 bool ProcessInstanceInfoMatch::ArchitectureMatches(
253 const ArchSpec
&arch_spec
) const {
254 return !m_match_info
.GetArchitecture().IsValid() ||
255 m_match_info
.GetArchitecture().IsCompatibleMatch(arch_spec
);
258 bool ProcessInstanceInfoMatch::NameMatches(const char *process_name
) const {
259 if (m_name_match_type
== NameMatch::Ignore
)
261 const char *match_name
= m_match_info
.GetName();
265 return lldb_private::NameMatches(process_name
, m_name_match_type
, match_name
);
268 bool ProcessInstanceInfoMatch::ProcessIDsMatch(
269 const ProcessInstanceInfo
&proc_info
) const {
270 if (m_match_info
.ProcessIDIsValid() &&
271 m_match_info
.GetProcessID() != proc_info
.GetProcessID())
274 if (m_match_info
.ParentProcessIDIsValid() &&
275 m_match_info
.GetParentProcessID() != proc_info
.GetParentProcessID())
280 bool ProcessInstanceInfoMatch::UserIDsMatch(
281 const ProcessInstanceInfo
&proc_info
) const {
282 if (m_match_info
.UserIDIsValid() &&
283 m_match_info
.GetUserID() != proc_info
.GetUserID())
286 if (m_match_info
.GroupIDIsValid() &&
287 m_match_info
.GetGroupID() != proc_info
.GetGroupID())
290 if (m_match_info
.EffectiveUserIDIsValid() &&
291 m_match_info
.GetEffectiveUserID() != proc_info
.GetEffectiveUserID())
294 if (m_match_info
.EffectiveGroupIDIsValid() &&
295 m_match_info
.GetEffectiveGroupID() != proc_info
.GetEffectiveGroupID())
299 bool ProcessInstanceInfoMatch::Matches(
300 const ProcessInstanceInfo
&proc_info
) const {
301 return ArchitectureMatches(proc_info
.GetArchitecture()) &&
302 ProcessIDsMatch(proc_info
) && UserIDsMatch(proc_info
) &&
303 NameMatches(proc_info
.GetName());
306 bool ProcessInstanceInfoMatch::MatchAllProcesses() const {
307 if (m_name_match_type
!= NameMatch::Ignore
)
310 if (m_match_info
.ProcessIDIsValid())
313 if (m_match_info
.ParentProcessIDIsValid())
316 if (m_match_info
.UserIDIsValid())
319 if (m_match_info
.GroupIDIsValid())
322 if (m_match_info
.EffectiveUserIDIsValid())
325 if (m_match_info
.EffectiveGroupIDIsValid())
328 if (m_match_info
.GetArchitecture().IsValid())
331 if (m_match_all_users
)
337 void ProcessInstanceInfoMatch::Clear() {
338 m_match_info
.Clear();
339 m_name_match_type
= NameMatch::Ignore
;
340 m_match_all_users
= false;