TargetList.cpp revision ed0a0fbd021e44727469d6fa20cc337c58bd04c3
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/Debugger.h"
16#include "lldb/Core/Event.h"
17#include "lldb/Core/Module.h"
18#include "lldb/Core/State.h"
19#include "lldb/Core/Timer.h"
20#include "lldb/Host/Host.h"
21#include "lldb/Interpreter/CommandInterpreter.h"
22#include "lldb/Interpreter/OptionGroupPlatform.h"
23#include "lldb/Target/Platform.h"
24#include "lldb/Target/Process.h"
25#include "lldb/Target/TargetList.h"
26
27using namespace lldb;
28using namespace lldb_private;
29
30ConstString &
31TargetList::GetStaticBroadcasterClass ()
32{
33    static ConstString class_name ("lldb.targetList");
34    return class_name;
35}
36
37//----------------------------------------------------------------------
38// TargetList constructor
39//----------------------------------------------------------------------
40TargetList::TargetList(Debugger &debugger) :
41    Broadcaster(&debugger, TargetList::GetStaticBroadcasterClass().AsCString()),
42    m_target_list(),
43    m_target_list_mutex (Mutex::eMutexTypeRecursive),
44    m_selected_target_idx (0)
45{
46    CheckInWithManager();
47}
48
49//----------------------------------------------------------------------
50// Destructor
51//----------------------------------------------------------------------
52TargetList::~TargetList()
53{
54    Mutex::Locker locker(m_target_list_mutex);
55    m_target_list.clear();
56}
57
58Error
59TargetList::CreateTarget (Debugger &debugger,
60                          const char *user_exe_path,
61                          const char *triple_cstr,
62                          bool get_dependent_files,
63                          const OptionGroupPlatform *platform_options,
64                          TargetSP &target_sp)
65{
66    Error error;
67    PlatformSP platform_sp;
68
69    // This is purposely left empty unless it is specified by triple_cstr.
70    // If not initialized via triple_cstr, then the currently selected platform
71    // will set the architecture correctly.
72    const ArchSpec arch(triple_cstr);
73    if (triple_cstr && triple_cstr[0])
74    {
75        if (!arch.IsValid())
76        {
77            error.SetErrorStringWithFormat("invalid triple '%s'", triple_cstr);
78            return error;
79        }
80    }
81
82    ArchSpec platform_arch(arch);
83    CommandInterpreter &interpreter = debugger.GetCommandInterpreter();
84    if (platform_options)
85    {
86        if (platform_options->PlatformWasSpecified ())
87        {
88            const bool select_platform = true;
89            platform_sp = platform_options->CreatePlatformWithOptions (interpreter,
90                                                                       arch,
91                                                                       select_platform,
92                                                                       error,
93                                                                       platform_arch);
94            if (!platform_sp)
95                return error;
96        }
97    }
98
99    if (!platform_sp)
100    {
101        // Get the current platform and make sure it is compatible with the
102        // current architecture if we have a valid architecture.
103        platform_sp = debugger.GetPlatformList().GetSelectedPlatform ();
104
105        if (arch.IsValid() && !platform_sp->IsCompatibleArchitecture(arch, &platform_arch))
106        {
107            platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch);
108        }
109    }
110
111    if (!platform_arch.IsValid())
112        platform_arch = arch;
113
114    error = TargetList::CreateTarget (debugger,
115                                      user_exe_path,
116                                      platform_arch,
117                                      get_dependent_files,
118                                      platform_sp,
119                                      target_sp);
120    return error;
121}
122
123Error
124TargetList::CreateTarget (Debugger &debugger,
125                          const char *user_exe_path,
126                          const ArchSpec& specified_arch,
127                          bool get_dependent_files,
128                          PlatformSP &platform_sp,
129                          TargetSP &target_sp)
130{
131    Timer scoped_timer (__PRETTY_FUNCTION__,
132                        "TargetList::CreateTarget (file = '%s', arch = '%s')",
133                        user_exe_path,
134                        specified_arch.GetArchitectureName());
135    Error error;
136
137    ArchSpec arch(specified_arch);
138
139    if (platform_sp)
140    {
141        if (arch.IsValid())
142        {
143            if (!platform_sp->IsCompatibleArchitecture(arch))
144                platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
145        }
146    }
147    else if (arch.IsValid())
148    {
149        platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
150    }
151
152    if (!platform_sp)
153        platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
154
155    if (!arch.IsValid())
156        arch = specified_arch;
157
158    FileSpec file (user_exe_path, false);
159    if (file)
160    {
161        if (file.IsRelativeToCurrentWorkingDirectory())
162        {
163            // Ignore paths that start with "./" and "../"
164            if (!((user_exe_path[0] == '.' && user_exe_path[1] == '/') ||
165                  (user_exe_path[0] == '.' && user_exe_path[1] == '.' && user_exe_path[2] == '/')))
166            {
167                char cwd[PATH_MAX];
168                if (getcwd (cwd, sizeof(cwd)))
169                {
170                    std::string cwd_user_exe_path (cwd);
171                    cwd_user_exe_path += '/';
172                    cwd_user_exe_path += user_exe_path;
173                    file.SetFile(cwd_user_exe_path.c_str(), false);
174                }
175            }
176        }
177
178        ModuleSP exe_module_sp;
179        if (platform_sp)
180        {
181            FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
182            error = platform_sp->ResolveExecutable (file,
183                                                    arch,
184                                                    exe_module_sp,
185                                                    executable_search_paths.GetSize() ? &executable_search_paths : NULL);
186        }
187
188        if (error.Success() && exe_module_sp)
189        {
190            if (exe_module_sp->GetObjectFile() == NULL)
191            {
192                if (arch.IsValid())
193                {
194                    error.SetErrorStringWithFormat("\"%s%s%s\" doesn't contain architecture %s",
195                                                   file.GetDirectory().AsCString(),
196                                                   file.GetDirectory() ? "/" : "",
197                                                   file.GetFilename().AsCString(),
198                                                   arch.GetArchitectureName());
199                }
200                else
201                {
202                    error.SetErrorStringWithFormat("unsupported file type \"%s%s%s\"",
203                                                   file.GetDirectory().AsCString(),
204                                                   file.GetDirectory() ? "/" : "",
205                                                   file.GetFilename().AsCString());
206                }
207                return error;
208            }
209            target_sp.reset(new Target(debugger, arch, platform_sp));
210            target_sp->SetExecutableModule (exe_module_sp, get_dependent_files);
211        }
212    }
213    else
214    {
215        // No file was specified, just create an empty target with any arch
216        // if a valid arch was specified
217        target_sp.reset(new Target(debugger, arch, platform_sp));
218    }
219
220    if (target_sp)
221    {
222        if (user_exe_path)
223        {
224            // Use exactly what the user typed as the first argument when we exec or posix_spawn
225            target_sp->SetArg0 (user_exe_path);
226        }
227        if (file.GetDirectory())
228        {
229            FileSpec file_dir;
230            file_dir.GetDirectory() = file.GetDirectory();
231            target_sp->GetExecutableSearchPaths ().Append (file_dir);
232        }
233        Mutex::Locker locker(m_target_list_mutex);
234        m_selected_target_idx = m_target_list.size();
235        m_target_list.push_back(target_sp);
236
237
238    }
239
240    return error;
241}
242
243bool
244TargetList::DeleteTarget (TargetSP &target_sp)
245{
246    Mutex::Locker locker(m_target_list_mutex);
247    collection::iterator pos, end = m_target_list.end();
248
249    for (pos = m_target_list.begin(); pos != end; ++pos)
250    {
251        if (pos->get() == target_sp.get())
252        {
253            m_target_list.erase(pos);
254            return true;
255        }
256    }
257    return false;
258}
259
260
261TargetSP
262TargetList::FindTargetWithExecutableAndArchitecture
263(
264    const FileSpec &exe_file_spec,
265    const ArchSpec *exe_arch_ptr
266) const
267{
268    Mutex::Locker locker (m_target_list_mutex);
269    TargetSP target_sp;
270    bool full_match = exe_file_spec.GetDirectory();
271
272    collection::const_iterator pos, end = m_target_list.end();
273    for (pos = m_target_list.begin(); pos != end; ++pos)
274    {
275        Module *exe_module = (*pos)->GetExecutableModulePointer();
276
277        if (exe_module)
278        {
279            if (FileSpec::Equal (exe_file_spec, exe_module->GetFileSpec(), full_match))
280            {
281                if (exe_arch_ptr)
282                {
283                    if (*exe_arch_ptr != exe_module->GetArchitecture())
284                        continue;
285                }
286                target_sp = *pos;
287                break;
288            }
289        }
290    }
291    return target_sp;
292}
293
294TargetSP
295TargetList::FindTargetWithProcessID (lldb::pid_t pid) const
296{
297    Mutex::Locker locker(m_target_list_mutex);
298    TargetSP target_sp;
299    collection::const_iterator pos, end = m_target_list.end();
300    for (pos = m_target_list.begin(); pos != end; ++pos)
301    {
302        Process* process = (*pos)->GetProcessSP().get();
303        if (process && process->GetID() == pid)
304        {
305            target_sp = *pos;
306            break;
307        }
308    }
309    return target_sp;
310}
311
312
313TargetSP
314TargetList::FindTargetWithProcess (Process *process) const
315{
316    TargetSP target_sp;
317    if (process)
318    {
319        Mutex::Locker locker(m_target_list_mutex);
320        collection::const_iterator pos, end = m_target_list.end();
321        for (pos = m_target_list.begin(); pos != end; ++pos)
322        {
323            if (process == (*pos)->GetProcessSP().get())
324            {
325                target_sp = *pos;
326                break;
327            }
328        }
329    }
330    return target_sp;
331}
332
333TargetSP
334TargetList::GetTargetSP (Target *target) const
335{
336    TargetSP target_sp;
337    if (target)
338    {
339        Mutex::Locker locker(m_target_list_mutex);
340        collection::const_iterator pos, end = m_target_list.end();
341        for (pos = m_target_list.begin(); pos != end; ++pos)
342        {
343            if (target == (*pos).get())
344            {
345                target_sp = *pos;
346                break;
347            }
348        }
349    }
350    return target_sp;
351}
352
353uint32_t
354TargetList::SendAsyncInterrupt (lldb::pid_t pid)
355{
356    uint32_t num_async_interrupts_sent = 0;
357
358    if (pid != LLDB_INVALID_PROCESS_ID)
359    {
360        TargetSP target_sp(FindTargetWithProcessID (pid));
361        if (target_sp.get())
362        {
363            Process* process = target_sp->GetProcessSP().get();
364            if (process)
365            {
366                process->SendAsyncInterrupt();
367                ++num_async_interrupts_sent;
368            }
369        }
370    }
371    else
372    {
373        // We don't have a valid pid to broadcast to, so broadcast to the target
374        // list's async broadcaster...
375        BroadcastEvent (Process::eBroadcastBitInterrupt, NULL);
376    }
377
378    return num_async_interrupts_sent;
379}
380
381uint32_t
382TargetList::SignalIfRunning (lldb::pid_t pid, int signo)
383{
384    uint32_t num_signals_sent = 0;
385    Process *process = NULL;
386    if (pid == LLDB_INVALID_PROCESS_ID)
387    {
388        // Signal all processes with signal
389        Mutex::Locker locker(m_target_list_mutex);
390        collection::iterator pos, end = m_target_list.end();
391        for (pos = m_target_list.begin(); pos != end; ++pos)
392        {
393            process = (*pos)->GetProcessSP().get();
394            if (process)
395            {
396                if (process->IsAlive())
397                {
398                    ++num_signals_sent;
399                    process->Signal (signo);
400                }
401            }
402        }
403    }
404    else
405    {
406        // Signal a specific process with signal
407        TargetSP target_sp(FindTargetWithProcessID (pid));
408        if (target_sp.get())
409        {
410            process = target_sp->GetProcessSP().get();
411            if (process)
412            {
413                if (process->IsAlive())
414                {
415                    ++num_signals_sent;
416                    process->Signal (signo);
417                }
418            }
419        }
420    }
421    return num_signals_sent;
422}
423
424int
425TargetList::GetNumTargets () const
426{
427    Mutex::Locker locker (m_target_list_mutex);
428    return m_target_list.size();
429}
430
431lldb::TargetSP
432TargetList::GetTargetAtIndex (uint32_t idx) const
433{
434    TargetSP target_sp;
435    Mutex::Locker locker (m_target_list_mutex);
436    if (idx < m_target_list.size())
437        target_sp = m_target_list[idx];
438    return target_sp;
439}
440
441uint32_t
442TargetList::GetIndexOfTarget (lldb::TargetSP target_sp) const
443{
444    Mutex::Locker locker (m_target_list_mutex);
445    size_t num_targets = m_target_list.size();
446    for (size_t idx = 0; idx < num_targets; idx++)
447    {
448        if (target_sp == m_target_list[idx])
449            return idx;
450    }
451    return UINT32_MAX;
452}
453
454uint32_t
455TargetList::SetSelectedTarget (Target* target)
456{
457    Mutex::Locker locker (m_target_list_mutex);
458    collection::const_iterator pos,
459        begin = m_target_list.begin(),
460        end = m_target_list.end();
461    for (pos = begin; pos != end; ++pos)
462    {
463        if (pos->get() == target)
464        {
465            m_selected_target_idx = std::distance (begin, pos);
466            return m_selected_target_idx;
467        }
468    }
469    m_selected_target_idx = 0;
470    return m_selected_target_idx;
471}
472
473lldb::TargetSP
474TargetList::GetSelectedTarget ()
475{
476    Mutex::Locker locker (m_target_list_mutex);
477    if (m_selected_target_idx >= m_target_list.size())
478        m_selected_target_idx = 0;
479    return GetTargetAtIndex (m_selected_target_idx);
480}
481