343 lines · cpp
1//===-- ProcessInfo.cpp ---------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Utility/ProcessInfo.h"10 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"17 18#include <climits>19#include <optional>20 21using namespace lldb;22using namespace lldb_private;23 24ProcessInfo::ProcessInfo()25 : m_executable(), m_arguments(), m_environment(), m_arch(), m_listener_sp(),26 m_hijack_listener_sp(), m_shadow_listener_sp() {}27 28ProcessInfo::ProcessInfo(const char *name, const ArchSpec &arch,29 lldb::pid_t pid)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() {}33 34void ProcessInfo::Clear() {35 m_executable.Clear();36 m_arguments.Clear();37 m_environment.clear();38 m_uid = UINT32_MAX;39 m_gid = UINT32_MAX;40 m_arch.Clear();41 m_pid = LLDB_INVALID_PROCESS_ID;42 m_scripted_metadata_sp.reset();43}44 45const char *ProcessInfo::GetName() const {46 return m_executable.GetFilename().GetCString();47}48 49llvm::StringRef ProcessInfo::GetNameAsStringRef() const {50 return m_executable.GetFilename().GetStringRef();51}52 53void ProcessInfo::Dump(Stream &s, Platform *platform) const {54 s << "Executable: " << GetName() << "\n";55 s << "Triple: ";56 m_arch.DumpTriple(s.AsRawOstream());57 s << "\n";58 59 s << "Arguments:\n";60 m_arguments.Dump(s);61 62 s.Format("Environment:\n{0}", m_environment);63}64 65void ProcessInfo::SetExecutableFile(const FileSpec &exe_file,66 bool add_exe_file_as_first_arg) {67 if (exe_file) {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);74 }75 } else {76 m_executable.Clear();77 }78}79 80llvm::StringRef ProcessInfo::GetArg0() const { return m_arg0; }81 82void ProcessInfo::SetArg0(llvm::StringRef arg) { m_arg0 = std::string(arg); }83 84void ProcessInfo::SetArguments(char const **argv,85 bool first_arg_is_executable) {86 m_arguments.SetArguments(argv);87 88 // Is the first argument the executable?89 if (first_arg_is_executable) {90 const char *first_arg = m_arguments.GetArgumentAtIndex(0);91 if (first_arg) {92 // Yes the first argument is an executable, set it as the executable in93 // the launch options. Don't resolve the file path as the path could be a94 // remote platform path95 m_executable.SetFile(first_arg, FileSpec::Style::native);96 }97 }98}99 100void ProcessInfo::SetArguments(const Args &args, bool first_arg_is_executable) {101 // Copy all arguments102 m_arguments = args;103 104 // Is the first argument the executable?105 if (first_arg_is_executable) {106 const char *first_arg = m_arguments.GetArgumentAtIndex(0);107 if (first_arg) {108 // Yes the first argument is an executable, set it as the executable in109 // the launch options. Don't resolve the file path as the path could be a110 // remote platform path111 m_executable.SetFile(first_arg, FileSpec::Style::native);112 }113 }114}115 116bool ProcessInfo::IsScriptedProcess() const {117 return m_scripted_metadata_sp && *m_scripted_metadata_sp;118}119 120void ProcessInstanceInfo::Dump(Stream &s, UserIDResolver &resolver) const {121 if (m_pid != LLDB_INVALID_PROCESS_ID)122 s.Printf(" pid = %" PRIu64 "\n", m_pid);123 124 if (ParentProcessIDIsValid())125 s.Printf(" parent = %" PRIu64 "\n", GetParentProcessID());126 127 if (m_executable) {128 s.Printf(" name = %s\n", m_executable.GetFilename().GetCString());129 s.PutCString(" file = ");130 m_executable.Dump(s.AsRawOstream());131 s.EOL();132 }133 const uint32_t argc = m_arguments.GetArgumentCount();134 if (argc > 0) {135 for (uint32_t i = 0; i < argc; i++) {136 const char *arg = m_arguments.GetArgumentAtIndex(i);137 if (i < 10)138 s.Printf(" arg[%u] = %s\n", i, arg);139 else140 s.Printf("arg[%u] = %s\n", i, arg);141 }142 }143 144 s.Format("{0}", m_environment);145 146 if (m_arch.IsValid()) {147 s.Printf(" arch = ");148 m_arch.DumpTriple(s.AsRawOstream());149 s.EOL();150 }151 152 if (UserIDIsValid()) {153 s.Format(" uid = {0,-5} ({1})\n", GetUserID(),154 resolver.GetUserName(GetUserID()).value_or(""));155 }156 if (GroupIDIsValid()) {157 s.Format(" gid = {0,-5} ({1})\n", GetGroupID(),158 resolver.GetGroupName(GetGroupID()).value_or(""));159 }160 if (EffectiveUserIDIsValid()) {161 s.Format(" euid = {0,-5} ({1})\n", GetEffectiveUserID(),162 resolver.GetUserName(GetEffectiveUserID()).value_or(""));163 }164 if (EffectiveGroupIDIsValid()) {165 s.Format(" egid = {0,-5} ({1})\n", GetEffectiveGroupID(),166 resolver.GetGroupName(GetEffectiveGroupID()).value_or(""));167 }168}169 170void ProcessInstanceInfo::DumpTableHeader(Stream &s, bool show_args,171 bool verbose) {172 const char *label;173 if (show_args || verbose)174 label = "ARGUMENTS";175 else176 label = "NAME";177 178 if (verbose) {179 s.Printf("PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE "180 " %s\n",181 label);182 s.PutCString(183 "====== ====== ========== ========== ========== ========== "184 "============================== ============================\n");185 } else {186 s.Printf("PID PARENT USER TRIPLE %s\n",187 label);188 s.PutCString("====== ====== ========== ============================== "189 "============================\n");190 }191}192 193void 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);198 199 StreamString arch_strm;200 if (m_arch.IsValid())201 m_arch.DumpTriple(arch_strm.AsRawOstream());202 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, "");210 return;211 }212 uint32_t id = (this->*getID)();213 if (auto name = (resolver.*getName)(id))214 s.Format(format, *name);215 else216 s.Format(format, id);217 };218 if (verbose) {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);229 230 s.Printf("%-30s ", arch_strm.GetData());231 } else {232 print(&ProcessInstanceInfo::EffectiveUserIDIsValid,233 &ProcessInstanceInfo::GetEffectiveUserID,234 &UserIDResolver::GetUserName);235 s.Printf("%-30s ", arch_strm.GetData());236 }237 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++) {242 s.PutChar(' ');243 s.PutCString(m_arguments.GetArgumentAtIndex(i));244 }245 } else {246 s.PutCString(GetName());247 }248 249 s.EOL();250 }251}252 253bool ProcessInstanceInfoMatch::ArchitectureMatches(254 const ArchSpec &arch_spec) const {255 return !m_match_info.GetArchitecture().IsValid() ||256 m_match_info.GetArchitecture().IsCompatibleMatch(arch_spec);257}258 259bool ProcessInstanceInfoMatch::NameMatches(const char *process_name) const {260 if (m_name_match_type == NameMatch::Ignore)261 return true;262 const char *match_name = m_match_info.GetName();263 if (!match_name)264 return true;265 266 return lldb_private::NameMatches(process_name, m_name_match_type, match_name);267}268 269bool ProcessInstanceInfoMatch::ProcessIDsMatch(270 const ProcessInstanceInfo &proc_info) const {271 if (m_match_info.ProcessIDIsValid() &&272 m_match_info.GetProcessID() != proc_info.GetProcessID())273 return false;274 275 if (m_match_info.ParentProcessIDIsValid() &&276 m_match_info.GetParentProcessID() != proc_info.GetParentProcessID())277 return false;278 return true;279}280 281bool ProcessInstanceInfoMatch::UserIDsMatch(282 const ProcessInstanceInfo &proc_info) const {283 if (m_match_info.UserIDIsValid() &&284 m_match_info.GetUserID() != proc_info.GetUserID())285 return false;286 287 if (m_match_info.GroupIDIsValid() &&288 m_match_info.GetGroupID() != proc_info.GetGroupID())289 return false;290 291 if (m_match_info.EffectiveUserIDIsValid() &&292 m_match_info.GetEffectiveUserID() != proc_info.GetEffectiveUserID())293 return false;294 295 if (m_match_info.EffectiveGroupIDIsValid() &&296 m_match_info.GetEffectiveGroupID() != proc_info.GetEffectiveGroupID())297 return false;298 return true;299}300bool 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());305}306 307bool ProcessInstanceInfoMatch::MatchAllProcesses() const {308 if (m_name_match_type != NameMatch::Ignore)309 return false;310 311 if (m_match_info.ProcessIDIsValid())312 return false;313 314 if (m_match_info.ParentProcessIDIsValid())315 return false;316 317 if (m_match_info.UserIDIsValid())318 return false;319 320 if (m_match_info.GroupIDIsValid())321 return false;322 323 if (m_match_info.EffectiveUserIDIsValid())324 return false;325 326 if (m_match_info.EffectiveGroupIDIsValid())327 return false;328 329 if (m_match_info.GetArchitecture().IsValid())330 return false;331 332 if (m_match_all_users)333 return false;334 335 return true;336}337 338void ProcessInstanceInfoMatch::Clear() {339 m_match_info.Clear();340 m_name_match_type = NameMatch::Ignore;341 m_match_all_users = false;342}343