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