15ffd83dbSDimitry Andric //===-- TargetList.cpp ----------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "lldb/Target/TargetList.h" 100b57cec5SDimitry Andric #include "lldb/Core/Debugger.h" 110b57cec5SDimitry Andric #include "lldb/Core/Module.h" 120b57cec5SDimitry Andric #include "lldb/Core/ModuleSpec.h" 130b57cec5SDimitry Andric #include "lldb/Host/Host.h" 140b57cec5SDimitry Andric #include "lldb/Host/HostInfo.h" 150b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h" 160b57cec5SDimitry Andric #include "lldb/Interpreter/OptionGroupPlatform.h" 170b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h" 180b57cec5SDimitry Andric #include "lldb/Target/Platform.h" 190b57cec5SDimitry Andric #include "lldb/Target/Process.h" 200b57cec5SDimitry Andric #include "lldb/Utility/Broadcaster.h" 210b57cec5SDimitry Andric #include "lldb/Utility/Event.h" 220b57cec5SDimitry Andric #include "lldb/Utility/State.h" 230b57cec5SDimitry Andric #include "lldb/Utility/TildeExpressionResolver.h" 240b57cec5SDimitry Andric #include "lldb/Utility/Timer.h" 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 270b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric using namespace lldb; 300b57cec5SDimitry Andric using namespace lldb_private; 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric ConstString &TargetList::GetStaticBroadcasterClass() { 330b57cec5SDimitry Andric static ConstString class_name("lldb.targetList"); 340b57cec5SDimitry Andric return class_name; 350b57cec5SDimitry Andric } 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric // TargetList constructor 380b57cec5SDimitry Andric TargetList::TargetList(Debugger &debugger) 390b57cec5SDimitry Andric : Broadcaster(debugger.GetBroadcasterManager(), 400b57cec5SDimitry Andric TargetList::GetStaticBroadcasterClass().AsCString()), 410b57cec5SDimitry Andric m_target_list(), m_target_list_mutex(), m_selected_target_idx(0) { 420b57cec5SDimitry Andric CheckInWithManager(); 430b57cec5SDimitry Andric } 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric Status TargetList::CreateTarget(Debugger &debugger, 460b57cec5SDimitry Andric llvm::StringRef user_exe_path, 470b57cec5SDimitry Andric llvm::StringRef triple_str, 480b57cec5SDimitry Andric LoadDependentFiles load_dependent_files, 490b57cec5SDimitry Andric const OptionGroupPlatform *platform_options, 500b57cec5SDimitry Andric TargetSP &target_sp) { 51fe6060f1SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 52e8d8bef9SDimitry Andric auto result = TargetList::CreateTargetInternal( 53e8d8bef9SDimitry Andric debugger, user_exe_path, triple_str, load_dependent_files, 54e8d8bef9SDimitry Andric platform_options, target_sp); 55e8d8bef9SDimitry Andric 56e8d8bef9SDimitry Andric if (target_sp && result.Success()) 57e8d8bef9SDimitry Andric AddTargetInternal(target_sp, /*do_select*/ true); 58e8d8bef9SDimitry Andric return result; 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric Status TargetList::CreateTarget(Debugger &debugger, 620b57cec5SDimitry Andric llvm::StringRef user_exe_path, 630b57cec5SDimitry Andric const ArchSpec &specified_arch, 640b57cec5SDimitry Andric LoadDependentFiles load_dependent_files, 650b57cec5SDimitry Andric PlatformSP &platform_sp, TargetSP &target_sp) { 66fe6060f1SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 67e8d8bef9SDimitry Andric auto result = TargetList::CreateTargetInternal( 68e8d8bef9SDimitry Andric debugger, user_exe_path, specified_arch, load_dependent_files, 69e8d8bef9SDimitry Andric platform_sp, target_sp); 70e8d8bef9SDimitry Andric 71e8d8bef9SDimitry Andric if (target_sp && result.Success()) 72e8d8bef9SDimitry Andric AddTargetInternal(target_sp, /*do_select*/ true); 73e8d8bef9SDimitry Andric return result; 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric Status TargetList::CreateTargetInternal( 770b57cec5SDimitry Andric Debugger &debugger, llvm::StringRef user_exe_path, 780b57cec5SDimitry Andric llvm::StringRef triple_str, LoadDependentFiles load_dependent_files, 79e8d8bef9SDimitry Andric const OptionGroupPlatform *platform_options, TargetSP &target_sp) { 800b57cec5SDimitry Andric Status error; 810b57cec5SDimitry Andric 8281ad6265SDimitry Andric PlatformList &platform_list = debugger.GetPlatformList(); 83e8d8bef9SDimitry Andric // Let's start by looking at the selected platform. 8481ad6265SDimitry Andric PlatformSP platform_sp = platform_list.GetSelectedPlatform(); 85e8d8bef9SDimitry Andric 86e8d8bef9SDimitry Andric // This variable corresponds to the architecture specified by the triple 87e8d8bef9SDimitry Andric // string. If that string was empty the currently selected platform will 88e8d8bef9SDimitry Andric // determine the architecture. 890b57cec5SDimitry Andric const ArchSpec arch(triple_str); 90e8d8bef9SDimitry Andric if (!triple_str.empty() && !arch.IsValid()) { 910b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid triple '%s'", 920b57cec5SDimitry Andric triple_str.str().c_str()); 930b57cec5SDimitry Andric return error; 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric ArchSpec platform_arch(arch); 970b57cec5SDimitry Andric 98e8d8bef9SDimitry Andric // Create a new platform if a platform was specified in the platform options 99e8d8bef9SDimitry Andric // and doesn't match the selected platform. 100e8d8bef9SDimitry Andric if (platform_options && platform_options->PlatformWasSpecified() && 101e8d8bef9SDimitry Andric !platform_options->PlatformMatches(platform_sp)) { 1020b57cec5SDimitry Andric const bool select_platform = true; 1030b57cec5SDimitry Andric platform_sp = platform_options->CreatePlatformWithOptions( 104e8d8bef9SDimitry Andric debugger.GetCommandInterpreter(), arch, select_platform, error, 105e8d8bef9SDimitry Andric platform_arch); 1060b57cec5SDimitry Andric if (!platform_sp) 1070b57cec5SDimitry Andric return error; 1080b57cec5SDimitry Andric } 109e8d8bef9SDimitry Andric 110e8d8bef9SDimitry Andric bool prefer_platform_arch = false; 111e8d8bef9SDimitry Andric auto update_platform_arch = [&](const ArchSpec &module_arch) { 112e8d8bef9SDimitry Andric // If the OS or vendor weren't specified, then adopt the module's 113e8d8bef9SDimitry Andric // architecture so that the platform matching can be more accurate. 114e8d8bef9SDimitry Andric if (!platform_arch.TripleOSWasSpecified() || 115e8d8bef9SDimitry Andric !platform_arch.TripleVendorWasSpecified()) { 116e8d8bef9SDimitry Andric prefer_platform_arch = true; 117e8d8bef9SDimitry Andric platform_arch = module_arch; 1180b57cec5SDimitry Andric } 119e8d8bef9SDimitry Andric }; 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric if (!user_exe_path.empty()) { 122e8d8bef9SDimitry Andric ModuleSpec module_spec(FileSpec(user_exe_path, FileSpec::Style::native)); 1230b57cec5SDimitry Andric FileSystem::Instance().Resolve(module_spec.GetFileSpec()); 12481ad6265SDimitry Andric 12581ad6265SDimitry Andric // Try to resolve the exe based on PATH and/or platform-specific suffixes, 12681ad6265SDimitry Andric // but only if using the host platform. 12781ad6265SDimitry Andric if (platform_sp->IsHost() && 12881ad6265SDimitry Andric !FileSystem::Instance().Exists(module_spec.GetFileSpec())) 12981ad6265SDimitry Andric FileSystem::Instance().ResolveExecutableLocation( 13081ad6265SDimitry Andric module_spec.GetFileSpec()); 13181ad6265SDimitry Andric 1320b57cec5SDimitry Andric // Resolve the executable in case we are given a path to a application 133e8d8bef9SDimitry Andric // bundle like a .app bundle on MacOSX. 1340b57cec5SDimitry Andric Host::ResolveExecutableInBundle(module_spec.GetFileSpec()); 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric lldb::offset_t file_offset = 0; 1370b57cec5SDimitry Andric lldb::offset_t file_size = 0; 138e8d8bef9SDimitry Andric ModuleSpecList module_specs; 1390b57cec5SDimitry Andric const size_t num_specs = ObjectFile::GetModuleSpecifications( 1400b57cec5SDimitry Andric module_spec.GetFileSpec(), file_offset, file_size, module_specs); 141e8d8bef9SDimitry Andric 1420b57cec5SDimitry Andric if (num_specs > 0) { 1430b57cec5SDimitry Andric ModuleSpec matching_module_spec; 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric if (num_specs == 1) { 1460b57cec5SDimitry Andric if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec)) { 1470b57cec5SDimitry Andric if (platform_arch.IsValid()) { 1480b57cec5SDimitry Andric if (platform_arch.IsCompatibleMatch( 1490b57cec5SDimitry Andric matching_module_spec.GetArchitecture())) { 1500b57cec5SDimitry Andric // If the OS or vendor weren't specified, then adopt the module's 1510b57cec5SDimitry Andric // architecture so that the platform matching can be more 152e8d8bef9SDimitry Andric // accurate. 153e8d8bef9SDimitry Andric update_platform_arch(matching_module_spec.GetArchitecture()); 1540b57cec5SDimitry Andric } else { 1550b57cec5SDimitry Andric StreamString platform_arch_strm; 1560b57cec5SDimitry Andric StreamString module_arch_strm; 1570b57cec5SDimitry Andric 158480093f4SDimitry Andric platform_arch.DumpTriple(platform_arch_strm.AsRawOstream()); 1590b57cec5SDimitry Andric matching_module_spec.GetArchitecture().DumpTriple( 160480093f4SDimitry Andric module_arch_strm.AsRawOstream()); 1610b57cec5SDimitry Andric error.SetErrorStringWithFormat( 1620b57cec5SDimitry Andric "the specified architecture '%s' is not compatible with '%s' " 1630b57cec5SDimitry Andric "in '%s'", 1640b57cec5SDimitry Andric platform_arch_strm.GetData(), module_arch_strm.GetData(), 1650b57cec5SDimitry Andric module_spec.GetFileSpec().GetPath().c_str()); 1660b57cec5SDimitry Andric return error; 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric } else { 169e8d8bef9SDimitry Andric // Only one arch and none was specified. 1700b57cec5SDimitry Andric prefer_platform_arch = true; 1710b57cec5SDimitry Andric platform_arch = matching_module_spec.GetArchitecture(); 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric } 174e8d8bef9SDimitry Andric } else if (arch.IsValid()) { 175e8d8bef9SDimitry Andric // Fat binary. A (valid) architecture was specified. 1760b57cec5SDimitry Andric module_spec.GetArchitecture() = arch; 1770b57cec5SDimitry Andric if (module_specs.FindMatchingModuleSpec(module_spec, 178e8d8bef9SDimitry Andric matching_module_spec)) 179e8d8bef9SDimitry Andric update_platform_arch(matching_module_spec.GetArchitecture()); 1800b57cec5SDimitry Andric } else { 181e8d8bef9SDimitry Andric // Fat binary. No architecture specified, check if there is 182e8d8bef9SDimitry Andric // only one platform for all of the architectures. 18381ad6265SDimitry Andric std::vector<PlatformSP> candidates; 18481ad6265SDimitry Andric std::vector<ArchSpec> archs; 18581ad6265SDimitry Andric for (const ModuleSpec &spec : module_specs.ModuleSpecs()) 18681ad6265SDimitry Andric archs.push_back(spec.GetArchitecture()); 18781ad6265SDimitry Andric if (PlatformSP platform_for_archs_sp = 18881ad6265SDimitry Andric platform_list.GetOrCreate(archs, {}, candidates)) { 18981ad6265SDimitry Andric platform_sp = platform_for_archs_sp; 19081ad6265SDimitry Andric } else if (candidates.empty()) { 191e8d8bef9SDimitry Andric error.SetErrorString("no matching platforms found for this file"); 1920b57cec5SDimitry Andric return error; 1930b57cec5SDimitry Andric } else { 194e8d8bef9SDimitry Andric // More than one platform claims to support this file. 1950b57cec5SDimitry Andric StreamString error_strm; 19681ad6265SDimitry Andric std::set<llvm::StringRef> platform_set; 1970b57cec5SDimitry Andric error_strm.Printf( 1980b57cec5SDimitry Andric "more than one platform supports this executable ("); 19981ad6265SDimitry Andric for (const auto &candidate : candidates) { 20081ad6265SDimitry Andric llvm::StringRef platform_name = candidate->GetName(); 20181ad6265SDimitry Andric if (platform_set.count(platform_name)) 20281ad6265SDimitry Andric continue; 2030b57cec5SDimitry Andric if (!platform_set.empty()) 2040b57cec5SDimitry Andric error_strm.PutCString(", "); 20581ad6265SDimitry Andric error_strm.PutCString(platform_name); 20681ad6265SDimitry Andric platform_set.insert(platform_name); 2070b57cec5SDimitry Andric } 208e8d8bef9SDimitry Andric error_strm.Printf("), specify an architecture to disambiguate"); 2090b57cec5SDimitry Andric error.SetErrorString(error_strm.GetString()); 2100b57cec5SDimitry Andric return error; 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric // If we have a valid architecture, make sure the current platform is 217e8d8bef9SDimitry Andric // compatible with that architecture. 2180b57cec5SDimitry Andric if (!prefer_platform_arch && arch.IsValid()) { 219bdd1243dSDimitry Andric if (!platform_sp->IsCompatibleArchitecture( 220bdd1243dSDimitry Andric arch, {}, ArchSpec::CompatibleMatch, nullptr)) { 22181ad6265SDimitry Andric platform_sp = platform_list.GetOrCreate(arch, {}, &platform_arch); 222e8d8bef9SDimitry Andric if (platform_sp) 22381ad6265SDimitry Andric platform_list.SetSelectedPlatform(platform_sp); 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric } else if (platform_arch.IsValid()) { 226e8d8bef9SDimitry Andric // If "arch" isn't valid, yet "platform_arch" is, it means we have an 227e8d8bef9SDimitry Andric // executable file with a single architecture which should be used. 2280b57cec5SDimitry Andric ArchSpec fixed_platform_arch; 229bdd1243dSDimitry Andric if (!platform_sp->IsCompatibleArchitecture( 230bdd1243dSDimitry Andric platform_arch, {}, ArchSpec::CompatibleMatch, nullptr)) { 23181ad6265SDimitry Andric platform_sp = 23281ad6265SDimitry Andric platform_list.GetOrCreate(platform_arch, {}, &fixed_platform_arch); 233e8d8bef9SDimitry Andric if (platform_sp) 23481ad6265SDimitry Andric platform_list.SetSelectedPlatform(platform_sp); 2350b57cec5SDimitry Andric } 2360b57cec5SDimitry Andric } 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric if (!platform_arch.IsValid()) 2390b57cec5SDimitry Andric platform_arch = arch; 2400b57cec5SDimitry Andric 241e8d8bef9SDimitry Andric return TargetList::CreateTargetInternal(debugger, user_exe_path, 242e8d8bef9SDimitry Andric platform_arch, load_dependent_files, 243e8d8bef9SDimitry Andric platform_sp, target_sp); 2440b57cec5SDimitry Andric } 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric Status TargetList::CreateTargetInternal(Debugger &debugger, 2470b57cec5SDimitry Andric llvm::StringRef user_exe_path, 2480b57cec5SDimitry Andric const ArchSpec &specified_arch, 2490b57cec5SDimitry Andric LoadDependentFiles load_dependent_files, 2500b57cec5SDimitry Andric lldb::PlatformSP &platform_sp, 251e8d8bef9SDimitry Andric lldb::TargetSP &target_sp) { 252e8d8bef9SDimitry Andric LLDB_SCOPED_TIMERF("TargetList::CreateTarget (file = '%s', arch = '%s')", 253e8d8bef9SDimitry Andric user_exe_path.str().c_str(), 254e8d8bef9SDimitry Andric specified_arch.GetArchitectureName()); 2550b57cec5SDimitry Andric Status error; 256e8d8bef9SDimitry Andric const bool is_dummy_target = false; 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric ArchSpec arch(specified_arch); 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric if (arch.IsValid()) { 261bdd1243dSDimitry Andric if (!platform_sp || !platform_sp->IsCompatibleArchitecture( 262bdd1243dSDimitry Andric arch, {}, ArchSpec::CompatibleMatch, nullptr)) 26381ad6265SDimitry Andric platform_sp = 26481ad6265SDimitry Andric debugger.GetPlatformList().GetOrCreate(specified_arch, {}, &arch); 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric if (!platform_sp) 2680b57cec5SDimitry Andric platform_sp = debugger.GetPlatformList().GetSelectedPlatform(); 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric if (!arch.IsValid()) 2710b57cec5SDimitry Andric arch = specified_arch; 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric FileSpec file(user_exe_path); 2740b57cec5SDimitry Andric if (!FileSystem::Instance().Exists(file) && user_exe_path.startswith("~")) { 2750b57cec5SDimitry Andric // we want to expand the tilde but we don't want to resolve any symbolic 2760b57cec5SDimitry Andric // links so we can't use the FileSpec constructor's resolve flag 2770b57cec5SDimitry Andric llvm::SmallString<64> unglobbed_path; 2780b57cec5SDimitry Andric StandardTildeExpressionResolver Resolver; 2790b57cec5SDimitry Andric Resolver.ResolveFullPath(user_exe_path, unglobbed_path); 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric if (unglobbed_path.empty()) 2820b57cec5SDimitry Andric file = FileSpec(user_exe_path); 2830b57cec5SDimitry Andric else 2840b57cec5SDimitry Andric file = FileSpec(unglobbed_path.c_str()); 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric bool user_exe_path_is_bundle = false; 2880b57cec5SDimitry Andric char resolved_bundle_exe_path[PATH_MAX]; 2890b57cec5SDimitry Andric resolved_bundle_exe_path[0] = '\0'; 2900b57cec5SDimitry Andric if (file) { 2910b57cec5SDimitry Andric if (FileSystem::Instance().IsDirectory(file)) 2920b57cec5SDimitry Andric user_exe_path_is_bundle = true; 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric if (file.IsRelative() && !user_exe_path.empty()) { 2950b57cec5SDimitry Andric llvm::SmallString<64> cwd; 2960b57cec5SDimitry Andric if (! llvm::sys::fs::current_path(cwd)) { 2970b57cec5SDimitry Andric FileSpec cwd_file(cwd.c_str()); 2980b57cec5SDimitry Andric cwd_file.AppendPathComponent(file); 2990b57cec5SDimitry Andric if (FileSystem::Instance().Exists(cwd_file)) 3000b57cec5SDimitry Andric file = cwd_file; 3010b57cec5SDimitry Andric } 3020b57cec5SDimitry Andric } 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric ModuleSP exe_module_sp; 3050b57cec5SDimitry Andric if (platform_sp) { 3060b57cec5SDimitry Andric FileSpecList executable_search_paths( 3070b57cec5SDimitry Andric Target::GetDefaultExecutableSearchPaths()); 3080b57cec5SDimitry Andric ModuleSpec module_spec(file, arch); 3090b57cec5SDimitry Andric error = platform_sp->ResolveExecutable(module_spec, exe_module_sp, 3100b57cec5SDimitry Andric executable_search_paths.GetSize() 3110b57cec5SDimitry Andric ? &executable_search_paths 3120b57cec5SDimitry Andric : nullptr); 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric if (error.Success() && exe_module_sp) { 3160b57cec5SDimitry Andric if (exe_module_sp->GetObjectFile() == nullptr) { 3170b57cec5SDimitry Andric if (arch.IsValid()) { 3180b57cec5SDimitry Andric error.SetErrorStringWithFormat( 3190b57cec5SDimitry Andric "\"%s\" doesn't contain architecture %s", file.GetPath().c_str(), 3200b57cec5SDimitry Andric arch.GetArchitectureName()); 3210b57cec5SDimitry Andric } else { 3220b57cec5SDimitry Andric error.SetErrorStringWithFormat("unsupported file type \"%s\"", 3230b57cec5SDimitry Andric file.GetPath().c_str()); 3240b57cec5SDimitry Andric } 3250b57cec5SDimitry Andric return error; 3260b57cec5SDimitry Andric } 3270b57cec5SDimitry Andric target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target)); 328*fe013be4SDimitry Andric debugger.GetTargetList().RegisterInProcessTarget(target_sp); 3290b57cec5SDimitry Andric target_sp->SetExecutableModule(exe_module_sp, load_dependent_files); 3300b57cec5SDimitry Andric if (user_exe_path_is_bundle) 3310b57cec5SDimitry Andric exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path, 3320b57cec5SDimitry Andric sizeof(resolved_bundle_exe_path)); 3335ffd83dbSDimitry Andric if (target_sp->GetPreloadSymbols()) 3345ffd83dbSDimitry Andric exe_module_sp->PreloadSymbols(); 3350b57cec5SDimitry Andric } 3360b57cec5SDimitry Andric } else { 3370b57cec5SDimitry Andric // No file was specified, just create an empty target with any arch if a 3380b57cec5SDimitry Andric // valid arch was specified 3390b57cec5SDimitry Andric target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target)); 340*fe013be4SDimitry Andric debugger.GetTargetList().RegisterInProcessTarget(target_sp); 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 343e8d8bef9SDimitry Andric if (!target_sp) 344e8d8bef9SDimitry Andric return error; 345e8d8bef9SDimitry Andric 3460b57cec5SDimitry Andric // Set argv0 with what the user typed, unless the user specified a 3470b57cec5SDimitry Andric // directory. If the user specified a directory, then it is probably a 3480b57cec5SDimitry Andric // bundle that was resolved and we need to use the resolved bundle path 3490b57cec5SDimitry Andric if (!user_exe_path.empty()) { 3500b57cec5SDimitry Andric // Use exactly what the user typed as the first argument when we exec or 3510b57cec5SDimitry Andric // posix_spawn 3520b57cec5SDimitry Andric if (user_exe_path_is_bundle && resolved_bundle_exe_path[0]) { 3530b57cec5SDimitry Andric target_sp->SetArg0(resolved_bundle_exe_path); 3540b57cec5SDimitry Andric } else { 3550b57cec5SDimitry Andric // Use resolved path 3560b57cec5SDimitry Andric target_sp->SetArg0(file.GetPath().c_str()); 3570b57cec5SDimitry Andric } 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric if (file.GetDirectory()) { 3600b57cec5SDimitry Andric FileSpec file_dir; 361bdd1243dSDimitry Andric file_dir.SetDirectory(file.GetDirectory()); 3620b57cec5SDimitry Andric target_sp->AppendExecutableSearchPaths(file_dir); 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric // Now prime this from the dummy target: 3660b57cec5SDimitry Andric target_sp->PrimeFromDummyTarget(debugger.GetDummyTarget()); 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric return error; 3690b57cec5SDimitry Andric } 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric bool TargetList::DeleteTarget(TargetSP &target_sp) { 3720b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 373e8d8bef9SDimitry Andric auto it = std::find(m_target_list.begin(), m_target_list.end(), target_sp); 374e8d8bef9SDimitry Andric if (it == m_target_list.end()) 3750b57cec5SDimitry Andric return false; 376e8d8bef9SDimitry Andric 377e8d8bef9SDimitry Andric m_target_list.erase(it); 378e8d8bef9SDimitry Andric return true; 3790b57cec5SDimitry Andric } 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric TargetSP TargetList::FindTargetWithExecutableAndArchitecture( 3820b57cec5SDimitry Andric const FileSpec &exe_file_spec, const ArchSpec *exe_arch_ptr) const { 3830b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 384e8d8bef9SDimitry Andric auto it = std::find_if(m_target_list.begin(), m_target_list.end(), 385e8d8bef9SDimitry Andric [&exe_file_spec, exe_arch_ptr](const TargetSP &item) { 386e8d8bef9SDimitry Andric Module *exe_module = item->GetExecutableModulePointer(); 387e8d8bef9SDimitry Andric if (!exe_module || 388e8d8bef9SDimitry Andric !FileSpec::Match(exe_file_spec, exe_module->GetFileSpec())) 389e8d8bef9SDimitry Andric return false; 3900b57cec5SDimitry Andric 391e8d8bef9SDimitry Andric return !exe_arch_ptr || 392e8d8bef9SDimitry Andric exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture()); 393e8d8bef9SDimitry Andric }); 394e8d8bef9SDimitry Andric 395e8d8bef9SDimitry Andric if (it != m_target_list.end()) 396e8d8bef9SDimitry Andric return *it; 397e8d8bef9SDimitry Andric 398e8d8bef9SDimitry Andric return TargetSP(); 3990b57cec5SDimitry Andric } 4000b57cec5SDimitry Andric 4010b57cec5SDimitry Andric TargetSP TargetList::FindTargetWithProcessID(lldb::pid_t pid) const { 4020b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 403e8d8bef9SDimitry Andric auto it = std::find_if(m_target_list.begin(), m_target_list.end(), 404e8d8bef9SDimitry Andric [pid](const TargetSP &item) { 405e8d8bef9SDimitry Andric auto *process_ptr = item->GetProcessSP().get(); 406e8d8bef9SDimitry Andric return process_ptr && (process_ptr->GetID() == pid); 407e8d8bef9SDimitry Andric }); 408e8d8bef9SDimitry Andric 409e8d8bef9SDimitry Andric if (it != m_target_list.end()) 410e8d8bef9SDimitry Andric return *it; 411e8d8bef9SDimitry Andric 412e8d8bef9SDimitry Andric return TargetSP(); 4130b57cec5SDimitry Andric } 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric TargetSP TargetList::FindTargetWithProcess(Process *process) const { 4160b57cec5SDimitry Andric TargetSP target_sp; 417e8d8bef9SDimitry Andric if (!process) 418e8d8bef9SDimitry Andric return target_sp; 419e8d8bef9SDimitry Andric 4200b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 421e8d8bef9SDimitry Andric auto it = std::find_if(m_target_list.begin(), m_target_list.end(), 422e8d8bef9SDimitry Andric [process](const TargetSP &item) { 423e8d8bef9SDimitry Andric return item->GetProcessSP().get() == process; 424e8d8bef9SDimitry Andric }); 425e8d8bef9SDimitry Andric 426e8d8bef9SDimitry Andric if (it != m_target_list.end()) 427e8d8bef9SDimitry Andric target_sp = *it; 428e8d8bef9SDimitry Andric 4290b57cec5SDimitry Andric return target_sp; 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric TargetSP TargetList::GetTargetSP(Target *target) const { 4330b57cec5SDimitry Andric TargetSP target_sp; 434e8d8bef9SDimitry Andric if (!target) 435e8d8bef9SDimitry Andric return target_sp; 436e8d8bef9SDimitry Andric 4370b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 438e8d8bef9SDimitry Andric auto it = std::find_if(m_target_list.begin(), m_target_list.end(), 439e8d8bef9SDimitry Andric [target](const TargetSP &item) { return item.get() == target; }); 440e8d8bef9SDimitry Andric if (it != m_target_list.end()) 441e8d8bef9SDimitry Andric target_sp = *it; 442e8d8bef9SDimitry Andric 4430b57cec5SDimitry Andric return target_sp; 4440b57cec5SDimitry Andric } 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric uint32_t TargetList::SendAsyncInterrupt(lldb::pid_t pid) { 4470b57cec5SDimitry Andric uint32_t num_async_interrupts_sent = 0; 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric if (pid != LLDB_INVALID_PROCESS_ID) { 4500b57cec5SDimitry Andric TargetSP target_sp(FindTargetWithProcessID(pid)); 4510b57cec5SDimitry Andric if (target_sp) { 4520b57cec5SDimitry Andric Process *process = target_sp->GetProcessSP().get(); 4530b57cec5SDimitry Andric if (process) { 4540b57cec5SDimitry Andric process->SendAsyncInterrupt(); 4550b57cec5SDimitry Andric ++num_async_interrupts_sent; 4560b57cec5SDimitry Andric } 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric } else { 4590b57cec5SDimitry Andric // We don't have a valid pid to broadcast to, so broadcast to the target 4600b57cec5SDimitry Andric // list's async broadcaster... 4610b57cec5SDimitry Andric BroadcastEvent(Process::eBroadcastBitInterrupt, nullptr); 4620b57cec5SDimitry Andric } 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andric return num_async_interrupts_sent; 4650b57cec5SDimitry Andric } 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric uint32_t TargetList::SignalIfRunning(lldb::pid_t pid, int signo) { 4680b57cec5SDimitry Andric uint32_t num_signals_sent = 0; 4690b57cec5SDimitry Andric Process *process = nullptr; 4700b57cec5SDimitry Andric if (pid == LLDB_INVALID_PROCESS_ID) { 4710b57cec5SDimitry Andric // Signal all processes with signal 4720b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 473e8d8bef9SDimitry Andric for (const auto &target_sp : m_target_list) { 474e8d8bef9SDimitry Andric process = target_sp->GetProcessSP().get(); 475e8d8bef9SDimitry Andric if (process && process->IsAlive()) { 4760b57cec5SDimitry Andric ++num_signals_sent; 4770b57cec5SDimitry Andric process->Signal(signo); 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric } else { 4810b57cec5SDimitry Andric // Signal a specific process with signal 4820b57cec5SDimitry Andric TargetSP target_sp(FindTargetWithProcessID(pid)); 4830b57cec5SDimitry Andric if (target_sp) { 4840b57cec5SDimitry Andric process = target_sp->GetProcessSP().get(); 485e8d8bef9SDimitry Andric if (process && process->IsAlive()) { 4860b57cec5SDimitry Andric ++num_signals_sent; 4870b57cec5SDimitry Andric process->Signal(signo); 4880b57cec5SDimitry Andric } 4890b57cec5SDimitry Andric } 4900b57cec5SDimitry Andric } 4910b57cec5SDimitry Andric return num_signals_sent; 4920b57cec5SDimitry Andric } 4930b57cec5SDimitry Andric 494*fe013be4SDimitry Andric size_t TargetList::GetNumTargets() const { 4950b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 4960b57cec5SDimitry Andric return m_target_list.size(); 4970b57cec5SDimitry Andric } 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric lldb::TargetSP TargetList::GetTargetAtIndex(uint32_t idx) const { 5000b57cec5SDimitry Andric TargetSP target_sp; 5010b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 5020b57cec5SDimitry Andric if (idx < m_target_list.size()) 5030b57cec5SDimitry Andric target_sp = m_target_list[idx]; 5040b57cec5SDimitry Andric return target_sp; 5050b57cec5SDimitry Andric } 5060b57cec5SDimitry Andric 5070b57cec5SDimitry Andric uint32_t TargetList::GetIndexOfTarget(lldb::TargetSP target_sp) const { 5080b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 509e8d8bef9SDimitry Andric auto it = std::find(m_target_list.begin(), m_target_list.end(), target_sp); 510e8d8bef9SDimitry Andric if (it != m_target_list.end()) 511e8d8bef9SDimitry Andric return std::distance(m_target_list.begin(), it); 5120b57cec5SDimitry Andric return UINT32_MAX; 5130b57cec5SDimitry Andric } 5140b57cec5SDimitry Andric 515e8d8bef9SDimitry Andric void TargetList::AddTargetInternal(TargetSP target_sp, bool do_select) { 516fcaf7f86SDimitry Andric lldbassert(!llvm::is_contained(m_target_list, target_sp) && 517e8d8bef9SDimitry Andric "target already exists it the list"); 518*fe013be4SDimitry Andric UnregisterInProcessTarget(target_sp); 519e8d8bef9SDimitry Andric m_target_list.push_back(std::move(target_sp)); 520e8d8bef9SDimitry Andric if (do_select) 521e8d8bef9SDimitry Andric SetSelectedTargetInternal(m_target_list.size() - 1); 522e8d8bef9SDimitry Andric } 523e8d8bef9SDimitry Andric 524e8d8bef9SDimitry Andric void TargetList::SetSelectedTargetInternal(uint32_t index) { 525e8d8bef9SDimitry Andric lldbassert(!m_target_list.empty()); 526e8d8bef9SDimitry Andric m_selected_target_idx = index < m_target_list.size() ? index : 0; 527e8d8bef9SDimitry Andric } 528e8d8bef9SDimitry Andric 529e8d8bef9SDimitry Andric void TargetList::SetSelectedTarget(uint32_t index) { 5300b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 531e8d8bef9SDimitry Andric SetSelectedTargetInternal(index); 5320b57cec5SDimitry Andric } 533e8d8bef9SDimitry Andric 534e8d8bef9SDimitry Andric void TargetList::SetSelectedTarget(const TargetSP &target_sp) { 535e8d8bef9SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 536e8d8bef9SDimitry Andric auto it = std::find(m_target_list.begin(), m_target_list.end(), target_sp); 537e8d8bef9SDimitry Andric SetSelectedTargetInternal(std::distance(m_target_list.begin(), it)); 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric lldb::TargetSP TargetList::GetSelectedTarget() { 5410b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 5420b57cec5SDimitry Andric if (m_selected_target_idx >= m_target_list.size()) 5430b57cec5SDimitry Andric m_selected_target_idx = 0; 5440b57cec5SDimitry Andric return GetTargetAtIndex(m_selected_target_idx); 5450b57cec5SDimitry Andric } 546*fe013be4SDimitry Andric 547*fe013be4SDimitry Andric bool TargetList::AnyTargetContainsModule(Module &module) { 548*fe013be4SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 549*fe013be4SDimitry Andric for (const auto &target_sp : m_target_list) { 550*fe013be4SDimitry Andric if (target_sp->GetImages().FindModule(&module)) 551*fe013be4SDimitry Andric return true; 552*fe013be4SDimitry Andric } 553*fe013be4SDimitry Andric for (const auto &target_sp: m_in_process_target_list) { 554*fe013be4SDimitry Andric if (target_sp->GetImages().FindModule(&module)) 555*fe013be4SDimitry Andric return true; 556*fe013be4SDimitry Andric } 557*fe013be4SDimitry Andric return false; 558*fe013be4SDimitry Andric } 559*fe013be4SDimitry Andric 560*fe013be4SDimitry Andric void TargetList::RegisterInProcessTarget(TargetSP target_sp) { 561*fe013be4SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 562*fe013be4SDimitry Andric [[maybe_unused]] bool was_added; 563*fe013be4SDimitry Andric std::tie(std::ignore, was_added) = 564*fe013be4SDimitry Andric m_in_process_target_list.insert(target_sp); 565*fe013be4SDimitry Andric assert(was_added && "Target pointer was left in the in-process map"); 566*fe013be4SDimitry Andric } 567*fe013be4SDimitry Andric 568*fe013be4SDimitry Andric void TargetList::UnregisterInProcessTarget(TargetSP target_sp) { 569*fe013be4SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 570*fe013be4SDimitry Andric [[maybe_unused]] bool was_present = 571*fe013be4SDimitry Andric m_in_process_target_list.erase(target_sp); 572*fe013be4SDimitry Andric assert(was_present && "Target pointer being removed was not registered"); 573*fe013be4SDimitry Andric } 574*fe013be4SDimitry Andric 575*fe013be4SDimitry Andric bool TargetList::IsTargetInProcess(TargetSP target_sp) { 576*fe013be4SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex); 577*fe013be4SDimitry Andric return m_in_process_target_list.count(target_sp) == 1; 578*fe013be4SDimitry Andric } 579