180814287SRaphael Isemann //===-- TargetList.cpp ----------------------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
9fb1a0a0dSZachary Turner #include "lldb/Target/TargetList.h"
10ded470d3SGreg Clayton #include "lldb/Core/Debugger.h"
111f746071SGreg Clayton #include "lldb/Core/Module.h"
12f4d6de6aSGreg Clayton #include "lldb/Core/ModuleSpec.h"
1330fdc8d8SChris Lattner #include "lldb/Host/Host.h"
14893c932aSJim Ingham #include "lldb/Host/HostInfo.h"
15b3a40ba8SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
16cac9c5f9SGreg Clayton #include "lldb/Interpreter/OptionGroupPlatform.h"
17f4d6de6aSGreg Clayton #include "lldb/Symbol/ObjectFile.h"
18e996fd30SGreg Clayton #include "lldb/Target/Platform.h"
1930fdc8d8SChris Lattner #include "lldb/Target/Process.h"
20181b823bSPavel Labath #include "lldb/Utility/Broadcaster.h"
21181b823bSPavel Labath #include "lldb/Utility/Event.h"
22d821c997SPavel Labath #include "lldb/Utility/State.h"
238d48cd60SZachary Turner #include "lldb/Utility/TildeExpressionResolver.h"
2438d0632eSPavel Labath #include "lldb/Utility/Timer.h"
2530fdc8d8SChris Lattner 
261d5855b1SPavel Labath #include "llvm/ADT/SmallString.h"
271d5855b1SPavel Labath #include "llvm/Support/FileSystem.h"
281d5855b1SPavel Labath 
2930fdc8d8SChris Lattner using namespace lldb;
3030fdc8d8SChris Lattner using namespace lldb_private;
3130fdc8d8SChris Lattner 
GetStaticBroadcasterClass()32b9c1b51eSKate Stone ConstString &TargetList::GetStaticBroadcasterClass() {
334bddaeb5SJim Ingham   static ConstString class_name("lldb.targetList");
344bddaeb5SJim Ingham   return class_name;
354bddaeb5SJim Ingham }
3630fdc8d8SChris Lattner 
3730fdc8d8SChris Lattner // TargetList constructor
TargetList(Debugger & debugger)3816ff8604SSaleem Abdulrasool TargetList::TargetList(Debugger &debugger)
39b9c1b51eSKate Stone     : Broadcaster(debugger.GetBroadcasterManager(),
40b9c1b51eSKate Stone                   TargetList::GetStaticBroadcasterClass().AsCString()),
41b9c1b51eSKate Stone       m_target_list(), m_target_list_mutex(), m_selected_target_idx(0) {
424bddaeb5SJim Ingham   CheckInWithManager();
4330fdc8d8SChris Lattner }
4430fdc8d8SChris Lattner 
CreateTarget(Debugger & debugger,llvm::StringRef user_exe_path,llvm::StringRef triple_str,LoadDependentFiles load_dependent_files,const OptionGroupPlatform * platform_options,TargetSP & target_sp)4597206d57SZachary Turner Status TargetList::CreateTarget(Debugger &debugger,
46a47464b2SZachary Turner                                 llvm::StringRef user_exe_path,
47a47464b2SZachary Turner                                 llvm::StringRef triple_str,
48f9a07e9fSJonas Devlieghere                                 LoadDependentFiles load_dependent_files,
49cac9c5f9SGreg Clayton                                 const OptionGroupPlatform *platform_options,
50b9c1b51eSKate Stone                                 TargetSP &target_sp) {
51ba51da82SRaphael Isemann   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
522634ec6cSTatyana Krasnukha   auto result = TargetList::CreateTargetInternal(
532634ec6cSTatyana Krasnukha       debugger, user_exe_path, triple_str, load_dependent_files,
542634ec6cSTatyana Krasnukha       platform_options, target_sp);
552634ec6cSTatyana Krasnukha 
562634ec6cSTatyana Krasnukha   if (target_sp && result.Success())
572634ec6cSTatyana Krasnukha     AddTargetInternal(target_sp, /*do_select*/ true);
582634ec6cSTatyana Krasnukha   return result;
59893c932aSJim Ingham }
60893c932aSJim Ingham 
CreateTarget(Debugger & debugger,llvm::StringRef user_exe_path,const ArchSpec & specified_arch,LoadDependentFiles load_dependent_files,PlatformSP & platform_sp,TargetSP & target_sp)6197206d57SZachary Turner Status TargetList::CreateTarget(Debugger &debugger,
62a47464b2SZachary Turner                                 llvm::StringRef user_exe_path,
63893c932aSJim Ingham                                 const ArchSpec &specified_arch,
64f9a07e9fSJonas Devlieghere                                 LoadDependentFiles load_dependent_files,
65b9c1b51eSKate Stone                                 PlatformSP &platform_sp, TargetSP &target_sp) {
66ba51da82SRaphael Isemann   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
672634ec6cSTatyana Krasnukha   auto result = TargetList::CreateTargetInternal(
682634ec6cSTatyana Krasnukha       debugger, user_exe_path, specified_arch, load_dependent_files,
692634ec6cSTatyana Krasnukha       platform_sp, target_sp);
702634ec6cSTatyana Krasnukha 
712634ec6cSTatyana Krasnukha   if (target_sp && result.Success())
722634ec6cSTatyana Krasnukha     AddTargetInternal(target_sp, /*do_select*/ true);
732634ec6cSTatyana Krasnukha   return result;
74893c932aSJim Ingham }
75893c932aSJim Ingham 
CreateTargetInternal(Debugger & debugger,llvm::StringRef user_exe_path,llvm::StringRef triple_str,LoadDependentFiles load_dependent_files,const OptionGroupPlatform * platform_options,TargetSP & target_sp)7697206d57SZachary Turner Status TargetList::CreateTargetInternal(
77a47464b2SZachary Turner     Debugger &debugger, llvm::StringRef user_exe_path,
78f9a07e9fSJonas Devlieghere     llvm::StringRef triple_str, LoadDependentFiles load_dependent_files,
7916e5a347SVedant Kumar     const OptionGroupPlatform *platform_options, TargetSP &target_sp) {
8097206d57SZachary Turner   Status error;
81cac9c5f9SGreg Clayton 
82af921006SPavel Labath   PlatformList &platform_list = debugger.GetPlatformList();
834add8536SJonas Devlieghere   // Let's start by looking at the selected platform.
84af921006SPavel Labath   PlatformSP platform_sp = platform_list.GetSelectedPlatform();
854add8536SJonas Devlieghere 
864add8536SJonas Devlieghere   // This variable corresponds to the architecture specified by the triple
874add8536SJonas Devlieghere   // string. If that string was empty the currently selected platform will
884add8536SJonas Devlieghere   // determine the architecture.
89a47464b2SZachary Turner   const ArchSpec arch(triple_str);
904add8536SJonas Devlieghere   if (!triple_str.empty() && !arch.IsValid()) {
91a47464b2SZachary Turner     error.SetErrorStringWithFormat("invalid triple '%s'",
92a47464b2SZachary Turner                                    triple_str.str().c_str());
93cac9c5f9SGreg Clayton     return error;
94cac9c5f9SGreg Clayton   }
95b3a40ba8SGreg Clayton 
9670512317SGreg Clayton   ArchSpec platform_arch(arch);
97f4d6de6aSGreg Clayton 
984add8536SJonas Devlieghere   // Create a new platform if a platform was specified in the platform options
994add8536SJonas Devlieghere   // and doesn't match the selected platform.
1004add8536SJonas Devlieghere   if (platform_options && platform_options->PlatformWasSpecified() &&
1014add8536SJonas Devlieghere       !platform_options->PlatformMatches(platform_sp)) {
102b0cc53cfSGreg Clayton     const bool select_platform = true;
103b9c1b51eSKate Stone     platform_sp = platform_options->CreatePlatformWithOptions(
1044add8536SJonas Devlieghere         debugger.GetCommandInterpreter(), arch, select_platform, error,
1054add8536SJonas Devlieghere         platform_arch);
106b0cc53cfSGreg Clayton     if (!platform_sp)
107b0cc53cfSGreg Clayton       return error;
108b0cc53cfSGreg Clayton   }
1094add8536SJonas Devlieghere 
1104add8536SJonas Devlieghere   bool prefer_platform_arch = false;
1110fa520afSAdrian Prantl   auto update_platform_arch = [&](const ArchSpec &module_arch) {
1120fa520afSAdrian Prantl     // If the OS or vendor weren't specified, then adopt the module's
1130fa520afSAdrian Prantl     // architecture so that the platform matching can be more accurate.
1140fa520afSAdrian Prantl     if (!platform_arch.TripleOSWasSpecified() ||
1150fa520afSAdrian Prantl         !platform_arch.TripleVendorWasSpecified()) {
1160fa520afSAdrian Prantl       prefer_platform_arch = true;
1170fa520afSAdrian Prantl       platform_arch = module_arch;
1180fa520afSAdrian Prantl     }
1190fa520afSAdrian Prantl   };
120b0cc53cfSGreg Clayton 
121a47464b2SZachary Turner   if (!user_exe_path.empty()) {
1224add8536SJonas Devlieghere     ModuleSpec module_spec(FileSpec(user_exe_path, FileSpec::Style::native));
1238f3be7a3SJonas Devlieghere     FileSystem::Instance().Resolve(module_spec.GetFileSpec());
1242bae9560SAlvin Wong 
1252bae9560SAlvin Wong     // Try to resolve the exe based on PATH and/or platform-specific suffixes,
1262bae9560SAlvin Wong     // but only if using the host platform.
1272bae9560SAlvin Wong     if (platform_sp->IsHost() &&
1282bae9560SAlvin Wong         !FileSystem::Instance().Exists(module_spec.GetFileSpec()))
1292bae9560SAlvin Wong       FileSystem::Instance().ResolveExecutableLocation(
1302bae9560SAlvin Wong           module_spec.GetFileSpec());
1312bae9560SAlvin Wong 
132b9c1b51eSKate Stone     // Resolve the executable in case we are given a path to a application
1334add8536SJonas Devlieghere     // bundle like a .app bundle on MacOSX.
134c76fa8a3SGreg Clayton     Host::ResolveExecutableInBundle(module_spec.GetFileSpec());
135c76fa8a3SGreg Clayton 
136f4d6de6aSGreg Clayton     lldb::offset_t file_offset = 0;
1372540a8a7SGreg Clayton     lldb::offset_t file_size = 0;
1384add8536SJonas Devlieghere     ModuleSpecList module_specs;
139b9c1b51eSKate Stone     const size_t num_specs = ObjectFile::GetModuleSpecifications(
140b9c1b51eSKate Stone         module_spec.GetFileSpec(), file_offset, file_size, module_specs);
1414add8536SJonas Devlieghere 
142b9c1b51eSKate Stone     if (num_specs > 0) {
143f4d6de6aSGreg Clayton       ModuleSpec matching_module_spec;
144f4d6de6aSGreg Clayton 
145b9c1b51eSKate Stone       if (num_specs == 1) {
146b9c1b51eSKate Stone         if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec)) {
147b9c1b51eSKate Stone           if (platform_arch.IsValid()) {
148b9c1b51eSKate Stone             if (platform_arch.IsCompatibleMatch(
149b9c1b51eSKate Stone                     matching_module_spec.GetArchitecture())) {
1503f19ada8SGreg Clayton               // If the OS or vendor weren't specified, then adopt the module's
15105097246SAdrian Prantl               // architecture so that the platform matching can be more
1524add8536SJonas Devlieghere               // accurate.
1530fa520afSAdrian Prantl               update_platform_arch(matching_module_spec.GetArchitecture());
154b9c1b51eSKate Stone             } else {
1557df337f8STodd Fiala               StreamString platform_arch_strm;
1567df337f8STodd Fiala               StreamString module_arch_strm;
1577df337f8STodd Fiala 
1582f1e7b3dSRaphael Isemann               platform_arch.DumpTriple(platform_arch_strm.AsRawOstream());
159b9c1b51eSKate Stone               matching_module_spec.GetArchitecture().DumpTriple(
1602f1e7b3dSRaphael Isemann                   module_arch_strm.AsRawOstream());
161b9c1b51eSKate Stone               error.SetErrorStringWithFormat(
162b9c1b51eSKate Stone                   "the specified architecture '%s' is not compatible with '%s' "
163b9c1b51eSKate Stone                   "in '%s'",
164c156427dSZachary Turner                   platform_arch_strm.GetData(), module_arch_strm.GetData(),
165b5ad4ec7SGreg Clayton                   module_spec.GetFileSpec().GetPath().c_str());
166f4d6de6aSGreg Clayton               return error;
167f4d6de6aSGreg Clayton             }
168b9c1b51eSKate Stone           } else {
1694add8536SJonas Devlieghere             // Only one arch and none was specified.
1703f19ada8SGreg Clayton             prefer_platform_arch = true;
171f4d6de6aSGreg Clayton             platform_arch = matching_module_spec.GetArchitecture();
172f4d6de6aSGreg Clayton           }
173f4d6de6aSGreg Clayton         }
1744add8536SJonas Devlieghere       } else if (arch.IsValid()) {
1750fa520afSAdrian Prantl         // Fat binary. A (valid) architecture was specified.
176f4d6de6aSGreg Clayton         module_spec.GetArchitecture() = arch;
177b9c1b51eSKate Stone         if (module_specs.FindMatchingModuleSpec(module_spec,
1780fa520afSAdrian Prantl                                                 matching_module_spec))
1790fa520afSAdrian Prantl             update_platform_arch(matching_module_spec.GetArchitecture());
180b9c1b51eSKate Stone       } else {
1810fa520afSAdrian Prantl         // Fat binary. No architecture specified, check if there is
1820fa520afSAdrian Prantl         // only one platform for all of the architectures.
183a114ec0cSJonas Devlieghere         std::vector<PlatformSP> candidates;
184a114ec0cSJonas Devlieghere         std::vector<ArchSpec> archs;
185a114ec0cSJonas Devlieghere         for (const ModuleSpec &spec : module_specs.ModuleSpecs())
186a114ec0cSJonas Devlieghere           archs.push_back(spec.GetArchitecture());
187a114ec0cSJonas Devlieghere         if (PlatformSP platform_for_archs_sp =
188af921006SPavel Labath                 platform_list.GetOrCreate(archs, {}, candidates)) {
189a114ec0cSJonas Devlieghere           platform_sp = platform_for_archs_sp;
190a114ec0cSJonas Devlieghere         } else if (candidates.empty()) {
1914add8536SJonas Devlieghere           error.SetErrorString("no matching platforms found for this file");
1929d58c728SJason Molenda           return error;
193b9c1b51eSKate Stone         } else {
1944add8536SJonas Devlieghere           // More than one platform claims to support this file.
195b0cc53cfSGreg Clayton           StreamString error_strm;
196a114ec0cSJonas Devlieghere           std::set<llvm::StringRef> platform_set;
197b9c1b51eSKate Stone           error_strm.Printf(
198b9c1b51eSKate Stone               "more than one platform supports this executable (");
199a114ec0cSJonas Devlieghere           for (const auto &candidate : candidates) {
200a114ec0cSJonas Devlieghere             llvm::StringRef platform_name = candidate->GetName();
201a114ec0cSJonas Devlieghere             if (platform_set.count(platform_name))
202a114ec0cSJonas Devlieghere               continue;
203b0cc53cfSGreg Clayton             if (!platform_set.empty())
204b0cc53cfSGreg Clayton               error_strm.PutCString(", ");
205a114ec0cSJonas Devlieghere             error_strm.PutCString(platform_name);
206a114ec0cSJonas Devlieghere             platform_set.insert(platform_name);
207b0cc53cfSGreg Clayton           }
2084add8536SJonas Devlieghere           error_strm.Printf("), specify an architecture to disambiguate");
209c156427dSZachary Turner           error.SetErrorString(error_strm.GetString());
210b3a40ba8SGreg Clayton           return error;
211b3a40ba8SGreg Clayton         }
212b3a40ba8SGreg Clayton       }
213b0cc53cfSGreg Clayton     }
214b0cc53cfSGreg Clayton   }
215b3a40ba8SGreg Clayton 
216869e0c1cSTed Woodward   // If we have a valid architecture, make sure the current platform is
2174add8536SJonas Devlieghere   // compatible with that architecture.
218b9c1b51eSKate Stone   if (!prefer_platform_arch && arch.IsValid()) {
219dde487e5SJonas Devlieghere     if (!platform_sp->IsCompatibleArchitecture(arch, {}, false, nullptr)) {
220af921006SPavel Labath       platform_sp = platform_list.GetOrCreate(arch, {}, &platform_arch);
22116e5a347SVedant Kumar       if (platform_sp)
222af921006SPavel Labath         platform_list.SetSelectedPlatform(platform_sp);
22395bbdf64SGreg Clayton     }
224b9c1b51eSKate Stone   } else if (platform_arch.IsValid()) {
2254add8536SJonas Devlieghere     // If "arch" isn't valid, yet "platform_arch" is, it means we have an
2264add8536SJonas Devlieghere     // executable file with a single architecture which should be used.
2273f19ada8SGreg Clayton     ArchSpec fixed_platform_arch;
228af921006SPavel Labath     if (!platform_sp->IsCompatibleArchitecture(platform_arch, {}, false, nullptr)) {
229af921006SPavel Labath       platform_sp =
230af921006SPavel Labath           platform_list.GetOrCreate(platform_arch, {}, &fixed_platform_arch);
23116e5a347SVedant Kumar       if (platform_sp)
232af921006SPavel Labath         platform_list.SetSelectedPlatform(platform_sp);
23395bbdf64SGreg Clayton     }
2343f19ada8SGreg Clayton   }
235b3a40ba8SGreg Clayton 
23670512317SGreg Clayton   if (!platform_arch.IsValid())
23770512317SGreg Clayton     platform_arch = arch;
23870512317SGreg Clayton 
23916e5a347SVedant Kumar   return TargetList::CreateTargetInternal(debugger, user_exe_path,
24016e5a347SVedant Kumar                                           platform_arch, load_dependent_files,
24116e5a347SVedant Kumar                                           platform_sp, target_sp);
242893c932aSJim Ingham }
243893c932aSJim Ingham 
CreateTargetInternal(Debugger & debugger,llvm::StringRef user_exe_path,const ArchSpec & specified_arch,LoadDependentFiles load_dependent_files,lldb::PlatformSP & platform_sp,lldb::TargetSP & target_sp)24497206d57SZachary Turner Status TargetList::CreateTargetInternal(Debugger &debugger,
245a47464b2SZachary Turner                                         llvm::StringRef user_exe_path,
24670512317SGreg Clayton                                         const ArchSpec &specified_arch,
247f9a07e9fSJonas Devlieghere                                         LoadDependentFiles load_dependent_files,
248893c932aSJim Ingham                                         lldb::PlatformSP &platform_sp,
24916e5a347SVedant Kumar                                         lldb::TargetSP &target_sp) {
2505c1c8443SJonas Devlieghere   LLDB_SCOPED_TIMERF("TargetList::CreateTarget (file = '%s', arch = '%s')",
2515c1c8443SJonas Devlieghere                      user_exe_path.str().c_str(),
2525c1c8443SJonas Devlieghere                      specified_arch.GetArchitectureName());
25397206d57SZachary Turner   Status error;
25416e5a347SVedant Kumar   const bool is_dummy_target = false;
2555aee162fSJim Ingham 
25670512317SGreg Clayton   ArchSpec arch(specified_arch);
25770512317SGreg Clayton 
258b9c1b51eSKate Stone   if (arch.IsValid()) {
259b9c1b51eSKate Stone     if (!platform_sp ||
260dde487e5SJonas Devlieghere         !platform_sp->IsCompatibleArchitecture(arch, {}, false, nullptr))
261dde487e5SJonas Devlieghere       platform_sp =
262af921006SPavel Labath           debugger.GetPlatformList().GetOrCreate(specified_arch, {}, &arch);
26370512317SGreg Clayton   }
26470512317SGreg Clayton 
26570512317SGreg Clayton   if (!platform_sp)
26670512317SGreg Clayton     platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
267ded470d3SGreg Clayton 
2688ae50eb4SGreg Clayton   if (!arch.IsValid())
2698ae50eb4SGreg Clayton     arch = specified_arch;
2708ae50eb4SGreg Clayton 
2718f3be7a3SJonas Devlieghere   FileSpec file(user_exe_path);
272dbd7fabaSJonas Devlieghere   if (!FileSystem::Instance().Exists(file) && user_exe_path.startswith("~")) {
273b9c1b51eSKate Stone     // we want to expand the tilde but we don't want to resolve any symbolic
2748d48cd60SZachary Turner     // links so we can't use the FileSpec constructor's resolve flag
2758d48cd60SZachary Turner     llvm::SmallString<64> unglobbed_path;
27672787ac6SJonas Devlieghere     StandardTildeExpressionResolver Resolver;
27772787ac6SJonas Devlieghere     Resolver.ResolveFullPath(user_exe_path, unglobbed_path);
2789f822cd1SMichael Sartain 
2793f559740SZachary Turner     if (unglobbed_path.empty())
2808f3be7a3SJonas Devlieghere       file = FileSpec(user_exe_path);
2813f559740SZachary Turner     else
2828f3be7a3SJonas Devlieghere       file = FileSpec(unglobbed_path.c_str());
283d26206b5SJason Molenda   }
2849f822cd1SMichael Sartain 
28582d79295SGreg Clayton   bool user_exe_path_is_bundle = false;
28682d79295SGreg Clayton   char resolved_bundle_exe_path[PATH_MAX];
28782d79295SGreg Clayton   resolved_bundle_exe_path[0] = '\0';
288b9c1b51eSKate Stone   if (file) {
2893a58d898SJonas Devlieghere     if (FileSystem::Instance().IsDirectory(file))
29082d79295SGreg Clayton       user_exe_path_is_bundle = true;
29182d79295SGreg Clayton 
292a47464b2SZachary Turner     if (file.IsRelative() && !user_exe_path.empty()) {
2931d5855b1SPavel Labath       llvm::SmallString<64> cwd;
2941d5855b1SPavel Labath       if (! llvm::sys::fs::current_path(cwd)) {
2958f3be7a3SJonas Devlieghere         FileSpec cwd_file(cwd.c_str());
296d68dbd5aSGreg Clayton         cwd_file.AppendPathComponent(file);
297dbd7fabaSJonas Devlieghere         if (FileSystem::Instance().Exists(cwd_file))
2989ff5aae5SGreg Clayton           file = cwd_file;
299a0ca6601SGreg Clayton       }
300a0ca6601SGreg Clayton     }
301a0ca6601SGreg Clayton 
30230fdc8d8SChris Lattner     ModuleSP exe_module_sp;
303b9c1b51eSKate Stone     if (platform_sp) {
304b9c1b51eSKate Stone       FileSpecList executable_search_paths(
305b9c1b51eSKate Stone           Target::GetDefaultExecutableSearchPaths());
3068012cadbSGreg Clayton       ModuleSpec module_spec(file, arch);
307b9c1b51eSKate Stone       error = platform_sp->ResolveExecutable(module_spec, exe_module_sp,
308b9c1b51eSKate Stone                                              executable_search_paths.GetSize()
309b9c1b51eSKate Stone                                                  ? &executable_search_paths
310b9c1b51eSKate Stone                                                  : nullptr);
311c859e2d5SGreg Clayton     }
312428a9a58SCaroline Tice 
313b9c1b51eSKate Stone     if (error.Success() && exe_module_sp) {
314b9c1b51eSKate Stone       if (exe_module_sp->GetObjectFile() == nullptr) {
315b9c1b51eSKate Stone         if (arch.IsValid()) {
316b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
317b9c1b51eSKate Stone               "\"%s\" doesn't contain architecture %s", file.GetPath().c_str(),
31864195a2cSGreg Clayton               arch.GetArchitectureName());
319b9c1b51eSKate Stone         } else {
320b5ad4ec7SGreg Clayton           error.SetErrorStringWithFormat("unsupported file type \"%s\"",
321b5ad4ec7SGreg Clayton                                          file.GetPath().c_str());
322bc5cad6cSGreg Clayton         }
3235aee162fSJim Ingham         return error;
3245aee162fSJim Ingham       }
325893c932aSJim Ingham       target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
326f9a07e9fSJonas Devlieghere       target_sp->SetExecutableModule(exe_module_sp, load_dependent_files);
32782d79295SGreg Clayton       if (user_exe_path_is_bundle)
328b9c1b51eSKate Stone         exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path,
329b9c1b51eSKate Stone                                              sizeof(resolved_bundle_exe_path));
330631048e8SLevon Ter-Grigoryan       if (target_sp->GetPreloadSymbols())
331631048e8SLevon Ter-Grigoryan         exe_module_sp->PreloadSymbols();
3325aee162fSJim Ingham     }
333b9c1b51eSKate Stone   } else {
33405097246SAdrian Prantl     // No file was specified, just create an empty target with any arch if a
33505097246SAdrian Prantl     // valid arch was specified
336893c932aSJim Ingham     target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
337e996fd30SGreg Clayton   }
3381559a46bSCaroline Tice 
3395110fd03SAdrian Prantl   if (!target_sp)
3405110fd03SAdrian Prantl     return error;
3415110fd03SAdrian Prantl 
34282d79295SGreg Clayton   // Set argv0 with what the user typed, unless the user specified a
34382d79295SGreg Clayton   // directory. If the user specified a directory, then it is probably a
34482d79295SGreg Clayton   // bundle that was resolved and we need to use the resolved bundle path
345a47464b2SZachary Turner   if (!user_exe_path.empty()) {
346b9c1b51eSKate Stone     // Use exactly what the user typed as the first argument when we exec or
347b9c1b51eSKate Stone     // posix_spawn
348b9c1b51eSKate Stone     if (user_exe_path_is_bundle && resolved_bundle_exe_path[0]) {
34982d79295SGreg Clayton       target_sp->SetArg0(resolved_bundle_exe_path);
350b9c1b51eSKate Stone     } else {
3519f822cd1SMichael Sartain       // Use resolved path
3529f822cd1SMichael Sartain       target_sp->SetArg0(file.GetPath().c_str());
353a0ca6601SGreg Clayton     }
35482d79295SGreg Clayton   }
355b9c1b51eSKate Stone   if (file.GetDirectory()) {
356a0ca6601SGreg Clayton     FileSpec file_dir;
357*1b4b12a3SNico Weber     file_dir.GetDirectory() = file.GetDirectory();
358acbf0058SFrederic Riss     target_sp->AppendExecutableSearchPaths(file_dir);
359a0ca6601SGreg Clayton   }
360893c932aSJim Ingham 
36133df7cd3SJim Ingham   // Now prime this from the dummy target:
36233df7cd3SJim Ingham   target_sp->PrimeFromDummyTarget(debugger.GetDummyTarget());
36330fdc8d8SChris Lattner 
36430fdc8d8SChris Lattner   return error;
36530fdc8d8SChris Lattner }
36630fdc8d8SChris Lattner 
DeleteTarget(TargetSP & target_sp)367b9c1b51eSKate Stone bool TargetList::DeleteTarget(TargetSP &target_sp) {
36816ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
3697832d7e9STatyana Krasnukha   auto it = std::find(m_target_list.begin(), m_target_list.end(), target_sp);
3707832d7e9STatyana Krasnukha   if (it == m_target_list.end())
37130fdc8d8SChris Lattner     return false;
3727832d7e9STatyana Krasnukha 
3737832d7e9STatyana Krasnukha   m_target_list.erase(it);
3747832d7e9STatyana Krasnukha   return true;
37530fdc8d8SChris Lattner }
37630fdc8d8SChris Lattner 
FindTargetWithExecutableAndArchitecture(const FileSpec & exe_file_spec,const ArchSpec * exe_arch_ptr) const377b9c1b51eSKate Stone TargetSP TargetList::FindTargetWithExecutableAndArchitecture(
378b9c1b51eSKate Stone     const FileSpec &exe_file_spec, const ArchSpec *exe_arch_ptr) const {
37916ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
3807832d7e9STatyana Krasnukha   auto it = std::find_if(m_target_list.begin(), m_target_list.end(),
3817832d7e9STatyana Krasnukha       [&exe_file_spec, exe_arch_ptr](const TargetSP &item) {
3827832d7e9STatyana Krasnukha         Module *exe_module = item->GetExecutableModulePointer();
3837832d7e9STatyana Krasnukha         if (!exe_module ||
3847832d7e9STatyana Krasnukha             !FileSpec::Match(exe_file_spec, exe_module->GetFileSpec()))
3857832d7e9STatyana Krasnukha           return false;
38630fdc8d8SChris Lattner 
3877832d7e9STatyana Krasnukha         return !exe_arch_ptr ||
3887832d7e9STatyana Krasnukha                exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture());
3897832d7e9STatyana Krasnukha       });
3907832d7e9STatyana Krasnukha 
3917832d7e9STatyana Krasnukha   if (it != m_target_list.end())
3927832d7e9STatyana Krasnukha     return *it;
3937832d7e9STatyana Krasnukha 
3947832d7e9STatyana Krasnukha   return TargetSP();
39530fdc8d8SChris Lattner }
39630fdc8d8SChris Lattner 
FindTargetWithProcessID(lldb::pid_t pid) const397b9c1b51eSKate Stone TargetSP TargetList::FindTargetWithProcessID(lldb::pid_t pid) const {
39816ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
3997832d7e9STatyana Krasnukha   auto it = std::find_if(m_target_list.begin(), m_target_list.end(),
4007832d7e9STatyana Krasnukha       [pid](const TargetSP &item) {
4017832d7e9STatyana Krasnukha         auto *process_ptr = item->GetProcessSP().get();
4027832d7e9STatyana Krasnukha         return process_ptr && (process_ptr->GetID() == pid);
4037832d7e9STatyana Krasnukha       });
4047832d7e9STatyana Krasnukha 
4057832d7e9STatyana Krasnukha   if (it != m_target_list.end())
4067832d7e9STatyana Krasnukha     return *it;
4077832d7e9STatyana Krasnukha 
4087832d7e9STatyana Krasnukha   return TargetSP();
40930fdc8d8SChris Lattner }
41030fdc8d8SChris Lattner 
FindTargetWithProcess(Process * process) const411b9c1b51eSKate Stone TargetSP TargetList::FindTargetWithProcess(Process *process) const {
41230fdc8d8SChris Lattner   TargetSP target_sp;
4137832d7e9STatyana Krasnukha   if (!process)
4147832d7e9STatyana Krasnukha     return target_sp;
4157832d7e9STatyana Krasnukha 
41616ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
4177832d7e9STatyana Krasnukha   auto it = std::find_if(m_target_list.begin(), m_target_list.end(),
4187832d7e9STatyana Krasnukha       [process](const TargetSP &item) {
4197832d7e9STatyana Krasnukha         return item->GetProcessSP().get() == process;
4207832d7e9STatyana Krasnukha       });
4217832d7e9STatyana Krasnukha 
4227832d7e9STatyana Krasnukha   if (it != m_target_list.end())
4237832d7e9STatyana Krasnukha     target_sp = *it;
4247832d7e9STatyana Krasnukha 
42530fdc8d8SChris Lattner   return target_sp;
42630fdc8d8SChris Lattner }
42730fdc8d8SChris Lattner 
GetTargetSP(Target * target) const428b9c1b51eSKate Stone TargetSP TargetList::GetTargetSP(Target *target) const {
42930fdc8d8SChris Lattner   TargetSP target_sp;
4307832d7e9STatyana Krasnukha   if (!target)
4317832d7e9STatyana Krasnukha     return target_sp;
4327832d7e9STatyana Krasnukha 
43316ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
4347832d7e9STatyana Krasnukha   auto it = std::find_if(m_target_list.begin(), m_target_list.end(),
4357832d7e9STatyana Krasnukha       [target](const TargetSP &item) { return item.get() == target; });
4367832d7e9STatyana Krasnukha   if (it != m_target_list.end())
4377832d7e9STatyana Krasnukha     target_sp = *it;
4387832d7e9STatyana Krasnukha 
43930fdc8d8SChris Lattner   return target_sp;
44030fdc8d8SChris Lattner }
44130fdc8d8SChris Lattner 
SendAsyncInterrupt(lldb::pid_t pid)442b9c1b51eSKate Stone uint32_t TargetList::SendAsyncInterrupt(lldb::pid_t pid) {
44330fdc8d8SChris Lattner   uint32_t num_async_interrupts_sent = 0;
44430fdc8d8SChris Lattner 
445b9c1b51eSKate Stone   if (pid != LLDB_INVALID_PROCESS_ID) {
44630fdc8d8SChris Lattner     TargetSP target_sp(FindTargetWithProcessID(pid));
447b9c1b51eSKate Stone     if (target_sp) {
44830fdc8d8SChris Lattner       Process *process = target_sp->GetProcessSP().get();
449b9c1b51eSKate Stone       if (process) {
450cfc0935eSJim Ingham         process->SendAsyncInterrupt();
45130fdc8d8SChris Lattner         ++num_async_interrupts_sent;
45230fdc8d8SChris Lattner       }
45330fdc8d8SChris Lattner     }
454b9c1b51eSKate Stone   } else {
45530fdc8d8SChris Lattner     // We don't have a valid pid to broadcast to, so broadcast to the target
45630fdc8d8SChris Lattner     // list's async broadcaster...
457e65b2cf2SEugene Zelenko     BroadcastEvent(Process::eBroadcastBitInterrupt, nullptr);
45830fdc8d8SChris Lattner   }
45930fdc8d8SChris Lattner 
46030fdc8d8SChris Lattner   return num_async_interrupts_sent;
46130fdc8d8SChris Lattner }
46230fdc8d8SChris Lattner 
SignalIfRunning(lldb::pid_t pid,int signo)463b9c1b51eSKate Stone uint32_t TargetList::SignalIfRunning(lldb::pid_t pid, int signo) {
46430fdc8d8SChris Lattner   uint32_t num_signals_sent = 0;
465e65b2cf2SEugene Zelenko   Process *process = nullptr;
466b9c1b51eSKate Stone   if (pid == LLDB_INVALID_PROCESS_ID) {
46730fdc8d8SChris Lattner     // Signal all processes with signal
46816ff8604SSaleem Abdulrasool     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
4697832d7e9STatyana Krasnukha     for (const auto &target_sp : m_target_list) {
4707832d7e9STatyana Krasnukha       process = target_sp->GetProcessSP().get();
4717832d7e9STatyana Krasnukha       if (process && process->IsAlive()) {
47230fdc8d8SChris Lattner         ++num_signals_sent;
47330fdc8d8SChris Lattner         process->Signal(signo);
47430fdc8d8SChris Lattner       }
47530fdc8d8SChris Lattner     }
476b9c1b51eSKate Stone   } else {
47730fdc8d8SChris Lattner     // Signal a specific process with signal
47830fdc8d8SChris Lattner     TargetSP target_sp(FindTargetWithProcessID(pid));
479b9c1b51eSKate Stone     if (target_sp) {
48030fdc8d8SChris Lattner       process = target_sp->GetProcessSP().get();
4817832d7e9STatyana Krasnukha       if (process && process->IsAlive()) {
48230fdc8d8SChris Lattner         ++num_signals_sent;
48330fdc8d8SChris Lattner         process->Signal(signo);
48430fdc8d8SChris Lattner       }
48530fdc8d8SChris Lattner     }
48630fdc8d8SChris Lattner   }
48730fdc8d8SChris Lattner   return num_signals_sent;
48830fdc8d8SChris Lattner }
48930fdc8d8SChris Lattner 
GetNumTargets() const490b9c1b51eSKate Stone int TargetList::GetNumTargets() const {
49116ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
49230fdc8d8SChris Lattner   return m_target_list.size();
49330fdc8d8SChris Lattner }
49430fdc8d8SChris Lattner 
GetTargetAtIndex(uint32_t idx) const495b9c1b51eSKate Stone lldb::TargetSP TargetList::GetTargetAtIndex(uint32_t idx) const {
49630fdc8d8SChris Lattner   TargetSP target_sp;
49716ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
49830fdc8d8SChris Lattner   if (idx < m_target_list.size())
49930fdc8d8SChris Lattner     target_sp = m_target_list[idx];
50030fdc8d8SChris Lattner   return target_sp;
50130fdc8d8SChris Lattner }
50230fdc8d8SChris Lattner 
GetIndexOfTarget(lldb::TargetSP target_sp) const503b9c1b51eSKate Stone uint32_t TargetList::GetIndexOfTarget(lldb::TargetSP target_sp) const {
50416ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
5057832d7e9STatyana Krasnukha   auto it = std::find(m_target_list.begin(), m_target_list.end(), target_sp);
5067832d7e9STatyana Krasnukha   if (it != m_target_list.end())
5077832d7e9STatyana Krasnukha     return std::distance(m_target_list.begin(), it);
5088499e1a4SJim Ingham   return UINT32_MAX;
5098499e1a4SJim Ingham }
5108499e1a4SJim Ingham 
AddTargetInternal(TargetSP target_sp,bool do_select)5112634ec6cSTatyana Krasnukha void TargetList::AddTargetInternal(TargetSP target_sp, bool do_select) {
512360c1111SKazu Hirata   lldbassert(!llvm::is_contained(m_target_list, target_sp) &&
5132634ec6cSTatyana Krasnukha              "target already exists it the list");
5142634ec6cSTatyana Krasnukha   m_target_list.push_back(std::move(target_sp));
5152634ec6cSTatyana Krasnukha   if (do_select)
5162634ec6cSTatyana Krasnukha     SetSelectedTargetInternal(m_target_list.size() - 1);
5172634ec6cSTatyana Krasnukha }
5182634ec6cSTatyana Krasnukha 
SetSelectedTargetInternal(uint32_t index)5192634ec6cSTatyana Krasnukha void TargetList::SetSelectedTargetInternal(uint32_t index) {
5202634ec6cSTatyana Krasnukha   lldbassert(!m_target_list.empty());
5212634ec6cSTatyana Krasnukha   m_selected_target_idx = index < m_target_list.size() ? index : 0;
5222634ec6cSTatyana Krasnukha }
5232634ec6cSTatyana Krasnukha 
SetSelectedTarget(uint32_t index)5242634ec6cSTatyana Krasnukha void TargetList::SetSelectedTarget(uint32_t index) {
52516ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
5262634ec6cSTatyana Krasnukha   SetSelectedTargetInternal(index);
52730fdc8d8SChris Lattner }
5282634ec6cSTatyana Krasnukha 
SetSelectedTarget(const TargetSP & target_sp)5292634ec6cSTatyana Krasnukha void TargetList::SetSelectedTarget(const TargetSP &target_sp) {
5302634ec6cSTatyana Krasnukha   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
5312634ec6cSTatyana Krasnukha   auto it = std::find(m_target_list.begin(), m_target_list.end(), target_sp);
5322634ec6cSTatyana Krasnukha   SetSelectedTargetInternal(std::distance(m_target_list.begin(), it));
53330fdc8d8SChris Lattner }
53430fdc8d8SChris Lattner 
GetSelectedTarget()535b9c1b51eSKate Stone lldb::TargetSP TargetList::GetSelectedTarget() {
53616ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
5372976d00aSJim Ingham   if (m_selected_target_idx >= m_target_list.size())
5382976d00aSJim Ingham     m_selected_target_idx = 0;
5392976d00aSJim Ingham   return GetTargetAtIndex(m_selected_target_idx);
54030fdc8d8SChris Lattner }
541