blob: e412beb1da5e5c12ec19b8ba4af525fa313b44b6 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- 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"
Greg Claytonded470d2011-03-19 01:12:21 +000015#include "lldb/Core/Debugger.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016#include "lldb/Core/Event.h"
17#include "lldb/Core/State.h"
18#include "lldb/Core/Timer.h"
19#include "lldb/Host/Host.h"
Greg Claytoncac9c5f2011-09-24 00:52:29 +000020#include "lldb/Interpreter/OptionGroupPlatform.h"
Greg Claytone996fd32011-03-08 22:40:15 +000021#include "lldb/Target/Platform.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022#include "lldb/Target/Process.h"
23#include "lldb/Target/TargetList.h"
24
25using namespace lldb;
26using namespace lldb_private;
27
28
29//----------------------------------------------------------------------
30// TargetList constructor
31//----------------------------------------------------------------------
32TargetList::TargetList() :
33 Broadcaster("TargetList"),
34 m_target_list(),
35 m_target_list_mutex (Mutex::eMutexTypeRecursive),
Jim Ingham2976d002010-08-26 21:32:51 +000036 m_selected_target_idx (0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000037{
38}
39
40//----------------------------------------------------------------------
41// Destructor
42//----------------------------------------------------------------------
43TargetList::~TargetList()
44{
45 Mutex::Locker locker(m_target_list_mutex);
46 m_target_list.clear();
47}
48
49Error
Greg Claytoncac9c5f2011-09-24 00:52:29 +000050TargetList::CreateTarget (Debugger &debugger,
51 const FileSpec& file,
52 const char *triple_cstr,
53 bool get_dependent_files,
54 const OptionGroupPlatform *platform_options,
55 TargetSP &target_sp)
56{
57 Error error;
58 PlatformSP platform_sp;
59 if (platform_options)
60 {
61 if (platform_options->PlatformWasSpecified ())
62 {
63 const bool select_platform = true;
64 platform_sp = platform_options->CreatePlatformWithOptions (debugger.GetCommandInterpreter(),
65 select_platform,
66 error);
67 if (!platform_sp)
68 return error;
69 }
70 }
71
72 if (!platform_sp)
73 platform_sp = debugger.GetPlatformList().GetSelectedPlatform ();
74
Johnny Chencdc21d42012-01-05 01:26:01 +000075 // This is purposely left empty unless it is specified by triple_cstr.
76 // If not initialized via triple_cstr, then the currently selected platform
77 // will set the architecture correctly.
Greg Claytoncac9c5f2011-09-24 00:52:29 +000078 ArchSpec arch;
79
80 if (triple_cstr)
81 {
82 arch.SetTriple(triple_cstr, platform_sp.get());
83 if (!arch.IsValid())
84 {
Greg Clayton86edbf42011-10-26 00:56:27 +000085 error.SetErrorStringWithFormat("invalid triple '%s'", triple_cstr);
Greg Claytoncac9c5f2011-09-24 00:52:29 +000086 return error;
87 }
88 }
89 error = TargetList::CreateTarget (debugger,
90 file,
91 arch,
92 get_dependent_files,
93 platform_sp,
94 target_sp);
Greg Claytonc859e2d2012-02-13 23:10:39 +000095
96 if (target_sp)
97 {
98 if (file.GetDirectory())
99 {
100 FileSpec file_dir;
101 file_dir.GetDirectory() = file.GetDirectory();
102 target_sp->GetExecutableSearchPaths ().Append (file_dir);
103 }
104 }
Greg Claytoncac9c5f2011-09-24 00:52:29 +0000105 return error;
106}
107
108Error
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000109TargetList::CreateTarget
110(
Greg Clayton66111032010-06-23 01:19:29 +0000111 Debugger &debugger,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000112 const FileSpec& file,
113 const ArchSpec& arch,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000114 bool get_dependent_files,
Greg Claytoncac9c5f2011-09-24 00:52:29 +0000115 const PlatformSP &platform_sp,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000116 TargetSP &target_sp
117)
118{
119 Timer scoped_timer (__PRETTY_FUNCTION__,
Greg Claytone996fd32011-03-08 22:40:15 +0000120 "TargetList::CreateTarget (file = '%s/%s', arch = '%s')",
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000121 file.GetDirectory().AsCString(),
122 file.GetFilename().AsCString(),
Greg Claytone996fd32011-03-08 22:40:15 +0000123 arch.GetArchitectureName());
Jim Ingham5aee1622010-08-09 23:31:02 +0000124 Error error;
Greg Claytonded470d2011-03-19 01:12:21 +0000125
Jim Ingham5aee1622010-08-09 23:31:02 +0000126
Greg Claytone996fd32011-03-08 22:40:15 +0000127 if (file)
Jim Ingham5aee1622010-08-09 23:31:02 +0000128 {
129 ModuleSP exe_module_sp;
130 FileSpec resolved_file(file);
Caroline Tice428a9a52010-09-10 04:48:55 +0000131
Greg Claytone996fd32011-03-08 22:40:15 +0000132 if (platform_sp)
Greg Claytonc859e2d2012-02-13 23:10:39 +0000133 {
134 FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
135 error = platform_sp->ResolveExecutable (file, arch,
136 exe_module_sp,
137 executable_search_paths.GetSize() ? &executable_search_paths : NULL);
138 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000139
Greg Claytone996fd32011-03-08 22:40:15 +0000140 if (error.Success() && exe_module_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000141 {
Jim Ingham5aee1622010-08-09 23:31:02 +0000142 if (exe_module_sp->GetObjectFile() == NULL)
143 {
Greg Claytonbc5cad62010-12-08 04:55:11 +0000144 if (arch.IsValid())
145 {
146 error.SetErrorStringWithFormat("\"%s%s%s\" doesn't contain architecture %s",
147 file.GetDirectory().AsCString(),
148 file.GetDirectory() ? "/" : "",
149 file.GetFilename().AsCString(),
Greg Clayton64195a22011-02-23 00:35:02 +0000150 arch.GetArchitectureName());
Greg Claytonbc5cad62010-12-08 04:55:11 +0000151 }
152 else
153 {
154 error.SetErrorStringWithFormat("unsupported file type \"%s%s%s\"",
155 file.GetDirectory().AsCString(),
156 file.GetDirectory() ? "/" : "",
157 file.GetFilename().AsCString());
158 }
Jim Ingham5aee1622010-08-09 23:31:02 +0000159 return error;
160 }
Greg Clayton32e0a752011-03-30 18:16:51 +0000161 target_sp.reset(new Target(debugger, arch, platform_sp));
Jim Ingham5aee1622010-08-09 23:31:02 +0000162 target_sp->SetExecutableModule (exe_module_sp, get_dependent_files);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000163 }
Jim Ingham5aee1622010-08-09 23:31:02 +0000164 }
Greg Claytone996fd32011-03-08 22:40:15 +0000165 else
Jim Ingham5aee1622010-08-09 23:31:02 +0000166 {
Greg Claytone996fd32011-03-08 22:40:15 +0000167 // No file was specified, just create an empty target with any arch
168 // if a valid arch was specified
Greg Clayton32e0a752011-03-30 18:16:51 +0000169 target_sp.reset(new Target(debugger, arch, platform_sp));
Greg Claytone996fd32011-03-08 22:40:15 +0000170 }
171
172 if (target_sp)
173 {
174 target_sp->UpdateInstanceName();
175
Jim Ingham5aee1622010-08-09 23:31:02 +0000176 Mutex::Locker locker(m_target_list_mutex);
Jim Ingham2976d002010-08-26 21:32:51 +0000177 m_selected_target_idx = m_target_list.size();
Jim Ingham5aee1622010-08-09 23:31:02 +0000178 m_target_list.push_back(target_sp);
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000179
180 // Now sign the Debugger up to listen to target events for this target:
181 debugger.GetListener().StartListeningForEvents(target_sp.get(), Target::eBroadcastBitBreakpointChanged);
Jim Ingham5aee1622010-08-09 23:31:02 +0000182 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000183
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000184 return error;
185}
186
187bool
188TargetList::DeleteTarget (TargetSP &target_sp)
189{
190 Mutex::Locker locker(m_target_list_mutex);
191 collection::iterator pos, end = m_target_list.end();
192
193 for (pos = m_target_list.begin(); pos != end; ++pos)
194 {
195 if (pos->get() == target_sp.get())
196 {
197 m_target_list.erase(pos);
198 return true;
199 }
200 }
201 return false;
202}
203
204
205TargetSP
206TargetList::FindTargetWithExecutableAndArchitecture
207(
208 const FileSpec &exe_file_spec,
209 const ArchSpec *exe_arch_ptr
210) const
211{
212 Mutex::Locker locker (m_target_list_mutex);
213 TargetSP target_sp;
214 bool full_match = exe_file_spec.GetDirectory();
215
216 collection::const_iterator pos, end = m_target_list.end();
217 for (pos = m_target_list.begin(); pos != end; ++pos)
218 {
Greg Claytonaa149cb2011-08-11 02:48:45 +0000219 Module *exe_module = (*pos)->GetExecutableModulePointer();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000220
Greg Claytonaa149cb2011-08-11 02:48:45 +0000221 if (exe_module)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000222 {
Greg Claytonaa149cb2011-08-11 02:48:45 +0000223 if (FileSpec::Equal (exe_file_spec, exe_module->GetFileSpec(), full_match))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000224 {
225 if (exe_arch_ptr)
226 {
Greg Claytonaa149cb2011-08-11 02:48:45 +0000227 if (*exe_arch_ptr != exe_module->GetArchitecture())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000228 continue;
229 }
230 target_sp = *pos;
231 break;
232 }
233 }
234 }
235 return target_sp;
236}
237
238TargetSP
239TargetList::FindTargetWithProcessID (lldb::pid_t pid) const
240{
241 Mutex::Locker locker(m_target_list_mutex);
242 TargetSP target_sp;
243 collection::const_iterator pos, end = m_target_list.end();
244 for (pos = m_target_list.begin(); pos != end; ++pos)
245 {
246 Process* process = (*pos)->GetProcessSP().get();
247 if (process && process->GetID() == pid)
248 {
249 target_sp = *pos;
250 break;
251 }
252 }
253 return target_sp;
254}
255
256
257TargetSP
258TargetList::FindTargetWithProcess (Process *process) const
259{
260 TargetSP target_sp;
261 if (process)
262 {
263 Mutex::Locker locker(m_target_list_mutex);
264 collection::const_iterator pos, end = m_target_list.end();
265 for (pos = m_target_list.begin(); pos != end; ++pos)
266 {
267 if (process == (*pos)->GetProcessSP().get())
268 {
269 target_sp = *pos;
270 break;
271 }
272 }
273 }
274 return target_sp;
275}
276
277TargetSP
278TargetList::GetTargetSP (Target *target) const
279{
280 TargetSP target_sp;
281 if (target)
282 {
283 Mutex::Locker locker(m_target_list_mutex);
284 collection::const_iterator pos, end = m_target_list.end();
285 for (pos = m_target_list.begin(); pos != end; ++pos)
286 {
287 if (target == (*pos).get())
288 {
289 target_sp = *pos;
290 break;
291 }
292 }
293 }
294 return target_sp;
295}
296
297uint32_t
298TargetList::SendAsyncInterrupt (lldb::pid_t pid)
299{
300 uint32_t num_async_interrupts_sent = 0;
301
302 if (pid != LLDB_INVALID_PROCESS_ID)
303 {
304 TargetSP target_sp(FindTargetWithProcessID (pid));
305 if (target_sp.get())
306 {
307 Process* process = target_sp->GetProcessSP().get();
308 if (process)
309 {
310 process->BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
311 ++num_async_interrupts_sent;
312 }
313 }
314 }
315 else
316 {
317 // We don't have a valid pid to broadcast to, so broadcast to the target
318 // list's async broadcaster...
319 BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
320 }
321
322 return num_async_interrupts_sent;
323}
324
325uint32_t
326TargetList::SignalIfRunning (lldb::pid_t pid, int signo)
327{
328 uint32_t num_signals_sent = 0;
329 Process *process = NULL;
330 if (pid == LLDB_INVALID_PROCESS_ID)
331 {
332 // Signal all processes with signal
333 Mutex::Locker locker(m_target_list_mutex);
334 collection::iterator pos, end = m_target_list.end();
335 for (pos = m_target_list.begin(); pos != end; ++pos)
336 {
337 process = (*pos)->GetProcessSP().get();
338 if (process)
339 {
340 if (process->IsAlive())
341 {
342 ++num_signals_sent;
343 process->Signal (signo);
344 }
345 }
346 }
347 }
348 else
349 {
350 // Signal a specific process with signal
351 TargetSP target_sp(FindTargetWithProcessID (pid));
352 if (target_sp.get())
353 {
354 process = target_sp->GetProcessSP().get();
355 if (process)
356 {
357 if (process->IsAlive())
358 {
359 ++num_signals_sent;
360 process->Signal (signo);
361 }
362 }
363 }
364 }
365 return num_signals_sent;
366}
367
368int
369TargetList::GetNumTargets () const
370{
371 Mutex::Locker locker (m_target_list_mutex);
372 return m_target_list.size();
373}
374
375lldb::TargetSP
376TargetList::GetTargetAtIndex (uint32_t idx) const
377{
378 TargetSP target_sp;
379 Mutex::Locker locker (m_target_list_mutex);
380 if (idx < m_target_list.size())
381 target_sp = m_target_list[idx];
382 return target_sp;
383}
384
385uint32_t
Jim Ingham2976d002010-08-26 21:32:51 +0000386TargetList::SetSelectedTarget (Target* target)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000387{
388 Mutex::Locker locker (m_target_list_mutex);
389 collection::const_iterator pos,
390 begin = m_target_list.begin(),
391 end = m_target_list.end();
392 for (pos = begin; pos != end; ++pos)
393 {
394 if (pos->get() == target)
395 {
Jim Ingham2976d002010-08-26 21:32:51 +0000396 m_selected_target_idx = std::distance (begin, pos);
397 return m_selected_target_idx;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000398 }
399 }
Jim Ingham2976d002010-08-26 21:32:51 +0000400 m_selected_target_idx = 0;
401 return m_selected_target_idx;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000402}
403
404lldb::TargetSP
Jim Ingham2976d002010-08-26 21:32:51 +0000405TargetList::GetSelectedTarget ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000406{
407 Mutex::Locker locker (m_target_list_mutex);
Jim Ingham2976d002010-08-26 21:32:51 +0000408 if (m_selected_target_idx >= m_target_list.size())
409 m_selected_target_idx = 0;
410 return GetTargetAtIndex (m_selected_target_idx);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000411}