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 
GetStaticBroadcasterClass()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
TargetList(Debugger & debugger)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 
CreateTarget(Debugger & debugger,llvm::StringRef user_exe_path,llvm::StringRef triple_str,LoadDependentFiles load_dependent_files,const OptionGroupPlatform * platform_options,TargetSP & target_sp)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 
CreateTarget(Debugger & debugger,llvm::StringRef user_exe_path,const ArchSpec & specified_arch,LoadDependentFiles load_dependent_files,PlatformSP & platform_sp,TargetSP & target_sp)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 
CreateTargetInternal(Debugger & debugger,llvm::StringRef user_exe_path,llvm::StringRef triple_str,LoadDependentFiles load_dependent_files,const OptionGroupPlatform * platform_options,TargetSP & target_sp)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 
CreateTargetInternal(Debugger & debugger,llvm::StringRef user_exe_path,const ArchSpec & specified_arch,LoadDependentFiles load_dependent_files,lldb::PlatformSP & platform_sp,lldb::TargetSP & target_sp)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);
2745f757f3fSDimitry Andric   if (!FileSystem::Instance().Exists(file) && user_exe_path.starts_with("~")) {
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));
32806c3fb27SDimitry 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));
34006c3fb27SDimitry 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 
DeleteTarget(TargetSP & target_sp)3710b57cec5SDimitry Andric bool TargetList::DeleteTarget(TargetSP &target_sp) {
3720b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
3735f757f3fSDimitry Andric   auto it = llvm::find(m_target_list, 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 
FindTargetWithExecutableAndArchitecture(const FileSpec & exe_file_spec,const ArchSpec * exe_arch_ptr) const3810b57cec5SDimitry 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 
FindTargetWithProcessID(lldb::pid_t pid) const4010b57cec5SDimitry 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 
FindTargetWithProcess(Process * process) const4150b57cec5SDimitry 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 
GetTargetSP(Target * target) const4320b57cec5SDimitry 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 
SendAsyncInterrupt(lldb::pid_t pid)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 
SignalIfRunning(lldb::pid_t pid,int signo)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 
GetNumTargets() const49406c3fb27SDimitry 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 
GetTargetAtIndex(uint32_t idx) const4990b57cec5SDimitry 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 
GetIndexOfTarget(lldb::TargetSP target_sp) const5070b57cec5SDimitry Andric uint32_t TargetList::GetIndexOfTarget(lldb::TargetSP target_sp) const {
5080b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
5095f757f3fSDimitry Andric   auto it = llvm::find(m_target_list, 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 
AddTargetInternal(TargetSP target_sp,bool do_select)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");
51806c3fb27SDimitry 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 
SetSelectedTargetInternal(uint32_t index)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 
SetSelectedTarget(uint32_t index)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 
SetSelectedTarget(const TargetSP & target_sp)534e8d8bef9SDimitry Andric void TargetList::SetSelectedTarget(const TargetSP &target_sp) {
535e8d8bef9SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
5365f757f3fSDimitry Andric   auto it = llvm::find(m_target_list, target_sp);
537e8d8bef9SDimitry Andric   SetSelectedTargetInternal(std::distance(m_target_list.begin(), it));
5380b57cec5SDimitry Andric }
5390b57cec5SDimitry Andric 
GetSelectedTarget()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 }
54606c3fb27SDimitry Andric 
AnyTargetContainsModule(Module & module)54706c3fb27SDimitry Andric bool TargetList::AnyTargetContainsModule(Module &module) {
54806c3fb27SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
54906c3fb27SDimitry Andric   for (const auto &target_sp : m_target_list) {
55006c3fb27SDimitry Andric     if (target_sp->GetImages().FindModule(&module))
55106c3fb27SDimitry Andric       return true;
55206c3fb27SDimitry Andric   }
55306c3fb27SDimitry Andric   for (const auto &target_sp: m_in_process_target_list) {
55406c3fb27SDimitry Andric     if (target_sp->GetImages().FindModule(&module))
55506c3fb27SDimitry Andric       return true;
55606c3fb27SDimitry Andric   }
55706c3fb27SDimitry Andric   return false;
55806c3fb27SDimitry Andric }
55906c3fb27SDimitry Andric 
RegisterInProcessTarget(TargetSP target_sp)56006c3fb27SDimitry Andric   void TargetList::RegisterInProcessTarget(TargetSP target_sp) {
56106c3fb27SDimitry Andric     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
56206c3fb27SDimitry Andric     [[maybe_unused]] bool was_added;
56306c3fb27SDimitry Andric     std::tie(std::ignore, was_added) =
56406c3fb27SDimitry Andric         m_in_process_target_list.insert(target_sp);
56506c3fb27SDimitry Andric     assert(was_added && "Target pointer was left in the in-process map");
56606c3fb27SDimitry Andric   }
56706c3fb27SDimitry Andric 
UnregisterInProcessTarget(TargetSP target_sp)56806c3fb27SDimitry Andric   void TargetList::UnregisterInProcessTarget(TargetSP target_sp) {
56906c3fb27SDimitry Andric     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
57006c3fb27SDimitry Andric     [[maybe_unused]] bool was_present =
57106c3fb27SDimitry Andric         m_in_process_target_list.erase(target_sp);
57206c3fb27SDimitry Andric     assert(was_present && "Target pointer being removed was not registered");
57306c3fb27SDimitry Andric   }
57406c3fb27SDimitry Andric 
IsTargetInProcess(TargetSP target_sp)57506c3fb27SDimitry Andric   bool TargetList::IsTargetInProcess(TargetSP target_sp) {
57606c3fb27SDimitry Andric     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
57706c3fb27SDimitry Andric     return m_in_process_target_list.count(target_sp) == 1;
57806c3fb27SDimitry Andric   }
579