diff options
Diffstat (limited to 'lldb/source/Host/freebsd/Host.cpp')
-rw-r--r-- | lldb/source/Host/freebsd/Host.cpp | 111 |
1 files changed, 81 insertions, 30 deletions
diff --git a/lldb/source/Host/freebsd/Host.cpp b/lldb/source/Host/freebsd/Host.cpp index 3d6596c028f..3a4174f7548 100644 --- a/lldb/source/Host/freebsd/Host.cpp +++ b/lldb/source/Host/freebsd/Host.cpp @@ -9,12 +9,18 @@ // C Includes #include <stdio.h> +#include <dlfcn.h> #include <execinfo.h> #include <sys/types.h> #include <sys/user.h> #include <sys/utsname.h> #include <sys/sysctl.h> +#include <sys/ptrace.h> +#include <sys/exec.h> +#include <machine/elf.h> + + // C++ Includes // Other libraries and framework includes // Project includes @@ -26,15 +32,19 @@ #include "lldb/Core/StreamString.h" #include "lldb/Target/Process.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" #include "llvm/Support/Host.h" + extern "C" { - char **environ; + extern char **environ; } using namespace lldb; using namespace lldb_private; + class FreeBSDThread { public: @@ -77,7 +87,7 @@ Host::Backtrace (Stream &strm, uint32_t max_frames) std::vector<void *> frame_buffer (max_frames, NULL); int count = ::backtrace (&frame_buffer[0], frame_buffer.size()); ::backtrace_symbols_fd (&frame_buffer[0], count, backtrace_fd); - + const off_t buffer_size = ::lseek(backtrace_fd, 0, SEEK_CUR); if (::lseek(backtrace_fd, 0, SEEK_SET) == 0) @@ -101,7 +111,7 @@ Host::GetEnvironment (StringList &env) { char *v; char **var = environ; - for (var = environ; var != NULL; ++var) { + for (; var != NULL && *var != NULL; ++var) { v = strchr(*var, (int)'-'); if (v == NULL) continue; @@ -168,49 +178,47 @@ GetFreeBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr, ProcessInstanceInfo &process_info) { if (process_info.ProcessIDIsValid()) { - int mib[3] = { CTL_KERN, KERN_PROC_ARGS, process_info.GetProcessID() }; + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, process_info.GetProcessID() }; char arg_data[8192]; size_t arg_data_size = sizeof(arg_data); - if (::sysctl (mib, 3, arg_data, &arg_data_size , NULL, 0) == 0) + if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0) { DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *)); uint32_t offset = 0; - uint32_t start_offset; - uint32_t argc = data.GetU32 (&offset); const char *cstr; - + cstr = data.GetCStr (&offset); if (cstr) { process_info.GetExecutableFile().SetFile(cstr, false); - if (match_info_ptr == NULL || + if (!(match_info_ptr == NULL || NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(), match_info_ptr->GetNameMatchType(), - match_info_ptr->GetProcessInfo().GetName())) + match_info_ptr->GetProcessInfo().GetName()))) + return false; + + Args &proc_args = process_info.GetArguments(); + while (1) { - // Skip NULLs - while (1) + const uint8_t *p = data.PeekData(offset, 1); + while ((p != NULL) && (*p == '\0') && offset < arg_data_size) { - const uint8_t *p = data.PeekData(offset, 1); - if ((p == NULL) || (*p != '\0')) - break; ++offset; + p = data.PeekData(offset, 1); } - // Now extract all arguments - Args &proc_args = process_info.GetArguments(); - for (int i=0; i<argc; ++i) - { - start_offset = offset; - cstr = data.GetCStr(&offset); - if (cstr) - proc_args.AppendArgument(cstr); - } - return true; + if (p == NULL || offset >= arg_data_size) + return true; + + cstr = data.GetCStr(&offset); + if (cstr) + proc_args.AppendArgument(cstr); + else + return true; } } - } + } } return false; } @@ -219,8 +227,8 @@ static bool GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info) { if (process_info.ProcessIDIsValid()) { - // TODO: This - // return true; + process_info.GetArchitecture() = Host::GetArchitecture (Host::eSystemDefaultArchitecture); + return true; } process_info.GetArchitecture().Clear(); return false; @@ -249,7 +257,7 @@ GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) if (proc_kinfo.ki_ngroups > 0) process_info.SetEffectiveGroupID (proc_kinfo.ki_groups[0]); else - process_info.SetEffectiveGroupID (UINT32_MAX); + process_info.SetEffectiveGroupID (UINT32_MAX); return true; } } @@ -258,7 +266,7 @@ GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) process_info.SetUserID (UINT32_MAX); process_info.SetGroupID (UINT32_MAX); process_info.SetEffectiveUserID (UINT32_MAX); - process_info.SetEffectiveGroupID (UINT32_MAX); + process_info.SetEffectiveGroupID (UINT32_MAX); return false; } @@ -275,3 +283,46 @@ Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) process_info.Clear(); return false; } + +lldb::DataBufferSP +Host::GetAuxvData(lldb_private::Process *process) +{ + int mib[2] = { CTL_KERN, KERN_PS_STRINGS }; + void *ps_strings_addr, *auxv_addr; + size_t ps_strings_size = sizeof(void *); + Elf_Auxinfo aux_info[AT_COUNT]; + struct ps_strings ps_strings; + struct ptrace_io_desc pid; + DataBufferSP buf_sp; + std::auto_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0)); + + if (::sysctl(mib, 2, &ps_strings_addr, &ps_strings_size, NULL, 0) == 0) { + pid.piod_op = PIOD_READ_D; + pid.piod_addr = &ps_strings; + pid.piod_offs = ps_strings_addr; + pid.piod_len = sizeof(ps_strings); + if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, NULL)) { + perror("failed to fetch ps_strings"); + buf_ap.release(); + goto done; + } + + auxv_addr = ps_strings.ps_envstr + ps_strings.ps_nenvstr + 1; + + pid.piod_addr = aux_info; + pid.piod_offs = auxv_addr; + pid.piod_len = sizeof(aux_info); + if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, NULL)) { + perror("failed to fetch aux_info"); + buf_ap.release(); + goto done; + } + memcpy(buf_ap->GetBytes(), aux_info, pid.piod_len); + buf_sp.reset(buf_ap.release()); + } else { + perror("sysctl failed on ps_strings"); + } + + done: + return buf_sp; +} |