diff options
Diffstat (limited to 'lldb/source/Utility/ProcessInfo.cpp')
| -rw-r--r-- | lldb/source/Utility/ProcessInfo.cpp | 333 | 
1 files changed, 333 insertions, 0 deletions
diff --git a/lldb/source/Utility/ProcessInfo.cpp b/lldb/source/Utility/ProcessInfo.cpp new file mode 100644 index 000000000000..5743d223be4f --- /dev/null +++ b/lldb/source/Utility/ProcessInfo.cpp @@ -0,0 +1,333 @@ +//===-- ProcessInfo.cpp -----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/ProcessInfo.h" + +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/Stream.h" +#include "lldb/Utility/StreamString.h" +#include "lldb/Utility/UserIDResolver.h" +#include "llvm/ADT/SmallString.h" + +#include <climits> + +using namespace lldb; +using namespace lldb_private; + +ProcessInfo::ProcessInfo() +    : m_executable(), m_arguments(), m_environment(), m_uid(UINT32_MAX), +      m_gid(UINT32_MAX), m_arch(), m_pid(LLDB_INVALID_PROCESS_ID) {} + +ProcessInfo::ProcessInfo(const char *name, const ArchSpec &arch, +                         lldb::pid_t pid) +    : m_executable(name), m_arguments(), m_environment(), m_uid(UINT32_MAX), +      m_gid(UINT32_MAX), m_arch(arch), m_pid(pid) {} + +void ProcessInfo::Clear() { +  m_executable.Clear(); +  m_arguments.Clear(); +  m_environment.clear(); +  m_uid = UINT32_MAX; +  m_gid = UINT32_MAX; +  m_arch.Clear(); +  m_pid = LLDB_INVALID_PROCESS_ID; +} + +const char *ProcessInfo::GetName() const { +  return m_executable.GetFilename().GetCString(); +} + +llvm::StringRef ProcessInfo::GetNameAsStringRef() const { +  return m_executable.GetFilename().GetStringRef(); +} + +void ProcessInfo::Dump(Stream &s, Platform *platform) const { +  s << "Executable: " << GetName() << "\n"; +  s << "Triple: "; +  m_arch.DumpTriple(s); +  s << "\n"; + +  s << "Arguments:\n"; +  m_arguments.Dump(s); + +  s.Format("Environment:\n{0}", m_environment); +} + +void ProcessInfo::SetExecutableFile(const FileSpec &exe_file, +                                    bool add_exe_file_as_first_arg) { +  if (exe_file) { +    m_executable = exe_file; +    if (add_exe_file_as_first_arg) { +      llvm::SmallString<128> filename; +      exe_file.GetPath(filename); +      if (!filename.empty()) +        m_arguments.InsertArgumentAtIndex(0, filename); +    } +  } else { +    m_executable.Clear(); +  } +} + +llvm::StringRef ProcessInfo::GetArg0() const { return m_arg0; } + +void ProcessInfo::SetArg0(llvm::StringRef arg) { m_arg0 = arg; } + +void ProcessInfo::SetArguments(char const **argv, +                               bool first_arg_is_executable) { +  m_arguments.SetArguments(argv); + +  // Is the first argument the executable? +  if (first_arg_is_executable) { +    const char *first_arg = m_arguments.GetArgumentAtIndex(0); +    if (first_arg) { +      // Yes the first argument is an executable, set it as the executable in +      // the launch options. Don't resolve the file path as the path could be a +      // remote platform path +      m_executable.SetFile(first_arg, FileSpec::Style::native); +    } +  } +} + +void ProcessInfo::SetArguments(const Args &args, bool first_arg_is_executable) { +  // Copy all arguments +  m_arguments = args; + +  // Is the first argument the executable? +  if (first_arg_is_executable) { +    const char *first_arg = m_arguments.GetArgumentAtIndex(0); +    if (first_arg) { +      // Yes the first argument is an executable, set it as the executable in +      // the launch options. Don't resolve the file path as the path could be a +      // remote platform path +      m_executable.SetFile(first_arg, FileSpec::Style::native); +    } +  } +} + +void ProcessInstanceInfo::Dump(Stream &s, UserIDResolver &resolver) const { +  if (m_pid != LLDB_INVALID_PROCESS_ID) +    s.Printf("    pid = %" PRIu64 "\n", m_pid); + +  if (m_parent_pid != LLDB_INVALID_PROCESS_ID) +    s.Printf(" parent = %" PRIu64 "\n", m_parent_pid); + +  if (m_executable) { +    s.Printf("   name = %s\n", m_executable.GetFilename().GetCString()); +    s.PutCString("   file = "); +    m_executable.Dump(&s); +    s.EOL(); +  } +  const uint32_t argc = m_arguments.GetArgumentCount(); +  if (argc > 0) { +    for (uint32_t i = 0; i < argc; i++) { +      const char *arg = m_arguments.GetArgumentAtIndex(i); +      if (i < 10) +        s.Printf(" arg[%u] = %s\n", i, arg); +      else +        s.Printf("arg[%u] = %s\n", i, arg); +    } +  } + +  s.Format("{0}", m_environment); + +  if (m_arch.IsValid()) { +    s.Printf("   arch = "); +    m_arch.DumpTriple(s); +    s.EOL(); +  } + +  if (UserIDIsValid()) { +    s.Format("    uid = {0,-5} ({1})\n", GetUserID(), +             resolver.GetUserName(GetUserID()).getValueOr("")); +  } +  if (GroupIDIsValid()) { +    s.Format("    gid = {0,-5} ({1})\n", GetGroupID(), +             resolver.GetGroupName(GetGroupID()).getValueOr("")); +  } +  if (EffectiveUserIDIsValid()) { +    s.Format("   euid = {0,-5} ({1})\n", GetEffectiveUserID(), +             resolver.GetUserName(GetEffectiveUserID()).getValueOr("")); +  } +  if (EffectiveGroupIDIsValid()) { +    s.Format("   egid = {0,-5} ({1})\n", GetEffectiveGroupID(), +             resolver.GetGroupName(GetEffectiveGroupID()).getValueOr("")); +  } +} + +void ProcessInstanceInfo::DumpTableHeader(Stream &s, bool show_args, +                                          bool verbose) { +  const char *label; +  if (show_args || verbose) +    label = "ARGUMENTS"; +  else +    label = "NAME"; + +  if (verbose) { +    s.Printf("PID    PARENT USER       GROUP      EFF USER   EFF GROUP  TRIPLE " +             "                        %s\n", +             label); +    s.PutCString( +        "====== ====== ========== ========== ========== ========== " +        "============================== ============================\n"); +  } else { +    s.Printf("PID    PARENT USER       TRIPLE                         %s\n", +             label); +    s.PutCString("====== ====== ========== ============================== " +                 "============================\n"); +  } +} + +void ProcessInstanceInfo::DumpAsTableRow(Stream &s, UserIDResolver &resolver, +                                         bool show_args, bool verbose) const { +  if (m_pid != LLDB_INVALID_PROCESS_ID) { +    s.Printf("%-6" PRIu64 " %-6" PRIu64 " ", m_pid, m_parent_pid); + +    StreamString arch_strm; +    if (m_arch.IsValid()) +      m_arch.DumpTriple(arch_strm); + +    auto print = [&](bool (ProcessInstanceInfo::*isValid)() const, +                     uint32_t (ProcessInstanceInfo::*getID)() const, +                     llvm::Optional<llvm::StringRef> (UserIDResolver::*getName)( +                         UserIDResolver::id_t id)) { +      const char *format = "{0,-10} "; +      if (!(this->*isValid)()) { +        s.Format(format, ""); +        return; +      } +      uint32_t id = (this->*getID)(); +      if (auto name = (resolver.*getName)(id)) +        s.Format(format, *name); +      else +        s.Format(format, id); +    }; +    if (verbose) { +      print(&ProcessInstanceInfo::UserIDIsValid, +            &ProcessInstanceInfo::GetUserID, &UserIDResolver::GetUserName); +      print(&ProcessInstanceInfo::GroupIDIsValid, +            &ProcessInstanceInfo::GetGroupID, &UserIDResolver::GetGroupName); +      print(&ProcessInstanceInfo::EffectiveUserIDIsValid, +            &ProcessInstanceInfo::GetEffectiveUserID, +            &UserIDResolver::GetUserName); +      print(&ProcessInstanceInfo::EffectiveGroupIDIsValid, +            &ProcessInstanceInfo::GetEffectiveGroupID, +            &UserIDResolver::GetGroupName); + +      s.Printf("%-30s ", arch_strm.GetData()); +    } else { +      print(&ProcessInstanceInfo::EffectiveUserIDIsValid, +            &ProcessInstanceInfo::GetEffectiveUserID, +            &UserIDResolver::GetUserName); +      s.Printf("%-30s ", arch_strm.GetData()); +    } + +    if (verbose || show_args) { +      s.PutCString(m_arg0); +      const uint32_t argc = m_arguments.GetArgumentCount(); +      for (uint32_t i = 0; i < argc; i++) { +        s.PutChar(' '); +        s.PutCString(m_arguments.GetArgumentAtIndex(i)); +      } +    } else { +      s.PutCString(GetName()); +    } + +    s.EOL(); +  } +} + +bool ProcessInstanceInfoMatch::ArchitectureMatches( +    const ArchSpec &arch_spec) const { +  return !m_match_info.GetArchitecture().IsValid() || +         m_match_info.GetArchitecture().IsCompatibleMatch(arch_spec); +} + +bool ProcessInstanceInfoMatch::NameMatches(const char *process_name) const { +  if (m_name_match_type == NameMatch::Ignore) +    return true; +  const char *match_name = m_match_info.GetName(); +  if (!match_name) +    return true; + +  return lldb_private::NameMatches(process_name, m_name_match_type, match_name); +} + +bool ProcessInstanceInfoMatch::ProcessIDsMatch( +    const ProcessInstanceInfo &proc_info) const { +  if (m_match_info.ProcessIDIsValid() && +      m_match_info.GetProcessID() != proc_info.GetProcessID()) +    return false; + +  if (m_match_info.ParentProcessIDIsValid() && +      m_match_info.GetParentProcessID() != proc_info.GetParentProcessID()) +    return false; +  return true; +} + +bool ProcessInstanceInfoMatch::UserIDsMatch( +    const ProcessInstanceInfo &proc_info) const { +  if (m_match_info.UserIDIsValid() && +      m_match_info.GetUserID() != proc_info.GetUserID()) +    return false; + +  if (m_match_info.GroupIDIsValid() && +      m_match_info.GetGroupID() != proc_info.GetGroupID()) +    return false; + +  if (m_match_info.EffectiveUserIDIsValid() && +      m_match_info.GetEffectiveUserID() != proc_info.GetEffectiveUserID()) +    return false; + +  if (m_match_info.EffectiveGroupIDIsValid() && +      m_match_info.GetEffectiveGroupID() != proc_info.GetEffectiveGroupID()) +    return false; +  return true; +} +bool ProcessInstanceInfoMatch::Matches( +    const ProcessInstanceInfo &proc_info) const { +  return ArchitectureMatches(proc_info.GetArchitecture()) && +         ProcessIDsMatch(proc_info) && UserIDsMatch(proc_info) && +         NameMatches(proc_info.GetName()); +} + +bool ProcessInstanceInfoMatch::MatchAllProcesses() const { +  if (m_name_match_type != NameMatch::Ignore) +    return false; + +  if (m_match_info.ProcessIDIsValid()) +    return false; + +  if (m_match_info.ParentProcessIDIsValid()) +    return false; + +  if (m_match_info.UserIDIsValid()) +    return false; + +  if (m_match_info.GroupIDIsValid()) +    return false; + +  if (m_match_info.EffectiveUserIDIsValid()) +    return false; + +  if (m_match_info.EffectiveGroupIDIsValid()) +    return false; + +  if (m_match_info.GetArchitecture().IsValid()) +    return false; + +  if (m_match_all_users) +    return false; + +  return true; +} + +void ProcessInstanceInfoMatch::Clear() { +  m_match_info.Clear(); +  m_name_match_type = NameMatch::Ignore; +  m_match_all_users = false; +}  | 
