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