Bug Summary

File:tools/lldb/source/Core/Debugger.cpp
Location:line 2649, column 41
Description:Value stored to 'var_success' is never read

Annotated Source Code

1//===-- 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-python.h"
11
12#include "lldb/Core/Debugger.h"
13
14#include <map>
15
16#include "clang/AST/DeclCXX.h"
17#include "clang/AST/Type.h"
18#include "llvm/ADT/StringRef.h"
19
20#include "lldb/lldb-private.h"
21#include "lldb/Core/Module.h"
22#include "lldb/Core/PluginManager.h"
23#include "lldb/Core/RegisterValue.h"
24#include "lldb/Core/State.h"
25#include "lldb/Core/StreamAsynchronousIO.h"
26#include "lldb/Core/StreamCallback.h"
27#include "lldb/Core/StreamFile.h"
28#include "lldb/Core/StreamString.h"
29#include "lldb/Core/StructuredData.h"
30#include "lldb/Core/Timer.h"
31#include "lldb/Core/ValueObject.h"
32#include "lldb/Core/ValueObjectVariable.h"
33#include "lldb/DataFormatters/DataVisualization.h"
34#include "lldb/DataFormatters/FormatManager.h"
35#include "lldb/DataFormatters/TypeSummary.h"
36#include "lldb/Host/ConnectionFileDescriptor.h"
37#include "lldb/Host/HostInfo.h"
38#include "lldb/Host/Terminal.h"
39#include "lldb/Host/ThreadLauncher.h"
40#include "lldb/Interpreter/CommandInterpreter.h"
41#include "lldb/Interpreter/OptionValueSInt64.h"
42#include "lldb/Interpreter/OptionValueString.h"
43#include "lldb/Symbol/ClangASTContext.h"
44#include "lldb/Symbol/CompileUnit.h"
45#include "lldb/Symbol/Function.h"
46#include "lldb/Symbol/Symbol.h"
47#include "lldb/Symbol/VariableList.h"
48#include "lldb/Target/CPPLanguageRuntime.h"
49#include "lldb/Target/ObjCLanguageRuntime.h"
50#include "lldb/Target/TargetList.h"
51#include "lldb/Target/Process.h"
52#include "lldb/Target/RegisterContext.h"
53#include "lldb/Target/SectionLoadList.h"
54#include "lldb/Target/StopInfo.h"
55#include "lldb/Target/Target.h"
56#include "lldb/Target/Thread.h"
57#include "lldb/Utility/AnsiTerminal.h"
58
59#include "llvm/Support/DynamicLibrary.h"
60
61using namespace lldb;
62using namespace lldb_private;
63
64
65static uint32_t g_shared_debugger_refcount = 0;
66static lldb::user_id_t g_unique_id = 1;
67static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024;
68
69#pragma mark Static Functions
70
71static Mutex &
72GetDebuggerListMutex ()
73{
74 static Mutex g_mutex(Mutex::eMutexTypeRecursive);
75 return g_mutex;
76}
77
78typedef std::vector<DebuggerSP> DebuggerList;
79
80static DebuggerList &
81GetDebuggerList()
82{
83 // hide the static debugger list inside a singleton accessor to avoid
84 // global init constructors
85 static DebuggerList g_list;
86 return g_list;
87}
88
89OptionEnumValueElement
90g_show_disassembly_enum_values[] =
91{
92 { Debugger::eStopDisassemblyTypeNever, "never", "Never show disassembly when displaying a stop context."},
93 { Debugger::eStopDisassemblyTypeNoSource, "no-source", "Show disassembly when there is no source information, or the source file is missing when displaying a stop context."},
94 { Debugger::eStopDisassemblyTypeAlways, "always", "Always show disassembly when displaying a stop context."},
95 { 0, NULL__null, NULL__null }
96};
97
98OptionEnumValueElement
99g_language_enumerators[] =
100{
101 { eScriptLanguageNone, "none", "Disable scripting languages."},
102 { eScriptLanguagePython, "python", "Select python as the default scripting language."},
103 { eScriptLanguageDefault, "default", "Select the lldb default as the default scripting language."},
104 { 0, NULL__null, NULL__null }
105};
106
107#define MODULE_WITH_FUNC"{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}" "{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}"
108#define FILE_AND_LINE"{ at ${line.file.basename}:${line.number}}" "{ at ${line.file.basename}:${line.number}}"
109
110#define DEFAULT_THREAD_FORMAT"thread #${thread.index}: tid = ${thread.id%tid}" "{, ${frame.pc}}"
"{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}"
"{ at ${line.file.basename}:${line.number}}" "{, name = '${thread.name}'}"
"{, queue = '${thread.queue}'}" "{, activity = '${thread.info.activity.name}'}"
"{, ${thread.info.trace_messages} messages}" "{, stop reason = ${thread.stop-reason}}"
"{\\nReturn value: ${thread.return-value}}" "{\\nCompleted expression: ${thread.completed-expression}}"
"\\n"
"thread #${thread.index}: tid = ${thread.id%tid}"\
111 "{, ${frame.pc}}"\
112 MODULE_WITH_FUNC"{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}"\
113 FILE_AND_LINE"{ at ${line.file.basename}:${line.number}}"\
114 "{, name = '${thread.name}'}"\
115 "{, queue = '${thread.queue}'}"\
116 "{, activity = '${thread.info.activity.name}'}" \
117 "{, ${thread.info.trace_messages} messages}" \
118 "{, stop reason = ${thread.stop-reason}}"\
119 "{\\nReturn value: ${thread.return-value}}"\
120 "{\\nCompleted expression: ${thread.completed-expression}}"\
121 "\\n"
122
123#define DEFAULT_FRAME_FORMAT"frame #${frame.index}: ${frame.pc}" "{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}"
"{ at ${line.file.basename}:${line.number}}" "\\n"
"frame #${frame.index}: ${frame.pc}"\
124 MODULE_WITH_FUNC"{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}"\
125 FILE_AND_LINE"{ at ${line.file.basename}:${line.number}}"\
126 "\\n"
127
128#define DEFAULT_DISASSEMBLY_FORMAT"${current-pc-arrow}${addr-file-or-load}{ <${function.name-without-args}${function.concrete-only-addr-offset-no-padding}>}: " "${current-pc-arrow}${addr-file-or-load}{ <${function.name-without-args}${function.concrete-only-addr-offset-no-padding}>}: "
129
130static PropertyDefinition
131g_properties[] =
132{
133{ "auto-confirm", OptionValue::eTypeBoolean, true, false, NULL__null, NULL__null, "If true all confirmation prompts will receive their default reply." },
134{ "disassembly-format", OptionValue::eTypeString , true, 0 , DEFAULT_DISASSEMBLY_FORMAT"${current-pc-arrow}${addr-file-or-load}{ <${function.name-without-args}${function.concrete-only-addr-offset-no-padding}>}: ", NULL__null, "The default disassembly format string to use when disassembling instruction sequences." },
135{ "frame-format", OptionValue::eTypeString , true, 0 , DEFAULT_FRAME_FORMAT"frame #${frame.index}: ${frame.pc}" "{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}"
"{ at ${line.file.basename}:${line.number}}" "\\n"
, NULL__null, "The default frame format string to use when displaying stack frame information for threads." },
136{ "notify-void", OptionValue::eTypeBoolean, true, false, NULL__null, NULL__null, "Notify the user explicitly if an expression returns void (default: false)." },
137{ "prompt", OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", NULL__null, "The debugger command line prompt displayed for the user." },
138{ "script-lang", OptionValue::eTypeEnum , true, eScriptLanguagePython, NULL__null, g_language_enumerators, "The script language to be used for evaluating user-written scripts." },
139{ "stop-disassembly-count", OptionValue::eTypeSInt64 , true, 4 , NULL__null, NULL__null, "The number of disassembly lines to show when displaying a stopped context." },
140{ "stop-disassembly-display", OptionValue::eTypeEnum , true, Debugger::eStopDisassemblyTypeNoSource, NULL__null, g_show_disassembly_enum_values, "Control when to display disassembly when displaying a stopped context." },
141{ "stop-line-count-after", OptionValue::eTypeSInt64 , true, 3 , NULL__null, NULL__null, "The number of sources lines to display that come after the current source line when displaying a stopped context." },
142{ "stop-line-count-before", OptionValue::eTypeSInt64 , true, 3 , NULL__null, NULL__null, "The number of sources lines to display that come before the current source line when displaying a stopped context." },
143{ "term-width", OptionValue::eTypeSInt64 , true, 80 , NULL__null, NULL__null, "The maximum number of columns to use for displaying text." },
144{ "thread-format", OptionValue::eTypeString , true, 0 , DEFAULT_THREAD_FORMAT"thread #${thread.index}: tid = ${thread.id%tid}" "{, ${frame.pc}}"
"{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}"
"{ at ${line.file.basename}:${line.number}}" "{, name = '${thread.name}'}"
"{, queue = '${thread.queue}'}" "{, activity = '${thread.info.activity.name}'}"
"{, ${thread.info.trace_messages} messages}" "{, stop reason = ${thread.stop-reason}}"
"{\\nReturn value: ${thread.return-value}}" "{\\nCompleted expression: ${thread.completed-expression}}"
"\\n"
, NULL__null, "The default thread format string to use when displaying thread information." },
145{ "use-external-editor", OptionValue::eTypeBoolean, true, false, NULL__null, NULL__null, "Whether to use an external editor or not." },
146{ "use-color", OptionValue::eTypeBoolean, true, true , NULL__null, NULL__null, "Whether to use Ansi color codes or not." },
147{ "auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, NULL__null, NULL__null, "If true, LLDB will automatically display small structs in one-liner format (default: true)." },
148{ "escape-non-printables", OptionValue::eTypeBoolean, true, true, NULL__null, NULL__null, "If true, LLDB will automatically escape non-printable and escape characters when formatting strings." },
149
150 { NULL__null, OptionValue::eTypeInvalid, true, 0 , NULL__null, NULL__null, NULL__null }
151};
152
153enum
154{
155 ePropertyAutoConfirm = 0,
156 ePropertyDisassemblyFormat,
157 ePropertyFrameFormat,
158 ePropertyNotiftVoid,
159 ePropertyPrompt,
160 ePropertyScriptLanguage,
161 ePropertyStopDisassemblyCount,
162 ePropertyStopDisassemblyDisplay,
163 ePropertyStopLineCountAfter,
164 ePropertyStopLineCountBefore,
165 ePropertyTerminalWidth,
166 ePropertyThreadFormat,
167 ePropertyUseExternalEditor,
168 ePropertyUseColor,
169 ePropertyAutoOneLineSummaries,
170 ePropertyEscapeNonPrintables
171};
172
173Debugger::LoadPluginCallbackType Debugger::g_load_plugin_callback = NULL__null;
174
175Error
176Debugger::SetPropertyValue (const ExecutionContext *exe_ctx,
177 VarSetOperationType op,
178 const char *property_path,
179 const char *value)
180{
181 bool is_load_script = strcmp(property_path,"target.load-script-from-symbol-file") == 0;
182 bool is_escape_non_printables = strcmp(property_path, "escape-non-printables") == 0;
183 TargetSP target_sp;
184 LoadScriptFromSymFile load_script_old_value;
185 if (is_load_script && exe_ctx->GetTargetSP())
186 {
187 target_sp = exe_ctx->GetTargetSP();
188 load_script_old_value = target_sp->TargetProperties::GetLoadScriptFromSymbolFile();
189 }
190 Error error (Properties::SetPropertyValue (exe_ctx, op, property_path, value));
191 if (error.Success())
192 {
193 // FIXME it would be nice to have "on-change" callbacks for properties
194 if (strcmp(property_path, g_properties[ePropertyPrompt].name) == 0)
195 {
196 const char *new_prompt = GetPrompt();
197 std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes (new_prompt, GetUseColor());
198 if (str.length())
199 new_prompt = str.c_str();
200 GetCommandInterpreter().UpdatePrompt(new_prompt);
201 EventSP prompt_change_event_sp (new Event(CommandInterpreter::eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));
202 GetCommandInterpreter().BroadcastEvent (prompt_change_event_sp);
203 }
204 else if (strcmp(property_path, g_properties[ePropertyUseColor].name) == 0)
205 {
206 // use-color changed. Ping the prompt so it can reset the ansi terminal codes.
207 SetPrompt (GetPrompt());
208 }
209 else if (is_load_script && target_sp && load_script_old_value == eLoadScriptFromSymFileWarn)
210 {
211 if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() == eLoadScriptFromSymFileTrue)
212 {
213 std::list<Error> errors;
214 StreamString feedback_stream;
215 if (!target_sp->LoadScriptingResources(errors,&feedback_stream))
216 {
217 StreamFileSP stream_sp (GetErrorFile());
218 if (stream_sp)
219 {
220 for (auto error : errors)
221 {
222 stream_sp->Printf("%s\n",error.AsCString());
223 }
224 if (feedback_stream.GetSize())
225 stream_sp->Printf("%s",feedback_stream.GetData());
226 }
227 }
228 }
229 }
230 else if (is_escape_non_printables)
231 {
232 DataVisualization::ForceUpdate();
233 }
234 }
235 return error;
236}
237
238bool
239Debugger::GetAutoConfirm () const
240{
241 const uint32_t idx = ePropertyAutoConfirm;
242 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL__null, idx, g_properties[idx].default_uint_value != 0);
243}
244
245const char *
246Debugger::GetDisassemblyFormat() const
247{
248 const uint32_t idx = ePropertyDisassemblyFormat;
249 return m_collection_sp->GetPropertyAtIndexAsString (NULL__null, idx, g_properties[idx].default_cstr_value);
250}
251
252const char *
253Debugger::GetFrameFormat() const
254{
255 const uint32_t idx = ePropertyFrameFormat;
256 return m_collection_sp->GetPropertyAtIndexAsString (NULL__null, idx, g_properties[idx].default_cstr_value);
257}
258
259bool
260Debugger::GetNotifyVoid () const
261{
262 const uint32_t idx = ePropertyNotiftVoid;
263 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL__null, idx, g_properties[idx].default_uint_value != 0);
264}
265
266const char *
267Debugger::GetPrompt() const
268{
269 const uint32_t idx = ePropertyPrompt;
270 return m_collection_sp->GetPropertyAtIndexAsString (NULL__null, idx, g_properties[idx].default_cstr_value);
271}
272
273void
274Debugger::SetPrompt(const char *p)
275{
276 const uint32_t idx = ePropertyPrompt;
277 m_collection_sp->SetPropertyAtIndexAsString (NULL__null, idx, p);
278 const char *new_prompt = GetPrompt();
279 std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes (new_prompt, GetUseColor());
280 if (str.length())
281 new_prompt = str.c_str();
282 GetCommandInterpreter().UpdatePrompt(new_prompt);
283}
284
285const char *
286Debugger::GetThreadFormat() const
287{
288 const uint32_t idx = ePropertyThreadFormat;
289 return m_collection_sp->GetPropertyAtIndexAsString (NULL__null, idx, g_properties[idx].default_cstr_value);
290}
291
292lldb::ScriptLanguage
293Debugger::GetScriptLanguage() const
294{
295 const uint32_t idx = ePropertyScriptLanguage;
296 return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL__null, idx, g_properties[idx].default_uint_value);
297}
298
299bool
300Debugger::SetScriptLanguage (lldb::ScriptLanguage script_lang)
301{
302 const uint32_t idx = ePropertyScriptLanguage;
303 return m_collection_sp->SetPropertyAtIndexAsEnumeration (NULL__null, idx, script_lang);
304}
305
306uint32_t
307Debugger::GetTerminalWidth () const
308{
309 const uint32_t idx = ePropertyTerminalWidth;
310 return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL__null, idx, g_properties[idx].default_uint_value);
311}
312
313bool
314Debugger::SetTerminalWidth (uint32_t term_width)
315{
316 const uint32_t idx = ePropertyTerminalWidth;
317 return m_collection_sp->SetPropertyAtIndexAsSInt64 (NULL__null, idx, term_width);
318}
319
320bool
321Debugger::GetUseExternalEditor () const
322{
323 const uint32_t idx = ePropertyUseExternalEditor;
324 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL__null, idx, g_properties[idx].default_uint_value != 0);
325}
326
327bool
328Debugger::SetUseExternalEditor (bool b)
329{
330 const uint32_t idx = ePropertyUseExternalEditor;
331 return m_collection_sp->SetPropertyAtIndexAsBoolean (NULL__null, idx, b);
332}
333
334bool
335Debugger::GetUseColor () const
336{
337 const uint32_t idx = ePropertyUseColor;
338 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL__null, idx, g_properties[idx].default_uint_value != 0);
339}
340
341bool
342Debugger::SetUseColor (bool b)
343{
344 const uint32_t idx = ePropertyUseColor;
345 bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean (NULL__null, idx, b);
346 SetPrompt (GetPrompt());
347 return ret;
348}
349
350uint32_t
351Debugger::GetStopSourceLineCount (bool before) const
352{
353 const uint32_t idx = before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter;
354 return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL__null, idx, g_properties[idx].default_uint_value);
355}
356
357Debugger::StopDisassemblyType
358Debugger::GetStopDisassemblyDisplay () const
359{
360 const uint32_t idx = ePropertyStopDisassemblyDisplay;
361 return (Debugger::StopDisassemblyType)m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL__null, idx, g_properties[idx].default_uint_value);
362}
363
364uint32_t
365Debugger::GetDisassemblyLineCount () const
366{
367 const uint32_t idx = ePropertyStopDisassemblyCount;
368 return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL__null, idx, g_properties[idx].default_uint_value);
369}
370
371bool
372Debugger::GetAutoOneLineSummaries () const
373{
374 const uint32_t idx = ePropertyAutoOneLineSummaries;
375 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL__null, idx, true);
376}
377
378bool
379Debugger::GetEscapeNonPrintables () const
380{
381 const uint32_t idx = ePropertyEscapeNonPrintables;
382 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL__null, idx, true);
383}
384
385#pragma mark Debugger
386
387//const DebuggerPropertiesSP &
388//Debugger::GetSettings() const
389//{
390// return m_properties_sp;
391//}
392//
393
394int
395Debugger::TestDebuggerRefCount ()
396{
397 return g_shared_debugger_refcount;
398}
399
400void
401Debugger::Initialize (LoadPluginCallbackType load_plugin_callback)
402{
403 g_load_plugin_callback = load_plugin_callback;
404 if (g_shared_debugger_refcount++ == 0)
405 lldb_private::Initialize();
406}
407
408void
409Debugger::Terminate ()
410{
411 if (g_shared_debugger_refcount > 0)
412 {
413 g_shared_debugger_refcount--;
414 if (g_shared_debugger_refcount == 0)
415 {
416 lldb_private::WillTerminate();
417 lldb_private::Terminate();
418
419 // Clear our master list of debugger objects
420 Mutex::Locker locker (GetDebuggerListMutex ());
421 GetDebuggerList().clear();
422 }
423 }
424}
425
426void
427Debugger::SettingsInitialize ()
428{
429 Target::SettingsInitialize ();
430}
431
432void
433Debugger::SettingsTerminate ()
434{
435 Target::SettingsTerminate ();
436}
437
438bool
439Debugger::LoadPlugin (const FileSpec& spec, Error& error)
440{
441 if (g_load_plugin_callback)
442 {
443 llvm::sys::DynamicLibrary dynlib = g_load_plugin_callback (shared_from_this(), spec, error);
444 if (dynlib.isValid())
445 {
446 m_loaded_plugins.push_back(dynlib);
447 return true;
448 }
449 }
450 else
451 {
452 // The g_load_plugin_callback is registered in SBDebugger::Initialize()
453 // and if the public API layer isn't available (code is linking against
454 // all of the internal LLDB static libraries), then we can't load plugins
455 error.SetErrorString("Public API layer is not available");
456 }
457 return false;
458}
459
460static FileSpec::EnumerateDirectoryResult
461LoadPluginCallback
462(
463 void *baton,
464 FileSpec::FileType file_type,
465 const FileSpec &file_spec
466 )
467{
468 Error error;
469
470 static ConstString g_dylibext("dylib");
471 static ConstString g_solibext("so");
472
473 if (!baton)
474 return FileSpec::eEnumerateDirectoryResultQuit;
475
476 Debugger *debugger = (Debugger*)baton;
477
478 // If we have a regular file, a symbolic link or unknown file type, try
479 // and process the file. We must handle unknown as sometimes the directory
480 // enumeration might be enumerating a file system that doesn't have correct
481 // file type information.
482 if (file_type == FileSpec::eFileTypeRegular ||
483 file_type == FileSpec::eFileTypeSymbolicLink ||
484 file_type == FileSpec::eFileTypeUnknown )
485 {
486 FileSpec plugin_file_spec (file_spec);
487 plugin_file_spec.ResolvePath ();
488
489 if (plugin_file_spec.GetFileNameExtension() != g_dylibext &&
490 plugin_file_spec.GetFileNameExtension() != g_solibext)
491 {
492 return FileSpec::eEnumerateDirectoryResultNext;
493 }
494
495 Error plugin_load_error;
496 debugger->LoadPlugin (plugin_file_spec, plugin_load_error);
497
498 return FileSpec::eEnumerateDirectoryResultNext;
499 }
500
501 else if (file_type == FileSpec::eFileTypeUnknown ||
502 file_type == FileSpec::eFileTypeDirectory ||
503 file_type == FileSpec::eFileTypeSymbolicLink )
504 {
505 // Try and recurse into anything that a directory or symbolic link.
506 // We must also do this for unknown as sometimes the directory enumeration
507 // might be enumerating a file system that doesn't have correct file type
508 // information.
509 return FileSpec::eEnumerateDirectoryResultEnter;
510 }
511
512 return FileSpec::eEnumerateDirectoryResultNext;
513}
514
515void
516Debugger::InstanceInitialize ()
517{
518 FileSpec dir_spec;
519 const bool find_directories = true;
520 const bool find_files = true;
521 const bool find_other = true;
522 char dir_path[PATH_MAX4096];
523 if (HostInfo::GetLLDBPath(ePathTypeLLDBSystemPlugins, dir_spec))
524 {
525 if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path)))
526 {
527 FileSpec::EnumerateDirectory (dir_path,
528 find_directories,
529 find_files,
530 find_other,
531 LoadPluginCallback,
532 this);
533 }
534 }
535
536 if (HostInfo::GetLLDBPath(ePathTypeLLDBUserPlugins, dir_spec))
537 {
538 if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path)))
539 {
540 FileSpec::EnumerateDirectory (dir_path,
541 find_directories,
542 find_files,
543 find_other,
544 LoadPluginCallback,
545 this);
546 }
547 }
548
549 PluginManager::DebuggerInitialize (*this);
550}
551
552DebuggerSP
553Debugger::CreateInstance (lldb::LogOutputCallback log_callback, void *baton)
554{
555 DebuggerSP debugger_sp (new Debugger(log_callback, baton));
556 if (g_shared_debugger_refcount > 0)
557 {
558 Mutex::Locker locker (GetDebuggerListMutex ());
559 GetDebuggerList().push_back(debugger_sp);
560 }
561 debugger_sp->InstanceInitialize ();
562 return debugger_sp;
563}
564
565void
566Debugger::Destroy (DebuggerSP &debugger_sp)
567{
568 if (debugger_sp.get() == NULL__null)
569 return;
570
571 debugger_sp->Clear();
572
573 if (g_shared_debugger_refcount > 0)
574 {
575 Mutex::Locker locker (GetDebuggerListMutex ());
576 DebuggerList &debugger_list = GetDebuggerList ();
577 DebuggerList::iterator pos, end = debugger_list.end();
578 for (pos = debugger_list.begin (); pos != end; ++pos)
579 {
580 if ((*pos).get() == debugger_sp.get())
581 {
582 debugger_list.erase (pos);
583 return;
584 }
585 }
586 }
587}
588
589DebuggerSP
590Debugger::FindDebuggerWithInstanceName (const ConstString &instance_name)
591{
592 DebuggerSP debugger_sp;
593 if (g_shared_debugger_refcount > 0)
594 {
595 Mutex::Locker locker (GetDebuggerListMutex ());
596 DebuggerList &debugger_list = GetDebuggerList();
597 DebuggerList::iterator pos, end = debugger_list.end();
598
599 for (pos = debugger_list.begin(); pos != end; ++pos)
600 {
601 if ((*pos).get()->m_instance_name == instance_name)
602 {
603 debugger_sp = *pos;
604 break;
605 }
606 }
607 }
608 return debugger_sp;
609}
610
611TargetSP
612Debugger::FindTargetWithProcessID (lldb::pid_t pid)
613{
614 TargetSP target_sp;
615 if (g_shared_debugger_refcount > 0)
616 {
617 Mutex::Locker locker (GetDebuggerListMutex ());
618 DebuggerList &debugger_list = GetDebuggerList();
619 DebuggerList::iterator pos, end = debugger_list.end();
620 for (pos = debugger_list.begin(); pos != end; ++pos)
621 {
622 target_sp = (*pos)->GetTargetList().FindTargetWithProcessID (pid);
623 if (target_sp)
624 break;
625 }
626 }
627 return target_sp;
628}
629
630TargetSP
631Debugger::FindTargetWithProcess (Process *process)
632{
633 TargetSP target_sp;
634 if (g_shared_debugger_refcount > 0)
635 {
636 Mutex::Locker locker (GetDebuggerListMutex ());
637 DebuggerList &debugger_list = GetDebuggerList();
638 DebuggerList::iterator pos, end = debugger_list.end();
639 for (pos = debugger_list.begin(); pos != end; ++pos)
640 {
641 target_sp = (*pos)->GetTargetList().FindTargetWithProcess (process);
642 if (target_sp)
643 break;
644 }
645 }
646 return target_sp;
647}
648
649Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton) :
650 UserID(g_unique_id++),
651 Properties(OptionValuePropertiesSP(new OptionValueProperties())),
652 m_input_file_sp(new StreamFile(stdinstdin, false)),
653 m_output_file_sp(new StreamFile(stdoutstdout, false)),
654 m_error_file_sp(new StreamFile(stderrstderr, false)),
655 m_terminal_state(),
656 m_target_list(*this),
657 m_platform_list(),
658 m_listener("lldb.Debugger"),
659 m_source_manager_ap(),
660 m_source_file_cache(),
661 m_command_interpreter_ap(new CommandInterpreter(*this, eScriptLanguageDefault, false)),
662 m_input_reader_stack(),
663 m_instance_name(),
664 m_loaded_plugins(),
665 m_event_handler_thread (),
666 m_io_handler_thread (),
667 m_sync_broadcaster (NULL__null, "lldb.debugger.sync")
668{
669 char instance_cstr[256];
670 snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID());
671 m_instance_name.SetCString(instance_cstr);
672 if (log_callback)
673 m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton));
674 m_command_interpreter_ap->Initialize ();
675 // Always add our default platform to the platform list
676 PlatformSP default_platform_sp (Platform::GetHostPlatform());
677 assert (default_platform_sp.get())((default_platform_sp.get()) ? static_cast<void> (0) : __assert_fail
("default_platform_sp.get()", "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn227765/tools/lldb/source/Core/Debugger.cpp"
, 677, __PRETTY_FUNCTION__))
;
678 m_platform_list.Append (default_platform_sp, true);
679
680 m_collection_sp->Initialize (g_properties);
681 m_collection_sp->AppendProperty (ConstString("target"),
682 ConstString("Settings specify to debugging targets."),
683 true,
684 Target::GetGlobalProperties()->GetValueProperties());
685 if (m_command_interpreter_ap.get())
686 {
687 m_collection_sp->AppendProperty (ConstString("interpreter"),
688 ConstString("Settings specify to the debugger's command interpreter."),
689 true,
690 m_command_interpreter_ap->GetValueProperties());
691 }
692 OptionValueSInt64 *term_width = m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64 (NULL__null, ePropertyTerminalWidth);
693 term_width->SetMinimumValue(10);
694 term_width->SetMaximumValue(1024);
695
696 // Turn off use-color if this is a dumb terminal.
697 const char *term = getenv ("TERM");
698 if (term && !strcmp (term, "dumb"))
699 SetUseColor (false);
700}
701
702Debugger::~Debugger ()
703{
704 Clear();
705}
706
707void
708Debugger::Clear()
709{
710 ClearIOHandlers();
711 StopIOHandlerThread();
712 StopEventHandlerThread();
713 m_listener.Clear();
714 int num_targets = m_target_list.GetNumTargets();
715 for (int i = 0; i < num_targets; i++)
716 {
717 TargetSP target_sp (m_target_list.GetTargetAtIndex (i));
718 if (target_sp)
719 {
720 ProcessSP process_sp (target_sp->GetProcessSP());
721 if (process_sp)
722 process_sp->Finalize();
723 target_sp->Destroy();
724 }
725 }
726 BroadcasterManager::Clear ();
727
728 // Close the input file _before_ we close the input read communications class
729 // as it does NOT own the input file, our m_input_file does.
730 m_terminal_state.Clear();
731 if (m_input_file_sp)
732 m_input_file_sp->GetFile().Close ();
733
734 m_command_interpreter_ap->Clear();
735}
736
737bool
738Debugger::GetCloseInputOnEOF () const
739{
740// return m_input_comm.GetCloseOnEOF();
741 return false;
742}
743
744void
745Debugger::SetCloseInputOnEOF (bool b)
746{
747// m_input_comm.SetCloseOnEOF(b);
748}
749
750bool
751Debugger::GetAsyncExecution ()
752{
753 return !m_command_interpreter_ap->GetSynchronous();
754}
755
756void
757Debugger::SetAsyncExecution (bool async_execution)
758{
759 m_command_interpreter_ap->SetSynchronous (!async_execution);
760}
761
762
763void
764Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership)
765{
766 if (m_input_file_sp)
767 m_input_file_sp->GetFile().SetStream (fh, tranfer_ownership);
768 else
769 m_input_file_sp.reset (new StreamFile (fh, tranfer_ownership));
770
771 File &in_file = m_input_file_sp->GetFile();
772 if (in_file.IsValid() == false)
773 in_file.SetStream (stdinstdin, true);
774
775 // Save away the terminal state if that is relevant, so that we can restore it in RestoreInputState.
776 SaveInputTerminalState ();
777}
778
779void
780Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership)
781{
782 if (m_output_file_sp)
783 m_output_file_sp->GetFile().SetStream (fh, tranfer_ownership);
784 else
785 m_output_file_sp.reset (new StreamFile (fh, tranfer_ownership));
786
787 File &out_file = m_output_file_sp->GetFile();
788 if (out_file.IsValid() == false)
789 out_file.SetStream (stdoutstdout, false);
790
791 // do not create the ScriptInterpreter just for setting the output file handle
792 // as the constructor will know how to do the right thing on its own
793 const bool can_create = false;
794 ScriptInterpreter* script_interpreter = GetCommandInterpreter().GetScriptInterpreter(can_create);
795 if (script_interpreter)
796 script_interpreter->ResetOutputFileHandle (fh);
797}
798
799void
800Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership)
801{
802 if (m_error_file_sp)
803 m_error_file_sp->GetFile().SetStream (fh, tranfer_ownership);
804 else
805 m_error_file_sp.reset (new StreamFile (fh, tranfer_ownership));
806
807 File &err_file = m_error_file_sp->GetFile();
808 if (err_file.IsValid() == false)
809 err_file.SetStream (stderrstderr, false);
810}
811
812void
813Debugger::SaveInputTerminalState ()
814{
815 if (m_input_file_sp)
816 {
817 File &in_file = m_input_file_sp->GetFile();
818 if (in_file.GetDescriptor() != File::kInvalidDescriptor)
819 m_terminal_state.Save(in_file.GetDescriptor(), true);
820 }
821}
822
823void
824Debugger::RestoreInputTerminalState ()
825{
826 m_terminal_state.Restore();
827}
828
829ExecutionContext
830Debugger::GetSelectedExecutionContext ()
831{
832 ExecutionContext exe_ctx;
833 TargetSP target_sp(GetSelectedTarget());
834 exe_ctx.SetTargetSP (target_sp);
835
836 if (target_sp)
837 {
838 ProcessSP process_sp (target_sp->GetProcessSP());
839 exe_ctx.SetProcessSP (process_sp);
840 if (process_sp && process_sp->IsRunning() == false)
841 {
842 ThreadSP thread_sp (process_sp->GetThreadList().GetSelectedThread());
843 if (thread_sp)
844 {
845 exe_ctx.SetThreadSP (thread_sp);
846 exe_ctx.SetFrameSP (thread_sp->GetSelectedFrame());
847 if (exe_ctx.GetFramePtr() == NULL__null)
848 exe_ctx.SetFrameSP (thread_sp->GetStackFrameAtIndex (0));
849 }
850 }
851 }
852 return exe_ctx;
853}
854
855void
856Debugger::DispatchInputInterrupt ()
857{
858 Mutex::Locker locker (m_input_reader_stack.GetMutex());
859 IOHandlerSP reader_sp (m_input_reader_stack.Top());
860 if (reader_sp)
861 reader_sp->Interrupt();
862}
863
864void
865Debugger::DispatchInputEndOfFile ()
866{
867 Mutex::Locker locker (m_input_reader_stack.GetMutex());
868 IOHandlerSP reader_sp (m_input_reader_stack.Top());
869 if (reader_sp)
870 reader_sp->GotEOF();
871}
872
873void
874Debugger::ClearIOHandlers ()
875{
876 // The bottom input reader should be the main debugger input reader. We do not want to close that one here.
877 Mutex::Locker locker (m_input_reader_stack.GetMutex());
878 while (m_input_reader_stack.GetSize() > 1)
879 {
880 IOHandlerSP reader_sp (m_input_reader_stack.Top());
881 if (reader_sp)
882 {
883 m_input_reader_stack.Pop();
884 reader_sp->SetIsDone(true);
885 reader_sp->Cancel();
886 }
887 }
888}
889
890void
891Debugger::ExecuteIOHanders()
892{
893
894 while (1)
895 {
896 IOHandlerSP reader_sp(m_input_reader_stack.Top());
897 if (!reader_sp)
898 break;
899
900 reader_sp->Activate();
901 reader_sp->Run();
902 reader_sp->Deactivate();
903
904 // Remove all input readers that are done from the top of the stack
905 while (1)
906 {
907 IOHandlerSP top_reader_sp = m_input_reader_stack.Top();
908 if (top_reader_sp && top_reader_sp->GetIsDone())
909 m_input_reader_stack.Pop();
910 else
911 break;
912 }
913 }
914 ClearIOHandlers();
915}
916
917bool
918Debugger::IsTopIOHandler (const lldb::IOHandlerSP& reader_sp)
919{
920 return m_input_reader_stack.IsTop (reader_sp);
921}
922
923
924ConstString
925Debugger::GetTopIOHandlerControlSequence(char ch)
926{
927 return m_input_reader_stack.GetTopIOHandlerControlSequence (ch);
928}
929
930const char *
931Debugger::GetIOHandlerCommandPrefix()
932{
933 return m_input_reader_stack.GetTopIOHandlerCommandPrefix();
934}
935
936const char *
937Debugger::GetIOHandlerHelpPrologue()
938{
939 return m_input_reader_stack.GetTopIOHandlerHelpPrologue();
940}
941
942void
943Debugger::RunIOHandler (const IOHandlerSP& reader_sp)
944{
945 PushIOHandler (reader_sp);
946
947 IOHandlerSP top_reader_sp = reader_sp;
948 while (top_reader_sp)
949 {
950 top_reader_sp->Activate();
951 top_reader_sp->Run();
952 top_reader_sp->Deactivate();
953
954 if (top_reader_sp.get() == reader_sp.get())
955 {
956 if (PopIOHandler (reader_sp))
957 break;
958 }
959
960 while (1)
961 {
962 top_reader_sp = m_input_reader_stack.Top();
963 if (top_reader_sp && top_reader_sp->GetIsDone())
964 m_input_reader_stack.Pop();
965 else
966 break;
967 }
968 }
969}
970
971void
972Debugger::AdoptTopIOHandlerFilesIfInvalid (StreamFileSP &in, StreamFileSP &out, StreamFileSP &err)
973{
974 // Before an IOHandler runs, it must have in/out/err streams.
975 // This function is called when one ore more of the streams
976 // are NULL. We use the top input reader's in/out/err streams,
977 // or fall back to the debugger file handles, or we fall back
978 // onto stdin/stdout/stderr as a last resort.
979
980 Mutex::Locker locker (m_input_reader_stack.GetMutex());
981 IOHandlerSP top_reader_sp (m_input_reader_stack.Top());
982 // If no STDIN has been set, then set it appropriately
983 if (!in)
984 {
985 if (top_reader_sp)
986 in = top_reader_sp->GetInputStreamFile();
987 else
988 in = GetInputFile();
989
990 // If there is nothing, use stdin
991 if (!in)
992 in = StreamFileSP(new StreamFile(stdinstdin, false));
993 }
994 // If no STDOUT has been set, then set it appropriately
995 if (!out)
996 {
997 if (top_reader_sp)
998 out = top_reader_sp->GetOutputStreamFile();
999 else
1000 out = GetOutputFile();
1001
1002 // If there is nothing, use stdout
1003 if (!out)
1004 out = StreamFileSP(new StreamFile(stdoutstdout, false));
1005 }
1006 // If no STDERR has been set, then set it appropriately
1007 if (!err)
1008 {
1009 if (top_reader_sp)
1010 err = top_reader_sp->GetErrorStreamFile();
1011 else
1012 err = GetErrorFile();
1013
1014 // If there is nothing, use stderr
1015 if (!err)
1016 err = StreamFileSP(new StreamFile(stdoutstdout, false));
1017
1018 }
1019}
1020
1021void
1022Debugger::PushIOHandler (const IOHandlerSP& reader_sp)
1023{
1024 if (!reader_sp)
1025 return;
1026
1027 // Got the current top input reader...
1028 IOHandlerSP top_reader_sp (m_input_reader_stack.Top());
1029
1030 // Don't push the same IO handler twice...
1031 if (reader_sp.get() != top_reader_sp.get())
1032 {
1033 // Push our new input reader
1034 m_input_reader_stack.Push (reader_sp);
1035
1036 // Interrupt the top input reader to it will exit its Run() function
1037 // and let this new input reader take over
1038 if (top_reader_sp)
1039 top_reader_sp->Deactivate();
1040 }
1041}
1042
1043bool
1044Debugger::PopIOHandler (const IOHandlerSP& pop_reader_sp)
1045{
1046 bool result = false;
1047
1048 Mutex::Locker locker (m_input_reader_stack.GetMutex());
1049
1050 // The reader on the stop of the stack is done, so let the next
1051 // read on the stack refresh its prompt and if there is one...
1052 if (!m_input_reader_stack.IsEmpty())
1053 {
1054 IOHandlerSP reader_sp(m_input_reader_stack.Top());
1055
1056 if (!pop_reader_sp || pop_reader_sp.get() == reader_sp.get())
1057 {
1058 reader_sp->Deactivate();
1059 reader_sp->Cancel();
1060 m_input_reader_stack.Pop ();
1061
1062 reader_sp = m_input_reader_stack.Top();
1063 if (reader_sp)
1064 reader_sp->Activate();
1065
1066 result = true;
1067 }
1068 }
1069 return result;
1070}
1071
1072bool
1073Debugger::HideTopIOHandler()
1074{
1075 Mutex::Locker locker;
1076
1077 if (locker.TryLock(m_input_reader_stack.GetMutex()))
1078 {
1079 IOHandlerSP reader_sp(m_input_reader_stack.Top());
1080 if (reader_sp)
1081 reader_sp->Hide();
1082 return true;
1083 }
1084 return false;
1085}
1086
1087void
1088Debugger::RefreshTopIOHandler()
1089{
1090 IOHandlerSP reader_sp(m_input_reader_stack.Top());
1091 if (reader_sp)
1092 reader_sp->Refresh();
1093}
1094
1095
1096StreamSP
1097Debugger::GetAsyncOutputStream ()
1098{
1099 return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(),
1100 CommandInterpreter::eBroadcastBitAsynchronousOutputData));
1101}
1102
1103StreamSP
1104Debugger::GetAsyncErrorStream ()
1105{
1106 return StreamSP (new StreamAsynchronousIO (GetCommandInterpreter(),
1107 CommandInterpreter::eBroadcastBitAsynchronousErrorData));
1108}
1109
1110size_t
1111Debugger::GetNumDebuggers()
1112{
1113 if (g_shared_debugger_refcount > 0)
1114 {
1115 Mutex::Locker locker (GetDebuggerListMutex ());
1116 return GetDebuggerList().size();
1117 }
1118 return 0;
1119}
1120
1121lldb::DebuggerSP
1122Debugger::GetDebuggerAtIndex (size_t index)
1123{
1124 DebuggerSP debugger_sp;
1125
1126 if (g_shared_debugger_refcount > 0)
1127 {
1128 Mutex::Locker locker (GetDebuggerListMutex ());
1129 DebuggerList &debugger_list = GetDebuggerList();
1130
1131 if (index < debugger_list.size())
1132 debugger_sp = debugger_list[index];
1133 }
1134
1135 return debugger_sp;
1136}
1137
1138DebuggerSP
1139Debugger::FindDebuggerWithID (lldb::user_id_t id)
1140{
1141 DebuggerSP debugger_sp;
1142
1143 if (g_shared_debugger_refcount > 0)
1144 {
1145 Mutex::Locker locker (GetDebuggerListMutex ());
1146 DebuggerList &debugger_list = GetDebuggerList();
1147 DebuggerList::iterator pos, end = debugger_list.end();
1148 for (pos = debugger_list.begin(); pos != end; ++pos)
1149 {
1150 if ((*pos).get()->GetID() == id)
1151 {
1152 debugger_sp = *pos;
1153 break;
1154 }
1155 }
1156 }
1157 return debugger_sp;
1158}
1159
1160#if 0
1161static void
1162TestPromptFormats (StackFrame *frame)
1163{
1164 if (frame == NULL__null)
1165 return;
1166
1167 StreamString s;
1168 const char *prompt_format =
1169 "{addr = '${addr}'\n}"
1170 "{addr-file-or-load = '${addr-file-or-load}'\n}"
1171 "{current-pc-arrow = '${current-pc-arrow}'\n}"
1172 "{process.id = '${process.id}'\n}"
1173 "{process.name = '${process.name}'\n}"
1174 "{process.file.basename = '${process.file.basename}'\n}"
1175 "{process.file.fullpath = '${process.file.fullpath}'\n}"
1176 "{thread.id = '${thread.id}'\n}"
1177 "{thread.index = '${thread.index}'\n}"
1178 "{thread.name = '${thread.name}'\n}"
1179 "{thread.queue = '${thread.queue}'\n}"
1180 "{thread.stop-reason = '${thread.stop-reason}'\n}"
1181 "{target.arch = '${target.arch}'\n}"
1182 "{module.file.basename = '${module.file.basename}'\n}"
1183 "{module.file.fullpath = '${module.file.fullpath}'\n}"
1184 "{file.basename = '${file.basename}'\n}"
1185 "{file.fullpath = '${file.fullpath}'\n}"
1186 "{frame.index = '${frame.index}'\n}"
1187 "{frame.pc = '${frame.pc}'\n}"
1188 "{frame.sp = '${frame.sp}'\n}"
1189 "{frame.fp = '${frame.fp}'\n}"
1190 "{frame.flags = '${frame.flags}'\n}"
1191 "{frame.reg.rdi = '${frame.reg.rdi}'\n}"
1192 "{frame.reg.rip = '${frame.reg.rip}'\n}"
1193 "{frame.reg.rsp = '${frame.reg.rsp}'\n}"
1194 "{frame.reg.rbp = '${frame.reg.rbp}'\n}"
1195 "{frame.reg.rflags = '${frame.reg.rflags}'\n}"
1196 "{frame.reg.xmm0 = '${frame.reg.xmm0}'\n}"
1197 "{frame.reg.carp = '${frame.reg.carp}'\n}"
1198 "{function.id = '${function.id}'\n}"
1199 "{function.changed = '${function.changed}'\n}"
1200 "{function.initial-function = '${function.initial-function}'\n}"
1201 "{function.name = '${function.name}'\n}"
1202 "{function.name-without-args = '${function.name-without-args}'\n}"
1203 "{function.name-with-args = '${function.name-with-args}'\n}"
1204 "{function.addr-offset = '${function.addr-offset}'\n}"
1205 "{function.concrete-only-addr-offset-no-padding = '${function.concrete-only-addr-offset-no-padding}'\n}"
1206 "{function.line-offset = '${function.line-offset}'\n}"
1207 "{function.pc-offset = '${function.pc-offset}'\n}"
1208 "{line.file.basename = '${line.file.basename}'\n}"
1209 "{line.file.fullpath = '${line.file.fullpath}'\n}"
1210 "{line.number = '${line.number}'\n}"
1211 "{line.start-addr = '${line.start-addr}'\n}"
1212 "{line.end-addr = '${line.end-addr}'\n}"
1213;
1214
1215 SymbolContext sc (frame->GetSymbolContext(eSymbolContextEverything));
1216 ExecutionContext exe_ctx;
1217 frame->CalculateExecutionContext(exe_ctx);
1218 if (Debugger::FormatPrompt (prompt_format, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s))
1219 {
1220 printf("%s\n", s.GetData());
1221 }
1222 else
1223 {
1224 printf ("what we got: %s\n", s.GetData());
1225 }
1226}
1227#endif
1228
1229static bool
1230ScanFormatDescriptor (const char* var_name_begin,
1231 const char* var_name_end,
1232 const char** var_name_final,
1233 const char** percent_position,
1234 Format* custom_format,
1235 ValueObject::ValueObjectRepresentationStyle* val_obj_display)
1236{
1237 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES(1u << 19)));
1238 *percent_position = ::strchr(var_name_begin,'%');
1239 if (!*percent_position || *percent_position > var_name_end)
1240 {
1241 if (log)
1242 log->Printf("[ScanFormatDescriptor] no format descriptor in string, skipping");
1243 *var_name_final = var_name_end;
1244 }
1245 else
1246 {
1247 *var_name_final = *percent_position;
1248 std::string format_name(*var_name_final+1, var_name_end-*var_name_final-1);
1249 if (log)
1250 log->Printf("[ScanFormatDescriptor] parsing %s as a format descriptor", format_name.c_str());
1251 if ( !FormatManager::GetFormatFromCString(format_name.c_str(),
1252 true,
1253 *custom_format) )
1254 {
1255 if (log)
1256 log->Printf("[ScanFormatDescriptor] %s is an unknown format", format_name.c_str());
1257
1258 switch (format_name.front())
1259 {
1260 case '@': // if this is an @ sign, print ObjC description
1261 *val_obj_display = ValueObject::eValueObjectRepresentationStyleLanguageSpecific;
1262 break;
1263 case 'V': // if this is a V, print the value using the default format
1264 *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
1265 break;
1266 case 'L': // if this is an L, print the location of the value
1267 *val_obj_display = ValueObject::eValueObjectRepresentationStyleLocation;
1268 break;
1269 case 'S': // if this is an S, print the summary after all
1270 *val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary;
1271 break;
1272 case '#': // if this is a '#', print the number of children
1273 *val_obj_display = ValueObject::eValueObjectRepresentationStyleChildrenCount;
1274 break;
1275 case 'T': // if this is a 'T', print the type
1276 *val_obj_display = ValueObject::eValueObjectRepresentationStyleType;
1277 break;
1278 case 'N': // if this is a 'N', print the name
1279 *val_obj_display = ValueObject::eValueObjectRepresentationStyleName;
1280 break;
1281 case '>': // if this is a '>', print the name
1282 *val_obj_display = ValueObject::eValueObjectRepresentationStyleExpressionPath;
1283 break;
1284 default:
1285 if (log)
1286 log->Printf("ScanFormatDescriptor] %s is an error, leaving the previous value alone", format_name.c_str());
1287 break;
1288 }
1289 }
1290 // a good custom format tells us to print the value using it
1291 else
1292 {
1293 if (log)
1294 log->Printf("[ScanFormatDescriptor] will display value for this VO");
1295 *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
1296 }
1297 }
1298 if (log)
1299 log->Printf("[ScanFormatDescriptor] final format description outcome: custom_format = %d, val_obj_display = %d",
1300 *custom_format,
1301 *val_obj_display);
1302 return true;
1303}
1304
1305static bool
1306ScanBracketedRange (const char* var_name_begin,
1307 const char* var_name_end,
1308 const char* var_name_final,
1309 const char** open_bracket_position,
1310 const char** separator_position,
1311 const char** close_bracket_position,
1312 const char** var_name_final_if_array_range,
1313 int64_t* index_lower,
1314 int64_t* index_higher)
1315{
1316 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES(1u << 19)));
1317 *open_bracket_position = ::strchr(var_name_begin,'[');
1318 if (*open_bracket_position && *open_bracket_position < var_name_final)
1319 {
1320 *separator_position = ::strchr(*open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield
1321 *close_bracket_position = ::strchr(*open_bracket_position,']');
1322 // as usual, we assume that [] will come before %
1323 //printf("trying to expand a []\n");
1324 *var_name_final_if_array_range = *open_bracket_position;
1325 if (*close_bracket_position - *open_bracket_position == 1)
1326 {
1327 if (log)
1328 log->Printf("[ScanBracketedRange] '[]' detected.. going from 0 to end of data");
1329 *index_lower = 0;
1330 }
1331 else if (*separator_position == NULL__null || *separator_position > var_name_end)
1332 {
1333 char *end = NULL__null;
1334 *index_lower = ::strtoul (*open_bracket_position+1, &end, 0);
1335 *index_higher = *index_lower;
1336 if (log)
1337 log->Printf("[ScanBracketedRange] [%" PRId64"l" "d" "] detected, high index is same", *index_lower);
1338 }
1339 else if (*close_bracket_position && *close_bracket_position < var_name_end)
1340 {
1341 char *end = NULL__null;
1342 *index_lower = ::strtoul (*open_bracket_position+1, &end, 0);
1343 *index_higher = ::strtoul (*separator_position+1, &end, 0);
1344 if (log)
1345 log->Printf("[ScanBracketedRange] [%" PRId64"l" "d" "-%" PRId64"l" "d" "] detected", *index_lower, *index_higher);
1346 }
1347 else
1348 {
1349 if (log)
1350 log->Printf("[ScanBracketedRange] expression is erroneous, cannot extract indices out of it");
1351 return false;
1352 }
1353 if (*index_lower > *index_higher && *index_higher > 0)
1354 {
1355 if (log)
1356 log->Printf("[ScanBracketedRange] swapping indices");
1357 int64_t temp = *index_lower;
1358 *index_lower = *index_higher;
1359 *index_higher = temp;
1360 }
1361 }
1362 else if (log)
1363 log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
1364 return true;
1365}
1366
1367template <typename T>
1368static bool RunScriptFormatKeyword(Stream &s, ScriptInterpreter *script_interpreter, T t, const std::string& script_name)
1369{
1370 if (script_interpreter)
1371 {
1372 Error script_error;
1373 std::string script_output;
1374
1375 if (script_interpreter->RunScriptFormatKeyword(script_name.c_str(), t, script_output, script_error) && script_error.Success())
1376 {
1377 s.Printf("%s", script_output.c_str());
1378 return true;
1379 }
1380 else
1381 {
1382 s.Printf("<error: %s>",script_error.AsCString());
1383 }
1384 }
1385 return false;
1386}
1387
1388static ValueObjectSP
1389ExpandIndexedExpression (ValueObject* valobj,
1390 size_t index,
1391 StackFrame* frame,
1392 bool deref_pointer)
1393{
1394 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES(1u << 19)));
1395 const char* ptr_deref_format = "[%d]";
1396 std::string ptr_deref_buffer(10,0);
1397 ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index);
1398 if (log)
1399 log->Printf("[ExpandIndexedExpression] name to deref: %s",ptr_deref_buffer.c_str());
1400 const char* first_unparsed;
1401 ValueObject::GetValueForExpressionPathOptions options;
1402 ValueObject::ExpressionPathEndResultType final_value_type;
1403 ValueObject::ExpressionPathScanEndReason reason_to_stop;
1404 ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing);
1405 ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.c_str(),
1406 &first_unparsed,
1407 &reason_to_stop,
1408 &final_value_type,
1409 options,
1410 &what_next);
1411 if (!item)
1412 {
1413 if (log)
1414 log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d,"
1415 " final_value_type %d",
1416 first_unparsed, reason_to_stop, final_value_type);
1417 }
1418 else
1419 {
1420 if (log)
1421 log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d,"
1422 " final_value_type %d",
1423 first_unparsed, reason_to_stop, final_value_type);
1424 }
1425 return item;
1426}
1427
1428static inline bool
1429IsToken(const char *var_name_begin, const char *var)
1430{
1431 return (::strncmp (var_name_begin, var, strlen(var)) == 0);
1432}
1433
1434static bool
1435IsTokenWithFormat(const char *var_name_begin, const char *var, std::string &format, const char *default_format,
1436 const ExecutionContext *exe_ctx_ptr, const SymbolContext *sc_ptr)
1437{
1438 int var_len = strlen(var);
1439 if (::strncmp (var_name_begin, var, var_len) == 0)
1440 {
1441 var_name_begin += var_len;
1442 if (*var_name_begin == '}')
1443 {
1444 format = default_format;
1445 return true;
1446 }
1447 else if (*var_name_begin == '%')
1448 {
1449 // Allow format specifiers: x|X|u with optional width specifiers.
1450 // ${thread.id%x} ; hex
1451 // ${thread.id%X} ; uppercase hex
1452 // ${thread.id%u} ; unsigned decimal
1453 // ${thread.id%8.8X} ; width.precision + specifier
1454 // ${thread.id%tid} ; unsigned on FreeBSD/Linux, otherwise default_format (0x%4.4x for thread.id)
1455 int dot_count = 0;
1456 const char *specifier = NULL__null;
1457 int width_precision_length = 0;
1458 const char *width_precision = ++var_name_begin;
1459 while (isdigit(*var_name_begin) || *var_name_begin == '.')
1460 {
1461 dot_count += (*var_name_begin == '.');
1462 if (dot_count > 1)
1463 break;
1464 var_name_begin++;
1465 width_precision_length++;
1466 }
1467
1468 if (IsToken (var_name_begin, "tid}"))
1469 {
1470 Target *target = Target::GetTargetFromContexts (exe_ctx_ptr, sc_ptr);
1471 if (target)
1472 {
1473 ArchSpec arch (target->GetArchitecture ());
1474 llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS;
1475 if ((ostype == llvm::Triple::FreeBSD) || (ostype == llvm::Triple::Linux))
1476 specifier = PRIu64"l" "u";
1477 }
1478 if (!specifier)
1479 {
1480 format = default_format;
1481 return true;
1482 }
1483 }
1484 else if (IsToken (var_name_begin, "x}"))
1485 specifier = PRIx64"l" "x";
1486 else if (IsToken (var_name_begin, "X}"))
1487 specifier = PRIX64"l" "X";
1488 else if (IsToken (var_name_begin, "u}"))
1489 specifier = PRIu64"l" "u";
1490
1491 if (specifier)
1492 {
1493 format = "%";
1494 if (width_precision_length)
1495 format += std::string(width_precision, width_precision_length);
1496 format += specifier;
1497 return true;
1498 }
1499 }
1500 }
1501 return false;
1502}
1503
1504// Find information for the "thread.info.*" specifiers in a format string
1505static bool
1506FormatThreadExtendedInfoRecurse
1507(
1508 const char *var_name_begin,
1509 StructuredData::ObjectSP thread_info_dictionary,
1510 const SymbolContext *sc,
1511 const ExecutionContext *exe_ctx,
1512 Stream &s
1513)
1514{
1515 bool var_success = false;
1516 std::string token_format;
1517
1518 llvm::StringRef var_name(var_name_begin);
1519 size_t percent_idx = var_name.find('%');
1520 size_t close_curly_idx = var_name.find('}');
1521 llvm::StringRef path = var_name;
1522 llvm::StringRef formatter = var_name;
1523
1524 // 'path' will be the dot separated list of objects to transverse up until we hit
1525 // a close curly brace, a percent sign, or an end of string.
1526 if (percent_idx != llvm::StringRef::npos || close_curly_idx != llvm::StringRef::npos)
1527 {
1528 if (percent_idx != llvm::StringRef::npos && close_curly_idx != llvm::StringRef::npos)
1529 {
1530 if (percent_idx < close_curly_idx)
1531 {
1532 path = var_name.slice(0, percent_idx);
1533 formatter = var_name.substr (percent_idx);
1534 }
1535 else
1536 {
1537 path = var_name.slice(0, close_curly_idx);
1538 formatter = var_name.substr (close_curly_idx);
1539 }
1540 }
1541 else if (percent_idx != llvm::StringRef::npos)
1542 {
1543 path = var_name.slice(0, percent_idx);
1544 formatter = var_name.substr (percent_idx);
1545 }
1546 else if (close_curly_idx != llvm::StringRef::npos)
1547 {
1548 path = var_name.slice(0, close_curly_idx);
1549 formatter = var_name.substr (close_curly_idx);
1550 }
1551 }
1552
1553 StructuredData::ObjectSP value = thread_info_dictionary->GetObjectForDotSeparatedPath (path);
1554
1555 if (value.get())
1556 {
1557 if (value->GetType() == StructuredData::Type::eTypeInteger)
1558 {
1559 if (IsTokenWithFormat (formatter.str().c_str(), "", token_format, "0x%4.4" PRIx64"l" "x", exe_ctx, sc))
1560 {
1561 s.Printf(token_format.c_str(), value->GetAsInteger()->GetValue());
1562 var_success = true;
1563 }
1564 }
1565 else if (value->GetType() == StructuredData::Type::eTypeFloat)
1566 {
1567 s.Printf ("%f", value->GetAsFloat()->GetValue());
1568 var_success = true;
1569 }
1570 else if (value->GetType() == StructuredData::Type::eTypeString)
1571 {
1572 s.Printf("%s", value->GetAsString()->GetValue().c_str());
1573 var_success = true;
1574 }
1575 else if (value->GetType() == StructuredData::Type::eTypeArray)
1576 {
1577 if (value->GetAsArray()->GetSize() > 0)
1578 {
1579 s.Printf ("%zu", value->GetAsArray()->GetSize());
1580 var_success = true;
1581 }
1582 }
1583 else if (value->GetType() == StructuredData::Type::eTypeDictionary)
1584 {
1585 s.Printf ("%zu", value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
1586 var_success = true;
1587 }
1588 }
1589
1590 return var_success;
1591}
1592
1593
1594static bool
1595FormatPromptRecurse
1596(
1597 const char *format,
1598 const SymbolContext *sc,
1599 const ExecutionContext *exe_ctx,
1600 const Address *addr,
1601 Stream &s,
1602 const char **end,
1603 ValueObject* valobj,
1604 bool function_changed,
1605 bool initial_function
1606)
1607{
1608 ValueObject* realvalobj = NULL__null; // makes it super-easy to parse pointers
1609 bool success = true;
1610 const char *p;
1611 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES(1u << 19)));
1612
1613 for (p = format; *p != '\0'; ++p)
1614 {
1615 if (realvalobj)
1616 {
1617 valobj = realvalobj;
1618 realvalobj = NULL__null;
1619 }
1620 size_t non_special_chars = ::strcspn (p, "${}\\");
1621 if (non_special_chars > 0)
1622 {
1623 if (success)
1624 s.Write (p, non_special_chars);
1625 p += non_special_chars;
1626 }
1627
1628 if (*p == '\0')
1629 {
1630 break;
1631 }
1632 else if (*p == '{')
1633 {
1634 // Start a new scope that must have everything it needs if it is to
1635 // to make it into the final output stream "s". If you want to make
1636 // a format that only prints out the function or symbol name if there
1637 // is one in the symbol context you can use:
1638 // "{function =${function.name}}"
1639 // The first '{' starts a new scope that end with the matching '}' at
1640 // the end of the string. The contents "function =${function.name}"
1641 // will then be evaluated and only be output if there is a function
1642 // or symbol with a valid name.
1643 StreamString sub_strm;
1644
1645 ++p; // Skip the '{'
1646
1647 if (FormatPromptRecurse (p, sc, exe_ctx, addr, sub_strm, &p, valobj, function_changed, initial_function))
1648 {
1649 // The stream had all it needed
1650 s.Write(sub_strm.GetData(), sub_strm.GetSize());
1651 }
1652 if (*p != '}')
1653 {
1654 success = false;
1655 break;
1656 }
1657 }
1658 else if (*p == '}')
1659 {
1660 // End of a enclosing scope
1661 break;
1662 }
1663 else if (*p == '$')
1664 {
1665 // We have a prompt variable to print
1666 ++p;
1667 if (*p == '{')
1668 {
1669 ++p;
1670 const char *var_name_begin = p;
1671 const char *var_name_end = ::strchr (p, '}');
1672
1673 if (var_name_end && var_name_begin < var_name_end)
1674 {
1675 // if we have already failed to parse, skip this variable
1676 if (success)
1677 {
1678 const char *cstr = NULL__null;
1679 std::string token_format;
1680 Address format_addr;
1681
1682 // normally "addr" means print a raw address but
1683 // "file-addr-or-load-addr" means print a module + file addr if there's no load addr
1684 bool print_file_addr_or_load_addr = false;
1685 bool addr_offset_concrete_func_only = false;
1686 bool addr_offset_print_with_no_padding = false;
1687 bool calculate_format_addr_function_offset = false;
1688 // Set reg_kind and reg_num to invalid values
1689 RegisterKind reg_kind = kNumRegisterKinds;
1690 uint32_t reg_num = LLDB_INVALID_REGNUM(4294967295U);
1691 FileSpec format_file_spec;
1692 const RegisterInfo *reg_info = NULL__null;
1693 RegisterContext *reg_ctx = NULL__null;
1694 bool do_deref_pointer = false;
1695 ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;
1696 ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain;
1697
1698 // Each variable must set success to true below...
1699 bool var_success = false;
1700 switch (var_name_begin[0])
1701 {
1702 case '*':
1703 case 'v':
1704 case 's':
1705 {
1706 if (!valobj)
1707 break;
1708
1709 if (log)
1710 log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin);
1711
1712 // check for *var and *svar
1713 if (*var_name_begin == '*')
1714 {
1715 do_deref_pointer = true;
1716 var_name_begin++;
1717 if (log)
1718 log->Printf("[Debugger::FormatPrompt] found a deref, new string is: %s",var_name_begin);
1719 }
1720
1721 if (*var_name_begin == 's')
1722 {
1723 if (!valobj->IsSynthetic())
1724 valobj = valobj->GetSyntheticValue().get();
1725 if (!valobj)
1726 break;
1727 var_name_begin++;
1728 if (log)
1729 log->Printf("[Debugger::FormatPrompt] found a synthetic, new string is: %s",var_name_begin);
1730 }
1731
1732 // should be a 'v' by now
1733 if (*var_name_begin != 'v')
1734 break;
1735
1736 if (log)
1737 log->Printf("[Debugger::FormatPrompt] string I am working with: %s",var_name_begin);
1738
1739 ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ?
1740 ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing);
1741 ValueObject::GetValueForExpressionPathOptions options;
1742 options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren();
1743 ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary;
1744 ValueObject* target = NULL__null;
1745 Format custom_format = eFormatInvalid;
1746 const char* var_name_final = NULL__null;
1747 const char* var_name_final_if_array_range = NULL__null;
1748 const char* close_bracket_position = NULL__null;
1749 int64_t index_lower = -1;
1750 int64_t index_higher = -1;
1751 bool is_array_range = false;
1752 const char* first_unparsed;
1753 bool was_plain_var = false;
1754 bool was_var_format = false;
1755 bool was_var_indexed = false;
1756
1757 if (!valobj) break;
1758 // simplest case ${var}, just print valobj's value
1759 if (IsToken (var_name_begin, "var}"))
1760 {
1761 was_plain_var = true;
1762 target = valobj;
1763 val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
1764 }
1765 else if (IsToken (var_name_begin, "var.script:"))
1766 {
1767 var_name_begin += ::strlen("var.script:");
1768 std::string script_name(var_name_begin,var_name_end);
1769 ScriptInterpreter* script_interpreter = valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
1770 if (RunScriptFormatKeyword (s, script_interpreter, valobj, script_name))
1771 var_success = true;
1772 break;
1773 }
1774 else if (IsToken (var_name_begin,"var%"))
1775 {
1776 was_var_format = true;
1777 // this is a variable with some custom format applied to it
1778 const char* percent_position;
1779 target = valobj;
1780 val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
1781 ScanFormatDescriptor (var_name_begin,
1782 var_name_end,
1783 &var_name_final,
1784 &percent_position,
1785 &custom_format,
1786 &val_obj_display);
1787 }
1788 // this is ${var.something} or multiple .something nested
1789 else if (IsToken (var_name_begin, "var"))
1790 {
1791 if (IsToken (var_name_begin, "var["))
1792 was_var_indexed = true;
1793 const char* percent_position;
1794 ScanFormatDescriptor (var_name_begin,
1795 var_name_end,
1796 &var_name_final,
1797 &percent_position,
1798 &custom_format,
1799 &val_obj_display);
1800
1801 const char* open_bracket_position;
1802 const char* separator_position;
1803 ScanBracketedRange (var_name_begin,
1804 var_name_end,
1805 var_name_final,
1806 &open_bracket_position,
1807 &separator_position,
1808 &close_bracket_position,
1809 &var_name_final_if_array_range,
1810 &index_lower,
1811 &index_higher);
1812
1813 Error error;
1814
1815 std::string expr_path(var_name_final-var_name_begin-1,0);
1816 memcpy(&expr_path[0], var_name_begin+3,var_name_final-var_name_begin-3);
1817
1818 if (log)
1819 log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",expr_path.c_str());
1820
1821 target = valobj->GetValueForExpressionPath(expr_path.c_str(),
1822 &first_unparsed,
1823 &reason_to_stop,
1824 &final_value_type,
1825 options,
1826 &what_next).get();
1827
1828 if (!target)
1829 {
1830 if (log)
1831 log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d,"
1832 " final_value_type %d",
1833 first_unparsed, reason_to_stop, final_value_type);
1834 break;
1835 }
1836 else
1837 {
1838 if (log)
1839 log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d,"
1840 " final_value_type %d",
1841 first_unparsed, reason_to_stop, final_value_type);
1842 target = target->GetQualifiedRepresentationIfAvailable(target->GetDynamicValueType(), true).get();
1843 }
1844 }
1845 else
1846 break;
1847
1848 is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange ||
1849 final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange);
1850
1851 do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference);
1852
1853 if (do_deref_pointer && !is_array_range)
1854 {
1855 // I have not deref-ed yet, let's do it
1856 // this happens when we are not going through GetValueForVariableExpressionPath
1857 // to get to the target ValueObject
1858 Error error;
1859 target = target->Dereference(error).get();
1860 if (error.Fail())
1861 {
1862 if (log)
1863 log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", error.AsCString("unknown")); \
1864 break;
1865 }
1866 do_deref_pointer = false;
1867 }
1868
1869 if (!target)
1870 {
1871 if (log)
1872 log->Printf("[Debugger::FormatPrompt] could not calculate target for prompt expression");
1873 break;
1874 }
1875
1876 // we do not want to use the summary for a bitfield of type T:n
1877 // if we were originally dealing with just a T - that would get
1878 // us into an endless recursion
1879 if (target->IsBitfield() && was_var_indexed)
1880 {
1881 // TODO: check for a (T:n)-specific summary - we should still obey that
1882 StreamString bitfield_name;
1883 bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize());
1884 lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false));
1885 if (!DataVisualization::GetSummaryForType(type_sp))
1886 val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
1887 }
1888
1889 // TODO use flags for these
1890 const uint32_t type_info_flags = target->GetClangType().GetTypeInfo(NULL__null);
1891 bool is_array = (type_info_flags & eTypeIsArray) != 0;
1892 bool is_pointer = (type_info_flags & eTypeIsPointer) != 0;
1893 bool is_aggregate = target->GetClangType().IsAggregateType();
1894
1895 if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions
1896 {
1897 StreamString str_temp;
1898 if (log)
1899 log->Printf("[Debugger::FormatPrompt] I am into array || pointer && !range");
1900
1901 if (target->HasSpecialPrintableRepresentation(val_obj_display, custom_format))
1902 {
1903 // try to use the special cases
1904 var_success = target->DumpPrintableRepresentation(str_temp,
1905 val_obj_display,
1906 custom_format);
1907 if (log)
1908 log->Printf("[Debugger::FormatPrompt] special cases did%s match", var_success ? "" : "n't");
1909
1910 // should not happen
1911 if (var_success)
1912 s << str_temp.GetData();
1913 var_success = true;
1914 break;
1915 }
1916 else
1917 {
1918 if (was_plain_var) // if ${var}
1919 {
1920 s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
1921 }
1922 else if (is_pointer) // if pointer, value is the address stored
1923 {
1924 target->DumpPrintableRepresentation (s,
1925 val_obj_display,
1926 custom_format,
1927 ValueObject::ePrintableRepresentationSpecialCasesDisable);
1928 }
1929 var_success = true;
1930 break;
1931 }
1932 }
1933
1934 // if directly trying to print ${var}, and this is an aggregate, display a nice
1935 // type @ location message
1936 if (is_aggregate && was_plain_var)
1937 {
1938 s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
1939 var_success = true;
1940 break;
1941 }
1942
1943 // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it
1944 if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue)))
1945 {
1946 s << "<invalid use of aggregate type>";
1947 var_success = true;
1948 break;
1949 }
1950
1951 if (!is_array_range)
1952 {
1953 if (log)
1954 log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output");
1955 var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format);
1956 }
1957 else
1958 {
1959 if (log)
1960 log->Printf("[Debugger::FormatPrompt] checking if I can handle as array");
1961 if (!is_array && !is_pointer)
1962 break;
1963 if (log)
1964 log->Printf("[Debugger::FormatPrompt] handle as array");
1965 const char* special_directions = NULL__null;
1966 StreamString special_directions_writer;
1967 if (close_bracket_position && (var_name_end-close_bracket_position > 1))
1968 {
1969 ConstString additional_data;
1970 additional_data.SetCStringWithLength(close_bracket_position+1, var_name_end-close_bracket_position-1);
1971 special_directions_writer.Printf("${%svar%s}",
1972 do_deref_pointer ? "*" : "",
1973 additional_data.GetCString());
1974 special_directions = special_directions_writer.GetData();
1975 }
1976
1977 // let us display items index_lower thru index_higher of this array
1978 s.PutChar('[');
1979 var_success = true;
1980
1981 if (index_higher < 0)
1982 index_higher = valobj->GetNumChildren() - 1;
1983
1984 uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
1985
1986 for (;index_lower<=index_higher;index_lower++)
1987 {
1988 ValueObject* item = ExpandIndexedExpression (target,
1989 index_lower,
1990 exe_ctx->GetFramePtr(),
1991 false).get();
1992
1993 if (!item)
1994 {
1995 if (log)
1996 log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at index %" PRId64"l" "d", index_lower);
1997 }
1998 else
1999 {
2000 if (log)
2001 log->Printf("[Debugger::FormatPrompt] special_directions for child item: %s",special_directions);
2002 }
2003
2004 if (!special_directions)
2005 var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format);
2006 else
2007 var_success &= FormatPromptRecurse(special_directions, sc, exe_ctx, addr, s, NULL__null, item, function_changed, initial_function);
2008
2009 if (--max_num_children == 0)
2010 {
2011 s.PutCString(", ...");
2012 break;
2013 }
2014
2015 if (index_lower < index_higher)
2016 s.PutChar(',');
2017 }
2018 s.PutChar(']');
2019 }
2020 }
2021 break;
2022 case 'a':
2023 if (IsToken (var_name_begin, "addr-file-or-load}"))
2024 {
2025 print_file_addr_or_load_addr = true;
2026 }
2027 if (IsToken (var_name_begin, "addr}")
2028 || IsToken (var_name_begin, "addr-file-or-load}"))
2029 {
2030 if (addr && addr->IsValid())
2031 {
2032 var_success = true;
2033 format_addr = *addr;
2034 }
2035 }
2036 break;
2037
2038 case 'p':
2039 if (IsToken (var_name_begin, "process."))
2040 {
2041 if (exe_ctx)
2042 {
2043 Process *process = exe_ctx->GetProcessPtr();
2044 if (process)
2045 {
2046 var_name_begin += ::strlen ("process.");
2047 if (IsTokenWithFormat (var_name_begin, "id", token_format, "%" PRIu64"l" "u", exe_ctx, sc))
2048 {
2049 s.Printf(token_format.c_str(), process->GetID());
2050 var_success = true;
2051 }
2052 else if ((IsToken (var_name_begin, "name}")) ||
2053 (IsToken (var_name_begin, "file.basename}")) ||
2054 (IsToken (var_name_begin, "file.fullpath}")))
2055 {
2056 Module *exe_module = process->GetTarget().GetExecutableModulePointer();
2057 if (exe_module)
2058 {
2059 if (var_name_begin[0] == 'n' || var_name_begin[5] == 'f')
2060 {
2061 format_file_spec.GetFilename() = exe_module->GetFileSpec().GetFilename();
2062 var_success = (bool)format_file_spec;
2063 }
2064 else
2065 {
2066 format_file_spec = exe_module->GetFileSpec();
2067 var_success = (bool)format_file_spec;
2068 }
2069 }
2070 }
2071 else if (IsToken (var_name_begin, "script:"))
2072 {
2073 var_name_begin += ::strlen("script:");
2074 std::string script_name(var_name_begin,var_name_end);
2075 ScriptInterpreter* script_interpreter = process->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
2076 if (RunScriptFormatKeyword (s, script_interpreter, process, script_name))
2077 var_success = true;
2078 }
2079 }
2080 }
2081 }
2082 break;
2083
2084 case 't':
2085 if (IsToken (var_name_begin, "thread."))
2086 {
2087 if (exe_ctx)
2088 {
2089 Thread *thread = exe_ctx->GetThreadPtr();
2090 if (thread)
2091 {
2092 var_name_begin += ::strlen ("thread.");
2093 if (IsTokenWithFormat (var_name_begin, "id", token_format, "0x%4.4" PRIx64"l" "x", exe_ctx, sc))
2094 {
2095 s.Printf(token_format.c_str(), thread->GetID());
2096 var_success = true;
2097 }
2098 else if (IsTokenWithFormat (var_name_begin, "protocol_id", token_format, "0x%4.4" PRIx64"l" "x", exe_ctx, sc))
2099 {
2100 s.Printf(token_format.c_str(), thread->GetProtocolID());
2101 var_success = true;
2102 }
2103 else if (IsTokenWithFormat (var_name_begin, "index", token_format, "%" PRIu64"l" "u", exe_ctx, sc))
2104 {
2105 s.Printf(token_format.c_str(), (uint64_t)thread->GetIndexID());
2106 var_success = true;
2107 }
2108 else if (IsToken (var_name_begin, "name}"))
2109 {
2110 cstr = thread->GetName();
2111 var_success = cstr && cstr[0];
2112 if (var_success)
2113 s.PutCString(cstr);
2114 }
2115 else if (IsToken (var_name_begin, "queue}"))
2116 {
2117 cstr = thread->GetQueueName();
2118 var_success = cstr && cstr[0];
2119 if (var_success)
2120 s.PutCString(cstr);
2121 }
2122 else if (IsToken (var_name_begin, "stop-reason}"))
2123 {
2124 StopInfoSP stop_info_sp = thread->GetStopInfo ();
2125 if (stop_info_sp && stop_info_sp->IsValid())
2126 {
2127 cstr = stop_info_sp->GetDescription();
2128 if (cstr && cstr[0])
2129 {
2130 s.PutCString(cstr);
2131 var_success = true;
2132 }
2133 }
2134 }
2135 else if (IsToken (var_name_begin, "return-value}"))
2136 {
2137 StopInfoSP stop_info_sp = thread->GetStopInfo ();
2138 if (stop_info_sp && stop_info_sp->IsValid())
2139 {
2140 ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp);
2141 if (return_valobj_sp)
2142 {
2143 return_valobj_sp->Dump(s);
2144 var_success = true;
2145 }
2146 }
2147 }
2148 else if (IsToken (var_name_begin, "completed-expression}"))
2149 {
2150 StopInfoSP stop_info_sp = thread->GetStopInfo ();
2151 if (stop_info_sp && stop_info_sp->IsValid())
2152 {
2153 ClangExpressionVariableSP expression_var_sp = StopInfo::GetExpressionVariable (stop_info_sp);
2154 if (expression_var_sp && expression_var_sp->GetValueObject())
2155 {
2156 expression_var_sp->GetValueObject()->Dump(s);
2157 var_success = true;
2158 }
2159 }
2160 }
2161 else if (IsToken (var_name_begin, "script:"))
2162 {
2163 var_name_begin += ::strlen("script:");
2164 std::string script_name(var_name_begin,var_name_end);
2165 ScriptInterpreter* script_interpreter = thread->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
2166 if (RunScriptFormatKeyword (s, script_interpreter, thread, script_name))
2167 var_success = true;
2168 }
2169 else if (IsToken (var_name_begin, "info."))
2170 {
2171 var_name_begin += ::strlen("info.");
2172 StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
2173 if (object_sp && object_sp->GetType() == StructuredData::Type::eTypeDictionary)
2174 {
2175 var_success = FormatThreadExtendedInfoRecurse (var_name_begin, object_sp, sc, exe_ctx, s);
2176 }
2177 }
2178 }
2179 }
2180 }
2181 else if (IsToken (var_name_begin, "target."))
2182 {
2183 // TODO: hookup properties
2184// if (!target_properties_sp)
2185// {
2186// Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
2187// if (target)
2188// target_properties_sp = target->GetProperties();
2189// }
2190//
2191// if (target_properties_sp)
2192// {
2193// var_name_begin += ::strlen ("target.");
2194// const char *end_property = strchr(var_name_begin, '}');
2195// if (end_property)
2196// {
2197// ConstString property_name(var_name_begin, end_property - var_name_begin);
2198// std::string property_value (target_properties_sp->GetPropertyValue(property_name));
2199// if (!property_value.empty())
2200// {
2201// s.PutCString (property_value.c_str());
2202// var_success = true;
2203// }
2204// }
2205// }
2206 Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
2207 if (target)
2208 {
2209 var_name_begin += ::strlen ("target.");
2210 if (IsToken (var_name_begin, "arch}"))
2211 {
2212 ArchSpec arch (target->GetArchitecture ());
2213 if (arch.IsValid())
2214 {
2215 s.PutCString (arch.GetArchitectureName());
2216 var_success = true;
2217 }
2218 }
2219 else if (IsToken (var_name_begin, "script:"))
2220 {
2221 var_name_begin += ::strlen("script:");
2222 std::string script_name(var_name_begin,var_name_end);
2223 ScriptInterpreter* script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
2224 if (RunScriptFormatKeyword (s, script_interpreter, target, script_name))
2225 var_success = true;
2226 }
2227 }
2228 }
2229 break;
2230
2231 case 'm':
2232 if (IsToken (var_name_begin, "module."))
2233 {
2234 if (sc && sc->module_sp.get())
2235 {
2236 Module *module = sc->module_sp.get();
2237 var_name_begin += ::strlen ("module.");
2238
2239 if (IsToken (var_name_begin, "file."))
2240 {
2241 if (module->GetFileSpec())
2242 {
2243 var_name_begin += ::strlen ("file.");
2244
2245 if (IsToken (var_name_begin, "basename}"))
2246 {
2247 format_file_spec.GetFilename() = module->GetFileSpec().GetFilename();
2248 var_success = (bool)format_file_spec;
2249 }
2250 else if (IsToken (var_name_begin, "fullpath}"))
2251 {
2252 format_file_spec = module->GetFileSpec();
2253 var_success = (bool)format_file_spec;
2254 }
2255 }
2256 }
2257 }
2258 }
2259 break;
2260
2261
2262 case 'f':
2263 if (IsToken (var_name_begin, "file."))
2264 {
2265 if (sc && sc->comp_unit != NULL__null)
2266 {
2267 var_name_begin += ::strlen ("file.");
2268
2269 if (IsToken (var_name_begin, "basename}"))
2270 {
2271 format_file_spec.GetFilename() = sc->comp_unit->GetFilename();
2272 var_success = (bool)format_file_spec;
2273 }
2274 else if (IsToken (var_name_begin, "fullpath}"))
2275 {
2276 format_file_spec = *sc->comp_unit;
2277 var_success = (bool)format_file_spec;
2278 }
2279 }
2280 }
2281 else if (IsToken (var_name_begin, "frame."))
2282 {
2283 if (exe_ctx)
2284 {
2285 StackFrame *frame = exe_ctx->GetFramePtr();
2286 if (frame)
2287 {
2288 var_name_begin += ::strlen ("frame.");
2289 if (IsToken (var_name_begin, "index}"))
2290 {
2291 s.Printf("%u", frame->GetFrameIndex());
2292 var_success = true;
2293 }
2294 else if (IsToken (var_name_begin, "pc}"))
2295 {
2296 reg_kind = eRegisterKindGeneric;
2297 reg_num = LLDB_REGNUM_GENERIC_PC0;
2298 var_success = true;
2299 }
2300 else if (IsToken (var_name_begin, "sp}"))
2301 {
2302 reg_kind = eRegisterKindGeneric;
2303 reg_num = LLDB_REGNUM_GENERIC_SP1;
2304 var_success = true;
2305 }
2306 else if (IsToken (var_name_begin, "fp}"))
2307 {
2308 reg_kind = eRegisterKindGeneric;
2309 reg_num = LLDB_REGNUM_GENERIC_FP2;
2310 var_success = true;
2311 }
2312 else if (IsToken (var_name_begin, "flags}"))
2313 {
2314 reg_kind = eRegisterKindGeneric;
2315 reg_num = LLDB_REGNUM_GENERIC_FLAGS4;
2316 var_success = true;
2317 }
2318 else if (IsToken (var_name_begin, "reg."))
2319 {
2320 reg_ctx = frame->GetRegisterContext().get();
2321 if (reg_ctx)
2322 {
2323 var_name_begin += ::strlen ("reg.");
2324 if (var_name_begin < var_name_end)
2325 {
2326 std::string reg_name (var_name_begin, var_name_end);
2327 reg_info = reg_ctx->GetRegisterInfoByName (reg_name.c_str());
2328 if (reg_info)
2329 var_success = true;
2330 }
2331 }
2332 }
2333 else if (IsToken (var_name_begin, "script:"))
2334 {
2335 var_name_begin += ::strlen("script:");
2336 std::string script_name(var_name_begin,var_name_end);
2337 ScriptInterpreter* script_interpreter = frame->GetThread()->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
2338 if (RunScriptFormatKeyword (s, script_interpreter, frame, script_name))
2339 var_success = true;
2340 }
2341 }
2342 }
2343 }
2344 else if (IsToken (var_name_begin, "function."))
2345 {
2346 if (sc && (sc->function != NULL__null || sc->symbol != NULL__null))
2347 {
2348 var_name_begin += ::strlen ("function.");
2349 if (IsToken (var_name_begin, "id}"))
2350 {
2351 if (sc->function)
2352 s.Printf("function{0x%8.8" PRIx64"l" "x" "}", sc->function->GetID());
2353 else
2354 s.Printf("symbol[%u]", sc->symbol->GetID());
2355
2356 var_success = true;
2357 }
2358 if (IsToken (var_name_begin, "changed}") && function_changed)
2359 {
2360 var_success = true;
2361 }
2362 if (IsToken (var_name_begin, "initial-function}") && initial_function)
2363 {
2364 var_success = true;
2365 }
2366 else if (IsToken (var_name_begin, "name}"))
2367 {
2368 if (sc->function)
2369 cstr = sc->function->GetName().AsCString (NULL__null);
2370 else if (sc->symbol)
2371 cstr = sc->symbol->GetName().AsCString (NULL__null);
2372 if (cstr)
2373 {
2374 s.PutCString(cstr);
2375
2376 if (sc->block)
2377 {
2378 Block *inline_block = sc->block->GetContainingInlinedBlock ();
2379 if (inline_block)
2380 {
2381 const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo();
2382 if (inline_info)
2383 {
2384 s.PutCString(" [inlined] ");
2385 inline_info->GetName().Dump(&s);
2386 }
2387 }
2388 }
2389 var_success = true;
2390 }
2391 }
2392 else if (IsToken (var_name_begin, "name-without-args}"))
2393 {
2394 ConstString name;
2395 if (sc->function)
2396 name = sc->function->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments);
2397 else if (sc->symbol)
2398 name = sc->symbol->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments);
2399 if (name)
2400 {
2401 s.PutCString(name.GetCString());
2402 var_success = true;
2403 }
2404 }
2405 else if (IsToken (var_name_begin, "name-with-args}"))
2406 {
2407 // Print the function name with arguments in it
2408
2409 if (sc->function)
2410 {
2411 var_success = true;
2412 ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL__null;
2413 cstr = sc->function->GetName().AsCString (NULL__null);
2414 if (cstr)
2415 {
2416 const InlineFunctionInfo *inline_info = NULL__null;
2417 VariableListSP variable_list_sp;
2418 bool get_function_vars = true;
2419 if (sc->block)
2420 {
2421 Block *inline_block = sc->block->GetContainingInlinedBlock ();
2422
2423 if (inline_block)
2424 {
2425 get_function_vars = false;
2426 inline_info = sc->block->GetInlinedFunctionInfo();
2427 if (inline_info)
2428 variable_list_sp = inline_block->GetBlockVariableList (true);
2429 }
2430 }
2431
2432 if (get_function_vars)
2433 {
2434 variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true);
2435 }
2436
2437 if (inline_info)
2438 {
2439 s.PutCString (cstr);
2440 s.PutCString (" [inlined] ");
2441 cstr = inline_info->GetName().GetCString();
2442 }
2443
2444 VariableList args;
2445 if (variable_list_sp)
2446 variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args);
2447 if (args.GetSize() > 0)
2448 {
2449 const char *open_paren = strchr (cstr, '(');
2450 const char *close_paren = nullptr;
2451 const char *generic = strchr(cstr, '<');
2452 // if before the arguments list begins there is a template sign
2453 // then scan to the end of the generic args before you try to find
2454 // the arguments list
2455 if (generic && open_paren && generic < open_paren)
2456 {
2457 int generic_depth = 1;
2458 ++generic;
2459 for (;
2460 *generic && generic_depth > 0;
2461 generic++)
2462 {
2463 if (*generic == '<')
2464 generic_depth++;
2465 if (*generic == '>')
2466 generic_depth--;
2467 }
2468 if (*generic)
2469 open_paren = strchr(generic, '(');
2470 else
2471 open_paren = nullptr;
2472 }
2473 if (open_paren)
2474 {
2475 if (IsToken (open_paren, "(anonymous namespace)"))
2476 {
2477 open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '(');
2478 if (open_paren)
2479 close_paren = strchr (open_paren, ')');
2480 }
2481 else
2482 close_paren = strchr (open_paren, ')');
2483 }
2484
2485 if (open_paren)
2486 s.Write(cstr, open_paren - cstr + 1);
2487 else
2488 {
2489 s.PutCString (cstr);
2490 s.PutChar ('(');
2491 }
2492 const size_t num_args = args.GetSize();
2493 for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx)
2494 {
2495 std::string buffer;
2496
2497 VariableSP var_sp (args.GetVariableAtIndex (arg_idx));
2498 ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp));
2499 const char *var_representation = nullptr;
2500 const char *var_name = var_value_sp->GetName().GetCString();
2501 if (var_value_sp->GetClangType().IsAggregateType() &&
2502 DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get()))
2503 {
2504 static StringSummaryFormat format(TypeSummaryImpl::Flags()
2505 .SetHideItemNames(false)
2506 .SetShowMembersOneLiner(true),
2507 "");
2508 format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions());
2509 var_representation = buffer.c_str();
2510 }
2511 else
2512 var_representation = var_value_sp->GetValueAsCString();
2513 if (arg_idx > 0)
2514 s.PutCString (", ");
2515 if (var_value_sp->GetError().Success())
2516 {
2517 if (var_representation)
2518 s.Printf ("%s=%s", var_name, var_representation);
2519 else
2520 s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString());
2521 }
2522 else
2523 s.Printf ("%s=<unavailable>", var_name);
2524 }
2525
2526 if (close_paren)
2527 s.PutCString (close_paren);
2528 else
2529 s.PutChar(')');
2530
2531 }
2532 else
2533 {
2534 s.PutCString(cstr);
2535 }
2536 }
2537 }
2538 else if (sc->symbol)
2539 {
2540 cstr = sc->symbol->GetName().AsCString (NULL__null);
2541 if (cstr)
2542 {
2543 s.PutCString(cstr);
2544 var_success = true;
2545 }
2546 }
2547 }
2548 else if (IsToken (var_name_begin, "addr-offset}")
2549 || IsToken (var_name_begin, "concrete-only-addr-offset-no-padding}"))
2550 {
2551 if (IsToken (var_name_begin, "concrete-only-addr-offset-no-padding}"))
2552 {
2553 addr_offset_print_with_no_padding = true;
2554 addr_offset_concrete_func_only = true;
2555 }
2556 var_success = addr != NULL__null;
2557 if (var_success)
2558 {
2559 format_addr = *addr;
2560 calculate_format_addr_function_offset = true;
2561 }
2562 }
2563 else if (IsToken (var_name_begin, "line-offset}"))
2564 {
2565 var_success = sc->line_entry.range.GetBaseAddress().IsValid();
2566 if (var_success)
2567 {
2568 format_addr = sc->line_entry.range.GetBaseAddress();
2569 calculate_format_addr_function_offset = true;
2570 }
2571 }
2572 else if (IsToken (var_name_begin, "pc-offset}"))
2573 {
2574 StackFrame *frame = exe_ctx->GetFramePtr();
2575 var_success = frame != NULL__null;
2576 if (var_success)
2577 {
2578 format_addr = frame->GetFrameCodeAddress();
2579 calculate_format_addr_function_offset = true;
2580 }
2581 }
2582 }
2583 }
2584 break;
2585
2586 case 'l':
2587 if (IsToken (var_name_begin, "line."))
2588 {
2589 if (sc && sc->line_entry.IsValid())
2590 {
2591 var_name_begin += ::strlen ("line.");
2592 if (IsToken (var_name_begin, "file."))
2593 {
2594 var_name_begin += ::strlen ("file.");
2595
2596 if (IsToken (var_name_begin, "basename}"))
2597 {
2598 format_file_spec.GetFilename() = sc->line_entry.file.GetFilename();
2599 var_success = (bool)format_file_spec;
2600 }
2601 else if (IsToken (var_name_begin, "fullpath}"))
2602 {
2603 format_file_spec = sc->line_entry.file;
2604 var_success = (bool)format_file_spec;
2605 }
2606 }
2607 else if (IsTokenWithFormat (var_name_begin, "number", token_format, "%" PRIu64"l" "u", exe_ctx, sc))
2608 {
2609 var_success = true;
2610 s.Printf(token_format.c_str(), (uint64_t)sc->line_entry.line);
2611 }
2612 else if ((IsToken (var_name_begin, "start-addr}")) ||
2613 (IsToken (var_name_begin, "end-addr}")))
2614 {
2615 var_success = sc && sc->line_entry.range.GetBaseAddress().IsValid();
2616 if (var_success)
2617 {
2618 format_addr = sc->line_entry.range.GetBaseAddress();
2619 if (var_name_begin[0] == 'e')
2620 format_addr.Slide (sc->line_entry.range.GetByteSize());
2621 }
2622 }
2623 }
2624 }
2625 break;
2626 case 'c':
2627 if (IsToken (var_name_begin, "current-pc-arrow"))
2628 {
2629 if (addr && exe_ctx && exe_ctx->GetFramePtr())
2630 {
2631 RegisterContextSP reg_ctx = exe_ctx->GetFramePtr()->GetRegisterContextSP();
2632 if (reg_ctx.get())
2633 {
2634 addr_t pc_loadaddr = reg_ctx->GetPC();
2635 if (pc_loadaddr != LLDB_INVALID_ADDRESS(18446744073709551615UL))
2636 {
2637 Address pc;
2638 pc.SetLoadAddress (pc_loadaddr, exe_ctx->GetTargetPtr());
2639 if (pc == *addr)
2640 {
2641 s.Printf ("-> ");
2642 var_success = true;
2643 }
2644 }
2645 }
2646 if (var_success == false)
2647 {
2648 s.Printf(" ");
2649 var_success = true;
Value stored to 'var_success' is never read
2650 }
2651 }
2652 var_success = true;
2653 }
2654 break;
2655 }
2656
2657 if (var_success)
2658 {
2659 // If format addr is valid, then we need to print an address
2660 if (reg_num != LLDB_INVALID_REGNUM(4294967295U))
2661 {
2662 StackFrame *frame = exe_ctx->GetFramePtr();
2663 // We have a register value to display...
2664 if (reg_num == LLDB_REGNUM_GENERIC_PC0 && reg_kind == eRegisterKindGeneric)
2665 {
2666 format_addr = frame->GetFrameCodeAddress();
2667 }
2668 else
2669 {
2670 if (reg_ctx == NULL__null)
2671 reg_ctx = frame->GetRegisterContext().get();
2672
2673 if (reg_ctx)
2674 {
2675 if (reg_kind != kNumRegisterKinds)
2676 reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
2677 reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num);
2678 var_success = reg_info != NULL__null;
2679 }
2680 }
2681 }
2682
2683 if (reg_info != NULL__null)
2684 {
2685 RegisterValue reg_value;
2686 var_success = reg_ctx->ReadRegister (reg_info, reg_value);
2687 if (var_success)
2688 {
2689 reg_value.Dump(&s, reg_info, false, false, eFormatDefault);
2690 }
2691 }
2692
2693 if (format_file_spec)
2694 {
2695 s << format_file_spec;
2696 }
2697
2698 // If format addr is valid, then we need to print an address
2699 if (format_addr.IsValid())
2700 {
2701 var_success = false;
2702
2703 if (calculate_format_addr_function_offset)
2704 {
2705 Address func_addr;
2706
2707 if (sc)
2708 {
2709 if (sc->function)
2710 {
2711 func_addr = sc->function->GetAddressRange().GetBaseAddress();
2712 if (sc->block && addr_offset_concrete_func_only == false)
2713 {
2714 // Check to make sure we aren't in an inline
2715 // function. If we are, use the inline block
2716 // range that contains "format_addr" since
2717 // blocks can be discontiguous.
2718 Block *inline_block = sc->block->GetContainingInlinedBlock ();
2719 AddressRange inline_range;
2720 if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range))
2721 func_addr = inline_range.GetBaseAddress();
2722 }
2723 }
2724 else if (sc->symbol && sc->symbol->ValueIsAddress())
2725 func_addr = sc->symbol->GetAddress();
2726 }
2727
2728 if (func_addr.IsValid())
2729 {
2730 const char *addr_offset_padding = " ";
2731 if (addr_offset_print_with_no_padding)
2732 {
2733 addr_offset_padding = "";
2734 }
2735 if (func_addr.GetSection() == format_addr.GetSection())
2736 {
2737 addr_t func_file_addr = func_addr.GetFileAddress();
2738 addr_t addr_file_addr = format_addr.GetFileAddress();
2739 if (addr_file_addr > func_file_addr)
2740 s.Printf("%s+%s%" PRIu64"l" "u", addr_offset_padding, addr_offset_padding, addr_file_addr - func_file_addr);
2741 else if (addr_file_addr < func_file_addr)
2742 s.Printf("%s-%s%" PRIu64"l" "u", addr_offset_padding, addr_offset_padding, func_file_addr - addr_file_addr);
2743 var_success = true;
2744 }
2745 else
2746 {
2747 Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
2748 if (target)
2749 {
2750 addr_t func_load_addr = func_addr.GetLoadAddress (target);
2751 addr_t addr_load_addr = format_addr.GetLoadAddress (target);
2752 if (addr_load_addr > func_load_addr)
2753 s.Printf("%s+%s%" PRIu64"l" "u", addr_offset_padding, addr_offset_padding, addr_load_addr - func_load_addr);
2754 else if (addr_load_addr < func_load_addr)
2755 s.Printf("%s-%s%" PRIu64"l" "u", addr_offset_padding, addr_offset_padding, func_load_addr - addr_load_addr);
2756 var_success = true;
2757 }
2758 }
2759 }
2760 }
2761 else
2762 {
2763 Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
2764 addr_t vaddr = LLDB_INVALID_ADDRESS(18446744073709551615UL);
2765 if (exe_ctx && !target->GetSectionLoadList().IsEmpty())
2766 vaddr = format_addr.GetLoadAddress (target);
2767 if (vaddr == LLDB_INVALID_ADDRESS(18446744073709551615UL))
2768 vaddr = format_addr.GetFileAddress ();
2769
2770 if (vaddr != LLDB_INVALID_ADDRESS(18446744073709551615UL))
2771 {
2772 int addr_width = 0;
2773 if (exe_ctx && target)
2774 {
2775 addr_width = target->GetArchitecture().GetAddressByteSize() * 2;
2776 }
2777 if (addr_width == 0)
2778 addr_width = 16;
2779 if (print_file_addr_or_load_addr)
2780 {
2781 format_addr.Dump (&s, exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL__null, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0);
2782 }
2783 else
2784 {
2785 s.Printf("0x%*.*" PRIx64"l" "x", addr_width, addr_width, vaddr);
2786 }
2787 var_success = true;
2788 }
2789 }
2790 }
2791 }
2792
2793 if (var_success == false)
2794 success = false;
2795 }
2796 p = var_name_end;
2797 }
2798 else
2799 break;
2800 }
2801 else
2802 {
2803 // We got a dollar sign with no '{' after it, it must just be a dollar sign
2804 s.PutChar(*p);
2805 }
2806 }
2807 else if (*p == '\\')
2808 {
2809 ++p; // skip the slash
2810 switch (*p)
2811 {
2812 case 'a': s.PutChar ('\a'); break;
2813 case 'b': s.PutChar ('\b'); break;
2814 case 'f': s.PutChar ('\f'); break;
2815 case 'n': s.PutChar ('\n'); break;
2816 case 'r': s.PutChar ('\r'); break;
2817 case 't': s.PutChar ('\t'); break;
2818 case 'v': s.PutChar ('\v'); break;
2819 case '\'': s.PutChar ('\''); break;
2820 case '\\': s.PutChar ('\\'); break;
2821 case '0':
2822 // 1 to 3 octal chars
2823 {
2824 // Make a string that can hold onto the initial zero char,
2825 // up to 3 octal digits, and a terminating NULL.
2826 char oct_str[5] = { 0, 0, 0, 0, 0 };
2827
2828 int i;
2829 for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i)
2830 oct_str[i] = p[i];
2831
2832 // We don't want to consume the last octal character since
2833 // the main for loop will do this for us, so we advance p by
2834 // one less than i (even if i is zero)
2835 p += i - 1;
2836 unsigned long octal_value = ::strtoul (oct_str, NULL__null, 8);
2837 if (octal_value <= UINT8_MAX(255))
2838 {
2839 s.PutChar((char)octal_value);
2840 }
2841 }
2842 break;
2843
2844 case 'x':
2845 // hex number in the format
2846 if (isxdigit(p[1]))
2847 {
2848 ++p; // Skip the 'x'
2849
2850 // Make a string that can hold onto two hex chars plus a
2851 // NULL terminator
2852 char hex_str[3] = { 0,0,0 };
2853 hex_str[0] = *p;
2854 if (isxdigit(p[1]))
2855 {
2856 ++p; // Skip the first of the two hex chars
2857 hex_str[1] = *p;
2858 }
2859
2860 unsigned long hex_value = strtoul (hex_str, NULL__null, 16);
2861 if (hex_value <= UINT8_MAX(255))
2862 s.PutChar ((char)hex_value);
2863 }
2864 else
2865 {
2866 s.PutChar('x');
2867 }
2868 break;
2869
2870 default:
2871 // Just desensitize any other character by just printing what
2872 // came after the '\'
2873 s << *p;
2874 break;
2875
2876 }
2877
2878 }
2879 }
2880 if (end)
2881 *end = p;
2882 return success;
2883}
2884
2885bool
2886Debugger::FormatPrompt
2887(
2888 const char *format,
2889 const SymbolContext *sc,
2890 const ExecutionContext *exe_ctx,
2891 const Address *addr,
2892 Stream &s,
2893 ValueObject* valobj
2894)
2895{
2896 bool use_color = exe_ctx ? exe_ctx->GetTargetRef().GetDebugger().GetUseColor() : true;
2897 std::string format_str = lldb_utility::ansi::FormatAnsiTerminalCodes (format, use_color);
2898 if (format_str.length())
2899 format = format_str.c_str();
2900 return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL__null, valobj, false, false);
2901}
2902
2903bool
2904Debugger::FormatDisassemblerAddress (const char *format,
2905 const SymbolContext *sc,
2906 const SymbolContext *prev_sc,
2907 const ExecutionContext *exe_ctx,
2908 const Address *addr,
2909 Stream &s)
2910{
2911 if (format == NULL__null && exe_ctx != NULL__null && exe_ctx->HasTargetScope())
2912 {
2913 format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
2914 }
2915 bool function_changed = false;
2916 bool initial_function = false;
2917 if (prev_sc && (prev_sc->function || prev_sc->symbol))
2918 {
2919 if (sc && (sc->function || sc->symbol))
2920 {
2921 if (prev_sc->symbol && sc->symbol)
2922 {
2923 if (!sc->symbol->Compare (prev_sc->symbol->GetName(), prev_sc->symbol->GetType()))
2924 {
2925 function_changed = true;
2926 }
2927 }
2928 else if (prev_sc->function && sc->function)
2929 {
2930 if (prev_sc->function->GetMangled() != sc->function->GetMangled())
2931 {
2932 function_changed = true;
2933 }
2934 }
2935 }
2936 }
2937 // The first context on a list of instructions will have a prev_sc that
2938 // has no Function or Symbol -- if SymbolContext had an IsValid() method, it
2939 // would return false. But we do get a prev_sc pointer.
2940 if ((sc && (sc->function || sc->symbol))
2941 && prev_sc && (prev_sc->function == NULL__null && prev_sc->symbol == NULL__null))
2942 {
2943 initial_function = true;
2944 }
2945 return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL__null, NULL__null, function_changed, initial_function);
2946}
2947
2948
2949void
2950Debugger::SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton)
2951{
2952 // For simplicity's sake, I am not going to deal with how to close down any
2953 // open logging streams, I just redirect everything from here on out to the
2954 // callback.
2955 m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton));
2956}
2957
2958bool
2959Debugger::EnableLog (const char *channel, const char **categories, const char *log_file, uint32_t log_options, Stream &error_stream)
2960{
2961 Log::Callbacks log_callbacks;
2962
2963 StreamSP log_stream_sp;
2964 if (m_log_callback_stream_sp)
2965 {
2966 log_stream_sp = m_log_callback_stream_sp;
2967 // For now when using the callback mode you always get thread & timestamp.
2968 log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP(1u << 4) | LLDB_LOG_OPTION_PREPEND_THREAD_NAME(1U << 6);
2969 }
2970 else if (log_file == NULL__null || *log_file == '\0')
2971 {
2972 log_stream_sp = GetOutputFile();
2973 }
2974 else
2975 {
2976 LogStreamMap::iterator pos = m_log_streams.find(log_file);
2977 if (pos != m_log_streams.end())
2978 log_stream_sp = pos->second.lock();
2979 if (!log_stream_sp)
2980 {
2981 log_stream_sp.reset (new StreamFile (log_file));
2982 m_log_streams[log_file] = log_stream_sp;
2983 }
2984 }
2985 assert (log_stream_sp.get())((log_stream_sp.get()) ? static_cast<void> (0) : __assert_fail
("log_stream_sp.get()", "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn227765/tools/lldb/source/Core/Debugger.cpp"
, 2985, __PRETTY_FUNCTION__))
;
2986
2987 if (log_options == 0)
2988 log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME(1U << 6) | LLDB_LOG_OPTION_THREADSAFE(1u << 0);
2989
2990 if (Log::GetLogChannelCallbacks (ConstString(channel), log_callbacks))
2991 {
2992 log_callbacks.enable (log_stream_sp, log_options, categories, &error_stream);
2993 return true;
2994 }
2995 else
2996 {
2997 LogChannelSP log_channel_sp (LogChannel::FindPlugin (channel));
2998 if (log_channel_sp)
2999 {
3000 if (log_channel_sp->Enable (log_stream_sp, log_options, &error_stream, categories))
3001 {
3002 return true;
3003 }
3004 else
3005 {
3006 error_stream.Printf ("Invalid log channel '%s'.\n", channel);
3007 return false;
3008 }
3009 }
3010 else
3011 {
3012 error_stream.Printf ("Invalid log channel '%s'.\n", channel);
3013 return false;
3014 }
3015 }
3016 return false;
3017}
3018
3019SourceManager &
3020Debugger::GetSourceManager ()
3021{
3022 if (m_source_manager_ap.get() == NULL__null)
3023 m_source_manager_ap.reset (new SourceManager (shared_from_this()));
3024 return *m_source_manager_ap;
3025}
3026
3027
3028
3029// This function handles events that were broadcast by the process.
3030void
3031Debugger::HandleBreakpointEvent (const EventSP &event_sp)
3032{
3033 using namespace lldb;
3034 const uint32_t event_type = Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (event_sp);
3035
3036// if (event_type & eBreakpointEventTypeAdded
3037// || event_type & eBreakpointEventTypeRemoved
3038// || event_type & eBreakpointEventTypeEnabled
3039// || event_type & eBreakpointEventTypeDisabled
3040// || event_type & eBreakpointEventTypeCommandChanged
3041// || event_type & eBreakpointEventTypeConditionChanged
3042// || event_type & eBreakpointEventTypeIgnoreChanged
3043// || event_type & eBreakpointEventTypeLocationsResolved)
3044// {
3045// // Don't do anything about these events, since the breakpoint commands already echo these actions.
3046// }
3047//
3048 if (event_type & eBreakpointEventTypeLocationsAdded)
3049 {
3050 uint32_t num_new_locations = Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(event_sp);
3051 if (num_new_locations > 0)
3052 {
3053 BreakpointSP breakpoint = Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp);
3054 StreamFileSP output_sp (GetOutputFile());
3055 if (output_sp)
3056 {
3057 output_sp->Printf("%d location%s added to breakpoint %d\n",
3058 num_new_locations,
3059 num_new_locations == 1 ? "" : "s",
3060 breakpoint->GetID());
3061 RefreshTopIOHandler();
3062 }
3063 }
3064 }
3065// else if (event_type & eBreakpointEventTypeLocationsRemoved)
3066// {
3067// // These locations just get disabled, not sure it is worth spamming folks about this on the command line.
3068// }
3069// else if (event_type & eBreakpointEventTypeLocationsResolved)
3070// {
3071// // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy.
3072// }
3073}
3074
3075size_t
3076Debugger::GetProcessSTDOUT (Process *process, Stream *stream)
3077{
3078 size_t total_bytes = 0;
3079 if (stream == NULL__null)
3080 stream = GetOutputFile().get();
3081
3082 if (stream)
3083 {
3084 // The process has stuff waiting for stdout; get it and write it out to the appropriate place.
3085 if (process == NULL__null)
3086 {
3087 TargetSP target_sp = GetTargetList().GetSelectedTarget();
3088 if (target_sp)
3089 process = target_sp->GetProcessSP().get();
3090 }
3091 if (process)
3092 {
3093 Error error;
3094 size_t len;
3095 char stdio_buffer[1024];
3096 while ((len = process->GetSTDOUT (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
3097 {
3098 stream->Write(stdio_buffer, len);
3099 total_bytes += len;
3100 }
3101 }
3102 stream->Flush();
3103 }
3104 return total_bytes;
3105}
3106
3107size_t
3108Debugger::GetProcessSTDERR (Process *process, Stream *stream)
3109{
3110 size_t total_bytes = 0;
3111 if (stream == NULL__null)
3112 stream = GetOutputFile().get();
3113
3114 if (stream)
3115 {
3116 // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
3117 if (process == NULL__null)
3118 {
3119 TargetSP target_sp = GetTargetList().GetSelectedTarget();
3120 if (target_sp)
3121 process = target_sp->GetProcessSP().get();
3122 }
3123 if (process)
3124 {
3125 Error error;
3126 size_t len;
3127 char stdio_buffer[1024];
3128 while ((len = process->GetSTDERR (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
3129 {
3130 stream->Write(stdio_buffer, len);
3131 total_bytes += len;
3132 }
3133 }
3134 stream->Flush();
3135 }
3136 return total_bytes;
3137}
3138
3139
3140// This function handles events that were broadcast by the process.
3141void
3142Debugger::HandleProcessEvent (const EventSP &event_sp)
3143{
3144 using namespace lldb;
3145 const uint32_t event_type = event_sp->GetType();
3146 ProcessSP process_sp = Process::ProcessEventData::GetProcessFromEvent(event_sp.get());
3147
3148 StreamString output_stream;
3149 StreamString error_stream;
3150 const bool gui_enabled = IsForwardingEvents();
3151
3152 if (!gui_enabled)
3153 {
3154 bool pop_process_io_handler = false;
3155 assert (process_sp)((process_sp) ? static_cast<void> (0) : __assert_fail (
"process_sp", "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn227765/tools/lldb/source/Core/Debugger.cpp"
, 3155, __PRETTY_FUNCTION__))
;
3156
3157 if (event_type & Process::eBroadcastBitSTDOUT || event_type & Process::eBroadcastBitStateChanged)
3158 {
3159 GetProcessSTDOUT (process_sp.get(), &output_stream);
3160 }
3161
3162 if (event_type & Process::eBroadcastBitSTDERR || event_type & Process::eBroadcastBitStateChanged)
3163 {
3164 GetProcessSTDERR (process_sp.get(), &error_stream);
3165 }
3166
3167 if (event_type & Process::eBroadcastBitStateChanged)
3168 {
3169 Process::HandleProcessStateChangedEvent (event_sp, &output_stream, pop_process_io_handler);
3170 }
3171
3172 if (output_stream.GetSize() || error_stream.GetSize())
3173 {
3174 StreamFileSP error_stream_sp (GetOutputFile());
3175 bool top_io_handler_hid = false;
3176
3177 if (process_sp->ProcessIOHandlerIsActive() == false)
3178 top_io_handler_hid = HideTopIOHandler();
3179
3180 if (output_stream.GetSize())
3181 {
3182 StreamFileSP output_stream_sp (GetOutputFile());
3183 if (output_stream_sp)
3184 output_stream_sp->Write (output_stream.GetData(), output_stream.GetSize());
3185 }
3186
3187 if (error_stream.GetSize())
3188 {
3189 StreamFileSP error_stream_sp (GetErrorFile());
3190 if (error_stream_sp)
3191 error_stream_sp->Write (error_stream.GetData(), error_stream.GetSize());
3192 }
3193
3194 if (top_io_handler_hid)
3195 RefreshTopIOHandler();
3196 }
3197
3198 if (pop_process_io_handler)
3199 process_sp->PopProcessIOHandler();
3200 }
3201}
3202
3203void
3204Debugger::HandleThreadEvent (const EventSP &event_sp)
3205{
3206 // At present the only thread event we handle is the Frame Changed event,
3207 // and all we do for that is just reprint the thread status for that thread.
3208 using namespace lldb;
3209 const uint32_t event_type = event_sp->GetType();
3210 if (event_type == Thread::eBroadcastBitStackChanged ||
3211 event_type == Thread::eBroadcastBitThreadSelected )
3212 {
3213 ThreadSP thread_sp (Thread::ThreadEventData::GetThreadFromEvent (event_sp.get()));
3214 if (thread_sp)
3215 {
3216 HideTopIOHandler();
3217 StreamFileSP stream_sp (GetOutputFile());
3218 thread_sp->GetStatus(*stream_sp, 0, 1, 1);
3219 RefreshTopIOHandler();
3220 }
3221 }
3222}
3223
3224bool
3225Debugger::IsForwardingEvents ()
3226{
3227 return (bool)m_forward_listener_sp;
3228}
3229
3230void
3231Debugger::EnableForwardEvents (const ListenerSP &listener_sp)
3232{
3233 m_forward_listener_sp = listener_sp;
3234}
3235
3236void
3237Debugger::CancelForwardEvents (const ListenerSP &listener_sp)
3238{
3239 m_forward_listener_sp.reset();
3240}
3241
3242
3243void
3244Debugger::DefaultEventHandler()
3245{
3246 Listener& listener(GetListener());
3247 ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
3248 ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
3249 ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
3250 BroadcastEventSpec target_event_spec (broadcaster_class_target,
3251 Target::eBroadcastBitBreakpointChanged);
3252
3253 BroadcastEventSpec process_event_spec (broadcaster_class_process,
3254 Process::eBroadcastBitStateChanged |
3255 Process::eBroadcastBitSTDOUT |
3256 Process::eBroadcastBitSTDERR);
3257
3258 BroadcastEventSpec thread_event_spec (broadcaster_class_thread,
3259 Thread::eBroadcastBitStackChanged |
3260 Thread::eBroadcastBitThreadSelected );
3261
3262 listener.StartListeningForEventSpec (*this, target_event_spec);
3263 listener.StartListeningForEventSpec (*this, process_event_spec);
3264 listener.StartListeningForEventSpec (*this, thread_event_spec);
3265 listener.StartListeningForEvents (m_command_interpreter_ap.get(),
3266 CommandInterpreter::eBroadcastBitQuitCommandReceived |
3267 CommandInterpreter::eBroadcastBitAsynchronousOutputData |
3268 CommandInterpreter::eBroadcastBitAsynchronousErrorData );
3269
3270 // Let the thread that spawned us know that we have started up and
3271 // that we are now listening to all required events so no events get missed
3272 m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening);
3273
3274 bool done = false;
3275 while (!done)
3276 {
3277 EventSP event_sp;
3278 if (listener.WaitForEvent(NULL__null, event_sp))
3279 {
3280 if (event_sp)
3281 {
3282 Broadcaster *broadcaster = event_sp->GetBroadcaster();
3283 if (broadcaster)
3284 {
3285 uint32_t event_type = event_sp->GetType();
3286 ConstString broadcaster_class (broadcaster->GetBroadcasterClass());
3287 if (broadcaster_class == broadcaster_class_process)
3288 {
3289 HandleProcessEvent (event_sp);
3290 }
3291 else if (broadcaster_class == broadcaster_class_target)
3292 {
3293 if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(event_sp.get()))
3294 {
3295 HandleBreakpointEvent (event_sp);
3296 }
3297 }
3298 else if (broadcaster_class == broadcaster_class_thread)
3299 {
3300 HandleThreadEvent (event_sp);
3301 }
3302 else if (broadcaster == m_command_interpreter_ap.get())
3303 {
3304 if (event_type & CommandInterpreter::eBroadcastBitQuitCommandReceived)
3305 {
3306 done = true;
3307 }
3308 else if (event_type & CommandInterpreter::eBroadcastBitAsynchronousErrorData)
3309 {
3310 const char *data = reinterpret_cast<const char *>(EventDataBytes::GetBytesFromEvent (event_sp.get()));
3311 if (data && data[0])
3312 {
3313 StreamFileSP error_sp (GetErrorFile());
3314 if (error_sp)
3315 {
3316 HideTopIOHandler();
3317 error_sp->PutCString(data);
3318 error_sp->Flush();
3319 RefreshTopIOHandler();
3320 }
3321 }
3322 }
3323 else if (event_type & CommandInterpreter::eBroadcastBitAsynchronousOutputData)
3324 {
3325 const char *data = reinterpret_cast<const char *>(EventDataBytes::GetBytesFromEvent (event_sp.get()));
3326 if (data && data[0])
3327 {
3328 StreamFileSP output_sp (GetOutputFile());
3329 if (output_sp)
3330 {
3331 HideTopIOHandler();
3332 output_sp->PutCString(data);
3333 output_sp->Flush();
3334 RefreshTopIOHandler();
3335 }
3336 }
3337 }
3338 }
3339 }
3340
3341 if (m_forward_listener_sp)
3342 m_forward_listener_sp->AddEvent(event_sp);
3343 }
3344 }
3345 }
3346}
3347
3348lldb::thread_result_t
3349Debugger::EventHandlerThread (lldb::thread_arg_t arg)
3350{
3351 ((Debugger *)arg)->DefaultEventHandler();
3352 return NULL__null;
3353}
3354
3355bool
3356Debugger::StartEventHandlerThread()
3357{
3358 if (!m_event_handler_thread.IsJoinable())
3359 {
3360 // We must synchronize with the DefaultEventHandler() thread to ensure
3361 // it is up and running and listening to events before we return from
3362 // this function. We do this by listening to events for the
3363 // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster
3364 Listener listener("lldb.debugger.event-handler");
3365 listener.StartListeningForEvents(&m_sync_broadcaster, eBroadcastBitEventThreadIsListening);
3366
3367 // Use larger 8MB stack for this thread
3368 m_event_handler_thread = ThreadLauncher::LaunchThread("lldb.debugger.event-handler", EventHandlerThread,
3369 this,
3370 NULL__null,
3371 g_debugger_event_thread_stack_bytes);
3372
3373 // Make sure DefaultEventHandler() is running and listening to events before we return
3374 // from this function. We are only listening for events of type
3375 // eBroadcastBitEventThreadIsListening so we don't need to check the event, we just need
3376 // to wait an infinite amount of time for it (NULL timeout as the first parameter)
3377 lldb::EventSP event_sp;
3378 listener.WaitForEvent(NULL__null, event_sp);
3379 }
3380 return m_event_handler_thread.IsJoinable();
3381}
3382
3383void
3384Debugger::StopEventHandlerThread()
3385{
3386 if (m_event_handler_thread.IsJoinable())
3387 {
3388 GetCommandInterpreter().BroadcastEvent(CommandInterpreter::eBroadcastBitQuitCommandReceived);
3389 m_event_handler_thread.Join(nullptr);
3390 }
3391}
3392
3393
3394lldb::thread_result_t
3395Debugger::IOHandlerThread (lldb::thread_arg_t arg)
3396{
3397 Debugger *debugger = (Debugger *)arg;
3398 debugger->ExecuteIOHanders();
3399 debugger->StopEventHandlerThread();
3400 return NULL__null;
3401}
3402
3403bool
3404Debugger::StartIOHandlerThread()
3405{
3406 if (!m_io_handler_thread.IsJoinable())
3407 m_io_handler_thread = ThreadLauncher::LaunchThread ("lldb.debugger.io-handler",
3408 IOHandlerThread,
3409 this,
3410 NULL__null,
3411 8*1024*1024); // Use larger 8MB stack for this thread
3412 return m_io_handler_thread.IsJoinable();
3413}
3414
3415void
3416Debugger::StopIOHandlerThread()
3417{
3418 if (m_io_handler_thread.IsJoinable())
3419 {
3420 if (m_input_file_sp)
3421 m_input_file_sp->GetFile().Close();
3422 m_io_handler_thread.Join(nullptr);
3423 }
3424}
3425
3426Target *
3427Debugger::GetDummyTarget()
3428{
3429 return m_target_list.GetDummyTarget (*this).get();
3430}
3431
3432Target *
3433Debugger::GetSelectedOrDummyTarget(bool prefer_dummy)
3434{
3435 Target *target = nullptr;
3436 if (!prefer_dummy)
3437 {
3438 target = m_target_list.GetSelectedTarget().get();
3439 if (target)
3440 return target;
3441 }
3442
3443 return GetDummyTarget();
3444}
3445