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 #include "lldb/Interpreter/Args.h"
14 #include "lldb/Core/Debugger.h"
15 #include "lldb/Core/State.h"
16 #include "lldb/Target/Process.h"
17 #include "lldb/Target/TargetList.h"
18 
19 #include "lldb/API/SBListener.h"
20 #include "lldb/API/SBBroadcaster.h"
21 #include "lldb/API/SBCommandInterpreter.h"
22 #include "lldb/API/SBCommandReturnObject.h"
23 #include "lldb/API/SBEvent.h"
24 #include "lldb/API/SBFrame.h"
25 #include "lldb/API/SBTarget.h"
26 #include "lldb/API/SBProcess.h"
27 #include "lldb/API/SBThread.h"
28 #include "lldb/API/SBSourceManager.h"
29 #include "lldb/API/SBInputReader.h"
30 
31 using namespace lldb;
32 using namespace lldb_private;
33 
34 void
35 SBDebugger::Initialize ()
36 {
37     Debugger::Initialize();
38 }
39 
40 void
41 SBDebugger::Terminate ()
42 {
43     Debugger::Terminate();
44 }
45 
46 SBDebugger
47 SBDebugger::Create()
48 {
49     SBDebugger debugger;
50     debugger.reset(Debugger::CreateInstance());
51     return debugger;
52 }
53 
54 SBDebugger::SBDebugger () :
55     m_opaque_sp ()
56 {
57 }
58 
59 SBDebugger::~SBDebugger ()
60 {
61 }
62 
63 bool
64 SBDebugger::IsValid() const
65 {
66     return m_opaque_sp.get() != NULL;
67 }
68 
69 
70 void
71 SBDebugger::SetAsync (bool b)
72 {
73     if (m_opaque_sp)
74         m_opaque_sp->SetAsyncExecution(b);
75 }
76 
77 // Shouldn't really be settable after initialization as this could cause lots of problems; don't want users
78 // trying to switch modes in the middle of a debugging session.
79 void
80 SBDebugger::SetInputFileHandle (FILE *fh, bool transfer_ownership)
81 {
82     if (m_opaque_sp)
83         m_opaque_sp->SetInputFileHandle (fh, transfer_ownership);
84 }
85 
86 void
87 SBDebugger::SetOutputFileHandle (FILE *fh, bool transfer_ownership)
88 {
89     if (m_opaque_sp)
90         m_opaque_sp->SetOutputFileHandle (fh, transfer_ownership);
91 }
92 
93 void
94 SBDebugger::SetErrorFileHandle (FILE *fh, bool transfer_ownership)
95 {
96     if (m_opaque_sp)
97         m_opaque_sp->SetErrorFileHandle (fh, transfer_ownership);
98 }
99 
100 FILE *
101 SBDebugger::GetInputFileHandle ()
102 {
103     if (m_opaque_sp)
104         return m_opaque_sp->GetInputFileHandle();
105     return NULL;
106 }
107 
108 FILE *
109 SBDebugger::GetOutputFileHandle ()
110 {
111     if (m_opaque_sp)
112         return m_opaque_sp->GetOutputFileHandle();
113     return NULL;
114 }
115 
116 FILE *
117 SBDebugger::GetErrorFileHandle ()
118 {
119     if (m_opaque_sp)
120         return m_opaque_sp->GetErrorFileHandle();
121     return NULL;
122 }
123 
124 SBCommandInterpreter
125 SBDebugger::GetCommandInterpreter ()
126 {
127     SBCommandInterpreter sb_interpreter;
128     if (m_opaque_sp)
129         sb_interpreter.reset (&m_opaque_sp->GetCommandInterpreter());
130     return sb_interpreter;
131 }
132 
133 void
134 SBDebugger::HandleCommand (const char *command)
135 {
136     if (m_opaque_sp)
137     {
138         SBCommandInterpreter sb_interpreter(GetCommandInterpreter ());
139         SBCommandReturnObject result;
140 
141         sb_interpreter.HandleCommand (command, result, false);
142 
143         if (GetErrorFileHandle() != NULL)
144             result.PutError (GetErrorFileHandle());
145         if (GetOutputFileHandle() != NULL)
146             result.PutOutput (GetOutputFileHandle());
147 
148         if (m_opaque_sp->GetAsyncExecution() == false)
149         {
150             SBProcess process(GetCommandInterpreter().GetProcess ());
151             if (process.IsValid())
152             {
153                 EventSP event_sp;
154                 Listener &lldb_listener = m_opaque_sp->GetListener();
155                 while (lldb_listener.GetNextEventForBroadcaster (process.get(), event_sp))
156                 {
157                     SBEvent event(event_sp);
158                     HandleProcessEvent (process, event, GetOutputFileHandle(), GetErrorFileHandle());
159                 }
160             }
161         }
162     }
163 }
164 
165 SBListener
166 SBDebugger::GetListener ()
167 {
168     SBListener sb_listener;
169     if (m_opaque_sp)
170         sb_listener.reset(&m_opaque_sp->GetListener(), false);
171     return sb_listener;
172 }
173 
174 void
175 SBDebugger::HandleProcessEvent (const SBProcess &process, const SBEvent &event, FILE *out, FILE *err)
176 {
177      const uint32_t event_type = event.GetType();
178      char stdio_buffer[1024];
179      size_t len;
180 
181      if (event_type & Process::eBroadcastBitSTDOUT)
182      {
183          while ((len = process.GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
184              if (out != NULL)
185                  ::fwrite (stdio_buffer, 1, len, out);
186      }
187      else if (event_type & Process::eBroadcastBitSTDERR)
188      {
189          while ((len = process.GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
190              if (out != NULL)
191                  ::fwrite (stdio_buffer, 1, len, out);
192      }
193      else if (event_type & Process::eBroadcastBitStateChanged)
194      {
195          // Drain any stdout messages.
196          while ((len = process.GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
197              if (out != NULL)
198                  ::fwrite (stdio_buffer, 1, len, out);
199 
200          // Drain any stderr messages.
201          while ((len = process.GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
202              if (out != NULL)
203                  ::fwrite (stdio_buffer, 1, len, out);
204 
205          StateType event_state = SBProcess::GetStateFromEvent (event);
206 
207          if (event_state == eStateInvalid)
208              return;
209 
210          bool is_stopped = StateIsStoppedState (event_state);
211          if (!is_stopped)
212              process.ReportCurrentState (event, out);
213    }
214 }
215 
216 void
217 SBDebugger::UpdateCurrentThread (SBProcess &process)
218 {
219     if (process.IsValid())
220     {
221         SBThread curr_thread = process.GetCurrentThread ();
222         SBThread thread;
223         StopReason curr_thread_stop_reason = eStopReasonInvalid;
224         if (curr_thread.IsValid())
225         {
226             if (curr_thread.GetStopReason() != eStopReasonInvalid)
227                 curr_thread_stop_reason = curr_thread.GetStopReason ();
228         }
229 
230         if (! curr_thread.IsValid()
231             || curr_thread_stop_reason == eStopReasonInvalid
232             || curr_thread_stop_reason == eStopReasonNone)
233           {
234             // Prefer a thread that has just completed its plan over another thread as current thread.
235             SBThread plan_thread;
236             SBThread other_thread;
237             const size_t num_threads = process.GetNumThreads ();
238             size_t i;
239             for (i = 0; i < num_threads; ++i)
240             {
241                 thread = process.GetThreadAtIndex(i);
242                 if (thread.GetStopReason () != eStopReasonInvalid)
243                 {
244                     switch (thread.GetStopReason ())
245                     {
246                         default:
247                         case eStopReasonInvalid:
248                         case eStopReasonNone:
249                             break;
250 
251                         case eStopReasonTrace:
252                         case eStopReasonBreakpoint:
253                         case eStopReasonWatchpoint:
254                         case eStopReasonSignal:
255                         case eStopReasonException:
256                             if (! other_thread.IsValid())
257                                 other_thread = thread;
258                             break;
259                         case eStopReasonPlanComplete:
260                             if (! plan_thread.IsValid())
261                                 plan_thread = thread;
262                             break;
263                     }
264                 }
265             }
266             if (plan_thread.IsValid())
267                 process.SetCurrentThreadByID (plan_thread.GetThreadID());
268             else if (other_thread.IsValid())
269                 process.SetCurrentThreadByID (other_thread.GetThreadID());
270             else
271             {
272                 if (curr_thread.IsValid())
273                     thread = curr_thread;
274                 else
275                     thread = process.GetThreadAtIndex(0);
276 
277                 if (thread.IsValid())
278                     process.SetCurrentThreadByID (thread.GetThreadID());
279             }
280         }
281     }
282 }
283 
284 SBSourceManager &
285 SBDebugger::GetSourceManager ()
286 {
287     static SourceManager g_lldb_source_manager;
288     static SBSourceManager g_sb_source_manager (g_lldb_source_manager);
289     return g_sb_source_manager;
290 }
291 
292 
293 bool
294 SBDebugger::GetDefaultArchitecture (char *arch_name, size_t arch_name_len)
295 {
296     if (arch_name && arch_name_len)
297     {
298         ArchSpec &default_arch = lldb_private::GetDefaultArchitecture ();
299         if (default_arch.IsValid())
300         {
301             ::snprintf (arch_name, arch_name_len, "%s", default_arch.AsCString());
302             return true;
303         }
304     }
305     if (arch_name && arch_name_len)
306         arch_name[0] = '\0';
307     return false;
308 }
309 
310 
311 bool
312 SBDebugger::SetDefaultArchitecture (const char *arch_name)
313 {
314     if (arch_name)
315     {
316         ArchSpec arch (arch_name);
317         if (arch.IsValid())
318         {
319             lldb_private::GetDefaultArchitecture () = arch;
320             return true;
321         }
322     }
323     return false;
324 }
325 
326 ScriptLanguage
327 SBDebugger::GetScriptingLanguage (const char *script_language_name)
328 {
329     return Args::StringToScriptLanguage (script_language_name,
330                                          eScriptLanguageDefault,
331                                          NULL);
332 }
333 
334 const char *
335 SBDebugger::GetVersionString ()
336 {
337     return lldb_private::GetVersion();
338 }
339 
340 const char *
341 SBDebugger::StateAsCString (lldb::StateType state)
342 {
343     return lldb_private::StateAsCString (state);
344 }
345 
346 bool
347 SBDebugger::StateIsRunningState (lldb::StateType state)
348 {
349     return lldb_private::StateIsRunningState (state);
350 }
351 
352 bool
353 SBDebugger::StateIsStoppedState (lldb::StateType state)
354 {
355     return lldb_private::StateIsStoppedState (state);
356 }
357 
358 
359 SBTarget
360 SBDebugger::CreateTargetWithFileAndTargetTriple (const char *filename,
361                                                  const char *target_triple)
362 {
363     SBTarget target;
364     if (m_opaque_sp)
365     {
366         ArchSpec arch;
367         FileSpec file_spec (filename);
368         arch.SetArchFromTargetTriple(target_triple);
369         TargetSP target_sp;
370         Error error (m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file_spec, arch, NULL, true, target_sp));
371         target.reset (target_sp);
372     }
373     return target;
374 }
375 
376 SBTarget
377 SBDebugger::CreateTargetWithFileAndArch (const char *filename, const char *archname)
378 {
379     SBTarget target;
380     if (m_opaque_sp)
381     {
382         FileSpec file (filename);
383         ArchSpec arch = lldb_private::GetDefaultArchitecture();
384         TargetSP target_sp;
385         Error error;
386 
387         if (archname != NULL)
388         {
389             ArchSpec arch2 (archname);
390             error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch2, NULL, true, target_sp);
391         }
392         else
393         {
394             if (!arch.IsValid())
395                 arch = LLDB_ARCH_DEFAULT;
396 
397             error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch, NULL, true, target_sp);
398 
399             if (error.Fail())
400             {
401                 if (arch == LLDB_ARCH_DEFAULT_32BIT)
402                     arch = LLDB_ARCH_DEFAULT_64BIT;
403                 else
404                     arch = LLDB_ARCH_DEFAULT_32BIT;
405 
406                 error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch, NULL, true, target_sp);
407             }
408         }
409 
410         if (error.Success())
411         {
412             m_opaque_sp->GetTargetList().SetCurrentTarget (target_sp.get());
413             target.reset(target_sp);
414         }
415     }
416     return target;
417 }
418 
419 SBTarget
420 SBDebugger::CreateTarget (const char *filename)
421 {
422     SBTarget target;
423     if (m_opaque_sp)
424     {
425         FileSpec file (filename);
426         ArchSpec arch = lldb_private::GetDefaultArchitecture();
427         TargetSP target_sp;
428         Error error;
429 
430         if (!arch.IsValid())
431             arch = LLDB_ARCH_DEFAULT;
432 
433         error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch, NULL, true, target_sp);
434 
435         if (error.Fail())
436         {
437             if (arch == LLDB_ARCH_DEFAULT_32BIT)
438                 arch = LLDB_ARCH_DEFAULT_64BIT;
439             else
440                 arch = LLDB_ARCH_DEFAULT_32BIT;
441 
442             error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, file, arch, NULL, true, target_sp);
443         }
444 
445         if (error.Success())
446         {
447             m_opaque_sp->GetTargetList().SetCurrentTarget (target_sp.get());
448             target.reset (target_sp);
449         }
450     }
451     return target;
452 }
453 
454 SBTarget
455 SBDebugger::GetTargetAtIndex (uint32_t idx)
456 {
457     SBTarget sb_target;
458     if (m_opaque_sp)
459         sb_target.reset(m_opaque_sp->GetTargetList().GetTargetAtIndex (idx));
460     return sb_target;
461 }
462 
463 SBTarget
464 SBDebugger::FindTargetWithProcessID (pid_t pid)
465 {
466     SBTarget sb_target;
467     if (m_opaque_sp)
468         sb_target.reset(m_opaque_sp->GetTargetList().FindTargetWithProcessID (pid));
469     return sb_target;
470 }
471 
472 SBTarget
473 SBDebugger::FindTargetWithFileAndArch (const char *filename, const char *arch_name)
474 {
475     SBTarget sb_target;
476     if (m_opaque_sp && filename && filename[0])
477     {
478         ArchSpec arch;
479         if (arch_name)
480             arch.SetArch(arch_name);
481         TargetSP target_sp (m_opaque_sp->GetTargetList().FindTargetWithExecutableAndArchitecture (FileSpec(filename), arch_name ? &arch : NULL));
482         sb_target.reset(target_sp);
483     }
484     return sb_target;
485 }
486 
487 SBTarget
488 SBDebugger::FindTargetWithLLDBProcess (const lldb::ProcessSP &process_sp)
489 {
490     SBTarget sb_target;
491     if (m_opaque_sp)
492         sb_target.reset(m_opaque_sp->GetTargetList().FindTargetWithProcess (process_sp.get()));
493     return sb_target;
494 }
495 
496 
497 uint32_t
498 SBDebugger::GetNumTargets ()
499 {
500     if (m_opaque_sp)
501         return m_opaque_sp->GetTargetList().GetNumTargets ();
502     return 0;
503 }
504 
505 SBTarget
506 SBDebugger::GetCurrentTarget ()
507 {
508     SBTarget sb_target;
509     if (m_opaque_sp)
510         sb_target.reset(m_opaque_sp->GetTargetList().GetCurrentTarget ());
511     return sb_target;
512 }
513 
514 void
515 SBDebugger::DispatchInput (void *baton, const void *data, size_t data_len)
516 {
517     if (m_opaque_sp)
518         m_opaque_sp->DispatchInput ((const char *) data, data_len);
519 }
520 
521 void
522 SBDebugger::PushInputReader (SBInputReader &reader)
523 {
524     if (m_opaque_sp && reader.IsValid())
525     {
526         InputReaderSP reader_sp(*reader);
527         m_opaque_sp->PushInputReader (reader_sp);
528     }
529 }
530 
531 void
532 SBDebugger::reset (const lldb::DebuggerSP &debugger_sp)
533 {
534     m_opaque_sp = debugger_sp;
535 }
536 
537 Debugger *
538 SBDebugger::get () const
539 {
540     return m_opaque_sp.get();
541 }
542 
543 Debugger &
544 SBDebugger::ref () const
545 {
546     assert (m_opaque_sp.get());
547     return *m_opaque_sp;
548 }
549 
550 
551 SBDebugger
552 SBDebugger::FindDebuggerWithID (int id)
553 {
554     SBDebugger sb_debugger;
555     lldb::DebuggerSP debugger_sp = Debugger::FindDebuggerWithID (id);
556     if (debugger_sp)
557         sb_debugger.reset (debugger_sp);
558     return sb_debugger;
559 }
560