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