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