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