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