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