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                 error.SetErrorStringWithFormat("%s%s%s: doesn't contain architecture %s",
94                                                file.GetDirectory().AsCString(),
95                                                file.GetDirectory() ? "/" : "",
96                                                file.GetFilename().AsCString(),
97                                                arch.AsCString());
98                 return error;
99             }
100             target_sp.reset(new Target(debugger));
101             target_sp->SetExecutableModule (exe_module_sp, get_dependent_files);
102         }
103     }
104 
105     if (target_sp.get())
106         target_sp->UpdateInstanceName();
107 
108     if (target_sp.get())
109     {
110         Mutex::Locker locker(m_target_list_mutex);
111         m_selected_target_idx = m_target_list.size();
112         m_target_list.push_back(target_sp);
113     }
114 
115 //        target_sp.reset(new Target);
116 //        // Let the target resolve any funky bundle paths before we try and get
117 //        // the object file...
118 //        target_sp->SetExecutableModule (exe_module_sp, get_dependent_files);
119 //        if (exe_module_sp->GetObjectFile() == NULL)
120 //        {
121 //            error.SetErrorStringWithFormat("%s%s%s: doesn't contain architecture %s",
122 //                                           file.GetDirectory().AsCString(),
123 //                                           file.GetDirectory() ? "/" : "",
124 //                                           file.GetFilename().AsCString(),
125 //                                           arch.AsCString());
126 //        }
127 //        else
128 //        {
129 //            if (target_sp.get())
130 //            {
131 //                error.Clear();
132 //                Mutex::Locker locker(m_target_list_mutex);
133 //                m_selected_target_idx = m_target_list.size();
134 //                m_target_list.push_back(target_sp);
135 //            }
136 //        }
137     else
138     {
139         target_sp.reset();
140     }
141 
142     return error;
143 }
144 
145 bool
146 TargetList::DeleteTarget (TargetSP &target_sp)
147 {
148     Mutex::Locker locker(m_target_list_mutex);
149     collection::iterator pos, end = m_target_list.end();
150 
151     for (pos = m_target_list.begin(); pos != end; ++pos)
152     {
153         if (pos->get() == target_sp.get())
154         {
155             m_target_list.erase(pos);
156             return true;
157         }
158     }
159     return false;
160 }
161 
162 
163 TargetSP
164 TargetList::FindTargetWithExecutableAndArchitecture
165 (
166     const FileSpec &exe_file_spec,
167     const ArchSpec *exe_arch_ptr
168 ) const
169 {
170     Mutex::Locker locker (m_target_list_mutex);
171     TargetSP target_sp;
172     bool full_match = exe_file_spec.GetDirectory();
173 
174     collection::const_iterator pos, end = m_target_list.end();
175     for (pos = m_target_list.begin(); pos != end; ++pos)
176     {
177         ModuleSP module_sp ((*pos)->GetExecutableModule());
178 
179         if (module_sp)
180         {
181             if (FileSpec::Equal (exe_file_spec, module_sp->GetFileSpec(), full_match))
182             {
183                 if (exe_arch_ptr)
184                 {
185                     if (*exe_arch_ptr != module_sp->GetArchitecture())
186                         continue;
187                 }
188                 target_sp = *pos;
189                 break;
190             }
191         }
192     }
193     return target_sp;
194 }
195 
196 TargetSP
197 TargetList::FindTargetWithProcessID (lldb::pid_t pid) const
198 {
199     Mutex::Locker locker(m_target_list_mutex);
200     TargetSP target_sp;
201     collection::const_iterator pos, end = m_target_list.end();
202     for (pos = m_target_list.begin(); pos != end; ++pos)
203     {
204         Process* process = (*pos)->GetProcessSP().get();
205         if (process && process->GetID() == pid)
206         {
207             target_sp = *pos;
208             break;
209         }
210     }
211     return target_sp;
212 }
213 
214 
215 TargetSP
216 TargetList::FindTargetWithProcess (Process *process) const
217 {
218     TargetSP target_sp;
219     if (process)
220     {
221         Mutex::Locker locker(m_target_list_mutex);
222         collection::const_iterator pos, end = m_target_list.end();
223         for (pos = m_target_list.begin(); pos != end; ++pos)
224         {
225             if (process == (*pos)->GetProcessSP().get())
226             {
227                 target_sp = *pos;
228                 break;
229             }
230         }
231     }
232     return target_sp;
233 }
234 
235 TargetSP
236 TargetList::GetTargetSP (Target *target) const
237 {
238     TargetSP target_sp;
239     if (target)
240     {
241         Mutex::Locker locker(m_target_list_mutex);
242         collection::const_iterator pos, end = m_target_list.end();
243         for (pos = m_target_list.begin(); pos != end; ++pos)
244         {
245             if (target == (*pos).get())
246             {
247                 target_sp = *pos;
248                 break;
249             }
250         }
251     }
252     return target_sp;
253 }
254 
255 uint32_t
256 TargetList::SendAsyncInterrupt (lldb::pid_t pid)
257 {
258     uint32_t num_async_interrupts_sent = 0;
259 
260     if (pid != LLDB_INVALID_PROCESS_ID)
261     {
262         TargetSP target_sp(FindTargetWithProcessID (pid));
263         if (target_sp.get())
264         {
265             Process* process = target_sp->GetProcessSP().get();
266             if (process)
267             {
268                 process->BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
269                 ++num_async_interrupts_sent;
270             }
271         }
272     }
273     else
274     {
275         // We don't have a valid pid to broadcast to, so broadcast to the target
276         // list's async broadcaster...
277         BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
278     }
279 
280     return num_async_interrupts_sent;
281 }
282 
283 uint32_t
284 TargetList::SignalIfRunning (lldb::pid_t pid, int signo)
285 {
286     uint32_t num_signals_sent = 0;
287     Process *process = NULL;
288     if (pid == LLDB_INVALID_PROCESS_ID)
289     {
290         // Signal all processes with signal
291         Mutex::Locker locker(m_target_list_mutex);
292         collection::iterator pos, end = m_target_list.end();
293         for (pos = m_target_list.begin(); pos != end; ++pos)
294         {
295             process = (*pos)->GetProcessSP().get();
296             if (process)
297             {
298                 if (process->IsAlive())
299                 {
300                     ++num_signals_sent;
301                     process->Signal (signo);
302                 }
303             }
304         }
305     }
306     else
307     {
308         // Signal a specific process with signal
309         TargetSP target_sp(FindTargetWithProcessID (pid));
310         if (target_sp.get())
311         {
312             process = target_sp->GetProcessSP().get();
313             if (process)
314             {
315                 if (process->IsAlive())
316                 {
317                     ++num_signals_sent;
318                     process->Signal (signo);
319                 }
320             }
321         }
322     }
323     return num_signals_sent;
324 }
325 
326 int
327 TargetList::GetNumTargets () const
328 {
329     Mutex::Locker locker (m_target_list_mutex);
330     return m_target_list.size();
331 }
332 
333 lldb::TargetSP
334 TargetList::GetTargetAtIndex (uint32_t idx) const
335 {
336     TargetSP target_sp;
337     Mutex::Locker locker (m_target_list_mutex);
338     if (idx < m_target_list.size())
339         target_sp = m_target_list[idx];
340     return target_sp;
341 }
342 
343 uint32_t
344 TargetList::SetSelectedTarget (Target* target)
345 {
346     Mutex::Locker locker (m_target_list_mutex);
347     collection::const_iterator pos,
348         begin = m_target_list.begin(),
349         end = m_target_list.end();
350     for (pos = begin; pos != end; ++pos)
351     {
352         if (pos->get() == target)
353         {
354             m_selected_target_idx = std::distance (begin, pos);
355             return m_selected_target_idx;
356         }
357     }
358     m_selected_target_idx = 0;
359     return m_selected_target_idx;
360 }
361 
362 lldb::TargetSP
363 TargetList::GetSelectedTarget ()
364 {
365     Mutex::Locker locker (m_target_list_mutex);
366     if (m_selected_target_idx >= m_target_list.size())
367         m_selected_target_idx = 0;
368     return GetTargetAtIndex (m_selected_target_idx);
369 }
370