1dda28197Spatrick //===-- ProcessInfo.cpp ---------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "lldb/Utility/ProcessInfo.h"
10061da546Spatrick
11061da546Spatrick #include "lldb/Utility/ArchSpec.h"
12061da546Spatrick #include "lldb/Utility/Stream.h"
13061da546Spatrick #include "lldb/Utility/StreamString.h"
14061da546Spatrick #include "lldb/Utility/UserIDResolver.h"
15061da546Spatrick #include "llvm/ADT/SmallString.h"
16061da546Spatrick
17061da546Spatrick #include <climits>
18*f6aab3d8Srobert #include <optional>
19061da546Spatrick
20061da546Spatrick using namespace lldb;
21061da546Spatrick using namespace lldb_private;
22061da546Spatrick
ProcessInfo()23061da546Spatrick ProcessInfo::ProcessInfo()
24be691f3bSpatrick : m_executable(), m_arguments(), m_environment(), m_arch() {}
25061da546Spatrick
ProcessInfo(const char * name,const ArchSpec & arch,lldb::pid_t pid)26061da546Spatrick ProcessInfo::ProcessInfo(const char *name, const ArchSpec &arch,
27061da546Spatrick lldb::pid_t pid)
28*f6aab3d8Srobert : m_executable(name), m_arguments(), m_environment(), m_arch(arch),
29*f6aab3d8Srobert m_pid(pid) {}
30061da546Spatrick
Clear()31061da546Spatrick void ProcessInfo::Clear() {
32061da546Spatrick m_executable.Clear();
33061da546Spatrick m_arguments.Clear();
34061da546Spatrick m_environment.clear();
35061da546Spatrick m_uid = UINT32_MAX;
36061da546Spatrick m_gid = UINT32_MAX;
37061da546Spatrick m_arch.Clear();
38061da546Spatrick m_pid = LLDB_INVALID_PROCESS_ID;
39061da546Spatrick }
40061da546Spatrick
GetName() const41061da546Spatrick const char *ProcessInfo::GetName() const {
42061da546Spatrick return m_executable.GetFilename().GetCString();
43061da546Spatrick }
44061da546Spatrick
GetNameAsStringRef() const45061da546Spatrick llvm::StringRef ProcessInfo::GetNameAsStringRef() const {
46061da546Spatrick return m_executable.GetFilename().GetStringRef();
47061da546Spatrick }
48061da546Spatrick
Dump(Stream & s,Platform * platform) const49061da546Spatrick void ProcessInfo::Dump(Stream &s, Platform *platform) const {
50061da546Spatrick s << "Executable: " << GetName() << "\n";
51061da546Spatrick s << "Triple: ";
52061da546Spatrick m_arch.DumpTriple(s.AsRawOstream());
53061da546Spatrick s << "\n";
54061da546Spatrick
55061da546Spatrick s << "Arguments:\n";
56061da546Spatrick m_arguments.Dump(s);
57061da546Spatrick
58061da546Spatrick s.Format("Environment:\n{0}", m_environment);
59061da546Spatrick }
60061da546Spatrick
SetExecutableFile(const FileSpec & exe_file,bool add_exe_file_as_first_arg)61061da546Spatrick void ProcessInfo::SetExecutableFile(const FileSpec &exe_file,
62061da546Spatrick bool add_exe_file_as_first_arg) {
63061da546Spatrick if (exe_file) {
64061da546Spatrick m_executable = exe_file;
65061da546Spatrick if (add_exe_file_as_first_arg) {
66061da546Spatrick llvm::SmallString<128> filename;
67061da546Spatrick exe_file.GetPath(filename);
68061da546Spatrick if (!filename.empty())
69061da546Spatrick m_arguments.InsertArgumentAtIndex(0, filename);
70061da546Spatrick }
71061da546Spatrick } else {
72061da546Spatrick m_executable.Clear();
73061da546Spatrick }
74061da546Spatrick }
75061da546Spatrick
GetArg0() const76061da546Spatrick llvm::StringRef ProcessInfo::GetArg0() const { return m_arg0; }
77061da546Spatrick
SetArg0(llvm::StringRef arg)78dda28197Spatrick void ProcessInfo::SetArg0(llvm::StringRef arg) { m_arg0 = std::string(arg); }
79061da546Spatrick
SetArguments(char const ** argv,bool first_arg_is_executable)80061da546Spatrick void ProcessInfo::SetArguments(char const **argv,
81061da546Spatrick bool first_arg_is_executable) {
82061da546Spatrick m_arguments.SetArguments(argv);
83061da546Spatrick
84061da546Spatrick // Is the first argument the executable?
85061da546Spatrick if (first_arg_is_executable) {
86061da546Spatrick const char *first_arg = m_arguments.GetArgumentAtIndex(0);
87061da546Spatrick if (first_arg) {
88061da546Spatrick // Yes the first argument is an executable, set it as the executable in
89061da546Spatrick // the launch options. Don't resolve the file path as the path could be a
90061da546Spatrick // remote platform path
91061da546Spatrick m_executable.SetFile(first_arg, FileSpec::Style::native);
92061da546Spatrick }
93061da546Spatrick }
94061da546Spatrick }
95061da546Spatrick
SetArguments(const Args & args,bool first_arg_is_executable)96061da546Spatrick void ProcessInfo::SetArguments(const Args &args, bool first_arg_is_executable) {
97061da546Spatrick // Copy all arguments
98061da546Spatrick m_arguments = args;
99061da546Spatrick
100061da546Spatrick // Is the first argument the executable?
101061da546Spatrick if (first_arg_is_executable) {
102061da546Spatrick const char *first_arg = m_arguments.GetArgumentAtIndex(0);
103061da546Spatrick if (first_arg) {
104061da546Spatrick // Yes the first argument is an executable, set it as the executable in
105061da546Spatrick // the launch options. Don't resolve the file path as the path could be a
106061da546Spatrick // remote platform path
107061da546Spatrick m_executable.SetFile(first_arg, FileSpec::Style::native);
108061da546Spatrick }
109061da546Spatrick }
110061da546Spatrick }
111061da546Spatrick
Dump(Stream & s,UserIDResolver & resolver) const112061da546Spatrick void ProcessInstanceInfo::Dump(Stream &s, UserIDResolver &resolver) const {
113061da546Spatrick if (m_pid != LLDB_INVALID_PROCESS_ID)
114061da546Spatrick s.Printf(" pid = %" PRIu64 "\n", m_pid);
115061da546Spatrick
116061da546Spatrick if (m_parent_pid != LLDB_INVALID_PROCESS_ID)
117061da546Spatrick s.Printf(" parent = %" PRIu64 "\n", m_parent_pid);
118061da546Spatrick
119061da546Spatrick if (m_executable) {
120061da546Spatrick s.Printf(" name = %s\n", m_executable.GetFilename().GetCString());
121061da546Spatrick s.PutCString(" file = ");
122061da546Spatrick m_executable.Dump(s.AsRawOstream());
123061da546Spatrick s.EOL();
124061da546Spatrick }
125061da546Spatrick const uint32_t argc = m_arguments.GetArgumentCount();
126061da546Spatrick if (argc > 0) {
127061da546Spatrick for (uint32_t i = 0; i < argc; i++) {
128061da546Spatrick const char *arg = m_arguments.GetArgumentAtIndex(i);
129061da546Spatrick if (i < 10)
130061da546Spatrick s.Printf(" arg[%u] = %s\n", i, arg);
131061da546Spatrick else
132061da546Spatrick s.Printf("arg[%u] = %s\n", i, arg);
133061da546Spatrick }
134061da546Spatrick }
135061da546Spatrick
136061da546Spatrick s.Format("{0}", m_environment);
137061da546Spatrick
138061da546Spatrick if (m_arch.IsValid()) {
139061da546Spatrick s.Printf(" arch = ");
140061da546Spatrick m_arch.DumpTriple(s.AsRawOstream());
141061da546Spatrick s.EOL();
142061da546Spatrick }
143061da546Spatrick
144061da546Spatrick if (UserIDIsValid()) {
145061da546Spatrick s.Format(" uid = {0,-5} ({1})\n", GetUserID(),
146*f6aab3d8Srobert resolver.GetUserName(GetUserID()).value_or(""));
147061da546Spatrick }
148061da546Spatrick if (GroupIDIsValid()) {
149061da546Spatrick s.Format(" gid = {0,-5} ({1})\n", GetGroupID(),
150*f6aab3d8Srobert resolver.GetGroupName(GetGroupID()).value_or(""));
151061da546Spatrick }
152061da546Spatrick if (EffectiveUserIDIsValid()) {
153061da546Spatrick s.Format(" euid = {0,-5} ({1})\n", GetEffectiveUserID(),
154*f6aab3d8Srobert resolver.GetUserName(GetEffectiveUserID()).value_or(""));
155061da546Spatrick }
156061da546Spatrick if (EffectiveGroupIDIsValid()) {
157061da546Spatrick s.Format(" egid = {0,-5} ({1})\n", GetEffectiveGroupID(),
158*f6aab3d8Srobert resolver.GetGroupName(GetEffectiveGroupID()).value_or(""));
159061da546Spatrick }
160061da546Spatrick }
161061da546Spatrick
DumpTableHeader(Stream & s,bool show_args,bool verbose)162061da546Spatrick void ProcessInstanceInfo::DumpTableHeader(Stream &s, bool show_args,
163061da546Spatrick bool verbose) {
164061da546Spatrick const char *label;
165061da546Spatrick if (show_args || verbose)
166061da546Spatrick label = "ARGUMENTS";
167061da546Spatrick else
168061da546Spatrick label = "NAME";
169061da546Spatrick
170061da546Spatrick if (verbose) {
171061da546Spatrick s.Printf("PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE "
172061da546Spatrick " %s\n",
173061da546Spatrick label);
174061da546Spatrick s.PutCString(
175061da546Spatrick "====== ====== ========== ========== ========== ========== "
176061da546Spatrick "============================== ============================\n");
177061da546Spatrick } else {
178061da546Spatrick s.Printf("PID PARENT USER TRIPLE %s\n",
179061da546Spatrick label);
180061da546Spatrick s.PutCString("====== ====== ========== ============================== "
181061da546Spatrick "============================\n");
182061da546Spatrick }
183061da546Spatrick }
184061da546Spatrick
DumpAsTableRow(Stream & s,UserIDResolver & resolver,bool show_args,bool verbose) const185061da546Spatrick void ProcessInstanceInfo::DumpAsTableRow(Stream &s, UserIDResolver &resolver,
186061da546Spatrick bool show_args, bool verbose) const {
187061da546Spatrick if (m_pid != LLDB_INVALID_PROCESS_ID) {
188061da546Spatrick s.Printf("%-6" PRIu64 " %-6" PRIu64 " ", m_pid, m_parent_pid);
189061da546Spatrick
190061da546Spatrick StreamString arch_strm;
191061da546Spatrick if (m_arch.IsValid())
192061da546Spatrick m_arch.DumpTriple(arch_strm.AsRawOstream());
193061da546Spatrick
194061da546Spatrick auto print = [&](bool (ProcessInstanceInfo::*isValid)() const,
195061da546Spatrick uint32_t (ProcessInstanceInfo::*getID)() const,
196*f6aab3d8Srobert std::optional<llvm::StringRef> (UserIDResolver::*getName)(
197061da546Spatrick UserIDResolver::id_t id)) {
198061da546Spatrick const char *format = "{0,-10} ";
199061da546Spatrick if (!(this->*isValid)()) {
200061da546Spatrick s.Format(format, "");
201061da546Spatrick return;
202061da546Spatrick }
203061da546Spatrick uint32_t id = (this->*getID)();
204061da546Spatrick if (auto name = (resolver.*getName)(id))
205061da546Spatrick s.Format(format, *name);
206061da546Spatrick else
207061da546Spatrick s.Format(format, id);
208061da546Spatrick };
209061da546Spatrick if (verbose) {
210061da546Spatrick print(&ProcessInstanceInfo::UserIDIsValid,
211061da546Spatrick &ProcessInstanceInfo::GetUserID, &UserIDResolver::GetUserName);
212061da546Spatrick print(&ProcessInstanceInfo::GroupIDIsValid,
213061da546Spatrick &ProcessInstanceInfo::GetGroupID, &UserIDResolver::GetGroupName);
214061da546Spatrick print(&ProcessInstanceInfo::EffectiveUserIDIsValid,
215061da546Spatrick &ProcessInstanceInfo::GetEffectiveUserID,
216061da546Spatrick &UserIDResolver::GetUserName);
217061da546Spatrick print(&ProcessInstanceInfo::EffectiveGroupIDIsValid,
218061da546Spatrick &ProcessInstanceInfo::GetEffectiveGroupID,
219061da546Spatrick &UserIDResolver::GetGroupName);
220061da546Spatrick
221061da546Spatrick s.Printf("%-30s ", arch_strm.GetData());
222061da546Spatrick } else {
223061da546Spatrick print(&ProcessInstanceInfo::EffectiveUserIDIsValid,
224061da546Spatrick &ProcessInstanceInfo::GetEffectiveUserID,
225061da546Spatrick &UserIDResolver::GetUserName);
226061da546Spatrick s.Printf("%-30s ", arch_strm.GetData());
227061da546Spatrick }
228061da546Spatrick
229061da546Spatrick if (verbose || show_args) {
230061da546Spatrick s.PutCString(m_arg0);
231061da546Spatrick const uint32_t argc = m_arguments.GetArgumentCount();
232061da546Spatrick for (uint32_t i = 0; i < argc; i++) {
233061da546Spatrick s.PutChar(' ');
234061da546Spatrick s.PutCString(m_arguments.GetArgumentAtIndex(i));
235061da546Spatrick }
236061da546Spatrick } else {
237061da546Spatrick s.PutCString(GetName());
238061da546Spatrick }
239061da546Spatrick
240061da546Spatrick s.EOL();
241061da546Spatrick }
242061da546Spatrick }
243061da546Spatrick
ArchitectureMatches(const ArchSpec & arch_spec) const244061da546Spatrick bool ProcessInstanceInfoMatch::ArchitectureMatches(
245061da546Spatrick const ArchSpec &arch_spec) const {
246061da546Spatrick return !m_match_info.GetArchitecture().IsValid() ||
247061da546Spatrick m_match_info.GetArchitecture().IsCompatibleMatch(arch_spec);
248061da546Spatrick }
249061da546Spatrick
NameMatches(const char * process_name) const250061da546Spatrick bool ProcessInstanceInfoMatch::NameMatches(const char *process_name) const {
251061da546Spatrick if (m_name_match_type == NameMatch::Ignore)
252061da546Spatrick return true;
253061da546Spatrick const char *match_name = m_match_info.GetName();
254061da546Spatrick if (!match_name)
255061da546Spatrick return true;
256061da546Spatrick
257061da546Spatrick return lldb_private::NameMatches(process_name, m_name_match_type, match_name);
258061da546Spatrick }
259061da546Spatrick
ProcessIDsMatch(const ProcessInstanceInfo & proc_info) const260061da546Spatrick bool ProcessInstanceInfoMatch::ProcessIDsMatch(
261061da546Spatrick const ProcessInstanceInfo &proc_info) const {
262061da546Spatrick if (m_match_info.ProcessIDIsValid() &&
263061da546Spatrick m_match_info.GetProcessID() != proc_info.GetProcessID())
264061da546Spatrick return false;
265061da546Spatrick
266061da546Spatrick if (m_match_info.ParentProcessIDIsValid() &&
267061da546Spatrick m_match_info.GetParentProcessID() != proc_info.GetParentProcessID())
268061da546Spatrick return false;
269061da546Spatrick return true;
270061da546Spatrick }
271061da546Spatrick
UserIDsMatch(const ProcessInstanceInfo & proc_info) const272061da546Spatrick bool ProcessInstanceInfoMatch::UserIDsMatch(
273061da546Spatrick const ProcessInstanceInfo &proc_info) const {
274061da546Spatrick if (m_match_info.UserIDIsValid() &&
275061da546Spatrick m_match_info.GetUserID() != proc_info.GetUserID())
276061da546Spatrick return false;
277061da546Spatrick
278061da546Spatrick if (m_match_info.GroupIDIsValid() &&
279061da546Spatrick m_match_info.GetGroupID() != proc_info.GetGroupID())
280061da546Spatrick return false;
281061da546Spatrick
282061da546Spatrick if (m_match_info.EffectiveUserIDIsValid() &&
283061da546Spatrick m_match_info.GetEffectiveUserID() != proc_info.GetEffectiveUserID())
284061da546Spatrick return false;
285061da546Spatrick
286061da546Spatrick if (m_match_info.EffectiveGroupIDIsValid() &&
287061da546Spatrick m_match_info.GetEffectiveGroupID() != proc_info.GetEffectiveGroupID())
288061da546Spatrick return false;
289061da546Spatrick return true;
290061da546Spatrick }
Matches(const ProcessInstanceInfo & proc_info) const291061da546Spatrick bool ProcessInstanceInfoMatch::Matches(
292061da546Spatrick const ProcessInstanceInfo &proc_info) const {
293061da546Spatrick return ArchitectureMatches(proc_info.GetArchitecture()) &&
294061da546Spatrick ProcessIDsMatch(proc_info) && UserIDsMatch(proc_info) &&
295061da546Spatrick NameMatches(proc_info.GetName());
296061da546Spatrick }
297061da546Spatrick
MatchAllProcesses() const298061da546Spatrick bool ProcessInstanceInfoMatch::MatchAllProcesses() const {
299061da546Spatrick if (m_name_match_type != NameMatch::Ignore)
300061da546Spatrick return false;
301061da546Spatrick
302061da546Spatrick if (m_match_info.ProcessIDIsValid())
303061da546Spatrick return false;
304061da546Spatrick
305061da546Spatrick if (m_match_info.ParentProcessIDIsValid())
306061da546Spatrick return false;
307061da546Spatrick
308061da546Spatrick if (m_match_info.UserIDIsValid())
309061da546Spatrick return false;
310061da546Spatrick
311061da546Spatrick if (m_match_info.GroupIDIsValid())
312061da546Spatrick return false;
313061da546Spatrick
314061da546Spatrick if (m_match_info.EffectiveUserIDIsValid())
315061da546Spatrick return false;
316061da546Spatrick
317061da546Spatrick if (m_match_info.EffectiveGroupIDIsValid())
318061da546Spatrick return false;
319061da546Spatrick
320061da546Spatrick if (m_match_info.GetArchitecture().IsValid())
321061da546Spatrick return false;
322061da546Spatrick
323061da546Spatrick if (m_match_all_users)
324061da546Spatrick return false;
325061da546Spatrick
326061da546Spatrick return true;
327061da546Spatrick }
328061da546Spatrick
Clear()329061da546Spatrick void ProcessInstanceInfoMatch::Clear() {
330061da546Spatrick m_match_info.Clear();
331061da546Spatrick m_name_match_type = NameMatch::Ignore;
332061da546Spatrick m_match_all_users = false;
333061da546Spatrick }
334