180814287SRaphael Isemann //===-- ProcessInfo.cpp ---------------------------------------------------===// 2805e7106SZachary Turner // 3805e7106SZachary Turner // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4805e7106SZachary Turner // See https://llvm.org/LICENSE.txt for license information. 5805e7106SZachary Turner // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6805e7106SZachary Turner // 7805e7106SZachary Turner //===----------------------------------------------------------------------===// 8805e7106SZachary Turner 9805e7106SZachary Turner #include "lldb/Utility/ProcessInfo.h" 10805e7106SZachary Turner 11805e7106SZachary Turner #include "lldb/Utility/ArchSpec.h" 12*bb894b97SJonas Devlieghere #include "lldb/Utility/ReproducerProvider.h" 13805e7106SZachary Turner #include "lldb/Utility/Stream.h" 14805e7106SZachary Turner #include "lldb/Utility/StreamString.h" 15805e7106SZachary Turner #include "lldb/Utility/UserIDResolver.h" 16805e7106SZachary Turner #include "llvm/ADT/SmallString.h" 17805e7106SZachary Turner 18805e7106SZachary Turner #include <climits> 19805e7106SZachary Turner 20805e7106SZachary Turner using namespace lldb; 21805e7106SZachary Turner using namespace lldb_private; 222451cbf0SJonas Devlieghere using namespace lldb_private::repro; 23805e7106SZachary Turner 24805e7106SZachary Turner ProcessInfo::ProcessInfo() 25805e7106SZachary Turner : m_executable(), m_arguments(), m_environment(), m_uid(UINT32_MAX), 26805e7106SZachary Turner m_gid(UINT32_MAX), m_arch(), m_pid(LLDB_INVALID_PROCESS_ID) {} 27805e7106SZachary Turner 28805e7106SZachary Turner ProcessInfo::ProcessInfo(const char *name, const ArchSpec &arch, 29805e7106SZachary Turner lldb::pid_t pid) 30805e7106SZachary Turner : m_executable(name), m_arguments(), m_environment(), m_uid(UINT32_MAX), 31805e7106SZachary Turner m_gid(UINT32_MAX), m_arch(arch), m_pid(pid) {} 32805e7106SZachary Turner 33805e7106SZachary Turner void ProcessInfo::Clear() { 34805e7106SZachary Turner m_executable.Clear(); 35805e7106SZachary Turner m_arguments.Clear(); 36805e7106SZachary Turner m_environment.clear(); 37805e7106SZachary Turner m_uid = UINT32_MAX; 38805e7106SZachary Turner m_gid = UINT32_MAX; 39805e7106SZachary Turner m_arch.Clear(); 40805e7106SZachary Turner m_pid = LLDB_INVALID_PROCESS_ID; 41805e7106SZachary Turner } 42805e7106SZachary Turner 43805e7106SZachary Turner const char *ProcessInfo::GetName() const { 44805e7106SZachary Turner return m_executable.GetFilename().GetCString(); 45805e7106SZachary Turner } 46805e7106SZachary Turner 4772ca5f36SRaphael Isemann llvm::StringRef ProcessInfo::GetNameAsStringRef() const { 4872ca5f36SRaphael Isemann return m_executable.GetFilename().GetStringRef(); 49805e7106SZachary Turner } 50805e7106SZachary Turner 51805e7106SZachary Turner void ProcessInfo::Dump(Stream &s, Platform *platform) const { 52805e7106SZachary Turner s << "Executable: " << GetName() << "\n"; 53805e7106SZachary Turner s << "Triple: "; 542f1e7b3dSRaphael Isemann m_arch.DumpTriple(s.AsRawOstream()); 55805e7106SZachary Turner s << "\n"; 56805e7106SZachary Turner 57805e7106SZachary Turner s << "Arguments:\n"; 58805e7106SZachary Turner m_arguments.Dump(s); 59805e7106SZachary Turner 60805e7106SZachary Turner s.Format("Environment:\n{0}", m_environment); 61805e7106SZachary Turner } 62805e7106SZachary Turner 63805e7106SZachary Turner void ProcessInfo::SetExecutableFile(const FileSpec &exe_file, 64805e7106SZachary Turner bool add_exe_file_as_first_arg) { 65805e7106SZachary Turner if (exe_file) { 66805e7106SZachary Turner m_executable = exe_file; 67805e7106SZachary Turner if (add_exe_file_as_first_arg) { 68805e7106SZachary Turner llvm::SmallString<128> filename; 69805e7106SZachary Turner exe_file.GetPath(filename); 70805e7106SZachary Turner if (!filename.empty()) 71805e7106SZachary Turner m_arguments.InsertArgumentAtIndex(0, filename); 72805e7106SZachary Turner } 73805e7106SZachary Turner } else { 74805e7106SZachary Turner m_executable.Clear(); 75805e7106SZachary Turner } 76805e7106SZachary Turner } 77805e7106SZachary Turner 78805e7106SZachary Turner llvm::StringRef ProcessInfo::GetArg0() const { return m_arg0; } 79805e7106SZachary Turner 80adcd0268SBenjamin Kramer void ProcessInfo::SetArg0(llvm::StringRef arg) { m_arg0 = std::string(arg); } 81805e7106SZachary Turner 82805e7106SZachary Turner void ProcessInfo::SetArguments(char const **argv, 83805e7106SZachary Turner bool first_arg_is_executable) { 84805e7106SZachary Turner m_arguments.SetArguments(argv); 85805e7106SZachary Turner 86805e7106SZachary Turner // Is the first argument the executable? 87805e7106SZachary Turner if (first_arg_is_executable) { 88805e7106SZachary Turner const char *first_arg = m_arguments.GetArgumentAtIndex(0); 89805e7106SZachary Turner if (first_arg) { 90805e7106SZachary Turner // Yes the first argument is an executable, set it as the executable in 91805e7106SZachary Turner // the launch options. Don't resolve the file path as the path could be a 92805e7106SZachary Turner // remote platform path 93805e7106SZachary Turner m_executable.SetFile(first_arg, FileSpec::Style::native); 94805e7106SZachary Turner } 95805e7106SZachary Turner } 96805e7106SZachary Turner } 97805e7106SZachary Turner 98805e7106SZachary Turner void ProcessInfo::SetArguments(const Args &args, bool first_arg_is_executable) { 99805e7106SZachary Turner // Copy all arguments 100805e7106SZachary Turner m_arguments = args; 101805e7106SZachary Turner 102805e7106SZachary Turner // Is the first argument the executable? 103805e7106SZachary Turner if (first_arg_is_executable) { 104805e7106SZachary Turner const char *first_arg = m_arguments.GetArgumentAtIndex(0); 105805e7106SZachary Turner if (first_arg) { 106805e7106SZachary Turner // Yes the first argument is an executable, set it as the executable in 107805e7106SZachary Turner // the launch options. Don't resolve the file path as the path could be a 108805e7106SZachary Turner // remote platform path 109805e7106SZachary Turner m_executable.SetFile(first_arg, FileSpec::Style::native); 110805e7106SZachary Turner } 111805e7106SZachary Turner } 112805e7106SZachary Turner } 113805e7106SZachary Turner 114805e7106SZachary Turner void ProcessInstanceInfo::Dump(Stream &s, UserIDResolver &resolver) const { 115805e7106SZachary Turner if (m_pid != LLDB_INVALID_PROCESS_ID) 116805e7106SZachary Turner s.Printf(" pid = %" PRIu64 "\n", m_pid); 117805e7106SZachary Turner 118805e7106SZachary Turner if (m_parent_pid != LLDB_INVALID_PROCESS_ID) 119805e7106SZachary Turner s.Printf(" parent = %" PRIu64 "\n", m_parent_pid); 120805e7106SZachary Turner 121805e7106SZachary Turner if (m_executable) { 122805e7106SZachary Turner s.Printf(" name = %s\n", m_executable.GetFilename().GetCString()); 123805e7106SZachary Turner s.PutCString(" file = "); 1244dac97ebSRaphael Isemann m_executable.Dump(s.AsRawOstream()); 125805e7106SZachary Turner s.EOL(); 126805e7106SZachary Turner } 127805e7106SZachary Turner const uint32_t argc = m_arguments.GetArgumentCount(); 128805e7106SZachary Turner if (argc > 0) { 129805e7106SZachary Turner for (uint32_t i = 0; i < argc; i++) { 130805e7106SZachary Turner const char *arg = m_arguments.GetArgumentAtIndex(i); 131805e7106SZachary Turner if (i < 10) 132805e7106SZachary Turner s.Printf(" arg[%u] = %s\n", i, arg); 133805e7106SZachary Turner else 134805e7106SZachary Turner s.Printf("arg[%u] = %s\n", i, arg); 135805e7106SZachary Turner } 136805e7106SZachary Turner } 137805e7106SZachary Turner 138805e7106SZachary Turner s.Format("{0}", m_environment); 139805e7106SZachary Turner 140805e7106SZachary Turner if (m_arch.IsValid()) { 141805e7106SZachary Turner s.Printf(" arch = "); 1422f1e7b3dSRaphael Isemann m_arch.DumpTriple(s.AsRawOstream()); 143805e7106SZachary Turner s.EOL(); 144805e7106SZachary Turner } 145805e7106SZachary Turner 146805e7106SZachary Turner if (UserIDIsValid()) { 147805e7106SZachary Turner s.Format(" uid = {0,-5} ({1})\n", GetUserID(), 148805e7106SZachary Turner resolver.GetUserName(GetUserID()).getValueOr("")); 149805e7106SZachary Turner } 150805e7106SZachary Turner if (GroupIDIsValid()) { 151805e7106SZachary Turner s.Format(" gid = {0,-5} ({1})\n", GetGroupID(), 152805e7106SZachary Turner resolver.GetGroupName(GetGroupID()).getValueOr("")); 153805e7106SZachary Turner } 154805e7106SZachary Turner if (EffectiveUserIDIsValid()) { 155805e7106SZachary Turner s.Format(" euid = {0,-5} ({1})\n", GetEffectiveUserID(), 156805e7106SZachary Turner resolver.GetUserName(GetEffectiveUserID()).getValueOr("")); 157805e7106SZachary Turner } 158805e7106SZachary Turner if (EffectiveGroupIDIsValid()) { 159805e7106SZachary Turner s.Format(" egid = {0,-5} ({1})\n", GetEffectiveGroupID(), 160805e7106SZachary Turner resolver.GetGroupName(GetEffectiveGroupID()).getValueOr("")); 161805e7106SZachary Turner } 162805e7106SZachary Turner } 163805e7106SZachary Turner 164805e7106SZachary Turner void ProcessInstanceInfo::DumpTableHeader(Stream &s, bool show_args, 165805e7106SZachary Turner bool verbose) { 166805e7106SZachary Turner const char *label; 167805e7106SZachary Turner if (show_args || verbose) 168805e7106SZachary Turner label = "ARGUMENTS"; 169805e7106SZachary Turner else 170805e7106SZachary Turner label = "NAME"; 171805e7106SZachary Turner 172805e7106SZachary Turner if (verbose) { 173805e7106SZachary Turner s.Printf("PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE " 174805e7106SZachary Turner " %s\n", 175805e7106SZachary Turner label); 176e0a398bfSWalter Erquinigo s.PutCString( 177e0a398bfSWalter Erquinigo "====== ====== ========== ========== ========== ========== " 178e0a398bfSWalter Erquinigo "============================== ============================\n"); 179805e7106SZachary Turner } else { 180e0a398bfSWalter Erquinigo s.Printf("PID PARENT USER TRIPLE %s\n", 181e0a398bfSWalter Erquinigo label); 182e0a398bfSWalter Erquinigo s.PutCString("====== ====== ========== ============================== " 183805e7106SZachary Turner "============================\n"); 184805e7106SZachary Turner } 185805e7106SZachary Turner } 186805e7106SZachary Turner 187805e7106SZachary Turner void ProcessInstanceInfo::DumpAsTableRow(Stream &s, UserIDResolver &resolver, 188805e7106SZachary Turner bool show_args, bool verbose) const { 189805e7106SZachary Turner if (m_pid != LLDB_INVALID_PROCESS_ID) { 190805e7106SZachary Turner s.Printf("%-6" PRIu64 " %-6" PRIu64 " ", m_pid, m_parent_pid); 191805e7106SZachary Turner 192805e7106SZachary Turner StreamString arch_strm; 193805e7106SZachary Turner if (m_arch.IsValid()) 1942f1e7b3dSRaphael Isemann m_arch.DumpTriple(arch_strm.AsRawOstream()); 195805e7106SZachary Turner 196602f29fdSPavel Labath auto print = [&](bool (ProcessInstanceInfo::*isValid)() const, 197602f29fdSPavel Labath uint32_t (ProcessInstanceInfo::*getID)() const, 198602f29fdSPavel Labath llvm::Optional<llvm::StringRef> (UserIDResolver::*getName)( 199805e7106SZachary Turner UserIDResolver::id_t id)) { 200602f29fdSPavel Labath const char *format = "{0,-10} "; 201602f29fdSPavel Labath if (!(this->*isValid)()) { 202602f29fdSPavel Labath s.Format(format, ""); 203602f29fdSPavel Labath return; 204602f29fdSPavel Labath } 205602f29fdSPavel Labath uint32_t id = (this->*getID)(); 206602f29fdSPavel Labath if (auto name = (resolver.*getName)(id)) 207602f29fdSPavel Labath s.Format(format, *name); 208805e7106SZachary Turner else 209602f29fdSPavel Labath s.Format(format, id); 210805e7106SZachary Turner }; 211805e7106SZachary Turner if (verbose) { 212602f29fdSPavel Labath print(&ProcessInstanceInfo::UserIDIsValid, 213602f29fdSPavel Labath &ProcessInstanceInfo::GetUserID, &UserIDResolver::GetUserName); 214602f29fdSPavel Labath print(&ProcessInstanceInfo::GroupIDIsValid, 215602f29fdSPavel Labath &ProcessInstanceInfo::GetGroupID, &UserIDResolver::GetGroupName); 216602f29fdSPavel Labath print(&ProcessInstanceInfo::EffectiveUserIDIsValid, 217602f29fdSPavel Labath &ProcessInstanceInfo::GetEffectiveUserID, 218602f29fdSPavel Labath &UserIDResolver::GetUserName); 219602f29fdSPavel Labath print(&ProcessInstanceInfo::EffectiveGroupIDIsValid, 220602f29fdSPavel Labath &ProcessInstanceInfo::GetEffectiveGroupID, 221602f29fdSPavel Labath &UserIDResolver::GetGroupName); 222805e7106SZachary Turner 223e0a398bfSWalter Erquinigo s.Printf("%-30s ", arch_strm.GetData()); 224805e7106SZachary Turner } else { 225602f29fdSPavel Labath print(&ProcessInstanceInfo::EffectiveUserIDIsValid, 226602f29fdSPavel Labath &ProcessInstanceInfo::GetEffectiveUserID, 227602f29fdSPavel Labath &UserIDResolver::GetUserName); 228e0a398bfSWalter Erquinigo s.Printf("%-30s ", arch_strm.GetData()); 229805e7106SZachary Turner } 230805e7106SZachary Turner 231805e7106SZachary Turner if (verbose || show_args) { 23248a50ee0SWalter Erquinigo s.PutCString(m_arg0); 233805e7106SZachary Turner const uint32_t argc = m_arguments.GetArgumentCount(); 234805e7106SZachary Turner for (uint32_t i = 0; i < argc; i++) { 235805e7106SZachary Turner s.PutChar(' '); 236805e7106SZachary Turner s.PutCString(m_arguments.GetArgumentAtIndex(i)); 237805e7106SZachary Turner } 238805e7106SZachary Turner } else { 239805e7106SZachary Turner s.PutCString(GetName()); 240805e7106SZachary Turner } 241805e7106SZachary Turner 242805e7106SZachary Turner s.EOL(); 243805e7106SZachary Turner } 244805e7106SZachary Turner } 245805e7106SZachary Turner 246a8b18baaSPavel Labath bool ProcessInstanceInfoMatch::ArchitectureMatches( 247a8b18baaSPavel Labath const ArchSpec &arch_spec) const { 248a8b18baaSPavel Labath return !m_match_info.GetArchitecture().IsValid() || 249a8b18baaSPavel Labath m_match_info.GetArchitecture().IsCompatibleMatch(arch_spec); 250a8b18baaSPavel Labath } 251a8b18baaSPavel Labath 252805e7106SZachary Turner bool ProcessInstanceInfoMatch::NameMatches(const char *process_name) const { 253a8b18baaSPavel Labath if (m_name_match_type == NameMatch::Ignore) 254805e7106SZachary Turner return true; 255805e7106SZachary Turner const char *match_name = m_match_info.GetName(); 256805e7106SZachary Turner if (!match_name) 257805e7106SZachary Turner return true; 258805e7106SZachary Turner 259805e7106SZachary Turner return lldb_private::NameMatches(process_name, m_name_match_type, match_name); 260805e7106SZachary Turner } 261805e7106SZachary Turner 262a8b18baaSPavel Labath bool ProcessInstanceInfoMatch::ProcessIDsMatch( 263805e7106SZachary Turner const ProcessInstanceInfo &proc_info) const { 264805e7106SZachary Turner if (m_match_info.ProcessIDIsValid() && 265805e7106SZachary Turner m_match_info.GetProcessID() != proc_info.GetProcessID()) 266805e7106SZachary Turner return false; 267805e7106SZachary Turner 268805e7106SZachary Turner if (m_match_info.ParentProcessIDIsValid() && 269805e7106SZachary Turner m_match_info.GetParentProcessID() != proc_info.GetParentProcessID()) 270805e7106SZachary Turner return false; 271a8b18baaSPavel Labath return true; 272a8b18baaSPavel Labath } 273805e7106SZachary Turner 274a8b18baaSPavel Labath bool ProcessInstanceInfoMatch::UserIDsMatch( 275a8b18baaSPavel Labath const ProcessInstanceInfo &proc_info) const { 276805e7106SZachary Turner if (m_match_info.UserIDIsValid() && 277805e7106SZachary Turner m_match_info.GetUserID() != proc_info.GetUserID()) 278805e7106SZachary Turner return false; 279805e7106SZachary Turner 280805e7106SZachary Turner if (m_match_info.GroupIDIsValid() && 281805e7106SZachary Turner m_match_info.GetGroupID() != proc_info.GetGroupID()) 282805e7106SZachary Turner return false; 283805e7106SZachary Turner 284805e7106SZachary Turner if (m_match_info.EffectiveUserIDIsValid() && 285805e7106SZachary Turner m_match_info.GetEffectiveUserID() != proc_info.GetEffectiveUserID()) 286805e7106SZachary Turner return false; 287805e7106SZachary Turner 288805e7106SZachary Turner if (m_match_info.EffectiveGroupIDIsValid() && 289805e7106SZachary Turner m_match_info.GetEffectiveGroupID() != proc_info.GetEffectiveGroupID()) 290805e7106SZachary Turner return false; 291805e7106SZachary Turner return true; 292805e7106SZachary Turner } 293a8b18baaSPavel Labath bool ProcessInstanceInfoMatch::Matches( 294a8b18baaSPavel Labath const ProcessInstanceInfo &proc_info) const { 295a8b18baaSPavel Labath return ArchitectureMatches(proc_info.GetArchitecture()) && 296a8b18baaSPavel Labath ProcessIDsMatch(proc_info) && UserIDsMatch(proc_info) && 297a8b18baaSPavel Labath NameMatches(proc_info.GetName()); 298a8b18baaSPavel Labath } 299805e7106SZachary Turner 300805e7106SZachary Turner bool ProcessInstanceInfoMatch::MatchAllProcesses() const { 301805e7106SZachary Turner if (m_name_match_type != NameMatch::Ignore) 302805e7106SZachary Turner return false; 303805e7106SZachary Turner 304805e7106SZachary Turner if (m_match_info.ProcessIDIsValid()) 305805e7106SZachary Turner return false; 306805e7106SZachary Turner 307805e7106SZachary Turner if (m_match_info.ParentProcessIDIsValid()) 308805e7106SZachary Turner return false; 309805e7106SZachary Turner 310805e7106SZachary Turner if (m_match_info.UserIDIsValid()) 311805e7106SZachary Turner return false; 312805e7106SZachary Turner 313805e7106SZachary Turner if (m_match_info.GroupIDIsValid()) 314805e7106SZachary Turner return false; 315805e7106SZachary Turner 316805e7106SZachary Turner if (m_match_info.EffectiveUserIDIsValid()) 317805e7106SZachary Turner return false; 318805e7106SZachary Turner 319805e7106SZachary Turner if (m_match_info.EffectiveGroupIDIsValid()) 320805e7106SZachary Turner return false; 321805e7106SZachary Turner 322805e7106SZachary Turner if (m_match_info.GetArchitecture().IsValid()) 323805e7106SZachary Turner return false; 324805e7106SZachary Turner 325805e7106SZachary Turner if (m_match_all_users) 326805e7106SZachary Turner return false; 327805e7106SZachary Turner 328805e7106SZachary Turner return true; 329805e7106SZachary Turner } 330805e7106SZachary Turner 331805e7106SZachary Turner void ProcessInstanceInfoMatch::Clear() { 332805e7106SZachary Turner m_match_info.Clear(); 333805e7106SZachary Turner m_name_match_type = NameMatch::Ignore; 334805e7106SZachary Turner m_match_all_users = false; 335805e7106SZachary Turner } 3360ce3b710SJonas Devlieghere 3370ce3b710SJonas Devlieghere void llvm::yaml::MappingTraits<ProcessInstanceInfo>::mapping( 3380ce3b710SJonas Devlieghere IO &io, ProcessInstanceInfo &Info) { 3390ce3b710SJonas Devlieghere io.mapRequired("executable", Info.m_executable); 3400ce3b710SJonas Devlieghere io.mapRequired("arg0", Info.m_arg0); 341bad61548SJonas Devlieghere io.mapRequired("args", Info.m_arguments); 3420ce3b710SJonas Devlieghere io.mapRequired("arch", Info.m_arch); 3430ce3b710SJonas Devlieghere io.mapRequired("uid", Info.m_uid); 3440ce3b710SJonas Devlieghere io.mapRequired("gid", Info.m_gid); 3450ce3b710SJonas Devlieghere io.mapRequired("pid", Info.m_pid); 3460ce3b710SJonas Devlieghere io.mapRequired("effective-uid", Info.m_euid); 3470ce3b710SJonas Devlieghere io.mapRequired("effective-gid", Info.m_egid); 3480ce3b710SJonas Devlieghere io.mapRequired("parent-pid", Info.m_parent_pid); 3490ce3b710SJonas Devlieghere } 3502451cbf0SJonas Devlieghere 3512451cbf0SJonas Devlieghere 3522451cbf0SJonas Devlieghere llvm::Optional<ProcessInstanceInfoList> 3532451cbf0SJonas Devlieghere repro::GetReplayProcessInstanceInfoList() { 3542451cbf0SJonas Devlieghere static std::unique_ptr<repro::MultiLoader<repro::ProcessInfoProvider>> 3552451cbf0SJonas Devlieghere loader = repro::MultiLoader<repro::ProcessInfoProvider>::Create( 3562451cbf0SJonas Devlieghere repro::Reproducer::Instance().GetLoader()); 3572451cbf0SJonas Devlieghere 3582451cbf0SJonas Devlieghere if (!loader) 3592451cbf0SJonas Devlieghere return {}; 3602451cbf0SJonas Devlieghere 3612451cbf0SJonas Devlieghere llvm::Optional<std::string> nextfile = loader->GetNextFile(); 3622451cbf0SJonas Devlieghere if (!nextfile) 3632451cbf0SJonas Devlieghere return {}; 3642451cbf0SJonas Devlieghere 3652451cbf0SJonas Devlieghere auto error_or_file = llvm::MemoryBuffer::getFile(*nextfile); 3662451cbf0SJonas Devlieghere if (std::error_code err = error_or_file.getError()) 3672451cbf0SJonas Devlieghere return {}; 3682451cbf0SJonas Devlieghere 3692451cbf0SJonas Devlieghere ProcessInstanceInfoList infos; 3702451cbf0SJonas Devlieghere llvm::yaml::Input yin((*error_or_file)->getBuffer()); 3712451cbf0SJonas Devlieghere yin >> infos; 3722451cbf0SJonas Devlieghere 3732451cbf0SJonas Devlieghere if (auto err = yin.error()) 3742451cbf0SJonas Devlieghere return {}; 3752451cbf0SJonas Devlieghere 3762451cbf0SJonas Devlieghere return infos; 3772451cbf0SJonas Devlieghere } 378