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