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/State.h"
21 #include "lldb/Core/Timer.h"
22 #include "lldb/Host/Host.h"
23 #include "lldb/Interpreter/CommandInterpreter.h"
24 #include "lldb/Interpreter/OptionGroupPlatform.h"
25 #include "lldb/Target/Platform.h"
26 #include "lldb/Target/Process.h"
27 #include "lldb/Target/TargetList.h"
28 
29 using namespace lldb;
30 using namespace lldb_private;
31 
32 ConstString &
33 TargetList::GetStaticBroadcasterClass ()
34 {
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, TargetList::GetStaticBroadcasterClass().AsCString()),
44     m_target_list(),
45     m_target_list_mutex (Mutex::eMutexTypeRecursive),
46     m_selected_target_idx (0)
47 {
48     CheckInWithManager();
49 }
50 
51 //----------------------------------------------------------------------
52 // Destructor
53 //----------------------------------------------------------------------
54 TargetList::~TargetList()
55 {
56     Mutex::Locker locker(m_target_list_mutex);
57     m_target_list.clear();
58 }
59 
60 Error
61 TargetList::CreateTarget (Debugger &debugger,
62                           const char *user_exe_path,
63                           const char *triple_cstr,
64                           bool get_dependent_files,
65                           const OptionGroupPlatform *platform_options,
66                           TargetSP &target_sp)
67 {
68     Error error;
69     PlatformSP platform_sp;
70 
71     // This is purposely left empty unless it is specified by triple_cstr.
72     // If not initialized via triple_cstr, then the currently selected platform
73     // will set the architecture correctly.
74     const ArchSpec arch(triple_cstr);
75     if (triple_cstr && triple_cstr[0])
76     {
77         if (!arch.IsValid())
78         {
79             error.SetErrorStringWithFormat("invalid triple '%s'", triple_cstr);
80             return error;
81         }
82     }
83 
84     ArchSpec platform_arch(arch);
85     CommandInterpreter &interpreter = debugger.GetCommandInterpreter();
86     if (platform_options)
87     {
88         if (platform_options->PlatformWasSpecified ())
89         {
90             const bool select_platform = true;
91             platform_sp = platform_options->CreatePlatformWithOptions (interpreter,
92                                                                        arch,
93                                                                        select_platform,
94                                                                        error,
95                                                                        platform_arch);
96             if (!platform_sp)
97                 return error;
98         }
99     }
100 
101     if (!platform_sp)
102     {
103         // Get the current platform and make sure it is compatible with the
104         // current architecture if we have a valid architecture.
105         platform_sp = debugger.GetPlatformList().GetSelectedPlatform ();
106 
107         if (arch.IsValid() && !platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch))
108         {
109             platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch);
110         }
111     }
112 
113     if (!platform_arch.IsValid())
114         platform_arch = arch;
115 
116     error = TargetList::CreateTarget (debugger,
117                                       user_exe_path,
118                                       platform_arch,
119                                       get_dependent_files,
120                                       platform_sp,
121                                       target_sp);
122     return error;
123 }
124 
125 Error
126 TargetList::CreateTarget (Debugger &debugger,
127                           const char *user_exe_path,
128                           const ArchSpec& specified_arch,
129                           bool get_dependent_files,
130                           PlatformSP &platform_sp,
131                           TargetSP &target_sp)
132 {
133     Timer scoped_timer (__PRETTY_FUNCTION__,
134                         "TargetList::CreateTarget (file = '%s', arch = '%s')",
135                         user_exe_path,
136                         specified_arch.GetArchitectureName());
137     Error error;
138 
139     ArchSpec arch(specified_arch);
140 
141     if (platform_sp)
142     {
143         if (arch.IsValid())
144         {
145             if (!platform_sp->IsCompatibleArchitecture(arch, false, NULL))
146                 platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
147         }
148     }
149     else if (arch.IsValid())
150     {
151         platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
152     }
153 
154     if (!platform_sp)
155         platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
156 
157     if (!arch.IsValid())
158         arch = specified_arch;
159 
160     FileSpec file (user_exe_path, false);
161     bool user_exe_path_is_bundle = false;
162     char resolved_bundle_exe_path[PATH_MAX];
163     resolved_bundle_exe_path[0] = '\0';
164     if (file)
165     {
166         if (file.GetFileType() == FileSpec::eFileTypeDirectory)
167             user_exe_path_is_bundle = true;
168 
169         if (file.IsRelativeToCurrentWorkingDirectory())
170         {
171             // Ignore paths that start with "./" and "../"
172             if (!((user_exe_path[0] == '.' && user_exe_path[1] == '/') ||
173                   (user_exe_path[0] == '.' && user_exe_path[1] == '.' && user_exe_path[2] == '/')))
174             {
175                 char cwd[PATH_MAX];
176                 if (getcwd (cwd, sizeof(cwd)))
177                 {
178                     std::string cwd_user_exe_path (cwd);
179                     cwd_user_exe_path += '/';
180                     cwd_user_exe_path += user_exe_path;
181                     file.SetFile(cwd_user_exe_path.c_str(), false);
182                 }
183             }
184         }
185 
186         ModuleSP exe_module_sp;
187         if (platform_sp)
188         {
189             FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
190             error = platform_sp->ResolveExecutable (file,
191                                                     arch,
192                                                     exe_module_sp,
193                                                     executable_search_paths.GetSize() ? &executable_search_paths : NULL);
194         }
195 
196         if (error.Success() && exe_module_sp)
197         {
198             if (exe_module_sp->GetObjectFile() == NULL)
199             {
200                 if (arch.IsValid())
201                 {
202                     error.SetErrorStringWithFormat("\"%s%s%s\" doesn't contain architecture %s",
203                                                    file.GetDirectory().AsCString(),
204                                                    file.GetDirectory() ? "/" : "",
205                                                    file.GetFilename().AsCString(),
206                                                    arch.GetArchitectureName());
207                 }
208                 else
209                 {
210                     error.SetErrorStringWithFormat("unsupported file type \"%s%s%s\"",
211                                                    file.GetDirectory().AsCString(),
212                                                    file.GetDirectory() ? "/" : "",
213                                                    file.GetFilename().AsCString());
214                 }
215                 return error;
216             }
217             target_sp.reset(new Target(debugger, arch, platform_sp));
218             target_sp->SetExecutableModule (exe_module_sp, get_dependent_files);
219             if (user_exe_path_is_bundle)
220                 exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path, sizeof(resolved_bundle_exe_path));
221         }
222     }
223     else
224     {
225         // No file was specified, just create an empty target with any arch
226         // if a valid arch was specified
227         target_sp.reset(new Target(debugger, arch, platform_sp));
228     }
229 
230     if (target_sp)
231     {
232         // Set argv0 with what the user typed, unless the user specified a
233         // directory. If the user specified a directory, then it is probably a
234         // bundle that was resolved and we need to use the resolved bundle path
235         if (user_exe_path)
236         {
237             // Use exactly what the user typed as the first argument when we exec or posix_spawn
238             if (user_exe_path_is_bundle && resolved_bundle_exe_path[0])
239             {
240                 target_sp->SetArg0 (resolved_bundle_exe_path);
241             }
242             else
243             {
244                 // Just use what the user typed
245                 target_sp->SetArg0 (user_exe_path);
246             }
247         }
248         if (file.GetDirectory())
249         {
250             FileSpec file_dir;
251             file_dir.GetDirectory() = file.GetDirectory();
252             target_sp->GetExecutableSearchPaths ().Append (file_dir);
253         }
254         Mutex::Locker locker(m_target_list_mutex);
255         m_selected_target_idx = m_target_list.size();
256         m_target_list.push_back(target_sp);
257 
258 
259     }
260 
261     return error;
262 }
263 
264 bool
265 TargetList::DeleteTarget (TargetSP &target_sp)
266 {
267     Mutex::Locker locker(m_target_list_mutex);
268     collection::iterator pos, end = m_target_list.end();
269 
270     for (pos = m_target_list.begin(); pos != end; ++pos)
271     {
272         if (pos->get() == target_sp.get())
273         {
274             m_target_list.erase(pos);
275             return true;
276         }
277     }
278     return false;
279 }
280 
281 
282 TargetSP
283 TargetList::FindTargetWithExecutableAndArchitecture
284 (
285     const FileSpec &exe_file_spec,
286     const ArchSpec *exe_arch_ptr
287 ) const
288 {
289     Mutex::Locker locker (m_target_list_mutex);
290     TargetSP target_sp;
291     bool full_match = exe_file_spec.GetDirectory();
292 
293     collection::const_iterator pos, end = m_target_list.end();
294     for (pos = m_target_list.begin(); pos != end; ++pos)
295     {
296         Module *exe_module = (*pos)->GetExecutableModulePointer();
297 
298         if (exe_module)
299         {
300             if (FileSpec::Equal (exe_file_spec, exe_module->GetFileSpec(), full_match))
301             {
302                 if (exe_arch_ptr)
303                 {
304                     if (!exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture()))
305                         continue;
306                 }
307                 target_sp = *pos;
308                 break;
309             }
310         }
311     }
312     return target_sp;
313 }
314 
315 TargetSP
316 TargetList::FindTargetWithProcessID (lldb::pid_t pid) const
317 {
318     Mutex::Locker locker(m_target_list_mutex);
319     TargetSP target_sp;
320     collection::const_iterator pos, end = m_target_list.end();
321     for (pos = m_target_list.begin(); pos != end; ++pos)
322     {
323         Process* process = (*pos)->GetProcessSP().get();
324         if (process && process->GetID() == pid)
325         {
326             target_sp = *pos;
327             break;
328         }
329     }
330     return target_sp;
331 }
332 
333 
334 TargetSP
335 TargetList::FindTargetWithProcess (Process *process) const
336 {
337     TargetSP target_sp;
338     if (process)
339     {
340         Mutex::Locker locker(m_target_list_mutex);
341         collection::const_iterator pos, end = m_target_list.end();
342         for (pos = m_target_list.begin(); pos != end; ++pos)
343         {
344             if (process == (*pos)->GetProcessSP().get())
345             {
346                 target_sp = *pos;
347                 break;
348             }
349         }
350     }
351     return target_sp;
352 }
353 
354 TargetSP
355 TargetList::GetTargetSP (Target *target) const
356 {
357     TargetSP target_sp;
358     if (target)
359     {
360         Mutex::Locker locker(m_target_list_mutex);
361         collection::const_iterator pos, end = m_target_list.end();
362         for (pos = m_target_list.begin(); pos != end; ++pos)
363         {
364             if (target == (*pos).get())
365             {
366                 target_sp = *pos;
367                 break;
368             }
369         }
370     }
371     return target_sp;
372 }
373 
374 uint32_t
375 TargetList::SendAsyncInterrupt (lldb::pid_t pid)
376 {
377     uint32_t num_async_interrupts_sent = 0;
378 
379     if (pid != LLDB_INVALID_PROCESS_ID)
380     {
381         TargetSP target_sp(FindTargetWithProcessID (pid));
382         if (target_sp.get())
383         {
384             Process* process = target_sp->GetProcessSP().get();
385             if (process)
386             {
387                 process->SendAsyncInterrupt();
388                 ++num_async_interrupts_sent;
389             }
390         }
391     }
392     else
393     {
394         // We don't have a valid pid to broadcast to, so broadcast to the target
395         // list's async broadcaster...
396         BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
397     }
398 
399     return num_async_interrupts_sent;
400 }
401 
402 uint32_t
403 TargetList::SignalIfRunning (lldb::pid_t pid, int signo)
404 {
405     uint32_t num_signals_sent = 0;
406     Process *process = NULL;
407     if (pid == LLDB_INVALID_PROCESS_ID)
408     {
409         // Signal all processes with signal
410         Mutex::Locker locker(m_target_list_mutex);
411         collection::iterator pos, end = m_target_list.end();
412         for (pos = m_target_list.begin(); pos != end; ++pos)
413         {
414             process = (*pos)->GetProcessSP().get();
415             if (process)
416             {
417                 if (process->IsAlive())
418                 {
419                     ++num_signals_sent;
420                     process->Signal (signo);
421                 }
422             }
423         }
424     }
425     else
426     {
427         // Signal a specific process with signal
428         TargetSP target_sp(FindTargetWithProcessID (pid));
429         if (target_sp.get())
430         {
431             process = target_sp->GetProcessSP().get();
432             if (process)
433             {
434                 if (process->IsAlive())
435                 {
436                     ++num_signals_sent;
437                     process->Signal (signo);
438                 }
439             }
440         }
441     }
442     return num_signals_sent;
443 }
444 
445 int
446 TargetList::GetNumTargets () const
447 {
448     Mutex::Locker locker (m_target_list_mutex);
449     return m_target_list.size();
450 }
451 
452 lldb::TargetSP
453 TargetList::GetTargetAtIndex (uint32_t idx) const
454 {
455     TargetSP target_sp;
456     Mutex::Locker locker (m_target_list_mutex);
457     if (idx < m_target_list.size())
458         target_sp = m_target_list[idx];
459     return target_sp;
460 }
461 
462 uint32_t
463 TargetList::GetIndexOfTarget (lldb::TargetSP target_sp) const
464 {
465     Mutex::Locker locker (m_target_list_mutex);
466     size_t num_targets = m_target_list.size();
467     for (size_t idx = 0; idx < num_targets; idx++)
468     {
469         if (target_sp == m_target_list[idx])
470             return idx;
471     }
472     return UINT32_MAX;
473 }
474 
475 uint32_t
476 TargetList::SetSelectedTarget (Target* target)
477 {
478     Mutex::Locker locker (m_target_list_mutex);
479     collection::const_iterator pos,
480         begin = m_target_list.begin(),
481         end = m_target_list.end();
482     for (pos = begin; pos != end; ++pos)
483     {
484         if (pos->get() == target)
485         {
486             m_selected_target_idx = std::distance (begin, pos);
487             return m_selected_target_idx;
488         }
489     }
490     m_selected_target_idx = 0;
491     return m_selected_target_idx;
492 }
493 
494 lldb::TargetSP
495 TargetList::GetSelectedTarget ()
496 {
497     Mutex::Locker locker (m_target_list_mutex);
498     if (m_selected_target_idx >= m_target_list.size())
499         m_selected_target_idx = 0;
500     return GetTargetAtIndex (m_selected_target_idx);
501 }
502