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/Core/Timer.h"
1930fdc8d8SChris Lattner #include "lldb/Host/Host.h"
20893c932aSJim Ingham #include "lldb/Host/HostInfo.h"
21b3a40ba8SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
22cac9c5f9SGreg Clayton #include "lldb/Interpreter/OptionGroupPlatform.h"
23f4d6de6aSGreg Clayton #include "lldb/Symbol/ObjectFile.h"
24e996fd30SGreg Clayton #include "lldb/Target/Platform.h"
2530fdc8d8SChris Lattner #include "lldb/Target/Process.h"
2630fdc8d8SChris Lattner 
271d5855b1SPavel Labath // Other libraries and framework includes
281d5855b1SPavel Labath #include "llvm/ADT/SmallString.h"
291d5855b1SPavel Labath #include "llvm/Support/FileSystem.h"
301d5855b1SPavel Labath 
3130fdc8d8SChris Lattner using namespace lldb;
3230fdc8d8SChris Lattner using namespace lldb_private;
3330fdc8d8SChris Lattner 
34b9c1b51eSKate Stone ConstString &TargetList::GetStaticBroadcasterClass() {
354bddaeb5SJim Ingham   static ConstString class_name("lldb.targetList");
364bddaeb5SJim Ingham   return class_name;
374bddaeb5SJim Ingham }
3830fdc8d8SChris Lattner 
3930fdc8d8SChris Lattner //----------------------------------------------------------------------
4030fdc8d8SChris Lattner // TargetList constructor
4130fdc8d8SChris Lattner //----------------------------------------------------------------------
4216ff8604SSaleem Abdulrasool TargetList::TargetList(Debugger &debugger)
43b9c1b51eSKate Stone     : Broadcaster(debugger.GetBroadcasterManager(),
44b9c1b51eSKate Stone                   TargetList::GetStaticBroadcasterClass().AsCString()),
45b9c1b51eSKate Stone       m_target_list(), m_target_list_mutex(), m_selected_target_idx(0) {
464bddaeb5SJim Ingham   CheckInWithManager();
4730fdc8d8SChris Lattner }
4830fdc8d8SChris Lattner 
4930fdc8d8SChris Lattner //----------------------------------------------------------------------
5030fdc8d8SChris Lattner // Destructor
5130fdc8d8SChris Lattner //----------------------------------------------------------------------
52b9c1b51eSKate Stone TargetList::~TargetList() {
5316ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
5430fdc8d8SChris Lattner   m_target_list.clear();
5530fdc8d8SChris Lattner }
5630fdc8d8SChris Lattner 
57a47464b2SZachary Turner Error TargetList::CreateTarget(Debugger &debugger,
58a47464b2SZachary Turner                                llvm::StringRef user_exe_path,
59a47464b2SZachary Turner                                llvm::StringRef triple_str,
60cac9c5f9SGreg Clayton                                bool get_dependent_files,
61cac9c5f9SGreg Clayton                                const OptionGroupPlatform *platform_options,
62b9c1b51eSKate Stone                                TargetSP &target_sp) {
63a47464b2SZachary Turner   return CreateTargetInternal(debugger, user_exe_path, triple_str,
64b9c1b51eSKate Stone                               get_dependent_files, platform_options, target_sp,
65893c932aSJim Ingham                               false);
66893c932aSJim Ingham }
67893c932aSJim Ingham 
68a47464b2SZachary Turner Error TargetList::CreateTarget(Debugger &debugger,
69a47464b2SZachary Turner                                llvm::StringRef user_exe_path,
70893c932aSJim Ingham                                const ArchSpec &specified_arch,
71893c932aSJim Ingham                                bool get_dependent_files,
72b9c1b51eSKate Stone                                PlatformSP &platform_sp, TargetSP &target_sp) {
73b9c1b51eSKate Stone   return CreateTargetInternal(debugger, user_exe_path, specified_arch,
74b9c1b51eSKate Stone                               get_dependent_files, platform_sp, target_sp,
75893c932aSJim Ingham                               false);
76893c932aSJim Ingham }
77893c932aSJim Ingham 
78b9c1b51eSKate Stone Error TargetList::CreateTargetInternal(
79a47464b2SZachary Turner     Debugger &debugger, llvm::StringRef user_exe_path,
80a47464b2SZachary Turner     llvm::StringRef triple_str, bool get_dependent_files,
81a47464b2SZachary Turner     const OptionGroupPlatform *platform_options, TargetSP &target_sp,
82a47464b2SZachary Turner     bool is_dummy_target) {
83cac9c5f9SGreg Clayton   Error error;
84cac9c5f9SGreg Clayton   PlatformSP platform_sp;
85cac9c5f9SGreg Clayton 
86cdc21d4cSJohnny Chen   // This is purposely left empty unless it is specified by triple_cstr.
87cdc21d4cSJohnny Chen   // If not initialized via triple_cstr, then the currently selected platform
88cdc21d4cSJohnny Chen   // will set the architecture correctly.
89a47464b2SZachary Turner   const ArchSpec arch(triple_str);
90a47464b2SZachary Turner   if (!triple_str.empty()) {
91b9c1b51eSKate Stone     if (!arch.IsValid()) {
92a47464b2SZachary Turner       error.SetErrorStringWithFormat("invalid triple '%s'",
93a47464b2SZachary Turner                                      triple_str.str().c_str());
94cac9c5f9SGreg Clayton       return error;
95cac9c5f9SGreg Clayton     }
96cac9c5f9SGreg Clayton   }
97b3a40ba8SGreg Clayton 
9870512317SGreg Clayton   ArchSpec platform_arch(arch);
99f4d6de6aSGreg Clayton 
1003f19ada8SGreg Clayton   bool prefer_platform_arch = false;
101f4d6de6aSGreg Clayton 
102b0cc53cfSGreg Clayton   CommandInterpreter &interpreter = debugger.GetCommandInterpreter();
1031b5a74eeSVince Harron 
104b9c1b51eSKate Stone   // let's see if there is already an existing plaform before we go creating
105b9c1b51eSKate Stone   // another...
1061b5a74eeSVince Harron   platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
1071b5a74eeSVince Harron 
108b9c1b51eSKate Stone   if (platform_options && platform_options->PlatformWasSpecified()) {
109ccd2a6d9SGreg Clayton     // Create a new platform if it doesn't match the selected platform
110b9c1b51eSKate Stone     if (!platform_options->PlatformMatches(platform_sp)) {
111b0cc53cfSGreg Clayton       const bool select_platform = true;
112b9c1b51eSKate Stone       platform_sp = platform_options->CreatePlatformWithOptions(
113b9c1b51eSKate Stone           interpreter, arch, select_platform, error, platform_arch);
114b0cc53cfSGreg Clayton       if (!platform_sp)
115b0cc53cfSGreg Clayton         return error;
116b0cc53cfSGreg Clayton     }
117ccd2a6d9SGreg Clayton   }
118b0cc53cfSGreg Clayton 
119a47464b2SZachary Turner   if (!user_exe_path.empty()) {
120f4d6de6aSGreg Clayton     ModuleSpecList module_specs;
121f4d6de6aSGreg Clayton     ModuleSpec module_spec;
122f4d6de6aSGreg Clayton     module_spec.GetFileSpec().SetFile(user_exe_path, true);
123c76fa8a3SGreg Clayton 
124b9c1b51eSKate Stone     // Resolve the executable in case we are given a path to a application
125b9c1b51eSKate Stone     // bundle
126c76fa8a3SGreg Clayton     // 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
1423f19ada8SGreg Clayton               // architecture so that the platform matching can be more accurate
143b9c1b51eSKate Stone               if (!platform_arch.TripleOSWasSpecified() ||
144b9c1b51eSKate Stone                   !platform_arch.TripleVendorWasSpecified()) {
1453f19ada8SGreg Clayton                 prefer_platform_arch = true;
1463f19ada8SGreg Clayton                 platform_arch = matching_module_spec.GetArchitecture();
1473f19ada8SGreg Clayton               }
148b9c1b51eSKate Stone             } else {
1497df337f8STodd Fiala               StreamString platform_arch_strm;
1507df337f8STodd Fiala               StreamString module_arch_strm;
1517df337f8STodd Fiala 
1527df337f8STodd Fiala               platform_arch.DumpTriple(platform_arch_strm);
153b9c1b51eSKate Stone               matching_module_spec.GetArchitecture().DumpTriple(
154b9c1b51eSKate Stone                   module_arch_strm);
155b9c1b51eSKate Stone               error.SetErrorStringWithFormat(
156b9c1b51eSKate Stone                   "the specified architecture '%s' is not compatible with '%s' "
157b9c1b51eSKate Stone                   "in '%s'",
158c156427dSZachary Turner                   platform_arch_strm.GetData(), module_arch_strm.GetData(),
159b5ad4ec7SGreg Clayton                   module_spec.GetFileSpec().GetPath().c_str());
160f4d6de6aSGreg Clayton               return error;
161f4d6de6aSGreg Clayton             }
162b9c1b51eSKate Stone           } else {
163f4d6de6aSGreg Clayton             // Only one arch and none was specified
1643f19ada8SGreg Clayton             prefer_platform_arch = true;
165f4d6de6aSGreg Clayton             platform_arch = matching_module_spec.GetArchitecture();
166f4d6de6aSGreg Clayton           }
167f4d6de6aSGreg Clayton         }
168b9c1b51eSKate Stone       } else {
169b9c1b51eSKate Stone         if (arch.IsValid()) {
170f4d6de6aSGreg Clayton           module_spec.GetArchitecture() = arch;
171b9c1b51eSKate Stone           if (module_specs.FindMatchingModuleSpec(module_spec,
172b9c1b51eSKate Stone                                                   matching_module_spec)) {
1733f19ada8SGreg Clayton             prefer_platform_arch = true;
174f4d6de6aSGreg Clayton             platform_arch = matching_module_spec.GetArchitecture();
175f4d6de6aSGreg Clayton           }
176b9c1b51eSKate Stone         } else {
177b0cc53cfSGreg Clayton           // No architecture specified, check if there is only one platform for
178b0cc53cfSGreg Clayton           // all of the architectures.
179b0cc53cfSGreg Clayton 
180b0cc53cfSGreg Clayton           typedef std::vector<PlatformSP> PlatformList;
181b0cc53cfSGreg Clayton           PlatformList platforms;
182615eb7e6SGreg Clayton           PlatformSP host_platform_sp = Platform::GetHostPlatform();
183b9c1b51eSKate Stone           for (size_t i = 0; i < num_specs; ++i) {
184b0cc53cfSGreg Clayton             ModuleSpec module_spec;
185b9c1b51eSKate Stone             if (module_specs.GetModuleSpecAtIndex(i, module_spec)) {
186b0cc53cfSGreg Clayton               // See if there was a selected platform and check that first
187b0cc53cfSGreg Clayton               // since the user may have specified it.
188b9c1b51eSKate Stone               if (platform_sp) {
189b9c1b51eSKate Stone                 if (platform_sp->IsCompatibleArchitecture(
190b9c1b51eSKate Stone                         module_spec.GetArchitecture(), false, nullptr)) {
191b0cc53cfSGreg Clayton                   platforms.push_back(platform_sp);
192b0cc53cfSGreg Clayton                   continue;
193f4d6de6aSGreg Clayton                 }
194f4d6de6aSGreg Clayton               }
195f4d6de6aSGreg Clayton 
196b0cc53cfSGreg Clayton               // Next check the host platform it if wasn't already checked above
197b9c1b51eSKate Stone               if (host_platform_sp &&
198b9c1b51eSKate Stone                   (!platform_sp ||
199b9c1b51eSKate Stone                    host_platform_sp->GetName() != platform_sp->GetName())) {
200b9c1b51eSKate Stone                 if (host_platform_sp->IsCompatibleArchitecture(
201b9c1b51eSKate Stone                         module_spec.GetArchitecture(), false, nullptr)) {
202b0cc53cfSGreg Clayton                   platforms.push_back(host_platform_sp);
203b0cc53cfSGreg Clayton                   continue;
204b0cc53cfSGreg Clayton                 }
205b0cc53cfSGreg Clayton               }
206b0cc53cfSGreg Clayton 
207b9c1b51eSKate Stone               // Just find a platform that matches the architecture in the
208b9c1b51eSKate Stone               // executable file
209b9c1b51eSKate Stone               PlatformSP fallback_platform_sp(
210b9c1b51eSKate Stone                   Platform::GetPlatformForArchitecture(
211b9c1b51eSKate Stone                       module_spec.GetArchitecture(), nullptr));
212b9c1b51eSKate Stone               if (fallback_platform_sp) {
213e92a74ceSJason Molenda                 platforms.push_back(fallback_platform_sp);
214e92a74ceSJason Molenda               }
215b0cc53cfSGreg Clayton             }
216b0cc53cfSGreg Clayton           }
217b0cc53cfSGreg Clayton 
218e65b2cf2SEugene Zelenko           Platform *platform_ptr = nullptr;
2199d58c728SJason Molenda           bool more_than_one_platforms = false;
220b9c1b51eSKate Stone           for (const auto &the_platform_sp : platforms) {
221b9c1b51eSKate Stone             if (platform_ptr) {
222b9c1b51eSKate Stone               if (platform_ptr->GetName() != the_platform_sp->GetName()) {
2239d58c728SJason Molenda                 more_than_one_platforms = true;
224e65b2cf2SEugene Zelenko                 platform_ptr = nullptr;
225b0cc53cfSGreg Clayton                 break;
226b0cc53cfSGreg Clayton               }
227b9c1b51eSKate Stone             } else {
228b0cc53cfSGreg Clayton               platform_ptr = the_platform_sp.get();
229b0cc53cfSGreg Clayton             }
230b0cc53cfSGreg Clayton           }
231b0cc53cfSGreg Clayton 
232b9c1b51eSKate Stone           if (platform_ptr) {
233b9c1b51eSKate Stone             // All platforms for all modules in the exectuable match, so we can
234b9c1b51eSKate Stone             // select this platform
235b0cc53cfSGreg Clayton             platform_sp = platforms.front();
236b9c1b51eSKate Stone           } else if (more_than_one_platforms == false) {
2379d58c728SJason Molenda             // No platforms claim to support this file
238b9c1b51eSKate Stone             error.SetErrorString("No matching platforms found for this file, "
239b9c1b51eSKate Stone                                  "specify one with the --platform option");
2409d58c728SJason Molenda             return error;
241b9c1b51eSKate Stone           } else {
242b9c1b51eSKate Stone             // More than one platform claims to support this file, so the
243b9c1b51eSKate Stone             // --platform option must be specified
244b0cc53cfSGreg Clayton             StreamString error_strm;
245b0cc53cfSGreg Clayton             std::set<Platform *> platform_set;
246b9c1b51eSKate Stone             error_strm.Printf(
247b9c1b51eSKate Stone                 "more than one platform supports this executable (");
248b9c1b51eSKate Stone             for (const auto &the_platform_sp : platforms) {
249b9c1b51eSKate Stone               if (platform_set.find(the_platform_sp.get()) ==
250b9c1b51eSKate Stone                   platform_set.end()) {
251b0cc53cfSGreg Clayton                 if (!platform_set.empty())
252b0cc53cfSGreg Clayton                   error_strm.PutCString(", ");
253b0cc53cfSGreg Clayton                 error_strm.PutCString(the_platform_sp->GetName().GetCString());
254b0cc53cfSGreg Clayton                 platform_set.insert(the_platform_sp.get());
255b0cc53cfSGreg Clayton               }
256b0cc53cfSGreg Clayton             }
257b9c1b51eSKate Stone             error_strm.Printf(
258b9c1b51eSKate Stone                 "), use the --platform option to specify a platform");
259c156427dSZachary Turner             error.SetErrorString(error_strm.GetString());
260b3a40ba8SGreg Clayton             return error;
261b3a40ba8SGreg Clayton           }
262b3a40ba8SGreg Clayton         }
263b0cc53cfSGreg Clayton       }
264b0cc53cfSGreg Clayton     }
265b0cc53cfSGreg Clayton   }
266b3a40ba8SGreg Clayton 
267869e0c1cSTed Woodward   // If we have a valid architecture, make sure the current platform is
268869e0c1cSTed Woodward   // compatible with that architecture
269b9c1b51eSKate Stone   if (!prefer_platform_arch && arch.IsValid()) {
270b9c1b51eSKate Stone     if (!platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) {
27170512317SGreg Clayton       platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch);
2728ec55a53SRobert Flack       if (!is_dummy_target && platform_sp)
27395bbdf64SGreg Clayton         debugger.GetPlatformList().SetSelectedPlatform(platform_sp);
27495bbdf64SGreg Clayton     }
275b9c1b51eSKate Stone   } else if (platform_arch.IsValid()) {
276b9c1b51eSKate Stone     // if "arch" isn't valid, yet "platform_arch" is, it means we have an
277b9c1b51eSKate Stone     // executable file with
2783f19ada8SGreg Clayton     // a single architecture which should be used
2793f19ada8SGreg Clayton     ArchSpec fixed_platform_arch;
280b9c1b51eSKate Stone     if (!platform_sp->IsCompatibleArchitecture(platform_arch, false,
281b9c1b51eSKate Stone                                                &fixed_platform_arch)) {
282b9c1b51eSKate Stone       platform_sp = Platform::GetPlatformForArchitecture(platform_arch,
283b9c1b51eSKate Stone                                                          &fixed_platform_arch);
2848ec55a53SRobert Flack       if (!is_dummy_target && platform_sp)
28595bbdf64SGreg Clayton         debugger.GetPlatformList().SetSelectedPlatform(platform_sp);
28695bbdf64SGreg Clayton     }
2873f19ada8SGreg Clayton   }
288b3a40ba8SGreg Clayton 
28970512317SGreg Clayton   if (!platform_arch.IsValid())
29070512317SGreg Clayton     platform_arch = arch;
29170512317SGreg Clayton 
292b9c1b51eSKate Stone   error = TargetList::CreateTargetInternal(
293b9c1b51eSKate Stone       debugger, user_exe_path, platform_arch, get_dependent_files, platform_sp,
294b9c1b51eSKate Stone       target_sp, is_dummy_target);
295cac9c5f9SGreg Clayton   return error;
296cac9c5f9SGreg Clayton }
297cac9c5f9SGreg Clayton 
298b9c1b51eSKate Stone lldb::TargetSP TargetList::GetDummyTarget(lldb_private::Debugger &debugger) {
299893c932aSJim Ingham   // FIXME: Maybe the dummy target should be per-Debugger
300b9c1b51eSKate Stone   if (!m_dummy_target_sp || !m_dummy_target_sp->IsValid()) {
301893c932aSJim Ingham     ArchSpec arch(Target::GetDefaultArchitecture());
302893c932aSJim Ingham     if (!arch.IsValid())
303893c932aSJim Ingham       arch = HostInfo::GetArchitecture();
304b9c1b51eSKate Stone     Error err = CreateDummyTarget(
305b9c1b51eSKate Stone         debugger, arch.GetTriple().getTriple().c_str(), m_dummy_target_sp);
306893c932aSJim Ingham   }
307893c932aSJim Ingham 
308893c932aSJim Ingham   return m_dummy_target_sp;
309893c932aSJim Ingham }
310893c932aSJim Ingham 
311b9c1b51eSKate Stone Error TargetList::CreateDummyTarget(Debugger &debugger,
312a47464b2SZachary Turner                                     llvm::StringRef specified_arch_name,
313b9c1b51eSKate Stone                                     lldb::TargetSP &target_sp) {
314893c932aSJim Ingham   PlatformSP host_platform_sp(Platform::GetHostPlatform());
315b9c1b51eSKate Stone   return CreateTargetInternal(
316b9c1b51eSKate Stone       debugger, (const char *)nullptr, specified_arch_name, false,
317b9c1b51eSKate Stone       (const OptionGroupPlatform *)nullptr, target_sp, true);
318893c932aSJim Ingham }
319893c932aSJim Ingham 
320b9c1b51eSKate Stone Error TargetList::CreateTargetInternal(Debugger &debugger,
321a47464b2SZachary Turner                                        llvm::StringRef user_exe_path,
32270512317SGreg Clayton                                        const ArchSpec &specified_arch,
32330fdc8d8SChris Lattner                                        bool get_dependent_files,
324893c932aSJim Ingham                                        lldb::PlatformSP &platform_sp,
325893c932aSJim Ingham                                        lldb::TargetSP &target_sp,
326b9c1b51eSKate Stone                                        bool is_dummy_target) {
327f343968fSZachary Turner   Timer scoped_timer(LLVM_PRETTY_FUNCTION,
328a0ca6601SGreg Clayton                      "TargetList::CreateTarget (file = '%s', arch = '%s')",
32972f4997cSZachary Turner                      user_exe_path.str().c_str(),
33072f4997cSZachary Turner                      specified_arch.GetArchitectureName());
3315aee162fSJim Ingham   Error error;
3325aee162fSJim Ingham 
33370512317SGreg Clayton   ArchSpec arch(specified_arch);
33470512317SGreg Clayton 
335b9c1b51eSKate Stone   if (arch.IsValid()) {
336b9c1b51eSKate Stone     if (!platform_sp ||
337b9c1b51eSKate Stone         !platform_sp->IsCompatibleArchitecture(arch, false, nullptr))
33870512317SGreg Clayton       platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
33970512317SGreg Clayton   }
34070512317SGreg Clayton 
34170512317SGreg Clayton   if (!platform_sp)
34270512317SGreg Clayton     platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
343ded470d3SGreg Clayton 
3448ae50eb4SGreg Clayton   if (!arch.IsValid())
3458ae50eb4SGreg Clayton     arch = specified_arch;
3468ae50eb4SGreg Clayton 
347d26206b5SJason Molenda   FileSpec file(user_exe_path, false);
348a47464b2SZachary Turner   if (!file.Exists() && user_exe_path.startswith("~")) {
349b9c1b51eSKate Stone     // we want to expand the tilde but we don't want to resolve any symbolic
350b9c1b51eSKate Stone     // links
3519f822cd1SMichael Sartain     // so we can't use the FileSpec constructor's resolve flag
3523f559740SZachary Turner     llvm::SmallString<64> unglobbed_path(user_exe_path);
3533f559740SZachary Turner     FileSpec::ResolveUsername(unglobbed_path);
3549f822cd1SMichael Sartain 
3553f559740SZachary Turner     if (unglobbed_path.empty())
3563f559740SZachary Turner       file = FileSpec(user_exe_path, false);
3573f559740SZachary Turner     else
3583f559740SZachary Turner       file = FileSpec(unglobbed_path.c_str(), false);
359d26206b5SJason Molenda   }
3609f822cd1SMichael Sartain 
36182d79295SGreg Clayton   bool user_exe_path_is_bundle = false;
36282d79295SGreg Clayton   char resolved_bundle_exe_path[PATH_MAX];
36382d79295SGreg Clayton   resolved_bundle_exe_path[0] = '\0';
364b9c1b51eSKate Stone   if (file) {
365*7d86ee5aSZachary Turner     if (llvm::sys::fs::is_directory(file.GetPath()))
36682d79295SGreg Clayton       user_exe_path_is_bundle = true;
36782d79295SGreg Clayton 
368a47464b2SZachary Turner     if (file.IsRelative() && !user_exe_path.empty()) {
369a0ca6601SGreg Clayton       // Ignore paths that start with "./" and "../"
370a47464b2SZachary Turner       if (!user_exe_path.startswith("./") && !user_exe_path.startswith("../")) {
3711d5855b1SPavel Labath         llvm::SmallString<64> cwd;
3721d5855b1SPavel Labath         if (! llvm::sys::fs::current_path(cwd)) {
3731d5855b1SPavel Labath           cwd += '/';
3741d5855b1SPavel Labath           cwd += user_exe_path;
3751d5855b1SPavel Labath           FileSpec cwd_file(cwd, false);
3769ff5aae5SGreg Clayton           if (cwd_file.Exists())
3779ff5aae5SGreg Clayton             file = cwd_file;
378a0ca6601SGreg Clayton         }
379a0ca6601SGreg Clayton       }
380a0ca6601SGreg Clayton     }
381a0ca6601SGreg Clayton 
38230fdc8d8SChris Lattner     ModuleSP exe_module_sp;
383b9c1b51eSKate Stone     if (platform_sp) {
384b9c1b51eSKate Stone       FileSpecList executable_search_paths(
385b9c1b51eSKate Stone           Target::GetDefaultExecutableSearchPaths());
3868012cadbSGreg Clayton       ModuleSpec module_spec(file, arch);
387b9c1b51eSKate Stone       error = platform_sp->ResolveExecutable(module_spec, exe_module_sp,
388b9c1b51eSKate Stone                                              executable_search_paths.GetSize()
389b9c1b51eSKate Stone                                                  ? &executable_search_paths
390b9c1b51eSKate Stone                                                  : nullptr);
391c859e2d5SGreg Clayton     }
392428a9a58SCaroline Tice 
393b9c1b51eSKate Stone     if (error.Success() && exe_module_sp) {
394b9c1b51eSKate Stone       if (exe_module_sp->GetObjectFile() == nullptr) {
395b9c1b51eSKate Stone         if (arch.IsValid()) {
396b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
397b9c1b51eSKate Stone               "\"%s\" doesn't contain architecture %s", file.GetPath().c_str(),
39864195a2cSGreg Clayton               arch.GetArchitectureName());
399b9c1b51eSKate Stone         } else {
400b5ad4ec7SGreg Clayton           error.SetErrorStringWithFormat("unsupported file type \"%s\"",
401b5ad4ec7SGreg Clayton                                          file.GetPath().c_str());
402bc5cad6cSGreg Clayton         }
4035aee162fSJim Ingham         return error;
4045aee162fSJim Ingham       }
405893c932aSJim Ingham       target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
40630fdc8d8SChris Lattner       target_sp->SetExecutableModule(exe_module_sp, get_dependent_files);
40782d79295SGreg Clayton       if (user_exe_path_is_bundle)
408b9c1b51eSKate Stone         exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path,
409b9c1b51eSKate Stone                                              sizeof(resolved_bundle_exe_path));
4105aee162fSJim Ingham     }
411b9c1b51eSKate Stone   } else {
412e996fd30SGreg Clayton     // No file was specified, just create an empty target with any arch
413e996fd30SGreg Clayton     // if a valid arch was specified
414893c932aSJim Ingham     target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
415e996fd30SGreg Clayton   }
4161559a46bSCaroline Tice 
417b9c1b51eSKate Stone   if (target_sp) {
41882d79295SGreg Clayton     // Set argv0 with what the user typed, unless the user specified a
41982d79295SGreg Clayton     // directory. If the user specified a directory, then it is probably a
42082d79295SGreg Clayton     // bundle that was resolved and we need to use the resolved bundle path
421a47464b2SZachary Turner     if (!user_exe_path.empty()) {
422b9c1b51eSKate Stone       // Use exactly what the user typed as the first argument when we exec or
423b9c1b51eSKate Stone       // posix_spawn
424b9c1b51eSKate Stone       if (user_exe_path_is_bundle && resolved_bundle_exe_path[0]) {
42582d79295SGreg Clayton         target_sp->SetArg0(resolved_bundle_exe_path);
426b9c1b51eSKate Stone       } else {
4279f822cd1SMichael Sartain         // Use resolved path
4289f822cd1SMichael Sartain         target_sp->SetArg0(file.GetPath().c_str());
429a0ca6601SGreg Clayton       }
43082d79295SGreg Clayton     }
431b9c1b51eSKate Stone     if (file.GetDirectory()) {
432a0ca6601SGreg Clayton       FileSpec file_dir;
433a0ca6601SGreg Clayton       file_dir.GetDirectory() = file.GetDirectory();
434a0ca6601SGreg Clayton       target_sp->GetExecutableSearchPaths().Append(file_dir);
435a0ca6601SGreg Clayton     }
436893c932aSJim Ingham 
437893c932aSJim Ingham     // Don't put the dummy target in the target list, it's held separately.
438b9c1b51eSKate Stone     if (!is_dummy_target) {
43916ff8604SSaleem Abdulrasool       std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
4402976d00aSJim Ingham       m_selected_target_idx = m_target_list.size();
44130fdc8d8SChris Lattner       m_target_list.push_back(target_sp);
44233df7cd3SJim Ingham       // Now prime this from the dummy target:
44333df7cd3SJim Ingham       target_sp->PrimeFromDummyTarget(debugger.GetDummyTarget());
444b9c1b51eSKate Stone     } else {
445893c932aSJim Ingham       m_dummy_target_sp = target_sp;
446893c932aSJim Ingham     }
44730fdc8d8SChris Lattner   }
44830fdc8d8SChris Lattner 
44930fdc8d8SChris Lattner   return error;
45030fdc8d8SChris Lattner }
45130fdc8d8SChris Lattner 
452b9c1b51eSKate Stone bool TargetList::DeleteTarget(TargetSP &target_sp) {
45316ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
45430fdc8d8SChris Lattner   collection::iterator pos, end = m_target_list.end();
45530fdc8d8SChris Lattner 
456b9c1b51eSKate Stone   for (pos = m_target_list.begin(); pos != end; ++pos) {
457b9c1b51eSKate Stone     if (pos->get() == target_sp.get()) {
45830fdc8d8SChris Lattner       m_target_list.erase(pos);
45930fdc8d8SChris Lattner       return true;
46030fdc8d8SChris Lattner     }
46130fdc8d8SChris Lattner   }
46230fdc8d8SChris Lattner   return false;
46330fdc8d8SChris Lattner }
46430fdc8d8SChris Lattner 
465b9c1b51eSKate Stone TargetSP TargetList::FindTargetWithExecutableAndArchitecture(
466b9c1b51eSKate Stone     const FileSpec &exe_file_spec, const ArchSpec *exe_arch_ptr) const {
46716ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
46830fdc8d8SChris Lattner   TargetSP target_sp;
469ddd7a2a6SSean Callanan   bool full_match = (bool)exe_file_spec.GetDirectory();
47030fdc8d8SChris Lattner 
47130fdc8d8SChris Lattner   collection::const_iterator pos, end = m_target_list.end();
472b9c1b51eSKate Stone   for (pos = m_target_list.begin(); pos != end; ++pos) {
473aa149cbdSGreg Clayton     Module *exe_module = (*pos)->GetExecutableModulePointer();
47430fdc8d8SChris Lattner 
475b9c1b51eSKate Stone     if (exe_module) {
476b9c1b51eSKate Stone       if (FileSpec::Equal(exe_file_spec, exe_module->GetFileSpec(),
477b9c1b51eSKate Stone                           full_match)) {
478b9c1b51eSKate Stone         if (exe_arch_ptr) {
479bf4b7be6SSean Callanan           if (!exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture()))
48030fdc8d8SChris Lattner             continue;
48130fdc8d8SChris Lattner         }
48230fdc8d8SChris Lattner         target_sp = *pos;
48330fdc8d8SChris Lattner         break;
48430fdc8d8SChris Lattner       }
48530fdc8d8SChris Lattner     }
48630fdc8d8SChris Lattner   }
48730fdc8d8SChris Lattner   return target_sp;
48830fdc8d8SChris Lattner }
48930fdc8d8SChris Lattner 
490b9c1b51eSKate Stone TargetSP TargetList::FindTargetWithProcessID(lldb::pid_t pid) const {
49116ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
49230fdc8d8SChris Lattner   TargetSP target_sp;
49330fdc8d8SChris Lattner   collection::const_iterator pos, end = m_target_list.end();
494b9c1b51eSKate Stone   for (pos = m_target_list.begin(); pos != end; ++pos) {
49530fdc8d8SChris Lattner     Process *process = (*pos)->GetProcessSP().get();
496b9c1b51eSKate Stone     if (process && process->GetID() == pid) {
49730fdc8d8SChris Lattner       target_sp = *pos;
49830fdc8d8SChris Lattner       break;
49930fdc8d8SChris Lattner     }
50030fdc8d8SChris Lattner   }
50130fdc8d8SChris Lattner   return target_sp;
50230fdc8d8SChris Lattner }
50330fdc8d8SChris Lattner 
504b9c1b51eSKate Stone TargetSP TargetList::FindTargetWithProcess(Process *process) const {
50530fdc8d8SChris Lattner   TargetSP target_sp;
506b9c1b51eSKate Stone   if (process) {
50716ff8604SSaleem Abdulrasool     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
50830fdc8d8SChris Lattner     collection::const_iterator pos, end = m_target_list.end();
509b9c1b51eSKate Stone     for (pos = m_target_list.begin(); pos != end; ++pos) {
510b9c1b51eSKate Stone       if (process == (*pos)->GetProcessSP().get()) {
51130fdc8d8SChris Lattner         target_sp = *pos;
51230fdc8d8SChris Lattner         break;
51330fdc8d8SChris Lattner       }
51430fdc8d8SChris Lattner     }
51530fdc8d8SChris Lattner   }
51630fdc8d8SChris Lattner   return target_sp;
51730fdc8d8SChris Lattner }
51830fdc8d8SChris Lattner 
519b9c1b51eSKate Stone TargetSP TargetList::GetTargetSP(Target *target) const {
52030fdc8d8SChris Lattner   TargetSP target_sp;
521b9c1b51eSKate Stone   if (target) {
52216ff8604SSaleem Abdulrasool     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
52330fdc8d8SChris Lattner     collection::const_iterator pos, end = m_target_list.end();
524b9c1b51eSKate Stone     for (pos = m_target_list.begin(); pos != end; ++pos) {
525b9c1b51eSKate Stone       if (target == (*pos).get()) {
52630fdc8d8SChris Lattner         target_sp = *pos;
52730fdc8d8SChris Lattner         break;
52830fdc8d8SChris Lattner       }
52930fdc8d8SChris Lattner     }
53030fdc8d8SChris Lattner   }
53130fdc8d8SChris Lattner   return target_sp;
53230fdc8d8SChris Lattner }
53330fdc8d8SChris Lattner 
534b9c1b51eSKate Stone uint32_t TargetList::SendAsyncInterrupt(lldb::pid_t pid) {
53530fdc8d8SChris Lattner   uint32_t num_async_interrupts_sent = 0;
53630fdc8d8SChris Lattner 
537b9c1b51eSKate Stone   if (pid != LLDB_INVALID_PROCESS_ID) {
53830fdc8d8SChris Lattner     TargetSP target_sp(FindTargetWithProcessID(pid));
539b9c1b51eSKate Stone     if (target_sp) {
54030fdc8d8SChris Lattner       Process *process = target_sp->GetProcessSP().get();
541b9c1b51eSKate Stone       if (process) {
542cfc0935eSJim Ingham         process->SendAsyncInterrupt();
54330fdc8d8SChris Lattner         ++num_async_interrupts_sent;
54430fdc8d8SChris Lattner       }
54530fdc8d8SChris Lattner     }
546b9c1b51eSKate Stone   } else {
54730fdc8d8SChris Lattner     // We don't have a valid pid to broadcast to, so broadcast to the target
54830fdc8d8SChris Lattner     // list's async broadcaster...
549e65b2cf2SEugene Zelenko     BroadcastEvent(Process::eBroadcastBitInterrupt, nullptr);
55030fdc8d8SChris Lattner   }
55130fdc8d8SChris Lattner 
55230fdc8d8SChris Lattner   return num_async_interrupts_sent;
55330fdc8d8SChris Lattner }
55430fdc8d8SChris Lattner 
555b9c1b51eSKate Stone uint32_t TargetList::SignalIfRunning(lldb::pid_t pid, int signo) {
55630fdc8d8SChris Lattner   uint32_t num_signals_sent = 0;
557e65b2cf2SEugene Zelenko   Process *process = nullptr;
558b9c1b51eSKate Stone   if (pid == LLDB_INVALID_PROCESS_ID) {
55930fdc8d8SChris Lattner     // Signal all processes with signal
56016ff8604SSaleem Abdulrasool     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
56130fdc8d8SChris Lattner     collection::iterator pos, end = m_target_list.end();
562b9c1b51eSKate Stone     for (pos = m_target_list.begin(); pos != end; ++pos) {
56330fdc8d8SChris Lattner       process = (*pos)->GetProcessSP().get();
564b9c1b51eSKate Stone       if (process) {
565b9c1b51eSKate Stone         if (process->IsAlive()) {
56630fdc8d8SChris Lattner           ++num_signals_sent;
56730fdc8d8SChris Lattner           process->Signal(signo);
56830fdc8d8SChris Lattner         }
56930fdc8d8SChris Lattner       }
57030fdc8d8SChris Lattner     }
571b9c1b51eSKate Stone   } else {
57230fdc8d8SChris Lattner     // Signal a specific process with signal
57330fdc8d8SChris Lattner     TargetSP target_sp(FindTargetWithProcessID(pid));
574b9c1b51eSKate Stone     if (target_sp) {
57530fdc8d8SChris Lattner       process = target_sp->GetProcessSP().get();
576b9c1b51eSKate Stone       if (process) {
577b9c1b51eSKate Stone         if (process->IsAlive()) {
57830fdc8d8SChris Lattner           ++num_signals_sent;
57930fdc8d8SChris Lattner           process->Signal(signo);
58030fdc8d8SChris Lattner         }
58130fdc8d8SChris Lattner       }
58230fdc8d8SChris Lattner     }
58330fdc8d8SChris Lattner   }
58430fdc8d8SChris Lattner   return num_signals_sent;
58530fdc8d8SChris Lattner }
58630fdc8d8SChris Lattner 
587b9c1b51eSKate Stone int TargetList::GetNumTargets() const {
58816ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
58930fdc8d8SChris Lattner   return m_target_list.size();
59030fdc8d8SChris Lattner }
59130fdc8d8SChris Lattner 
592b9c1b51eSKate Stone lldb::TargetSP TargetList::GetTargetAtIndex(uint32_t idx) const {
59330fdc8d8SChris Lattner   TargetSP target_sp;
59416ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
59530fdc8d8SChris Lattner   if (idx < m_target_list.size())
59630fdc8d8SChris Lattner     target_sp = m_target_list[idx];
59730fdc8d8SChris Lattner   return target_sp;
59830fdc8d8SChris Lattner }
59930fdc8d8SChris Lattner 
600b9c1b51eSKate Stone uint32_t TargetList::GetIndexOfTarget(lldb::TargetSP target_sp) const {
60116ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
6028499e1a4SJim Ingham   size_t num_targets = m_target_list.size();
603b9c1b51eSKate Stone   for (size_t idx = 0; idx < num_targets; idx++) {
6048499e1a4SJim Ingham     if (target_sp == m_target_list[idx])
6058499e1a4SJim Ingham       return idx;
6068499e1a4SJim Ingham   }
6078499e1a4SJim Ingham   return UINT32_MAX;
6088499e1a4SJim Ingham }
6098499e1a4SJim Ingham 
610b9c1b51eSKate Stone uint32_t TargetList::SetSelectedTarget(Target *target) {
61116ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
612b9c1b51eSKate Stone   collection::const_iterator pos, begin = m_target_list.begin(),
61330fdc8d8SChris Lattner                                   end = m_target_list.end();
614b9c1b51eSKate Stone   for (pos = begin; pos != end; ++pos) {
615b9c1b51eSKate Stone     if (pos->get() == target) {
6162976d00aSJim Ingham       m_selected_target_idx = std::distance(begin, pos);
6172976d00aSJim Ingham       return m_selected_target_idx;
61830fdc8d8SChris Lattner     }
61930fdc8d8SChris Lattner   }
6202976d00aSJim Ingham   m_selected_target_idx = 0;
6212976d00aSJim Ingham   return m_selected_target_idx;
62230fdc8d8SChris Lattner }
62330fdc8d8SChris Lattner 
624b9c1b51eSKate Stone lldb::TargetSP TargetList::GetSelectedTarget() {
62516ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
6262976d00aSJim Ingham   if (m_selected_target_idx >= m_target_list.size())
6272976d00aSJim Ingham     m_selected_target_idx = 0;
6282976d00aSJim Ingham   return GetTargetAtIndex(m_selected_target_idx);
62930fdc8d8SChris Lattner }
630