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