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         target_sp->UpdateInstanceName();
220 
221         Mutex::Locker locker(m_target_list_mutex);
222         m_selected_target_idx = m_target_list.size();
223         m_target_list.push_back(target_sp);
224     }
225 
226     return error;
227 }
228 
229 bool
230 TargetList::DeleteTarget (TargetSP &target_sp)
231 {
232     Mutex::Locker locker(m_target_list_mutex);
233     collection::iterator pos, end = m_target_list.end();
234 
235     for (pos = m_target_list.begin(); pos != end; ++pos)
236     {
237         if (pos->get() == target_sp.get())
238         {
239             m_target_list.erase(pos);
240             return true;
241         }
242     }
243     return false;
244 }
245 
246 
247 TargetSP
248 TargetList::FindTargetWithExecutableAndArchitecture
249 (
250     const FileSpec &exe_file_spec,
251     const ArchSpec *exe_arch_ptr
252 ) const
253 {
254     Mutex::Locker locker (m_target_list_mutex);
255     TargetSP target_sp;
256     bool full_match = exe_file_spec.GetDirectory();
257 
258     collection::const_iterator pos, end = m_target_list.end();
259     for (pos = m_target_list.begin(); pos != end; ++pos)
260     {
261         Module *exe_module = (*pos)->GetExecutableModulePointer();
262 
263         if (exe_module)
264         {
265             if (FileSpec::Equal (exe_file_spec, exe_module->GetFileSpec(), full_match))
266             {
267                 if (exe_arch_ptr)
268                 {
269                     if (*exe_arch_ptr != exe_module->GetArchitecture())
270                         continue;
271                 }
272                 target_sp = *pos;
273                 break;
274             }
275         }
276     }
277     return target_sp;
278 }
279 
280 TargetSP
281 TargetList::FindTargetWithProcessID (lldb::pid_t pid) const
282 {
283     Mutex::Locker locker(m_target_list_mutex);
284     TargetSP target_sp;
285     collection::const_iterator pos, end = m_target_list.end();
286     for (pos = m_target_list.begin(); pos != end; ++pos)
287     {
288         Process* process = (*pos)->GetProcessSP().get();
289         if (process && process->GetID() == pid)
290         {
291             target_sp = *pos;
292             break;
293         }
294     }
295     return target_sp;
296 }
297 
298 
299 TargetSP
300 TargetList::FindTargetWithProcess (Process *process) const
301 {
302     TargetSP target_sp;
303     if (process)
304     {
305         Mutex::Locker locker(m_target_list_mutex);
306         collection::const_iterator pos, end = m_target_list.end();
307         for (pos = m_target_list.begin(); pos != end; ++pos)
308         {
309             if (process == (*pos)->GetProcessSP().get())
310             {
311                 target_sp = *pos;
312                 break;
313             }
314         }
315     }
316     return target_sp;
317 }
318 
319 TargetSP
320 TargetList::GetTargetSP (Target *target) const
321 {
322     TargetSP target_sp;
323     if (target)
324     {
325         Mutex::Locker locker(m_target_list_mutex);
326         collection::const_iterator pos, end = m_target_list.end();
327         for (pos = m_target_list.begin(); pos != end; ++pos)
328         {
329             if (target == (*pos).get())
330             {
331                 target_sp = *pos;
332                 break;
333             }
334         }
335     }
336     return target_sp;
337 }
338 
339 uint32_t
340 TargetList::SendAsyncInterrupt (lldb::pid_t pid)
341 {
342     uint32_t num_async_interrupts_sent = 0;
343 
344     if (pid != LLDB_INVALID_PROCESS_ID)
345     {
346         TargetSP target_sp(FindTargetWithProcessID (pid));
347         if (target_sp.get())
348         {
349             Process* process = target_sp->GetProcessSP().get();
350             if (process)
351             {
352                 process->SendAsyncInterrupt();
353                 ++num_async_interrupts_sent;
354             }
355         }
356     }
357     else
358     {
359         // We don't have a valid pid to broadcast to, so broadcast to the target
360         // list's async broadcaster...
361         BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
362     }
363 
364     return num_async_interrupts_sent;
365 }
366 
367 uint32_t
368 TargetList::SignalIfRunning (lldb::pid_t pid, int signo)
369 {
370     uint32_t num_signals_sent = 0;
371     Process *process = NULL;
372     if (pid == LLDB_INVALID_PROCESS_ID)
373     {
374         // Signal all processes with signal
375         Mutex::Locker locker(m_target_list_mutex);
376         collection::iterator pos, end = m_target_list.end();
377         for (pos = m_target_list.begin(); pos != end; ++pos)
378         {
379             process = (*pos)->GetProcessSP().get();
380             if (process)
381             {
382                 if (process->IsAlive())
383                 {
384                     ++num_signals_sent;
385                     process->Signal (signo);
386                 }
387             }
388         }
389     }
390     else
391     {
392         // Signal a specific process with signal
393         TargetSP target_sp(FindTargetWithProcessID (pid));
394         if (target_sp.get())
395         {
396             process = target_sp->GetProcessSP().get();
397             if (process)
398             {
399                 if (process->IsAlive())
400                 {
401                     ++num_signals_sent;
402                     process->Signal (signo);
403                 }
404             }
405         }
406     }
407     return num_signals_sent;
408 }
409 
410 int
411 TargetList::GetNumTargets () const
412 {
413     Mutex::Locker locker (m_target_list_mutex);
414     return m_target_list.size();
415 }
416 
417 lldb::TargetSP
418 TargetList::GetTargetAtIndex (uint32_t idx) const
419 {
420     TargetSP target_sp;
421     Mutex::Locker locker (m_target_list_mutex);
422     if (idx < m_target_list.size())
423         target_sp = m_target_list[idx];
424     return target_sp;
425 }
426 
427 uint32_t
428 TargetList::GetIndexOfTarget (lldb::TargetSP target_sp) const
429 {
430     Mutex::Locker locker (m_target_list_mutex);
431     size_t num_targets = m_target_list.size();
432     for (size_t idx = 0; idx < num_targets; idx++)
433     {
434         if (target_sp == m_target_list[idx])
435             return idx;
436     }
437     return UINT32_MAX;
438 }
439 
440 uint32_t
441 TargetList::SetSelectedTarget (Target* target)
442 {
443     Mutex::Locker locker (m_target_list_mutex);
444     collection::const_iterator pos,
445         begin = m_target_list.begin(),
446         end = m_target_list.end();
447     for (pos = begin; pos != end; ++pos)
448     {
449         if (pos->get() == target)
450         {
451             m_selected_target_idx = std::distance (begin, pos);
452             return m_selected_target_idx;
453         }
454     }
455     m_selected_target_idx = 0;
456     return m_selected_target_idx;
457 }
458 
459 lldb::TargetSP
460 TargetList::GetSelectedTarget ()
461 {
462     Mutex::Locker locker (m_target_list_mutex);
463     if (m_selected_target_idx >= m_target_list.size())
464         m_selected_target_idx = 0;
465     return GetTargetAtIndex (m_selected_target_idx);
466 }
467