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     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     ModuleSP exe_module_sp;
64     FileSpec resolved_file(file);
65     if (!Host::ResolveExecutableInBundle (&resolved_file))
66         resolved_file = file;
67 
68     Error error = ModuleList::GetSharedModule(resolved_file,
69                                               arch,
70                                               uuid_ptr,
71                                               NULL,
72                                               0,
73                                               exe_module_sp,
74                                               NULL,
75                                               NULL);
76     if (exe_module_sp)
77     {
78         target_sp.reset(new Target(debugger));
79         target_sp->SetExecutableModule (exe_module_sp, get_dependent_files);
80 
81         if (target_sp.get())
82         {
83             Mutex::Locker locker(m_target_list_mutex);
84             m_current_target_idx = m_target_list.size();
85             m_target_list.push_back(target_sp);
86         }
87 
88 //        target_sp.reset(new Target);
89 //        // Let the target resolve any funky bundle paths before we try and get
90 //        // the object file...
91 //        target_sp->SetExecutableModule (exe_module_sp, get_dependent_files);
92 //        if (exe_module_sp->GetObjectFile() == NULL)
93 //        {
94 //            error.SetErrorStringWithFormat("%s%s%s: doesn't contain architecture %s",
95 //                                           file.GetDirectory().AsCString(),
96 //                                           file.GetDirectory() ? "/" : "",
97 //                                           file.GetFilename().AsCString(),
98 //                                           arch.AsCString());
99 //        }
100 //        else
101 //        {
102 //            if (target_sp.get())
103 //            {
104 //                error.Clear();
105 //                Mutex::Locker locker(m_target_list_mutex);
106 //                m_current_target_idx = m_target_list.size();
107 //                m_target_list.push_back(target_sp);
108 //            }
109 //        }
110     }
111     else
112     {
113         target_sp.reset();
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::SetCurrentTarget (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_current_target_idx = std::distance (begin, pos);
329             return m_current_target_idx;
330         }
331     }
332     m_current_target_idx = 0;
333     return m_current_target_idx;
334 }
335 
336 lldb::TargetSP
337 TargetList::GetCurrentTarget ()
338 {
339     Mutex::Locker locker (m_target_list_mutex);
340     if (m_current_target_idx >= m_target_list.size())
341         m_current_target_idx = 0;
342     return GetTargetAtIndex (m_current_target_idx);
343 }
344