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