1 //===-- TargetList.cpp ------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // Project includes
11 #include "lldb/Core/Broadcaster.h"
12 #include "lldb/Core/Debugger.h"
13 #include "lldb/Core/Event.h"
14 #include "lldb/Core/Module.h"
15 #include "lldb/Core/ModuleSpec.h"
16 #include "lldb/Core/State.h"
17 #include "lldb/Core/Timer.h"
18 #include "lldb/Host/Host.h"
19 #include "lldb/Host/HostInfo.h"
20 #include "lldb/Interpreter/CommandInterpreter.h"
21 #include "lldb/Interpreter/OptionGroupPlatform.h"
22 #include "lldb/Symbol/ObjectFile.h"
23 #include "lldb/Target/Platform.h"
24 #include "lldb/Target/Process.h"
25 #include "lldb/Target/TargetList.h"
26 
27 // Other libraries and framework includes
28 #include "llvm/ADT/SmallString.h"
29 #include "llvm/Support/FileSystem.h"
30 
31 using namespace lldb;
32 using namespace lldb_private;
33 
34 ConstString &TargetList::GetStaticBroadcasterClass() {
35   static ConstString class_name("lldb.targetList");
36   return class_name;
37 }
38 
39 //----------------------------------------------------------------------
40 // TargetList constructor
41 //----------------------------------------------------------------------
42 TargetList::TargetList(Debugger &debugger)
43     : Broadcaster(debugger.GetBroadcasterManager(),
44                   TargetList::GetStaticBroadcasterClass().AsCString()),
45       m_target_list(), m_target_list_mutex(), m_selected_target_idx(0) {
46   CheckInWithManager();
47 }
48 
49 //----------------------------------------------------------------------
50 // Destructor
51 //----------------------------------------------------------------------
52 TargetList::~TargetList() {
53   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
54   m_target_list.clear();
55 }
56 
57 Error TargetList::CreateTarget(Debugger &debugger,
58                                llvm::StringRef user_exe_path,
59                                llvm::StringRef triple_str,
60                                bool get_dependent_files,
61                                const OptionGroupPlatform *platform_options,
62                                TargetSP &target_sp) {
63   return CreateTargetInternal(debugger, user_exe_path, triple_str,
64                               get_dependent_files, platform_options, target_sp,
65                               false);
66 }
67 
68 Error TargetList::CreateTarget(Debugger &debugger,
69                                llvm::StringRef user_exe_path,
70                                const ArchSpec &specified_arch,
71                                bool get_dependent_files,
72                                PlatformSP &platform_sp, TargetSP &target_sp) {
73   return CreateTargetInternal(debugger, user_exe_path, specified_arch,
74                               get_dependent_files, platform_sp, target_sp,
75                               false);
76 }
77 
78 Error TargetList::CreateTargetInternal(
79     Debugger &debugger, llvm::StringRef user_exe_path,
80     llvm::StringRef triple_str, bool get_dependent_files,
81     const OptionGroupPlatform *platform_options, TargetSP &target_sp,
82     bool is_dummy_target) {
83   Error error;
84   PlatformSP platform_sp;
85 
86   // This is purposely left empty unless it is specified by triple_cstr.
87   // If not initialized via triple_cstr, then the currently selected platform
88   // will set the architecture correctly.
89   const ArchSpec arch(triple_str);
90   if (!triple_str.empty()) {
91     if (!arch.IsValid()) {
92       error.SetErrorStringWithFormat("invalid triple '%s'",
93                                      triple_str.str().c_str());
94       return error;
95     }
96   }
97 
98   ArchSpec platform_arch(arch);
99 
100   bool prefer_platform_arch = false;
101 
102   CommandInterpreter &interpreter = debugger.GetCommandInterpreter();
103 
104   // let's see if there is already an existing plaform before we go creating
105   // another...
106   platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
107 
108   if (platform_options && platform_options->PlatformWasSpecified()) {
109     // Create a new platform if it doesn't match the selected platform
110     if (!platform_options->PlatformMatches(platform_sp)) {
111       const bool select_platform = true;
112       platform_sp = platform_options->CreatePlatformWithOptions(
113           interpreter, arch, select_platform, error, platform_arch);
114       if (!platform_sp)
115         return error;
116     }
117   }
118 
119   if (!user_exe_path.empty()) {
120     ModuleSpecList module_specs;
121     ModuleSpec module_spec;
122     module_spec.GetFileSpec().SetFile(user_exe_path, true);
123 
124     // Resolve the executable in case we are given a path to a application
125     // bundle
126     // like a .app bundle on MacOSX
127     Host::ResolveExecutableInBundle(module_spec.GetFileSpec());
128 
129     lldb::offset_t file_offset = 0;
130     lldb::offset_t file_size = 0;
131     const size_t num_specs = ObjectFile::GetModuleSpecifications(
132         module_spec.GetFileSpec(), file_offset, file_size, module_specs);
133     if (num_specs > 0) {
134       ModuleSpec matching_module_spec;
135 
136       if (num_specs == 1) {
137         if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec)) {
138           if (platform_arch.IsValid()) {
139             if (platform_arch.IsCompatibleMatch(
140                     matching_module_spec.GetArchitecture())) {
141               // If the OS or vendor weren't specified, then adopt the module's
142               // architecture so that the platform matching can be more accurate
143               if (!platform_arch.TripleOSWasSpecified() ||
144                   !platform_arch.TripleVendorWasSpecified()) {
145                 prefer_platform_arch = true;
146                 platform_arch = matching_module_spec.GetArchitecture();
147               }
148             } else {
149               StreamString platform_arch_strm;
150               StreamString module_arch_strm;
151 
152               platform_arch.DumpTriple(platform_arch_strm);
153               matching_module_spec.GetArchitecture().DumpTriple(
154                   module_arch_strm);
155               error.SetErrorStringWithFormat(
156                   "the specified architecture '%s' is not compatible with '%s' "
157                   "in '%s'",
158                   platform_arch_strm.GetData(), module_arch_strm.GetData(),
159                   module_spec.GetFileSpec().GetPath().c_str());
160               return error;
161             }
162           } else {
163             // Only one arch and none was specified
164             prefer_platform_arch = true;
165             platform_arch = matching_module_spec.GetArchitecture();
166           }
167         }
168       } else {
169         if (arch.IsValid()) {
170           module_spec.GetArchitecture() = arch;
171           if (module_specs.FindMatchingModuleSpec(module_spec,
172                                                   matching_module_spec)) {
173             prefer_platform_arch = true;
174             platform_arch = matching_module_spec.GetArchitecture();
175           }
176         } else {
177           // No architecture specified, check if there is only one platform for
178           // all of the architectures.
179 
180           typedef std::vector<PlatformSP> PlatformList;
181           PlatformList platforms;
182           PlatformSP host_platform_sp = Platform::GetHostPlatform();
183           for (size_t i = 0; i < num_specs; ++i) {
184             ModuleSpec module_spec;
185             if (module_specs.GetModuleSpecAtIndex(i, module_spec)) {
186               // See if there was a selected platform and check that first
187               // since the user may have specified it.
188               if (platform_sp) {
189                 if (platform_sp->IsCompatibleArchitecture(
190                         module_spec.GetArchitecture(), false, nullptr)) {
191                   platforms.push_back(platform_sp);
192                   continue;
193                 }
194               }
195 
196               // Next check the host platform it if wasn't already checked above
197               if (host_platform_sp &&
198                   (!platform_sp ||
199                    host_platform_sp->GetName() != platform_sp->GetName())) {
200                 if (host_platform_sp->IsCompatibleArchitecture(
201                         module_spec.GetArchitecture(), false, nullptr)) {
202                   platforms.push_back(host_platform_sp);
203                   continue;
204                 }
205               }
206 
207               // Just find a platform that matches the architecture in the
208               // executable file
209               PlatformSP fallback_platform_sp(
210                   Platform::GetPlatformForArchitecture(
211                       module_spec.GetArchitecture(), nullptr));
212               if (fallback_platform_sp) {
213                 platforms.push_back(fallback_platform_sp);
214               }
215             }
216           }
217 
218           Platform *platform_ptr = nullptr;
219           bool more_than_one_platforms = false;
220           for (const auto &the_platform_sp : platforms) {
221             if (platform_ptr) {
222               if (platform_ptr->GetName() != the_platform_sp->GetName()) {
223                 more_than_one_platforms = true;
224                 platform_ptr = nullptr;
225                 break;
226               }
227             } else {
228               platform_ptr = the_platform_sp.get();
229             }
230           }
231 
232           if (platform_ptr) {
233             // All platforms for all modules in the exectuable match, so we can
234             // select this platform
235             platform_sp = platforms.front();
236           } else if (more_than_one_platforms == false) {
237             // No platforms claim to support this file
238             error.SetErrorString("No matching platforms found for this file, "
239                                  "specify one with the --platform option");
240             return error;
241           } else {
242             // More than one platform claims to support this file, so the
243             // --platform option must be specified
244             StreamString error_strm;
245             std::set<Platform *> platform_set;
246             error_strm.Printf(
247                 "more than one platform supports this executable (");
248             for (const auto &the_platform_sp : platforms) {
249               if (platform_set.find(the_platform_sp.get()) ==
250                   platform_set.end()) {
251                 if (!platform_set.empty())
252                   error_strm.PutCString(", ");
253                 error_strm.PutCString(the_platform_sp->GetName().GetCString());
254                 platform_set.insert(the_platform_sp.get());
255               }
256             }
257             error_strm.Printf(
258                 "), use the --platform option to specify a platform");
259             error.SetErrorString(error_strm.GetString());
260             return error;
261           }
262         }
263       }
264     }
265   }
266 
267   // If we have a valid architecture, make sure the current platform is
268   // compatible with that architecture
269   if (!prefer_platform_arch && arch.IsValid()) {
270     if (!platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) {
271       platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch);
272       if (!is_dummy_target && platform_sp)
273         debugger.GetPlatformList().SetSelectedPlatform(platform_sp);
274     }
275   } else if (platform_arch.IsValid()) {
276     // if "arch" isn't valid, yet "platform_arch" is, it means we have an
277     // executable file with
278     // a single architecture which should be used
279     ArchSpec fixed_platform_arch;
280     if (!platform_sp->IsCompatibleArchitecture(platform_arch, false,
281                                                &fixed_platform_arch)) {
282       platform_sp = Platform::GetPlatformForArchitecture(platform_arch,
283                                                          &fixed_platform_arch);
284       if (!is_dummy_target && platform_sp)
285         debugger.GetPlatformList().SetSelectedPlatform(platform_sp);
286     }
287   }
288 
289   if (!platform_arch.IsValid())
290     platform_arch = arch;
291 
292   error = TargetList::CreateTargetInternal(
293       debugger, user_exe_path, platform_arch, get_dependent_files, platform_sp,
294       target_sp, is_dummy_target);
295   return error;
296 }
297 
298 lldb::TargetSP TargetList::GetDummyTarget(lldb_private::Debugger &debugger) {
299   // FIXME: Maybe the dummy target should be per-Debugger
300   if (!m_dummy_target_sp || !m_dummy_target_sp->IsValid()) {
301     ArchSpec arch(Target::GetDefaultArchitecture());
302     if (!arch.IsValid())
303       arch = HostInfo::GetArchitecture();
304     Error err = CreateDummyTarget(
305         debugger, arch.GetTriple().getTriple().c_str(), m_dummy_target_sp);
306   }
307 
308   return m_dummy_target_sp;
309 }
310 
311 Error TargetList::CreateDummyTarget(Debugger &debugger,
312                                     llvm::StringRef specified_arch_name,
313                                     lldb::TargetSP &target_sp) {
314   PlatformSP host_platform_sp(Platform::GetHostPlatform());
315   return CreateTargetInternal(
316       debugger, (const char *)nullptr, specified_arch_name, false,
317       (const OptionGroupPlatform *)nullptr, target_sp, true);
318 }
319 
320 Error TargetList::CreateTargetInternal(Debugger &debugger,
321                                        llvm::StringRef user_exe_path,
322                                        const ArchSpec &specified_arch,
323                                        bool get_dependent_files,
324                                        lldb::PlatformSP &platform_sp,
325                                        lldb::TargetSP &target_sp,
326                                        bool is_dummy_target) {
327   Timer scoped_timer(LLVM_PRETTY_FUNCTION,
328                      "TargetList::CreateTarget (file = '%s', arch = '%s')",
329                      user_exe_path.str().c_str(),
330                      specified_arch.GetArchitectureName());
331   Error error;
332 
333   ArchSpec arch(specified_arch);
334 
335   if (arch.IsValid()) {
336     if (!platform_sp ||
337         !platform_sp->IsCompatibleArchitecture(arch, false, nullptr))
338       platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
339   }
340 
341   if (!platform_sp)
342     platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
343 
344   if (!arch.IsValid())
345     arch = specified_arch;
346 
347   FileSpec file(user_exe_path, false);
348   if (!file.Exists() && user_exe_path.startswith("~")) {
349     // we want to expand the tilde but we don't want to resolve any symbolic
350     // links
351     // so we can't use the FileSpec constructor's resolve flag
352     llvm::SmallString<64> unglobbed_path(user_exe_path);
353     FileSpec::ResolveUsername(unglobbed_path);
354 
355     if (unglobbed_path.empty())
356       file = FileSpec(user_exe_path, false);
357     else
358       file = FileSpec(unglobbed_path.c_str(), false);
359   }
360 
361   bool user_exe_path_is_bundle = false;
362   char resolved_bundle_exe_path[PATH_MAX];
363   resolved_bundle_exe_path[0] = '\0';
364   if (file) {
365     if (file.GetFileType() == FileSpec::eFileTypeDirectory)
366       user_exe_path_is_bundle = true;
367 
368     if (file.IsRelative() && !user_exe_path.empty()) {
369       // Ignore paths that start with "./" and "../"
370       if (!user_exe_path.startswith("./") && !user_exe_path.startswith("../")) {
371         llvm::SmallString<64> cwd;
372         if (! llvm::sys::fs::current_path(cwd)) {
373           cwd += '/';
374           cwd += user_exe_path;
375           FileSpec cwd_file(cwd, false);
376           if (cwd_file.Exists())
377             file = cwd_file;
378         }
379       }
380     }
381 
382     ModuleSP exe_module_sp;
383     if (platform_sp) {
384       FileSpecList executable_search_paths(
385           Target::GetDefaultExecutableSearchPaths());
386       ModuleSpec module_spec(file, arch);
387       error = platform_sp->ResolveExecutable(module_spec, exe_module_sp,
388                                              executable_search_paths.GetSize()
389                                                  ? &executable_search_paths
390                                                  : nullptr);
391     }
392 
393     if (error.Success() && exe_module_sp) {
394       if (exe_module_sp->GetObjectFile() == nullptr) {
395         if (arch.IsValid()) {
396           error.SetErrorStringWithFormat(
397               "\"%s\" doesn't contain architecture %s", file.GetPath().c_str(),
398               arch.GetArchitectureName());
399         } else {
400           error.SetErrorStringWithFormat("unsupported file type \"%s\"",
401                                          file.GetPath().c_str());
402         }
403         return error;
404       }
405       target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
406       target_sp->SetExecutableModule(exe_module_sp, get_dependent_files);
407       if (user_exe_path_is_bundle)
408         exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path,
409                                              sizeof(resolved_bundle_exe_path));
410     }
411   } else {
412     // No file was specified, just create an empty target with any arch
413     // if a valid arch was specified
414     target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
415   }
416 
417   if (target_sp) {
418     // Set argv0 with what the user typed, unless the user specified a
419     // directory. If the user specified a directory, then it is probably a
420     // bundle that was resolved and we need to use the resolved bundle path
421     if (!user_exe_path.empty()) {
422       // Use exactly what the user typed as the first argument when we exec or
423       // posix_spawn
424       if (user_exe_path_is_bundle && resolved_bundle_exe_path[0]) {
425         target_sp->SetArg0(resolved_bundle_exe_path);
426       } else {
427         // Use resolved path
428         target_sp->SetArg0(file.GetPath().c_str());
429       }
430     }
431     if (file.GetDirectory()) {
432       FileSpec file_dir;
433       file_dir.GetDirectory() = file.GetDirectory();
434       target_sp->GetExecutableSearchPaths().Append(file_dir);
435     }
436 
437     // Don't put the dummy target in the target list, it's held separately.
438     if (!is_dummy_target) {
439       std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
440       m_selected_target_idx = m_target_list.size();
441       m_target_list.push_back(target_sp);
442       // Now prime this from the dummy target:
443       target_sp->PrimeFromDummyTarget(debugger.GetDummyTarget());
444     } else {
445       m_dummy_target_sp = target_sp;
446     }
447   }
448 
449   return error;
450 }
451 
452 bool TargetList::DeleteTarget(TargetSP &target_sp) {
453   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
454   collection::iterator pos, end = m_target_list.end();
455 
456   for (pos = m_target_list.begin(); pos != end; ++pos) {
457     if (pos->get() == target_sp.get()) {
458       m_target_list.erase(pos);
459       return true;
460     }
461   }
462   return false;
463 }
464 
465 TargetSP TargetList::FindTargetWithExecutableAndArchitecture(
466     const FileSpec &exe_file_spec, const ArchSpec *exe_arch_ptr) const {
467   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
468   TargetSP target_sp;
469   bool full_match = (bool)exe_file_spec.GetDirectory();
470 
471   collection::const_iterator pos, end = m_target_list.end();
472   for (pos = m_target_list.begin(); pos != end; ++pos) {
473     Module *exe_module = (*pos)->GetExecutableModulePointer();
474 
475     if (exe_module) {
476       if (FileSpec::Equal(exe_file_spec, exe_module->GetFileSpec(),
477                           full_match)) {
478         if (exe_arch_ptr) {
479           if (!exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture()))
480             continue;
481         }
482         target_sp = *pos;
483         break;
484       }
485     }
486   }
487   return target_sp;
488 }
489 
490 TargetSP TargetList::FindTargetWithProcessID(lldb::pid_t pid) const {
491   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
492   TargetSP target_sp;
493   collection::const_iterator pos, end = m_target_list.end();
494   for (pos = m_target_list.begin(); pos != end; ++pos) {
495     Process *process = (*pos)->GetProcessSP().get();
496     if (process && process->GetID() == pid) {
497       target_sp = *pos;
498       break;
499     }
500   }
501   return target_sp;
502 }
503 
504 TargetSP TargetList::FindTargetWithProcess(Process *process) const {
505   TargetSP target_sp;
506   if (process) {
507     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
508     collection::const_iterator pos, end = m_target_list.end();
509     for (pos = m_target_list.begin(); pos != end; ++pos) {
510       if (process == (*pos)->GetProcessSP().get()) {
511         target_sp = *pos;
512         break;
513       }
514     }
515   }
516   return target_sp;
517 }
518 
519 TargetSP TargetList::GetTargetSP(Target *target) const {
520   TargetSP target_sp;
521   if (target) {
522     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
523     collection::const_iterator pos, end = m_target_list.end();
524     for (pos = m_target_list.begin(); pos != end; ++pos) {
525       if (target == (*pos).get()) {
526         target_sp = *pos;
527         break;
528       }
529     }
530   }
531   return target_sp;
532 }
533 
534 uint32_t TargetList::SendAsyncInterrupt(lldb::pid_t pid) {
535   uint32_t num_async_interrupts_sent = 0;
536 
537   if (pid != LLDB_INVALID_PROCESS_ID) {
538     TargetSP target_sp(FindTargetWithProcessID(pid));
539     if (target_sp) {
540       Process *process = target_sp->GetProcessSP().get();
541       if (process) {
542         process->SendAsyncInterrupt();
543         ++num_async_interrupts_sent;
544       }
545     }
546   } else {
547     // We don't have a valid pid to broadcast to, so broadcast to the target
548     // list's async broadcaster...
549     BroadcastEvent(Process::eBroadcastBitInterrupt, nullptr);
550   }
551 
552   return num_async_interrupts_sent;
553 }
554 
555 uint32_t TargetList::SignalIfRunning(lldb::pid_t pid, int signo) {
556   uint32_t num_signals_sent = 0;
557   Process *process = nullptr;
558   if (pid == LLDB_INVALID_PROCESS_ID) {
559     // Signal all processes with signal
560     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
561     collection::iterator pos, end = m_target_list.end();
562     for (pos = m_target_list.begin(); pos != end; ++pos) {
563       process = (*pos)->GetProcessSP().get();
564       if (process) {
565         if (process->IsAlive()) {
566           ++num_signals_sent;
567           process->Signal(signo);
568         }
569       }
570     }
571   } else {
572     // Signal a specific process with signal
573     TargetSP target_sp(FindTargetWithProcessID(pid));
574     if (target_sp) {
575       process = target_sp->GetProcessSP().get();
576       if (process) {
577         if (process->IsAlive()) {
578           ++num_signals_sent;
579           process->Signal(signo);
580         }
581       }
582     }
583   }
584   return num_signals_sent;
585 }
586 
587 int TargetList::GetNumTargets() const {
588   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
589   return m_target_list.size();
590 }
591 
592 lldb::TargetSP TargetList::GetTargetAtIndex(uint32_t idx) const {
593   TargetSP target_sp;
594   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
595   if (idx < m_target_list.size())
596     target_sp = m_target_list[idx];
597   return target_sp;
598 }
599 
600 uint32_t TargetList::GetIndexOfTarget(lldb::TargetSP target_sp) const {
601   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
602   size_t num_targets = m_target_list.size();
603   for (size_t idx = 0; idx < num_targets; idx++) {
604     if (target_sp == m_target_list[idx])
605       return idx;
606   }
607   return UINT32_MAX;
608 }
609 
610 uint32_t TargetList::SetSelectedTarget(Target *target) {
611   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
612   collection::const_iterator pos, begin = m_target_list.begin(),
613                                   end = m_target_list.end();
614   for (pos = begin; pos != end; ++pos) {
615     if (pos->get() == target) {
616       m_selected_target_idx = std::distance(begin, pos);
617       return m_selected_target_idx;
618     }
619   }
620   m_selected_target_idx = 0;
621   return m_selected_target_idx;
622 }
623 
624 lldb::TargetSP TargetList::GetSelectedTarget() {
625   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
626   if (m_selected_target_idx >= m_target_list.size())
627     m_selected_target_idx = 0;
628   return GetTargetAtIndex(m_selected_target_idx);
629 }
630