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 
105*4ebdee0aSBruce 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;
123f4d6de6aSGreg Clayton     module_spec.GetFileSpec().SetFile(user_exe_path, true);
124c76fa8a3SGreg Clayton 
125b9c1b51eSKate Stone     // Resolve the executable in case we are given a path to a application
12605097246SAdrian Prantl     // bundle like a .app bundle on MacOSX
127c76fa8a3SGreg Clayton     Host::ResolveExecutableInBundle(module_spec.GetFileSpec());
128c76fa8a3SGreg Clayton 
129f4d6de6aSGreg Clayton     lldb::offset_t file_offset = 0;
1302540a8a7SGreg Clayton     lldb::offset_t file_size = 0;
131b9c1b51eSKate Stone     const size_t num_specs = ObjectFile::GetModuleSpecifications(
132b9c1b51eSKate Stone         module_spec.GetFileSpec(), file_offset, file_size, module_specs);
133b9c1b51eSKate Stone     if (num_specs > 0) {
134f4d6de6aSGreg Clayton       ModuleSpec matching_module_spec;
135f4d6de6aSGreg Clayton 
136b9c1b51eSKate Stone       if (num_specs == 1) {
137b9c1b51eSKate Stone         if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec)) {
138b9c1b51eSKate Stone           if (platform_arch.IsValid()) {
139b9c1b51eSKate Stone             if (platform_arch.IsCompatibleMatch(
140b9c1b51eSKate Stone                     matching_module_spec.GetArchitecture())) {
1413f19ada8SGreg Clayton               // If the OS or vendor weren't specified, then adopt the module's
14205097246SAdrian Prantl               // architecture so that the platform matching can be more
14305097246SAdrian Prantl               // accurate
144b9c1b51eSKate Stone               if (!platform_arch.TripleOSWasSpecified() ||
145b9c1b51eSKate Stone                   !platform_arch.TripleVendorWasSpecified()) {
1463f19ada8SGreg Clayton                 prefer_platform_arch = true;
1473f19ada8SGreg Clayton                 platform_arch = matching_module_spec.GetArchitecture();
1483f19ada8SGreg Clayton               }
149b9c1b51eSKate Stone             } else {
1507df337f8STodd Fiala               StreamString platform_arch_strm;
1517df337f8STodd Fiala               StreamString module_arch_strm;
1527df337f8STodd Fiala 
1537df337f8STodd Fiala               platform_arch.DumpTriple(platform_arch_strm);
154b9c1b51eSKate Stone               matching_module_spec.GetArchitecture().DumpTriple(
155b9c1b51eSKate Stone                   module_arch_strm);
156b9c1b51eSKate Stone               error.SetErrorStringWithFormat(
157b9c1b51eSKate Stone                   "the specified architecture '%s' is not compatible with '%s' "
158b9c1b51eSKate Stone                   "in '%s'",
159c156427dSZachary Turner                   platform_arch_strm.GetData(), module_arch_strm.GetData(),
160b5ad4ec7SGreg Clayton                   module_spec.GetFileSpec().GetPath().c_str());
161f4d6de6aSGreg Clayton               return error;
162f4d6de6aSGreg Clayton             }
163b9c1b51eSKate Stone           } else {
164f4d6de6aSGreg Clayton             // Only one arch and none was specified
1653f19ada8SGreg Clayton             prefer_platform_arch = true;
166f4d6de6aSGreg Clayton             platform_arch = matching_module_spec.GetArchitecture();
167f4d6de6aSGreg Clayton           }
168f4d6de6aSGreg Clayton         }
169b9c1b51eSKate Stone       } else {
170b9c1b51eSKate Stone         if (arch.IsValid()) {
171f4d6de6aSGreg Clayton           module_spec.GetArchitecture() = arch;
172b9c1b51eSKate Stone           if (module_specs.FindMatchingModuleSpec(module_spec,
173b9c1b51eSKate Stone                                                   matching_module_spec)) {
1743f19ada8SGreg Clayton             prefer_platform_arch = true;
175f4d6de6aSGreg Clayton             platform_arch = matching_module_spec.GetArchitecture();
176f4d6de6aSGreg Clayton           }
177b9c1b51eSKate Stone         } else {
178b0cc53cfSGreg Clayton           // No architecture specified, check if there is only one platform for
179b0cc53cfSGreg Clayton           // all of the architectures.
180b0cc53cfSGreg Clayton 
181b0cc53cfSGreg Clayton           typedef std::vector<PlatformSP> PlatformList;
182b0cc53cfSGreg Clayton           PlatformList platforms;
183615eb7e6SGreg Clayton           PlatformSP host_platform_sp = Platform::GetHostPlatform();
184b9c1b51eSKate Stone           for (size_t i = 0; i < num_specs; ++i) {
185b0cc53cfSGreg Clayton             ModuleSpec module_spec;
186b9c1b51eSKate Stone             if (module_specs.GetModuleSpecAtIndex(i, module_spec)) {
187b0cc53cfSGreg Clayton               // See if there was a selected platform and check that first
188b0cc53cfSGreg Clayton               // since the user may have specified it.
189b9c1b51eSKate Stone               if (platform_sp) {
190b9c1b51eSKate Stone                 if (platform_sp->IsCompatibleArchitecture(
191b9c1b51eSKate Stone                         module_spec.GetArchitecture(), false, nullptr)) {
192b0cc53cfSGreg Clayton                   platforms.push_back(platform_sp);
193b0cc53cfSGreg Clayton                   continue;
194f4d6de6aSGreg Clayton                 }
195f4d6de6aSGreg Clayton               }
196f4d6de6aSGreg Clayton 
19705097246SAdrian Prantl               // Next check the host platform it if wasn't already checked
19805097246SAdrian Prantl               // above
199b9c1b51eSKate Stone               if (host_platform_sp &&
200b9c1b51eSKate Stone                   (!platform_sp ||
201b9c1b51eSKate Stone                    host_platform_sp->GetName() != platform_sp->GetName())) {
202b9c1b51eSKate Stone                 if (host_platform_sp->IsCompatibleArchitecture(
203b9c1b51eSKate Stone                         module_spec.GetArchitecture(), false, nullptr)) {
204b0cc53cfSGreg Clayton                   platforms.push_back(host_platform_sp);
205b0cc53cfSGreg Clayton                   continue;
206b0cc53cfSGreg Clayton                 }
207b0cc53cfSGreg Clayton               }
208b0cc53cfSGreg Clayton 
209b9c1b51eSKate Stone               // Just find a platform that matches the architecture in the
210b9c1b51eSKate Stone               // executable file
211b9c1b51eSKate Stone               PlatformSP fallback_platform_sp(
212b9c1b51eSKate Stone                   Platform::GetPlatformForArchitecture(
213b9c1b51eSKate Stone                       module_spec.GetArchitecture(), nullptr));
214b9c1b51eSKate Stone               if (fallback_platform_sp) {
215e92a74ceSJason Molenda                 platforms.push_back(fallback_platform_sp);
216e92a74ceSJason Molenda               }
217b0cc53cfSGreg Clayton             }
218b0cc53cfSGreg Clayton           }
219b0cc53cfSGreg Clayton 
220e65b2cf2SEugene Zelenko           Platform *platform_ptr = nullptr;
2219d58c728SJason Molenda           bool more_than_one_platforms = false;
222b9c1b51eSKate Stone           for (const auto &the_platform_sp : platforms) {
223b9c1b51eSKate Stone             if (platform_ptr) {
224b9c1b51eSKate Stone               if (platform_ptr->GetName() != the_platform_sp->GetName()) {
2259d58c728SJason Molenda                 more_than_one_platforms = true;
226e65b2cf2SEugene Zelenko                 platform_ptr = nullptr;
227b0cc53cfSGreg Clayton                 break;
228b0cc53cfSGreg Clayton               }
229b9c1b51eSKate Stone             } else {
230b0cc53cfSGreg Clayton               platform_ptr = the_platform_sp.get();
231b0cc53cfSGreg Clayton             }
232b0cc53cfSGreg Clayton           }
233b0cc53cfSGreg Clayton 
234b9c1b51eSKate Stone           if (platform_ptr) {
235*4ebdee0aSBruce Mitchener             // All platforms for all modules in the executable match, so we can
236b9c1b51eSKate Stone             // select this platform
237b0cc53cfSGreg Clayton             platform_sp = platforms.front();
238b9c1b51eSKate Stone           } else if (more_than_one_platforms == false) {
2399d58c728SJason Molenda             // No platforms claim to support this file
240b9c1b51eSKate Stone             error.SetErrorString("No matching platforms found for this file, "
241b9c1b51eSKate Stone                                  "specify one with the --platform option");
2429d58c728SJason Molenda             return error;
243b9c1b51eSKate Stone           } else {
244b9c1b51eSKate Stone             // More than one platform claims to support this file, so the
245b9c1b51eSKate Stone             // --platform option must be specified
246b0cc53cfSGreg Clayton             StreamString error_strm;
247b0cc53cfSGreg Clayton             std::set<Platform *> platform_set;
248b9c1b51eSKate Stone             error_strm.Printf(
249b9c1b51eSKate Stone                 "more than one platform supports this executable (");
250b9c1b51eSKate Stone             for (const auto &the_platform_sp : platforms) {
251b9c1b51eSKate Stone               if (platform_set.find(the_platform_sp.get()) ==
252b9c1b51eSKate Stone                   platform_set.end()) {
253b0cc53cfSGreg Clayton                 if (!platform_set.empty())
254b0cc53cfSGreg Clayton                   error_strm.PutCString(", ");
255b0cc53cfSGreg Clayton                 error_strm.PutCString(the_platform_sp->GetName().GetCString());
256b0cc53cfSGreg Clayton                 platform_set.insert(the_platform_sp.get());
257b0cc53cfSGreg Clayton               }
258b0cc53cfSGreg Clayton             }
259b9c1b51eSKate Stone             error_strm.Printf(
260b9c1b51eSKate Stone                 "), use the --platform option to specify a platform");
261c156427dSZachary Turner             error.SetErrorString(error_strm.GetString());
262b3a40ba8SGreg Clayton             return error;
263b3a40ba8SGreg Clayton           }
264b3a40ba8SGreg Clayton         }
265b0cc53cfSGreg Clayton       }
266b0cc53cfSGreg Clayton     }
267b0cc53cfSGreg Clayton   }
268b3a40ba8SGreg Clayton 
269869e0c1cSTed Woodward   // If we have a valid architecture, make sure the current platform is
270869e0c1cSTed Woodward   // compatible with that architecture
271b9c1b51eSKate Stone   if (!prefer_platform_arch && arch.IsValid()) {
272b9c1b51eSKate Stone     if (!platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) {
27370512317SGreg Clayton       platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch);
2748ec55a53SRobert Flack       if (!is_dummy_target && platform_sp)
27595bbdf64SGreg Clayton         debugger.GetPlatformList().SetSelectedPlatform(platform_sp);
27695bbdf64SGreg Clayton     }
277b9c1b51eSKate Stone   } else if (platform_arch.IsValid()) {
278b9c1b51eSKate Stone     // if "arch" isn't valid, yet "platform_arch" is, it means we have an
27905097246SAdrian Prantl     // executable file with a single architecture which should be used
2803f19ada8SGreg Clayton     ArchSpec fixed_platform_arch;
281b9c1b51eSKate Stone     if (!platform_sp->IsCompatibleArchitecture(platform_arch, false,
282b9c1b51eSKate Stone                                                &fixed_platform_arch)) {
283b9c1b51eSKate Stone       platform_sp = Platform::GetPlatformForArchitecture(platform_arch,
284b9c1b51eSKate Stone                                                          &fixed_platform_arch);
2858ec55a53SRobert Flack       if (!is_dummy_target && platform_sp)
28695bbdf64SGreg Clayton         debugger.GetPlatformList().SetSelectedPlatform(platform_sp);
28795bbdf64SGreg Clayton     }
2883f19ada8SGreg Clayton   }
289b3a40ba8SGreg Clayton 
29070512317SGreg Clayton   if (!platform_arch.IsValid())
29170512317SGreg Clayton     platform_arch = arch;
29270512317SGreg Clayton 
293b9c1b51eSKate Stone   error = TargetList::CreateTargetInternal(
294b9c1b51eSKate Stone       debugger, user_exe_path, platform_arch, get_dependent_files, platform_sp,
295b9c1b51eSKate Stone       target_sp, is_dummy_target);
296cac9c5f9SGreg Clayton   return error;
297cac9c5f9SGreg Clayton }
298cac9c5f9SGreg Clayton 
299b9c1b51eSKate Stone lldb::TargetSP TargetList::GetDummyTarget(lldb_private::Debugger &debugger) {
300893c932aSJim Ingham   // FIXME: Maybe the dummy target should be per-Debugger
301b9c1b51eSKate Stone   if (!m_dummy_target_sp || !m_dummy_target_sp->IsValid()) {
302893c932aSJim Ingham     ArchSpec arch(Target::GetDefaultArchitecture());
303893c932aSJim Ingham     if (!arch.IsValid())
304893c932aSJim Ingham       arch = HostInfo::GetArchitecture();
30597206d57SZachary Turner     Status err = CreateDummyTarget(
306b9c1b51eSKate Stone         debugger, arch.GetTriple().getTriple().c_str(), m_dummy_target_sp);
307893c932aSJim Ingham   }
308893c932aSJim Ingham 
309893c932aSJim Ingham   return m_dummy_target_sp;
310893c932aSJim Ingham }
311893c932aSJim Ingham 
31297206d57SZachary Turner Status TargetList::CreateDummyTarget(Debugger &debugger,
313a47464b2SZachary Turner                                      llvm::StringRef specified_arch_name,
314b9c1b51eSKate Stone                                      lldb::TargetSP &target_sp) {
315893c932aSJim Ingham   PlatformSP host_platform_sp(Platform::GetHostPlatform());
316b9c1b51eSKate Stone   return CreateTargetInternal(
317b9c1b51eSKate Stone       debugger, (const char *)nullptr, specified_arch_name, false,
318b9c1b51eSKate Stone       (const OptionGroupPlatform *)nullptr, target_sp, true);
319893c932aSJim Ingham }
320893c932aSJim Ingham 
32197206d57SZachary Turner Status TargetList::CreateTargetInternal(Debugger &debugger,
322a47464b2SZachary Turner                                         llvm::StringRef user_exe_path,
32370512317SGreg Clayton                                         const ArchSpec &specified_arch,
32430fdc8d8SChris Lattner                                         bool get_dependent_files,
325893c932aSJim Ingham                                         lldb::PlatformSP &platform_sp,
326893c932aSJim Ingham                                         lldb::TargetSP &target_sp,
327b9c1b51eSKate Stone                                         bool is_dummy_target) {
328f9d16476SPavel Labath   static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
329f9d16476SPavel Labath   Timer scoped_timer(
330f9d16476SPavel Labath       func_cat, "TargetList::CreateTarget (file = '%s', arch = '%s')",
331f9d16476SPavel Labath       user_exe_path.str().c_str(), specified_arch.GetArchitectureName());
33297206d57SZachary Turner   Status error;
3335aee162fSJim Ingham 
33470512317SGreg Clayton   ArchSpec arch(specified_arch);
33570512317SGreg Clayton 
336b9c1b51eSKate Stone   if (arch.IsValid()) {
337b9c1b51eSKate Stone     if (!platform_sp ||
338b9c1b51eSKate Stone         !platform_sp->IsCompatibleArchitecture(arch, false, nullptr))
33970512317SGreg Clayton       platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
34070512317SGreg Clayton   }
34170512317SGreg Clayton 
34270512317SGreg Clayton   if (!platform_sp)
34370512317SGreg Clayton     platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
344ded470d3SGreg Clayton 
3458ae50eb4SGreg Clayton   if (!arch.IsValid())
3468ae50eb4SGreg Clayton     arch = specified_arch;
3478ae50eb4SGreg Clayton 
348d26206b5SJason Molenda   FileSpec file(user_exe_path, false);
349a47464b2SZachary Turner   if (!file.Exists() && user_exe_path.startswith("~")) {
350b9c1b51eSKate Stone     // we want to expand the tilde but we don't want to resolve any symbolic
3518d48cd60SZachary Turner     // links so we can't use the FileSpec constructor's resolve flag
3528d48cd60SZachary Turner     llvm::SmallString<64> unglobbed_path;
3538d48cd60SZachary Turner     StandardTildeExpressionResolver Resolver;
3548d48cd60SZachary Turner     Resolver.ResolveFullPath(user_exe_path, unglobbed_path);
3559f822cd1SMichael Sartain 
3563f559740SZachary Turner     if (unglobbed_path.empty())
3573f559740SZachary Turner       file = FileSpec(user_exe_path, false);
3583f559740SZachary Turner     else
3593f559740SZachary Turner       file = FileSpec(unglobbed_path.c_str(), false);
360d26206b5SJason Molenda   }
3619f822cd1SMichael Sartain 
36282d79295SGreg Clayton   bool user_exe_path_is_bundle = false;
36382d79295SGreg Clayton   char resolved_bundle_exe_path[PATH_MAX];
36482d79295SGreg Clayton   resolved_bundle_exe_path[0] = '\0';
365b9c1b51eSKate Stone   if (file) {
3667d86ee5aSZachary Turner     if (llvm::sys::fs::is_directory(file.GetPath()))
36782d79295SGreg Clayton       user_exe_path_is_bundle = true;
36882d79295SGreg Clayton 
369a47464b2SZachary Turner     if (file.IsRelative() && !user_exe_path.empty()) {
3701d5855b1SPavel Labath       llvm::SmallString<64> cwd;
3711d5855b1SPavel Labath       if (! llvm::sys::fs::current_path(cwd)) {
372d68dbd5aSGreg Clayton         FileSpec cwd_file(cwd.c_str(), false);
373d68dbd5aSGreg Clayton         cwd_file.AppendPathComponent(file);
3749ff5aae5SGreg Clayton         if (cwd_file.Exists())
3759ff5aae5SGreg Clayton           file = cwd_file;
376a0ca6601SGreg Clayton       }
377a0ca6601SGreg Clayton     }
378a0ca6601SGreg Clayton 
37930fdc8d8SChris Lattner     ModuleSP exe_module_sp;
380b9c1b51eSKate Stone     if (platform_sp) {
381b9c1b51eSKate Stone       FileSpecList executable_search_paths(
382b9c1b51eSKate Stone           Target::GetDefaultExecutableSearchPaths());
3838012cadbSGreg Clayton       ModuleSpec module_spec(file, arch);
384b9c1b51eSKate Stone       error = platform_sp->ResolveExecutable(module_spec, exe_module_sp,
385b9c1b51eSKate Stone                                              executable_search_paths.GetSize()
386b9c1b51eSKate Stone                                                  ? &executable_search_paths
387b9c1b51eSKate Stone                                                  : nullptr);
388c859e2d5SGreg Clayton     }
389428a9a58SCaroline Tice 
390b9c1b51eSKate Stone     if (error.Success() && exe_module_sp) {
391b9c1b51eSKate Stone       if (exe_module_sp->GetObjectFile() == nullptr) {
392b9c1b51eSKate Stone         if (arch.IsValid()) {
393b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
394b9c1b51eSKate Stone               "\"%s\" doesn't contain architecture %s", file.GetPath().c_str(),
39564195a2cSGreg Clayton               arch.GetArchitectureName());
396b9c1b51eSKate Stone         } else {
397b5ad4ec7SGreg Clayton           error.SetErrorStringWithFormat("unsupported file type \"%s\"",
398b5ad4ec7SGreg Clayton                                          file.GetPath().c_str());
399bc5cad6cSGreg Clayton         }
4005aee162fSJim Ingham         return error;
4015aee162fSJim Ingham       }
402893c932aSJim Ingham       target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
40330fdc8d8SChris Lattner       target_sp->SetExecutableModule(exe_module_sp, get_dependent_files);
40482d79295SGreg Clayton       if (user_exe_path_is_bundle)
405b9c1b51eSKate Stone         exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path,
406b9c1b51eSKate Stone                                              sizeof(resolved_bundle_exe_path));
4075aee162fSJim Ingham     }
408b9c1b51eSKate Stone   } else {
40905097246SAdrian Prantl     // No file was specified, just create an empty target with any arch if a
41005097246SAdrian Prantl     // valid arch was specified
411893c932aSJim Ingham     target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
412e996fd30SGreg Clayton   }
4131559a46bSCaroline Tice 
414b9c1b51eSKate Stone   if (target_sp) {
41582d79295SGreg Clayton     // Set argv0 with what the user typed, unless the user specified a
41682d79295SGreg Clayton     // directory. If the user specified a directory, then it is probably a
41782d79295SGreg Clayton     // bundle that was resolved and we need to use the resolved bundle path
418a47464b2SZachary Turner     if (!user_exe_path.empty()) {
419b9c1b51eSKate Stone       // Use exactly what the user typed as the first argument when we exec or
420b9c1b51eSKate Stone       // posix_spawn
421b9c1b51eSKate Stone       if (user_exe_path_is_bundle && resolved_bundle_exe_path[0]) {
42282d79295SGreg Clayton         target_sp->SetArg0(resolved_bundle_exe_path);
423b9c1b51eSKate Stone       } else {
4249f822cd1SMichael Sartain         // Use resolved path
4259f822cd1SMichael Sartain         target_sp->SetArg0(file.GetPath().c_str());
426a0ca6601SGreg Clayton       }
42782d79295SGreg Clayton     }
428b9c1b51eSKate Stone     if (file.GetDirectory()) {
429a0ca6601SGreg Clayton       FileSpec file_dir;
430a0ca6601SGreg Clayton       file_dir.GetDirectory() = file.GetDirectory();
431a0ca6601SGreg Clayton       target_sp->GetExecutableSearchPaths().Append(file_dir);
432a0ca6601SGreg Clayton     }
433893c932aSJim Ingham 
434893c932aSJim Ingham     // Don't put the dummy target in the target list, it's held separately.
435b9c1b51eSKate Stone     if (!is_dummy_target) {
43616ff8604SSaleem Abdulrasool       std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
4372976d00aSJim Ingham       m_selected_target_idx = m_target_list.size();
43830fdc8d8SChris Lattner       m_target_list.push_back(target_sp);
43933df7cd3SJim Ingham       // Now prime this from the dummy target:
44033df7cd3SJim Ingham       target_sp->PrimeFromDummyTarget(debugger.GetDummyTarget());
441b9c1b51eSKate Stone     } else {
442893c932aSJim Ingham       m_dummy_target_sp = target_sp;
443893c932aSJim Ingham     }
44430fdc8d8SChris Lattner   }
44530fdc8d8SChris Lattner 
44630fdc8d8SChris Lattner   return error;
44730fdc8d8SChris Lattner }
44830fdc8d8SChris Lattner 
449b9c1b51eSKate Stone bool TargetList::DeleteTarget(TargetSP &target_sp) {
45016ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
45130fdc8d8SChris Lattner   collection::iterator pos, end = m_target_list.end();
45230fdc8d8SChris Lattner 
453b9c1b51eSKate Stone   for (pos = m_target_list.begin(); pos != end; ++pos) {
454b9c1b51eSKate Stone     if (pos->get() == target_sp.get()) {
45530fdc8d8SChris Lattner       m_target_list.erase(pos);
45630fdc8d8SChris Lattner       return true;
45730fdc8d8SChris Lattner     }
45830fdc8d8SChris Lattner   }
45930fdc8d8SChris Lattner   return false;
46030fdc8d8SChris Lattner }
46130fdc8d8SChris Lattner 
462b9c1b51eSKate Stone TargetSP TargetList::FindTargetWithExecutableAndArchitecture(
463b9c1b51eSKate Stone     const FileSpec &exe_file_spec, const ArchSpec *exe_arch_ptr) const {
46416ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
46530fdc8d8SChris Lattner   TargetSP target_sp;
466ddd7a2a6SSean Callanan   bool full_match = (bool)exe_file_spec.GetDirectory();
46730fdc8d8SChris Lattner 
46830fdc8d8SChris Lattner   collection::const_iterator pos, end = m_target_list.end();
469b9c1b51eSKate Stone   for (pos = m_target_list.begin(); pos != end; ++pos) {
470aa149cbdSGreg Clayton     Module *exe_module = (*pos)->GetExecutableModulePointer();
47130fdc8d8SChris Lattner 
472b9c1b51eSKate Stone     if (exe_module) {
473b9c1b51eSKate Stone       if (FileSpec::Equal(exe_file_spec, exe_module->GetFileSpec(),
474b9c1b51eSKate Stone                           full_match)) {
475b9c1b51eSKate Stone         if (exe_arch_ptr) {
476bf4b7be6SSean Callanan           if (!exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture()))
47730fdc8d8SChris Lattner             continue;
47830fdc8d8SChris Lattner         }
47930fdc8d8SChris Lattner         target_sp = *pos;
48030fdc8d8SChris Lattner         break;
48130fdc8d8SChris Lattner       }
48230fdc8d8SChris Lattner     }
48330fdc8d8SChris Lattner   }
48430fdc8d8SChris Lattner   return target_sp;
48530fdc8d8SChris Lattner }
48630fdc8d8SChris Lattner 
487b9c1b51eSKate Stone TargetSP TargetList::FindTargetWithProcessID(lldb::pid_t pid) const {
48816ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
48930fdc8d8SChris Lattner   TargetSP target_sp;
49030fdc8d8SChris Lattner   collection::const_iterator pos, end = m_target_list.end();
491b9c1b51eSKate Stone   for (pos = m_target_list.begin(); pos != end; ++pos) {
49230fdc8d8SChris Lattner     Process *process = (*pos)->GetProcessSP().get();
493b9c1b51eSKate Stone     if (process && process->GetID() == pid) {
49430fdc8d8SChris Lattner       target_sp = *pos;
49530fdc8d8SChris Lattner       break;
49630fdc8d8SChris Lattner     }
49730fdc8d8SChris Lattner   }
49830fdc8d8SChris Lattner   return target_sp;
49930fdc8d8SChris Lattner }
50030fdc8d8SChris Lattner 
501b9c1b51eSKate Stone TargetSP TargetList::FindTargetWithProcess(Process *process) const {
50230fdc8d8SChris Lattner   TargetSP target_sp;
503b9c1b51eSKate Stone   if (process) {
50416ff8604SSaleem Abdulrasool     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
50530fdc8d8SChris Lattner     collection::const_iterator pos, end = m_target_list.end();
506b9c1b51eSKate Stone     for (pos = m_target_list.begin(); pos != end; ++pos) {
507b9c1b51eSKate Stone       if (process == (*pos)->GetProcessSP().get()) {
50830fdc8d8SChris Lattner         target_sp = *pos;
50930fdc8d8SChris Lattner         break;
51030fdc8d8SChris Lattner       }
51130fdc8d8SChris Lattner     }
51230fdc8d8SChris Lattner   }
51330fdc8d8SChris Lattner   return target_sp;
51430fdc8d8SChris Lattner }
51530fdc8d8SChris Lattner 
516b9c1b51eSKate Stone TargetSP TargetList::GetTargetSP(Target *target) const {
51730fdc8d8SChris Lattner   TargetSP target_sp;
518b9c1b51eSKate Stone   if (target) {
51916ff8604SSaleem Abdulrasool     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
52030fdc8d8SChris Lattner     collection::const_iterator pos, end = m_target_list.end();
521b9c1b51eSKate Stone     for (pos = m_target_list.begin(); pos != end; ++pos) {
522b9c1b51eSKate Stone       if (target == (*pos).get()) {
52330fdc8d8SChris Lattner         target_sp = *pos;
52430fdc8d8SChris Lattner         break;
52530fdc8d8SChris Lattner       }
52630fdc8d8SChris Lattner     }
52730fdc8d8SChris Lattner   }
52830fdc8d8SChris Lattner   return target_sp;
52930fdc8d8SChris Lattner }
53030fdc8d8SChris Lattner 
531b9c1b51eSKate Stone uint32_t TargetList::SendAsyncInterrupt(lldb::pid_t pid) {
53230fdc8d8SChris Lattner   uint32_t num_async_interrupts_sent = 0;
53330fdc8d8SChris Lattner 
534b9c1b51eSKate Stone   if (pid != LLDB_INVALID_PROCESS_ID) {
53530fdc8d8SChris Lattner     TargetSP target_sp(FindTargetWithProcessID(pid));
536b9c1b51eSKate Stone     if (target_sp) {
53730fdc8d8SChris Lattner       Process *process = target_sp->GetProcessSP().get();
538b9c1b51eSKate Stone       if (process) {
539cfc0935eSJim Ingham         process->SendAsyncInterrupt();
54030fdc8d8SChris Lattner         ++num_async_interrupts_sent;
54130fdc8d8SChris Lattner       }
54230fdc8d8SChris Lattner     }
543b9c1b51eSKate Stone   } else {
54430fdc8d8SChris Lattner     // We don't have a valid pid to broadcast to, so broadcast to the target
54530fdc8d8SChris Lattner     // list's async broadcaster...
546e65b2cf2SEugene Zelenko     BroadcastEvent(Process::eBroadcastBitInterrupt, nullptr);
54730fdc8d8SChris Lattner   }
54830fdc8d8SChris Lattner 
54930fdc8d8SChris Lattner   return num_async_interrupts_sent;
55030fdc8d8SChris Lattner }
55130fdc8d8SChris Lattner 
552b9c1b51eSKate Stone uint32_t TargetList::SignalIfRunning(lldb::pid_t pid, int signo) {
55330fdc8d8SChris Lattner   uint32_t num_signals_sent = 0;
554e65b2cf2SEugene Zelenko   Process *process = nullptr;
555b9c1b51eSKate Stone   if (pid == LLDB_INVALID_PROCESS_ID) {
55630fdc8d8SChris Lattner     // Signal all processes with signal
55716ff8604SSaleem Abdulrasool     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
55830fdc8d8SChris Lattner     collection::iterator pos, end = m_target_list.end();
559b9c1b51eSKate Stone     for (pos = m_target_list.begin(); pos != end; ++pos) {
56030fdc8d8SChris Lattner       process = (*pos)->GetProcessSP().get();
561b9c1b51eSKate Stone       if (process) {
562b9c1b51eSKate Stone         if (process->IsAlive()) {
56330fdc8d8SChris Lattner           ++num_signals_sent;
56430fdc8d8SChris Lattner           process->Signal(signo);
56530fdc8d8SChris Lattner         }
56630fdc8d8SChris Lattner       }
56730fdc8d8SChris Lattner     }
568b9c1b51eSKate Stone   } else {
56930fdc8d8SChris Lattner     // Signal a specific process with signal
57030fdc8d8SChris Lattner     TargetSP target_sp(FindTargetWithProcessID(pid));
571b9c1b51eSKate Stone     if (target_sp) {
57230fdc8d8SChris Lattner       process = target_sp->GetProcessSP().get();
573b9c1b51eSKate Stone       if (process) {
574b9c1b51eSKate Stone         if (process->IsAlive()) {
57530fdc8d8SChris Lattner           ++num_signals_sent;
57630fdc8d8SChris Lattner           process->Signal(signo);
57730fdc8d8SChris Lattner         }
57830fdc8d8SChris Lattner       }
57930fdc8d8SChris Lattner     }
58030fdc8d8SChris Lattner   }
58130fdc8d8SChris Lattner   return num_signals_sent;
58230fdc8d8SChris Lattner }
58330fdc8d8SChris Lattner 
584b9c1b51eSKate Stone int TargetList::GetNumTargets() const {
58516ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
58630fdc8d8SChris Lattner   return m_target_list.size();
58730fdc8d8SChris Lattner }
58830fdc8d8SChris Lattner 
589b9c1b51eSKate Stone lldb::TargetSP TargetList::GetTargetAtIndex(uint32_t idx) const {
59030fdc8d8SChris Lattner   TargetSP target_sp;
59116ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
59230fdc8d8SChris Lattner   if (idx < m_target_list.size())
59330fdc8d8SChris Lattner     target_sp = m_target_list[idx];
59430fdc8d8SChris Lattner   return target_sp;
59530fdc8d8SChris Lattner }
59630fdc8d8SChris Lattner 
597b9c1b51eSKate Stone uint32_t TargetList::GetIndexOfTarget(lldb::TargetSP target_sp) const {
59816ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
5998499e1a4SJim Ingham   size_t num_targets = m_target_list.size();
600b9c1b51eSKate Stone   for (size_t idx = 0; idx < num_targets; idx++) {
6018499e1a4SJim Ingham     if (target_sp == m_target_list[idx])
6028499e1a4SJim Ingham       return idx;
6038499e1a4SJim Ingham   }
6048499e1a4SJim Ingham   return UINT32_MAX;
6058499e1a4SJim Ingham }
6068499e1a4SJim Ingham 
607b9c1b51eSKate Stone uint32_t TargetList::SetSelectedTarget(Target *target) {
60816ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
609b9c1b51eSKate Stone   collection::const_iterator pos, begin = m_target_list.begin(),
61030fdc8d8SChris Lattner                                   end = m_target_list.end();
611b9c1b51eSKate Stone   for (pos = begin; pos != end; ++pos) {
612b9c1b51eSKate Stone     if (pos->get() == target) {
6132976d00aSJim Ingham       m_selected_target_idx = std::distance(begin, pos);
6142976d00aSJim Ingham       return m_selected_target_idx;
61530fdc8d8SChris Lattner     }
61630fdc8d8SChris Lattner   }
6172976d00aSJim Ingham   m_selected_target_idx = 0;
6182976d00aSJim Ingham   return m_selected_target_idx;
61930fdc8d8SChris Lattner }
62030fdc8d8SChris Lattner 
621b9c1b51eSKate Stone lldb::TargetSP TargetList::GetSelectedTarget() {
62216ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
6232976d00aSJim Ingham   if (m_selected_target_idx >= m_target_list.size())
6242976d00aSJim Ingham     m_selected_target_idx = 0;
6252976d00aSJim Ingham   return GetTargetAtIndex(m_selected_target_idx);
62630fdc8d8SChris Lattner }
627