1 //===-- source/Host/freebsd/Host.cpp ------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // C Includes 11 #include <stdio.h> 12 #include <dlfcn.h> 13 #include <execinfo.h> 14 #include <sys/types.h> 15 #include <sys/user.h> 16 #include <sys/sysctl.h> 17 #include <sys/proc.h> 18 19 #include <sys/ptrace.h> 20 #include <sys/exec.h> 21 #include <machine/elf.h> 22 23 // C++ Includes 24 // Other libraries and framework includes 25 // Project includes 26 #include "lldb/Core/Error.h" 27 #include "lldb/Host/Endian.h" 28 #include "lldb/Host/Host.h" 29 #include "lldb/Host/HostInfo.h" 30 #include "lldb/Core/Module.h" 31 #include "lldb/Core/DataExtractor.h" 32 #include "lldb/Core/StreamFile.h" 33 #include "lldb/Core/StreamString.h" 34 #include "lldb/Core/Log.h" 35 #include "lldb/Target/Process.h" 36 #include "lldb/Target/Platform.h" 37 38 #include "lldb/Core/DataBufferHeap.h" 39 #include "lldb/Core/DataExtractor.h" 40 #include "lldb/Utility/CleanUp.h" 41 42 #include "Plugins/Process/Utility/FreeBSDSignals.h" 43 44 #include "llvm/Support/Host.h" 45 46 extern "C" { 47 extern char **environ; 48 } 49 50 using namespace lldb; 51 using namespace lldb_private; 52 53 class FreeBSDThread 54 { 55 public: 56 FreeBSDThread(const char *thread_name) 57 { 58 Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name); 59 } 60 static void PThreadDestructor (void *v) 61 { 62 delete (FreeBSDThread*)v; 63 } 64 }; 65 66 static pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT; 67 static pthread_key_t g_thread_create_key = 0; 68 69 static void 70 InitThreadCreated() 71 { 72 ::pthread_key_create (&g_thread_create_key, FreeBSDThread::PThreadDestructor); 73 } 74 75 void 76 Host::ThreadCreated (const char *thread_name) 77 { 78 ::pthread_once (&g_thread_create_once, InitThreadCreated); 79 if (g_thread_create_key) 80 { 81 ::pthread_setspecific (g_thread_create_key, new FreeBSDThread(thread_name)); 82 } 83 84 Host::SetShortThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name, 16); 85 } 86 87 std::string 88 Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid) 89 { 90 struct kinfo_proc *kp = nullptr, *nkp; 91 size_t len = 0; 92 int error; 93 int name[4] = { 94 CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD, (int)pid 95 }; 96 97 while (1) { 98 error = sysctl(name, 4, kp, &len, nullptr, 0); 99 if (kp == nullptr || (error != 0 && errno == ENOMEM)) { 100 // Add extra space in case threads are added before next call. 101 len += sizeof(*kp) + len / 10; 102 nkp = (struct kinfo_proc *)realloc(kp, len); 103 if (nkp == nullptr) 104 { 105 free(kp); 106 return std::string(); 107 } 108 kp = nkp; 109 continue; 110 } 111 if (error != 0) 112 len = 0; 113 break; 114 } 115 116 std::string thread_name; 117 for (size_t i = 0; i < len / sizeof(*kp); i++) { 118 if (kp[i].ki_tid == (int)tid) { 119 thread_name = kp[i].ki_tdname; 120 break; 121 } 122 } 123 free(kp); 124 return thread_name; 125 } 126 127 void 128 Host::Backtrace (Stream &strm, uint32_t max_frames) 129 { 130 char backtrace_path[] = "/tmp/lldb-backtrace-tmp-XXXXXX"; 131 int backtrace_fd = ::mkstemp (backtrace_path); 132 if (backtrace_fd != -1) 133 { 134 std::vector<void *> frame_buffer (max_frames, NULL); 135 int count = ::backtrace (&frame_buffer[0], frame_buffer.size()); 136 ::backtrace_symbols_fd (&frame_buffer[0], count, backtrace_fd); 137 138 const off_t buffer_size = ::lseek(backtrace_fd, 0, SEEK_CUR); 139 140 if (::lseek(backtrace_fd, 0, SEEK_SET) == 0) 141 { 142 char *buffer = (char *)::malloc (buffer_size); 143 if (buffer) 144 { 145 ssize_t bytes_read = ::read (backtrace_fd, buffer, buffer_size); 146 if (bytes_read > 0) 147 strm.Write(buffer, bytes_read); 148 ::free (buffer); 149 } 150 } 151 ::close (backtrace_fd); 152 ::unlink (backtrace_path); 153 } 154 } 155 156 size_t 157 Host::GetEnvironment (StringList &env) 158 { 159 char *v; 160 char **var = environ; 161 for (; var != NULL && *var != NULL; ++var) 162 { 163 v = strchr(*var, (int)'-'); 164 if (v == NULL) 165 continue; 166 env.AppendString(v); 167 } 168 return env.GetSize(); 169 } 170 171 static bool 172 GetFreeBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr, 173 ProcessInstanceInfo &process_info) 174 { 175 if (process_info.ProcessIDIsValid()) 176 { 177 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, (int)process_info.GetProcessID() }; 178 179 char arg_data[8192]; 180 size_t arg_data_size = sizeof(arg_data); 181 if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0) 182 { 183 DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *)); 184 lldb::offset_t offset = 0; 185 const char *cstr; 186 187 cstr = data.GetCStr (&offset); 188 if (cstr) 189 { 190 process_info.GetExecutableFile().SetFile(cstr, false); 191 192 if (!(match_info_ptr == NULL || 193 NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(), 194 match_info_ptr->GetNameMatchType(), 195 match_info_ptr->GetProcessInfo().GetName()))) 196 return false; 197 198 Args &proc_args = process_info.GetArguments(); 199 while (1) 200 { 201 const uint8_t *p = data.PeekData(offset, 1); 202 while ((p != NULL) && (*p == '\0') && offset < arg_data_size) 203 { 204 ++offset; 205 p = data.PeekData(offset, 1); 206 } 207 if (p == NULL || offset >= arg_data_size) 208 return true; 209 210 cstr = data.GetCStr(&offset); 211 if (cstr) 212 proc_args.AppendArgument(cstr); 213 else 214 return true; 215 } 216 } 217 } 218 } 219 return false; 220 } 221 222 static bool 223 GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info) 224 { 225 if (process_info.ProcessIDIsValid()) 226 { 227 process_info.GetArchitecture() = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); 228 return true; 229 } 230 process_info.GetArchitecture().Clear(); 231 return false; 232 } 233 234 static bool 235 GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) 236 { 237 struct kinfo_proc proc_kinfo; 238 size_t proc_kinfo_size; 239 240 if (process_info.ProcessIDIsValid()) 241 { 242 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, 243 (int)process_info.GetProcessID() }; 244 proc_kinfo_size = sizeof(struct kinfo_proc); 245 246 if (::sysctl (mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) 247 { 248 if (proc_kinfo_size > 0) 249 { 250 process_info.SetParentProcessID (proc_kinfo.ki_ppid); 251 process_info.SetUserID (proc_kinfo.ki_ruid); 252 process_info.SetGroupID (proc_kinfo.ki_rgid); 253 process_info.SetEffectiveUserID (proc_kinfo.ki_uid); 254 if (proc_kinfo.ki_ngroups > 0) 255 process_info.SetEffectiveGroupID (proc_kinfo.ki_groups[0]); 256 else 257 process_info.SetEffectiveGroupID (UINT32_MAX); 258 return true; 259 } 260 } 261 } 262 process_info.SetParentProcessID (LLDB_INVALID_PROCESS_ID); 263 process_info.SetUserID (UINT32_MAX); 264 process_info.SetGroupID (UINT32_MAX); 265 process_info.SetEffectiveUserID (UINT32_MAX); 266 process_info.SetEffectiveGroupID (UINT32_MAX); 267 return false; 268 } 269 270 uint32_t 271 Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) 272 { 273 std::vector<struct kinfo_proc> kinfos; 274 275 int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; 276 277 size_t pid_data_size = 0; 278 if (::sysctl (mib, 3, NULL, &pid_data_size, NULL, 0) != 0) 279 return 0; 280 281 // Add a few extra in case a few more show up 282 const size_t estimated_pid_count = (pid_data_size / sizeof(struct kinfo_proc)) + 10; 283 284 kinfos.resize (estimated_pid_count); 285 pid_data_size = kinfos.size() * sizeof(struct kinfo_proc); 286 287 if (::sysctl (mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0) 288 return 0; 289 290 const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc)); 291 292 bool all_users = match_info.GetMatchAllUsers(); 293 const ::pid_t our_pid = getpid(); 294 const uid_t our_uid = getuid(); 295 for (size_t i = 0; i < actual_pid_count; i++) 296 { 297 const struct kinfo_proc &kinfo = kinfos[i]; 298 const bool kinfo_user_matches = (all_users || 299 (kinfo.ki_ruid == our_uid) || 300 // Special case, if lldb is being run as root we can attach to anything. 301 (our_uid == 0) 302 ); 303 304 if (kinfo_user_matches == false || // Make sure the user is acceptable 305 kinfo.ki_pid == our_pid || // Skip this process 306 kinfo.ki_pid == 0 || // Skip kernel (kernel pid is zero) 307 kinfo.ki_stat == SZOMB || // Zombies are bad, they like brains... 308 kinfo.ki_flag & P_TRACED || // Being debugged? 309 kinfo.ki_flag & P_WEXIT) // Working on exiting 310 continue; 311 312 // Every thread is a process in FreeBSD, but all the threads of a single process 313 // have the same pid. Do not store the process info in the result list if a process 314 // with given identifier is already registered there. 315 bool already_registered = false; 316 for (uint32_t pi = 0; 317 !already_registered && 318 (const int)kinfo.ki_numthreads > 1 && 319 pi < (const uint32_t)process_infos.GetSize(); pi++) 320 already_registered = (process_infos.GetProcessIDAtIndex(pi) == (uint32_t)kinfo.ki_pid); 321 322 if (already_registered) 323 continue; 324 325 ProcessInstanceInfo process_info; 326 process_info.SetProcessID (kinfo.ki_pid); 327 process_info.SetParentProcessID (kinfo.ki_ppid); 328 process_info.SetUserID (kinfo.ki_ruid); 329 process_info.SetGroupID (kinfo.ki_rgid); 330 process_info.SetEffectiveUserID (kinfo.ki_svuid); 331 process_info.SetEffectiveGroupID (kinfo.ki_svgid); 332 333 // Make sure our info matches before we go fetch the name and cpu type 334 if (match_info.Matches (process_info) && 335 GetFreeBSDProcessArgs (&match_info, process_info)) 336 { 337 GetFreeBSDProcessCPUType (process_info); 338 if (match_info.Matches (process_info)) 339 process_infos.Append (process_info); 340 } 341 } 342 343 return process_infos.GetSize(); 344 } 345 346 bool 347 Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 348 { 349 process_info.SetProcessID(pid); 350 351 if (GetFreeBSDProcessArgs(NULL, process_info)) 352 { 353 // should use libprocstat instead of going right into sysctl? 354 GetFreeBSDProcessCPUType(process_info); 355 GetFreeBSDProcessUserAndGroup(process_info); 356 return true; 357 } 358 359 process_info.Clear(); 360 return false; 361 } 362 363 lldb::DataBufferSP 364 Host::GetAuxvData(lldb_private::Process *process) 365 { 366 int mib[2] = { CTL_KERN, KERN_PS_STRINGS }; 367 void *ps_strings_addr, *auxv_addr; 368 size_t ps_strings_size = sizeof(void *); 369 Elf_Auxinfo aux_info[AT_COUNT]; 370 struct ps_strings ps_strings; 371 struct ptrace_io_desc pid; 372 DataBufferSP buf_sp; 373 std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0)); 374 375 if (::sysctl(mib, 2, &ps_strings_addr, &ps_strings_size, NULL, 0) == 0) { 376 pid.piod_op = PIOD_READ_D; 377 pid.piod_addr = &ps_strings; 378 pid.piod_offs = ps_strings_addr; 379 pid.piod_len = sizeof(ps_strings); 380 if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) { 381 perror("failed to fetch ps_strings"); 382 buf_ap.release(); 383 goto done; 384 } 385 386 auxv_addr = ps_strings.ps_envstr + ps_strings.ps_nenvstr + 1; 387 388 pid.piod_addr = aux_info; 389 pid.piod_offs = auxv_addr; 390 pid.piod_len = sizeof(aux_info); 391 if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) { 392 perror("failed to fetch aux_info"); 393 buf_ap.release(); 394 goto done; 395 } 396 memcpy(buf_ap->GetBytes(), aux_info, pid.piod_len); 397 buf_sp.reset(buf_ap.release()); 398 } else { 399 perror("sysctl failed on ps_strings"); 400 } 401 402 done: 403 return buf_sp; 404 } 405 406 const UnixSignalsSP& 407 Host::GetUnixSignals () 408 { 409 static const lldb_private::UnixSignalsSP s_unix_signals_sp (new FreeBSDSignals ()); 410 return s_unix_signals_sp; 411 } 412 413