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 (ParentProcessIDIsValid())
125 s
.Printf(" parent = %" PRIu64
"\n", GetParentProcessID());
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
,
197 (ParentProcessIDIsValid()) ? GetParentProcessID() : 0);
199 StreamString arch_strm
;
200 if (m_arch
.IsValid())
201 m_arch
.DumpTriple(arch_strm
.AsRawOstream());
203 auto print
= [&](bool (ProcessInstanceInfo::*isValid
)() const,
204 uint32_t (ProcessInstanceInfo::*getID
)() const,
205 std::optional
<llvm::StringRef
> (UserIDResolver::*getName
)(
206 UserIDResolver::id_t id
)) {
207 const char *format
= "{0,-10} ";
208 if (!(this->*isValid
)()) {
209 s
.Format(format
, "");
212 uint32_t id
= (this->*getID
)();
213 if (auto name
= (resolver
.*getName
)(id
))
214 s
.Format(format
, *name
);
216 s
.Format(format
, id
);
219 print(&ProcessInstanceInfo::UserIDIsValid
,
220 &ProcessInstanceInfo::GetUserID
, &UserIDResolver::GetUserName
);
221 print(&ProcessInstanceInfo::GroupIDIsValid
,
222 &ProcessInstanceInfo::GetGroupID
, &UserIDResolver::GetGroupName
);
223 print(&ProcessInstanceInfo::EffectiveUserIDIsValid
,
224 &ProcessInstanceInfo::GetEffectiveUserID
,
225 &UserIDResolver::GetUserName
);
226 print(&ProcessInstanceInfo::EffectiveGroupIDIsValid
,
227 &ProcessInstanceInfo::GetEffectiveGroupID
,
228 &UserIDResolver::GetGroupName
);
230 s
.Printf("%-30s ", arch_strm
.GetData());
232 print(&ProcessInstanceInfo::EffectiveUserIDIsValid
,
233 &ProcessInstanceInfo::GetEffectiveUserID
,
234 &UserIDResolver::GetUserName
);
235 s
.Printf("%-30s ", arch_strm
.GetData());
238 if (verbose
|| show_args
) {
239 s
.PutCString(m_arg0
);
240 const uint32_t argc
= m_arguments
.GetArgumentCount();
241 for (uint32_t i
= 0; i
< argc
; i
++) {
243 s
.PutCString(m_arguments
.GetArgumentAtIndex(i
));
246 s
.PutCString(GetName());
253 bool ProcessInstanceInfoMatch::ArchitectureMatches(
254 const ArchSpec
&arch_spec
) const {
255 return !m_match_info
.GetArchitecture().IsValid() ||
256 m_match_info
.GetArchitecture().IsCompatibleMatch(arch_spec
);
259 bool ProcessInstanceInfoMatch::NameMatches(const char *process_name
) const {
260 if (m_name_match_type
== NameMatch::Ignore
)
262 const char *match_name
= m_match_info
.GetName();
266 return lldb_private::NameMatches(process_name
, m_name_match_type
, match_name
);
269 bool ProcessInstanceInfoMatch::ProcessIDsMatch(
270 const ProcessInstanceInfo
&proc_info
) const {
271 if (m_match_info
.ProcessIDIsValid() &&
272 m_match_info
.GetProcessID() != proc_info
.GetProcessID())
275 if (m_match_info
.ParentProcessIDIsValid() &&
276 m_match_info
.GetParentProcessID() != proc_info
.GetParentProcessID())
281 bool ProcessInstanceInfoMatch::UserIDsMatch(
282 const ProcessInstanceInfo
&proc_info
) const {
283 if (m_match_info
.UserIDIsValid() &&
284 m_match_info
.GetUserID() != proc_info
.GetUserID())
287 if (m_match_info
.GroupIDIsValid() &&
288 m_match_info
.GetGroupID() != proc_info
.GetGroupID())
291 if (m_match_info
.EffectiveUserIDIsValid() &&
292 m_match_info
.GetEffectiveUserID() != proc_info
.GetEffectiveUserID())
295 if (m_match_info
.EffectiveGroupIDIsValid() &&
296 m_match_info
.GetEffectiveGroupID() != proc_info
.GetEffectiveGroupID())
300 bool ProcessInstanceInfoMatch::Matches(
301 const ProcessInstanceInfo
&proc_info
) const {
302 return ArchitectureMatches(proc_info
.GetArchitecture()) &&
303 ProcessIDsMatch(proc_info
) && UserIDsMatch(proc_info
) &&
304 NameMatches(proc_info
.GetName());
307 bool ProcessInstanceInfoMatch::MatchAllProcesses() const {
308 if (m_name_match_type
!= NameMatch::Ignore
)
311 if (m_match_info
.ProcessIDIsValid())
314 if (m_match_info
.ParentProcessIDIsValid())
317 if (m_match_info
.UserIDIsValid())
320 if (m_match_info
.GroupIDIsValid())
323 if (m_match_info
.EffectiveUserIDIsValid())
326 if (m_match_info
.EffectiveGroupIDIsValid())
329 if (m_match_info
.GetArchitecture().IsValid())
332 if (m_match_all_users
)
338 void ProcessInstanceInfoMatch::Clear() {
339 m_match_info
.Clear();
340 m_name_match_type
= NameMatch::Ignore
;
341 m_match_all_users
= false;