blob: 1cdd7ad4d87fbaf0ab2eae63aaa3462307ab977d [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 (),
Jim Inghame40e4212010-08-30 19:44:40 +0000131 m_input_reader_data (),
132 m_use_external_editor(false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000133{
Greg Clayton66111032010-06-23 01:19:29 +0000134 m_command_interpreter_ap->Initialize ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000135}
136
137Debugger::~Debugger ()
138{
Greg Clayton66111032010-06-23 01:19:29 +0000139 int num_targets = m_target_list.GetNumTargets();
140 for (int i = 0; i < num_targets; i++)
141 {
142 ProcessSP process_sp (m_target_list.GetTargetAtIndex (i)->GetProcessSP());
143 if (process_sp)
144 process_sp->Destroy();
145 }
146 DisconnectInput();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000147}
148
149
150bool
151Debugger::GetAsyncExecution ()
152{
Greg Clayton66111032010-06-23 01:19:29 +0000153 return !m_command_interpreter_ap->GetSynchronous();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000154}
155
156void
157Debugger::SetAsyncExecution (bool async_execution)
158{
Greg Clayton66111032010-06-23 01:19:29 +0000159 m_command_interpreter_ap->SetSynchronous (!async_execution);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000160}
161
162void
163Debugger::DisconnectInput()
164{
165 m_input_comm.Clear ();
166}
167
168void
169Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership)
170{
171 m_input_file.SetFileHandle (fh, tranfer_ownership);
172 if (m_input_file.GetFileHandle() == NULL)
173 m_input_file.SetFileHandle (stdin, false);
174
175 // Disconnect from any old connection if we had one
176 m_input_comm.Disconnect ();
177 m_input_comm.SetConnection (new ConnectionFileDescriptor (::fileno (GetInputFileHandle()), true));
178 m_input_comm.SetReadThreadBytesReceivedCallback (Debugger::DispatchInputCallback, this);
179
180 Error error;
181 if (m_input_comm.StartReadThread (&error) == false)
182 {
183 FILE *err_fh = GetErrorFileHandle();
184 if (err_fh)
185 {
186 ::fprintf (err_fh, "error: failed to main input read thread: %s", error.AsCString() ? error.AsCString() : "unkown error");
187 exit(1);
188 }
189 }
190
191}
192
193FILE *
194Debugger::GetInputFileHandle ()
195{
196 return m_input_file.GetFileHandle();
197}
198
199
200void
201Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership)
202{
203 m_output_file.SetFileHandle (fh, tranfer_ownership);
204 if (m_output_file.GetFileHandle() == NULL)
205 m_output_file.SetFileHandle (stdin, false);
206}
207
208FILE *
209Debugger::GetOutputFileHandle ()
210{
211 return m_output_file.GetFileHandle();
212}
213
214void
215Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership)
216{
217 m_error_file.SetFileHandle (fh, tranfer_ownership);
218 if (m_error_file.GetFileHandle() == NULL)
219 m_error_file.SetFileHandle (stdin, false);
220}
221
222
223FILE *
224Debugger::GetErrorFileHandle ()
225{
226 return m_error_file.GetFileHandle();
227}
228
229CommandInterpreter &
230Debugger::GetCommandInterpreter ()
231{
Greg Clayton66111032010-06-23 01:19:29 +0000232 assert (m_command_interpreter_ap.get());
233 return *m_command_interpreter_ap;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000234}
235
236Listener &
237Debugger::GetListener ()
238{
239 return m_listener;
240}
241
242
243TargetSP
Jim Ingham2976d002010-08-26 21:32:51 +0000244Debugger::GetSelectedTarget ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000245{
Jim Ingham2976d002010-08-26 21:32:51 +0000246 return m_target_list.GetSelectedTarget ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000247}
248
249ExecutionContext
Jim Ingham2976d002010-08-26 21:32:51 +0000250Debugger::GetSelectedExecutionContext ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000251{
252 ExecutionContext exe_ctx;
253 exe_ctx.Clear();
254
Jim Ingham2976d002010-08-26 21:32:51 +0000255 lldb::TargetSP target_sp = GetSelectedTarget();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000256 exe_ctx.target = target_sp.get();
257
258 if (target_sp)
259 {
260 exe_ctx.process = target_sp->GetProcessSP().get();
261 if (exe_ctx.process && exe_ctx.process->IsRunning() == false)
262 {
Jim Ingham2976d002010-08-26 21:32:51 +0000263 exe_ctx.thread = exe_ctx.process->GetThreadList().GetSelectedThread().get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000264 if (exe_ctx.thread == NULL)
265 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
266 if (exe_ctx.thread)
267 {
Jim Ingham2976d002010-08-26 21:32:51 +0000268 exe_ctx.frame = exe_ctx.thread->GetSelectedFrame().get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000269 if (exe_ctx.frame == NULL)
270 exe_ctx.frame = exe_ctx.thread->GetStackFrameAtIndex (0).get();
271 }
272 }
273 }
274 return exe_ctx;
275
276}
277
278SourceManager &
279Debugger::GetSourceManager ()
280{
281 return m_source_manager;
282}
283
284
285TargetList&
286Debugger::GetTargetList ()
287{
288 return m_target_list;
289}
290
291void
292Debugger::DispatchInputCallback (void *baton, const void *bytes, size_t bytes_len)
293{
294 ((Debugger *)baton)->DispatchInput ((char *)bytes, bytes_len);
295}
296
297
298void
299Debugger::DispatchInput (const char *bytes, size_t bytes_len)
300{
301 if (bytes == NULL || bytes_len == 0)
302 return;
303
304 // TODO: implement the STDIO to the process as an input reader...
Jim Ingham2976d002010-08-26 21:32:51 +0000305 TargetSP target = GetSelectedTarget();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000306 if (target.get() != NULL)
307 {
308 ProcessSP process_sp = target->GetProcessSP();
309 if (process_sp.get() != NULL
310 && StateIsRunningState (process_sp->GetState()))
311 {
312 Error error;
313 if (process_sp->PutSTDIN (bytes, bytes_len, error) == bytes_len)
314 return;
315 }
316 }
317
318 WriteToDefaultReader (bytes, bytes_len);
319}
320
321void
322Debugger::WriteToDefaultReader (const char *bytes, size_t bytes_len)
323{
324 if (bytes && bytes_len)
325 m_input_reader_data.append (bytes, bytes_len);
326
327 if (m_input_reader_data.empty())
328 return;
329
330 while (!m_input_readers.empty() && !m_input_reader_data.empty())
331 {
332 while (CheckIfTopInputReaderIsDone ())
333 /* Do nothing. */;
334
335 // Get the input reader from the top of the stack
336 InputReaderSP reader_sp(m_input_readers.top());
337
338 if (!reader_sp)
339 break;
340
Greg Clayton471b31c2010-07-20 22:52:08 +0000341 size_t bytes_handled = reader_sp->HandleRawBytes (m_input_reader_data.c_str(),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000342 m_input_reader_data.size());
343 if (bytes_handled)
344 {
345 m_input_reader_data.erase (0, bytes_handled);
346 }
347 else
348 {
349 // No bytes were handled, we might not have reached our
350 // granularity, just return and wait for more data
351 break;
352 }
353 }
354
355 // Flush out any input readers that are donesvn
356 while (CheckIfTopInputReaderIsDone ())
357 /* Do nothing. */;
358
359}
360
361void
362Debugger::PushInputReader (const InputReaderSP& reader_sp)
363{
364 if (!reader_sp)
365 return;
366 if (!m_input_readers.empty())
367 {
368 // Deactivate the old top reader
369 InputReaderSP top_reader_sp (m_input_readers.top());
370 if (top_reader_sp)
371 top_reader_sp->Notify (eInputReaderDeactivate);
372 }
373 m_input_readers.push (reader_sp);
374 reader_sp->Notify (eInputReaderActivate);
375 ActivateInputReader (reader_sp);
376}
377
378bool
379Debugger::PopInputReader (const lldb::InputReaderSP& pop_reader_sp)
380{
381 bool result = false;
382
383 // The reader on the stop of the stack is done, so let the next
384 // read on the stack referesh its prompt and if there is one...
385 if (!m_input_readers.empty())
386 {
387 InputReaderSP reader_sp(m_input_readers.top());
388
389 if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get())
390 {
391 m_input_readers.pop ();
392 reader_sp->Notify (eInputReaderDeactivate);
393 reader_sp->Notify (eInputReaderDone);
394 result = true;
395
396 if (!m_input_readers.empty())
397 {
398 reader_sp = m_input_readers.top();
399 if (reader_sp)
400 {
401 ActivateInputReader (reader_sp);
402 reader_sp->Notify (eInputReaderReactivate);
403 }
404 }
405 }
406 }
407 return result;
408}
409
410bool
411Debugger::CheckIfTopInputReaderIsDone ()
412{
413 bool result = false;
414 if (!m_input_readers.empty())
415 {
416 InputReaderSP reader_sp(m_input_readers.top());
417
418 if (reader_sp && reader_sp->IsDone())
419 {
420 result = true;
421 PopInputReader (reader_sp);
422 }
423 }
424 return result;
425}
426
427void
428Debugger::ActivateInputReader (const InputReaderSP &reader_sp)
429{
430 FILE *in_fh = GetInputFileHandle();
431
432 if (in_fh)
433 {
434 struct termios in_fh_termios;
435 int in_fd = fileno (in_fh);
436 if (::tcgetattr(in_fd, &in_fh_termios) == 0)
437 {
438 if (reader_sp->GetEcho())
439 in_fh_termios.c_lflag |= ECHO; // Turn on echoing
440 else
441 in_fh_termios.c_lflag &= ~ECHO; // Turn off echoing
442
443 switch (reader_sp->GetGranularity())
444 {
445 case eInputReaderGranularityByte:
446 case eInputReaderGranularityWord:
447 in_fh_termios.c_lflag &= ~ICANON; // Get one char at a time
448 break;
449
450 case eInputReaderGranularityLine:
451 case eInputReaderGranularityAll:
452 in_fh_termios.c_lflag |= ICANON; // Get lines at a time
453 break;
454
455 default:
456 break;
457 }
458 ::tcsetattr (in_fd, TCSANOW, &in_fh_termios);
459 }
460 }
461}
Greg Clayton66111032010-06-23 01:19:29 +0000462
463void
464Debugger::UpdateExecutionContext (ExecutionContext *override_context)
465{
466 m_exe_ctx.Clear();
467
468 if (override_context != NULL)
469 {
470 m_exe_ctx.target = override_context->target;
471 m_exe_ctx.process = override_context->process;
472 m_exe_ctx.thread = override_context->thread;
473 m_exe_ctx.frame = override_context->frame;
474 }
475 else
476 {
Jim Ingham2976d002010-08-26 21:32:51 +0000477 TargetSP target_sp (GetSelectedTarget());
Greg Clayton66111032010-06-23 01:19:29 +0000478 if (target_sp)
479 {
480 m_exe_ctx.target = target_sp.get();
481 m_exe_ctx.process = target_sp->GetProcessSP().get();
Johnny Chen725945d2010-09-03 22:35:47 +0000482 if (m_exe_ctx.process && m_exe_ctx.process->IsAlive() && !m_exe_ctx.process->IsRunning())
Greg Clayton66111032010-06-23 01:19:29 +0000483 {
Jim Ingham2976d002010-08-26 21:32:51 +0000484 m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetSelectedThread().get();
Greg Clayton66111032010-06-23 01:19:29 +0000485 if (m_exe_ctx.thread == NULL)
486 m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
487 if (m_exe_ctx.thread)
488 {
Jim Ingham2976d002010-08-26 21:32:51 +0000489 m_exe_ctx.frame = m_exe_ctx.thread->GetSelectedFrame().get();
Greg Clayton66111032010-06-23 01:19:29 +0000490 if (m_exe_ctx.frame == NULL)
491 m_exe_ctx.frame = m_exe_ctx.thread->GetStackFrameAtIndex (0).get();
492 }
493 }
494 }
495 }
496}
497
Caroline Ticeebc1bb22010-06-30 16:22:25 +0000498DebuggerSP
499Debugger::FindDebuggerWithID (lldb::user_id_t id)
500{
501 lldb::DebuggerSP debugger_sp;
502
503 Mutex::Locker locker (GetDebuggerListMutex ());
504 DebuggerList &debugger_list = GetDebuggerList();
505 DebuggerList::iterator pos, end = debugger_list.end();
506 for (pos = debugger_list.begin(); pos != end; ++pos)
507 {
508 if ((*pos).get()->GetID() == id)
509 {
510 debugger_sp = *pos;
511 break;
512 }
513 }
514 return debugger_sp;
515}