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(), nullptr)); 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().GetCString()); 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 = Platform::GetPlatformForArchitecture(arch, &platform_arch); 262 if (platform_sp) 263 debugger.GetPlatformList().SetSelectedPlatform(platform_sp); 264 } 265 } else if (platform_arch.IsValid()) { 266 // If "arch" isn't valid, yet "platform_arch" is, it means we have an 267 // executable file with a single architecture which should be used. 268 ArchSpec fixed_platform_arch; 269 if (!platform_sp->IsCompatibleArchitecture(platform_arch, false, nullptr)) { 270 platform_sp = Platform::GetPlatformForArchitecture(platform_arch, 271 &fixed_platform_arch); 272 if (platform_sp) 273 debugger.GetPlatformList().SetSelectedPlatform(platform_sp); 274 } 275 } 276 277 if (!platform_arch.IsValid()) 278 platform_arch = arch; 279 280 return TargetList::CreateTargetInternal(debugger, user_exe_path, 281 platform_arch, load_dependent_files, 282 platform_sp, target_sp); 283 } 284 285 Status TargetList::CreateTargetInternal(Debugger &debugger, 286 llvm::StringRef user_exe_path, 287 const ArchSpec &specified_arch, 288 LoadDependentFiles load_dependent_files, 289 lldb::PlatformSP &platform_sp, 290 lldb::TargetSP &target_sp) { 291 LLDB_SCOPED_TIMERF("TargetList::CreateTarget (file = '%s', arch = '%s')", 292 user_exe_path.str().c_str(), 293 specified_arch.GetArchitectureName()); 294 Status error; 295 const bool is_dummy_target = false; 296 297 ArchSpec arch(specified_arch); 298 299 if (arch.IsValid()) { 300 if (!platform_sp || 301 !platform_sp->IsCompatibleArchitecture(arch, false, nullptr)) 302 platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch); 303 } 304 305 if (!platform_sp) 306 platform_sp = debugger.GetPlatformList().GetSelectedPlatform(); 307 308 if (!arch.IsValid()) 309 arch = specified_arch; 310 311 FileSpec file(user_exe_path); 312 if (!FileSystem::Instance().Exists(file) && user_exe_path.startswith("~")) { 313 // we want to expand the tilde but we don't want to resolve any symbolic 314 // links so we can't use the FileSpec constructor's resolve flag 315 llvm::SmallString<64> unglobbed_path; 316 StandardTildeExpressionResolver Resolver; 317 Resolver.ResolveFullPath(user_exe_path, unglobbed_path); 318 319 if (unglobbed_path.empty()) 320 file = FileSpec(user_exe_path); 321 else 322 file = FileSpec(unglobbed_path.c_str()); 323 } 324 325 bool user_exe_path_is_bundle = false; 326 char resolved_bundle_exe_path[PATH_MAX]; 327 resolved_bundle_exe_path[0] = '\0'; 328 if (file) { 329 if (FileSystem::Instance().IsDirectory(file)) 330 user_exe_path_is_bundle = true; 331 332 if (file.IsRelative() && !user_exe_path.empty()) { 333 llvm::SmallString<64> cwd; 334 if (! llvm::sys::fs::current_path(cwd)) { 335 FileSpec cwd_file(cwd.c_str()); 336 cwd_file.AppendPathComponent(file); 337 if (FileSystem::Instance().Exists(cwd_file)) 338 file = cwd_file; 339 } 340 } 341 342 ModuleSP exe_module_sp; 343 if (platform_sp) { 344 FileSpecList executable_search_paths( 345 Target::GetDefaultExecutableSearchPaths()); 346 ModuleSpec module_spec(file, arch); 347 error = platform_sp->ResolveExecutable(module_spec, exe_module_sp, 348 executable_search_paths.GetSize() 349 ? &executable_search_paths 350 : nullptr); 351 } 352 353 if (error.Success() && exe_module_sp) { 354 if (exe_module_sp->GetObjectFile() == nullptr) { 355 if (arch.IsValid()) { 356 error.SetErrorStringWithFormat( 357 "\"%s\" doesn't contain architecture %s", file.GetPath().c_str(), 358 arch.GetArchitectureName()); 359 } else { 360 error.SetErrorStringWithFormat("unsupported file type \"%s\"", 361 file.GetPath().c_str()); 362 } 363 return error; 364 } 365 target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target)); 366 target_sp->SetExecutableModule(exe_module_sp, load_dependent_files); 367 if (user_exe_path_is_bundle) 368 exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path, 369 sizeof(resolved_bundle_exe_path)); 370 if (target_sp->GetPreloadSymbols()) 371 exe_module_sp->PreloadSymbols(); 372 } 373 } else { 374 // No file was specified, just create an empty target with any arch if a 375 // valid arch was specified 376 target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target)); 377 } 378 379 if (!target_sp) 380 return error; 381 382 // Set argv0 with what the user typed, unless the user specified a 383 // directory. If the user specified a directory, then it is probably a 384 // bundle that was resolved and we need to use the resolved bundle path 385 if (!user_exe_path.empty()) { 386 // Use exactly what the user typed as the first argument when we exec or 387 // posix_spawn 388 if (user_exe_path_is_bundle && resolved_bundle_exe_path[0]) { 389 target_sp->SetArg0(resolved_bundle_exe_path); 390 } else { 391 // Use resolved path 392 target_sp->SetArg0(file.GetPath().c_str()); 393 } 394 } 395 if (file.GetDirectory()) { 396 FileSpec file_dir; 397 file_dir.GetDirectory() = file.GetDirectory(); 398 target_sp->AppendExecutableSearchPaths(file_dir); 399 } 400 401 // Now prime this from the dummy target: 402 target_sp->PrimeFromDummyTarget(debugger.GetDummyTarget()); 403 404 return error; 405 } 406 407 bool TargetList::DeleteTarget(TargetSP &target_sp) { 408 std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 409 auto it = std::find(m_target_list.begin(), m_target_list.end(), target_sp); 410 if (it == m_target_list.end()) 411 return false; 412 413 m_target_list.erase(it); 414 return true; 415 } 416 417 TargetSP TargetList::FindTargetWithExecutableAndArchitecture( 418 const FileSpec &exe_file_spec, const ArchSpec *exe_arch_ptr) const { 419 std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 420 auto it = std::find_if(m_target_list.begin(), m_target_list.end(), 421 [&exe_file_spec, exe_arch_ptr](const TargetSP &item) { 422 Module *exe_module = item->GetExecutableModulePointer(); 423 if (!exe_module || 424 !FileSpec::Match(exe_file_spec, exe_module->GetFileSpec())) 425 return false; 426 427 return !exe_arch_ptr || 428 exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture()); 429 }); 430 431 if (it != m_target_list.end()) 432 return *it; 433 434 return TargetSP(); 435 } 436 437 TargetSP TargetList::FindTargetWithProcessID(lldb::pid_t pid) const { 438 std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 439 auto it = std::find_if(m_target_list.begin(), m_target_list.end(), 440 [pid](const TargetSP &item) { 441 auto *process_ptr = item->GetProcessSP().get(); 442 return process_ptr && (process_ptr->GetID() == pid); 443 }); 444 445 if (it != m_target_list.end()) 446 return *it; 447 448 return TargetSP(); 449 } 450 451 TargetSP TargetList::FindTargetWithProcess(Process *process) const { 452 TargetSP target_sp; 453 if (!process) 454 return target_sp; 455 456 std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 457 auto it = std::find_if(m_target_list.begin(), m_target_list.end(), 458 [process](const TargetSP &item) { 459 return item->GetProcessSP().get() == process; 460 }); 461 462 if (it != m_target_list.end()) 463 target_sp = *it; 464 465 return target_sp; 466 } 467 468 TargetSP TargetList::GetTargetSP(Target *target) const { 469 TargetSP target_sp; 470 if (!target) 471 return target_sp; 472 473 std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 474 auto it = std::find_if(m_target_list.begin(), m_target_list.end(), 475 [target](const TargetSP &item) { return item.get() == target; }); 476 if (it != m_target_list.end()) 477 target_sp = *it; 478 479 return target_sp; 480 } 481 482 uint32_t TargetList::SendAsyncInterrupt(lldb::pid_t pid) { 483 uint32_t num_async_interrupts_sent = 0; 484 485 if (pid != LLDB_INVALID_PROCESS_ID) { 486 TargetSP target_sp(FindTargetWithProcessID(pid)); 487 if (target_sp) { 488 Process *process = target_sp->GetProcessSP().get(); 489 if (process) { 490 process->SendAsyncInterrupt(); 491 ++num_async_interrupts_sent; 492 } 493 } 494 } else { 495 // We don't have a valid pid to broadcast to, so broadcast to the target 496 // list's async broadcaster... 497 BroadcastEvent(Process::eBroadcastBitInterrupt, nullptr); 498 } 499 500 return num_async_interrupts_sent; 501 } 502 503 uint32_t TargetList::SignalIfRunning(lldb::pid_t pid, int signo) { 504 uint32_t num_signals_sent = 0; 505 Process *process = nullptr; 506 if (pid == LLDB_INVALID_PROCESS_ID) { 507 // Signal all processes with signal 508 std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 509 for (const auto &target_sp : m_target_list) { 510 process = target_sp->GetProcessSP().get(); 511 if (process && process->IsAlive()) { 512 ++num_signals_sent; 513 process->Signal(signo); 514 } 515 } 516 } else { 517 // Signal a specific process with signal 518 TargetSP target_sp(FindTargetWithProcessID(pid)); 519 if (target_sp) { 520 process = target_sp->GetProcessSP().get(); 521 if (process && process->IsAlive()) { 522 ++num_signals_sent; 523 process->Signal(signo); 524 } 525 } 526 } 527 return num_signals_sent; 528 } 529 530 int TargetList::GetNumTargets() const { 531 std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 532 return m_target_list.size(); 533 } 534 535 lldb::TargetSP TargetList::GetTargetAtIndex(uint32_t idx) const { 536 TargetSP target_sp; 537 std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 538 if (idx < m_target_list.size()) 539 target_sp = m_target_list[idx]; 540 return target_sp; 541 } 542 543 uint32_t TargetList::GetIndexOfTarget(lldb::TargetSP target_sp) const { 544 std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 545 auto it = std::find(m_target_list.begin(), m_target_list.end(), target_sp); 546 if (it != m_target_list.end()) 547 return std::distance(m_target_list.begin(), it); 548 return UINT32_MAX; 549 } 550 551 void TargetList::AddTargetInternal(TargetSP target_sp, bool do_select) { 552 lldbassert(std::find(m_target_list.begin(), m_target_list.end(), target_sp) == 553 m_target_list.end() && 554 "target already exists it the list"); 555 m_target_list.push_back(std::move(target_sp)); 556 if (do_select) 557 SetSelectedTargetInternal(m_target_list.size() - 1); 558 } 559 560 void TargetList::SetSelectedTargetInternal(uint32_t index) { 561 lldbassert(!m_target_list.empty()); 562 m_selected_target_idx = index < m_target_list.size() ? index : 0; 563 } 564 565 void TargetList::SetSelectedTarget(uint32_t index) { 566 std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 567 SetSelectedTargetInternal(index); 568 } 569 570 void TargetList::SetSelectedTarget(const TargetSP &target_sp) { 571 std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 572 auto it = std::find(m_target_list.begin(), m_target_list.end(), target_sp); 573 SetSelectedTargetInternal(std::distance(m_target_list.begin(), it)); 574 } 575 576 lldb::TargetSP TargetList::GetSelectedTarget() { 577 std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 578 if (m_selected_target_idx >= m_target_list.size()) 579 m_selected_target_idx = 0; 580 return GetTargetAtIndex(m_selected_target_idx); 581 } 582