1 //===-- TargetList.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 #include "lldb/lldb-python.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Core/Broadcaster.h" 17 #include "lldb/Core/Debugger.h" 18 #include "lldb/Core/Event.h" 19 #include "lldb/Core/Module.h" 20 #include "lldb/Core/ModuleSpec.h" 21 #include "lldb/Core/State.h" 22 #include "lldb/Core/Timer.h" 23 #include "lldb/Host/Host.h" 24 #include "lldb/Interpreter/CommandInterpreter.h" 25 #include "lldb/Interpreter/OptionGroupPlatform.h" 26 #include "lldb/Symbol/ObjectFile.h" 27 #include "lldb/Target/Platform.h" 28 #include "lldb/Target/Process.h" 29 #include "lldb/Target/TargetList.h" 30 31 #include "llvm/ADT/SmallString.h" 32 33 using namespace lldb; 34 using namespace lldb_private; 35 36 ConstString & 37 TargetList::GetStaticBroadcasterClass () 38 { 39 static ConstString class_name ("lldb.targetList"); 40 return class_name; 41 } 42 43 //---------------------------------------------------------------------- 44 // TargetList constructor 45 //---------------------------------------------------------------------- 46 TargetList::TargetList(Debugger &debugger) : 47 Broadcaster(&debugger, TargetList::GetStaticBroadcasterClass().AsCString()), 48 m_target_list(), 49 m_target_list_mutex (Mutex::eMutexTypeRecursive), 50 m_selected_target_idx (0) 51 { 52 CheckInWithManager(); 53 } 54 55 //---------------------------------------------------------------------- 56 // Destructor 57 //---------------------------------------------------------------------- 58 TargetList::~TargetList() 59 { 60 Mutex::Locker locker(m_target_list_mutex); 61 m_target_list.clear(); 62 } 63 64 Error 65 TargetList::CreateTarget (Debugger &debugger, 66 const char *user_exe_path, 67 const char *triple_cstr, 68 bool get_dependent_files, 69 const OptionGroupPlatform *platform_options, 70 TargetSP &target_sp) 71 { 72 Error error; 73 PlatformSP platform_sp; 74 75 // This is purposely left empty unless it is specified by triple_cstr. 76 // If not initialized via triple_cstr, then the currently selected platform 77 // will set the architecture correctly. 78 const ArchSpec arch(triple_cstr); 79 if (triple_cstr && triple_cstr[0]) 80 { 81 if (!arch.IsValid()) 82 { 83 error.SetErrorStringWithFormat("invalid triple '%s'", triple_cstr); 84 return error; 85 } 86 } 87 88 ArchSpec platform_arch(arch); 89 90 bool prefer_platform_arch = false; 91 92 if (user_exe_path && user_exe_path[0]) 93 { 94 ModuleSpecList module_specs; 95 ModuleSpec module_spec; 96 module_spec.GetFileSpec().SetFile(user_exe_path, true); 97 98 // Resolve the executable in case we are given a path to a application bundle 99 // like a .app bundle on MacOSX 100 Host::ResolveExecutableInBundle (module_spec.GetFileSpec()); 101 102 lldb::offset_t file_offset = 0; 103 lldb::offset_t file_size = 0; 104 const size_t num_specs = ObjectFile::GetModuleSpecifications (module_spec.GetFileSpec(), file_offset, file_size, module_specs); 105 if (num_specs > 0) 106 { 107 ModuleSpec matching_module_spec; 108 109 if (num_specs == 1) 110 { 111 if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec)) 112 { 113 if (platform_arch.IsValid()) 114 { 115 if (platform_arch.IsCompatibleMatch(matching_module_spec.GetArchitecture())) 116 { 117 // If the OS or vendor weren't specified, then adopt the module's 118 // architecture so that the platform matching can be more accurate 119 if (!platform_arch.TripleOSWasSpecified() || !platform_arch.TripleVendorWasSpecified()) 120 { 121 prefer_platform_arch = true; 122 platform_arch = matching_module_spec.GetArchitecture(); 123 } 124 } 125 else 126 { 127 error.SetErrorStringWithFormat("the specified architecture '%s' is not compatible with '%s' in '%s'", 128 platform_arch.GetTriple().str().c_str(), 129 matching_module_spec.GetArchitecture().GetTriple().str().c_str(), 130 module_spec.GetFileSpec().GetPath().c_str()); 131 return error; 132 } 133 } 134 else 135 { 136 // Only one arch and none was specified 137 prefer_platform_arch = true; 138 platform_arch = matching_module_spec.GetArchitecture(); 139 } 140 } 141 } 142 else 143 { 144 if (arch.IsValid()) 145 { 146 module_spec.GetArchitecture() = arch; 147 if (module_specs.FindMatchingModuleSpec(module_spec, matching_module_spec)) 148 { 149 prefer_platform_arch = true; 150 platform_arch = matching_module_spec.GetArchitecture(); 151 } 152 } 153 } 154 } 155 } 156 157 CommandInterpreter &interpreter = debugger.GetCommandInterpreter(); 158 if (platform_options) 159 { 160 if (platform_options->PlatformWasSpecified ()) 161 { 162 const bool select_platform = true; 163 platform_sp = platform_options->CreatePlatformWithOptions (interpreter, 164 arch, 165 select_platform, 166 error, 167 platform_arch); 168 if (!platform_sp) 169 return error; 170 } 171 } 172 173 if (!platform_sp) 174 { 175 // Get the current platform and make sure it is compatible with the 176 // current architecture if we have a valid architecture. 177 platform_sp = debugger.GetPlatformList().GetSelectedPlatform (); 178 179 if (!prefer_platform_arch && arch.IsValid()) 180 { 181 if (!platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) 182 platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch); 183 } 184 else if (platform_arch.IsValid()) 185 { 186 // if "arch" isn't valid, yet "platform_arch" is, it means we have an executable file with 187 // a single architecture which should be used 188 ArchSpec fixed_platform_arch; 189 if (!platform_sp->IsCompatibleArchitecture(platform_arch, false, &fixed_platform_arch)) 190 platform_sp = Platform::GetPlatformForArchitecture(platform_arch, &fixed_platform_arch); 191 } 192 } 193 194 if (!platform_arch.IsValid()) 195 platform_arch = arch; 196 197 error = TargetList::CreateTarget (debugger, 198 user_exe_path, 199 platform_arch, 200 get_dependent_files, 201 platform_sp, 202 target_sp); 203 return error; 204 } 205 206 Error 207 TargetList::CreateTarget (Debugger &debugger, 208 const char *user_exe_path, 209 const ArchSpec& specified_arch, 210 bool get_dependent_files, 211 PlatformSP &platform_sp, 212 TargetSP &target_sp) 213 { 214 Timer scoped_timer (__PRETTY_FUNCTION__, 215 "TargetList::CreateTarget (file = '%s', arch = '%s')", 216 user_exe_path, 217 specified_arch.GetArchitectureName()); 218 Error error; 219 220 ArchSpec arch(specified_arch); 221 222 if (platform_sp) 223 { 224 if (arch.IsValid()) 225 { 226 if (!platform_sp->IsCompatibleArchitecture(arch, false, NULL)) 227 platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch); 228 } 229 } 230 else if (arch.IsValid()) 231 { 232 platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch); 233 } 234 235 if (!platform_sp) 236 platform_sp = debugger.GetPlatformList().GetSelectedPlatform(); 237 238 if (!arch.IsValid()) 239 arch = specified_arch; 240 241 FileSpec file (user_exe_path, false); 242 if (!file.Exists() && user_exe_path && user_exe_path[0] == '~') 243 { 244 // we want to expand the tilde but we don't want to resolve any symbolic links 245 // so we can't use the FileSpec constructor's resolve flag 246 llvm::SmallString<64> unglobbed_path(user_exe_path); 247 FileSpec::ResolveUsername(unglobbed_path); 248 249 if (unglobbed_path.empty()) 250 file = FileSpec(user_exe_path, false); 251 else 252 file = FileSpec(unglobbed_path.c_str(), false); 253 } 254 255 bool user_exe_path_is_bundle = false; 256 char resolved_bundle_exe_path[PATH_MAX]; 257 resolved_bundle_exe_path[0] = '\0'; 258 if (file) 259 { 260 if (file.GetFileType() == FileSpec::eFileTypeDirectory) 261 user_exe_path_is_bundle = true; 262 263 if (file.IsRelativeToCurrentWorkingDirectory()) 264 { 265 // Ignore paths that start with "./" and "../" 266 if (!((user_exe_path[0] == '.' && user_exe_path[1] == '/') || 267 (user_exe_path[0] == '.' && user_exe_path[1] == '.' && user_exe_path[2] == '/'))) 268 { 269 char cwd[PATH_MAX]; 270 if (getcwd (cwd, sizeof(cwd))) 271 { 272 std::string cwd_user_exe_path (cwd); 273 cwd_user_exe_path += '/'; 274 cwd_user_exe_path += user_exe_path; 275 FileSpec cwd_file (cwd_user_exe_path.c_str(), false); 276 if (cwd_file.Exists()) 277 file = cwd_file; 278 } 279 } 280 } 281 282 ModuleSP exe_module_sp; 283 if (platform_sp) 284 { 285 FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); 286 error = platform_sp->ResolveExecutable (file, 287 arch, 288 exe_module_sp, 289 executable_search_paths.GetSize() ? &executable_search_paths : NULL); 290 } 291 292 if (error.Success() && exe_module_sp) 293 { 294 if (exe_module_sp->GetObjectFile() == NULL) 295 { 296 if (arch.IsValid()) 297 { 298 error.SetErrorStringWithFormat("\"%s\" doesn't contain architecture %s", 299 file.GetPath().c_str(), 300 arch.GetArchitectureName()); 301 } 302 else 303 { 304 error.SetErrorStringWithFormat("unsupported file type \"%s\"", 305 file.GetPath().c_str()); 306 } 307 return error; 308 } 309 target_sp.reset(new Target(debugger, arch, platform_sp)); 310 target_sp->SetExecutableModule (exe_module_sp, get_dependent_files); 311 if (user_exe_path_is_bundle) 312 exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path, sizeof(resolved_bundle_exe_path)); 313 } 314 } 315 else 316 { 317 // No file was specified, just create an empty target with any arch 318 // if a valid arch was specified 319 target_sp.reset(new Target(debugger, arch, platform_sp)); 320 } 321 322 if (target_sp) 323 { 324 // Set argv0 with what the user typed, unless the user specified a 325 // directory. If the user specified a directory, then it is probably a 326 // bundle that was resolved and we need to use the resolved bundle path 327 if (user_exe_path) 328 { 329 // Use exactly what the user typed as the first argument when we exec or posix_spawn 330 if (user_exe_path_is_bundle && resolved_bundle_exe_path[0]) 331 { 332 target_sp->SetArg0 (resolved_bundle_exe_path); 333 } 334 else 335 { 336 // Use resolved path 337 target_sp->SetArg0 (file.GetPath().c_str()); 338 } 339 } 340 if (file.GetDirectory()) 341 { 342 FileSpec file_dir; 343 file_dir.GetDirectory() = file.GetDirectory(); 344 target_sp->GetExecutableSearchPaths ().Append (file_dir); 345 } 346 Mutex::Locker locker(m_target_list_mutex); 347 m_selected_target_idx = m_target_list.size(); 348 m_target_list.push_back(target_sp); 349 350 351 } 352 353 return error; 354 } 355 356 bool 357 TargetList::DeleteTarget (TargetSP &target_sp) 358 { 359 Mutex::Locker locker(m_target_list_mutex); 360 collection::iterator pos, end = m_target_list.end(); 361 362 for (pos = m_target_list.begin(); pos != end; ++pos) 363 { 364 if (pos->get() == target_sp.get()) 365 { 366 m_target_list.erase(pos); 367 return true; 368 } 369 } 370 return false; 371 } 372 373 374 TargetSP 375 TargetList::FindTargetWithExecutableAndArchitecture 376 ( 377 const FileSpec &exe_file_spec, 378 const ArchSpec *exe_arch_ptr 379 ) const 380 { 381 Mutex::Locker locker (m_target_list_mutex); 382 TargetSP target_sp; 383 bool full_match = (bool)exe_file_spec.GetDirectory(); 384 385 collection::const_iterator pos, end = m_target_list.end(); 386 for (pos = m_target_list.begin(); pos != end; ++pos) 387 { 388 Module *exe_module = (*pos)->GetExecutableModulePointer(); 389 390 if (exe_module) 391 { 392 if (FileSpec::Equal (exe_file_spec, exe_module->GetFileSpec(), full_match)) 393 { 394 if (exe_arch_ptr) 395 { 396 if (!exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture())) 397 continue; 398 } 399 target_sp = *pos; 400 break; 401 } 402 } 403 } 404 return target_sp; 405 } 406 407 TargetSP 408 TargetList::FindTargetWithProcessID (lldb::pid_t pid) const 409 { 410 Mutex::Locker locker(m_target_list_mutex); 411 TargetSP target_sp; 412 collection::const_iterator pos, end = m_target_list.end(); 413 for (pos = m_target_list.begin(); pos != end; ++pos) 414 { 415 Process* process = (*pos)->GetProcessSP().get(); 416 if (process && process->GetID() == pid) 417 { 418 target_sp = *pos; 419 break; 420 } 421 } 422 return target_sp; 423 } 424 425 426 TargetSP 427 TargetList::FindTargetWithProcess (Process *process) const 428 { 429 TargetSP target_sp; 430 if (process) 431 { 432 Mutex::Locker locker(m_target_list_mutex); 433 collection::const_iterator pos, end = m_target_list.end(); 434 for (pos = m_target_list.begin(); pos != end; ++pos) 435 { 436 if (process == (*pos)->GetProcessSP().get()) 437 { 438 target_sp = *pos; 439 break; 440 } 441 } 442 } 443 return target_sp; 444 } 445 446 TargetSP 447 TargetList::GetTargetSP (Target *target) const 448 { 449 TargetSP target_sp; 450 if (target) 451 { 452 Mutex::Locker locker(m_target_list_mutex); 453 collection::const_iterator pos, end = m_target_list.end(); 454 for (pos = m_target_list.begin(); pos != end; ++pos) 455 { 456 if (target == (*pos).get()) 457 { 458 target_sp = *pos; 459 break; 460 } 461 } 462 } 463 return target_sp; 464 } 465 466 uint32_t 467 TargetList::SendAsyncInterrupt (lldb::pid_t pid) 468 { 469 uint32_t num_async_interrupts_sent = 0; 470 471 if (pid != LLDB_INVALID_PROCESS_ID) 472 { 473 TargetSP target_sp(FindTargetWithProcessID (pid)); 474 if (target_sp.get()) 475 { 476 Process* process = target_sp->GetProcessSP().get(); 477 if (process) 478 { 479 process->SendAsyncInterrupt(); 480 ++num_async_interrupts_sent; 481 } 482 } 483 } 484 else 485 { 486 // We don't have a valid pid to broadcast to, so broadcast to the target 487 // list's async broadcaster... 488 BroadcastEvent (Process::eBroadcastBitInterrupt, NULL); 489 } 490 491 return num_async_interrupts_sent; 492 } 493 494 uint32_t 495 TargetList::SignalIfRunning (lldb::pid_t pid, int signo) 496 { 497 uint32_t num_signals_sent = 0; 498 Process *process = NULL; 499 if (pid == LLDB_INVALID_PROCESS_ID) 500 { 501 // Signal all processes with signal 502 Mutex::Locker locker(m_target_list_mutex); 503 collection::iterator pos, end = m_target_list.end(); 504 for (pos = m_target_list.begin(); pos != end; ++pos) 505 { 506 process = (*pos)->GetProcessSP().get(); 507 if (process) 508 { 509 if (process->IsAlive()) 510 { 511 ++num_signals_sent; 512 process->Signal (signo); 513 } 514 } 515 } 516 } 517 else 518 { 519 // Signal a specific process with signal 520 TargetSP target_sp(FindTargetWithProcessID (pid)); 521 if (target_sp.get()) 522 { 523 process = target_sp->GetProcessSP().get(); 524 if (process) 525 { 526 if (process->IsAlive()) 527 { 528 ++num_signals_sent; 529 process->Signal (signo); 530 } 531 } 532 } 533 } 534 return num_signals_sent; 535 } 536 537 int 538 TargetList::GetNumTargets () const 539 { 540 Mutex::Locker locker (m_target_list_mutex); 541 return m_target_list.size(); 542 } 543 544 lldb::TargetSP 545 TargetList::GetTargetAtIndex (uint32_t idx) const 546 { 547 TargetSP target_sp; 548 Mutex::Locker locker (m_target_list_mutex); 549 if (idx < m_target_list.size()) 550 target_sp = m_target_list[idx]; 551 return target_sp; 552 } 553 554 uint32_t 555 TargetList::GetIndexOfTarget (lldb::TargetSP target_sp) const 556 { 557 Mutex::Locker locker (m_target_list_mutex); 558 size_t num_targets = m_target_list.size(); 559 for (size_t idx = 0; idx < num_targets; idx++) 560 { 561 if (target_sp == m_target_list[idx]) 562 return idx; 563 } 564 return UINT32_MAX; 565 } 566 567 uint32_t 568 TargetList::SetSelectedTarget (Target* target) 569 { 570 Mutex::Locker locker (m_target_list_mutex); 571 collection::const_iterator pos, 572 begin = m_target_list.begin(), 573 end = m_target_list.end(); 574 for (pos = begin; pos != end; ++pos) 575 { 576 if (pos->get() == target) 577 { 578 m_selected_target_idx = std::distance (begin, pos); 579 return m_selected_target_idx; 580 } 581 } 582 m_selected_target_idx = 0; 583 return m_selected_target_idx; 584 } 585 586 lldb::TargetSP 587 TargetList::GetSelectedTarget () 588 { 589 Mutex::Locker locker (m_target_list_mutex); 590 if (m_selected_target_idx >= m_target_list.size()) 591 m_selected_target_idx = 0; 592 return GetTargetAtIndex (m_selected_target_idx); 593 } 594