1 //===-- SBDebugger.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/SBDebugger.h"
11 
12 #include "lldb/lldb-include.h"
13 
14 #include "lldb/API/SBListener.h"
15 #include "lldb/API/SBBroadcaster.h"
16 #include "lldb/API/SBCommandInterpreter.h"
17 #include "lldb/API/SBCommandReturnObject.h"
18 #include "lldb/API/SBEvent.h"
19 #include "lldb/API/SBFrame.h"
20 #include "lldb/API/SBInputReader.h"
21 #include "lldb/API/SBProcess.h"
22 #include "lldb/API/SBSourceManager.h"
23 #include "lldb/API/SBStream.h"
24 #include "lldb/API/SBStringList.h"
25 #include "lldb/API/SBTarget.h"
26 #include "lldb/API/SBThread.h"
27 #include "lldb/Core/Debugger.h"
28 #include "lldb/Core/State.h"
29 #include "lldb/Interpreter/Args.h"
30 #include "lldb/Interpreter/CommandInterpreter.h"
31 #include "lldb/Target/Process.h"
32 #include "lldb/Target/TargetList.h"
33 
34 using namespace lldb;
35 using namespace lldb_private;
36 
37 void
38 SBDebugger::Initialize ()
39 {
40     Debugger::Initialize();
41 }
42 
43 void
44 SBDebugger::Terminate ()
45 {
46     Debugger::Terminate();
47 }
48 
49 void
50 SBDebugger::Clear ()
51 {
52     m_opaque_sp.reset();
53 }
54 
55 SBDebugger
56 SBDebugger::Create()
57 {
58     SBDebugger debugger;
59     debugger.reset(Debugger::CreateInstance());
60     return debugger;
61 }
62 
63 SBDebugger::SBDebugger () :
64     m_opaque_sp ()
65 {
66 }
67 
68 SBDebugger::~SBDebugger ()
69 {
70 }
71 
72 bool
73 SBDebugger::IsValid() const
74 {
75     return m_opaque_sp.get() != NULL;
76 }
77 
78 
79 void
80 SBDebugger::SetAsync (bool b)
81 {
82     if (m_opaque_sp)
83         m_opaque_sp->SetAsyncExecution(b);
84 }
85 
86 void
87 SBDebugger::SkipLLDBInitFiles (bool b)
88 {
89     if (m_opaque_sp)
90         m_opaque_sp->GetCommandInterpreter().SkipLLDBInitFiles (b);
91 }
92 
93 // Shouldn't really be settable after initialization as this could cause lots of problems; don't want users
94 // trying to switch modes in the middle of a debugging session.
95 void
96 SBDebugger::SetInputFileHandle (FILE *fh, bool transfer_ownership)
97 {
98     if (m_opaque_sp)
99         m_opaque_sp->SetInputFileHandle (fh, transfer_ownership);
100 }
101 
102 void
103 SBDebugger::SetOutputFileHandle (FILE *fh, bool transfer_ownership)
104 {
105     if (m_opaque_sp)
106         m_opaque_sp->SetOutputFileHandle (fh, transfer_ownership);
107 }
108 
109 void
110 SBDebugger::SetErrorFileHandle (FILE *fh, bool transfer_ownership)
111 {
112     if (m_opaque_sp)
113         m_opaque_sp->SetErrorFileHandle (fh, transfer_ownership);
114 }
115 
116 FILE *
117 SBDebugger::GetInputFileHandle ()
118 {
119     if (m_opaque_sp)
120         return m_opaque_sp->GetInputFileHandle();
121     return NULL;
122 }
123 
124 FILE *
125 SBDebugger::GetOutputFileHandle ()
126 {
127     if (m_opaque_sp)
128         return m_opaque_sp->GetOutputFileHandle();
129     return NULL;
130 }
131 
132 FILE *
133 SBDebugger::GetErrorFileHandle ()
134 {
135     if (m_opaque_sp)
136         return m_opaque_sp->GetErrorFileHandle();
137     return NULL;
138 }
139 
140 SBCommandInterpreter
141 SBDebugger::GetCommandInterpreter ()
142 {
143     SBCommandInterpreter sb_interpreter;
144     if (m_opaque_sp)
145         sb_interpreter.reset (&m_opaque_sp->GetCommandInterpreter());
146     return sb_interpreter;
147 }
148 
149 void
150 SBDebugger::HandleCommand (const char *command)
151 {
152     if (m_opaque_sp)
153     {
154         SBCommandInterpreter sb_interpreter(GetCommandInterpreter ());
155         SBCommandReturnObject result;
156 
157         sb_interpreter.HandleCommand (command, result, false);
158 
159         if (GetErrorFileHandle() != NULL)
160             result.PutError (GetErrorFileHandle());
161         if (GetOutputFileHandle() != NULL)
162             result.PutOutput (GetOutputFileHandle());
163 
164         if (m_opaque_sp->GetAsyncExecution() == false)
165         {
166             SBProcess process(GetCommandInterpreter().GetProcess ());
167             if (process.IsValid())
168             {
169                 EventSP event_sp;
170                 Listener &lldb_listener = m_opaque_sp->GetListener();
171                 while (lldb_listener.GetNextEventForBroadcaster (process.get(), event_sp))
172                 {
173                     SBEvent event(event_sp);
174                     HandleProcessEvent (process, event, GetOutputFileHandle(), GetErrorFileHandle());
175                 }
176             }
177         }
178     }
179 }
180 
181 SBListener
182 SBDebugger::GetListener ()
183 {
184     SBListener sb_listener;
185     if (m_opaque_sp)
186         sb_listener.reset(&m_opaque_sp->GetListener(), false);
187     return sb_listener;
188 }
189 
190 void
191 SBDebugger::HandleProcessEvent (const SBProcess &process, const SBEvent &event, FILE *out, FILE *err)
192 {
193      const uint32_t event_type = event.GetType();
194      char stdio_buffer[1024];
195      size_t len;
196 
197      if (event_type & Process::eBroadcastBitSTDOUT)
198      {
199          while ((len = process.GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
200              if (out != NULL)
201                  ::fwrite (stdio_buffer, 1, len, out);
202      }
203      else if (event_type & Process::eBroadcastBitSTDERR)
204      {
205          while ((len = process.GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
206              if (out != NULL)
207                  ::fwrite (stdio_buffer, 1, len, out);
208      }
209      else if (event_type & Process::eBroadcastBitStateChanged)
210      {
211          // Drain any stdout messages.
212          while ((len = process.GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
213              if (out != NULL)
214                  ::fwrite (stdio_buffer, 1, len, out);
215 
216          // Drain any stderr messages.
217          while ((len = process.GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
218              if (out != NULL)
219                  ::fwrite (stdio_buffer, 1, len, out);
220 
221          StateType event_state = SBProcess::GetStateFromEvent (event);
222 
223          if (event_state == eStateInvalid)
224              return;
225 
226          bool is_stopped = StateIsStoppedState (event_state);
227          if (!is_stopped)
228              process.ReportEventState (event, out);
229    }
230 }
231 
232 void
233 SBDebugger::UpdateSelectedThread (SBProcess &process)
234 {
235     if (process.IsValid())
236     {
237         SBThread curr_thread = process.GetSelectedThread ();
238         SBThread thread;
239         StopReason curr_thread_stop_reason = eStopReasonInvalid;
240         if (curr_thread.IsValid())
241         {
242             if (curr_thread.GetStopReason() != eStopReasonInvalid)
243                 curr_thread_stop_reason = curr_thread.GetStopReason ();
244         }
245 
246         if (! curr_thread.IsValid()
247             || curr_thread_stop_reason == eStopReasonInvalid
248             || curr_thread_stop_reason == eStopReasonNone)
249           {
250             // Prefer a thread that has just completed its plan over another thread as current thread.
251             SBThread plan_thread;
252             SBThread other_thread;
253             const size_t num_threads = process.GetNumThreads ();
254             size_t i;
255             for (i = 0; i < num_threads; ++i)
256             {
257                 thread = process.GetThreadAtIndex(i);
258                 if (thread.GetStopReason () != eStopReasonInvalid)
259                 {
260                     switch (thread.GetStopReason ())
261                     {
262                         default:
263                         case eStopReasonInvalid:
264                         case eStopReasonNone:
265                             break;
266 
267                         case eStopReasonTrace:
268                         case eStopReasonBreakpoint:
269                         case eStopReasonWatchpoint:
270                         case eStopReasonSignal:
271                         case eStopReasonException:
272                             if (! other_thread.IsValid())
273                                 other_thread = thread;
274                             break;
275                         case eStopReasonPlanComplete:
276                             if (! plan_thread.IsValid())
277                                 plan_thread = thread;
278                             break;
279                     }
280                 }
281             }
282             if (plan_thread.IsValid())
283                 process.SetSelectedThreadByID (plan_thread.GetThreadID());
284             else if (other_thread.IsValid())
285                 process.SetSelectedThreadByID (other_thread.GetThreadID());
286             else
287             {
288                 if (curr_thread.IsValid())
289                     thread = curr_thread;
290                 else
291                     thread = process.GetThreadAtIndex(0);
292 
293                 if (thread.IsValid())
294                     process.SetSelectedThreadByID (thread.GetThreadID());
295             }
296         }
297     }
298 }
299 
300 SBSourceManager &
301 SBDebugger::GetSourceManager ()
302 {
303     static SourceManager g_lldb_source_manager;
304     static SBSourceManager g_sb_source_manager (g_lldb_source_manager);
305     return g_sb_source_manager;
306 }
307 
308 
309 bool
310 SBDebugger::GetDefaultArchitecture (char *arch_name, size_t arch_name_len)
311 {
312     if (arch_name && arch_name_len)
313     {
314         ArchSpec default_arch = lldb_private::Target::GetDefaultArchitecture ();
315 
316         if (default_arch.IsValid())
317         {
318             ::snprintf (arch_name, arch_name_len, "%s", default_arch.AsCString());
319             return true;
320         }
321     }
322     if (arch_name && arch_name_len)
323         arch_name[0] = '\0';
324     return false;
325 }
326 
327 
328 bool
329 SBDebugger::SetDefaultArchitecture (const char *arch_name)
330 {
331     if (arch_name)
332     {
333         ArchSpec arch (arch_name);
334         if (arch.IsValid())
335         {
336             lldb_private::Target::SetDefaultArchitecture (arch);
337             return true;
338         }
339     }
340     return false;
341 }
342 
343 ScriptLanguage
344 SBDebugger::GetScriptingLanguage (const char *script_language_name)
345 {
346     return Args::StringToScriptLanguage (script_language_name,
347                                          eScriptLanguageDefault,
348                                          NULL);
349 }
350 
351 const char *
352 SBDebugger::GetVersionString ()
353 {
354     return lldb_private::GetVersion();
355 }
356 
357 const char *
358 SBDebugger::StateAsCString (lldb::StateType state)
359 {
360     return lldb_private::StateAsCString (state);
361 }
362 
363 bool
364 SBDebugger::StateIsRunningState (lldb::StateType state)
365 {
366     return lldb_private::StateIsRunningState (state);
367 }
368 
369 bool
370 SBDebugger::StateIsStoppedState (lldb::StateType state)
371 {
372     return lldb_private::StateIsStoppedState (state);
373 }
374 
375 
376 SBTarget
377 SBDebugger::CreateTargetWithFileAndTargetTriple (const char *filename,
378                                                  const char *target_triple)
379 {
380     SBTarget target;
381     if (m_opaque_sp)
382     {
383         ArchSpec arch;
384         FileSpec file_spec (filename, true);
385         arch.SetArchFromTargetTriple(target_triple);
386         TargetSP target_sp;
387         Error error (m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file_spec, arch, NULL, true, target_sp));
388         target.reset (target_sp);
389     }
390     return target;
391 }
392 
393 SBTarget
394 SBDebugger::CreateTargetWithFileAndArch (const char *filename, const char *archname)
395 {
396     SBTarget target;
397     if (m_opaque_sp)
398     {
399         FileSpec file (filename, true);
400         ArchSpec arch = lldb_private::Target::GetDefaultArchitecture ();
401         TargetSP target_sp;
402         Error error;
403 
404         if (archname != NULL)
405         {
406             ArchSpec arch2 (archname);
407             error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch2, NULL, true, target_sp);
408         }
409         else
410         {
411             if (!arch.IsValid())
412                 arch = LLDB_ARCH_DEFAULT;
413 
414             error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch, NULL, true, target_sp);
415 
416             if (error.Fail())
417             {
418                 if (arch == LLDB_ARCH_DEFAULT_32BIT)
419                     arch = LLDB_ARCH_DEFAULT_64BIT;
420                 else
421                     arch = LLDB_ARCH_DEFAULT_32BIT;
422 
423                 error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch, NULL, true, target_sp);
424             }
425         }
426 
427         if (error.Success())
428         {
429             m_opaque_sp->GetTargetList().SetSelectedTarget (target_sp.get());
430             target.reset(target_sp);
431         }
432     }
433     return target;
434 }
435 
436 SBTarget
437 SBDebugger::CreateTarget (const char *filename)
438 {
439     SBTarget target;
440     if (m_opaque_sp)
441     {
442         FileSpec file (filename, true);
443         ArchSpec arch = lldb_private::Target::GetDefaultArchitecture ();
444         TargetSP target_sp;
445         Error error;
446 
447         if (!arch.IsValid())
448             arch = LLDB_ARCH_DEFAULT;
449 
450         error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch, NULL, true, target_sp);
451 
452         if (error.Fail())
453         {
454             if (arch == LLDB_ARCH_DEFAULT_32BIT)
455                 arch = LLDB_ARCH_DEFAULT_64BIT;
456             else
457                 arch = LLDB_ARCH_DEFAULT_32BIT;
458 
459             error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch, NULL, true, target_sp);
460         }
461 
462         if (error.Success())
463         {
464             m_opaque_sp->GetTargetList().SetSelectedTarget (target_sp.get());
465             target.reset (target_sp);
466         }
467     }
468     return target;
469 }
470 
471 SBTarget
472 SBDebugger::GetTargetAtIndex (uint32_t idx)
473 {
474     SBTarget sb_target;
475     if (m_opaque_sp)
476         sb_target.reset(m_opaque_sp->GetTargetList().GetTargetAtIndex (idx));
477     return sb_target;
478 }
479 
480 SBTarget
481 SBDebugger::FindTargetWithProcessID (pid_t pid)
482 {
483     SBTarget sb_target;
484     if (m_opaque_sp)
485         sb_target.reset(m_opaque_sp->GetTargetList().FindTargetWithProcessID (pid));
486     return sb_target;
487 }
488 
489 SBTarget
490 SBDebugger::FindTargetWithFileAndArch (const char *filename, const char *arch_name)
491 {
492     SBTarget sb_target;
493     if (m_opaque_sp && filename && filename[0])
494     {
495         ArchSpec arch;
496         if (arch_name)
497             arch.SetArch(arch_name);
498         TargetSP target_sp (m_opaque_sp->GetTargetList().FindTargetWithExecutableAndArchitecture (FileSpec(filename, false), arch_name ? &arch : NULL));
499         sb_target.reset(target_sp);
500     }
501     return sb_target;
502 }
503 
504 SBTarget
505 SBDebugger::FindTargetWithLLDBProcess (const lldb::ProcessSP &process_sp)
506 {
507     SBTarget sb_target;
508     if (m_opaque_sp)
509         sb_target.reset(m_opaque_sp->GetTargetList().FindTargetWithProcess (process_sp.get()));
510     return sb_target;
511 }
512 
513 
514 uint32_t
515 SBDebugger::GetNumTargets ()
516 {
517     if (m_opaque_sp)
518         return m_opaque_sp->GetTargetList().GetNumTargets ();
519     return 0;
520 }
521 
522 SBTarget
523 SBDebugger::GetSelectedTarget ()
524 {
525     SBTarget sb_target;
526     if (m_opaque_sp)
527         sb_target.reset(m_opaque_sp->GetTargetList().GetSelectedTarget ());
528     return sb_target;
529 }
530 
531 void
532 SBDebugger::DispatchInput (void *baton, const void *data, size_t data_len)
533 {
534     if (m_opaque_sp)
535         m_opaque_sp->DispatchInput ((const char *) data, data_len);
536 }
537 
538 void
539 SBDebugger::PushInputReader (SBInputReader &reader)
540 {
541     if (m_opaque_sp && reader.IsValid())
542     {
543         InputReaderSP reader_sp(*reader);
544         m_opaque_sp->PushInputReader (reader_sp);
545     }
546 }
547 
548 void
549 SBDebugger::reset (const lldb::DebuggerSP &debugger_sp)
550 {
551     m_opaque_sp = debugger_sp;
552 }
553 
554 Debugger *
555 SBDebugger::get () const
556 {
557     return m_opaque_sp.get();
558 }
559 
560 Debugger &
561 SBDebugger::ref () const
562 {
563     assert (m_opaque_sp.get());
564     return *m_opaque_sp;
565 }
566 
567 
568 SBDebugger
569 SBDebugger::FindDebuggerWithID (int id)
570 {
571     SBDebugger sb_debugger;
572     lldb::DebuggerSP debugger_sp = Debugger::FindDebuggerWithID (id);
573     if (debugger_sp)
574         sb_debugger.reset (debugger_sp);
575     return sb_debugger;
576 }
577 
578 const char *
579 SBDebugger::GetInstanceName()
580 {
581     if (m_opaque_sp)
582         return m_opaque_sp->GetInstanceName().AsCString();
583     else
584         return NULL;
585 }
586 
587 SBError
588 SBDebugger::SetInternalVariable (const char *var_name, const char *value, const char *debugger_instance_name)
589 {
590     lldb::UserSettingsControllerSP root_settings_controller = lldb_private::Debugger::GetSettingsController();
591 
592     Error err = root_settings_controller->SetVariable (var_name, value, lldb::eVarSetOperationAssign, true,
593                                                        debugger_instance_name);
594     SBError sb_error;
595     sb_error.SetError (err);
596 
597     return sb_error;
598 }
599 
600 lldb::SBStringList
601 SBDebugger::GetInternalVariableValue (const char *var_name, const char *debugger_instance_name)
602 {
603     SBStringList ret_value;
604     lldb::SettableVariableType var_type;
605     lldb_private:Error err;
606 
607     lldb::UserSettingsControllerSP root_settings_controller = lldb_private::Debugger::GetSettingsController();
608 
609     StringList value = root_settings_controller->GetVariable (var_name, var_type, debugger_instance_name, err);
610 
611     if (err.Success())
612     {
613         for (unsigned i = 0; i != value.GetSize(); ++i)
614             ret_value.AppendString (value.GetStringAtIndex(i));
615     }
616     else
617     {
618         ret_value.AppendString (err.AsCString());
619     }
620 
621 
622     return ret_value;
623 }
624 
625 uint32_t
626 SBDebugger::GetTerminalWidth () const
627 {
628     if (m_opaque_sp)
629         return m_opaque_sp->GetTerminalWidth ();
630     return 0;
631 }
632 
633 void
634 SBDebugger::SetTerminalWidth (uint32_t term_width)
635 {
636     if (m_opaque_sp)
637         m_opaque_sp->SetTerminalWidth (term_width);
638 }
639 
640 const char *
641 SBDebugger::GetPrompt() const
642 {
643     if (m_opaque_sp)
644         return m_opaque_sp->GetPrompt ();
645     return 0;
646 }
647 
648 void
649 SBDebugger::SetPrompt (const char *prompt)
650 {
651     if (m_opaque_sp)
652         m_opaque_sp->SetPrompt (prompt);
653 }
654 
655 
656 lldb::ScriptLanguage
657 SBDebugger::GetScriptLanguage() const
658 {
659     if (m_opaque_sp)
660         return m_opaque_sp->GetScriptLanguage ();
661     return eScriptLanguageNone;
662 }
663 
664 void
665 SBDebugger::SetScriptLanguage (lldb::ScriptLanguage script_lang)
666 {
667     if (m_opaque_sp)
668         m_opaque_sp->SetScriptLanguage (script_lang);
669 }
670 
671 
672 
673 
674 bool
675 SBDebugger::SetUseExternalEditor (bool value)
676 {
677     if (m_opaque_sp)
678         return m_opaque_sp->SetUseExternalEditor (value);
679     else
680         return false;
681 }
682 
683 bool
684 SBDebugger::GetUseExternalEditor ()
685 {
686     if (m_opaque_sp)
687         return m_opaque_sp->GetUseExternalEditor ();
688     else
689         return false;
690 }
691 
692 bool
693 SBDebugger::GetDescription (SBStream &description)
694 {
695     if (m_opaque_sp)
696     {
697         const char *name = m_opaque_sp->GetInstanceName().AsCString();
698         lldb::user_id_t id = m_opaque_sp->GetID();
699         description.Printf ("Debugger (instance: '%s', id: %d)", name, id);
700     }
701     else
702         description.Printf ("No value");
703 
704     return true;
705 }
706