blob: ff9e8558ccd2731ce3c6084035cae515d8374d0a [file] [log] [blame]
Chris Lattner24943d22010-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 Malead891f9b2012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
11
Chris Lattner24943d22010-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 Claytonb1888f22011-03-19 01:12:21 +000017#include "lldb/Core/Debugger.h"
Chris Lattner24943d22010-06-08 16:52:24 +000018#include "lldb/Core/Event.h"
Greg Clayton49ce8962012-08-29 21:13:06 +000019#include "lldb/Core/Module.h"
Chris Lattner24943d22010-06-08 16:52:24 +000020#include "lldb/Core/State.h"
21#include "lldb/Core/Timer.h"
22#include "lldb/Host/Host.h"
Greg Claytonb1db6582012-03-20 18:34:04 +000023#include "lldb/Interpreter/CommandInterpreter.h"
Greg Clayton3e8c25f2011-09-24 00:52:29 +000024#include "lldb/Interpreter/OptionGroupPlatform.h"
Greg Claytone4b9c1f2011-03-08 22:40:15 +000025#include "lldb/Target/Platform.h"
Chris Lattner24943d22010-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 Ingham5a15e692012-02-16 06:50:00 +000032ConstString &
33TargetList::GetStaticBroadcasterClass ()
34{
35 static ConstString class_name ("lldb.targetList");
36 return class_name;
37}
Chris Lattner24943d22010-06-08 16:52:24 +000038
39//----------------------------------------------------------------------
40// TargetList constructor
41//----------------------------------------------------------------------
Jim Ingham5a15e692012-02-16 06:50:00 +000042TargetList::TargetList(Debugger &debugger) :
Jim Ingham94a5d0d2012-10-10 18:32:14 +000043 Broadcaster(&debugger, TargetList::GetStaticBroadcasterClass().AsCString()),
Chris Lattner24943d22010-06-08 16:52:24 +000044 m_target_list(),
45 m_target_list_mutex (Mutex::eMutexTypeRecursive),
Jim Inghamc8332952010-08-26 21:32:51 +000046 m_selected_target_idx (0)
Chris Lattner24943d22010-06-08 16:52:24 +000047{
Jim Ingham5a15e692012-02-16 06:50:00 +000048 CheckInWithManager();
Chris Lattner24943d22010-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 Clayton3e8c25f2011-09-24 00:52:29 +000061TargetList::CreateTarget (Debugger &debugger,
Greg Claytoned0a0fb2012-10-18 16:33:33 +000062 const char *user_exe_path,
Greg Clayton3e8c25f2011-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 Clayton3e8c25f2011-09-24 00:52:29 +000070
Johnny Chen94113c42012-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 Claytonb170aee2012-05-08 01:45:38 +000074 const ArchSpec arch(triple_cstr);
75 if (triple_cstr && triple_cstr[0])
Greg Clayton3e8c25f2011-09-24 00:52:29 +000076 {
Greg Clayton3e8c25f2011-09-24 00:52:29 +000077 if (!arch.IsValid())
78 {
Greg Clayton9c236732011-10-26 00:56:27 +000079 error.SetErrorStringWithFormat("invalid triple '%s'", triple_cstr);
Greg Clayton3e8c25f2011-09-24 00:52:29 +000080 return error;
81 }
82 }
Greg Claytonb1db6582012-03-20 18:34:04 +000083
Greg Claytonb170aee2012-05-08 01:45:38 +000084 ArchSpec platform_arch(arch);
Greg Claytonb1db6582012-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 Claytonb170aee2012-05-08 01:45:38 +000094 error,
95 platform_arch);
Greg Claytonb1db6582012-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 Claytonb170aee2012-05-08 01:45:38 +0000107 if (arch.IsValid() && !platform_sp->IsCompatibleArchitecture(arch, &platform_arch))
Greg Claytonb1db6582012-03-20 18:34:04 +0000108 {
Greg Claytonb170aee2012-05-08 01:45:38 +0000109 platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch);
Greg Claytonb1db6582012-03-20 18:34:04 +0000110 }
111 }
Greg Claytonb170aee2012-05-08 01:45:38 +0000112
113 if (!platform_arch.IsValid())
114 platform_arch = arch;
Greg Claytonb1db6582012-03-20 18:34:04 +0000115
Greg Clayton3e8c25f2011-09-24 00:52:29 +0000116 error = TargetList::CreateTarget (debugger,
Greg Claytoned0a0fb2012-10-18 16:33:33 +0000117 user_exe_path,
Greg Claytonb170aee2012-05-08 01:45:38 +0000118 platform_arch,
Greg Clayton3e8c25f2011-09-24 00:52:29 +0000119 get_dependent_files,
120 platform_sp,
121 target_sp);
122 return error;
123}
124
125Error
Greg Claytoned0a0fb2012-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 Lattner24943d22010-06-08 16:52:24 +0000132{
133 Timer scoped_timer (__PRETTY_FUNCTION__,
Greg Claytoned0a0fb2012-10-18 16:33:33 +0000134 "TargetList::CreateTarget (file = '%s', arch = '%s')",
135 user_exe_path,
Greg Claytonb170aee2012-05-08 01:45:38 +0000136 specified_arch.GetArchitectureName());
Jim Ingham7508e732010-08-09 23:31:02 +0000137 Error error;
Greg Claytonb1888f22011-03-19 01:12:21 +0000138
Greg Claytonb170aee2012-05-08 01:45:38 +0000139 ArchSpec arch(specified_arch);
140
141 if (platform_sp)
142 {
143 if (arch.IsValid())
144 {
145 if (!platform_sp->IsCompatibleArchitecture(arch))
146 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 Ingham7508e732010-08-09 23:31:02 +0000153
Greg Claytonb170aee2012-05-08 01:45:38 +0000154 if (!platform_sp)
155 platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
156
Greg Clayton7f206ba2012-06-05 21:17:09 +0000157 if (!arch.IsValid())
158 arch = specified_arch;
Greg Clayton7f206ba2012-06-05 21:17:09 +0000159
Greg Claytoned0a0fb2012-10-18 16:33:33 +0000160 FileSpec file (user_exe_path, false);
Greg Claytonfb467722012-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 Claytone4b9c1f2011-03-08 22:40:15 +0000164 if (file)
Jim Ingham7508e732010-08-09 23:31:02 +0000165 {
Greg Claytonfb467722012-10-25 22:45:35 +0000166 if (file.GetFileType() == FileSpec::eFileTypeDirectory)
167 user_exe_path_is_bundle = true;
168
Greg Claytoned0a0fb2012-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;
181 file.SetFile(cwd_user_exe_path.c_str(), false);
182 }
183 }
184 }
185
Jim Ingham7508e732010-08-09 23:31:02 +0000186 ModuleSP exe_module_sp;
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000187 if (platform_sp)
Greg Clayton9ce95382012-02-13 23:10:39 +0000188 {
189 FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
Greg Claytonb170aee2012-05-08 01:45:38 +0000190 error = platform_sp->ResolveExecutable (file,
191 arch,
Greg Clayton9ce95382012-02-13 23:10:39 +0000192 exe_module_sp,
193 executable_search_paths.GetSize() ? &executable_search_paths : NULL);
194 }
Chris Lattner24943d22010-06-08 16:52:24 +0000195
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000196 if (error.Success() && exe_module_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000197 {
Jim Ingham7508e732010-08-09 23:31:02 +0000198 if (exe_module_sp->GetObjectFile() == NULL)
199 {
Greg Claytonfa2f48b2010-12-08 04:55:11 +0000200 if (arch.IsValid())
201 {
202 error.SetErrorStringWithFormat("\"%s%s%s\" doesn't contain architecture %s",
203 file.GetDirectory().AsCString(),
204 file.GetDirectory() ? "/" : "",
205 file.GetFilename().AsCString(),
Greg Clayton940b1032011-02-23 00:35:02 +0000206 arch.GetArchitectureName());
Greg Claytonfa2f48b2010-12-08 04:55:11 +0000207 }
208 else
209 {
210 error.SetErrorStringWithFormat("unsupported file type \"%s%s%s\"",
211 file.GetDirectory().AsCString(),
212 file.GetDirectory() ? "/" : "",
213 file.GetFilename().AsCString());
214 }
Jim Ingham7508e732010-08-09 23:31:02 +0000215 return error;
216 }
Greg Clayton24bc5d92011-03-30 18:16:51 +0000217 target_sp.reset(new Target(debugger, arch, platform_sp));
Jim Ingham7508e732010-08-09 23:31:02 +0000218 target_sp->SetExecutableModule (exe_module_sp, get_dependent_files);
Greg Claytonfb467722012-10-25 22:45:35 +0000219 if (user_exe_path_is_bundle)
220 exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path, sizeof(resolved_bundle_exe_path));
Chris Lattner24943d22010-06-08 16:52:24 +0000221 }
Jim Ingham7508e732010-08-09 23:31:02 +0000222 }
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000223 else
Jim Ingham7508e732010-08-09 23:31:02 +0000224 {
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000225 // No file was specified, just create an empty target with any arch
226 // if a valid arch was specified
Greg Clayton24bc5d92011-03-30 18:16:51 +0000227 target_sp.reset(new Target(debugger, arch, platform_sp));
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000228 }
229
230 if (target_sp)
231 {
Greg Claytonfb467722012-10-25 22:45:35 +0000232 // Set argv0 with what the user typed, unless the user specified a
233 // directory. If the user specified a directory, then it is probably a
234 // bundle that was resolved and we need to use the resolved bundle path
Greg Claytoned0a0fb2012-10-18 16:33:33 +0000235 if (user_exe_path)
236 {
237 // Use exactly what the user typed as the first argument when we exec or posix_spawn
Greg Claytonfb467722012-10-25 22:45:35 +0000238 if (user_exe_path_is_bundle && resolved_bundle_exe_path[0])
239 {
240 target_sp->SetArg0 (resolved_bundle_exe_path);
241 }
242 else
243 {
244 // Just use what the user typed
245 target_sp->SetArg0 (user_exe_path);
246 }
Greg Claytoned0a0fb2012-10-18 16:33:33 +0000247 }
248 if (file.GetDirectory())
249 {
250 FileSpec file_dir;
251 file_dir.GetDirectory() = file.GetDirectory();
252 target_sp->GetExecutableSearchPaths ().Append (file_dir);
253 }
Jim Ingham7508e732010-08-09 23:31:02 +0000254 Mutex::Locker locker(m_target_list_mutex);
Jim Inghamc8332952010-08-26 21:32:51 +0000255 m_selected_target_idx = m_target_list.size();
Jim Ingham7508e732010-08-09 23:31:02 +0000256 m_target_list.push_back(target_sp);
Greg Claytoned0a0fb2012-10-18 16:33:33 +0000257
258
Jim Ingham7508e732010-08-09 23:31:02 +0000259 }
Chris Lattner24943d22010-06-08 16:52:24 +0000260
Chris Lattner24943d22010-06-08 16:52:24 +0000261 return error;
262}
263
264bool
265TargetList::DeleteTarget (TargetSP &target_sp)
266{
267 Mutex::Locker locker(m_target_list_mutex);
268 collection::iterator pos, end = m_target_list.end();
269
270 for (pos = m_target_list.begin(); pos != end; ++pos)
271 {
272 if (pos->get() == target_sp.get())
273 {
274 m_target_list.erase(pos);
275 return true;
276 }
277 }
278 return false;
279}
280
281
282TargetSP
283TargetList::FindTargetWithExecutableAndArchitecture
284(
285 const FileSpec &exe_file_spec,
286 const ArchSpec *exe_arch_ptr
287) const
288{
289 Mutex::Locker locker (m_target_list_mutex);
290 TargetSP target_sp;
291 bool full_match = exe_file_spec.GetDirectory();
292
293 collection::const_iterator pos, end = m_target_list.end();
294 for (pos = m_target_list.begin(); pos != end; ++pos)
295 {
Greg Clayton5beb99d2011-08-11 02:48:45 +0000296 Module *exe_module = (*pos)->GetExecutableModulePointer();
Chris Lattner24943d22010-06-08 16:52:24 +0000297
Greg Clayton5beb99d2011-08-11 02:48:45 +0000298 if (exe_module)
Chris Lattner24943d22010-06-08 16:52:24 +0000299 {
Greg Clayton5beb99d2011-08-11 02:48:45 +0000300 if (FileSpec::Equal (exe_file_spec, exe_module->GetFileSpec(), full_match))
Chris Lattner24943d22010-06-08 16:52:24 +0000301 {
302 if (exe_arch_ptr)
303 {
Greg Clayton5beb99d2011-08-11 02:48:45 +0000304 if (*exe_arch_ptr != exe_module->GetArchitecture())
Chris Lattner24943d22010-06-08 16:52:24 +0000305 continue;
306 }
307 target_sp = *pos;
308 break;
309 }
310 }
311 }
312 return target_sp;
313}
314
315TargetSP
316TargetList::FindTargetWithProcessID (lldb::pid_t pid) const
317{
318 Mutex::Locker locker(m_target_list_mutex);
319 TargetSP target_sp;
320 collection::const_iterator pos, end = m_target_list.end();
321 for (pos = m_target_list.begin(); pos != end; ++pos)
322 {
323 Process* process = (*pos)->GetProcessSP().get();
324 if (process && process->GetID() == pid)
325 {
326 target_sp = *pos;
327 break;
328 }
329 }
330 return target_sp;
331}
332
333
334TargetSP
335TargetList::FindTargetWithProcess (Process *process) const
336{
337 TargetSP target_sp;
338 if (process)
339 {
340 Mutex::Locker locker(m_target_list_mutex);
341 collection::const_iterator pos, end = m_target_list.end();
342 for (pos = m_target_list.begin(); pos != end; ++pos)
343 {
344 if (process == (*pos)->GetProcessSP().get())
345 {
346 target_sp = *pos;
347 break;
348 }
349 }
350 }
351 return target_sp;
352}
353
354TargetSP
355TargetList::GetTargetSP (Target *target) const
356{
357 TargetSP target_sp;
358 if (target)
359 {
360 Mutex::Locker locker(m_target_list_mutex);
361 collection::const_iterator pos, end = m_target_list.end();
362 for (pos = m_target_list.begin(); pos != end; ++pos)
363 {
364 if (target == (*pos).get())
365 {
366 target_sp = *pos;
367 break;
368 }
369 }
370 }
371 return target_sp;
372}
373
374uint32_t
375TargetList::SendAsyncInterrupt (lldb::pid_t pid)
376{
377 uint32_t num_async_interrupts_sent = 0;
378
379 if (pid != LLDB_INVALID_PROCESS_ID)
380 {
381 TargetSP target_sp(FindTargetWithProcessID (pid));
382 if (target_sp.get())
383 {
384 Process* process = target_sp->GetProcessSP().get();
385 if (process)
386 {
Jim Ingham5d90ade2012-07-27 23:57:19 +0000387 process->SendAsyncInterrupt();
Chris Lattner24943d22010-06-08 16:52:24 +0000388 ++num_async_interrupts_sent;
389 }
390 }
391 }
392 else
393 {
394 // We don't have a valid pid to broadcast to, so broadcast to the target
395 // list's async broadcaster...
396 BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
397 }
398
399 return num_async_interrupts_sent;
400}
401
402uint32_t
403TargetList::SignalIfRunning (lldb::pid_t pid, int signo)
404{
405 uint32_t num_signals_sent = 0;
406 Process *process = NULL;
407 if (pid == LLDB_INVALID_PROCESS_ID)
408 {
409 // Signal all processes with signal
410 Mutex::Locker locker(m_target_list_mutex);
411 collection::iterator pos, end = m_target_list.end();
412 for (pos = m_target_list.begin(); pos != end; ++pos)
413 {
414 process = (*pos)->GetProcessSP().get();
415 if (process)
416 {
417 if (process->IsAlive())
418 {
419 ++num_signals_sent;
420 process->Signal (signo);
421 }
422 }
423 }
424 }
425 else
426 {
427 // Signal a specific process with signal
428 TargetSP target_sp(FindTargetWithProcessID (pid));
429 if (target_sp.get())
430 {
431 process = target_sp->GetProcessSP().get();
432 if (process)
433 {
434 if (process->IsAlive())
435 {
436 ++num_signals_sent;
437 process->Signal (signo);
438 }
439 }
440 }
441 }
442 return num_signals_sent;
443}
444
445int
446TargetList::GetNumTargets () const
447{
448 Mutex::Locker locker (m_target_list_mutex);
449 return m_target_list.size();
450}
451
452lldb::TargetSP
453TargetList::GetTargetAtIndex (uint32_t idx) const
454{
455 TargetSP target_sp;
456 Mutex::Locker locker (m_target_list_mutex);
457 if (idx < m_target_list.size())
458 target_sp = m_target_list[idx];
459 return target_sp;
460}
461
462uint32_t
Jim Inghamf92ddcc2012-05-08 23:06:07 +0000463TargetList::GetIndexOfTarget (lldb::TargetSP target_sp) const
464{
465 Mutex::Locker locker (m_target_list_mutex);
466 size_t num_targets = m_target_list.size();
467 for (size_t idx = 0; idx < num_targets; idx++)
468 {
469 if (target_sp == m_target_list[idx])
470 return idx;
471 }
472 return UINT32_MAX;
473}
474
475uint32_t
Jim Inghamc8332952010-08-26 21:32:51 +0000476TargetList::SetSelectedTarget (Target* target)
Chris Lattner24943d22010-06-08 16:52:24 +0000477{
478 Mutex::Locker locker (m_target_list_mutex);
479 collection::const_iterator pos,
480 begin = m_target_list.begin(),
481 end = m_target_list.end();
482 for (pos = begin; pos != end; ++pos)
483 {
484 if (pos->get() == target)
485 {
Jim Inghamc8332952010-08-26 21:32:51 +0000486 m_selected_target_idx = std::distance (begin, pos);
487 return m_selected_target_idx;
Chris Lattner24943d22010-06-08 16:52:24 +0000488 }
489 }
Jim Inghamc8332952010-08-26 21:32:51 +0000490 m_selected_target_idx = 0;
491 return m_selected_target_idx;
Chris Lattner24943d22010-06-08 16:52:24 +0000492}
493
494lldb::TargetSP
Jim Inghamc8332952010-08-26 21:32:51 +0000495TargetList::GetSelectedTarget ()
Chris Lattner24943d22010-06-08 16:52:24 +0000496{
497 Mutex::Locker locker (m_target_list_mutex);
Jim Inghamc8332952010-08-26 21:32:51 +0000498 if (m_selected_target_idx >= m_target_list.size())
499 m_selected_target_idx = 0;
500 return GetTargetAtIndex (m_selected_target_idx);
Chris Lattner24943d22010-06-08 16:52:24 +0000501}