blob: 0b7676ca7327e6eaca5bcd1ef9eefe0dd01efbfa [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Debugger.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/lldb-private.h"
11#include "lldb/Core/ConnectionFileDescriptor.h"
12#include "lldb/Core/Debugger.h"
13#include "lldb/Core/InputReader.h"
14#include "lldb/Core/State.h"
15#include "lldb/Core/Timer.h"
Greg Clayton66111032010-06-23 01:19:29 +000016#include "lldb/Interpreter/CommandInterpreter.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017#include "lldb/Target/TargetList.h"
18#include "lldb/Target/Process.h"
19#include "lldb/Target/Thread.h"
20
21
22using namespace lldb;
23using namespace lldb_private;
24
Greg Clayton66111032010-06-23 01:19:29 +000025static uint32_t g_shared_debugger_refcount = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000026
27void
28Debugger::Initialize ()
29{
Greg Clayton66111032010-06-23 01:19:29 +000030 if (g_shared_debugger_refcount == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000031 lldb_private::Initialize();
Greg Clayton66111032010-06-23 01:19:29 +000032 g_shared_debugger_refcount++;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033}
34
35void
36Debugger::Terminate ()
37{
Greg Clayton66111032010-06-23 01:19:29 +000038 if (g_shared_debugger_refcount > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000039 {
Greg Clayton66111032010-06-23 01:19:29 +000040 g_shared_debugger_refcount--;
41 if (g_shared_debugger_refcount == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000042 {
Greg Clayton66111032010-06-23 01:19:29 +000043 lldb_private::WillTerminate();
44 lldb_private::Terminate();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000045 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000046 }
47}
48
Greg Clayton66111032010-06-23 01:19:29 +000049typedef std::vector<DebuggerSP> DebuggerList;
50
51static Mutex &
52GetDebuggerListMutex ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +000053{
Greg Clayton66111032010-06-23 01:19:29 +000054 static Mutex g_mutex(Mutex::eMutexTypeRecursive);
55 return g_mutex;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000056}
57
Greg Clayton66111032010-06-23 01:19:29 +000058static DebuggerList &
59GetDebuggerList()
60{
61 // hide the static debugger list inside a singleton accessor to avoid
62 // global init contructors
63 static DebuggerList g_list;
64 return g_list;
65}
66
67
68DebuggerSP
69Debugger::CreateInstance ()
70{
71 DebuggerSP debugger_sp (new Debugger);
72 // Scope for locker
73 {
74 Mutex::Locker locker (GetDebuggerListMutex ());
75 GetDebuggerList().push_back(debugger_sp);
76 }
77 return debugger_sp;
78}
79
80lldb::DebuggerSP
81Debugger::GetSP ()
82{
83 lldb::DebuggerSP debugger_sp;
84
85 Mutex::Locker locker (GetDebuggerListMutex ());
86 DebuggerList &debugger_list = GetDebuggerList();
87 DebuggerList::iterator pos, end = debugger_list.end();
88 for (pos = debugger_list.begin(); pos != end; ++pos)
89 {
90 if ((*pos).get() == this)
91 {
92 debugger_sp = *pos;
93 break;
94 }
95 }
96 return debugger_sp;
97}
98
99
100TargetSP
101Debugger::FindTargetWithProcessID (lldb::pid_t pid)
102{
103 lldb::TargetSP target_sp;
104 Mutex::Locker locker (GetDebuggerListMutex ());
105 DebuggerList &debugger_list = GetDebuggerList();
106 DebuggerList::iterator pos, end = debugger_list.end();
107 for (pos = debugger_list.begin(); pos != end; ++pos)
108 {
109 target_sp = (*pos)->GetTargetList().FindTargetWithProcessID (pid);
110 if (target_sp)
111 break;
112 }
113 return target_sp;
114}
115
116
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000117Debugger::Debugger () :
118 m_input_comm("debugger.input"),
119 m_input_file (),
120 m_output_file (),
121 m_error_file (),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000122 m_target_list (),
123 m_listener ("lldb.Debugger"),
124 m_source_manager (),
Greg Clayton66111032010-06-23 01:19:29 +0000125 m_command_interpreter_ap (new CommandInterpreter (*this, eScriptLanguageDefault, false)),
126 m_exe_ctx (),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000127 m_input_readers (),
128 m_input_reader_data ()
129{
Greg Clayton66111032010-06-23 01:19:29 +0000130 m_command_interpreter_ap->Initialize ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000131}
132
133Debugger::~Debugger ()
134{
Greg Clayton66111032010-06-23 01:19:29 +0000135 int num_targets = m_target_list.GetNumTargets();
136 for (int i = 0; i < num_targets; i++)
137 {
138 ProcessSP process_sp (m_target_list.GetTargetAtIndex (i)->GetProcessSP());
139 if (process_sp)
140 process_sp->Destroy();
141 }
142 DisconnectInput();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000143}
144
145
146bool
147Debugger::GetAsyncExecution ()
148{
Greg Clayton66111032010-06-23 01:19:29 +0000149 return !m_command_interpreter_ap->GetSynchronous();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000150}
151
152void
153Debugger::SetAsyncExecution (bool async_execution)
154{
Greg Clayton66111032010-06-23 01:19:29 +0000155 m_command_interpreter_ap->SetSynchronous (!async_execution);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000156}
157
158void
159Debugger::DisconnectInput()
160{
161 m_input_comm.Clear ();
162}
163
164void
165Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership)
166{
167 m_input_file.SetFileHandle (fh, tranfer_ownership);
168 if (m_input_file.GetFileHandle() == NULL)
169 m_input_file.SetFileHandle (stdin, false);
170
171 // Disconnect from any old connection if we had one
172 m_input_comm.Disconnect ();
173 m_input_comm.SetConnection (new ConnectionFileDescriptor (::fileno (GetInputFileHandle()), true));
174 m_input_comm.SetReadThreadBytesReceivedCallback (Debugger::DispatchInputCallback, this);
175
176 Error error;
177 if (m_input_comm.StartReadThread (&error) == false)
178 {
179 FILE *err_fh = GetErrorFileHandle();
180 if (err_fh)
181 {
182 ::fprintf (err_fh, "error: failed to main input read thread: %s", error.AsCString() ? error.AsCString() : "unkown error");
183 exit(1);
184 }
185 }
186
187}
188
189FILE *
190Debugger::GetInputFileHandle ()
191{
192 return m_input_file.GetFileHandle();
193}
194
195
196void
197Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership)
198{
199 m_output_file.SetFileHandle (fh, tranfer_ownership);
200 if (m_output_file.GetFileHandle() == NULL)
201 m_output_file.SetFileHandle (stdin, false);
202}
203
204FILE *
205Debugger::GetOutputFileHandle ()
206{
207 return m_output_file.GetFileHandle();
208}
209
210void
211Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership)
212{
213 m_error_file.SetFileHandle (fh, tranfer_ownership);
214 if (m_error_file.GetFileHandle() == NULL)
215 m_error_file.SetFileHandle (stdin, false);
216}
217
218
219FILE *
220Debugger::GetErrorFileHandle ()
221{
222 return m_error_file.GetFileHandle();
223}
224
225CommandInterpreter &
226Debugger::GetCommandInterpreter ()
227{
Greg Clayton66111032010-06-23 01:19:29 +0000228 assert (m_command_interpreter_ap.get());
229 return *m_command_interpreter_ap;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000230}
231
232Listener &
233Debugger::GetListener ()
234{
235 return m_listener;
236}
237
238
239TargetSP
240Debugger::GetCurrentTarget ()
241{
242 return m_target_list.GetCurrentTarget ();
243}
244
245ExecutionContext
246Debugger::GetCurrentExecutionContext ()
247{
248 ExecutionContext exe_ctx;
249 exe_ctx.Clear();
250
251 lldb::TargetSP target_sp = GetCurrentTarget();
252 exe_ctx.target = target_sp.get();
253
254 if (target_sp)
255 {
256 exe_ctx.process = target_sp->GetProcessSP().get();
257 if (exe_ctx.process && exe_ctx.process->IsRunning() == false)
258 {
259 exe_ctx.thread = exe_ctx.process->GetThreadList().GetCurrentThread().get();
260 if (exe_ctx.thread == NULL)
261 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
262 if (exe_ctx.thread)
263 {
264 exe_ctx.frame = exe_ctx.thread->GetCurrentFrame().get();
265 if (exe_ctx.frame == NULL)
266 exe_ctx.frame = exe_ctx.thread->GetStackFrameAtIndex (0).get();
267 }
268 }
269 }
270 return exe_ctx;
271
272}
273
274SourceManager &
275Debugger::GetSourceManager ()
276{
277 return m_source_manager;
278}
279
280
281TargetList&
282Debugger::GetTargetList ()
283{
284 return m_target_list;
285}
286
287void
288Debugger::DispatchInputCallback (void *baton, const void *bytes, size_t bytes_len)
289{
290 ((Debugger *)baton)->DispatchInput ((char *)bytes, bytes_len);
291}
292
293
294void
295Debugger::DispatchInput (const char *bytes, size_t bytes_len)
296{
297 if (bytes == NULL || bytes_len == 0)
298 return;
299
300 // TODO: implement the STDIO to the process as an input reader...
301 TargetSP target = GetCurrentTarget();
302 if (target.get() != NULL)
303 {
304 ProcessSP process_sp = target->GetProcessSP();
305 if (process_sp.get() != NULL
306 && StateIsRunningState (process_sp->GetState()))
307 {
308 Error error;
309 if (process_sp->PutSTDIN (bytes, bytes_len, error) == bytes_len)
310 return;
311 }
312 }
313
314 WriteToDefaultReader (bytes, bytes_len);
315}
316
317void
318Debugger::WriteToDefaultReader (const char *bytes, size_t bytes_len)
319{
320 if (bytes && bytes_len)
321 m_input_reader_data.append (bytes, bytes_len);
322
323 if (m_input_reader_data.empty())
324 return;
325
326 while (!m_input_readers.empty() && !m_input_reader_data.empty())
327 {
328 while (CheckIfTopInputReaderIsDone ())
329 /* Do nothing. */;
330
331 // Get the input reader from the top of the stack
332 InputReaderSP reader_sp(m_input_readers.top());
333
334 if (!reader_sp)
335 break;
336
337 size_t bytes_handled = reader_sp->HandleRawBytes (m_input_reader_data.data(),
338 m_input_reader_data.size());
339 if (bytes_handled)
340 {
341 m_input_reader_data.erase (0, bytes_handled);
342 }
343 else
344 {
345 // No bytes were handled, we might not have reached our
346 // granularity, just return and wait for more data
347 break;
348 }
349 }
350
351 // Flush out any input readers that are donesvn
352 while (CheckIfTopInputReaderIsDone ())
353 /* Do nothing. */;
354
355}
356
357void
358Debugger::PushInputReader (const InputReaderSP& reader_sp)
359{
360 if (!reader_sp)
361 return;
362 if (!m_input_readers.empty())
363 {
364 // Deactivate the old top reader
365 InputReaderSP top_reader_sp (m_input_readers.top());
366 if (top_reader_sp)
367 top_reader_sp->Notify (eInputReaderDeactivate);
368 }
369 m_input_readers.push (reader_sp);
370 reader_sp->Notify (eInputReaderActivate);
371 ActivateInputReader (reader_sp);
372}
373
374bool
375Debugger::PopInputReader (const lldb::InputReaderSP& pop_reader_sp)
376{
377 bool result = false;
378
379 // The reader on the stop of the stack is done, so let the next
380 // read on the stack referesh its prompt and if there is one...
381 if (!m_input_readers.empty())
382 {
383 InputReaderSP reader_sp(m_input_readers.top());
384
385 if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get())
386 {
387 m_input_readers.pop ();
388 reader_sp->Notify (eInputReaderDeactivate);
389 reader_sp->Notify (eInputReaderDone);
390 result = true;
391
392 if (!m_input_readers.empty())
393 {
394 reader_sp = m_input_readers.top();
395 if (reader_sp)
396 {
397 ActivateInputReader (reader_sp);
398 reader_sp->Notify (eInputReaderReactivate);
399 }
400 }
401 }
402 }
403 return result;
404}
405
406bool
407Debugger::CheckIfTopInputReaderIsDone ()
408{
409 bool result = false;
410 if (!m_input_readers.empty())
411 {
412 InputReaderSP reader_sp(m_input_readers.top());
413
414 if (reader_sp && reader_sp->IsDone())
415 {
416 result = true;
417 PopInputReader (reader_sp);
418 }
419 }
420 return result;
421}
422
423void
424Debugger::ActivateInputReader (const InputReaderSP &reader_sp)
425{
426 FILE *in_fh = GetInputFileHandle();
427
428 if (in_fh)
429 {
430 struct termios in_fh_termios;
431 int in_fd = fileno (in_fh);
432 if (::tcgetattr(in_fd, &in_fh_termios) == 0)
433 {
434 if (reader_sp->GetEcho())
435 in_fh_termios.c_lflag |= ECHO; // Turn on echoing
436 else
437 in_fh_termios.c_lflag &= ~ECHO; // Turn off echoing
438
439 switch (reader_sp->GetGranularity())
440 {
441 case eInputReaderGranularityByte:
442 case eInputReaderGranularityWord:
443 in_fh_termios.c_lflag &= ~ICANON; // Get one char at a time
444 break;
445
446 case eInputReaderGranularityLine:
447 case eInputReaderGranularityAll:
448 in_fh_termios.c_lflag |= ICANON; // Get lines at a time
449 break;
450
451 default:
452 break;
453 }
454 ::tcsetattr (in_fd, TCSANOW, &in_fh_termios);
455 }
456 }
457}
Greg Clayton66111032010-06-23 01:19:29 +0000458
459void
460Debugger::UpdateExecutionContext (ExecutionContext *override_context)
461{
462 m_exe_ctx.Clear();
463
464 if (override_context != NULL)
465 {
466 m_exe_ctx.target = override_context->target;
467 m_exe_ctx.process = override_context->process;
468 m_exe_ctx.thread = override_context->thread;
469 m_exe_ctx.frame = override_context->frame;
470 }
471 else
472 {
473 TargetSP target_sp (GetCurrentTarget());
474 if (target_sp)
475 {
476 m_exe_ctx.target = target_sp.get();
477 m_exe_ctx.process = target_sp->GetProcessSP().get();
478 if (m_exe_ctx.process && m_exe_ctx.process->IsRunning() == false)
479 {
480 m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetCurrentThread().get();
481 if (m_exe_ctx.thread == NULL)
482 m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
483 if (m_exe_ctx.thread)
484 {
485 m_exe_ctx.frame = m_exe_ctx.thread->GetCurrentFrame().get();
486 if (m_exe_ctx.frame == NULL)
487 m_exe_ctx.frame = m_exe_ctx.thread->GetStackFrameAtIndex (0).get();
488 }
489 }
490 }
491 }
492}
493