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/Event.h"
16 #include "lldb/Core/State.h"
17 #include "lldb/Core/Timer.h"
18 #include "lldb/Host/Host.h"
19 #include "lldb/Target/Process.h"
20 #include "lldb/Target/TargetList.h"
21 
22 using namespace lldb;
23 using namespace lldb_private;
24 
25 
26 //----------------------------------------------------------------------
27 // TargetList constructor
28 //----------------------------------------------------------------------
29 TargetList::TargetList() :
30     Broadcaster("TargetList"),
31     m_target_list(),
32     m_target_list_mutex (Mutex::eMutexTypeRecursive),
33     m_selected_target_idx (0)
34 {
35 }
36 
37 //----------------------------------------------------------------------
38 // Destructor
39 //----------------------------------------------------------------------
40 TargetList::~TargetList()
41 {
42     Mutex::Locker locker(m_target_list_mutex);
43     m_target_list.clear();
44 }
45 
46 Error
47 TargetList::CreateTarget
48 (
49     Debugger &debugger,
50     const FileSpec& file,
51     const ArchSpec& arch,
52     const UUID *uuid_ptr,
53     bool get_dependent_files,
54     TargetSP &target_sp
55 )
56 {
57     Timer scoped_timer (__PRETTY_FUNCTION__,
58                         "TargetList::CreateTarget (file = '%s/%s', arch = '%s', uuid = %p)",
59                         file.GetDirectory().AsCString(),
60                         file.GetFilename().AsCString(),
61                         arch.AsCString(),
62                         uuid_ptr);
63     Error error;
64 
65     if (!file)
66     {
67         target_sp.reset(new Target(debugger));
68         target_sp->SetArchitecture(arch);
69     }
70     else
71     {
72         ModuleSP exe_module_sp;
73         FileSpec resolved_file(file);
74 
75         if (!resolved_file.Exists())
76             resolved_file.ResolveExecutableLocation ();
77 
78         if (!Host::ResolveExecutableInBundle (resolved_file))
79             resolved_file = file;
80 
81         error = ModuleList::GetSharedModule (resolved_file,
82                                              arch,
83                                              uuid_ptr,
84                                              NULL,
85                                              0,
86                                              exe_module_sp,
87                                              NULL,
88                                              NULL);
89         if (exe_module_sp)
90         {
91             if (exe_module_sp->GetObjectFile() == NULL)
92             {
93                 if (arch.IsValid())
94                 {
95                     error.SetErrorStringWithFormat("\"%s%s%s\" doesn't contain architecture %s",
96                                                    file.GetDirectory().AsCString(),
97                                                    file.GetDirectory() ? "/" : "",
98                                                    file.GetFilename().AsCString(),
99                                                    arch.AsCString());
100                 }
101                 else
102                 {
103                     error.SetErrorStringWithFormat("unsupported file type \"%s%s%s\"",
104                                                    file.GetDirectory().AsCString(),
105                                                    file.GetDirectory() ? "/" : "",
106                                                    file.GetFilename().AsCString());
107                 }
108                 return error;
109             }
110             target_sp.reset(new Target(debugger));
111             target_sp->SetExecutableModule (exe_module_sp, get_dependent_files);
112         }
113     }
114 
115     if (target_sp.get())
116         target_sp->UpdateInstanceName();
117 
118     if (target_sp.get())
119     {
120         Mutex::Locker locker(m_target_list_mutex);
121         m_selected_target_idx = m_target_list.size();
122         m_target_list.push_back(target_sp);
123     }
124 
125 //        target_sp.reset(new Target);
126 //        // Let the target resolve any funky bundle paths before we try and get
127 //        // the object file...
128 //        target_sp->SetExecutableModule (exe_module_sp, get_dependent_files);
129 //        if (exe_module_sp->GetObjectFile() == NULL)
130 //        {
131 //            error.SetErrorStringWithFormat("%s%s%s: doesn't contain architecture %s",
132 //                                           file.GetDirectory().AsCString(),
133 //                                           file.GetDirectory() ? "/" : "",
134 //                                           file.GetFilename().AsCString(),
135 //                                           arch.AsCString());
136 //        }
137 //        else
138 //        {
139 //            if (target_sp.get())
140 //            {
141 //                error.Clear();
142 //                Mutex::Locker locker(m_target_list_mutex);
143 //                m_selected_target_idx = m_target_list.size();
144 //                m_target_list.push_back(target_sp);
145 //            }
146 //        }
147     else
148     {
149         target_sp.reset();
150     }
151 
152     return error;
153 }
154 
155 bool
156 TargetList::DeleteTarget (TargetSP &target_sp)
157 {
158     Mutex::Locker locker(m_target_list_mutex);
159     collection::iterator pos, end = m_target_list.end();
160 
161     for (pos = m_target_list.begin(); pos != end; ++pos)
162     {
163         if (pos->get() == target_sp.get())
164         {
165             m_target_list.erase(pos);
166             return true;
167         }
168     }
169     return false;
170 }
171 
172 
173 TargetSP
174 TargetList::FindTargetWithExecutableAndArchitecture
175 (
176     const FileSpec &exe_file_spec,
177     const ArchSpec *exe_arch_ptr
178 ) const
179 {
180     Mutex::Locker locker (m_target_list_mutex);
181     TargetSP target_sp;
182     bool full_match = exe_file_spec.GetDirectory();
183 
184     collection::const_iterator pos, end = m_target_list.end();
185     for (pos = m_target_list.begin(); pos != end; ++pos)
186     {
187         ModuleSP module_sp ((*pos)->GetExecutableModule());
188 
189         if (module_sp)
190         {
191             if (FileSpec::Equal (exe_file_spec, module_sp->GetFileSpec(), full_match))
192             {
193                 if (exe_arch_ptr)
194                 {
195                     if (*exe_arch_ptr != module_sp->GetArchitecture())
196                         continue;
197                 }
198                 target_sp = *pos;
199                 break;
200             }
201         }
202     }
203     return target_sp;
204 }
205 
206 TargetSP
207 TargetList::FindTargetWithProcessID (lldb::pid_t pid) const
208 {
209     Mutex::Locker locker(m_target_list_mutex);
210     TargetSP target_sp;
211     collection::const_iterator pos, end = m_target_list.end();
212     for (pos = m_target_list.begin(); pos != end; ++pos)
213     {
214         Process* process = (*pos)->GetProcessSP().get();
215         if (process && process->GetID() == pid)
216         {
217             target_sp = *pos;
218             break;
219         }
220     }
221     return target_sp;
222 }
223 
224 
225 TargetSP
226 TargetList::FindTargetWithProcess (Process *process) const
227 {
228     TargetSP target_sp;
229     if (process)
230     {
231         Mutex::Locker locker(m_target_list_mutex);
232         collection::const_iterator pos, end = m_target_list.end();
233         for (pos = m_target_list.begin(); pos != end; ++pos)
234         {
235             if (process == (*pos)->GetProcessSP().get())
236             {
237                 target_sp = *pos;
238                 break;
239             }
240         }
241     }
242     return target_sp;
243 }
244 
245 TargetSP
246 TargetList::GetTargetSP (Target *target) const
247 {
248     TargetSP target_sp;
249     if (target)
250     {
251         Mutex::Locker locker(m_target_list_mutex);
252         collection::const_iterator pos, end = m_target_list.end();
253         for (pos = m_target_list.begin(); pos != end; ++pos)
254         {
255             if (target == (*pos).get())
256             {
257                 target_sp = *pos;
258                 break;
259             }
260         }
261     }
262     return target_sp;
263 }
264 
265 uint32_t
266 TargetList::SendAsyncInterrupt (lldb::pid_t pid)
267 {
268     uint32_t num_async_interrupts_sent = 0;
269 
270     if (pid != LLDB_INVALID_PROCESS_ID)
271     {
272         TargetSP target_sp(FindTargetWithProcessID (pid));
273         if (target_sp.get())
274         {
275             Process* process = target_sp->GetProcessSP().get();
276             if (process)
277             {
278                 process->BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
279                 ++num_async_interrupts_sent;
280             }
281         }
282     }
283     else
284     {
285         // We don't have a valid pid to broadcast to, so broadcast to the target
286         // list's async broadcaster...
287         BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
288     }
289 
290     return num_async_interrupts_sent;
291 }
292 
293 uint32_t
294 TargetList::SignalIfRunning (lldb::pid_t pid, int signo)
295 {
296     uint32_t num_signals_sent = 0;
297     Process *process = NULL;
298     if (pid == LLDB_INVALID_PROCESS_ID)
299     {
300         // Signal all processes with signal
301         Mutex::Locker locker(m_target_list_mutex);
302         collection::iterator pos, end = m_target_list.end();
303         for (pos = m_target_list.begin(); pos != end; ++pos)
304         {
305             process = (*pos)->GetProcessSP().get();
306             if (process)
307             {
308                 if (process->IsAlive())
309                 {
310                     ++num_signals_sent;
311                     process->Signal (signo);
312                 }
313             }
314         }
315     }
316     else
317     {
318         // Signal a specific process with signal
319         TargetSP target_sp(FindTargetWithProcessID (pid));
320         if (target_sp.get())
321         {
322             process = target_sp->GetProcessSP().get();
323             if (process)
324             {
325                 if (process->IsAlive())
326                 {
327                     ++num_signals_sent;
328                     process->Signal (signo);
329                 }
330             }
331         }
332     }
333     return num_signals_sent;
334 }
335 
336 int
337 TargetList::GetNumTargets () const
338 {
339     Mutex::Locker locker (m_target_list_mutex);
340     return m_target_list.size();
341 }
342 
343 lldb::TargetSP
344 TargetList::GetTargetAtIndex (uint32_t idx) const
345 {
346     TargetSP target_sp;
347     Mutex::Locker locker (m_target_list_mutex);
348     if (idx < m_target_list.size())
349         target_sp = m_target_list[idx];
350     return target_sp;
351 }
352 
353 uint32_t
354 TargetList::SetSelectedTarget (Target* target)
355 {
356     Mutex::Locker locker (m_target_list_mutex);
357     collection::const_iterator pos,
358         begin = m_target_list.begin(),
359         end = m_target_list.end();
360     for (pos = begin; pos != end; ++pos)
361     {
362         if (pos->get() == target)
363         {
364             m_selected_target_idx = std::distance (begin, pos);
365             return m_selected_target_idx;
366         }
367     }
368     m_selected_target_idx = 0;
369     return m_selected_target_idx;
370 }
371 
372 lldb::TargetSP
373 TargetList::GetSelectedTarget ()
374 {
375     Mutex::Locker locker (m_target_list_mutex);
376     if (m_selected_target_idx >= m_target_list.size())
377         m_selected_target_idx = 0;
378     return GetTargetAtIndex (m_selected_target_idx);
379 }
380