blob: be53e9253fcaa3acfa512dc1c5988136b259911b [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
Daniel Malea93a64302012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
11
Chris Lattner30fdc8d2010-06-08 16:52:24 +000012// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Core/Broadcaster.h"
Greg Claytonded470d2011-03-19 01:12:21 +000017#include "lldb/Core/Debugger.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018#include "lldb/Core/Event.h"
Greg Clayton1f746072012-08-29 21:13:06 +000019#include "lldb/Core/Module.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000020#include "lldb/Core/State.h"
21#include "lldb/Core/Timer.h"
22#include "lldb/Host/Host.h"
Greg Claytonb3a40ba2012-03-20 18:34:04 +000023#include "lldb/Interpreter/CommandInterpreter.h"
Greg Claytoncac9c5f2011-09-24 00:52:29 +000024#include "lldb/Interpreter/OptionGroupPlatform.h"
Greg Claytone996fd32011-03-08 22:40:15 +000025#include "lldb/Target/Platform.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000026#include "lldb/Target/Process.h"
27#include "lldb/Target/TargetList.h"
28
29using namespace lldb;
30using namespace lldb_private;
31
Jim Ingham4bddaeb2012-02-16 06:50:00 +000032ConstString &
33TargetList::GetStaticBroadcasterClass ()
34{
35 static ConstString class_name ("lldb.targetList");
36 return class_name;
37}
Chris Lattner30fdc8d2010-06-08 16:52:24 +000038
39//----------------------------------------------------------------------
40// TargetList constructor
41//----------------------------------------------------------------------
Jim Ingham4bddaeb2012-02-16 06:50:00 +000042TargetList::TargetList(Debugger &debugger) :
Jim Ingham4f465cf2012-10-10 18:32:14 +000043 Broadcaster(&debugger, TargetList::GetStaticBroadcasterClass().AsCString()),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000044 m_target_list(),
45 m_target_list_mutex (Mutex::eMutexTypeRecursive),
Jim Ingham2976d002010-08-26 21:32:51 +000046 m_selected_target_idx (0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000047{
Jim Ingham4bddaeb2012-02-16 06:50:00 +000048 CheckInWithManager();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000049}
50
51//----------------------------------------------------------------------
52// Destructor
53//----------------------------------------------------------------------
54TargetList::~TargetList()
55{
56 Mutex::Locker locker(m_target_list_mutex);
57 m_target_list.clear();
58}
59
60Error
Greg Claytoncac9c5f2011-09-24 00:52:29 +000061TargetList::CreateTarget (Debugger &debugger,
Greg Claytona0ca6602012-10-18 16:33:33 +000062 const char *user_exe_path,
Greg Claytoncac9c5f2011-09-24 00:52:29 +000063 const char *triple_cstr,
64 bool get_dependent_files,
65 const OptionGroupPlatform *platform_options,
66 TargetSP &target_sp)
67{
68 Error error;
69 PlatformSP platform_sp;
Greg Claytoncac9c5f2011-09-24 00:52:29 +000070
Johnny Chencdc21d42012-01-05 01:26:01 +000071 // This is purposely left empty unless it is specified by triple_cstr.
72 // If not initialized via triple_cstr, then the currently selected platform
73 // will set the architecture correctly.
Greg Clayton70512312012-05-08 01:45:38 +000074 const ArchSpec arch(triple_cstr);
75 if (triple_cstr && triple_cstr[0])
Greg Claytoncac9c5f2011-09-24 00:52:29 +000076 {
Greg Claytoncac9c5f2011-09-24 00:52:29 +000077 if (!arch.IsValid())
78 {
Greg Clayton86edbf42011-10-26 00:56:27 +000079 error.SetErrorStringWithFormat("invalid triple '%s'", triple_cstr);
Greg Claytoncac9c5f2011-09-24 00:52:29 +000080 return error;
81 }
82 }
Greg Claytonb3a40ba2012-03-20 18:34:04 +000083
Greg Clayton70512312012-05-08 01:45:38 +000084 ArchSpec platform_arch(arch);
Greg Claytonb3a40ba2012-03-20 18:34:04 +000085 CommandInterpreter &interpreter = debugger.GetCommandInterpreter();
86 if (platform_options)
87 {
88 if (platform_options->PlatformWasSpecified ())
89 {
90 const bool select_platform = true;
91 platform_sp = platform_options->CreatePlatformWithOptions (interpreter,
92 arch,
93 select_platform,
Greg Clayton70512312012-05-08 01:45:38 +000094 error,
95 platform_arch);
Greg Claytonb3a40ba2012-03-20 18:34:04 +000096 if (!platform_sp)
97 return error;
98 }
99 }
100
101 if (!platform_sp)
102 {
103 // Get the current platform and make sure it is compatible with the
104 // current architecture if we have a valid architecture.
105 platform_sp = debugger.GetPlatformList().GetSelectedPlatform ();
106
Greg Clayton1e0c8842013-01-11 20:49:54 +0000107 if (arch.IsValid() && !platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch))
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000108 {
Greg Clayton70512312012-05-08 01:45:38 +0000109 platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch);
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000110 }
111 }
Greg Clayton70512312012-05-08 01:45:38 +0000112
113 if (!platform_arch.IsValid())
114 platform_arch = arch;
Greg Claytonb3a40ba2012-03-20 18:34:04 +0000115
Greg Claytoncac9c5f2011-09-24 00:52:29 +0000116 error = TargetList::CreateTarget (debugger,
Greg Claytona0ca6602012-10-18 16:33:33 +0000117 user_exe_path,
Greg Clayton70512312012-05-08 01:45:38 +0000118 platform_arch,
Greg Claytoncac9c5f2011-09-24 00:52:29 +0000119 get_dependent_files,
120 platform_sp,
121 target_sp);
122 return error;
123}
124
125Error
Greg Claytona0ca6602012-10-18 16:33:33 +0000126TargetList::CreateTarget (Debugger &debugger,
127 const char *user_exe_path,
128 const ArchSpec& specified_arch,
129 bool get_dependent_files,
130 PlatformSP &platform_sp,
131 TargetSP &target_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000132{
133 Timer scoped_timer (__PRETTY_FUNCTION__,
Greg Claytona0ca6602012-10-18 16:33:33 +0000134 "TargetList::CreateTarget (file = '%s', arch = '%s')",
135 user_exe_path,
Greg Clayton70512312012-05-08 01:45:38 +0000136 specified_arch.GetArchitectureName());
Jim Ingham5aee1622010-08-09 23:31:02 +0000137 Error error;
Greg Claytonded470d2011-03-19 01:12:21 +0000138
Greg Clayton70512312012-05-08 01:45:38 +0000139 ArchSpec arch(specified_arch);
140
141 if (platform_sp)
142 {
143 if (arch.IsValid())
144 {
Greg Clayton1e0c8842013-01-11 20:49:54 +0000145 if (!platform_sp->IsCompatibleArchitecture(arch, false, NULL))
Greg Clayton70512312012-05-08 01:45:38 +0000146 platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
147 }
148 }
149 else if (arch.IsValid())
150 {
151 platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
152 }
Jim Ingham5aee1622010-08-09 23:31:02 +0000153
Greg Clayton70512312012-05-08 01:45:38 +0000154 if (!platform_sp)
155 platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
156
Greg Clayton8ae50eb2012-06-05 21:17:09 +0000157 if (!arch.IsValid())
158 arch = specified_arch;
Greg Clayton8ae50eb2012-06-05 21:17:09 +0000159
Greg Claytona0ca6602012-10-18 16:33:33 +0000160 FileSpec file (user_exe_path, false);
Greg Clayton82d79292012-10-25 22:45:35 +0000161 bool user_exe_path_is_bundle = false;
162 char resolved_bundle_exe_path[PATH_MAX];
163 resolved_bundle_exe_path[0] = '\0';
Greg Claytone996fd32011-03-08 22:40:15 +0000164 if (file)
Jim Ingham5aee1622010-08-09 23:31:02 +0000165 {
Greg Clayton82d79292012-10-25 22:45:35 +0000166 if (file.GetFileType() == FileSpec::eFileTypeDirectory)
167 user_exe_path_is_bundle = true;
168
Greg Claytona0ca6602012-10-18 16:33:33 +0000169 if (file.IsRelativeToCurrentWorkingDirectory())
170 {
171 // Ignore paths that start with "./" and "../"
172 if (!((user_exe_path[0] == '.' && user_exe_path[1] == '/') ||
173 (user_exe_path[0] == '.' && user_exe_path[1] == '.' && user_exe_path[2] == '/')))
174 {
175 char cwd[PATH_MAX];
176 if (getcwd (cwd, sizeof(cwd)))
177 {
178 std::string cwd_user_exe_path (cwd);
179 cwd_user_exe_path += '/';
180 cwd_user_exe_path += user_exe_path;
Greg Clayton9ff5aae2013-04-04 00:15:09 +0000181 FileSpec cwd_file (cwd_user_exe_path.c_str(), false);
182 if (cwd_file.Exists())
183 file = cwd_file;
Greg Claytona0ca6602012-10-18 16:33:33 +0000184 }
185 }
186 }
187
Jim Ingham5aee1622010-08-09 23:31:02 +0000188 ModuleSP exe_module_sp;
Greg Claytone996fd32011-03-08 22:40:15 +0000189 if (platform_sp)
Greg Claytonc859e2d2012-02-13 23:10:39 +0000190 {
191 FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
Greg Clayton70512312012-05-08 01:45:38 +0000192 error = platform_sp->ResolveExecutable (file,
193 arch,
Greg Claytonc859e2d2012-02-13 23:10:39 +0000194 exe_module_sp,
195 executable_search_paths.GetSize() ? &executable_search_paths : NULL);
196 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000197
Greg Claytone996fd32011-03-08 22:40:15 +0000198 if (error.Success() && exe_module_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000199 {
Jim Ingham5aee1622010-08-09 23:31:02 +0000200 if (exe_module_sp->GetObjectFile() == NULL)
201 {
Greg Claytonbc5cad62010-12-08 04:55:11 +0000202 if (arch.IsValid())
203 {
204 error.SetErrorStringWithFormat("\"%s%s%s\" doesn't contain architecture %s",
205 file.GetDirectory().AsCString(),
206 file.GetDirectory() ? "/" : "",
207 file.GetFilename().AsCString(),
Greg Clayton64195a22011-02-23 00:35:02 +0000208 arch.GetArchitectureName());
Greg Claytonbc5cad62010-12-08 04:55:11 +0000209 }
210 else
211 {
212 error.SetErrorStringWithFormat("unsupported file type \"%s%s%s\"",
213 file.GetDirectory().AsCString(),
214 file.GetDirectory() ? "/" : "",
215 file.GetFilename().AsCString());
216 }
Jim Ingham5aee1622010-08-09 23:31:02 +0000217 return error;
218 }
Greg Clayton32e0a752011-03-30 18:16:51 +0000219 target_sp.reset(new Target(debugger, arch, platform_sp));
Jim Ingham5aee1622010-08-09 23:31:02 +0000220 target_sp->SetExecutableModule (exe_module_sp, get_dependent_files);
Greg Clayton82d79292012-10-25 22:45:35 +0000221 if (user_exe_path_is_bundle)
222 exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path, sizeof(resolved_bundle_exe_path));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000223 }
Jim Ingham5aee1622010-08-09 23:31:02 +0000224 }
Greg Claytone996fd32011-03-08 22:40:15 +0000225 else
Jim Ingham5aee1622010-08-09 23:31:02 +0000226 {
Greg Claytone996fd32011-03-08 22:40:15 +0000227 // No file was specified, just create an empty target with any arch
228 // if a valid arch was specified
Greg Clayton32e0a752011-03-30 18:16:51 +0000229 target_sp.reset(new Target(debugger, arch, platform_sp));
Greg Claytone996fd32011-03-08 22:40:15 +0000230 }
231
232 if (target_sp)
233 {
Greg Clayton82d79292012-10-25 22:45:35 +0000234 // Set argv0 with what the user typed, unless the user specified a
235 // directory. If the user specified a directory, then it is probably a
236 // bundle that was resolved and we need to use the resolved bundle path
Greg Claytona0ca6602012-10-18 16:33:33 +0000237 if (user_exe_path)
238 {
239 // Use exactly what the user typed as the first argument when we exec or posix_spawn
Greg Clayton82d79292012-10-25 22:45:35 +0000240 if (user_exe_path_is_bundle && resolved_bundle_exe_path[0])
241 {
242 target_sp->SetArg0 (resolved_bundle_exe_path);
243 }
244 else
245 {
246 // Just use what the user typed
247 target_sp->SetArg0 (user_exe_path);
248 }
Greg Claytona0ca6602012-10-18 16:33:33 +0000249 }
250 if (file.GetDirectory())
251 {
252 FileSpec file_dir;
253 file_dir.GetDirectory() = file.GetDirectory();
254 target_sp->GetExecutableSearchPaths ().Append (file_dir);
255 }
Jim Ingham5aee1622010-08-09 23:31:02 +0000256 Mutex::Locker locker(m_target_list_mutex);
Jim Ingham2976d002010-08-26 21:32:51 +0000257 m_selected_target_idx = m_target_list.size();
Jim Ingham5aee1622010-08-09 23:31:02 +0000258 m_target_list.push_back(target_sp);
Greg Claytona0ca6602012-10-18 16:33:33 +0000259
260
Jim Ingham5aee1622010-08-09 23:31:02 +0000261 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000262
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000263 return error;
264}
265
266bool
267TargetList::DeleteTarget (TargetSP &target_sp)
268{
269 Mutex::Locker locker(m_target_list_mutex);
270 collection::iterator pos, end = m_target_list.end();
271
272 for (pos = m_target_list.begin(); pos != end; ++pos)
273 {
274 if (pos->get() == target_sp.get())
275 {
276 m_target_list.erase(pos);
277 return true;
278 }
279 }
280 return false;
281}
282
283
284TargetSP
285TargetList::FindTargetWithExecutableAndArchitecture
286(
287 const FileSpec &exe_file_spec,
288 const ArchSpec *exe_arch_ptr
289) const
290{
291 Mutex::Locker locker (m_target_list_mutex);
292 TargetSP target_sp;
293 bool full_match = exe_file_spec.GetDirectory();
294
295 collection::const_iterator pos, end = m_target_list.end();
296 for (pos = m_target_list.begin(); pos != end; ++pos)
297 {
Greg Claytonaa149cb2011-08-11 02:48:45 +0000298 Module *exe_module = (*pos)->GetExecutableModulePointer();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000299
Greg Claytonaa149cb2011-08-11 02:48:45 +0000300 if (exe_module)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000301 {
Greg Claytonaa149cb2011-08-11 02:48:45 +0000302 if (FileSpec::Equal (exe_file_spec, exe_module->GetFileSpec(), full_match))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000303 {
304 if (exe_arch_ptr)
305 {
Sean Callananbf4b7be2012-12-13 22:07:14 +0000306 if (!exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture()))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000307 continue;
308 }
309 target_sp = *pos;
310 break;
311 }
312 }
313 }
314 return target_sp;
315}
316
317TargetSP
318TargetList::FindTargetWithProcessID (lldb::pid_t pid) const
319{
320 Mutex::Locker locker(m_target_list_mutex);
321 TargetSP target_sp;
322 collection::const_iterator pos, end = m_target_list.end();
323 for (pos = m_target_list.begin(); pos != end; ++pos)
324 {
325 Process* process = (*pos)->GetProcessSP().get();
326 if (process && process->GetID() == pid)
327 {
328 target_sp = *pos;
329 break;
330 }
331 }
332 return target_sp;
333}
334
335
336TargetSP
337TargetList::FindTargetWithProcess (Process *process) const
338{
339 TargetSP target_sp;
340 if (process)
341 {
342 Mutex::Locker locker(m_target_list_mutex);
343 collection::const_iterator pos, end = m_target_list.end();
344 for (pos = m_target_list.begin(); pos != end; ++pos)
345 {
346 if (process == (*pos)->GetProcessSP().get())
347 {
348 target_sp = *pos;
349 break;
350 }
351 }
352 }
353 return target_sp;
354}
355
356TargetSP
357TargetList::GetTargetSP (Target *target) const
358{
359 TargetSP target_sp;
360 if (target)
361 {
362 Mutex::Locker locker(m_target_list_mutex);
363 collection::const_iterator pos, end = m_target_list.end();
364 for (pos = m_target_list.begin(); pos != end; ++pos)
365 {
366 if (target == (*pos).get())
367 {
368 target_sp = *pos;
369 break;
370 }
371 }
372 }
373 return target_sp;
374}
375
376uint32_t
377TargetList::SendAsyncInterrupt (lldb::pid_t pid)
378{
379 uint32_t num_async_interrupts_sent = 0;
380
381 if (pid != LLDB_INVALID_PROCESS_ID)
382 {
383 TargetSP target_sp(FindTargetWithProcessID (pid));
384 if (target_sp.get())
385 {
386 Process* process = target_sp->GetProcessSP().get();
387 if (process)
388 {
Jim Inghamcfc09352012-07-27 23:57:19 +0000389 process->SendAsyncInterrupt();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000390 ++num_async_interrupts_sent;
391 }
392 }
393 }
394 else
395 {
396 // We don't have a valid pid to broadcast to, so broadcast to the target
397 // list's async broadcaster...
398 BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
399 }
400
401 return num_async_interrupts_sent;
402}
403
404uint32_t
405TargetList::SignalIfRunning (lldb::pid_t pid, int signo)
406{
407 uint32_t num_signals_sent = 0;
408 Process *process = NULL;
409 if (pid == LLDB_INVALID_PROCESS_ID)
410 {
411 // Signal all processes with signal
412 Mutex::Locker locker(m_target_list_mutex);
413 collection::iterator pos, end = m_target_list.end();
414 for (pos = m_target_list.begin(); pos != end; ++pos)
415 {
416 process = (*pos)->GetProcessSP().get();
417 if (process)
418 {
419 if (process->IsAlive())
420 {
421 ++num_signals_sent;
422 process->Signal (signo);
423 }
424 }
425 }
426 }
427 else
428 {
429 // Signal a specific process with signal
430 TargetSP target_sp(FindTargetWithProcessID (pid));
431 if (target_sp.get())
432 {
433 process = target_sp->GetProcessSP().get();
434 if (process)
435 {
436 if (process->IsAlive())
437 {
438 ++num_signals_sent;
439 process->Signal (signo);
440 }
441 }
442 }
443 }
444 return num_signals_sent;
445}
446
447int
448TargetList::GetNumTargets () const
449{
450 Mutex::Locker locker (m_target_list_mutex);
451 return m_target_list.size();
452}
453
454lldb::TargetSP
455TargetList::GetTargetAtIndex (uint32_t idx) const
456{
457 TargetSP target_sp;
458 Mutex::Locker locker (m_target_list_mutex);
459 if (idx < m_target_list.size())
460 target_sp = m_target_list[idx];
461 return target_sp;
462}
463
464uint32_t
Jim Ingham8499e1a2012-05-08 23:06:07 +0000465TargetList::GetIndexOfTarget (lldb::TargetSP target_sp) const
466{
467 Mutex::Locker locker (m_target_list_mutex);
468 size_t num_targets = m_target_list.size();
469 for (size_t idx = 0; idx < num_targets; idx++)
470 {
471 if (target_sp == m_target_list[idx])
472 return idx;
473 }
474 return UINT32_MAX;
475}
476
477uint32_t
Jim Ingham2976d002010-08-26 21:32:51 +0000478TargetList::SetSelectedTarget (Target* target)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000479{
480 Mutex::Locker locker (m_target_list_mutex);
481 collection::const_iterator pos,
482 begin = m_target_list.begin(),
483 end = m_target_list.end();
484 for (pos = begin; pos != end; ++pos)
485 {
486 if (pos->get() == target)
487 {
Jim Ingham2976d002010-08-26 21:32:51 +0000488 m_selected_target_idx = std::distance (begin, pos);
489 return m_selected_target_idx;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000490 }
491 }
Jim Ingham2976d002010-08-26 21:32:51 +0000492 m_selected_target_idx = 0;
493 return m_selected_target_idx;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000494}
495
496lldb::TargetSP
Jim Ingham2976d002010-08-26 21:32:51 +0000497TargetList::GetSelectedTarget ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000498{
499 Mutex::Locker locker (m_target_list_mutex);
Jim Ingham2976d002010-08-26 21:32:51 +0000500 if (m_selected_target_idx >= m_target_list.size())
501 m_selected_target_idx = 0;
502 return GetTargetAtIndex (m_selected_target_idx);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000503}