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"),
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 FileSpec& file,
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                                       file,
116                                       platform_arch,
117                                       get_dependent_files,
118                                       platform_sp,
119                                       target_sp);
120 
121     if (target_sp)
122     {
123         if (file.GetDirectory())
124         {
125             FileSpec file_dir;
126             file_dir.GetDirectory() = file.GetDirectory();
127             target_sp->GetExecutableSearchPaths ().Append (file_dir);
128         }
129     }
130     return error;
131 }
132 
133 Error
134 TargetList::CreateTarget
135 (
136     Debugger &debugger,
137     const FileSpec& file,
138     const ArchSpec& specified_arch,
139     bool get_dependent_files,
140     PlatformSP &platform_sp,
141     TargetSP &target_sp
142 )
143 {
144     Timer scoped_timer (__PRETTY_FUNCTION__,
145                         "TargetList::CreateTarget (file = '%s/%s', arch = '%s')",
146                         file.GetDirectory().AsCString(),
147                         file.GetFilename().AsCString(),
148                         specified_arch.GetArchitectureName());
149     Error error;
150 
151     ArchSpec arch(specified_arch);
152 
153     if (platform_sp)
154     {
155         if (arch.IsValid())
156         {
157             if (!platform_sp->IsCompatibleArchitecture(arch))
158                 platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
159         }
160     }
161     else if (arch.IsValid())
162     {
163         platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
164     }
165 
166     if (!platform_sp)
167         platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
168 
169     if (!arch.IsValid())
170         arch = specified_arch;
171 
172 
173     if (file)
174     {
175         ModuleSP exe_module_sp;
176         FileSpec resolved_file(file);
177         if (platform_sp)
178         {
179             FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
180             error = platform_sp->ResolveExecutable (file,
181                                                     arch,
182                                                     exe_module_sp,
183                                                     executable_search_paths.GetSize() ? &executable_search_paths : NULL);
184         }
185 
186         if (error.Success() && exe_module_sp)
187         {
188             if (exe_module_sp->GetObjectFile() == NULL)
189             {
190                 if (arch.IsValid())
191                 {
192                     error.SetErrorStringWithFormat("\"%s%s%s\" doesn't contain architecture %s",
193                                                    file.GetDirectory().AsCString(),
194                                                    file.GetDirectory() ? "/" : "",
195                                                    file.GetFilename().AsCString(),
196                                                    arch.GetArchitectureName());
197                 }
198                 else
199                 {
200                     error.SetErrorStringWithFormat("unsupported file type \"%s%s%s\"",
201                                                    file.GetDirectory().AsCString(),
202                                                    file.GetDirectory() ? "/" : "",
203                                                    file.GetFilename().AsCString());
204                 }
205                 return error;
206             }
207             target_sp.reset(new Target(debugger, arch, platform_sp));
208             target_sp->SetExecutableModule (exe_module_sp, get_dependent_files);
209         }
210     }
211     else
212     {
213         // No file was specified, just create an empty target with any arch
214         // if a valid arch was specified
215         target_sp.reset(new Target(debugger, arch, platform_sp));
216     }
217 
218     if (target_sp)
219     {
220         Mutex::Locker locker(m_target_list_mutex);
221         m_selected_target_idx = m_target_list.size();
222         m_target_list.push_back(target_sp);
223     }
224 
225     return error;
226 }
227 
228 bool
229 TargetList::DeleteTarget (TargetSP &target_sp)
230 {
231     Mutex::Locker locker(m_target_list_mutex);
232     collection::iterator pos, end = m_target_list.end();
233 
234     for (pos = m_target_list.begin(); pos != end; ++pos)
235     {
236         if (pos->get() == target_sp.get())
237         {
238             m_target_list.erase(pos);
239             return true;
240         }
241     }
242     return false;
243 }
244 
245 
246 TargetSP
247 TargetList::FindTargetWithExecutableAndArchitecture
248 (
249     const FileSpec &exe_file_spec,
250     const ArchSpec *exe_arch_ptr
251 ) const
252 {
253     Mutex::Locker locker (m_target_list_mutex);
254     TargetSP target_sp;
255     bool full_match = exe_file_spec.GetDirectory();
256 
257     collection::const_iterator pos, end = m_target_list.end();
258     for (pos = m_target_list.begin(); pos != end; ++pos)
259     {
260         Module *exe_module = (*pos)->GetExecutableModulePointer();
261 
262         if (exe_module)
263         {
264             if (FileSpec::Equal (exe_file_spec, exe_module->GetFileSpec(), full_match))
265             {
266                 if (exe_arch_ptr)
267                 {
268                     if (*exe_arch_ptr != exe_module->GetArchitecture())
269                         continue;
270                 }
271                 target_sp = *pos;
272                 break;
273             }
274         }
275     }
276     return target_sp;
277 }
278 
279 TargetSP
280 TargetList::FindTargetWithProcessID (lldb::pid_t pid) const
281 {
282     Mutex::Locker locker(m_target_list_mutex);
283     TargetSP target_sp;
284     collection::const_iterator pos, end = m_target_list.end();
285     for (pos = m_target_list.begin(); pos != end; ++pos)
286     {
287         Process* process = (*pos)->GetProcessSP().get();
288         if (process && process->GetID() == pid)
289         {
290             target_sp = *pos;
291             break;
292         }
293     }
294     return target_sp;
295 }
296 
297 
298 TargetSP
299 TargetList::FindTargetWithProcess (Process *process) const
300 {
301     TargetSP target_sp;
302     if (process)
303     {
304         Mutex::Locker locker(m_target_list_mutex);
305         collection::const_iterator pos, end = m_target_list.end();
306         for (pos = m_target_list.begin(); pos != end; ++pos)
307         {
308             if (process == (*pos)->GetProcessSP().get())
309             {
310                 target_sp = *pos;
311                 break;
312             }
313         }
314     }
315     return target_sp;
316 }
317 
318 TargetSP
319 TargetList::GetTargetSP (Target *target) const
320 {
321     TargetSP target_sp;
322     if (target)
323     {
324         Mutex::Locker locker(m_target_list_mutex);
325         collection::const_iterator pos, end = m_target_list.end();
326         for (pos = m_target_list.begin(); pos != end; ++pos)
327         {
328             if (target == (*pos).get())
329             {
330                 target_sp = *pos;
331                 break;
332             }
333         }
334     }
335     return target_sp;
336 }
337 
338 uint32_t
339 TargetList::SendAsyncInterrupt (lldb::pid_t pid)
340 {
341     uint32_t num_async_interrupts_sent = 0;
342 
343     if (pid != LLDB_INVALID_PROCESS_ID)
344     {
345         TargetSP target_sp(FindTargetWithProcessID (pid));
346         if (target_sp.get())
347         {
348             Process* process = target_sp->GetProcessSP().get();
349             if (process)
350             {
351                 process->SendAsyncInterrupt();
352                 ++num_async_interrupts_sent;
353             }
354         }
355     }
356     else
357     {
358         // We don't have a valid pid to broadcast to, so broadcast to the target
359         // list's async broadcaster...
360         BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
361     }
362 
363     return num_async_interrupts_sent;
364 }
365 
366 uint32_t
367 TargetList::SignalIfRunning (lldb::pid_t pid, int signo)
368 {
369     uint32_t num_signals_sent = 0;
370     Process *process = NULL;
371     if (pid == LLDB_INVALID_PROCESS_ID)
372     {
373         // Signal all processes with signal
374         Mutex::Locker locker(m_target_list_mutex);
375         collection::iterator pos, end = m_target_list.end();
376         for (pos = m_target_list.begin(); pos != end; ++pos)
377         {
378             process = (*pos)->GetProcessSP().get();
379             if (process)
380             {
381                 if (process->IsAlive())
382                 {
383                     ++num_signals_sent;
384                     process->Signal (signo);
385                 }
386             }
387         }
388     }
389     else
390     {
391         // Signal a specific process with signal
392         TargetSP target_sp(FindTargetWithProcessID (pid));
393         if (target_sp.get())
394         {
395             process = target_sp->GetProcessSP().get();
396             if (process)
397             {
398                 if (process->IsAlive())
399                 {
400                     ++num_signals_sent;
401                     process->Signal (signo);
402                 }
403             }
404         }
405     }
406     return num_signals_sent;
407 }
408 
409 int
410 TargetList::GetNumTargets () const
411 {
412     Mutex::Locker locker (m_target_list_mutex);
413     return m_target_list.size();
414 }
415 
416 lldb::TargetSP
417 TargetList::GetTargetAtIndex (uint32_t idx) const
418 {
419     TargetSP target_sp;
420     Mutex::Locker locker (m_target_list_mutex);
421     if (idx < m_target_list.size())
422         target_sp = m_target_list[idx];
423     return target_sp;
424 }
425 
426 uint32_t
427 TargetList::GetIndexOfTarget (lldb::TargetSP target_sp) const
428 {
429     Mutex::Locker locker (m_target_list_mutex);
430     size_t num_targets = m_target_list.size();
431     for (size_t idx = 0; idx < num_targets; idx++)
432     {
433         if (target_sp == m_target_list[idx])
434             return idx;
435     }
436     return UINT32_MAX;
437 }
438 
439 uint32_t
440 TargetList::SetSelectedTarget (Target* target)
441 {
442     Mutex::Locker locker (m_target_list_mutex);
443     collection::const_iterator pos,
444         begin = m_target_list.begin(),
445         end = m_target_list.end();
446     for (pos = begin; pos != end; ++pos)
447     {
448         if (pos->get() == target)
449         {
450             m_selected_target_idx = std::distance (begin, pos);
451             return m_selected_target_idx;
452         }
453     }
454     m_selected_target_idx = 0;
455     return m_selected_target_idx;
456 }
457 
458 lldb::TargetSP
459 TargetList::GetSelectedTarget ()
460 {
461     Mutex::Locker locker (m_target_list_mutex);
462     if (m_selected_target_idx >= m_target_list.size())
463         m_selected_target_idx = 0;
464     return GetTargetAtIndex (m_selected_target_idx);
465 }
466