1254721Semaste//===-- source/Host/freebsd/Host.cpp ------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste// C Includes 11254721Semaste#include <stdio.h> 12254721Semaste#include <dlfcn.h> 13254721Semaste#include <execinfo.h> 14254721Semaste#include <sys/types.h> 15254721Semaste#include <sys/user.h> 16254721Semaste#include <sys/utsname.h> 17254721Semaste#include <sys/sysctl.h> 18263363Semaste#include <sys/proc.h> 19254721Semaste 20254721Semaste#include <sys/ptrace.h> 21254721Semaste#include <sys/exec.h> 22254721Semaste#include <machine/elf.h> 23254721Semaste 24254721Semaste// C++ Includes 25254721Semaste// Other libraries and framework includes 26254721Semaste// Project includes 27254721Semaste#include "lldb/Core/Error.h" 28254721Semaste#include "lldb/Host/Endian.h" 29254721Semaste#include "lldb/Host/Host.h" 30263363Semaste#include "lldb/Core/Module.h" 31254721Semaste#include "lldb/Core/DataExtractor.h" 32254721Semaste#include "lldb/Core/StreamFile.h" 33254721Semaste#include "lldb/Core/StreamString.h" 34263363Semaste#include "lldb/Core/Log.h" 35254721Semaste#include "lldb/Target/Process.h" 36263363Semaste#include "lldb/Target/Platform.h" 37254721Semaste 38254721Semaste#include "lldb/Core/DataBufferHeap.h" 39254721Semaste#include "lldb/Core/DataExtractor.h" 40263363Semaste#include "lldb/Utility/CleanUp.h" 41263363Semaste 42254721Semaste#include "llvm/Support/Host.h" 43254721Semaste 44254721Semaste 45254721Semasteextern "C" { 46254721Semaste extern char **environ; 47254721Semaste} 48254721Semaste 49254721Semasteusing namespace lldb; 50254721Semasteusing namespace lldb_private; 51254721Semaste 52254721Semasteclass FreeBSDThread 53254721Semaste{ 54254721Semastepublic: 55254721Semaste FreeBSDThread(const char *thread_name) 56254721Semaste { 57254721Semaste Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name); 58254721Semaste } 59254721Semaste static void PThreadDestructor (void *v) 60254721Semaste { 61254721Semaste delete (FreeBSDThread*)v; 62254721Semaste } 63254721Semaste}; 64254721Semaste 65254721Semastestatic pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT; 66254721Semastestatic pthread_key_t g_thread_create_key = 0; 67254721Semaste 68254721Semastestatic void 69254721SemasteInitThreadCreated() 70254721Semaste{ 71254721Semaste ::pthread_key_create (&g_thread_create_key, FreeBSDThread::PThreadDestructor); 72254721Semaste} 73254721Semaste 74254721Semastevoid 75254721SemasteHost::ThreadCreated (const char *thread_name) 76254721Semaste{ 77254721Semaste ::pthread_once (&g_thread_create_once, InitThreadCreated); 78254721Semaste if (g_thread_create_key) 79254721Semaste { 80254721Semaste ::pthread_setspecific (g_thread_create_key, new FreeBSDThread(thread_name)); 81254721Semaste } 82254721Semaste 83254721Semaste Host::SetShortThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name, 16); 84254721Semaste} 85254721Semaste 86254721Semastestd::string 87254721SemasteHost::GetThreadName (lldb::pid_t pid, lldb::tid_t tid) 88254721Semaste{ 89254721Semaste std::string thread_name; 90254721Semaste return thread_name; 91254721Semaste} 92254721Semaste 93254721Semastevoid 94254721SemasteHost::Backtrace (Stream &strm, uint32_t max_frames) 95254721Semaste{ 96254721Semaste char backtrace_path[] = "/tmp/lldb-backtrace-tmp-XXXXXX"; 97254721Semaste int backtrace_fd = ::mkstemp (backtrace_path); 98254721Semaste if (backtrace_fd != -1) 99254721Semaste { 100254721Semaste std::vector<void *> frame_buffer (max_frames, NULL); 101254721Semaste int count = ::backtrace (&frame_buffer[0], frame_buffer.size()); 102254721Semaste ::backtrace_symbols_fd (&frame_buffer[0], count, backtrace_fd); 103254721Semaste 104254721Semaste const off_t buffer_size = ::lseek(backtrace_fd, 0, SEEK_CUR); 105254721Semaste 106254721Semaste if (::lseek(backtrace_fd, 0, SEEK_SET) == 0) 107254721Semaste { 108254721Semaste char *buffer = (char *)::malloc (buffer_size); 109254721Semaste if (buffer) 110254721Semaste { 111254721Semaste ssize_t bytes_read = ::read (backtrace_fd, buffer, buffer_size); 112254721Semaste if (bytes_read > 0) 113254721Semaste strm.Write(buffer, bytes_read); 114254721Semaste ::free (buffer); 115254721Semaste } 116254721Semaste } 117254721Semaste ::close (backtrace_fd); 118254721Semaste ::unlink (backtrace_path); 119254721Semaste } 120254721Semaste} 121254721Semaste 122254721Semastesize_t 123254721SemasteHost::GetEnvironment (StringList &env) 124254721Semaste{ 125254721Semaste char *v; 126254721Semaste char **var = environ; 127263363Semaste for (; var != NULL && *var != NULL; ++var) 128263363Semaste { 129254721Semaste v = strchr(*var, (int)'-'); 130254721Semaste if (v == NULL) 131254721Semaste continue; 132254721Semaste env.AppendString(v); 133254721Semaste } 134254721Semaste return env.GetSize(); 135254721Semaste} 136254721Semaste 137254721Semastebool 138254721SemasteHost::GetOSVersion(uint32_t &major, 139254721Semaste uint32_t &minor, 140254721Semaste uint32_t &update) 141254721Semaste{ 142254721Semaste struct utsname un; 143254721Semaste 144263363Semaste ::memset(&un, 0, sizeof(utsname)); 145254721Semaste if (uname(&un) < 0) 146254721Semaste return false; 147254721Semaste 148263363Semaste int status = sscanf(un.release, "%u.%u", &major, &minor); 149254721Semaste return status == 2; 150254721Semaste} 151254721Semaste 152254721Semastebool 153254721SemasteHost::GetOSBuildString (std::string &s) 154254721Semaste{ 155254721Semaste int mib[2] = { CTL_KERN, KERN_OSREV }; 156263363Semaste char osrev_str[12]; 157263363Semaste uint32_t osrev = 0; 158263363Semaste size_t osrev_len = sizeof(osrev); 159263363Semaste 160263363Semaste if (::sysctl (mib, 2, &osrev, &osrev_len, NULL, 0) == 0) 161254721Semaste { 162263363Semaste ::snprintf(osrev_str, sizeof(osrev_str), "%-8.8u", osrev); 163263363Semaste s.assign (osrev_str); 164254721Semaste return true; 165254721Semaste } 166263363Semaste 167254721Semaste s.clear(); 168254721Semaste return false; 169254721Semaste} 170254721Semaste 171254721Semastebool 172254721SemasteHost::GetOSKernelDescription (std::string &s) 173254721Semaste{ 174263363Semaste struct utsname un; 175263363Semaste 176263363Semaste ::memset(&un, 0, sizeof(utsname)); 177254721Semaste s.clear(); 178263363Semaste 179263363Semaste if (uname(&un) < 0) 180254721Semaste return false; 181263363Semaste 182263363Semaste s.assign (un.version); 183263363Semaste 184263363Semaste return true; 185254721Semaste} 186254721Semaste 187254721Semastestatic bool 188254721SemasteGetFreeBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr, 189254721Semaste ProcessInstanceInfo &process_info) 190254721Semaste{ 191263363Semaste if (process_info.ProcessIDIsValid()) 192263363Semaste { 193254721Semaste int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, (int)process_info.GetProcessID() }; 194254721Semaste 195254721Semaste char arg_data[8192]; 196254721Semaste size_t arg_data_size = sizeof(arg_data); 197254721Semaste if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0) 198254721Semaste { 199254721Semaste DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *)); 200254721Semaste lldb::offset_t offset = 0; 201254721Semaste const char *cstr; 202254721Semaste 203254721Semaste cstr = data.GetCStr (&offset); 204254721Semaste if (cstr) 205254721Semaste { 206254721Semaste process_info.GetExecutableFile().SetFile(cstr, false); 207254721Semaste 208254721Semaste if (!(match_info_ptr == NULL || 209254721Semaste NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(), 210254721Semaste match_info_ptr->GetNameMatchType(), 211254721Semaste match_info_ptr->GetProcessInfo().GetName()))) 212254721Semaste return false; 213254721Semaste 214254721Semaste Args &proc_args = process_info.GetArguments(); 215254721Semaste while (1) 216254721Semaste { 217254721Semaste const uint8_t *p = data.PeekData(offset, 1); 218254721Semaste while ((p != NULL) && (*p == '\0') && offset < arg_data_size) 219254721Semaste { 220254721Semaste ++offset; 221254721Semaste p = data.PeekData(offset, 1); 222254721Semaste } 223254721Semaste if (p == NULL || offset >= arg_data_size) 224254721Semaste return true; 225254721Semaste 226254721Semaste cstr = data.GetCStr(&offset); 227254721Semaste if (cstr) 228254721Semaste proc_args.AppendArgument(cstr); 229254721Semaste else 230254721Semaste return true; 231254721Semaste } 232254721Semaste } 233254721Semaste } 234254721Semaste } 235254721Semaste return false; 236254721Semaste} 237254721Semaste 238254721Semastestatic bool 239254721SemasteGetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info) 240254721Semaste{ 241263363Semaste if (process_info.ProcessIDIsValid()) 242263363Semaste { 243254721Semaste process_info.GetArchitecture() = Host::GetArchitecture (Host::eSystemDefaultArchitecture); 244254721Semaste return true; 245254721Semaste } 246254721Semaste process_info.GetArchitecture().Clear(); 247254721Semaste return false; 248254721Semaste} 249254721Semaste 250254721Semastestatic bool 251254721SemasteGetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) 252254721Semaste{ 253254721Semaste struct kinfo_proc proc_kinfo; 254254721Semaste size_t proc_kinfo_size; 255254721Semaste 256254721Semaste if (process_info.ProcessIDIsValid()) 257254721Semaste { 258254721Semaste int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, 259254721Semaste (int)process_info.GetProcessID() }; 260254721Semaste proc_kinfo_size = sizeof(struct kinfo_proc); 261254721Semaste 262254721Semaste if (::sysctl (mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) 263254721Semaste { 264254721Semaste if (proc_kinfo_size > 0) 265254721Semaste { 266254721Semaste process_info.SetParentProcessID (proc_kinfo.ki_ppid); 267254721Semaste process_info.SetUserID (proc_kinfo.ki_ruid); 268254721Semaste process_info.SetGroupID (proc_kinfo.ki_rgid); 269254721Semaste process_info.SetEffectiveUserID (proc_kinfo.ki_uid); 270254721Semaste if (proc_kinfo.ki_ngroups > 0) 271254721Semaste process_info.SetEffectiveGroupID (proc_kinfo.ki_groups[0]); 272254721Semaste else 273254721Semaste process_info.SetEffectiveGroupID (UINT32_MAX); 274254721Semaste return true; 275254721Semaste } 276254721Semaste } 277254721Semaste } 278254721Semaste process_info.SetParentProcessID (LLDB_INVALID_PROCESS_ID); 279254721Semaste process_info.SetUserID (UINT32_MAX); 280254721Semaste process_info.SetGroupID (UINT32_MAX); 281254721Semaste process_info.SetEffectiveUserID (UINT32_MAX); 282254721Semaste process_info.SetEffectiveGroupID (UINT32_MAX); 283254721Semaste return false; 284254721Semaste} 285254721Semaste 286263363Semasteuint32_t 287263363SemasteHost::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) 288263363Semaste{ 289263363Semaste std::vector<struct kinfo_proc> kinfos; 290263363Semaste 291263363Semaste int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; 292263363Semaste 293263363Semaste size_t pid_data_size = 0; 294263363Semaste if (::sysctl (mib, 3, NULL, &pid_data_size, NULL, 0) != 0) 295263363Semaste return 0; 296263363Semaste 297263363Semaste // Add a few extra in case a few more show up 298263363Semaste const size_t estimated_pid_count = (pid_data_size / sizeof(struct kinfo_proc)) + 10; 299263363Semaste 300263363Semaste kinfos.resize (estimated_pid_count); 301263363Semaste pid_data_size = kinfos.size() * sizeof(struct kinfo_proc); 302263363Semaste 303263363Semaste if (::sysctl (mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0) 304263363Semaste return 0; 305263363Semaste 306263363Semaste const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc)); 307263363Semaste 308263363Semaste bool all_users = match_info.GetMatchAllUsers(); 309263363Semaste const lldb::pid_t our_pid = getpid(); 310263363Semaste const uid_t our_uid = getuid(); 311263363Semaste for (int i = 0; i < actual_pid_count; i++) 312263363Semaste { 313263363Semaste const struct kinfo_proc &kinfo = kinfos[i]; 314263363Semaste const bool kinfo_user_matches = (all_users || 315263363Semaste (kinfo.ki_ruid == our_uid) || 316263363Semaste // Special case, if lldb is being run as root we can attach to anything. 317263363Semaste (our_uid == 0) 318263363Semaste ); 319263363Semaste 320263363Semaste if (kinfo_user_matches == false || // Make sure the user is acceptable 321263363Semaste kinfo.ki_pid == our_pid || // Skip this process 322263363Semaste kinfo.ki_pid == 0 || // Skip kernel (kernel pid is zero) 323263363Semaste kinfo.ki_stat == SZOMB || // Zombies are bad, they like brains... 324263363Semaste kinfo.ki_flag & P_TRACED || // Being debugged? 325263363Semaste kinfo.ki_flag & P_WEXIT) // Working on exiting 326263363Semaste continue; 327263363Semaste 328263363Semaste // Every thread is a process in FreeBSD, but all the threads of a single process 329263363Semaste // have the same pid. Do not store the process info in the result list if a process 330263363Semaste // with given identifier is already registered there. 331263363Semaste bool already_registered = false; 332263363Semaste for (uint32_t pi = 0; 333263363Semaste !already_registered && 334263363Semaste (const int)kinfo.ki_numthreads > 1 && 335263363Semaste pi < (const uint32_t)process_infos.GetSize(); pi++) 336263363Semaste already_registered = (process_infos.GetProcessIDAtIndex(pi) == (uint32_t)kinfo.ki_pid); 337263363Semaste 338263363Semaste if (already_registered) 339263363Semaste continue; 340263363Semaste 341263363Semaste ProcessInstanceInfo process_info; 342263363Semaste process_info.SetProcessID (kinfo.ki_pid); 343263363Semaste process_info.SetParentProcessID (kinfo.ki_ppid); 344263363Semaste process_info.SetUserID (kinfo.ki_ruid); 345263363Semaste process_info.SetGroupID (kinfo.ki_rgid); 346263363Semaste process_info.SetEffectiveUserID (kinfo.ki_svuid); 347263363Semaste process_info.SetEffectiveGroupID (kinfo.ki_svgid); 348263363Semaste 349263363Semaste // Make sure our info matches before we go fetch the name and cpu type 350263363Semaste if (match_info.Matches (process_info) && 351263363Semaste GetFreeBSDProcessArgs (&match_info, process_info)) 352263363Semaste { 353263363Semaste GetFreeBSDProcessCPUType (process_info); 354263363Semaste if (match_info.Matches (process_info)) 355263363Semaste process_infos.Append (process_info); 356263363Semaste } 357263363Semaste } 358263363Semaste 359263363Semaste return process_infos.GetSize(); 360263363Semaste} 361263363Semaste 362254721Semastebool 363254721SemasteHost::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 364254721Semaste{ 365254721Semaste process_info.SetProcessID(pid); 366263363Semaste 367263363Semaste if (GetFreeBSDProcessArgs(NULL, process_info)) 368263363Semaste { 369254721Semaste // should use libprocstat instead of going right into sysctl? 370254721Semaste GetFreeBSDProcessCPUType(process_info); 371254721Semaste GetFreeBSDProcessUserAndGroup(process_info); 372254721Semaste return true; 373254721Semaste } 374263363Semaste 375254721Semaste process_info.Clear(); 376254721Semaste return false; 377254721Semaste} 378254721Semaste 379254721Semastelldb::DataBufferSP 380254721SemasteHost::GetAuxvData(lldb_private::Process *process) 381254721Semaste{ 382254721Semaste int mib[2] = { CTL_KERN, KERN_PS_STRINGS }; 383254721Semaste void *ps_strings_addr, *auxv_addr; 384254721Semaste size_t ps_strings_size = sizeof(void *); 385254721Semaste Elf_Auxinfo aux_info[AT_COUNT]; 386254721Semaste struct ps_strings ps_strings; 387254721Semaste struct ptrace_io_desc pid; 388254721Semaste DataBufferSP buf_sp; 389254721Semaste std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0)); 390254721Semaste 391254721Semaste if (::sysctl(mib, 2, &ps_strings_addr, &ps_strings_size, NULL, 0) == 0) { 392254721Semaste pid.piod_op = PIOD_READ_D; 393254721Semaste pid.piod_addr = &ps_strings; 394254721Semaste pid.piod_offs = ps_strings_addr; 395254721Semaste pid.piod_len = sizeof(ps_strings); 396254721Semaste if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) { 397254721Semaste perror("failed to fetch ps_strings"); 398254721Semaste buf_ap.release(); 399254721Semaste goto done; 400254721Semaste } 401254721Semaste 402254721Semaste auxv_addr = ps_strings.ps_envstr + ps_strings.ps_nenvstr + 1; 403254721Semaste 404254721Semaste pid.piod_addr = aux_info; 405254721Semaste pid.piod_offs = auxv_addr; 406254721Semaste pid.piod_len = sizeof(aux_info); 407254721Semaste if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) { 408254721Semaste perror("failed to fetch aux_info"); 409254721Semaste buf_ap.release(); 410254721Semaste goto done; 411254721Semaste } 412254721Semaste memcpy(buf_ap->GetBytes(), aux_info, pid.piod_len); 413254721Semaste buf_sp.reset(buf_ap.release()); 414254721Semaste } else { 415254721Semaste perror("sysctl failed on ps_strings"); 416254721Semaste } 417254721Semaste 418254721Semaste done: 419254721Semaste return buf_sp; 420254721Semaste} 421