130fdc8d8SChris Lattner //===-- TargetList.cpp ------------------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
1030fdc8d8SChris Lattner // Project includes
11fb1a0a0dSZachary Turner #include "lldb/Target/TargetList.h"
1230fdc8d8SChris Lattner #include "lldb/Core/Broadcaster.h"
13ded470d3SGreg Clayton #include "lldb/Core/Debugger.h"
1430fdc8d8SChris Lattner #include "lldb/Core/Event.h"
151f746071SGreg Clayton #include "lldb/Core/Module.h"
16f4d6de6aSGreg Clayton #include "lldb/Core/ModuleSpec.h"
1730fdc8d8SChris Lattner #include "lldb/Core/State.h"
1830fdc8d8SChris Lattner #include "lldb/Host/Host.h"
19893c932aSJim Ingham #include "lldb/Host/HostInfo.h"
20b3a40ba8SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
21cac9c5f9SGreg Clayton #include "lldb/Interpreter/OptionGroupPlatform.h"
22f4d6de6aSGreg Clayton #include "lldb/Symbol/ObjectFile.h"
23e996fd30SGreg Clayton #include "lldb/Target/Platform.h"
2430fdc8d8SChris Lattner #include "lldb/Target/Process.h"
258d48cd60SZachary Turner #include "lldb/Utility/TildeExpressionResolver.h"
2638d0632eSPavel Labath #include "lldb/Utility/Timer.h"
2730fdc8d8SChris Lattner 
281d5855b1SPavel Labath // Other libraries and framework includes
291d5855b1SPavel Labath #include "llvm/ADT/SmallString.h"
301d5855b1SPavel Labath #include "llvm/Support/FileSystem.h"
311d5855b1SPavel Labath 
3230fdc8d8SChris Lattner using namespace lldb;
3330fdc8d8SChris Lattner using namespace lldb_private;
3430fdc8d8SChris Lattner 
35b9c1b51eSKate Stone ConstString &TargetList::GetStaticBroadcasterClass() {
364bddaeb5SJim Ingham   static ConstString class_name("lldb.targetList");
374bddaeb5SJim Ingham   return class_name;
384bddaeb5SJim Ingham }
3930fdc8d8SChris Lattner 
4030fdc8d8SChris Lattner //----------------------------------------------------------------------
4130fdc8d8SChris Lattner // TargetList constructor
4230fdc8d8SChris Lattner //----------------------------------------------------------------------
4316ff8604SSaleem Abdulrasool TargetList::TargetList(Debugger &debugger)
44b9c1b51eSKate Stone     : Broadcaster(debugger.GetBroadcasterManager(),
45b9c1b51eSKate Stone                   TargetList::GetStaticBroadcasterClass().AsCString()),
46b9c1b51eSKate Stone       m_target_list(), m_target_list_mutex(), m_selected_target_idx(0) {
474bddaeb5SJim Ingham   CheckInWithManager();
4830fdc8d8SChris Lattner }
4930fdc8d8SChris Lattner 
5030fdc8d8SChris Lattner //----------------------------------------------------------------------
5130fdc8d8SChris Lattner // Destructor
5230fdc8d8SChris Lattner //----------------------------------------------------------------------
53b9c1b51eSKate Stone TargetList::~TargetList() {
5416ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
5530fdc8d8SChris Lattner   m_target_list.clear();
5630fdc8d8SChris Lattner }
5730fdc8d8SChris Lattner 
5897206d57SZachary Turner Status TargetList::CreateTarget(Debugger &debugger,
59a47464b2SZachary Turner                                 llvm::StringRef user_exe_path,
60a47464b2SZachary Turner                                 llvm::StringRef triple_str,
61cac9c5f9SGreg Clayton                                 bool get_dependent_files,
62cac9c5f9SGreg Clayton                                 const OptionGroupPlatform *platform_options,
63b9c1b51eSKate Stone                                 TargetSP &target_sp) {
64a47464b2SZachary Turner   return CreateTargetInternal(debugger, user_exe_path, triple_str,
65b9c1b51eSKate Stone                               get_dependent_files, platform_options, target_sp,
66893c932aSJim Ingham                               false);
67893c932aSJim Ingham }
68893c932aSJim Ingham 
6997206d57SZachary Turner Status TargetList::CreateTarget(Debugger &debugger,
70a47464b2SZachary Turner                                 llvm::StringRef user_exe_path,
71893c932aSJim Ingham                                 const ArchSpec &specified_arch,
72893c932aSJim Ingham                                 bool get_dependent_files,
73b9c1b51eSKate Stone                                 PlatformSP &platform_sp, TargetSP &target_sp) {
74b9c1b51eSKate Stone   return CreateTargetInternal(debugger, user_exe_path, specified_arch,
75b9c1b51eSKate Stone                               get_dependent_files, platform_sp, target_sp,
76893c932aSJim Ingham                               false);
77893c932aSJim Ingham }
78893c932aSJim Ingham 
7997206d57SZachary Turner Status TargetList::CreateTargetInternal(
80a47464b2SZachary Turner     Debugger &debugger, llvm::StringRef user_exe_path,
81a47464b2SZachary Turner     llvm::StringRef triple_str, bool get_dependent_files,
82a47464b2SZachary Turner     const OptionGroupPlatform *platform_options, TargetSP &target_sp,
83a47464b2SZachary Turner     bool is_dummy_target) {
8497206d57SZachary Turner   Status error;
85cac9c5f9SGreg Clayton   PlatformSP platform_sp;
86cac9c5f9SGreg Clayton 
8705097246SAdrian Prantl   // This is purposely left empty unless it is specified by triple_cstr. If not
8805097246SAdrian Prantl   // initialized via triple_cstr, then the currently selected platform will set
8905097246SAdrian Prantl   // the architecture correctly.
90a47464b2SZachary Turner   const ArchSpec arch(triple_str);
91a47464b2SZachary Turner   if (!triple_str.empty()) {
92b9c1b51eSKate Stone     if (!arch.IsValid()) {
93a47464b2SZachary Turner       error.SetErrorStringWithFormat("invalid triple '%s'",
94a47464b2SZachary Turner                                      triple_str.str().c_str());
95cac9c5f9SGreg Clayton       return error;
96cac9c5f9SGreg Clayton     }
97cac9c5f9SGreg Clayton   }
98b3a40ba8SGreg Clayton 
9970512317SGreg Clayton   ArchSpec platform_arch(arch);
100f4d6de6aSGreg Clayton 
1013f19ada8SGreg Clayton   bool prefer_platform_arch = false;
102f4d6de6aSGreg Clayton 
103b0cc53cfSGreg Clayton   CommandInterpreter &interpreter = debugger.GetCommandInterpreter();
1041b5a74eeSVince Harron 
1054ebdee0aSBruce Mitchener   // let's see if there is already an existing platform before we go creating
106b9c1b51eSKate Stone   // another...
1071b5a74eeSVince Harron   platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
1081b5a74eeSVince Harron 
109b9c1b51eSKate Stone   if (platform_options && platform_options->PlatformWasSpecified()) {
110ccd2a6d9SGreg Clayton     // Create a new platform if it doesn't match the selected platform
111b9c1b51eSKate Stone     if (!platform_options->PlatformMatches(platform_sp)) {
112b0cc53cfSGreg Clayton       const bool select_platform = true;
113b9c1b51eSKate Stone       platform_sp = platform_options->CreatePlatformWithOptions(
114b9c1b51eSKate Stone           interpreter, arch, select_platform, error, platform_arch);
115b0cc53cfSGreg Clayton       if (!platform_sp)
116b0cc53cfSGreg Clayton         return error;
117b0cc53cfSGreg Clayton     }
118ccd2a6d9SGreg Clayton   }
119b0cc53cfSGreg Clayton 
120a47464b2SZachary Turner   if (!user_exe_path.empty()) {
121f4d6de6aSGreg Clayton     ModuleSpecList module_specs;
122f4d6de6aSGreg Clayton     ModuleSpec module_spec;
123*937348cdSJonas Devlieghere     module_spec.GetFileSpec().SetFile(user_exe_path, true,
124*937348cdSJonas Devlieghere                                       FileSpec::Style::native);
125c76fa8a3SGreg Clayton 
126b9c1b51eSKate Stone     // Resolve the executable in case we are given a path to a application
12705097246SAdrian Prantl     // bundle like a .app bundle on MacOSX
128c76fa8a3SGreg Clayton     Host::ResolveExecutableInBundle(module_spec.GetFileSpec());
129c76fa8a3SGreg Clayton 
130f4d6de6aSGreg Clayton     lldb::offset_t file_offset = 0;
1312540a8a7SGreg Clayton     lldb::offset_t file_size = 0;
132b9c1b51eSKate Stone     const size_t num_specs = ObjectFile::GetModuleSpecifications(
133b9c1b51eSKate Stone         module_spec.GetFileSpec(), file_offset, file_size, module_specs);
134b9c1b51eSKate Stone     if (num_specs > 0) {
135f4d6de6aSGreg Clayton       ModuleSpec matching_module_spec;
136f4d6de6aSGreg Clayton 
137b9c1b51eSKate Stone       if (num_specs == 1) {
138b9c1b51eSKate Stone         if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec)) {
139b9c1b51eSKate Stone           if (platform_arch.IsValid()) {
140b9c1b51eSKate Stone             if (platform_arch.IsCompatibleMatch(
141b9c1b51eSKate Stone                     matching_module_spec.GetArchitecture())) {
1423f19ada8SGreg Clayton               // If the OS or vendor weren't specified, then adopt the module's
14305097246SAdrian Prantl               // architecture so that the platform matching can be more
14405097246SAdrian Prantl               // accurate
145b9c1b51eSKate Stone               if (!platform_arch.TripleOSWasSpecified() ||
146b9c1b51eSKate Stone                   !platform_arch.TripleVendorWasSpecified()) {
1473f19ada8SGreg Clayton                 prefer_platform_arch = true;
1483f19ada8SGreg Clayton                 platform_arch = matching_module_spec.GetArchitecture();
1493f19ada8SGreg Clayton               }
150b9c1b51eSKate Stone             } else {
1517df337f8STodd Fiala               StreamString platform_arch_strm;
1527df337f8STodd Fiala               StreamString module_arch_strm;
1537df337f8STodd Fiala 
1547df337f8STodd Fiala               platform_arch.DumpTriple(platform_arch_strm);
155b9c1b51eSKate Stone               matching_module_spec.GetArchitecture().DumpTriple(
156b9c1b51eSKate Stone                   module_arch_strm);
157b9c1b51eSKate Stone               error.SetErrorStringWithFormat(
158b9c1b51eSKate Stone                   "the specified architecture '%s' is not compatible with '%s' "
159b9c1b51eSKate Stone                   "in '%s'",
160c156427dSZachary Turner                   platform_arch_strm.GetData(), module_arch_strm.GetData(),
161b5ad4ec7SGreg Clayton                   module_spec.GetFileSpec().GetPath().c_str());
162f4d6de6aSGreg Clayton               return error;
163f4d6de6aSGreg Clayton             }
164b9c1b51eSKate Stone           } else {
165f4d6de6aSGreg Clayton             // Only one arch and none was specified
1663f19ada8SGreg Clayton             prefer_platform_arch = true;
167f4d6de6aSGreg Clayton             platform_arch = matching_module_spec.GetArchitecture();
168f4d6de6aSGreg Clayton           }
169f4d6de6aSGreg Clayton         }
170b9c1b51eSKate Stone       } else {
171b9c1b51eSKate Stone         if (arch.IsValid()) {
172f4d6de6aSGreg Clayton           module_spec.GetArchitecture() = arch;
173b9c1b51eSKate Stone           if (module_specs.FindMatchingModuleSpec(module_spec,
174b9c1b51eSKate Stone                                                   matching_module_spec)) {
1753f19ada8SGreg Clayton             prefer_platform_arch = true;
176f4d6de6aSGreg Clayton             platform_arch = matching_module_spec.GetArchitecture();
177f4d6de6aSGreg Clayton           }
178b9c1b51eSKate Stone         } else {
179b0cc53cfSGreg Clayton           // No architecture specified, check if there is only one platform for
180b0cc53cfSGreg Clayton           // all of the architectures.
181b0cc53cfSGreg Clayton 
182b0cc53cfSGreg Clayton           typedef std::vector<PlatformSP> PlatformList;
183b0cc53cfSGreg Clayton           PlatformList platforms;
184615eb7e6SGreg Clayton           PlatformSP host_platform_sp = Platform::GetHostPlatform();
185b9c1b51eSKate Stone           for (size_t i = 0; i < num_specs; ++i) {
186b0cc53cfSGreg Clayton             ModuleSpec module_spec;
187b9c1b51eSKate Stone             if (module_specs.GetModuleSpecAtIndex(i, module_spec)) {
188b0cc53cfSGreg Clayton               // See if there was a selected platform and check that first
189b0cc53cfSGreg Clayton               // since the user may have specified it.
190b9c1b51eSKate Stone               if (platform_sp) {
191b9c1b51eSKate Stone                 if (platform_sp->IsCompatibleArchitecture(
192b9c1b51eSKate Stone                         module_spec.GetArchitecture(), false, nullptr)) {
193b0cc53cfSGreg Clayton                   platforms.push_back(platform_sp);
194b0cc53cfSGreg Clayton                   continue;
195f4d6de6aSGreg Clayton                 }
196f4d6de6aSGreg Clayton               }
197f4d6de6aSGreg Clayton 
19805097246SAdrian Prantl               // Next check the host platform it if wasn't already checked
19905097246SAdrian Prantl               // above
200b9c1b51eSKate Stone               if (host_platform_sp &&
201b9c1b51eSKate Stone                   (!platform_sp ||
202b9c1b51eSKate Stone                    host_platform_sp->GetName() != platform_sp->GetName())) {
203b9c1b51eSKate Stone                 if (host_platform_sp->IsCompatibleArchitecture(
204b9c1b51eSKate Stone                         module_spec.GetArchitecture(), false, nullptr)) {
205b0cc53cfSGreg Clayton                   platforms.push_back(host_platform_sp);
206b0cc53cfSGreg Clayton                   continue;
207b0cc53cfSGreg Clayton                 }
208b0cc53cfSGreg Clayton               }
209b0cc53cfSGreg Clayton 
210b9c1b51eSKate Stone               // Just find a platform that matches the architecture in the
211b9c1b51eSKate Stone               // executable file
212b9c1b51eSKate Stone               PlatformSP fallback_platform_sp(
213b9c1b51eSKate Stone                   Platform::GetPlatformForArchitecture(
214b9c1b51eSKate Stone                       module_spec.GetArchitecture(), nullptr));
215b9c1b51eSKate Stone               if (fallback_platform_sp) {
216e92a74ceSJason Molenda                 platforms.push_back(fallback_platform_sp);
217e92a74ceSJason Molenda               }
218b0cc53cfSGreg Clayton             }
219b0cc53cfSGreg Clayton           }
220b0cc53cfSGreg Clayton 
221e65b2cf2SEugene Zelenko           Platform *platform_ptr = nullptr;
2229d58c728SJason Molenda           bool more_than_one_platforms = false;
223b9c1b51eSKate Stone           for (const auto &the_platform_sp : platforms) {
224b9c1b51eSKate Stone             if (platform_ptr) {
225b9c1b51eSKate Stone               if (platform_ptr->GetName() != the_platform_sp->GetName()) {
2269d58c728SJason Molenda                 more_than_one_platforms = true;
227e65b2cf2SEugene Zelenko                 platform_ptr = nullptr;
228b0cc53cfSGreg Clayton                 break;
229b0cc53cfSGreg Clayton               }
230b9c1b51eSKate Stone             } else {
231b0cc53cfSGreg Clayton               platform_ptr = the_platform_sp.get();
232b0cc53cfSGreg Clayton             }
233b0cc53cfSGreg Clayton           }
234b0cc53cfSGreg Clayton 
235b9c1b51eSKate Stone           if (platform_ptr) {
2364ebdee0aSBruce Mitchener             // All platforms for all modules in the executable match, so we can
237b9c1b51eSKate Stone             // select this platform
238b0cc53cfSGreg Clayton             platform_sp = platforms.front();
239b9c1b51eSKate Stone           } else if (more_than_one_platforms == false) {
2409d58c728SJason Molenda             // No platforms claim to support this file
241b9c1b51eSKate Stone             error.SetErrorString("No matching platforms found for this file, "
242b9c1b51eSKate Stone                                  "specify one with the --platform option");
2439d58c728SJason Molenda             return error;
244b9c1b51eSKate Stone           } else {
245b9c1b51eSKate Stone             // More than one platform claims to support this file, so the
246b9c1b51eSKate Stone             // --platform option must be specified
247b0cc53cfSGreg Clayton             StreamString error_strm;
248b0cc53cfSGreg Clayton             std::set<Platform *> platform_set;
249b9c1b51eSKate Stone             error_strm.Printf(
250b9c1b51eSKate Stone                 "more than one platform supports this executable (");
251b9c1b51eSKate Stone             for (const auto &the_platform_sp : platforms) {
252b9c1b51eSKate Stone               if (platform_set.find(the_platform_sp.get()) ==
253b9c1b51eSKate Stone                   platform_set.end()) {
254b0cc53cfSGreg Clayton                 if (!platform_set.empty())
255b0cc53cfSGreg Clayton                   error_strm.PutCString(", ");
256b0cc53cfSGreg Clayton                 error_strm.PutCString(the_platform_sp->GetName().GetCString());
257b0cc53cfSGreg Clayton                 platform_set.insert(the_platform_sp.get());
258b0cc53cfSGreg Clayton               }
259b0cc53cfSGreg Clayton             }
260b9c1b51eSKate Stone             error_strm.Printf(
261b9c1b51eSKate Stone                 "), use the --platform option to specify a platform");
262c156427dSZachary Turner             error.SetErrorString(error_strm.GetString());
263b3a40ba8SGreg Clayton             return error;
264b3a40ba8SGreg Clayton           }
265b3a40ba8SGreg Clayton         }
266b0cc53cfSGreg Clayton       }
267b0cc53cfSGreg Clayton     }
268b0cc53cfSGreg Clayton   }
269b3a40ba8SGreg Clayton 
270869e0c1cSTed Woodward   // If we have a valid architecture, make sure the current platform is
271869e0c1cSTed Woodward   // compatible with that architecture
272b9c1b51eSKate Stone   if (!prefer_platform_arch && arch.IsValid()) {
273b9c1b51eSKate Stone     if (!platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) {
27470512317SGreg Clayton       platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch);
2758ec55a53SRobert Flack       if (!is_dummy_target && platform_sp)
27695bbdf64SGreg Clayton         debugger.GetPlatformList().SetSelectedPlatform(platform_sp);
27795bbdf64SGreg Clayton     }
278b9c1b51eSKate Stone   } else if (platform_arch.IsValid()) {
279b9c1b51eSKate Stone     // if "arch" isn't valid, yet "platform_arch" is, it means we have an
28005097246SAdrian Prantl     // executable file with a single architecture which should be used
2813f19ada8SGreg Clayton     ArchSpec fixed_platform_arch;
282b9c1b51eSKate Stone     if (!platform_sp->IsCompatibleArchitecture(platform_arch, false,
283b9c1b51eSKate Stone                                                &fixed_platform_arch)) {
284b9c1b51eSKate Stone       platform_sp = Platform::GetPlatformForArchitecture(platform_arch,
285b9c1b51eSKate Stone                                                          &fixed_platform_arch);
2868ec55a53SRobert Flack       if (!is_dummy_target && platform_sp)
28795bbdf64SGreg Clayton         debugger.GetPlatformList().SetSelectedPlatform(platform_sp);
28895bbdf64SGreg Clayton     }
2893f19ada8SGreg Clayton   }
290b3a40ba8SGreg Clayton 
29170512317SGreg Clayton   if (!platform_arch.IsValid())
29270512317SGreg Clayton     platform_arch = arch;
29370512317SGreg Clayton 
294b9c1b51eSKate Stone   error = TargetList::CreateTargetInternal(
295b9c1b51eSKate Stone       debugger, user_exe_path, platform_arch, get_dependent_files, platform_sp,
296b9c1b51eSKate Stone       target_sp, is_dummy_target);
297cac9c5f9SGreg Clayton   return error;
298cac9c5f9SGreg Clayton }
299cac9c5f9SGreg Clayton 
300b9c1b51eSKate Stone lldb::TargetSP TargetList::GetDummyTarget(lldb_private::Debugger &debugger) {
301893c932aSJim Ingham   // FIXME: Maybe the dummy target should be per-Debugger
302b9c1b51eSKate Stone   if (!m_dummy_target_sp || !m_dummy_target_sp->IsValid()) {
303893c932aSJim Ingham     ArchSpec arch(Target::GetDefaultArchitecture());
304893c932aSJim Ingham     if (!arch.IsValid())
305893c932aSJim Ingham       arch = HostInfo::GetArchitecture();
30697206d57SZachary Turner     Status err = CreateDummyTarget(
307b9c1b51eSKate Stone         debugger, arch.GetTriple().getTriple().c_str(), m_dummy_target_sp);
308893c932aSJim Ingham   }
309893c932aSJim Ingham 
310893c932aSJim Ingham   return m_dummy_target_sp;
311893c932aSJim Ingham }
312893c932aSJim Ingham 
31397206d57SZachary Turner Status TargetList::CreateDummyTarget(Debugger &debugger,
314a47464b2SZachary Turner                                      llvm::StringRef specified_arch_name,
315b9c1b51eSKate Stone                                      lldb::TargetSP &target_sp) {
316893c932aSJim Ingham   PlatformSP host_platform_sp(Platform::GetHostPlatform());
317b9c1b51eSKate Stone   return CreateTargetInternal(
318b9c1b51eSKate Stone       debugger, (const char *)nullptr, specified_arch_name, false,
319b9c1b51eSKate Stone       (const OptionGroupPlatform *)nullptr, target_sp, true);
320893c932aSJim Ingham }
321893c932aSJim Ingham 
32297206d57SZachary Turner Status TargetList::CreateTargetInternal(Debugger &debugger,
323a47464b2SZachary Turner                                         llvm::StringRef user_exe_path,
32470512317SGreg Clayton                                         const ArchSpec &specified_arch,
32530fdc8d8SChris Lattner                                         bool get_dependent_files,
326893c932aSJim Ingham                                         lldb::PlatformSP &platform_sp,
327893c932aSJim Ingham                                         lldb::TargetSP &target_sp,
328b9c1b51eSKate Stone                                         bool is_dummy_target) {
329f9d16476SPavel Labath   static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
330f9d16476SPavel Labath   Timer scoped_timer(
331f9d16476SPavel Labath       func_cat, "TargetList::CreateTarget (file = '%s', arch = '%s')",
332f9d16476SPavel Labath       user_exe_path.str().c_str(), specified_arch.GetArchitectureName());
33397206d57SZachary Turner   Status error;
3345aee162fSJim Ingham 
33570512317SGreg Clayton   ArchSpec arch(specified_arch);
33670512317SGreg Clayton 
337b9c1b51eSKate Stone   if (arch.IsValid()) {
338b9c1b51eSKate Stone     if (!platform_sp ||
339b9c1b51eSKate Stone         !platform_sp->IsCompatibleArchitecture(arch, false, nullptr))
34070512317SGreg Clayton       platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
34170512317SGreg Clayton   }
34270512317SGreg Clayton 
34370512317SGreg Clayton   if (!platform_sp)
34470512317SGreg Clayton     platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
345ded470d3SGreg Clayton 
3468ae50eb4SGreg Clayton   if (!arch.IsValid())
3478ae50eb4SGreg Clayton     arch = specified_arch;
3488ae50eb4SGreg Clayton 
349d26206b5SJason Molenda   FileSpec file(user_exe_path, false);
350a47464b2SZachary Turner   if (!file.Exists() && user_exe_path.startswith("~")) {
351b9c1b51eSKate Stone     // we want to expand the tilde but we don't want to resolve any symbolic
3528d48cd60SZachary Turner     // links so we can't use the FileSpec constructor's resolve flag
3538d48cd60SZachary Turner     llvm::SmallString<64> unglobbed_path;
3548d48cd60SZachary Turner     StandardTildeExpressionResolver Resolver;
3558d48cd60SZachary Turner     Resolver.ResolveFullPath(user_exe_path, unglobbed_path);
3569f822cd1SMichael Sartain 
3573f559740SZachary Turner     if (unglobbed_path.empty())
3583f559740SZachary Turner       file = FileSpec(user_exe_path, false);
3593f559740SZachary Turner     else
3603f559740SZachary Turner       file = FileSpec(unglobbed_path.c_str(), false);
361d26206b5SJason Molenda   }
3629f822cd1SMichael Sartain 
36382d79295SGreg Clayton   bool user_exe_path_is_bundle = false;
36482d79295SGreg Clayton   char resolved_bundle_exe_path[PATH_MAX];
36582d79295SGreg Clayton   resolved_bundle_exe_path[0] = '\0';
366b9c1b51eSKate Stone   if (file) {
3677d86ee5aSZachary Turner     if (llvm::sys::fs::is_directory(file.GetPath()))
36882d79295SGreg Clayton       user_exe_path_is_bundle = true;
36982d79295SGreg Clayton 
370a47464b2SZachary Turner     if (file.IsRelative() && !user_exe_path.empty()) {
3711d5855b1SPavel Labath       llvm::SmallString<64> cwd;
3721d5855b1SPavel Labath       if (! llvm::sys::fs::current_path(cwd)) {
373d68dbd5aSGreg Clayton         FileSpec cwd_file(cwd.c_str(), false);
374d68dbd5aSGreg Clayton         cwd_file.AppendPathComponent(file);
3759ff5aae5SGreg Clayton         if (cwd_file.Exists())
3769ff5aae5SGreg Clayton           file = cwd_file;
377a0ca6601SGreg Clayton       }
378a0ca6601SGreg Clayton     }
379a0ca6601SGreg Clayton 
38030fdc8d8SChris Lattner     ModuleSP exe_module_sp;
381b9c1b51eSKate Stone     if (platform_sp) {
382b9c1b51eSKate Stone       FileSpecList executable_search_paths(
383b9c1b51eSKate Stone           Target::GetDefaultExecutableSearchPaths());
3848012cadbSGreg Clayton       ModuleSpec module_spec(file, arch);
385b9c1b51eSKate Stone       error = platform_sp->ResolveExecutable(module_spec, exe_module_sp,
386b9c1b51eSKate Stone                                              executable_search_paths.GetSize()
387b9c1b51eSKate Stone                                                  ? &executable_search_paths
388b9c1b51eSKate Stone                                                  : nullptr);
389c859e2d5SGreg Clayton     }
390428a9a58SCaroline Tice 
391b9c1b51eSKate Stone     if (error.Success() && exe_module_sp) {
392b9c1b51eSKate Stone       if (exe_module_sp->GetObjectFile() == nullptr) {
393b9c1b51eSKate Stone         if (arch.IsValid()) {
394b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
395b9c1b51eSKate Stone               "\"%s\" doesn't contain architecture %s", file.GetPath().c_str(),
39664195a2cSGreg Clayton               arch.GetArchitectureName());
397b9c1b51eSKate Stone         } else {
398b5ad4ec7SGreg Clayton           error.SetErrorStringWithFormat("unsupported file type \"%s\"",
399b5ad4ec7SGreg Clayton                                          file.GetPath().c_str());
400bc5cad6cSGreg Clayton         }
4015aee162fSJim Ingham         return error;
4025aee162fSJim Ingham       }
403893c932aSJim Ingham       target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
40430fdc8d8SChris Lattner       target_sp->SetExecutableModule(exe_module_sp, get_dependent_files);
40582d79295SGreg Clayton       if (user_exe_path_is_bundle)
406b9c1b51eSKate Stone         exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path,
407b9c1b51eSKate Stone                                              sizeof(resolved_bundle_exe_path));
4085aee162fSJim Ingham     }
409b9c1b51eSKate Stone   } else {
41005097246SAdrian Prantl     // No file was specified, just create an empty target with any arch if a
41105097246SAdrian Prantl     // valid arch was specified
412893c932aSJim Ingham     target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
413e996fd30SGreg Clayton   }
4141559a46bSCaroline Tice 
415b9c1b51eSKate Stone   if (target_sp) {
41682d79295SGreg Clayton     // Set argv0 with what the user typed, unless the user specified a
41782d79295SGreg Clayton     // directory. If the user specified a directory, then it is probably a
41882d79295SGreg Clayton     // bundle that was resolved and we need to use the resolved bundle path
419a47464b2SZachary Turner     if (!user_exe_path.empty()) {
420b9c1b51eSKate Stone       // Use exactly what the user typed as the first argument when we exec or
421b9c1b51eSKate Stone       // posix_spawn
422b9c1b51eSKate Stone       if (user_exe_path_is_bundle && resolved_bundle_exe_path[0]) {
42382d79295SGreg Clayton         target_sp->SetArg0(resolved_bundle_exe_path);
424b9c1b51eSKate Stone       } else {
4259f822cd1SMichael Sartain         // Use resolved path
4269f822cd1SMichael Sartain         target_sp->SetArg0(file.GetPath().c_str());
427a0ca6601SGreg Clayton       }
42882d79295SGreg Clayton     }
429b9c1b51eSKate Stone     if (file.GetDirectory()) {
430a0ca6601SGreg Clayton       FileSpec file_dir;
431a0ca6601SGreg Clayton       file_dir.GetDirectory() = file.GetDirectory();
432a0ca6601SGreg Clayton       target_sp->GetExecutableSearchPaths().Append(file_dir);
433a0ca6601SGreg Clayton     }
434893c932aSJim Ingham 
435893c932aSJim Ingham     // Don't put the dummy target in the target list, it's held separately.
436b9c1b51eSKate Stone     if (!is_dummy_target) {
43716ff8604SSaleem Abdulrasool       std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
4382976d00aSJim Ingham       m_selected_target_idx = m_target_list.size();
43930fdc8d8SChris Lattner       m_target_list.push_back(target_sp);
44033df7cd3SJim Ingham       // Now prime this from the dummy target:
44133df7cd3SJim Ingham       target_sp->PrimeFromDummyTarget(debugger.GetDummyTarget());
442b9c1b51eSKate Stone     } else {
443893c932aSJim Ingham       m_dummy_target_sp = target_sp;
444893c932aSJim Ingham     }
44530fdc8d8SChris Lattner   }
44630fdc8d8SChris Lattner 
44730fdc8d8SChris Lattner   return error;
44830fdc8d8SChris Lattner }
44930fdc8d8SChris Lattner 
450b9c1b51eSKate Stone bool TargetList::DeleteTarget(TargetSP &target_sp) {
45116ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
45230fdc8d8SChris Lattner   collection::iterator pos, end = m_target_list.end();
45330fdc8d8SChris Lattner 
454b9c1b51eSKate Stone   for (pos = m_target_list.begin(); pos != end; ++pos) {
455b9c1b51eSKate Stone     if (pos->get() == target_sp.get()) {
45630fdc8d8SChris Lattner       m_target_list.erase(pos);
45730fdc8d8SChris Lattner       return true;
45830fdc8d8SChris Lattner     }
45930fdc8d8SChris Lattner   }
46030fdc8d8SChris Lattner   return false;
46130fdc8d8SChris Lattner }
46230fdc8d8SChris Lattner 
463b9c1b51eSKate Stone TargetSP TargetList::FindTargetWithExecutableAndArchitecture(
464b9c1b51eSKate Stone     const FileSpec &exe_file_spec, const ArchSpec *exe_arch_ptr) const {
46516ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
46630fdc8d8SChris Lattner   TargetSP target_sp;
467ddd7a2a6SSean Callanan   bool full_match = (bool)exe_file_spec.GetDirectory();
46830fdc8d8SChris Lattner 
46930fdc8d8SChris Lattner   collection::const_iterator pos, end = m_target_list.end();
470b9c1b51eSKate Stone   for (pos = m_target_list.begin(); pos != end; ++pos) {
471aa149cbdSGreg Clayton     Module *exe_module = (*pos)->GetExecutableModulePointer();
47230fdc8d8SChris Lattner 
473b9c1b51eSKate Stone     if (exe_module) {
474b9c1b51eSKate Stone       if (FileSpec::Equal(exe_file_spec, exe_module->GetFileSpec(),
475b9c1b51eSKate Stone                           full_match)) {
476b9c1b51eSKate Stone         if (exe_arch_ptr) {
477bf4b7be6SSean Callanan           if (!exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture()))
47830fdc8d8SChris Lattner             continue;
47930fdc8d8SChris Lattner         }
48030fdc8d8SChris Lattner         target_sp = *pos;
48130fdc8d8SChris Lattner         break;
48230fdc8d8SChris Lattner       }
48330fdc8d8SChris Lattner     }
48430fdc8d8SChris Lattner   }
48530fdc8d8SChris Lattner   return target_sp;
48630fdc8d8SChris Lattner }
48730fdc8d8SChris Lattner 
488b9c1b51eSKate Stone TargetSP TargetList::FindTargetWithProcessID(lldb::pid_t pid) const {
48916ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
49030fdc8d8SChris Lattner   TargetSP target_sp;
49130fdc8d8SChris Lattner   collection::const_iterator pos, end = m_target_list.end();
492b9c1b51eSKate Stone   for (pos = m_target_list.begin(); pos != end; ++pos) {
49330fdc8d8SChris Lattner     Process *process = (*pos)->GetProcessSP().get();
494b9c1b51eSKate Stone     if (process && process->GetID() == pid) {
49530fdc8d8SChris Lattner       target_sp = *pos;
49630fdc8d8SChris Lattner       break;
49730fdc8d8SChris Lattner     }
49830fdc8d8SChris Lattner   }
49930fdc8d8SChris Lattner   return target_sp;
50030fdc8d8SChris Lattner }
50130fdc8d8SChris Lattner 
502b9c1b51eSKate Stone TargetSP TargetList::FindTargetWithProcess(Process *process) const {
50330fdc8d8SChris Lattner   TargetSP target_sp;
504b9c1b51eSKate Stone   if (process) {
50516ff8604SSaleem Abdulrasool     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
50630fdc8d8SChris Lattner     collection::const_iterator pos, end = m_target_list.end();
507b9c1b51eSKate Stone     for (pos = m_target_list.begin(); pos != end; ++pos) {
508b9c1b51eSKate Stone       if (process == (*pos)->GetProcessSP().get()) {
50930fdc8d8SChris Lattner         target_sp = *pos;
51030fdc8d8SChris Lattner         break;
51130fdc8d8SChris Lattner       }
51230fdc8d8SChris Lattner     }
51330fdc8d8SChris Lattner   }
51430fdc8d8SChris Lattner   return target_sp;
51530fdc8d8SChris Lattner }
51630fdc8d8SChris Lattner 
517b9c1b51eSKate Stone TargetSP TargetList::GetTargetSP(Target *target) const {
51830fdc8d8SChris Lattner   TargetSP target_sp;
519b9c1b51eSKate Stone   if (target) {
52016ff8604SSaleem Abdulrasool     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
52130fdc8d8SChris Lattner     collection::const_iterator pos, end = m_target_list.end();
522b9c1b51eSKate Stone     for (pos = m_target_list.begin(); pos != end; ++pos) {
523b9c1b51eSKate Stone       if (target == (*pos).get()) {
52430fdc8d8SChris Lattner         target_sp = *pos;
52530fdc8d8SChris Lattner         break;
52630fdc8d8SChris Lattner       }
52730fdc8d8SChris Lattner     }
52830fdc8d8SChris Lattner   }
52930fdc8d8SChris Lattner   return target_sp;
53030fdc8d8SChris Lattner }
53130fdc8d8SChris Lattner 
532b9c1b51eSKate Stone uint32_t TargetList::SendAsyncInterrupt(lldb::pid_t pid) {
53330fdc8d8SChris Lattner   uint32_t num_async_interrupts_sent = 0;
53430fdc8d8SChris Lattner 
535b9c1b51eSKate Stone   if (pid != LLDB_INVALID_PROCESS_ID) {
53630fdc8d8SChris Lattner     TargetSP target_sp(FindTargetWithProcessID(pid));
537b9c1b51eSKate Stone     if (target_sp) {
53830fdc8d8SChris Lattner       Process *process = target_sp->GetProcessSP().get();
539b9c1b51eSKate Stone       if (process) {
540cfc0935eSJim Ingham         process->SendAsyncInterrupt();
54130fdc8d8SChris Lattner         ++num_async_interrupts_sent;
54230fdc8d8SChris Lattner       }
54330fdc8d8SChris Lattner     }
544b9c1b51eSKate Stone   } else {
54530fdc8d8SChris Lattner     // We don't have a valid pid to broadcast to, so broadcast to the target
54630fdc8d8SChris Lattner     // list's async broadcaster...
547e65b2cf2SEugene Zelenko     BroadcastEvent(Process::eBroadcastBitInterrupt, nullptr);
54830fdc8d8SChris Lattner   }
54930fdc8d8SChris Lattner 
55030fdc8d8SChris Lattner   return num_async_interrupts_sent;
55130fdc8d8SChris Lattner }
55230fdc8d8SChris Lattner 
553b9c1b51eSKate Stone uint32_t TargetList::SignalIfRunning(lldb::pid_t pid, int signo) {
55430fdc8d8SChris Lattner   uint32_t num_signals_sent = 0;
555e65b2cf2SEugene Zelenko   Process *process = nullptr;
556b9c1b51eSKate Stone   if (pid == LLDB_INVALID_PROCESS_ID) {
55730fdc8d8SChris Lattner     // Signal all processes with signal
55816ff8604SSaleem Abdulrasool     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
55930fdc8d8SChris Lattner     collection::iterator pos, end = m_target_list.end();
560b9c1b51eSKate Stone     for (pos = m_target_list.begin(); pos != end; ++pos) {
56130fdc8d8SChris Lattner       process = (*pos)->GetProcessSP().get();
562b9c1b51eSKate Stone       if (process) {
563b9c1b51eSKate Stone         if (process->IsAlive()) {
56430fdc8d8SChris Lattner           ++num_signals_sent;
56530fdc8d8SChris Lattner           process->Signal(signo);
56630fdc8d8SChris Lattner         }
56730fdc8d8SChris Lattner       }
56830fdc8d8SChris Lattner     }
569b9c1b51eSKate Stone   } else {
57030fdc8d8SChris Lattner     // Signal a specific process with signal
57130fdc8d8SChris Lattner     TargetSP target_sp(FindTargetWithProcessID(pid));
572b9c1b51eSKate Stone     if (target_sp) {
57330fdc8d8SChris Lattner       process = target_sp->GetProcessSP().get();
574b9c1b51eSKate Stone       if (process) {
575b9c1b51eSKate Stone         if (process->IsAlive()) {
57630fdc8d8SChris Lattner           ++num_signals_sent;
57730fdc8d8SChris Lattner           process->Signal(signo);
57830fdc8d8SChris Lattner         }
57930fdc8d8SChris Lattner       }
58030fdc8d8SChris Lattner     }
58130fdc8d8SChris Lattner   }
58230fdc8d8SChris Lattner   return num_signals_sent;
58330fdc8d8SChris Lattner }
58430fdc8d8SChris Lattner 
585b9c1b51eSKate Stone int TargetList::GetNumTargets() const {
58616ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
58730fdc8d8SChris Lattner   return m_target_list.size();
58830fdc8d8SChris Lattner }
58930fdc8d8SChris Lattner 
590b9c1b51eSKate Stone lldb::TargetSP TargetList::GetTargetAtIndex(uint32_t idx) const {
59130fdc8d8SChris Lattner   TargetSP target_sp;
59216ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
59330fdc8d8SChris Lattner   if (idx < m_target_list.size())
59430fdc8d8SChris Lattner     target_sp = m_target_list[idx];
59530fdc8d8SChris Lattner   return target_sp;
59630fdc8d8SChris Lattner }
59730fdc8d8SChris Lattner 
598b9c1b51eSKate Stone uint32_t TargetList::GetIndexOfTarget(lldb::TargetSP target_sp) const {
59916ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
6008499e1a4SJim Ingham   size_t num_targets = m_target_list.size();
601b9c1b51eSKate Stone   for (size_t idx = 0; idx < num_targets; idx++) {
6028499e1a4SJim Ingham     if (target_sp == m_target_list[idx])
6038499e1a4SJim Ingham       return idx;
6048499e1a4SJim Ingham   }
6058499e1a4SJim Ingham   return UINT32_MAX;
6068499e1a4SJim Ingham }
6078499e1a4SJim Ingham 
608b9c1b51eSKate Stone uint32_t TargetList::SetSelectedTarget(Target *target) {
60916ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
610b9c1b51eSKate Stone   collection::const_iterator pos, begin = m_target_list.begin(),
61130fdc8d8SChris Lattner                                   end = m_target_list.end();
612b9c1b51eSKate Stone   for (pos = begin; pos != end; ++pos) {
613b9c1b51eSKate Stone     if (pos->get() == target) {
6142976d00aSJim Ingham       m_selected_target_idx = std::distance(begin, pos);
6152976d00aSJim Ingham       return m_selected_target_idx;
61630fdc8d8SChris Lattner     }
61730fdc8d8SChris Lattner   }
6182976d00aSJim Ingham   m_selected_target_idx = 0;
6192976d00aSJim Ingham   return m_selected_target_idx;
62030fdc8d8SChris Lattner }
62130fdc8d8SChris Lattner 
622b9c1b51eSKate Stone lldb::TargetSP TargetList::GetSelectedTarget() {
62316ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
6242976d00aSJim Ingham   if (m_selected_target_idx >= m_target_list.size())
6252976d00aSJim Ingham     m_selected_target_idx = 0;
6262976d00aSJim Ingham   return GetTargetAtIndex(m_selected_target_idx);
62730fdc8d8SChris Lattner }
628