1 //===-- source/Host/linux/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 <sys/utsname.h> 13 #include <sys/types.h> 14 #include <sys/stat.h> 15 #include <dirent.h> 16 #include <fcntl.h> 17 #include <execinfo.h> 18 19 // C++ Includes 20 // Other libraries and framework includes 21 // Project includes 22 #include "lldb/Core/Error.h" 23 #include "lldb/Core/Log.h" 24 #include "lldb/Target/Process.h" 25 26 #include "lldb/Host/Host.h" 27 #include "lldb/Core/DataBufferHeap.h" 28 #include "lldb/Core/DataExtractor.h" 29 30 #include "lldb/Core/ModuleSpec.h" 31 #include "lldb/Symbol/ObjectFile.h" 32 #include "Plugins/Process/Linux/ProcFileReader.h" 33 34 using namespace lldb; 35 using namespace lldb_private; 36 37 typedef enum ProcessStateFlags 38 { 39 eProcessStateRunning = (1u << 0), // Running 40 eProcessStateSleeping = (1u << 1), // Sleeping in an interruptible wait 41 eProcessStateWaiting = (1u << 2), // Waiting in an uninterruptible disk sleep 42 eProcessStateZombie = (1u << 3), // Zombie 43 eProcessStateTracedOrStopped = (1u << 4), // Traced or stopped (on a signal) 44 eProcessStatePaging = (1u << 5) // Paging 45 } ProcessStateFlags; 46 47 typedef struct ProcessStatInfo 48 { 49 lldb::pid_t ppid; // Parent Process ID 50 uint32_t fProcessState; // ProcessStateFlags 51 } ProcessStatInfo; 52 53 // Get the process info with additional information from /proc/$PID/stat (like process state, and tracer pid). 54 static bool GetProcessAndStatInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info, ProcessStatInfo &stat_info, lldb::pid_t &tracerpid); 55 56 static bool 57 ReadProcPseudoFileStat (lldb::pid_t pid, ProcessStatInfo& stat_info) 58 { 59 // Read the /proc/$PID/stat file. 60 lldb::DataBufferSP buf_sp = ProcFileReader::ReadIntoDataBuffer (pid, "stat"); 61 62 // The filename of the executable is stored in parenthesis right after the pid. We look for the closing 63 // parenthesis for the filename and work from there in case the name has something funky like ')' in it. 64 const char *filename_end = strrchr ((const char *)buf_sp->GetBytes(), ')'); 65 if (filename_end) 66 { 67 char state = '\0'; 68 int ppid = LLDB_INVALID_PROCESS_ID; 69 70 // Read state and ppid. 71 sscanf (filename_end + 1, " %c %d", &state, &ppid); 72 73 stat_info.ppid = ppid; 74 75 switch (state) 76 { 77 case 'R': 78 stat_info.fProcessState |= eProcessStateRunning; 79 break; 80 case 'S': 81 stat_info.fProcessState |= eProcessStateSleeping; 82 break; 83 case 'D': 84 stat_info.fProcessState |= eProcessStateWaiting; 85 break; 86 case 'Z': 87 stat_info.fProcessState |= eProcessStateZombie; 88 break; 89 case 'T': 90 stat_info.fProcessState |= eProcessStateTracedOrStopped; 91 break; 92 case 'W': 93 stat_info.fProcessState |= eProcessStatePaging; 94 break; 95 } 96 97 return true; 98 } 99 100 return false; 101 } 102 103 static void 104 GetLinuxProcessUserAndGroup (lldb::pid_t pid, ProcessInstanceInfo &process_info, lldb::pid_t &tracerpid) 105 { 106 tracerpid = 0; 107 uint32_t rUid = UINT32_MAX; // Real User ID 108 uint32_t eUid = UINT32_MAX; // Effective User ID 109 uint32_t rGid = UINT32_MAX; // Real Group ID 110 uint32_t eGid = UINT32_MAX; // Effective Group ID 111 112 // Read the /proc/$PID/status file and parse the Uid:, Gid:, and TracerPid: fields. 113 lldb::DataBufferSP buf_sp = ProcFileReader::ReadIntoDataBuffer (pid, "status"); 114 115 static const char uid_token[] = "Uid:"; 116 char *buf_uid = strstr ((char *)buf_sp->GetBytes(), uid_token); 117 if (buf_uid) 118 { 119 // Real, effective, saved set, and file system UIDs. Read the first two. 120 buf_uid += sizeof(uid_token); 121 rUid = strtol (buf_uid, &buf_uid, 10); 122 eUid = strtol (buf_uid, &buf_uid, 10); 123 } 124 125 static const char gid_token[] = "Gid:"; 126 char *buf_gid = strstr ((char *)buf_sp->GetBytes(), gid_token); 127 if (buf_gid) 128 { 129 // Real, effective, saved set, and file system GIDs. Read the first two. 130 buf_gid += sizeof(gid_token); 131 rGid = strtol (buf_gid, &buf_gid, 10); 132 eGid = strtol (buf_gid, &buf_gid, 10); 133 } 134 135 static const char tracerpid_token[] = "TracerPid:"; 136 char *buf_tracerpid = strstr((char *)buf_sp->GetBytes(), tracerpid_token); 137 if (buf_tracerpid) 138 { 139 // Tracer PID. 0 if we're not being debugged. 140 buf_tracerpid += sizeof(tracerpid_token); 141 tracerpid = strtol (buf_tracerpid, &buf_tracerpid, 10); 142 } 143 144 process_info.SetUserID (rUid); 145 process_info.SetEffectiveUserID (eUid); 146 process_info.SetGroupID (rGid); 147 process_info.SetEffectiveGroupID (eGid); 148 } 149 150 bool 151 Host::GetOSVersion(uint32_t &major, 152 uint32_t &minor, 153 uint32_t &update) 154 { 155 struct utsname un; 156 int status; 157 158 if (uname(&un)) 159 return false; 160 161 status = sscanf(un.release, "%u.%u.%u", &major, &minor, &update); 162 if (status == 3) 163 return true; 164 165 // Some kernels omit the update version, so try looking for just "X.Y" and 166 // set update to 0. 167 update = 0; 168 status = sscanf(un.release, "%u.%u", &major, &minor); 169 return status == 2; 170 } 171 172 lldb::DataBufferSP 173 Host::GetAuxvData(lldb_private::Process *process) 174 { 175 return ProcFileReader::ReadIntoDataBuffer (process->GetID(), "auxv"); 176 } 177 178 lldb::DataBufferSP 179 Host::GetAuxvData (lldb::pid_t pid) 180 { 181 return ProcFileReader::ReadIntoDataBuffer (pid, "auxv"); 182 } 183 184 static bool 185 IsDirNumeric(const char *dname) 186 { 187 for (; *dname; dname++) 188 { 189 if (!isdigit (*dname)) 190 return false; 191 } 192 return true; 193 } 194 195 uint32_t 196 Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) 197 { 198 static const char procdir[] = "/proc/"; 199 200 DIR *dirproc = opendir (procdir); 201 if (dirproc) 202 { 203 struct dirent *direntry = NULL; 204 const uid_t our_uid = getuid(); 205 const lldb::pid_t our_pid = getpid(); 206 bool all_users = match_info.GetMatchAllUsers(); 207 208 while ((direntry = readdir (dirproc)) != NULL) 209 { 210 if (direntry->d_type != DT_DIR || !IsDirNumeric (direntry->d_name)) 211 continue; 212 213 lldb::pid_t pid = atoi (direntry->d_name); 214 215 // Skip this process. 216 if (pid == our_pid) 217 continue; 218 219 lldb::pid_t tracerpid; 220 ProcessStatInfo stat_info; 221 ProcessInstanceInfo process_info; 222 223 if (!GetProcessAndStatInfo (pid, process_info, stat_info, tracerpid)) 224 continue; 225 226 // Skip if process is being debugged. 227 if (tracerpid != 0) 228 continue; 229 230 // Skip zombies. 231 if (stat_info.fProcessState & eProcessStateZombie) 232 continue; 233 234 // Check for user match if we're not matching all users and not running as root. 235 if (!all_users && (our_uid != 0) && (process_info.GetUserID() != our_uid)) 236 continue; 237 238 if (match_info.Matches (process_info)) 239 { 240 process_infos.Append (process_info); 241 } 242 } 243 244 closedir (dirproc); 245 } 246 247 return process_infos.GetSize(); 248 } 249 250 bool 251 Host::FindProcessThreads (const lldb::pid_t pid, TidMap &tids_to_attach) 252 { 253 bool tids_changed = false; 254 static const char procdir[] = "/proc/"; 255 static const char taskdir[] = "/task/"; 256 std::string process_task_dir = procdir + std::to_string(pid) + taskdir; 257 DIR *dirproc = opendir (process_task_dir.c_str()); 258 259 if (dirproc) 260 { 261 struct dirent *direntry = NULL; 262 while ((direntry = readdir (dirproc)) != NULL) 263 { 264 if (direntry->d_type != DT_DIR || !IsDirNumeric (direntry->d_name)) 265 continue; 266 267 lldb::tid_t tid = atoi(direntry->d_name); 268 TidMap::iterator it = tids_to_attach.find(tid); 269 if (it == tids_to_attach.end()) 270 { 271 tids_to_attach.insert(TidPair(tid, false)); 272 tids_changed = true; 273 } 274 } 275 closedir (dirproc); 276 } 277 278 return tids_changed; 279 } 280 281 static bool 282 GetELFProcessCPUType (const char *exe_path, ProcessInstanceInfo &process_info) 283 { 284 // Clear the architecture. 285 process_info.GetArchitecture().Clear(); 286 287 ModuleSpecList specs; 288 FileSpec filespec (exe_path, false); 289 const size_t num_specs = ObjectFile::GetModuleSpecifications (filespec, 0, 0, specs); 290 // GetModuleSpecifications() could fail if the executable has been deleted or is locked. 291 // But it shouldn't return more than 1 architecture. 292 assert(num_specs <= 1 && "Linux plugin supports only a single architecture"); 293 if (num_specs == 1) 294 { 295 ModuleSpec module_spec; 296 if (specs.GetModuleSpecAtIndex (0, module_spec) && module_spec.GetArchitecture().IsValid()) 297 { 298 process_info.GetArchitecture () = module_spec.GetArchitecture(); 299 return true; 300 } 301 } 302 return false; 303 } 304 305 static bool 306 GetProcessAndStatInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info, ProcessStatInfo &stat_info, lldb::pid_t &tracerpid) 307 { 308 tracerpid = 0; 309 process_info.Clear(); 310 ::memset (&stat_info, 0, sizeof(stat_info)); 311 stat_info.ppid = LLDB_INVALID_PROCESS_ID; 312 313 // Use special code here because proc/[pid]/exe is a symbolic link. 314 char link_path[PATH_MAX]; 315 char exe_path[PATH_MAX] = ""; 316 if (snprintf (link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", pid) <= 0) 317 return false; 318 319 ssize_t len = readlink (link_path, exe_path, sizeof(exe_path) - 1); 320 if (len <= 0) 321 return false; 322 323 // readlink does not append a null byte. 324 exe_path[len] = 0; 325 326 // If the binary has been deleted, the link name has " (deleted)" appended. 327 // Remove if there. 328 static const ssize_t deleted_len = strlen(" (deleted)"); 329 if (len > deleted_len && 330 !strcmp(exe_path + len - deleted_len, " (deleted)")) 331 { 332 exe_path[len - deleted_len] = 0; 333 } 334 else 335 { 336 GetELFProcessCPUType (exe_path, process_info); 337 } 338 339 process_info.SetProcessID(pid); 340 process_info.GetExecutableFile().SetFile(exe_path, false); 341 342 lldb::DataBufferSP buf_sp; 343 344 // Get the process environment. 345 buf_sp = ProcFileReader::ReadIntoDataBuffer(pid, "environ"); 346 Args &info_env = process_info.GetEnvironmentEntries(); 347 char *next_var = (char *)buf_sp->GetBytes(); 348 char *end_buf = next_var + buf_sp->GetByteSize(); 349 while (next_var < end_buf && 0 != *next_var) 350 { 351 info_env.AppendArgument(next_var); 352 next_var += strlen(next_var) + 1; 353 } 354 355 // Get the command line used to start the process. 356 buf_sp = ProcFileReader::ReadIntoDataBuffer(pid, "cmdline"); 357 358 // Grab Arg0 first, if there is one. 359 char *cmd = (char *)buf_sp->GetBytes(); 360 if (cmd) 361 { 362 process_info.SetArg0(cmd); 363 364 // Now process any remaining arguments. 365 Args &info_args = process_info.GetArguments(); 366 char *next_arg = cmd + strlen(cmd) + 1; 367 end_buf = cmd + buf_sp->GetByteSize(); 368 while (next_arg < end_buf && 0 != *next_arg) 369 { 370 info_args.AppendArgument(next_arg); 371 next_arg += strlen(next_arg) + 1; 372 } 373 } 374 375 // Read /proc/$PID/stat to get our parent pid. 376 if (ReadProcPseudoFileStat (pid, stat_info)) 377 { 378 process_info.SetParentProcessID (stat_info.ppid); 379 } 380 381 // Get User and Group IDs and get tracer pid. 382 GetLinuxProcessUserAndGroup (pid, process_info, tracerpid); 383 384 return true; 385 } 386 387 bool 388 Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 389 { 390 lldb::pid_t tracerpid; 391 ProcessStatInfo stat_info; 392 393 return GetProcessAndStatInfo (pid, process_info, stat_info, tracerpid); 394 } 395 396 void 397 Host::ThreadCreated (const char *thread_name) 398 { 399 if (!Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name)) 400 { 401 Host::SetShortThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name, 16); 402 } 403 } 404 405 std::string 406 Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid) 407 { 408 assert(pid != LLDB_INVALID_PROCESS_ID); 409 assert(tid != LLDB_INVALID_THREAD_ID); 410 411 // Read /proc/$TID/comm file. 412 lldb::DataBufferSP buf_sp = ProcFileReader::ReadIntoDataBuffer (tid, "comm"); 413 const char *comm_str = (const char *)buf_sp->GetBytes(); 414 const char *cr_str = ::strchr(comm_str, '\n'); 415 size_t length = cr_str ? (cr_str - comm_str) : strlen(comm_str); 416 417 std::string thread_name(comm_str, length); 418 return thread_name; 419 } 420 421 void 422 Host::Backtrace (Stream &strm, uint32_t max_frames) 423 { 424 if (max_frames > 0) 425 { 426 std::vector<void *> frame_buffer (max_frames, NULL); 427 int num_frames = ::backtrace (&frame_buffer[0], frame_buffer.size()); 428 char** strs = ::backtrace_symbols (&frame_buffer[0], num_frames); 429 if (strs) 430 { 431 // Start at 1 to skip the "Host::Backtrace" frame 432 for (int i = 1; i < num_frames; ++i) 433 strm.Printf("%s\n", strs[i]); 434 ::free (strs); 435 } 436 } 437 } 438 439 size_t 440 Host::GetEnvironment (StringList &env) 441 { 442 char **host_env = environ; 443 char *env_entry; 444 size_t i; 445 for (i=0; (env_entry = host_env[i]) != NULL; ++i) 446 env.AppendString(env_entry); 447 return i; 448 } 449 450 const ConstString & 451 Host::GetDistributionId () 452 { 453 // Try to run 'lbs_release -i', and use that response 454 // for the distribution id. 455 456 static bool s_evaluated; 457 static ConstString s_distribution_id; 458 459 if (!s_evaluated) 460 { 461 s_evaluated = true; 462 463 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST)); 464 if (log) 465 log->Printf ("attempting to determine Linux distribution..."); 466 467 // check if the lsb_release command exists at one of the 468 // following paths 469 const char *const exe_paths[] = { 470 "/bin/lsb_release", 471 "/usr/bin/lsb_release" 472 }; 473 474 for (size_t exe_index = 0; 475 exe_index < sizeof (exe_paths) / sizeof (exe_paths[0]); 476 ++exe_index) 477 { 478 const char *const get_distribution_info_exe = exe_paths[exe_index]; 479 if (access (get_distribution_info_exe, F_OK)) 480 { 481 // this exe doesn't exist, move on to next exe 482 if (log) 483 log->Printf ("executable doesn't exist: %s", 484 get_distribution_info_exe); 485 continue; 486 } 487 488 // execute the distribution-retrieval command, read output 489 std::string get_distribution_id_command (get_distribution_info_exe); 490 get_distribution_id_command += " -i"; 491 492 FILE *file = popen (get_distribution_id_command.c_str (), "r"); 493 if (!file) 494 { 495 if (log) 496 log->Printf ( 497 "failed to run command: \"%s\", cannot retrieve " 498 "platform information", 499 get_distribution_id_command.c_str ()); 500 return s_distribution_id; 501 } 502 503 // retrieve the distribution id string. 504 char distribution_id[256] = { '\0' }; 505 if (fgets (distribution_id, sizeof (distribution_id) - 1, file) 506 != NULL) 507 { 508 if (log) 509 log->Printf ("distribution id command returned \"%s\"", 510 distribution_id); 511 512 const char *const distributor_id_key = "Distributor ID:\t"; 513 if (strstr (distribution_id, distributor_id_key)) 514 { 515 // strip newlines 516 std::string id_string (distribution_id + 517 strlen (distributor_id_key)); 518 id_string.erase( 519 std::remove ( 520 id_string.begin (), 521 id_string.end (), 522 '\n'), 523 id_string.end ()); 524 525 // lower case it and convert whitespace to underscores 526 std::transform ( 527 id_string.begin(), 528 id_string.end (), 529 id_string.begin (), 530 [] (char ch) 531 { return tolower ( isspace (ch) ? '_' : ch ); }); 532 533 s_distribution_id.SetCString (id_string.c_str ()); 534 if (log) 535 log->Printf ("distribution id set to \"%s\"", 536 s_distribution_id.GetCString ()); 537 } 538 else 539 { 540 if (log) 541 log->Printf ("failed to find \"%s\" field in \"%s\"", 542 distributor_id_key, distribution_id); 543 } 544 } 545 else 546 { 547 if (log) 548 log->Printf ( 549 "failed to retrieve distribution id, \"%s\" returned no" 550 " lines", get_distribution_id_command.c_str ()); 551 } 552 553 // clean up the file 554 pclose(file); 555 } 556 } 557 558 return s_distribution_id; 559 } 560