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 #include "lldb/Utility/NameMatches.h" 42 43 #include "llvm/Support/Host.h" 44 45 extern "C" { 46 extern char **environ; 47 } 48 49 using namespace lldb; 50 using namespace lldb_private; 51 52 size_t 53 Host::GetEnvironment (StringList &env) 54 { 55 char *v; 56 char **var = environ; 57 for (; var != NULL && *var != NULL; ++var) 58 { 59 v = strchr(*var, (int)'-'); 60 if (v == NULL) 61 continue; 62 env.AppendString(v); 63 } 64 return env.GetSize(); 65 } 66 67 static bool 68 GetFreeBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr, 69 ProcessInstanceInfo &process_info) 70 { 71 if (process_info.ProcessIDIsValid()) 72 { 73 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, (int)process_info.GetProcessID() }; 74 75 char arg_data[8192]; 76 size_t arg_data_size = sizeof(arg_data); 77 if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0) 78 { 79 DataExtractor data (arg_data, arg_data_size, endian::InlHostByteOrder(), sizeof(void *)); 80 lldb::offset_t offset = 0; 81 const char *cstr; 82 83 cstr = data.GetCStr (&offset); 84 if (cstr) 85 { 86 process_info.GetExecutableFile().SetFile(cstr, false); 87 88 if (!(match_info_ptr == NULL || 89 NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(), 90 match_info_ptr->GetNameMatchType(), 91 match_info_ptr->GetProcessInfo().GetName()))) 92 return false; 93 94 Args &proc_args = process_info.GetArguments(); 95 while (1) 96 { 97 const uint8_t *p = data.PeekData(offset, 1); 98 while ((p != NULL) && (*p == '\0') && offset < arg_data_size) 99 { 100 ++offset; 101 p = data.PeekData(offset, 1); 102 } 103 if (p == NULL || offset >= arg_data_size) 104 return true; 105 106 cstr = data.GetCStr(&offset); 107 if (cstr) 108 proc_args.AppendArgument(cstr); 109 else 110 return true; 111 } 112 } 113 } 114 } 115 return false; 116 } 117 118 static bool 119 GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info) 120 { 121 if (process_info.ProcessIDIsValid()) 122 { 123 process_info.GetArchitecture() = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); 124 return true; 125 } 126 process_info.GetArchitecture().Clear(); 127 return false; 128 } 129 130 static bool 131 GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) 132 { 133 struct kinfo_proc proc_kinfo; 134 size_t proc_kinfo_size; 135 136 if (process_info.ProcessIDIsValid()) 137 { 138 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, 139 (int)process_info.GetProcessID() }; 140 proc_kinfo_size = sizeof(struct kinfo_proc); 141 142 if (::sysctl (mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) 143 { 144 if (proc_kinfo_size > 0) 145 { 146 process_info.SetParentProcessID (proc_kinfo.ki_ppid); 147 process_info.SetUserID (proc_kinfo.ki_ruid); 148 process_info.SetGroupID (proc_kinfo.ki_rgid); 149 process_info.SetEffectiveUserID (proc_kinfo.ki_uid); 150 if (proc_kinfo.ki_ngroups > 0) 151 process_info.SetEffectiveGroupID (proc_kinfo.ki_groups[0]); 152 else 153 process_info.SetEffectiveGroupID (UINT32_MAX); 154 return true; 155 } 156 } 157 } 158 process_info.SetParentProcessID (LLDB_INVALID_PROCESS_ID); 159 process_info.SetUserID (UINT32_MAX); 160 process_info.SetGroupID (UINT32_MAX); 161 process_info.SetEffectiveUserID (UINT32_MAX); 162 process_info.SetEffectiveGroupID (UINT32_MAX); 163 return false; 164 } 165 166 uint32_t 167 Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) 168 { 169 std::vector<struct kinfo_proc> kinfos; 170 171 int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; 172 173 size_t pid_data_size = 0; 174 if (::sysctl (mib, 3, NULL, &pid_data_size, NULL, 0) != 0) 175 return 0; 176 177 // Add a few extra in case a few more show up 178 const size_t estimated_pid_count = (pid_data_size / sizeof(struct kinfo_proc)) + 10; 179 180 kinfos.resize (estimated_pid_count); 181 pid_data_size = kinfos.size() * sizeof(struct kinfo_proc); 182 183 if (::sysctl (mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0) 184 return 0; 185 186 const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc)); 187 188 bool all_users = match_info.GetMatchAllUsers(); 189 const ::pid_t our_pid = getpid(); 190 const uid_t our_uid = getuid(); 191 for (size_t i = 0; i < actual_pid_count; i++) 192 { 193 const struct kinfo_proc &kinfo = kinfos[i]; 194 const bool kinfo_user_matches = (all_users || 195 (kinfo.ki_ruid == our_uid) || 196 // Special case, if lldb is being run as root we can attach to anything. 197 (our_uid == 0) 198 ); 199 200 if (kinfo_user_matches == false || // Make sure the user is acceptable 201 kinfo.ki_pid == our_pid || // Skip this process 202 kinfo.ki_pid == 0 || // Skip kernel (kernel pid is zero) 203 kinfo.ki_stat == SZOMB || // Zombies are bad, they like brains... 204 kinfo.ki_flag & P_TRACED || // Being debugged? 205 kinfo.ki_flag & P_WEXIT) // Working on exiting 206 continue; 207 208 // Every thread is a process in FreeBSD, but all the threads of a single process 209 // have the same pid. Do not store the process info in the result list if a process 210 // with given identifier is already registered there. 211 bool already_registered = false; 212 for (uint32_t pi = 0; 213 !already_registered && 214 (const int)kinfo.ki_numthreads > 1 && 215 pi < (const uint32_t)process_infos.GetSize(); pi++) 216 already_registered = (process_infos.GetProcessIDAtIndex(pi) == (uint32_t)kinfo.ki_pid); 217 218 if (already_registered) 219 continue; 220 221 ProcessInstanceInfo process_info; 222 process_info.SetProcessID (kinfo.ki_pid); 223 process_info.SetParentProcessID (kinfo.ki_ppid); 224 process_info.SetUserID (kinfo.ki_ruid); 225 process_info.SetGroupID (kinfo.ki_rgid); 226 process_info.SetEffectiveUserID (kinfo.ki_svuid); 227 process_info.SetEffectiveGroupID (kinfo.ki_svgid); 228 229 // Make sure our info matches before we go fetch the name and cpu type 230 if (match_info.Matches (process_info) && 231 GetFreeBSDProcessArgs (&match_info, process_info)) 232 { 233 GetFreeBSDProcessCPUType (process_info); 234 if (match_info.Matches (process_info)) 235 process_infos.Append (process_info); 236 } 237 } 238 239 return process_infos.GetSize(); 240 } 241 242 bool 243 Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 244 { 245 process_info.SetProcessID(pid); 246 247 if (GetFreeBSDProcessArgs(NULL, process_info)) 248 { 249 // should use libprocstat instead of going right into sysctl? 250 GetFreeBSDProcessCPUType(process_info); 251 GetFreeBSDProcessUserAndGroup(process_info); 252 return true; 253 } 254 255 process_info.Clear(); 256 return false; 257 } 258 259 lldb::DataBufferSP 260 Host::GetAuxvData(lldb_private::Process *process) 261 { 262 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_AUXV, 0 }; 263 size_t auxv_size = AT_COUNT * sizeof(Elf_Auxinfo); 264 DataBufferSP buf_sp; 265 266 std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(auxv_size, 0)); 267 268 mib[3] = process->GetID(); 269 if (::sysctl(mib, 4, buf_ap->GetBytes(), &auxv_size, NULL, 0) == 0) { 270 buf_sp.reset(buf_ap.release()); 271 } else { 272 perror("sysctl failed on auxv"); 273 } 274 275 return buf_sp; 276 } 277 278 Error 279 Host::ShellExpandArguments (ProcessLaunchInfo &launch_info) 280 { 281 return Error("unimplemented"); 282 } 283 284