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 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 #include "llvm/ADT/SmallString.h"
14 
15 // Project includes
16 #include "lldb/Core/Broadcaster.h"
17 #include "lldb/Core/Debugger.h"
18 #include "lldb/Core/Event.h"
19 #include "lldb/Core/Module.h"
20 #include "lldb/Core/ModuleSpec.h"
21 #include "lldb/Core/State.h"
22 #include "lldb/Core/Timer.h"
23 #include "lldb/Host/Host.h"
24 #include "lldb/Host/HostInfo.h"
25 #include "lldb/Interpreter/CommandInterpreter.h"
26 #include "lldb/Interpreter/OptionGroupPlatform.h"
27 #include "lldb/Symbol/ObjectFile.h"
28 #include "lldb/Target/Platform.h"
29 #include "lldb/Target/Process.h"
30 #include "lldb/Target/TargetList.h"
31 
32 using namespace lldb;
33 using namespace lldb_private;
34 
35 ConstString &TargetList::GetStaticBroadcasterClass() {
36   static ConstString class_name("lldb.targetList");
37   return class_name;
38 }
39 
40 //----------------------------------------------------------------------
41 // TargetList constructor
42 //----------------------------------------------------------------------
43 TargetList::TargetList(Debugger &debugger)
44     : Broadcaster(debugger.GetBroadcasterManager(),
45                   TargetList::GetStaticBroadcasterClass().AsCString()),
46       m_target_list(), m_target_list_mutex(), m_selected_target_idx(0) {
47   CheckInWithManager();
48 }
49 
50 //----------------------------------------------------------------------
51 // Destructor
52 //----------------------------------------------------------------------
53 TargetList::~TargetList() {
54   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
55   m_target_list.clear();
56 }
57 
58 Error TargetList::CreateTarget(Debugger &debugger, const char *user_exe_path,
59                                const char *triple_cstr,
60                                bool get_dependent_files,
61                                const OptionGroupPlatform *platform_options,
62                                TargetSP &target_sp) {
63   return CreateTargetInternal(debugger, user_exe_path, triple_cstr,
64                               get_dependent_files, platform_options, target_sp,
65                               false);
66 }
67 
68 Error TargetList::CreateTarget(Debugger &debugger, const char *user_exe_path,
69                                const ArchSpec &specified_arch,
70                                bool get_dependent_files,
71                                PlatformSP &platform_sp, TargetSP &target_sp) {
72   return CreateTargetInternal(debugger, user_exe_path, specified_arch,
73                               get_dependent_files, platform_sp, target_sp,
74                               false);
75 }
76 
77 Error TargetList::CreateTargetInternal(
78     Debugger &debugger, const char *user_exe_path, const char *triple_cstr,
79     bool get_dependent_files, const OptionGroupPlatform *platform_options,
80     TargetSP &target_sp, bool is_dummy_target) {
81   Error error;
82   PlatformSP platform_sp;
83 
84   // This is purposely left empty unless it is specified by triple_cstr.
85   // If not initialized via triple_cstr, then the currently selected platform
86   // will set the architecture correctly.
87   const ArchSpec arch(triple_cstr);
88   if (triple_cstr && triple_cstr[0]) {
89     if (!arch.IsValid()) {
90       error.SetErrorStringWithFormat("invalid triple '%s'", triple_cstr);
91       return error;
92     }
93   }
94 
95   ArchSpec platform_arch(arch);
96 
97   bool prefer_platform_arch = false;
98 
99   CommandInterpreter &interpreter = debugger.GetCommandInterpreter();
100 
101   // let's see if there is already an existing plaform before we go creating
102   // another...
103   platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
104 
105   if (platform_options && platform_options->PlatformWasSpecified()) {
106     // Create a new platform if it doesn't match the selected platform
107     if (!platform_options->PlatformMatches(platform_sp)) {
108       const bool select_platform = true;
109       platform_sp = platform_options->CreatePlatformWithOptions(
110           interpreter, arch, select_platform, error, platform_arch);
111       if (!platform_sp)
112         return error;
113     }
114   }
115 
116   if (user_exe_path && user_exe_path[0]) {
117     ModuleSpecList module_specs;
118     ModuleSpec module_spec;
119     module_spec.GetFileSpec().SetFile(user_exe_path, true);
120 
121     // Resolve the executable in case we are given a path to a application
122     // bundle
123     // like a .app bundle on MacOSX
124     Host::ResolveExecutableInBundle(module_spec.GetFileSpec());
125 
126     lldb::offset_t file_offset = 0;
127     lldb::offset_t file_size = 0;
128     const size_t num_specs = ObjectFile::GetModuleSpecifications(
129         module_spec.GetFileSpec(), file_offset, file_size, module_specs);
130     if (num_specs > 0) {
131       ModuleSpec matching_module_spec;
132 
133       if (num_specs == 1) {
134         if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec)) {
135           if (platform_arch.IsValid()) {
136             if (platform_arch.IsCompatibleMatch(
137                     matching_module_spec.GetArchitecture())) {
138               // If the OS or vendor weren't specified, then adopt the module's
139               // architecture so that the platform matching can be more accurate
140               if (!platform_arch.TripleOSWasSpecified() ||
141                   !platform_arch.TripleVendorWasSpecified()) {
142                 prefer_platform_arch = true;
143                 platform_arch = matching_module_spec.GetArchitecture();
144               }
145             } else {
146               StreamString platform_arch_strm;
147               StreamString module_arch_strm;
148 
149               platform_arch.DumpTriple(platform_arch_strm);
150               matching_module_spec.GetArchitecture().DumpTriple(
151                   module_arch_strm);
152               error.SetErrorStringWithFormat(
153                   "the specified architecture '%s' is not compatible with '%s' "
154                   "in '%s'",
155                   platform_arch_strm.GetString().c_str(),
156                   module_arch_strm.GetString().c_str(),
157                   module_spec.GetFileSpec().GetPath().c_str());
158               return error;
159             }
160           } else {
161             // Only one arch and none was specified
162             prefer_platform_arch = true;
163             platform_arch = matching_module_spec.GetArchitecture();
164           }
165         }
166       } else {
167         if (arch.IsValid()) {
168           module_spec.GetArchitecture() = arch;
169           if (module_specs.FindMatchingModuleSpec(module_spec,
170                                                   matching_module_spec)) {
171             prefer_platform_arch = true;
172             platform_arch = matching_module_spec.GetArchitecture();
173           }
174         } else {
175           // No architecture specified, check if there is only one platform for
176           // all of the architectures.
177 
178           typedef std::vector<PlatformSP> PlatformList;
179           PlatformList platforms;
180           PlatformSP host_platform_sp = Platform::GetHostPlatform();
181           for (size_t i = 0; i < num_specs; ++i) {
182             ModuleSpec module_spec;
183             if (module_specs.GetModuleSpecAtIndex(i, module_spec)) {
184               // See if there was a selected platform and check that first
185               // since the user may have specified it.
186               if (platform_sp) {
187                 if (platform_sp->IsCompatibleArchitecture(
188                         module_spec.GetArchitecture(), false, nullptr)) {
189                   platforms.push_back(platform_sp);
190                   continue;
191                 }
192               }
193 
194               // Next check the host platform it if wasn't already checked above
195               if (host_platform_sp &&
196                   (!platform_sp ||
197                    host_platform_sp->GetName() != platform_sp->GetName())) {
198                 if (host_platform_sp->IsCompatibleArchitecture(
199                         module_spec.GetArchitecture(), false, nullptr)) {
200                   platforms.push_back(host_platform_sp);
201                   continue;
202                 }
203               }
204 
205               // Just find a platform that matches the architecture in the
206               // executable file
207               PlatformSP fallback_platform_sp(
208                   Platform::GetPlatformForArchitecture(
209                       module_spec.GetArchitecture(), nullptr));
210               if (fallback_platform_sp) {
211                 platforms.push_back(fallback_platform_sp);
212               }
213             }
214           }
215 
216           Platform *platform_ptr = nullptr;
217           bool more_than_one_platforms = false;
218           for (const auto &the_platform_sp : platforms) {
219             if (platform_ptr) {
220               if (platform_ptr->GetName() != the_platform_sp->GetName()) {
221                 more_than_one_platforms = true;
222                 platform_ptr = nullptr;
223                 break;
224               }
225             } else {
226               platform_ptr = the_platform_sp.get();
227             }
228           }
229 
230           if (platform_ptr) {
231             // All platforms for all modules in the exectuable match, so we can
232             // select this platform
233             platform_sp = platforms.front();
234           } else if (more_than_one_platforms == false) {
235             // No platforms claim to support this file
236             error.SetErrorString("No matching platforms found for this file, "
237                                  "specify one with the --platform option");
238             return error;
239           } else {
240             // More than one platform claims to support this file, so the
241             // --platform option must be specified
242             StreamString error_strm;
243             std::set<Platform *> platform_set;
244             error_strm.Printf(
245                 "more than one platform supports this executable (");
246             for (const auto &the_platform_sp : platforms) {
247               if (platform_set.find(the_platform_sp.get()) ==
248                   platform_set.end()) {
249                 if (!platform_set.empty())
250                   error_strm.PutCString(", ");
251                 error_strm.PutCString(the_platform_sp->GetName().GetCString());
252                 platform_set.insert(the_platform_sp.get());
253               }
254             }
255             error_strm.Printf(
256                 "), use the --platform option to specify a platform");
257             error.SetErrorString(error_strm.GetString().c_str());
258             return error;
259           }
260         }
261       }
262     }
263   }
264 
265   // If we have a valid architecture, make sure the current platform is
266   // compatible with that architecture
267   if (!prefer_platform_arch && arch.IsValid()) {
268     if (!platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) {
269       platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch);
270       if (!is_dummy_target && platform_sp)
271         debugger.GetPlatformList().SetSelectedPlatform(platform_sp);
272     }
273   } else if (platform_arch.IsValid()) {
274     // if "arch" isn't valid, yet "platform_arch" is, it means we have an
275     // executable file with
276     // a single architecture which should be used
277     ArchSpec fixed_platform_arch;
278     if (!platform_sp->IsCompatibleArchitecture(platform_arch, false,
279                                                &fixed_platform_arch)) {
280       platform_sp = Platform::GetPlatformForArchitecture(platform_arch,
281                                                          &fixed_platform_arch);
282       if (!is_dummy_target && platform_sp)
283         debugger.GetPlatformList().SetSelectedPlatform(platform_sp);
284     }
285   }
286 
287   if (!platform_arch.IsValid())
288     platform_arch = arch;
289 
290   error = TargetList::CreateTargetInternal(
291       debugger, user_exe_path, platform_arch, get_dependent_files, platform_sp,
292       target_sp, is_dummy_target);
293   return error;
294 }
295 
296 lldb::TargetSP TargetList::GetDummyTarget(lldb_private::Debugger &debugger) {
297   // FIXME: Maybe the dummy target should be per-Debugger
298   if (!m_dummy_target_sp || !m_dummy_target_sp->IsValid()) {
299     ArchSpec arch(Target::GetDefaultArchitecture());
300     if (!arch.IsValid())
301       arch = HostInfo::GetArchitecture();
302     Error err = CreateDummyTarget(
303         debugger, arch.GetTriple().getTriple().c_str(), m_dummy_target_sp);
304   }
305 
306   return m_dummy_target_sp;
307 }
308 
309 Error TargetList::CreateDummyTarget(Debugger &debugger,
310                                     const char *specified_arch_name,
311                                     lldb::TargetSP &target_sp) {
312   PlatformSP host_platform_sp(Platform::GetHostPlatform());
313   return CreateTargetInternal(
314       debugger, (const char *)nullptr, specified_arch_name, false,
315       (const OptionGroupPlatform *)nullptr, target_sp, true);
316 }
317 
318 Error TargetList::CreateTargetInternal(Debugger &debugger,
319                                        const char *user_exe_path,
320                                        const ArchSpec &specified_arch,
321                                        bool get_dependent_files,
322                                        lldb::PlatformSP &platform_sp,
323                                        lldb::TargetSP &target_sp,
324                                        bool is_dummy_target) {
325   Timer scoped_timer(LLVM_PRETTY_FUNCTION,
326                      "TargetList::CreateTarget (file = '%s', arch = '%s')",
327                      user_exe_path, specified_arch.GetArchitectureName());
328   Error error;
329 
330   ArchSpec arch(specified_arch);
331 
332   if (arch.IsValid()) {
333     if (!platform_sp ||
334         !platform_sp->IsCompatibleArchitecture(arch, false, nullptr))
335       platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
336   }
337 
338   if (!platform_sp)
339     platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
340 
341   if (!arch.IsValid())
342     arch = specified_arch;
343 
344   FileSpec file(user_exe_path, false);
345   if (!file.Exists() && user_exe_path && user_exe_path[0] == '~') {
346     // we want to expand the tilde but we don't want to resolve any symbolic
347     // links
348     // so we can't use the FileSpec constructor's resolve flag
349     llvm::SmallString<64> unglobbed_path(user_exe_path);
350     FileSpec::ResolveUsername(unglobbed_path);
351 
352     if (unglobbed_path.empty())
353       file = FileSpec(user_exe_path, false);
354     else
355       file = FileSpec(unglobbed_path.c_str(), false);
356   }
357 
358   bool user_exe_path_is_bundle = false;
359   char resolved_bundle_exe_path[PATH_MAX];
360   resolved_bundle_exe_path[0] = '\0';
361   if (file) {
362     if (file.GetFileType() == FileSpec::eFileTypeDirectory)
363       user_exe_path_is_bundle = true;
364 
365     if (file.IsRelative() && user_exe_path) {
366       // Ignore paths that start with "./" and "../"
367       if (!((user_exe_path[0] == '.' && user_exe_path[1] == '/') ||
368             (user_exe_path[0] == '.' && user_exe_path[1] == '.' &&
369              user_exe_path[2] == '/'))) {
370         char cwd[PATH_MAX];
371         if (getcwd(cwd, sizeof(cwd))) {
372           std::string cwd_user_exe_path(cwd);
373           cwd_user_exe_path += '/';
374           cwd_user_exe_path += user_exe_path;
375           FileSpec cwd_file(cwd_user_exe_path.c_str(), 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) {
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