1 //===-- SBTarget.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 #include "lldb/API/SBTarget.h"
11 
12 #include "lldb/lldb-public.h"
13 
14 #include "lldb/API/SBFileSpec.h"
15 #include "lldb/API/SBModule.h"
16 #include "lldb/API/SBStream.h"
17 #include "lldb/Breakpoint/BreakpointID.h"
18 #include "lldb/Breakpoint/BreakpointIDList.h"
19 #include "lldb/Breakpoint/BreakpointList.h"
20 #include "lldb/Breakpoint/BreakpointLocation.h"
21 #include "lldb/Core/Address.h"
22 #include "lldb/Core/AddressResolver.h"
23 #include "lldb/Core/AddressResolverName.h"
24 #include "lldb/Interpreter/Args.h"
25 #include "lldb/Core/ArchSpec.h"
26 #include "lldb/Core/Debugger.h"
27 #include "lldb/Core/Disassembler.h"
28 #include "lldb/Host/FileSpec.h"
29 #include "lldb/Core/Log.h"
30 #include "lldb/Core/RegularExpression.h"
31 #include "lldb/Core/SearchFilter.h"
32 #include "lldb/Core/STLUtils.h"
33 #include "lldb/Host/Host.h"
34 #include "lldb/Target/Process.h"
35 #include "lldb/Target/Target.h"
36 #include "lldb/Target/TargetList.h"
37 
38 #include "lldb/Interpreter/CommandReturnObject.h"
39 #include "../source/Commands/CommandObjectBreakpoint.h"
40 
41 #include "lldb/API/SBDebugger.h"
42 #include "lldb/API/SBProcess.h"
43 #include "lldb/API/SBListener.h"
44 #include "lldb/API/SBBreakpoint.h"
45 
46 using namespace lldb;
47 using namespace lldb_private;
48 
49 #define DEFAULT_DISASM_BYTE_SIZE 32
50 
51 //----------------------------------------------------------------------
52 // SBTarget constructor
53 //----------------------------------------------------------------------
54 SBTarget::SBTarget () :
55     m_opaque_sp ()
56 {
57 }
58 
59 SBTarget::SBTarget (const SBTarget& rhs) :
60     m_opaque_sp (rhs.m_opaque_sp)
61 {
62 }
63 
64 SBTarget::SBTarget(const TargetSP& target_sp) :
65     m_opaque_sp (target_sp)
66 {
67 }
68 
69 const SBTarget&
70 SBTarget::operator = (const SBTarget& rhs)
71 {
72     if (this != &rhs)
73         m_opaque_sp = rhs.m_opaque_sp;
74     return *this;
75 }
76 
77 //----------------------------------------------------------------------
78 // Destructor
79 //----------------------------------------------------------------------
80 SBTarget::~SBTarget()
81 {
82 }
83 
84 bool
85 SBTarget::IsValid () const
86 {
87     return m_opaque_sp.get() != NULL;
88 }
89 
90 SBProcess
91 SBTarget::GetProcess ()
92 {
93 
94     SBProcess sb_process;
95     if (m_opaque_sp)
96     {
97         Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
98         sb_process.SetProcess (m_opaque_sp->GetProcessSP());
99     }
100 
101     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
102     if (log)
103     {
104         log->Printf ("SBTarget(%p)::GetProcess () => SBProcess(%p)",
105                      m_opaque_sp.get(), sb_process.get());
106     }
107 
108     return sb_process;
109 }
110 
111 SBDebugger
112 SBTarget::GetDebugger () const
113 {
114     SBDebugger debugger;
115     if (m_opaque_sp)
116         debugger.reset (m_opaque_sp->GetDebugger().GetSP());
117     return debugger;
118 }
119 
120 SBProcess
121 SBTarget::LaunchSimple
122 (
123     char const **argv,
124     char const **envp,
125     const char *working_directory
126 )
127 {
128     char *stdin_path = NULL;
129     char *stdout_path = NULL;
130     char *stderr_path = NULL;
131     uint32_t launch_flags = 0;
132     bool stop_at_entry = false;
133     SBError error;
134     SBListener listener = GetDebugger().GetListener();
135     return Launch (listener,
136                    argv,
137                    envp,
138                    stdin_path,
139                    stdout_path,
140                    stderr_path,
141                    working_directory,
142                    launch_flags,
143                    stop_at_entry,
144                    error);
145 }
146 
147 SBProcess
148 SBTarget::Launch
149 (
150     SBListener &listener,
151     char const **argv,
152     char const **envp,
153     const char *stdin_path,
154     const char *stdout_path,
155     const char *stderr_path,
156     const char *working_directory,
157     uint32_t launch_flags,   // See LaunchFlags
158     bool stop_at_entry,
159     lldb::SBError& error
160 )
161 {
162     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
163 
164     if (log)
165     {
166         log->Printf ("SBTarget(%p)::Launch (argv=%p, envp=%p, stdin=%s, stdout=%s, stderr=%s, working-dir=%s, launch_flags=0x%x, stop_at_entry=%i, &error (%p))...",
167                      m_opaque_sp.get(),
168                      argv,
169                      envp,
170                      stdin_path ? stdin_path : "NULL",
171                      stdout_path ? stdout_path : "NULL",
172                      stderr_path ? stderr_path : "NULL",
173                      working_directory ? working_directory : "NULL",
174                      launch_flags,
175                      stop_at_entry,
176                      error.get());
177     }
178     SBProcess sb_process;
179     if (m_opaque_sp)
180     {
181         Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
182 
183         if (getenv("LLDB_LAUNCH_FLAG_DISABLE_ASLR"))
184             launch_flags |= eLaunchFlagDisableASLR;
185 
186         static const char *g_launch_tty = NULL;
187         static bool g_got_launch_tty = false;
188         if (!g_got_launch_tty)
189         {
190             // Get the LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY only once
191             g_got_launch_tty = true;
192             g_launch_tty = ::getenv ("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY");
193             if (g_launch_tty)
194             {
195                 // LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY is a path to a terminal to reuse
196                 // if the first character is '/', else it is a boolean value.
197                 if (g_launch_tty[0] != '/')
198                 {
199                     if (Args::StringToBoolean(g_launch_tty, false, NULL))
200                         g_launch_tty = "";
201                     else
202                         g_launch_tty = NULL;
203                 }
204             }
205         }
206 
207 //        if ((launch_flags & eLaunchFlagLaunchInTTY) || g_launch_tty)
208 //        {
209 //            ArchSpec arch (m_opaque_sp->GetArchitecture ());
210 //
211 //            Module *exe_module = m_opaque_sp->GetExecutableModule().get();
212 //            if (exe_module)
213 //            {
214 //                char exec_file_path[PATH_MAX];
215 //                exe_module->GetFileSpec().GetPath(exec_file_path, sizeof(exec_file_path));
216 //                if (exe_module->GetFileSpec().Exists())
217 //                {
218 //                    // Make a new argument vector
219 //                    std::vector<const char *> exec_path_plus_argv;
220 //                    // Append the resolved executable path
221 //                    exec_path_plus_argv.push_back (exec_file_path);
222 //
223 //                    // Push all args if there are any
224 //                    if (argv)
225 //                    {
226 //                        for (int i = 0; argv[i]; ++i)
227 //                            exec_path_plus_argv.push_back(argv[i]);
228 //                    }
229 //
230 //                    // Push a NULL to terminate the args.
231 //                    exec_path_plus_argv.push_back(NULL);
232 //
233 //
234 //                    const char *tty_name = NULL;
235 //                    if (g_launch_tty && g_launch_tty[0] == '/')
236 //                        tty_name = g_launch_tty;
237 //
238 //                    lldb::pid_t pid = Host::LaunchInNewTerminal (tty_name,
239 //                                                                 &exec_path_plus_argv[0],
240 //                                                                 envp,
241 //                                                                 working_directory,
242 //                                                                 &arch,
243 //                                                                 true,
244 //                                                                 launch_flags & eLaunchFlagDisableASLR);
245 //
246 //                    if (pid != LLDB_INVALID_PROCESS_ID)
247 //                    {
248 //                        sb_process = AttachToProcessWithID(listener, pid, error);
249 //                    }
250 //                    else
251 //                    {
252 //                        error.SetErrorStringWithFormat("failed to launch process in terminal");
253 //                    }
254 //                }
255 //                else
256 //                {
257 //                    error.SetErrorStringWithFormat("executable doesn't exist: \"%s\"", exec_file_path);
258 //                }
259 //            }
260 //            else
261 //            {
262 //                error.SetErrorStringWithFormat("invalid executable");
263 //            }
264 //        }
265 //        else
266         {
267             if (listener.IsValid())
268                 sb_process.SetProcess (m_opaque_sp->CreateProcess (listener.ref()));
269             else
270                 sb_process.SetProcess (m_opaque_sp->CreateProcess (m_opaque_sp->GetDebugger().GetListener()));
271 
272             if (sb_process.IsValid())
273             {
274 
275                 if (getenv("LLDB_LAUNCH_FLAG_DISABLE_STDIO"))
276                     launch_flags |= eLaunchFlagDisableSTDIO;
277 
278 
279                 error.SetError (sb_process->Launch (argv, envp, launch_flags, stdin_path, stdout_path, stderr_path, working_directory));
280                 if (error.Success())
281                 {
282                     // We we are stopping at the entry point, we can return now!
283                     if (stop_at_entry)
284                         return sb_process;
285 
286                     // Make sure we are stopped at the entry
287                     StateType state = sb_process->WaitForProcessToStop (NULL);
288                     if (state == eStateStopped)
289                     {
290                         // resume the process to skip the entry point
291                         error.SetError (sb_process->Resume());
292                         if (error.Success())
293                         {
294                             // If we are doing synchronous mode, then wait for the
295                             // process to stop yet again!
296                             if (m_opaque_sp->GetDebugger().GetAsyncExecution () == false)
297                                 sb_process->WaitForProcessToStop (NULL);
298                         }
299                     }
300                 }
301             }
302             else
303             {
304                 error.SetErrorString ("unable to create lldb_private::Process");
305             }
306         }
307     }
308     else
309     {
310         error.SetErrorString ("SBTarget is invalid");
311     }
312 
313     log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
314     if (log)
315     {
316         log->Printf ("SBTarget(%p)::Launch (...) => SBProceess(%p)",
317                      m_opaque_sp.get(), sb_process.get());
318     }
319 
320     return sb_process;
321 }
322 
323 
324 lldb::SBProcess
325 SBTarget::AttachToProcessWithID
326 (
327     SBListener &listener,
328     lldb::pid_t pid,// The process ID to attach to
329     SBError& error  // An error explaining what went wrong if attach fails
330 )
331 {
332     SBProcess sb_process;
333     if (m_opaque_sp)
334     {
335         Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
336         if (listener.IsValid())
337             sb_process.SetProcess (m_opaque_sp->CreateProcess (listener.ref()));
338         else
339             sb_process.SetProcess (m_opaque_sp->CreateProcess (m_opaque_sp->GetDebugger().GetListener()));
340 
341 
342         if (sb_process.IsValid())
343         {
344             error.SetError (sb_process->Attach (pid));
345         }
346         else
347         {
348             error.SetErrorString ("unable to create lldb_private::Process");
349         }
350     }
351     else
352     {
353         error.SetErrorString ("SBTarget is invalid");
354     }
355     return sb_process;
356 
357 }
358 
359 lldb::SBProcess
360 SBTarget::AttachToProcessWithName
361 (
362     SBListener &listener,
363     const char *name,   // basename of process to attach to
364     bool wait_for,      // if true wait for a new instance of "name" to be launched
365     SBError& error      // An error explaining what went wrong if attach fails
366 )
367 {
368     SBProcess sb_process;
369     if (m_opaque_sp)
370     {
371         Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
372 
373         if (listener.IsValid())
374             sb_process.SetProcess (m_opaque_sp->CreateProcess (listener.ref()));
375         else
376             sb_process.SetProcess (m_opaque_sp->CreateProcess (m_opaque_sp->GetDebugger().GetListener()));
377 
378         if (sb_process.IsValid())
379         {
380             error.SetError (sb_process->Attach (name, wait_for));
381         }
382         else
383         {
384             error.SetErrorString ("unable to create lldb_private::Process");
385         }
386     }
387     else
388     {
389         error.SetErrorString ("SBTarget is invalid");
390     }
391     return sb_process;
392 
393 }
394 
395 lldb::SBProcess
396 SBTarget::ConnectRemote
397 (
398     SBListener &listener,
399     const char *url,
400     const char *plugin_name,
401     SBError& error
402 )
403 {
404     SBProcess sb_process;
405     if (m_opaque_sp)
406     {
407         Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
408         if (listener.IsValid())
409             sb_process.SetProcess (m_opaque_sp->CreateProcess (listener.ref(), plugin_name));
410         else
411             sb_process.SetProcess (m_opaque_sp->CreateProcess (m_opaque_sp->GetDebugger().GetListener(), plugin_name));
412 
413 
414         if (sb_process.IsValid())
415         {
416             error.SetError (sb_process->ConnectRemote (url));
417         }
418         else
419         {
420             error.SetErrorString ("unable to create lldb_private::Process");
421         }
422     }
423     else
424     {
425         error.SetErrorString ("SBTarget is invalid");
426     }
427     return sb_process;
428 }
429 
430 SBFileSpec
431 SBTarget::GetExecutable ()
432 {
433 
434     SBFileSpec exe_file_spec;
435     if (m_opaque_sp)
436     {
437         ModuleSP exe_module_sp (m_opaque_sp->GetExecutableModule ());
438         if (exe_module_sp)
439             exe_file_spec.SetFileSpec (exe_module_sp->GetFileSpec());
440     }
441 
442     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
443     if (log)
444     {
445         log->Printf ("SBTarget(%p)::GetExecutable () => SBFileSpec(%p)",
446                      m_opaque_sp.get(), exe_file_spec.get());
447     }
448 
449     return exe_file_spec;
450 }
451 
452 
453 bool
454 SBTarget::DeleteTargetFromList (TargetList *list)
455 {
456     if (m_opaque_sp)
457         return list->DeleteTarget (m_opaque_sp);
458     else
459         return false;
460 }
461 
462 bool
463 SBTarget::operator == (const SBTarget &rhs) const
464 {
465     return m_opaque_sp.get() == rhs.m_opaque_sp.get();
466 }
467 
468 bool
469 SBTarget::operator != (const SBTarget &rhs) const
470 {
471     return m_opaque_sp.get() != rhs.m_opaque_sp.get();
472 }
473 
474 lldb_private::Target *
475 SBTarget::operator ->() const
476 {
477     return m_opaque_sp.get();
478 }
479 
480 lldb_private::Target *
481 SBTarget::get() const
482 {
483     return m_opaque_sp.get();
484 }
485 
486 void
487 SBTarget::reset (const lldb::TargetSP& target_sp)
488 {
489     m_opaque_sp = target_sp;
490 }
491 
492 bool
493 SBTarget::ResolveLoadAddress (lldb::addr_t vm_addr,
494                               lldb::SBAddress& addr)
495 {
496     if (m_opaque_sp)
497     {
498         Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
499         return m_opaque_sp->GetSectionLoadList().ResolveLoadAddress (vm_addr, *addr);
500     }
501 
502     addr->Clear();
503     return false;
504 }
505 
506 SBSymbolContext
507 SBTarget::ResolveSymbolContextForAddress (const SBAddress& addr, uint32_t resolve_scope)
508 {
509     SBSymbolContext sc;
510     if (m_opaque_sp)
511         m_opaque_sp->GetImages().ResolveSymbolContextForAddress (*addr, resolve_scope, sc.ref());
512     return sc;
513 }
514 
515 
516 SBBreakpoint
517 SBTarget::BreakpointCreateByLocation (const char *file, uint32_t line)
518 {
519     return SBBreakpoint(BreakpointCreateByLocation (SBFileSpec (file, false), line));
520 }
521 
522 SBBreakpoint
523 SBTarget::BreakpointCreateByLocation (const SBFileSpec &sb_file_spec, uint32_t line)
524 {
525     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
526 
527     SBBreakpoint sb_bp;
528     if (m_opaque_sp.get() && line != 0)
529     {
530         Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
531         *sb_bp = m_opaque_sp->CreateBreakpoint (NULL, *sb_file_spec, line, true, false);
532     }
533 
534     if (log)
535     {
536         SBStream sstr;
537         sb_bp.GetDescription (sstr);
538         char path[PATH_MAX];
539         sb_file_spec->GetPath (path, sizeof(path));
540         log->Printf ("SBTarget(%p)::BreakpointCreateByLocation ( %s:%u ) => SBBreakpoint(%p): %s",
541                      m_opaque_sp.get(),
542                      path,
543                      line,
544                      sb_bp.get(),
545                      sstr.GetData());
546     }
547 
548     return sb_bp;
549 }
550 
551 SBBreakpoint
552 SBTarget::BreakpointCreateByName (const char *symbol_name, const char *module_name)
553 {
554     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
555 
556     SBBreakpoint sb_bp;
557     if (m_opaque_sp.get() && symbol_name && symbol_name[0])
558     {
559         Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
560         if (module_name && module_name[0])
561         {
562             FileSpec module_file_spec(module_name, false);
563             *sb_bp = m_opaque_sp->CreateBreakpoint (&module_file_spec, symbol_name, eFunctionNameTypeFull | eFunctionNameTypeBase, false);
564         }
565         else
566         {
567             *sb_bp = m_opaque_sp->CreateBreakpoint (NULL, symbol_name, eFunctionNameTypeFull | eFunctionNameTypeBase, false);
568         }
569     }
570 
571     if (log)
572     {
573         log->Printf ("SBTarget(%p)::BreakpointCreateByName (symbol=\"%s\", module=\"%s\") => SBBreakpoint(%p)",
574                      m_opaque_sp.get(), symbol_name, module_name, sb_bp.get());
575     }
576 
577     return sb_bp;
578 }
579 
580 SBBreakpoint
581 SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *module_name)
582 {
583     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
584 
585     SBBreakpoint sb_bp;
586     if (m_opaque_sp.get() && symbol_name_regex && symbol_name_regex[0])
587     {
588         Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
589         RegularExpression regexp(symbol_name_regex);
590 
591         if (module_name && module_name[0])
592         {
593             FileSpec module_file_spec(module_name, false);
594 
595             *sb_bp = m_opaque_sp->CreateBreakpoint (&module_file_spec, regexp, false);
596         }
597         else
598         {
599             *sb_bp = m_opaque_sp->CreateBreakpoint (NULL, regexp, false);
600         }
601     }
602 
603     if (log)
604     {
605         log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (symbol_regex=\"%s\", module_name=\"%s\") => SBBreakpoint(%p)",
606                      m_opaque_sp.get(), symbol_name_regex, module_name, sb_bp.get());
607     }
608 
609     return sb_bp;
610 }
611 
612 
613 
614 SBBreakpoint
615 SBTarget::BreakpointCreateByAddress (addr_t address)
616 {
617     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
618 
619     SBBreakpoint sb_bp;
620     if (m_opaque_sp.get())
621     {
622         Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
623         *sb_bp = m_opaque_sp->CreateBreakpoint (address, false);
624     }
625 
626     if (log)
627     {
628         log->Printf ("SBTarget(%p)::BreakpointCreateByAddress (%p, address=%p) => SBBreakpoint(%p)", m_opaque_sp.get(), address, sb_bp.get());
629     }
630 
631     return sb_bp;
632 }
633 
634 SBBreakpoint
635 SBTarget::FindBreakpointByID (break_id_t bp_id)
636 {
637     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
638 
639     SBBreakpoint sb_breakpoint;
640     if (m_opaque_sp && bp_id != LLDB_INVALID_BREAK_ID)
641     {
642         Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
643         *sb_breakpoint = m_opaque_sp->GetBreakpointByID (bp_id);
644     }
645 
646     if (log)
647     {
648         log->Printf ("SBTarget(%p)::FindBreakpointByID (bp_id=%d) => SBBreakpoint(%p)",
649                      m_opaque_sp.get(), (uint32_t) bp_id, sb_breakpoint.get());
650     }
651 
652     return sb_breakpoint;
653 }
654 
655 uint32_t
656 SBTarget::GetNumBreakpoints () const
657 {
658     if (m_opaque_sp)
659     {
660         // The breakpoint list is thread safe, no need to lock
661         return m_opaque_sp->GetBreakpointList().GetSize();
662     }
663     return 0;
664 }
665 
666 SBBreakpoint
667 SBTarget::GetBreakpointAtIndex (uint32_t idx) const
668 {
669     SBBreakpoint sb_breakpoint;
670     if (m_opaque_sp)
671     {
672         // The breakpoint list is thread safe, no need to lock
673         *sb_breakpoint = m_opaque_sp->GetBreakpointList().GetBreakpointAtIndex(idx);
674     }
675     return sb_breakpoint;
676 }
677 
678 bool
679 SBTarget::BreakpointDelete (break_id_t bp_id)
680 {
681     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
682 
683     bool result = false;
684     if (m_opaque_sp)
685     {
686         Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
687         result = m_opaque_sp->RemoveBreakpointByID (bp_id);
688     }
689 
690     if (log)
691     {
692         log->Printf ("SBTarget(%p)::BreakpointDelete (bp_id=%d) => %i", m_opaque_sp.get(), (uint32_t) bp_id, result);
693     }
694 
695     return result;
696 }
697 
698 bool
699 SBTarget::EnableAllBreakpoints ()
700 {
701     if (m_opaque_sp)
702     {
703         Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
704         m_opaque_sp->EnableAllBreakpoints ();
705         return true;
706     }
707     return false;
708 }
709 
710 bool
711 SBTarget::DisableAllBreakpoints ()
712 {
713     if (m_opaque_sp)
714     {
715         Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
716         m_opaque_sp->DisableAllBreakpoints ();
717         return true;
718     }
719     return false;
720 }
721 
722 bool
723 SBTarget::DeleteAllBreakpoints ()
724 {
725     if (m_opaque_sp)
726     {
727         Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
728         m_opaque_sp->RemoveAllBreakpoints ();
729         return true;
730     }
731     return false;
732 }
733 
734 
735 uint32_t
736 SBTarget::GetNumModules () const
737 {
738     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
739 
740     uint32_t num = 0;
741     if (m_opaque_sp)
742     {
743         // The module list is thread safe, no need to lock
744         num = m_opaque_sp->GetImages().GetSize();
745     }
746 
747     if (log)
748         log->Printf ("SBTarget(%p)::GetNumModules () => %d", m_opaque_sp.get(), num);
749 
750     return num;
751 }
752 
753 void
754 SBTarget::Clear ()
755 {
756     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
757 
758     if (log)
759         log->Printf ("SBTarget(%p)::Clear ()", m_opaque_sp.get());
760 
761     m_opaque_sp.reset();
762 }
763 
764 
765 SBModule
766 SBTarget::FindModule (const SBFileSpec &sb_file_spec)
767 {
768     SBModule sb_module;
769     if (m_opaque_sp && sb_file_spec.IsValid())
770     {
771         // The module list is thread safe, no need to lock
772         sb_module.SetModule (m_opaque_sp->GetImages().FindFirstModuleForFileSpec (*sb_file_spec, NULL, NULL));
773     }
774     return sb_module;
775 }
776 
777 SBModule
778 SBTarget::GetModuleAtIndex (uint32_t idx)
779 {
780     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
781 
782     SBModule sb_module;
783     if (m_opaque_sp)
784     {
785         // The module list is thread safe, no need to lock
786         sb_module.SetModule(m_opaque_sp->GetImages().GetModuleAtIndex(idx));
787     }
788 
789     if (log)
790     {
791         log->Printf ("SBTarget(%p)::GetModuleAtIndex (idx=%d) => SBModule(%p)",
792                      m_opaque_sp.get(), idx, sb_module.get());
793     }
794 
795     return sb_module;
796 }
797 
798 
799 SBBroadcaster
800 SBTarget::GetBroadcaster () const
801 {
802     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
803 
804     SBBroadcaster broadcaster(m_opaque_sp.get(), false);
805 
806     if (log)
807         log->Printf ("SBTarget(%p)::GetBroadcaster () => SBBroadcaster(%p)",
808                      m_opaque_sp.get(), broadcaster.get());
809 
810     return broadcaster;
811 }
812 
813 
814 bool
815 SBTarget::GetDescription (SBStream &description, lldb::DescriptionLevel description_level)
816 {
817     if (m_opaque_sp)
818     {
819         description.ref();
820         m_opaque_sp->Dump (description.get(), description_level);
821     }
822     else
823         description.Printf ("No value");
824 
825     return true;
826 }
827 
828 bool
829 SBTarget::GetDescription (SBStream &description, lldb::DescriptionLevel description_level) const
830 {
831     if (m_opaque_sp)
832     {
833         description.ref();
834         m_opaque_sp->Dump (description.get(), description_level);
835     }
836     else
837         description.Printf ("No value");
838 
839     return true;
840 }
841