diff options
Diffstat (limited to 'source/Host/freebsd/Host.cpp')
-rw-r--r-- | source/Host/freebsd/Host.cpp | 139 |
1 files changed, 111 insertions, 28 deletions
diff --git a/source/Host/freebsd/Host.cpp b/source/Host/freebsd/Host.cpp index 405e7eacf5a96..c4a6ca37e9c4b 100644 --- a/source/Host/freebsd/Host.cpp +++ b/source/Host/freebsd/Host.cpp @@ -15,25 +15,30 @@ #include <sys/user.h> #include <sys/utsname.h> #include <sys/sysctl.h> +#include <sys/proc.h> #include <sys/ptrace.h> #include <sys/exec.h> #include <machine/elf.h> - // C++ Includes // Other libraries and framework includes // Project includes #include "lldb/Core/Error.h" #include "lldb/Host/Endian.h" #include "lldb/Host/Host.h" +#include "lldb/Core/Module.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" +#include "lldb/Core/Log.h" #include "lldb/Target/Process.h" +#include "lldb/Target/Platform.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" +#include "lldb/Utility/CleanUp.h" + #include "llvm/Support/Host.h" @@ -44,7 +49,6 @@ extern "C" { using namespace lldb; using namespace lldb_private; - class FreeBSDThread { public: @@ -120,7 +124,8 @@ Host::GetEnvironment (StringList &env) { char *v; char **var = environ; - for (; var != NULL && *var != NULL; ++var) { + for (; var != NULL && *var != NULL; ++var) + { v = strchr(*var, (int)'-'); if (v == NULL) continue; @@ -135,34 +140,30 @@ Host::GetOSVersion(uint32_t &major, uint32_t &update) { struct utsname un; - int status; + ::memset(&un, 0, sizeof(utsname)); if (uname(&un) < 0) return false; - status = sscanf(un.release, "%u.%u", &major, &minor); + int status = sscanf(un.release, "%u.%u", &major, &minor); return status == 2; } -Error -Host::LaunchProcess (ProcessLaunchInfo &launch_info) -{ - Error error; - assert(!"Not implemented yet!!!"); - return error; -} - bool Host::GetOSBuildString (std::string &s) { int mib[2] = { CTL_KERN, KERN_OSREV }; - char cstr[PATH_MAX]; - size_t cstr_len = sizeof(cstr); - if (::sysctl (mib, 2, cstr, &cstr_len, NULL, 0) == 0) + char osrev_str[12]; + uint32_t osrev = 0; + size_t osrev_len = sizeof(osrev); + + if (::sysctl (mib, 2, &osrev, &osrev_len, NULL, 0) == 0) { - s.assign (cstr, cstr_len); + ::snprintf(osrev_str, sizeof(osrev_str), "%-8.8u", osrev); + s.assign (osrev_str); return true; } + s.clear(); return false; } @@ -170,23 +171,25 @@ Host::GetOSBuildString (std::string &s) bool Host::GetOSKernelDescription (std::string &s) { - int mib[2] = { CTL_KERN, KERN_VERSION }; - char cstr[PATH_MAX]; - size_t cstr_len = sizeof(cstr); - if (::sysctl (mib, 2, cstr, &cstr_len, NULL, 0) == 0) - { - s.assign (cstr, cstr_len); - return true; - } + struct utsname un; + + ::memset(&un, 0, sizeof(utsname)); s.clear(); + + if (uname(&un) < 0) return false; + + s.assign (un.version); + + return true; } static bool GetFreeBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr, ProcessInstanceInfo &process_info) { - if (process_info.ProcessIDIsValid()) { + if (process_info.ProcessIDIsValid()) + { int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, (int)process_info.GetProcessID() }; char arg_data[8192]; @@ -235,7 +238,8 @@ GetFreeBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr, static bool GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info) { - if (process_info.ProcessIDIsValid()) { + if (process_info.ProcessIDIsValid()) + { process_info.GetArchitecture() = Host::GetArchitecture (Host::eSystemDefaultArchitecture); return true; } @@ -279,16 +283,95 @@ GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) return false; } +uint32_t +Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) +{ + std::vector<struct kinfo_proc> kinfos; + + int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; + + size_t pid_data_size = 0; + if (::sysctl (mib, 3, NULL, &pid_data_size, NULL, 0) != 0) + return 0; + + // Add a few extra in case a few more show up + const size_t estimated_pid_count = (pid_data_size / sizeof(struct kinfo_proc)) + 10; + + kinfos.resize (estimated_pid_count); + pid_data_size = kinfos.size() * sizeof(struct kinfo_proc); + + if (::sysctl (mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0) + return 0; + + const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc)); + + bool all_users = match_info.GetMatchAllUsers(); + const lldb::pid_t our_pid = getpid(); + const uid_t our_uid = getuid(); + for (int i = 0; i < actual_pid_count; i++) + { + const struct kinfo_proc &kinfo = kinfos[i]; + const bool kinfo_user_matches = (all_users || + (kinfo.ki_ruid == our_uid) || + // Special case, if lldb is being run as root we can attach to anything. + (our_uid == 0) + ); + + if (kinfo_user_matches == false || // Make sure the user is acceptable + kinfo.ki_pid == our_pid || // Skip this process + kinfo.ki_pid == 0 || // Skip kernel (kernel pid is zero) + kinfo.ki_stat == SZOMB || // Zombies are bad, they like brains... + kinfo.ki_flag & P_TRACED || // Being debugged? + kinfo.ki_flag & P_WEXIT) // Working on exiting + continue; + + // Every thread is a process in FreeBSD, but all the threads of a single process + // have the same pid. Do not store the process info in the result list if a process + // with given identifier is already registered there. + bool already_registered = false; + for (uint32_t pi = 0; + !already_registered && + (const int)kinfo.ki_numthreads > 1 && + pi < (const uint32_t)process_infos.GetSize(); pi++) + already_registered = (process_infos.GetProcessIDAtIndex(pi) == (uint32_t)kinfo.ki_pid); + + if (already_registered) + continue; + + ProcessInstanceInfo process_info; + process_info.SetProcessID (kinfo.ki_pid); + process_info.SetParentProcessID (kinfo.ki_ppid); + process_info.SetUserID (kinfo.ki_ruid); + process_info.SetGroupID (kinfo.ki_rgid); + process_info.SetEffectiveUserID (kinfo.ki_svuid); + process_info.SetEffectiveGroupID (kinfo.ki_svgid); + + // Make sure our info matches before we go fetch the name and cpu type + if (match_info.Matches (process_info) && + GetFreeBSDProcessArgs (&match_info, process_info)) + { + GetFreeBSDProcessCPUType (process_info); + if (match_info.Matches (process_info)) + process_infos.Append (process_info); + } + } + + return process_infos.GetSize(); +} + bool Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) { process_info.SetProcessID(pid); - if (GetFreeBSDProcessArgs(NULL, process_info)) { + + if (GetFreeBSDProcessArgs(NULL, process_info)) + { // should use libprocstat instead of going right into sysctl? GetFreeBSDProcessCPUType(process_info); GetFreeBSDProcessUserAndGroup(process_info); return true; } + process_info.Clear(); return false; } |