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