blob: 6bce57ae103022438b45773edee4d84f7dadc495 [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"
Greg Clayton1b654882010-09-19 02:33:57 +000015#include "lldb/Core/StreamString.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016#include "lldb/Core/Timer.h"
Greg Clayton66111032010-06-23 01:19:29 +000017#include "lldb/Interpreter/CommandInterpreter.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018#include "lldb/Target/TargetList.h"
19#include "lldb/Target/Process.h"
Greg Clayton1b654882010-09-19 02:33:57 +000020#include "lldb/Target/RegisterContext.h"
21#include "lldb/Target/StopInfo.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022#include "lldb/Target/Thread.h"
23
24
25using namespace lldb;
26using namespace lldb_private;
27
Chris Lattner30fdc8d2010-06-08 16:52:24 +000028
Greg Clayton1b654882010-09-19 02:33:57 +000029static uint32_t g_shared_debugger_refcount = 0;
Caroline Ticeebc1bb22010-06-30 16:22:25 +000030static lldb::user_id_t g_unique_id = 1;
31
Greg Clayton1b654882010-09-19 02:33:57 +000032#pragma mark Static Functions
33
34static Mutex &
35GetDebuggerListMutex ()
36{
37 static Mutex g_mutex(Mutex::eMutexTypeRecursive);
38 return g_mutex;
39}
40
41typedef std::vector<DebuggerSP> DebuggerList;
42
43static DebuggerList &
44GetDebuggerList()
45{
46 // hide the static debugger list inside a singleton accessor to avoid
47 // global init contructors
48 static DebuggerList g_list;
49 return g_list;
50}
51
52
53#pragma mark Debugger
54
Chris Lattner30fdc8d2010-06-08 16:52:24 +000055void
56Debugger::Initialize ()
57{
Greg Clayton66111032010-06-23 01:19:29 +000058 if (g_shared_debugger_refcount == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000059 lldb_private::Initialize();
Greg Clayton66111032010-06-23 01:19:29 +000060 g_shared_debugger_refcount++;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000061}
62
63void
64Debugger::Terminate ()
65{
Greg Clayton66111032010-06-23 01:19:29 +000066 if (g_shared_debugger_refcount > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000067 {
Greg Clayton66111032010-06-23 01:19:29 +000068 g_shared_debugger_refcount--;
69 if (g_shared_debugger_refcount == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000070 {
Greg Clayton66111032010-06-23 01:19:29 +000071 lldb_private::WillTerminate();
72 lldb_private::Terminate();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000073 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000074 }
75}
76
Greg Clayton66111032010-06-23 01:19:29 +000077DebuggerSP
78Debugger::CreateInstance ()
79{
80 DebuggerSP debugger_sp (new Debugger);
81 // Scope for locker
82 {
83 Mutex::Locker locker (GetDebuggerListMutex ());
84 GetDebuggerList().push_back(debugger_sp);
85 }
86 return debugger_sp;
87}
88
89lldb::DebuggerSP
90Debugger::GetSP ()
91{
92 lldb::DebuggerSP debugger_sp;
93
94 Mutex::Locker locker (GetDebuggerListMutex ());
95 DebuggerList &debugger_list = GetDebuggerList();
96 DebuggerList::iterator pos, end = debugger_list.end();
97 for (pos = debugger_list.begin(); pos != end; ++pos)
98 {
99 if ((*pos).get() == this)
100 {
101 debugger_sp = *pos;
102 break;
103 }
104 }
105 return debugger_sp;
106}
107
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000108lldb::DebuggerSP
109Debugger::FindDebuggerWithInstanceName (const ConstString &instance_name)
110{
111 lldb::DebuggerSP debugger_sp;
112
113 Mutex::Locker locker (GetDebuggerListMutex ());
114 DebuggerList &debugger_list = GetDebuggerList();
115 DebuggerList::iterator pos, end = debugger_list.end();
116
117 for (pos = debugger_list.begin(); pos != end; ++pos)
118 {
119 if ((*pos).get()->m_instance_name == instance_name)
120 {
121 debugger_sp = *pos;
122 break;
123 }
124 }
125 return debugger_sp;
126}
Greg Clayton66111032010-06-23 01:19:29 +0000127
128TargetSP
129Debugger::FindTargetWithProcessID (lldb::pid_t pid)
130{
131 lldb::TargetSP target_sp;
132 Mutex::Locker locker (GetDebuggerListMutex ());
133 DebuggerList &debugger_list = GetDebuggerList();
134 DebuggerList::iterator pos, end = debugger_list.end();
135 for (pos = debugger_list.begin(); pos != end; ++pos)
136 {
137 target_sp = (*pos)->GetTargetList().FindTargetWithProcessID (pid);
138 if (target_sp)
139 break;
140 }
141 return target_sp;
142}
143
144
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000145Debugger::Debugger () :
Caroline Ticeebc1bb22010-06-30 16:22:25 +0000146 UserID (g_unique_id++),
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000147 DebuggerInstanceSettings (*(Debugger::GetSettingsController().get())),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000148 m_input_comm("debugger.input"),
149 m_input_file (),
150 m_output_file (),
151 m_error_file (),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000152 m_target_list (),
153 m_listener ("lldb.Debugger"),
154 m_source_manager (),
Greg Clayton66111032010-06-23 01:19:29 +0000155 m_command_interpreter_ap (new CommandInterpreter (*this, eScriptLanguageDefault, false)),
156 m_exe_ctx (),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000157 m_input_readers (),
Jim Inghame40e4212010-08-30 19:44:40 +0000158 m_input_reader_data (),
159 m_use_external_editor(false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000160{
Greg Clayton66111032010-06-23 01:19:29 +0000161 m_command_interpreter_ap->Initialize ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000162}
163
164Debugger::~Debugger ()
165{
Greg Clayton66111032010-06-23 01:19:29 +0000166 int num_targets = m_target_list.GetNumTargets();
167 for (int i = 0; i < num_targets; i++)
168 {
169 ProcessSP process_sp (m_target_list.GetTargetAtIndex (i)->GetProcessSP());
170 if (process_sp)
171 process_sp->Destroy();
172 }
173 DisconnectInput();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000174}
175
176
177bool
178Debugger::GetAsyncExecution ()
179{
Greg Clayton66111032010-06-23 01:19:29 +0000180 return !m_command_interpreter_ap->GetSynchronous();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000181}
182
183void
184Debugger::SetAsyncExecution (bool async_execution)
185{
Greg Clayton66111032010-06-23 01:19:29 +0000186 m_command_interpreter_ap->SetSynchronous (!async_execution);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000187}
188
189void
190Debugger::DisconnectInput()
191{
192 m_input_comm.Clear ();
193}
194
195void
196Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership)
197{
198 m_input_file.SetFileHandle (fh, tranfer_ownership);
199 if (m_input_file.GetFileHandle() == NULL)
200 m_input_file.SetFileHandle (stdin, false);
201
202 // Disconnect from any old connection if we had one
203 m_input_comm.Disconnect ();
204 m_input_comm.SetConnection (new ConnectionFileDescriptor (::fileno (GetInputFileHandle()), true));
205 m_input_comm.SetReadThreadBytesReceivedCallback (Debugger::DispatchInputCallback, this);
206
207 Error error;
208 if (m_input_comm.StartReadThread (&error) == false)
209 {
210 FILE *err_fh = GetErrorFileHandle();
211 if (err_fh)
212 {
213 ::fprintf (err_fh, "error: failed to main input read thread: %s", error.AsCString() ? error.AsCString() : "unkown error");
214 exit(1);
215 }
216 }
217
218}
219
220FILE *
221Debugger::GetInputFileHandle ()
222{
223 return m_input_file.GetFileHandle();
224}
225
226
227void
228Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership)
229{
230 m_output_file.SetFileHandle (fh, tranfer_ownership);
231 if (m_output_file.GetFileHandle() == NULL)
232 m_output_file.SetFileHandle (stdin, false);
233}
234
235FILE *
236Debugger::GetOutputFileHandle ()
237{
238 return m_output_file.GetFileHandle();
239}
240
241void
242Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership)
243{
244 m_error_file.SetFileHandle (fh, tranfer_ownership);
245 if (m_error_file.GetFileHandle() == NULL)
246 m_error_file.SetFileHandle (stdin, false);
247}
248
249
250FILE *
251Debugger::GetErrorFileHandle ()
252{
253 return m_error_file.GetFileHandle();
254}
255
256CommandInterpreter &
257Debugger::GetCommandInterpreter ()
258{
Greg Clayton66111032010-06-23 01:19:29 +0000259 assert (m_command_interpreter_ap.get());
260 return *m_command_interpreter_ap;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000261}
262
263Listener &
264Debugger::GetListener ()
265{
266 return m_listener;
267}
268
269
270TargetSP
Jim Ingham2976d002010-08-26 21:32:51 +0000271Debugger::GetSelectedTarget ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000272{
Jim Ingham2976d002010-08-26 21:32:51 +0000273 return m_target_list.GetSelectedTarget ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000274}
275
276ExecutionContext
Jim Ingham2976d002010-08-26 21:32:51 +0000277Debugger::GetSelectedExecutionContext ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000278{
279 ExecutionContext exe_ctx;
280 exe_ctx.Clear();
281
Jim Ingham2976d002010-08-26 21:32:51 +0000282 lldb::TargetSP target_sp = GetSelectedTarget();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000283 exe_ctx.target = target_sp.get();
284
285 if (target_sp)
286 {
287 exe_ctx.process = target_sp->GetProcessSP().get();
288 if (exe_ctx.process && exe_ctx.process->IsRunning() == false)
289 {
Jim Ingham2976d002010-08-26 21:32:51 +0000290 exe_ctx.thread = exe_ctx.process->GetThreadList().GetSelectedThread().get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000291 if (exe_ctx.thread == NULL)
292 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
293 if (exe_ctx.thread)
294 {
Jim Ingham2976d002010-08-26 21:32:51 +0000295 exe_ctx.frame = exe_ctx.thread->GetSelectedFrame().get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000296 if (exe_ctx.frame == NULL)
297 exe_ctx.frame = exe_ctx.thread->GetStackFrameAtIndex (0).get();
298 }
299 }
300 }
301 return exe_ctx;
302
303}
304
305SourceManager &
306Debugger::GetSourceManager ()
307{
308 return m_source_manager;
309}
310
311
312TargetList&
313Debugger::GetTargetList ()
314{
315 return m_target_list;
316}
317
318void
319Debugger::DispatchInputCallback (void *baton, const void *bytes, size_t bytes_len)
320{
321 ((Debugger *)baton)->DispatchInput ((char *)bytes, bytes_len);
322}
323
324
325void
326Debugger::DispatchInput (const char *bytes, size_t bytes_len)
327{
328 if (bytes == NULL || bytes_len == 0)
329 return;
330
331 // TODO: implement the STDIO to the process as an input reader...
Jim Ingham2976d002010-08-26 21:32:51 +0000332 TargetSP target = GetSelectedTarget();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000333 if (target.get() != NULL)
334 {
335 ProcessSP process_sp = target->GetProcessSP();
336 if (process_sp.get() != NULL
337 && StateIsRunningState (process_sp->GetState()))
338 {
339 Error error;
340 if (process_sp->PutSTDIN (bytes, bytes_len, error) == bytes_len)
341 return;
342 }
343 }
344
345 WriteToDefaultReader (bytes, bytes_len);
346}
347
348void
349Debugger::WriteToDefaultReader (const char *bytes, size_t bytes_len)
350{
351 if (bytes && bytes_len)
352 m_input_reader_data.append (bytes, bytes_len);
353
354 if (m_input_reader_data.empty())
355 return;
356
357 while (!m_input_readers.empty() && !m_input_reader_data.empty())
358 {
359 while (CheckIfTopInputReaderIsDone ())
360 /* Do nothing. */;
361
362 // Get the input reader from the top of the stack
363 InputReaderSP reader_sp(m_input_readers.top());
364
365 if (!reader_sp)
366 break;
367
Greg Clayton471b31c2010-07-20 22:52:08 +0000368 size_t bytes_handled = reader_sp->HandleRawBytes (m_input_reader_data.c_str(),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000369 m_input_reader_data.size());
370 if (bytes_handled)
371 {
372 m_input_reader_data.erase (0, bytes_handled);
373 }
374 else
375 {
376 // No bytes were handled, we might not have reached our
377 // granularity, just return and wait for more data
378 break;
379 }
380 }
381
382 // Flush out any input readers that are donesvn
383 while (CheckIfTopInputReaderIsDone ())
384 /* Do nothing. */;
385
386}
387
388void
389Debugger::PushInputReader (const InputReaderSP& reader_sp)
390{
391 if (!reader_sp)
392 return;
393 if (!m_input_readers.empty())
394 {
395 // Deactivate the old top reader
396 InputReaderSP top_reader_sp (m_input_readers.top());
397 if (top_reader_sp)
398 top_reader_sp->Notify (eInputReaderDeactivate);
399 }
400 m_input_readers.push (reader_sp);
401 reader_sp->Notify (eInputReaderActivate);
402 ActivateInputReader (reader_sp);
403}
404
405bool
406Debugger::PopInputReader (const lldb::InputReaderSP& pop_reader_sp)
407{
408 bool result = false;
409
410 // The reader on the stop of the stack is done, so let the next
411 // read on the stack referesh its prompt and if there is one...
412 if (!m_input_readers.empty())
413 {
414 InputReaderSP reader_sp(m_input_readers.top());
415
416 if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get())
417 {
418 m_input_readers.pop ();
419 reader_sp->Notify (eInputReaderDeactivate);
420 reader_sp->Notify (eInputReaderDone);
421 result = true;
422
423 if (!m_input_readers.empty())
424 {
425 reader_sp = m_input_readers.top();
426 if (reader_sp)
427 {
428 ActivateInputReader (reader_sp);
429 reader_sp->Notify (eInputReaderReactivate);
430 }
431 }
432 }
433 }
434 return result;
435}
436
437bool
438Debugger::CheckIfTopInputReaderIsDone ()
439{
440 bool result = false;
441 if (!m_input_readers.empty())
442 {
443 InputReaderSP reader_sp(m_input_readers.top());
444
445 if (reader_sp && reader_sp->IsDone())
446 {
447 result = true;
448 PopInputReader (reader_sp);
449 }
450 }
451 return result;
452}
453
454void
455Debugger::ActivateInputReader (const InputReaderSP &reader_sp)
456{
457 FILE *in_fh = GetInputFileHandle();
458
459 if (in_fh)
460 {
461 struct termios in_fh_termios;
462 int in_fd = fileno (in_fh);
463 if (::tcgetattr(in_fd, &in_fh_termios) == 0)
464 {
465 if (reader_sp->GetEcho())
466 in_fh_termios.c_lflag |= ECHO; // Turn on echoing
467 else
468 in_fh_termios.c_lflag &= ~ECHO; // Turn off echoing
469
470 switch (reader_sp->GetGranularity())
471 {
472 case eInputReaderGranularityByte:
473 case eInputReaderGranularityWord:
474 in_fh_termios.c_lflag &= ~ICANON; // Get one char at a time
475 break;
476
477 case eInputReaderGranularityLine:
478 case eInputReaderGranularityAll:
479 in_fh_termios.c_lflag |= ICANON; // Get lines at a time
480 break;
481
482 default:
483 break;
484 }
485 ::tcsetattr (in_fd, TCSANOW, &in_fh_termios);
486 }
487 }
488}
Greg Clayton66111032010-06-23 01:19:29 +0000489
490void
491Debugger::UpdateExecutionContext (ExecutionContext *override_context)
492{
493 m_exe_ctx.Clear();
494
495 if (override_context != NULL)
496 {
497 m_exe_ctx.target = override_context->target;
498 m_exe_ctx.process = override_context->process;
499 m_exe_ctx.thread = override_context->thread;
500 m_exe_ctx.frame = override_context->frame;
501 }
502 else
503 {
Jim Ingham2976d002010-08-26 21:32:51 +0000504 TargetSP target_sp (GetSelectedTarget());
Greg Clayton66111032010-06-23 01:19:29 +0000505 if (target_sp)
506 {
507 m_exe_ctx.target = target_sp.get();
508 m_exe_ctx.process = target_sp->GetProcessSP().get();
Johnny Chen725945d2010-09-03 22:35:47 +0000509 if (m_exe_ctx.process && m_exe_ctx.process->IsAlive() && !m_exe_ctx.process->IsRunning())
Greg Clayton66111032010-06-23 01:19:29 +0000510 {
Jim Ingham2976d002010-08-26 21:32:51 +0000511 m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetSelectedThread().get();
Greg Clayton66111032010-06-23 01:19:29 +0000512 if (m_exe_ctx.thread == NULL)
Jim Ingham59ce7fe2010-09-10 23:06:30 +0000513 {
Greg Clayton66111032010-06-23 01:19:29 +0000514 m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
Jim Ingham59ce7fe2010-09-10 23:06:30 +0000515 // If we didn't have a selected thread, select one here.
516 if (m_exe_ctx.thread != NULL)
Johnny Chenc13ee522010-09-14 00:53:53 +0000517 m_exe_ctx.process->GetThreadList().SetSelectedThreadByID(m_exe_ctx.thread->GetID());
Jim Ingham59ce7fe2010-09-10 23:06:30 +0000518 }
Greg Clayton66111032010-06-23 01:19:29 +0000519 if (m_exe_ctx.thread)
520 {
Jim Ingham2976d002010-08-26 21:32:51 +0000521 m_exe_ctx.frame = m_exe_ctx.thread->GetSelectedFrame().get();
Greg Clayton66111032010-06-23 01:19:29 +0000522 if (m_exe_ctx.frame == NULL)
Jim Ingham59ce7fe2010-09-10 23:06:30 +0000523 {
Greg Clayton66111032010-06-23 01:19:29 +0000524 m_exe_ctx.frame = m_exe_ctx.thread->GetStackFrameAtIndex (0).get();
Jim Ingham59ce7fe2010-09-10 23:06:30 +0000525 // If we didn't have a selected frame select one here.
526 if (m_exe_ctx.frame != NULL)
527 m_exe_ctx.thread->SetSelectedFrame(m_exe_ctx.frame);
528 }
Greg Clayton66111032010-06-23 01:19:29 +0000529 }
530 }
531 }
532 }
533}
534
Caroline Ticeebc1bb22010-06-30 16:22:25 +0000535DebuggerSP
536Debugger::FindDebuggerWithID (lldb::user_id_t id)
537{
538 lldb::DebuggerSP debugger_sp;
539
540 Mutex::Locker locker (GetDebuggerListMutex ());
541 DebuggerList &debugger_list = GetDebuggerList();
542 DebuggerList::iterator pos, end = debugger_list.end();
543 for (pos = debugger_list.begin(); pos != end; ++pos)
544 {
545 if ((*pos).get()->GetID() == id)
546 {
547 debugger_sp = *pos;
548 break;
549 }
550 }
551 return debugger_sp;
552}
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000553
554lldb::UserSettingsControllerSP &
555Debugger::GetSettingsController (bool finish)
556{
Greg Clayton1b654882010-09-19 02:33:57 +0000557 static lldb::UserSettingsControllerSP g_settings_controller (new SettingsController);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000558 static bool initialized = false;
559
560 if (!initialized)
561 {
Jim Ingham95852752010-09-07 20:27:09 +0000562 initialized = UserSettingsController::InitializeSettingsController (g_settings_controller,
Greg Clayton1b654882010-09-19 02:33:57 +0000563 Debugger::SettingsController::global_settings_table,
564 Debugger::SettingsController::instance_settings_table);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000565 }
566
567 if (finish)
568 {
569 UserSettingsControllerSP parent = g_settings_controller->GetParent();
570 if (parent)
571 parent->RemoveChild (g_settings_controller);
572 g_settings_controller.reset();
573 }
574 return g_settings_controller;
575}
576
Greg Clayton1b654882010-09-19 02:33:57 +0000577static void
578TestPromptFormats (StackFrame *frame)
579{
580 if (frame == NULL)
581 return;
582
583 StreamString s;
584 const char *prompt_format =
585 "{addr = '${addr}'\n}"
586 "{process.id = '${process.id}'\n}"
587 "{process.name = '${process.name}'\n}"
588 "{process.file.basename = '${process.file.basename}'\n}"
589 "{process.file.fullpath = '${process.file.fullpath}'\n}"
590 "{thread.id = '${thread.id}'\n}"
591 "{thread.index = '${thread.index}'\n}"
592 "{thread.name = '${thread.name}'\n}"
593 "{thread.queue = '${thread.queue}'\n}"
594 "{thread.stop-reason = '${thread.stop-reason}'\n}"
595 "{target.arch = '${target.arch}'\n}"
596 "{module.file.basename = '${module.file.basename}'\n}"
597 "{module.file.fullpath = '${module.file.fullpath}'\n}"
598 "{file.basename = '${file.basename}'\n}"
599 "{file.fullpath = '${file.fullpath}'\n}"
600 "{frame.index = '${frame.index}'\n}"
601 "{frame.pc = '${frame.pc}'\n}"
602 "{frame.sp = '${frame.sp}'\n}"
603 "{frame.fp = '${frame.fp}'\n}"
604 "{frame.flags = '${frame.flags}'\n}"
605 "{frame.reg.rdi = '${frame.reg.rdi}'\n}"
606 "{frame.reg.rip = '${frame.reg.rip}'\n}"
607 "{frame.reg.rsp = '${frame.reg.rsp}'\n}"
608 "{frame.reg.rbp = '${frame.reg.rbp}'\n}"
609 "{frame.reg.rflags = '${frame.reg.rflags}'\n}"
610 "{frame.reg.xmm0 = '${frame.reg.xmm0}'\n}"
611 "{frame.reg.carp = '${frame.reg.carp}'\n}"
612 "{function.id = '${function.id}'\n}"
613 "{function.name = '${function.name}'\n}"
614 "{function.addr-offset = '${function.addr-offset}'\n}"
615 "{function.line-offset = '${function.line-offset}'\n}"
616 "{function.pc-offset = '${function.pc-offset}'\n}"
617 "{line.file.basename = '${line.file.basename}'\n}"
618 "{line.file.fullpath = '${line.file.fullpath}'\n}"
619 "{line.number = '${line.number}'\n}"
620 "{line.start-addr = '${line.start-addr}'\n}"
621 "{line.end-addr = '${line.end-addr}'\n}"
622;
623
624 SymbolContext sc (frame->GetSymbolContext(eSymbolContextEverything));
625 ExecutionContext exe_ctx;
626 frame->Calculate(exe_ctx);
627 const char *end = NULL;
628 if (Debugger::FormatPrompt (prompt_format, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, &end))
629 {
630 printf("%s\n", s.GetData());
631 }
632 else
633 {
634 printf ("error: at '%s'\n", end);
635 printf ("what we got: %s\n", s.GetData());
636 }
637}
638
639bool
640Debugger::FormatPrompt
641(
642 const char *format,
643 const SymbolContext *sc,
644 const ExecutionContext *exe_ctx,
645 const Address *addr,
646 Stream &s,
647 const char **end
648)
649{
650 bool success = true;
651 const char *p;
652 for (p = format; *p != '\0'; ++p)
653 {
654 size_t non_special_chars = ::strcspn (p, "${}\\");
655 if (non_special_chars > 0)
656 {
657 if (success)
658 s.Write (p, non_special_chars);
659 p += non_special_chars;
660 }
661
662 if (*p == '\0')
663 {
664 break;
665 }
666 else if (*p == '{')
667 {
668 // Start a new scope that must have everything it needs if it is to
669 // to make it into the final output stream "s". If you want to make
670 // a format that only prints out the function or symbol name if there
671 // is one in the symbol context you can use:
672 // "{function =${function.name}}"
673 // The first '{' starts a new scope that end with the matching '}' at
674 // the end of the string. The contents "function =${function.name}"
675 // will then be evaluated and only be output if there is a function
676 // or symbol with a valid name.
677 StreamString sub_strm;
678
679 ++p; // Skip the '{'
680
681 if (FormatPrompt (p, sc, exe_ctx, addr, sub_strm, &p))
682 {
683 // The stream had all it needed
684 s.Write(sub_strm.GetData(), sub_strm.GetSize());
685 }
686 if (*p != '}')
687 {
688 success = false;
689 break;
690 }
691 }
692 else if (*p == '}')
693 {
694 // End of a enclosing scope
695 break;
696 }
697 else if (*p == '$')
698 {
699 // We have a prompt variable to print
700 ++p;
701 if (*p == '{')
702 {
703 ++p;
704 const char *var_name_begin = p;
705 const char *var_name_end = ::strchr (p, '}');
706
707 if (var_name_end && var_name_begin < var_name_end)
708 {
709 // if we have already failed to parse, skip this variable
710 if (success)
711 {
712 const char *cstr = NULL;
713 Address format_addr;
714 bool calculate_format_addr_function_offset = false;
715 // Set reg_kind and reg_num to invalid values
716 RegisterKind reg_kind = kNumRegisterKinds;
717 uint32_t reg_num = LLDB_INVALID_REGNUM;
718 FileSpec format_file_spec;
719 const lldb::RegisterInfo *reg_info = NULL;
720 RegisterContext *reg_ctx = NULL;
721
722 // Each variable must set success to true below...
723 bool var_success = false;
724 switch (var_name_begin[0])
725 {
726 case 'a':
727 if (::strncmp (var_name_begin, "addr}", strlen("addr}")) == 0)
728 {
729 if (addr && addr->IsValid())
730 {
731 var_success = true;
732 format_addr = *addr;
733 }
734 }
735 break;
736
737 case 'p':
738 if (::strncmp (var_name_begin, "process.", strlen("process.")) == 0)
739 {
740 if (exe_ctx && exe_ctx->process != NULL)
741 {
742 var_name_begin += ::strlen ("process.");
743 if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0)
744 {
745 s.Printf("%i", exe_ctx->process->GetID());
746 var_success = true;
747 }
748 else if ((::strncmp (var_name_begin, "name}", strlen("name}")) == 0) ||
749 (::strncmp (var_name_begin, "file.basename}", strlen("file.basename}")) == 0) ||
750 (::strncmp (var_name_begin, "file.fullpath}", strlen("file.fullpath}")) == 0))
751 {
752 ModuleSP exe_module_sp (exe_ctx->process->GetTarget().GetExecutableModule());
753 if (exe_module_sp)
754 {
755 if (var_name_begin[0] == 'n' || var_name_begin[5] == 'f')
756 {
757 format_file_spec.GetFilename() = exe_module_sp->GetFileSpec().GetFilename();
758 var_success = format_file_spec;
759 }
760 else
761 {
762 format_file_spec = exe_module_sp->GetFileSpec();
763 var_success = format_file_spec;
764 }
765 }
766 }
767 }
768 }
769 break;
770
771 case 't':
772 if (::strncmp (var_name_begin, "thread.", strlen("thread.")) == 0)
773 {
774 if (exe_ctx && exe_ctx->thread)
775 {
776 var_name_begin += ::strlen ("thread.");
777 if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0)
778 {
779 s.Printf("0x%4.4x", exe_ctx->thread->GetID());
780 var_success = true;
781 }
782 else if (::strncmp (var_name_begin, "index}", strlen("index}")) == 0)
783 {
784 s.Printf("%u", exe_ctx->thread->GetIndexID());
785 var_success = true;
786 }
787 else if (::strncmp (var_name_begin, "name}", strlen("name}")) == 0)
788 {
789 cstr = exe_ctx->thread->GetName();
790 var_success = cstr && cstr[0];
791 if (var_success)
792 s.PutCString(cstr);
793 }
794 else if (::strncmp (var_name_begin, "queue}", strlen("queue}")) == 0)
795 {
796 cstr = exe_ctx->thread->GetQueueName();
797 var_success = cstr && cstr[0];
798 if (var_success)
799 s.PutCString(cstr);
800 }
801 else if (::strncmp (var_name_begin, "stop-reason}", strlen("stop-reason}")) == 0)
802 {
803 lldb_private::StopInfo *stop_info = exe_ctx->thread->GetStopInfo ();
804 if (stop_info)
805 {
806 cstr = stop_info->GetDescription();
807 if (cstr && cstr[0])
808 {
809 s.PutCString(cstr);
810 var_success = true;
811 }
812 }
813 }
814 }
815 }
816 else if (::strncmp (var_name_begin, "target.", strlen("target.")) == 0)
817 {
818 if (sc->target_sp || (exe_ctx && exe_ctx->process))
819 {
820 Target *target = sc->target_sp.get();
821 if (target == NULL)
822 target = &exe_ctx->process->GetTarget();
823 assert (target);
824 var_name_begin += ::strlen ("target.");
825 if (::strncmp (var_name_begin, "arch}", strlen("arch}")) == 0)
826 {
827 ArchSpec arch (target->GetArchitecture ());
828 if (arch.IsValid())
829 {
830 s.PutCString (arch.AsCString());
831 var_success = true;
832 }
833 }
834 }
835 }
836 break;
837
838
839 case 'm':
840 if (::strncmp (var_name_begin, "module.", strlen("module.")) == 0)
841 {
842 Module *module = sc->module_sp.get();
843
844 if (module)
845 {
846 var_name_begin += ::strlen ("module.");
847
848 if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0)
849 {
850 if (module->GetFileSpec())
851 {
852 var_name_begin += ::strlen ("file.");
853
854 if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0)
855 {
856 format_file_spec.GetFilename() = module->GetFileSpec().GetFilename();
857 var_success = format_file_spec;
858 }
859 else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0)
860 {
861 format_file_spec = module->GetFileSpec();
862 var_success = format_file_spec;
863 }
864 }
865 }
866 }
867 }
868 break;
869
870
871 case 'f':
872 if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0)
873 {
874 if (sc && sc->comp_unit != NULL)
875 {
876 var_name_begin += ::strlen ("file.");
877
878 if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0)
879 {
880 format_file_spec.GetFilename() = sc->comp_unit->GetFilename();
881 var_success = format_file_spec;
882 }
883 else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0)
884 {
885 format_file_spec = *sc->comp_unit;
886 var_success = format_file_spec;
887 }
888 }
889 }
890 else if (::strncmp (var_name_begin, "frame.", strlen("frame.")) == 0)
891 {
892 if (exe_ctx && exe_ctx->frame)
893 {
894 var_name_begin += ::strlen ("frame.");
895 if (::strncmp (var_name_begin, "index}", strlen("index}")) == 0)
896 {
897 s.Printf("%u", exe_ctx->frame->GetFrameIndex());
898 var_success = true;
899 }
900 else if (::strncmp (var_name_begin, "pc}", strlen("pc}")) == 0)
901 {
902 reg_kind = eRegisterKindGeneric;
903 reg_num = LLDB_REGNUM_GENERIC_PC;
904 var_success = true;
905 }
906 else if (::strncmp (var_name_begin, "sp}", strlen("sp}")) == 0)
907 {
908 reg_kind = eRegisterKindGeneric;
909 reg_num = LLDB_REGNUM_GENERIC_SP;
910 var_success = true;
911 }
912 else if (::strncmp (var_name_begin, "fp}", strlen("fp}")) == 0)
913 {
914 reg_kind = eRegisterKindGeneric;
915 reg_num = LLDB_REGNUM_GENERIC_FP;
916 var_success = true;
917 }
918 else if (::strncmp (var_name_begin, "flags}", strlen("flags}")) == 0)
919 {
920 reg_kind = eRegisterKindGeneric;
921 reg_num = LLDB_REGNUM_GENERIC_FLAGS;
922 var_success = true;
923 }
924 else if (::strncmp (var_name_begin, "reg.", strlen ("reg.")) == 0)
925 {
926 reg_ctx = exe_ctx->frame->GetRegisterContext();
927 if (reg_ctx)
928 {
929 var_name_begin += ::strlen ("reg.");
930 if (var_name_begin < var_name_end)
931 {
932 std::string reg_name (var_name_begin, var_name_end);
933 reg_info = reg_ctx->GetRegisterInfoByName (reg_name.c_str());
934 if (reg_info)
935 var_success = true;
936 }
937 }
938 }
939 }
940 }
941 else if (::strncmp (var_name_begin, "function.", strlen("function.")) == 0)
942 {
943 if (sc && (sc->function != NULL || sc->symbol != NULL))
944 {
945 var_name_begin += ::strlen ("function.");
946 if (::strncmp (var_name_begin, "id}", strlen("id}")) == 0)
947 {
948 if (sc->function)
949 s.Printf("function{0x%8.8x}", sc->function->GetID());
950 else
951 s.Printf("symbol[%u]", sc->symbol->GetID());
952
953 var_success = true;
954 }
955 else if (::strncmp (var_name_begin, "name}", strlen("name}")) == 0)
956 {
957 if (sc->function)
958 cstr = sc->function->GetName().AsCString (NULL);
959 else if (sc->symbol)
960 cstr = sc->symbol->GetName().AsCString (NULL);
961 if (cstr)
962 {
963 s.PutCString(cstr);
964 var_success = true;
965 }
966 }
967 else if (::strncmp (var_name_begin, "addr-offset}", strlen("addr-offset}")) == 0)
968 {
969 var_success = addr != NULL;
970 if (var_success)
971 {
972 format_addr = *addr;
973 calculate_format_addr_function_offset = true;
974 }
975 }
976 else if (::strncmp (var_name_begin, "line-offset}", strlen("line-offset}")) == 0)
977 {
978 var_success = sc->line_entry.range.GetBaseAddress().IsValid();
979 if (var_success)
980 {
981 format_addr = sc->line_entry.range.GetBaseAddress();
982 calculate_format_addr_function_offset = true;
983 }
984 }
985 else if (::strncmp (var_name_begin, "pc-offset}", strlen("pc-offset}")) == 0)
986 {
987 var_success = exe_ctx->frame;
988 if (var_success)
989 {
990 format_addr = exe_ctx->frame->GetFrameCodeAddress();
991 calculate_format_addr_function_offset = true;
992 }
993 }
994 }
995 }
996 break;
997
998 case 'l':
999 if (::strncmp (var_name_begin, "line.", strlen("line.")) == 0)
1000 {
1001 if (sc && sc->line_entry.IsValid())
1002 {
1003 var_name_begin += ::strlen ("line.");
1004 if (::strncmp (var_name_begin, "file.", strlen("file.")) == 0)
1005 {
1006 var_name_begin += ::strlen ("file.");
1007
1008 if (::strncmp (var_name_begin, "basename}", strlen("basename}")) == 0)
1009 {
1010 format_file_spec.GetFilename() = sc->line_entry.file.GetFilename();
1011 var_success = format_file_spec;
1012 }
1013 else if (::strncmp (var_name_begin, "fullpath}", strlen("fullpath}")) == 0)
1014 {
1015 format_file_spec = sc->line_entry.file;
1016 var_success = format_file_spec;
1017 }
1018 }
1019 else if (::strncmp (var_name_begin, "number}", strlen("number}")) == 0)
1020 {
1021 var_success = true;
1022 s.Printf("%u", sc->line_entry.line);
1023 }
1024 else if ((::strncmp (var_name_begin, "start-addr}", strlen("start-addr}")) == 0) ||
1025 (::strncmp (var_name_begin, "end-addr}", strlen("end-addr}")) == 0))
1026 {
1027 var_success = sc && sc->line_entry.range.GetBaseAddress().IsValid();
1028 if (var_success)
1029 {
1030 format_addr = sc->line_entry.range.GetBaseAddress();
1031 if (var_name_begin[0] == 'e')
1032 format_addr.Slide (sc->line_entry.range.GetByteSize());
1033 }
1034 }
1035 }
1036 }
1037 break;
1038 }
1039
1040 if (var_success)
1041 {
1042 // If format addr is valid, then we need to print an address
1043 if (reg_num != LLDB_INVALID_REGNUM)
1044 {
1045 // We have a register value to display...
1046 if (reg_num == LLDB_REGNUM_GENERIC_PC && reg_kind == eRegisterKindGeneric)
1047 {
1048 format_addr = exe_ctx->frame->GetFrameCodeAddress();
1049 }
1050 else
1051 {
1052 if (reg_ctx == NULL)
1053 reg_ctx = exe_ctx->frame->GetRegisterContext();
1054
1055 if (reg_ctx)
1056 {
1057 if (reg_kind != kNumRegisterKinds)
1058 reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
1059 reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num);
1060 var_success = reg_info != NULL;
1061 }
1062 }
1063 }
1064
1065 if (reg_info != NULL)
1066 {
1067 DataExtractor reg_data;
1068 var_success = reg_ctx->ReadRegisterBytes (reg_info->kinds[eRegisterKindLLDB], reg_data);
1069 {
1070 reg_data.Dump(&s, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
1071 }
1072 }
1073
1074 if (format_file_spec)
1075 {
1076 s << format_file_spec;
1077 }
1078
1079 // If format addr is valid, then we need to print an address
1080 if (format_addr.IsValid())
1081 {
1082 if (calculate_format_addr_function_offset)
1083 {
1084 Address func_addr;
1085 if (sc->function)
1086 func_addr = sc->function->GetAddressRange().GetBaseAddress();
1087 else if (sc->symbol && sc->symbol->GetAddressRangePtr())
1088 func_addr = sc->symbol->GetAddressRangePtr()->GetBaseAddress();
1089 else
1090 var_success = false;
1091
1092 if (var_success)
1093 {
1094 if (func_addr.GetSection() == format_addr.GetSection())
1095 {
1096 addr_t func_file_addr = func_addr.GetFileAddress();
1097 addr_t addr_file_addr = format_addr.GetFileAddress();
1098 if (addr_file_addr > func_file_addr)
1099 {
1100 s.Printf(" + %llu", addr_file_addr - func_file_addr);
1101 }
1102 else if (addr_file_addr < func_file_addr)
1103 {
1104 s.Printf(" - %llu", func_file_addr - addr_file_addr);
1105 }
1106 }
1107 else
1108 var_success = false;
1109 }
1110 }
1111 else
1112 {
1113 addr_t vaddr = LLDB_INVALID_ADDRESS;
1114 if (exe_ctx && exe_ctx->process && !exe_ctx->process->GetTarget().GetSectionLoadList().IsEmpty())
1115 vaddr = format_addr.GetLoadAddress (&exe_ctx->process->GetTarget());
1116 if (vaddr == LLDB_INVALID_ADDRESS)
1117 vaddr = format_addr.GetFileAddress ();
1118
1119 if (vaddr != LLDB_INVALID_ADDRESS)
1120 s.Printf("0x%16.16llx", vaddr);
1121 else
1122 var_success = false;
1123 }
1124 }
1125 }
1126
1127 if (var_success == false)
1128 success = false;
1129 }
1130 p = var_name_end;
1131 }
1132 else
1133 break;
1134 }
1135 else
1136 {
1137 // We got a dollar sign with no '{' after it, it must just be a dollar sign
1138 s.PutChar(*p);
1139 }
1140 }
1141 else if (*p == '\\')
1142 {
1143 ++p; // skip the slash
1144 switch (*p)
1145 {
1146 case 'a': s.PutChar ('\a'); break;
1147 case 'b': s.PutChar ('\b'); break;
1148 case 'f': s.PutChar ('\f'); break;
1149 case 'n': s.PutChar ('\n'); break;
1150 case 'r': s.PutChar ('\r'); break;
1151 case 't': s.PutChar ('\t'); break;
1152 case 'v': s.PutChar ('\v'); break;
1153 case '\'': s.PutChar ('\''); break;
1154 case '\\': s.PutChar ('\\'); break;
1155 case '0':
1156 // 1 to 3 octal chars
1157 {
1158 unsigned long octal_value = 0;
1159 ++p;
1160 int i=0;
1161 for (; i<3; ++i)
1162 {
1163 if (*p >= '0' && *p <= '7')
1164 octal_value = octal_value << 3 + (((uint8_t)*p) - '0');
1165 else
1166 break;
1167 }
1168 if (i>0)
1169 s.PutChar (octal_value);
1170 else
1171 s.PutCString ("\\0");
1172 }
1173 break;
1174
1175 case 'x':
1176 // hex number in the format
1177 {
1178 ++p;
1179
1180 if (isxdigit(*p))
1181 {
1182 char hex_str[3] = { 0,0,0 };
1183 hex_str[0] = *p;
1184 ++p;
1185 if (isxdigit(*p))
1186 hex_str[1] = *p;
1187 unsigned long hex_value = strtoul (hex_str, NULL, 16);
1188 s.PutChar (hex_value);
1189 }
1190 else
1191 {
1192 s.PutCString ("\\x");
1193 }
1194 }
1195 break;
1196
1197 default:
1198 s << '\\' << *p;
1199 break;
1200
1201 }
1202
1203 }
1204 }
1205 if (end)
1206 *end = p;
1207 return success;
1208}
1209
1210#pragma mark Debugger::SettingsController
1211
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001212//--------------------------------------------------
Greg Clayton1b654882010-09-19 02:33:57 +00001213// class Debugger::SettingsController
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001214//--------------------------------------------------
1215
Greg Clayton1b654882010-09-19 02:33:57 +00001216Debugger::SettingsController::SettingsController () :
Caroline Tice101c7c22010-09-09 06:25:08 +00001217 UserSettingsController ("", lldb::UserSettingsControllerSP())
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001218{
Caroline Tice91123da2010-09-08 17:48:55 +00001219 m_default_settings.reset (new DebuggerInstanceSettings (*this, false,
1220 InstanceSettings::GetDefaultName().AsCString()));
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001221}
1222
Greg Clayton1b654882010-09-19 02:33:57 +00001223Debugger::SettingsController::~SettingsController ()
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001224{
1225}
1226
1227
1228lldb::InstanceSettingsSP
Greg Clayton1b654882010-09-19 02:33:57 +00001229Debugger::SettingsController::CreateInstanceSettings (const char *instance_name)
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001230{
Caroline Tice91123da2010-09-08 17:48:55 +00001231 DebuggerInstanceSettings *new_settings = new DebuggerInstanceSettings (*(Debugger::GetSettingsController().get()),
1232 false, instance_name);
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001233 lldb::InstanceSettingsSP new_settings_sp (new_settings);
1234 return new_settings_sp;
1235}
1236
Greg Clayton1b654882010-09-19 02:33:57 +00001237#pragma mark DebuggerInstanceSettings
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001238//--------------------------------------------------
1239// class DebuggerInstanceSettings
1240//--------------------------------------------------
1241
Greg Claytona7015092010-09-18 01:14:36 +00001242DebuggerInstanceSettings::DebuggerInstanceSettings
1243(
1244 UserSettingsController &owner,
1245 bool live_instance,
1246 const char *name
1247) :
Caroline Tice9e41c152010-09-16 19:05:55 +00001248 InstanceSettings (owner, (name == NULL ? InstanceSettings::InvalidName().AsCString() : name), live_instance),
Greg Claytona7015092010-09-18 01:14:36 +00001249 m_term_width (80),
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001250 m_prompt (),
Caroline Ticedaccaa92010-09-20 20:44:43 +00001251 m_script_lang (),
1252 m_use_external_editor (false)
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001253{
Caroline Ticef20e8232010-09-09 18:26:37 +00001254 // CopyInstanceSettings is a pure virtual function in InstanceSettings; it therefore cannot be called
1255 // until the vtables for DebuggerInstanceSettings are properly set up, i.e. AFTER all the initializers.
1256 // For this reason it has to be called here, rather than in the initializer or in the parent constructor.
Caroline Tice9e41c152010-09-16 19:05:55 +00001257 // The same is true of CreateInstanceName().
1258
1259 if (GetInstanceName() == InstanceSettings::InvalidName())
1260 {
1261 ChangeInstanceName (std::string (CreateInstanceName().AsCString()));
1262 m_owner.RegisterInstanceSettings (this);
1263 }
Caroline Ticef20e8232010-09-09 18:26:37 +00001264
1265 if (live_instance)
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001266 {
1267 const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
1268 CopyInstanceSettings (pending_settings, false);
Caroline Ticef20e8232010-09-09 18:26:37 +00001269 //m_owner.RemovePendingSettings (m_instance_name);
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001270 }
1271}
1272
1273DebuggerInstanceSettings::DebuggerInstanceSettings (const DebuggerInstanceSettings &rhs) :
1274 InstanceSettings (*(Debugger::GetSettingsController().get()), CreateInstanceName ().AsCString()),
1275 m_prompt (rhs.m_prompt),
Caroline Ticedaccaa92010-09-20 20:44:43 +00001276 m_script_lang (rhs.m_script_lang),
1277 m_use_external_editor (rhs.m_use_external_editor)
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001278{
1279 const lldb::InstanceSettingsSP &pending_settings = m_owner.FindPendingSettings (m_instance_name);
1280 CopyInstanceSettings (pending_settings, false);
1281 m_owner.RemovePendingSettings (m_instance_name);
1282}
1283
1284DebuggerInstanceSettings::~DebuggerInstanceSettings ()
1285{
1286}
1287
1288DebuggerInstanceSettings&
1289DebuggerInstanceSettings::operator= (const DebuggerInstanceSettings &rhs)
1290{
1291 if (this != &rhs)
1292 {
Greg Clayton1b654882010-09-19 02:33:57 +00001293 m_term_width = rhs.m_term_width;
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001294 m_prompt = rhs.m_prompt;
1295 m_script_lang = rhs.m_script_lang;
Caroline Ticedaccaa92010-09-20 20:44:43 +00001296 m_use_external_editor = rhs.m_use_external_editor;
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001297 }
1298
1299 return *this;
1300}
1301
Greg Clayton1b654882010-09-19 02:33:57 +00001302bool
1303DebuggerInstanceSettings::ValidTermWidthValue (const char *value, Error err)
1304{
1305 bool valid = false;
1306
1307 // Verify we have a value string.
1308 if (value == NULL || value[0] == '\0')
1309 {
1310 err.SetErrorString ("Missing value. Can't set terminal width without a value.\n");
1311 }
1312 else
1313 {
1314 char *end = NULL;
1315 const uint32_t width = ::strtoul (value, &end, 0);
1316
Johnny Chenea9fc182010-09-20 16:36:43 +00001317 if (end && end[0] == '\0')
Greg Clayton1b654882010-09-19 02:33:57 +00001318 {
Johnny Chen433d7742010-09-20 17:04:41 +00001319 if (width >= 10 && width <= 1024)
Greg Clayton1b654882010-09-19 02:33:57 +00001320 valid = true;
1321 else
1322 err.SetErrorString ("Invalid term-width value; value must be between 10 and 1024.\n");
1323 }
1324 else
1325 err.SetErrorStringWithFormat ("'%s' is not a valid unsigned integer string.\n", value);
1326 }
1327
1328 return valid;
1329}
1330
1331
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001332void
1333DebuggerInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_name,
1334 const char *index_value,
1335 const char *value,
1336 const ConstString &instance_name,
1337 const SettingEntry &entry,
1338 lldb::VarSetOperationType op,
1339 Error &err,
1340 bool pending)
1341{
1342 if (var_name == PromptVarName())
1343 {
Caroline Tice101c7c22010-09-09 06:25:08 +00001344 UserSettingsController::UpdateStringVariable (op, m_prompt, value, err);
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001345 if (!pending)
1346 {
Caroline Tice49e27372010-09-07 18:35:40 +00001347 // 'instance_name' is actually (probably) in the form '[<instance_name>]'; if so, we need to
1348 // strip off the brackets before passing it to BroadcastPromptChange.
1349
1350 std::string tmp_instance_name (instance_name.AsCString());
1351 if ((tmp_instance_name[0] == '[')
1352 && (tmp_instance_name[instance_name.GetLength() - 1] == ']'))
1353 tmp_instance_name = tmp_instance_name.substr (1, instance_name.GetLength() - 2);
1354 ConstString new_name (tmp_instance_name.c_str());
1355
1356 BroadcastPromptChange (new_name, m_prompt.c_str());
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001357 }
1358 }
1359 else if (var_name == ScriptLangVarName())
1360 {
1361 bool success;
1362 m_script_lang = Args::StringToScriptLanguage (value, eScriptLanguageDefault,
1363 &success);
1364 }
Caroline Tice101c7c22010-09-09 06:25:08 +00001365 else if (var_name == TermWidthVarName())
1366 {
1367 if (ValidTermWidthValue (value, err))
1368 {
Greg Claytona7015092010-09-18 01:14:36 +00001369 m_term_width = ::strtoul (value, NULL, 0);
Caroline Tice101c7c22010-09-09 06:25:08 +00001370 }
1371 }
Caroline Ticedaccaa92010-09-20 20:44:43 +00001372 else if (var_name == UseExternalEditorVarName ())
1373 {
1374 UserSettingsController::UpdateBooleanVariable (op, m_use_external_editor, value, err);
1375 }
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001376}
1377
1378void
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001379DebuggerInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry,
1380 const ConstString &var_name,
Caroline Ticedaccaa92010-09-20 20:44:43 +00001381 StringList &value,
1382 Error &err)
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001383{
1384 if (var_name == PromptVarName())
1385 {
1386 value.AppendString (m_prompt.c_str());
1387
1388 }
1389 else if (var_name == ScriptLangVarName())
1390 {
1391 value.AppendString (ScriptInterpreter::LanguageToString (m_script_lang).c_str());
1392 }
Caroline Tice101c7c22010-09-09 06:25:08 +00001393 else if (var_name == TermWidthVarName())
1394 {
1395 StreamString width_str;
1396 width_str.Printf ("%d", m_term_width);
1397 value.AppendString (width_str.GetData());
1398 }
Caroline Ticedaccaa92010-09-20 20:44:43 +00001399 else if (var_name == UseExternalEditorVarName())
1400 {
1401 if (m_use_external_editor)
1402 value.AppendString ("true");
1403 else
1404 value.AppendString ("false");
1405 }
1406 else
1407 err.SetErrorStringWithFormat ("unrecognized variable name '%s'", var_name.AsCString());
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001408}
1409
1410void
1411DebuggerInstanceSettings::CopyInstanceSettings (const lldb::InstanceSettingsSP &new_settings,
1412 bool pending)
1413{
1414 if (new_settings.get() == NULL)
1415 return;
1416
1417 DebuggerInstanceSettings *new_debugger_settings = (DebuggerInstanceSettings *) new_settings.get();
1418
1419 m_prompt = new_debugger_settings->m_prompt;
1420 if (!pending)
Caroline Tice49e27372010-09-07 18:35:40 +00001421 {
1422 // 'instance_name' is actually (probably) in the form '[<instance_name>]'; if so, we need to
1423 // strip off the brackets before passing it to BroadcastPromptChange.
1424
1425 std::string tmp_instance_name (m_instance_name.AsCString());
1426 if ((tmp_instance_name[0] == '[')
1427 && (tmp_instance_name[m_instance_name.GetLength() - 1] == ']'))
1428 tmp_instance_name = tmp_instance_name.substr (1, m_instance_name.GetLength() - 2);
1429 ConstString new_name (tmp_instance_name.c_str());
1430
1431 BroadcastPromptChange (new_name, m_prompt.c_str());
1432 }
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001433
Caroline Ticedaccaa92010-09-20 20:44:43 +00001434 m_term_width = new_debugger_settings->m_term_width;
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001435 m_script_lang = new_debugger_settings->m_script_lang;
Caroline Ticedaccaa92010-09-20 20:44:43 +00001436 m_use_external_editor = new_debugger_settings->m_use_external_editor;
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001437}
1438
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001439
1440bool
1441DebuggerInstanceSettings::BroadcastPromptChange (const ConstString &instance_name, const char *new_prompt)
1442{
1443 std::string tmp_prompt;
1444
1445 if (new_prompt != NULL)
1446 {
1447 tmp_prompt = new_prompt ;
1448 int len = tmp_prompt.size();
1449 if (len > 1
1450 && (tmp_prompt[0] == '\'' || tmp_prompt[0] == '"')
1451 && (tmp_prompt[len-1] == tmp_prompt[0]))
1452 {
1453 tmp_prompt = tmp_prompt.substr(1,len-2);
1454 }
1455 len = tmp_prompt.size();
1456 if (tmp_prompt[len-1] != ' ')
1457 tmp_prompt.append(" ");
1458 }
1459 EventSP new_event_sp;
1460 new_event_sp.reset (new Event(CommandInterpreter::eBroadcastBitResetPrompt,
1461 new EventDataBytes (tmp_prompt.c_str())));
1462
1463 if (instance_name.GetLength() != 0)
1464 {
1465 // Set prompt for a particular instance.
1466 Debugger *dbg = Debugger::FindDebuggerWithInstanceName (instance_name).get();
1467 if (dbg != NULL)
1468 {
1469 dbg->GetCommandInterpreter().BroadcastEvent (new_event_sp);
1470 }
1471 }
1472
1473 return true;
1474}
1475
1476const ConstString
1477DebuggerInstanceSettings::CreateInstanceName ()
1478{
1479 static int instance_count = 1;
1480 StreamString sstr;
1481
1482 sstr.Printf ("debugger_%d", instance_count);
1483 ++instance_count;
1484
1485 const ConstString ret_val (sstr.GetData());
1486
1487 return ret_val;
1488}
1489
1490const ConstString &
1491DebuggerInstanceSettings::PromptVarName ()
1492{
1493 static ConstString prompt_var_name ("prompt");
1494
1495 return prompt_var_name;
1496}
1497
1498const ConstString &
1499DebuggerInstanceSettings::ScriptLangVarName ()
1500{
1501 static ConstString script_lang_var_name ("script-lang");
1502
1503 return script_lang_var_name;
1504}
1505
Caroline Tice101c7c22010-09-09 06:25:08 +00001506const ConstString &
1507DebuggerInstanceSettings::TermWidthVarName ()
1508{
1509 static ConstString term_width_var_name ("term-width");
1510
1511 return term_width_var_name;
1512}
1513
Caroline Ticedaccaa92010-09-20 20:44:43 +00001514const ConstString &
1515DebuggerInstanceSettings::UseExternalEditorVarName ()
1516{
1517 static ConstString use_external_editor_var_name ("use-external-editor");
1518
1519 return use_external_editor_var_name;
1520}
1521
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001522//--------------------------------------------------
Greg Clayton1b654882010-09-19 02:33:57 +00001523// SettingsController Variable Tables
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001524//--------------------------------------------------
1525
1526
1527SettingEntry
Greg Clayton1b654882010-09-19 02:33:57 +00001528Debugger::SettingsController::global_settings_table[] =
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001529{
1530 //{ "var-name", var-type, "default", enum-table, init'd, hidden, "help-text"},
Caroline Tice101c7c22010-09-09 06:25:08 +00001531 // The Debugger level global table should always be empty; all Debugger settable variables should be instance
1532 // variables.
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001533 { NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
1534};
1535
1536
1537
1538SettingEntry
Greg Clayton1b654882010-09-19 02:33:57 +00001539Debugger::SettingsController::instance_settings_table[] =
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001540{
1541 //{ "var-name", var-type , "default", enum-table, init'd, hidden, "help-text"},
Caroline Tice101c7c22010-09-09 06:25:08 +00001542 { "term-width" , eSetVarTypeInt, "80" , NULL, false , false , "The maximum number of columns to use for displaying text." },
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001543 { "script-lang" , eSetVarTypeString, "python", NULL, false, false, "The script language to be used for evaluating user-written scripts." },
1544 { "prompt" , eSetVarTypeString, "(lldb)", NULL, false, false, "The debugger command line prompt displayed for the user." },
Caroline Ticedaccaa92010-09-20 20:44:43 +00001545 { "use-external-editor", eSetVarTypeBool, "false", NULL, false, false, "Whether to use an external editor or not." },
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001546 { NULL, eSetVarTypeNone, NULL, NULL, 0, 0, NULL }
1547};