1 //===-- source/Host/linux/Host.cpp ----------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include <cerrno> 10 #include <cstdio> 11 #include <cstring> 12 #include <dirent.h> 13 #include <fcntl.h> 14 #include <optional> 15 #include <sys/stat.h> 16 #include <sys/types.h> 17 #include <sys/utsname.h> 18 #include <unistd.h> 19 20 #include "llvm/ADT/StringSwitch.h" 21 #include "llvm/Object/ELF.h" 22 #include "llvm/Support/ScopedPrinter.h" 23 24 #include "lldb/Utility/LLDBLog.h" 25 #include "lldb/Utility/Log.h" 26 #include "lldb/Utility/ProcessInfo.h" 27 #include "lldb/Utility/Status.h" 28 29 #include "lldb/Host/FileSystem.h" 30 #include "lldb/Host/Host.h" 31 #include "lldb/Host/HostInfo.h" 32 #include "lldb/Host/linux/Host.h" 33 #include "lldb/Host/linux/Support.h" 34 #include "lldb/Utility/DataExtractor.h" 35 36 using namespace lldb; 37 using namespace lldb_private; 38 39 namespace { 40 41 enum class ProcessState { 42 Unknown, 43 Dead, 44 DiskSleep, 45 Idle, 46 Paging, 47 Parked, 48 Running, 49 Sleeping, 50 TracedOrStopped, 51 Zombie, 52 }; 53 54 struct StatFields { 55 ::pid_t pid = LLDB_INVALID_PROCESS_ID; 56 // comm 57 char state; 58 ::pid_t ppid = LLDB_INVALID_PROCESS_ID; 59 ::pid_t pgrp = LLDB_INVALID_PROCESS_ID; 60 ::pid_t session = LLDB_INVALID_PROCESS_ID; 61 int tty_nr; 62 int tpgid; 63 unsigned flags; 64 long unsigned minflt; 65 long unsigned cminflt; 66 long unsigned majflt; 67 long unsigned cmajflt; 68 long unsigned utime; 69 long unsigned stime; 70 long cutime; 71 long cstime; 72 // In proc_pid_stat(5) this field is specified as priority 73 // but documented as realtime priority. To keep with the adopted 74 // nomenclature in ProcessInstanceInfo, we adopt the documented 75 // naming here. 76 long realtime_priority; 77 long priority; 78 // .... other things. We don't need them below 79 }; 80 } 81 82 namespace lldb_private { 83 class ProcessLaunchInfo; 84 } 85 86 static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo, 87 ProcessState &State, ::pid_t &TracerPid, 88 ::pid_t &Tgid) { 89 Log *log = GetLog(LLDBLog::Host); 90 91 auto BufferOrError = getProcFile(Pid, "stat"); 92 if (!BufferOrError) 93 return false; 94 95 llvm::StringRef Rest = BufferOrError.get()->getBuffer(); 96 if (Rest.empty()) 97 return false; 98 StatFields stat_fields; 99 if (sscanf( 100 Rest.data(), 101 "%d %*s %c %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld", 102 &stat_fields.pid, /* comm, */ &stat_fields.state, 103 &stat_fields.ppid, &stat_fields.pgrp, &stat_fields.session, 104 &stat_fields.tty_nr, &stat_fields.tpgid, &stat_fields.flags, 105 &stat_fields.minflt, &stat_fields.cminflt, &stat_fields.majflt, 106 &stat_fields.cmajflt, &stat_fields.utime, &stat_fields.stime, 107 &stat_fields.cutime, &stat_fields.cstime, 108 &stat_fields.realtime_priority, &stat_fields.priority) < 0) { 109 return false; 110 } 111 112 auto convert = [sc_clk_ticks = sysconf(_SC_CLK_TCK)](auto time_in_ticks) { 113 ProcessInstanceInfo::timespec ts; 114 if (sc_clk_ticks <= 0) { 115 return ts; 116 } 117 ts.tv_sec = time_in_ticks / sc_clk_ticks; 118 double remainder = 119 (static_cast<double>(time_in_ticks) / sc_clk_ticks) - ts.tv_sec; 120 ts.tv_usec = 121 std::chrono::microseconds{std::lround(1e+6 * remainder)}.count(); 122 return ts; 123 }; 124 125 // Priority (nice) values run from 19 to -20 inclusive (in linux). In the 126 // prpsinfo struct pr_nice is a char. 127 auto priority_value = static_cast<int8_t>( 128 (stat_fields.priority < 0 ? 0x80 : 0x00) | (stat_fields.priority & 0x7f)); 129 130 ProcessInfo.SetParentProcessID(stat_fields.ppid); 131 ProcessInfo.SetProcessGroupID(stat_fields.pgrp); 132 ProcessInfo.SetProcessSessionID(stat_fields.session); 133 ProcessInfo.SetUserTime(convert(stat_fields.utime)); 134 ProcessInfo.SetSystemTime(convert(stat_fields.stime)); 135 ProcessInfo.SetCumulativeUserTime(convert(stat_fields.cutime)); 136 ProcessInfo.SetCumulativeSystemTime(convert(stat_fields.cstime)); 137 ProcessInfo.SetPriorityValue(priority_value); 138 switch (stat_fields.state) { 139 case 'R': 140 State = ProcessState::Running; 141 break; 142 case 'S': 143 State = ProcessState::Sleeping; 144 break; 145 case 'D': 146 State = ProcessState::DiskSleep; 147 break; 148 case 'Z': 149 State = ProcessState::Zombie; 150 break; 151 case 'X': 152 State = ProcessState::Dead; 153 break; 154 case 'P': 155 State = ProcessState::Parked; 156 break; 157 case 'W': 158 State = ProcessState::Paging; 159 break; 160 case 'I': 161 State = ProcessState::Idle; 162 break; 163 case 'T': // Stopped on a signal or (before Linux 2.6.33) trace stopped 164 [[fallthrough]]; 165 case 't': 166 State = ProcessState::TracedOrStopped; 167 break; 168 default: 169 State = ProcessState::Unknown; 170 break; 171 } 172 ProcessInfo.SetIsZombie(State == ProcessState::Zombie); 173 174 if (State == ProcessState::Unknown) { 175 LLDB_LOG(log, "Unknown process state {0}", stat_fields.state); 176 } 177 178 BufferOrError = getProcFile(Pid, "status"); 179 if (!BufferOrError) 180 return false; 181 182 Rest = BufferOrError.get()->getBuffer(); 183 if (Rest.empty()) 184 return false; 185 186 while (!Rest.empty()) { 187 llvm::StringRef Line; 188 std::tie(Line, Rest) = Rest.split('\n'); 189 190 if (Line.consume_front("Gid:")) { 191 // Real, effective, saved set, and file system GIDs. Read the first two. 192 Line = Line.ltrim(); 193 uint32_t RGid, EGid; 194 Line.consumeInteger(10, RGid); 195 Line = Line.ltrim(); 196 Line.consumeInteger(10, EGid); 197 198 ProcessInfo.SetGroupID(RGid); 199 ProcessInfo.SetEffectiveGroupID(EGid); 200 } else if (Line.consume_front("Uid:")) { 201 // Real, effective, saved set, and file system UIDs. Read the first two. 202 Line = Line.ltrim(); 203 uint32_t RUid, EUid; 204 Line.consumeInteger(10, RUid); 205 Line = Line.ltrim(); 206 Line.consumeInteger(10, EUid); 207 208 ProcessInfo.SetUserID(RUid); 209 ProcessInfo.SetEffectiveUserID(EUid); 210 } else if (Line.consume_front("TracerPid:")) { 211 Line = Line.ltrim(); 212 Line.consumeInteger(10, TracerPid); 213 } else if (Line.consume_front("Tgid:")) { 214 Line = Line.ltrim(); 215 Line.consumeInteger(10, Tgid); 216 } 217 } 218 return true; 219 } 220 221 static bool IsDirNumeric(const char *dname) { 222 for (; *dname; dname++) { 223 if (!isdigit(*dname)) 224 return false; 225 } 226 return true; 227 } 228 229 static ArchSpec GetELFProcessCPUType(llvm::StringRef exe_path) { 230 Log *log = GetLog(LLDBLog::Host); 231 232 auto buffer_sp = FileSystem::Instance().CreateDataBuffer(exe_path, 0x20, 0); 233 if (!buffer_sp) 234 return ArchSpec(); 235 236 uint8_t exe_class = 237 llvm::object::getElfArchType( 238 {reinterpret_cast<const char *>(buffer_sp->GetBytes()), 239 size_t(buffer_sp->GetByteSize())}) 240 .first; 241 242 switch (exe_class) { 243 case llvm::ELF::ELFCLASS32: 244 return HostInfo::GetArchitecture(HostInfo::eArchKind32); 245 case llvm::ELF::ELFCLASS64: 246 return HostInfo::GetArchitecture(HostInfo::eArchKind64); 247 default: 248 LLDB_LOG(log, "Unknown elf class ({0}) in file {1}", exe_class, exe_path); 249 return ArchSpec(); 250 } 251 } 252 253 static void GetProcessArgs(::pid_t pid, ProcessInstanceInfo &process_info) { 254 auto BufferOrError = getProcFile(pid, "cmdline"); 255 if (!BufferOrError) 256 return; 257 std::unique_ptr<llvm::MemoryBuffer> Cmdline = std::move(*BufferOrError); 258 259 llvm::StringRef Arg0, Rest; 260 std::tie(Arg0, Rest) = Cmdline->getBuffer().split('\0'); 261 process_info.SetArg0(Arg0); 262 while (!Rest.empty()) { 263 llvm::StringRef Arg; 264 std::tie(Arg, Rest) = Rest.split('\0'); 265 process_info.GetArguments().AppendArgument(Arg); 266 } 267 } 268 269 static void GetExePathAndArch(::pid_t pid, ProcessInstanceInfo &process_info) { 270 Log *log = GetLog(LLDBLog::Process); 271 std::string ExePath(PATH_MAX, '\0'); 272 273 // We can't use getProcFile here because proc/[pid]/exe is a symbolic link. 274 llvm::SmallString<64> ProcExe; 275 (llvm::Twine("/proc/") + llvm::Twine(pid) + "/exe").toVector(ProcExe); 276 277 ssize_t len = readlink(ProcExe.c_str(), &ExePath[0], PATH_MAX); 278 if (len > 0) { 279 ExePath.resize(len); 280 } else { 281 LLDB_LOG(log, "failed to read link exe link for {0}: {1}", pid, 282 Status(errno, eErrorTypePOSIX)); 283 ExePath.resize(0); 284 } 285 // If the binary has been deleted, the link name has " (deleted)" appended. 286 // Remove if there. 287 llvm::StringRef PathRef = ExePath; 288 PathRef.consume_back(" (deleted)"); 289 290 if (!PathRef.empty()) { 291 process_info.GetExecutableFile().SetFile(PathRef, FileSpec::Style::native); 292 process_info.SetArchitecture(GetELFProcessCPUType(PathRef)); 293 } 294 } 295 296 static void GetProcessEnviron(::pid_t pid, ProcessInstanceInfo &process_info) { 297 // Get the process environment. 298 auto BufferOrError = getProcFile(pid, "environ"); 299 if (!BufferOrError) 300 return; 301 302 std::unique_ptr<llvm::MemoryBuffer> Environ = std::move(*BufferOrError); 303 llvm::StringRef Rest = Environ->getBuffer(); 304 while (!Rest.empty()) { 305 llvm::StringRef Var; 306 std::tie(Var, Rest) = Rest.split('\0'); 307 process_info.GetEnvironment().insert(Var); 308 } 309 } 310 311 static bool GetProcessAndStatInfo(::pid_t pid, 312 ProcessInstanceInfo &process_info, 313 ProcessState &State, ::pid_t &tracerpid) { 314 ::pid_t tgid; 315 tracerpid = 0; 316 process_info.Clear(); 317 318 process_info.SetProcessID(pid); 319 320 GetExePathAndArch(pid, process_info); 321 GetProcessArgs(pid, process_info); 322 GetProcessEnviron(pid, process_info); 323 324 // Get User and Group IDs and get tracer pid. 325 if (!GetStatusInfo(pid, process_info, State, tracerpid, tgid)) 326 return false; 327 328 return true; 329 } 330 331 uint32_t Host::FindProcessesImpl(const ProcessInstanceInfoMatch &match_info, 332 ProcessInstanceInfoList &process_infos) { 333 static const char procdir[] = "/proc/"; 334 335 DIR *dirproc = opendir(procdir); 336 if (dirproc) { 337 struct dirent *direntry = nullptr; 338 const uid_t our_uid = getuid(); 339 const lldb::pid_t our_pid = getpid(); 340 bool all_users = match_info.GetMatchAllUsers(); 341 342 while ((direntry = readdir(dirproc)) != nullptr) { 343 if (direntry->d_type != DT_DIR || !IsDirNumeric(direntry->d_name)) 344 continue; 345 346 lldb::pid_t pid = atoi(direntry->d_name); 347 348 // Skip this process. 349 if (pid == our_pid) 350 continue; 351 352 ::pid_t tracerpid; 353 ProcessState State; 354 ProcessInstanceInfo process_info; 355 356 if (!GetProcessAndStatInfo(pid, process_info, State, tracerpid)) 357 continue; 358 359 // Skip if process is being debugged. 360 if (tracerpid != 0) 361 continue; 362 363 if (State == ProcessState::Zombie) 364 continue; 365 366 // Check for user match if we're not matching all users and not running 367 // as root. 368 if (!all_users && (our_uid != 0) && (process_info.GetUserID() != our_uid)) 369 continue; 370 371 if (match_info.Matches(process_info)) { 372 process_infos.push_back(process_info); 373 } 374 } 375 376 closedir(dirproc); 377 } 378 379 return process_infos.size(); 380 } 381 382 bool Host::FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach) { 383 bool tids_changed = false; 384 static const char procdir[] = "/proc/"; 385 static const char taskdir[] = "/task/"; 386 std::string process_task_dir = procdir + llvm::to_string(pid) + taskdir; 387 DIR *dirproc = opendir(process_task_dir.c_str()); 388 389 if (dirproc) { 390 struct dirent *direntry = nullptr; 391 while ((direntry = readdir(dirproc)) != nullptr) { 392 if (direntry->d_type != DT_DIR || !IsDirNumeric(direntry->d_name)) 393 continue; 394 395 lldb::tid_t tid = atoi(direntry->d_name); 396 TidMap::iterator it = tids_to_attach.find(tid); 397 if (it == tids_to_attach.end()) { 398 tids_to_attach.insert(TidPair(tid, false)); 399 tids_changed = true; 400 } 401 } 402 closedir(dirproc); 403 } 404 405 return tids_changed; 406 } 407 408 bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) { 409 ::pid_t tracerpid; 410 ProcessState State; 411 return GetProcessAndStatInfo(pid, process_info, State, tracerpid); 412 } 413 414 Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { 415 return Status::FromErrorString("unimplemented"); 416 } 417 418 std::optional<lldb::pid_t> lldb_private::getPIDForTID(lldb::pid_t tid) { 419 ::pid_t tracerpid, tgid = LLDB_INVALID_PROCESS_ID; 420 ProcessInstanceInfo process_info; 421 ProcessState state; 422 423 if (!GetStatusInfo(tid, process_info, state, tracerpid, tgid) || 424 tgid == LLDB_INVALID_PROCESS_ID) 425 return std::nullopt; 426 return tgid; 427 } 428