diff options
Diffstat (limited to 'source/Core/Debugger.cpp')
-rw-r--r-- | source/Core/Debugger.cpp | 1750 |
1 files changed, 48 insertions, 1702 deletions
diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp index c7342ad..f25a3f4 100644 --- a/source/Core/Debugger.cpp +++ b/source/Core/Debugger.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/StringRef.h" #include "lldb/lldb-private.h" +#include "lldb/Core/FormatEntity.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/RegisterValue.h" @@ -130,24 +131,23 @@ g_language_enumerators[] = static PropertyDefinition g_properties[] = { -{ "auto-confirm", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true all confirmation prompts will receive their default reply." }, -{ "disassembly-format", OptionValue::eTypeString , true, 0 , DEFAULT_DISASSEMBLY_FORMAT, NULL, "The default disassembly format string to use when disassembling instruction sequences." }, -{ "frame-format", OptionValue::eTypeString , true, 0 , DEFAULT_FRAME_FORMAT, NULL, "The default frame format string to use when displaying stack frame information for threads." }, -{ "notify-void", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Notify the user explicitly if an expression returns void (default: false)." }, -{ "prompt", OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", NULL, "The debugger command line prompt displayed for the user." }, -{ "script-lang", OptionValue::eTypeEnum , true, eScriptLanguagePython, NULL, g_language_enumerators, "The script language to be used for evaluating user-written scripts." }, -{ "stop-disassembly-count", OptionValue::eTypeSInt64 , true, 4 , NULL, NULL, "The number of disassembly lines to show when displaying a stopped context." }, -{ "stop-disassembly-display", OptionValue::eTypeEnum , true, Debugger::eStopDisassemblyTypeNoSource, NULL, g_show_disassembly_enum_values, "Control when to display disassembly when displaying a stopped context." }, -{ "stop-line-count-after", OptionValue::eTypeSInt64 , true, 3 , NULL, NULL, "The number of sources lines to display that come after the current source line when displaying a stopped context." }, -{ "stop-line-count-before", OptionValue::eTypeSInt64 , true, 3 , NULL, NULL, "The number of sources lines to display that come before the current source line when displaying a stopped context." }, -{ "term-width", OptionValue::eTypeSInt64 , true, 80 , NULL, NULL, "The maximum number of columns to use for displaying text." }, -{ "thread-format", OptionValue::eTypeString , true, 0 , DEFAULT_THREAD_FORMAT, NULL, "The default thread format string to use when displaying thread information." }, -{ "use-external-editor", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Whether to use an external editor or not." }, -{ "use-color", OptionValue::eTypeBoolean, true, true , NULL, NULL, "Whether to use Ansi color codes or not." }, -{ "auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will automatically display small structs in one-liner format (default: true)." }, -{ "escape-non-printables", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will automatically escape non-printable and escape characters when formatting strings." }, - - { NULL, OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL } +{ "auto-confirm", OptionValue::eTypeBoolean , true, false, NULL, NULL, "If true all confirmation prompts will receive their default reply." }, +{ "disassembly-format", OptionValue::eTypeFormatEntity, true, 0 , DEFAULT_DISASSEMBLY_FORMAT, NULL, "The default disassembly format string to use when disassembling instruction sequences." }, +{ "frame-format", OptionValue::eTypeFormatEntity, true, 0 , DEFAULT_FRAME_FORMAT, NULL, "The default frame format string to use when displaying stack frame information for threads." }, +{ "notify-void", OptionValue::eTypeBoolean , true, false, NULL, NULL, "Notify the user explicitly if an expression returns void (default: false)." }, +{ "prompt", OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", NULL, "The debugger command line prompt displayed for the user." }, +{ "script-lang", OptionValue::eTypeEnum , true, eScriptLanguagePython, NULL, g_language_enumerators, "The script language to be used for evaluating user-written scripts." }, +{ "stop-disassembly-count", OptionValue::eTypeSInt64 , true, 4 , NULL, NULL, "The number of disassembly lines to show when displaying a stopped context." }, +{ "stop-disassembly-display", OptionValue::eTypeEnum , true, Debugger::eStopDisassemblyTypeNoSource, NULL, g_show_disassembly_enum_values, "Control when to display disassembly when displaying a stopped context." }, +{ "stop-line-count-after", OptionValue::eTypeSInt64 , true, 3 , NULL, NULL, "The number of sources lines to display that come after the current source line when displaying a stopped context." }, +{ "stop-line-count-before", OptionValue::eTypeSInt64 , true, 3 , NULL, NULL, "The number of sources lines to display that come before the current source line when displaying a stopped context." }, +{ "term-width", OptionValue::eTypeSInt64 , true, 80 , NULL, NULL, "The maximum number of columns to use for displaying text." }, +{ "thread-format", OptionValue::eTypeFormatEntity, true, 0 , DEFAULT_THREAD_FORMAT, NULL, "The default thread format string to use when displaying thread information." }, +{ "use-external-editor", OptionValue::eTypeBoolean , true, false, NULL, NULL, "Whether to use an external editor or not." }, +{ "use-color", OptionValue::eTypeBoolean , true, true , NULL, NULL, "Whether to use Ansi color codes or not." }, +{ "auto-one-line-summaries", OptionValue::eTypeBoolean , true, true, NULL, NULL, "If true, LLDB will automatically display small structs in one-liner format (default: true)." }, +{ "escape-non-printables", OptionValue::eTypeBoolean , true, true, NULL, NULL, "If true, LLDB will automatically escape non-printable and escape characters when formatting strings." }, +{ NULL, OptionValue::eTypeInvalid , true, 0 , NULL, NULL, NULL } }; enum @@ -242,18 +242,18 @@ Debugger::GetAutoConfirm () const return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); } -const char * +const FormatEntity::Entry * Debugger::GetDisassemblyFormat() const { const uint32_t idx = ePropertyDisassemblyFormat; - return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); + return m_collection_sp->GetPropertyAtIndexAsFormatEntity(NULL, idx); } -const char * +const FormatEntity::Entry * Debugger::GetFrameFormat() const { const uint32_t idx = ePropertyFrameFormat; - return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); + return m_collection_sp->GetPropertyAtIndexAsFormatEntity(NULL, idx); } bool @@ -282,11 +282,11 @@ Debugger::SetPrompt(const char *p) GetCommandInterpreter().UpdatePrompt(new_prompt); } -const char * +const FormatEntity::Entry * Debugger::GetThreadFormat() const { const uint32_t idx = ePropertyThreadFormat; - return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); + return m_collection_sp->GetPropertyAtIndexAsFormatEntity(NULL, idx); } lldb::ScriptLanguage @@ -927,6 +927,18 @@ Debugger::GetTopIOHandlerControlSequence(char ch) return m_input_reader_stack.GetTopIOHandlerControlSequence (ch); } +const char * +Debugger::GetIOHandlerCommandPrefix() +{ + return m_input_reader_stack.GetTopIOHandlerCommandPrefix(); +} + +const char * +Debugger::GetIOHandlerHelpPrologue() +{ + return m_input_reader_stack.GetTopIOHandlerHelpPrologue(); +} + void Debugger::RunIOHandler (const IOHandlerSP& reader_sp) { @@ -1214,1691 +1226,25 @@ TestPromptFormats (StackFrame *frame) } #endif -static bool -ScanFormatDescriptor (const char* var_name_begin, - const char* var_name_end, - const char** var_name_final, - const char** percent_position, - Format* custom_format, - ValueObject::ValueObjectRepresentationStyle* val_obj_display) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - *percent_position = ::strchr(var_name_begin,'%'); - if (!*percent_position || *percent_position > var_name_end) - { - if (log) - log->Printf("[ScanFormatDescriptor] no format descriptor in string, skipping"); - *var_name_final = var_name_end; - } - else - { - *var_name_final = *percent_position; - std::string format_name(*var_name_final+1, var_name_end-*var_name_final-1); - if (log) - log->Printf("[ScanFormatDescriptor] parsing %s as a format descriptor", format_name.c_str()); - if ( !FormatManager::GetFormatFromCString(format_name.c_str(), - true, - *custom_format) ) - { - if (log) - log->Printf("[ScanFormatDescriptor] %s is an unknown format", format_name.c_str()); - - switch (format_name.front()) - { - case '@': // if this is an @ sign, print ObjC description - *val_obj_display = ValueObject::eValueObjectRepresentationStyleLanguageSpecific; - break; - case 'V': // if this is a V, print the value using the default format - *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; - break; - case 'L': // if this is an L, print the location of the value - *val_obj_display = ValueObject::eValueObjectRepresentationStyleLocation; - break; - case 'S': // if this is an S, print the summary after all - *val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; - break; - case '#': // if this is a '#', print the number of children - *val_obj_display = ValueObject::eValueObjectRepresentationStyleChildrenCount; - break; - case 'T': // if this is a 'T', print the type - *val_obj_display = ValueObject::eValueObjectRepresentationStyleType; - break; - case 'N': // if this is a 'N', print the name - *val_obj_display = ValueObject::eValueObjectRepresentationStyleName; - break; - case '>': // if this is a '>', print the name - *val_obj_display = ValueObject::eValueObjectRepresentationStyleExpressionPath; - break; - default: - if (log) - log->Printf("ScanFormatDescriptor] %s is an error, leaving the previous value alone", format_name.c_str()); - break; - } - } - // a good custom format tells us to print the value using it - else - { - if (log) - log->Printf("[ScanFormatDescriptor] will display value for this VO"); - *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; - } - } - if (log) - log->Printf("[ScanFormatDescriptor] final format description outcome: custom_format = %d, val_obj_display = %d", - *custom_format, - *val_obj_display); - return true; -} - -static bool -ScanBracketedRange (const char* var_name_begin, - const char* var_name_end, - const char* var_name_final, - const char** open_bracket_position, - const char** separator_position, - const char** close_bracket_position, - const char** var_name_final_if_array_range, - int64_t* index_lower, - int64_t* index_higher) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - *open_bracket_position = ::strchr(var_name_begin,'['); - if (*open_bracket_position && *open_bracket_position < var_name_final) - { - *separator_position = ::strchr(*open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield - *close_bracket_position = ::strchr(*open_bracket_position,']'); - // as usual, we assume that [] will come before % - //printf("trying to expand a []\n"); - *var_name_final_if_array_range = *open_bracket_position; - if (*close_bracket_position - *open_bracket_position == 1) - { - if (log) - log->Printf("[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); - *index_lower = 0; - } - else if (*separator_position == NULL || *separator_position > var_name_end) - { - char *end = NULL; - *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); - *index_higher = *index_lower; - if (log) - log->Printf("[ScanBracketedRange] [%" PRId64 "] detected, high index is same", *index_lower); - } - else if (*close_bracket_position && *close_bracket_position < var_name_end) - { - char *end = NULL; - *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); - *index_higher = ::strtoul (*separator_position+1, &end, 0); - if (log) - log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", *index_lower, *index_higher); - } - else - { - if (log) - log->Printf("[ScanBracketedRange] expression is erroneous, cannot extract indices out of it"); - return false; - } - if (*index_lower > *index_higher && *index_higher > 0) - { - if (log) - log->Printf("[ScanBracketedRange] swapping indices"); - int64_t temp = *index_lower; - *index_lower = *index_higher; - *index_higher = temp; - } - } - else if (log) - log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); - return true; -} - -template <typename T> -static bool RunScriptFormatKeyword(Stream &s, ScriptInterpreter *script_interpreter, T t, const std::string& script_name) -{ - if (script_interpreter) - { - Error script_error; - std::string script_output; - - if (script_interpreter->RunScriptFormatKeyword(script_name.c_str(), t, script_output, script_error) && script_error.Success()) - { - s.Printf("%s", script_output.c_str()); - return true; - } - else - { - s.Printf("<error: %s>",script_error.AsCString()); - } - } - return false; -} - -static ValueObjectSP -ExpandIndexedExpression (ValueObject* valobj, - size_t index, - StackFrame* frame, - bool deref_pointer) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - const char* ptr_deref_format = "[%d]"; - std::string ptr_deref_buffer(10,0); - ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); - if (log) - log->Printf("[ExpandIndexedExpression] name to deref: %s",ptr_deref_buffer.c_str()); - const char* first_unparsed; - ValueObject::GetValueForExpressionPathOptions options; - ValueObject::ExpressionPathEndResultType final_value_type; - ValueObject::ExpressionPathScanEndReason reason_to_stop; - ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); - ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.c_str(), - &first_unparsed, - &reason_to_stop, - &final_value_type, - options, - &what_next); - if (!item) - { - if (log) - log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d," - " final_value_type %d", - first_unparsed, reason_to_stop, final_value_type); - } - else - { - if (log) - log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d," - " final_value_type %d", - first_unparsed, reason_to_stop, final_value_type); - } - return item; -} - -static inline bool -IsToken(const char *var_name_begin, const char *var) -{ - return (::strncmp (var_name_begin, var, strlen(var)) == 0); -} - -static bool -IsTokenWithFormat(const char *var_name_begin, const char *var, std::string &format, const char *default_format, - const ExecutionContext *exe_ctx_ptr, const SymbolContext *sc_ptr) -{ - int var_len = strlen(var); - if (::strncmp (var_name_begin, var, var_len) == 0) - { - var_name_begin += var_len; - if (*var_name_begin == '}') - { - format = default_format; - return true; - } - else if (*var_name_begin == '%') - { - // Allow format specifiers: x|X|u with optional width specifiers. - // ${thread.id%x} ; hex - // ${thread.id%X} ; uppercase hex - // ${thread.id%u} ; unsigned decimal - // ${thread.id%8.8X} ; width.precision + specifier - // ${thread.id%tid} ; unsigned on FreeBSD/Linux, otherwise default_format (0x%4.4x for thread.id) - int dot_count = 0; - const char *specifier = NULL; - int width_precision_length = 0; - const char *width_precision = ++var_name_begin; - while (isdigit(*var_name_begin) || *var_name_begin == '.') - { - dot_count += (*var_name_begin == '.'); - if (dot_count > 1) - break; - var_name_begin++; - width_precision_length++; - } - - if (IsToken (var_name_begin, "tid}")) - { - Target *target = Target::GetTargetFromContexts (exe_ctx_ptr, sc_ptr); - if (target) - { - ArchSpec arch (target->GetArchitecture ()); - llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS; - if ((ostype == llvm::Triple::FreeBSD) || (ostype == llvm::Triple::Linux)) - specifier = PRIu64; - } - if (!specifier) - { - format = default_format; - return true; - } - } - else if (IsToken (var_name_begin, "x}")) - specifier = PRIx64; - else if (IsToken (var_name_begin, "X}")) - specifier = PRIX64; - else if (IsToken (var_name_begin, "u}")) - specifier = PRIu64; - - if (specifier) - { - format = "%"; - if (width_precision_length) - format += std::string(width_precision, width_precision_length); - format += specifier; - return true; - } - } - } - return false; -} - -// Find information for the "thread.info.*" specifiers in a format string -static bool -FormatThreadExtendedInfoRecurse -( - const char *var_name_begin, - StructuredData::ObjectSP thread_info_dictionary, - const SymbolContext *sc, - const ExecutionContext *exe_ctx, - Stream &s -) -{ - bool var_success = false; - std::string token_format; - - llvm::StringRef var_name(var_name_begin); - size_t percent_idx = var_name.find('%'); - size_t close_curly_idx = var_name.find('}'); - llvm::StringRef path = var_name; - llvm::StringRef formatter = var_name; - - // 'path' will be the dot separated list of objects to transverse up until we hit - // a close curly brace, a percent sign, or an end of string. - if (percent_idx != llvm::StringRef::npos || close_curly_idx != llvm::StringRef::npos) - { - if (percent_idx != llvm::StringRef::npos && close_curly_idx != llvm::StringRef::npos) - { - if (percent_idx < close_curly_idx) - { - path = var_name.slice(0, percent_idx); - formatter = var_name.substr (percent_idx); - } - else - { - path = var_name.slice(0, close_curly_idx); - formatter = var_name.substr (close_curly_idx); - } - } - else if (percent_idx != llvm::StringRef::npos) - { - path = var_name.slice(0, percent_idx); - formatter = var_name.substr (percent_idx); - } - else if (close_curly_idx != llvm::StringRef::npos) - { - path = var_name.slice(0, close_curly_idx); - formatter = var_name.substr (close_curly_idx); - } - } - - StructuredData::ObjectSP value = thread_info_dictionary->GetObjectForDotSeparatedPath (path); - - if (value.get()) - { - if (value->GetType() == StructuredData::Type::eTypeInteger) - { - if (IsTokenWithFormat (formatter.str().c_str(), "", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) - { - s.Printf(token_format.c_str(), value->GetAsInteger()->GetValue()); - var_success = true; - } - } - else if (value->GetType() == StructuredData::Type::eTypeFloat) - { - s.Printf ("%f", value->GetAsFloat()->GetValue()); - var_success = true; - } - else if (value->GetType() == StructuredData::Type::eTypeString) - { - s.Printf("%s", value->GetAsString()->GetValue().c_str()); - var_success = true; - } - else if (value->GetType() == StructuredData::Type::eTypeArray) - { - if (value->GetAsArray()->GetSize() > 0) - { - s.Printf ("%zu", value->GetAsArray()->GetSize()); - var_success = true; - } - } - else if (value->GetType() == StructuredData::Type::eTypeDictionary) - { - s.Printf ("%zu", value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize()); - var_success = true; - } - } - - return var_success; -} - - -static bool -FormatPromptRecurse -( - const char *format, - const SymbolContext *sc, - const ExecutionContext *exe_ctx, - const Address *addr, - Stream &s, - const char **end, - ValueObject* valobj, - bool function_changed, - bool initial_function -) -{ - ValueObject* realvalobj = NULL; // makes it super-easy to parse pointers - bool success = true; - const char *p; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - - for (p = format; *p != '\0'; ++p) - { - if (realvalobj) - { - valobj = realvalobj; - realvalobj = NULL; - } - size_t non_special_chars = ::strcspn (p, "${}\\"); - if (non_special_chars > 0) - { - if (success) - s.Write (p, non_special_chars); - p += non_special_chars; - } - - if (*p == '\0') - { - break; - } - else if (*p == '{') - { - // Start a new scope that must have everything it needs if it is to - // to make it into the final output stream "s". If you want to make - // a format that only prints out the function or symbol name if there - // is one in the symbol context you can use: - // "{function =${function.name}}" - // The first '{' starts a new scope that end with the matching '}' at - // the end of the string. The contents "function =${function.name}" - // will then be evaluated and only be output if there is a function - // or symbol with a valid name. - StreamString sub_strm; - - ++p; // Skip the '{' - - if (FormatPromptRecurse (p, sc, exe_ctx, addr, sub_strm, &p, valobj, function_changed, initial_function)) - { - // The stream had all it needed - s.Write(sub_strm.GetData(), sub_strm.GetSize()); - } - if (*p != '}') - { - success = false; - break; - } - } - else if (*p == '}') - { - // End of a enclosing scope - break; - } - else if (*p == '$') - { - // We have a prompt variable to print - ++p; - if (*p == '{') - { - ++p; - const char *var_name_begin = p; - const char *var_name_end = ::strchr (p, '}'); - - if (var_name_end && var_name_begin < var_name_end) - { - // if we have already failed to parse, skip this variable - if (success) - { - const char *cstr = NULL; - std::string token_format; - Address format_addr; - - // normally "addr" means print a raw address but - // "file-addr-or-load-addr" means print a module + file addr if there's no load addr - bool print_file_addr_or_load_addr = false; - bool addr_offset_concrete_func_only = false; - bool addr_offset_print_with_no_padding = false; - bool calculate_format_addr_function_offset = false; - // Set reg_kind and reg_num to invalid values - RegisterKind reg_kind = kNumRegisterKinds; - uint32_t reg_num = LLDB_INVALID_REGNUM; - FileSpec format_file_spec; - const RegisterInfo *reg_info = NULL; - RegisterContext *reg_ctx = NULL; - bool do_deref_pointer = false; - ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; - ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain; - - // Each variable must set success to true below... - bool var_success = false; - switch (var_name_begin[0]) - { - case '*': - case 'v': - case 's': - { - if (!valobj) - break; - - if (log) - log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin); - - // check for *var and *svar - if (*var_name_begin == '*') - { - do_deref_pointer = true; - var_name_begin++; - if (log) - log->Printf("[Debugger::FormatPrompt] found a deref, new string is: %s",var_name_begin); - } - - if (*var_name_begin == 's') - { - if (!valobj->IsSynthetic()) - valobj = valobj->GetSyntheticValue().get(); - if (!valobj) - break; - var_name_begin++; - if (log) - log->Printf("[Debugger::FormatPrompt] found a synthetic, new string is: %s",var_name_begin); - } - - // should be a 'v' by now - if (*var_name_begin != 'v') - break; - - if (log) - log->Printf("[Debugger::FormatPrompt] string I am working with: %s",var_name_begin); - - ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ? - ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); - ValueObject::GetValueForExpressionPathOptions options; - options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren(); - ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; - ValueObject* target = NULL; - Format custom_format = eFormatInvalid; - const char* var_name_final = NULL; - const char* var_name_final_if_array_range = NULL; - const char* close_bracket_position = NULL; - int64_t index_lower = -1; - int64_t index_higher = -1; - bool is_array_range = false; - const char* first_unparsed; - bool was_plain_var = false; - bool was_var_format = false; - bool was_var_indexed = false; - - if (!valobj) break; - // simplest case ${var}, just print valobj's value - if (IsToken (var_name_begin, "var}")) - { - was_plain_var = true; - target = valobj; - val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; - } - else if (IsToken (var_name_begin, "var.script:")) - { - var_name_begin += ::strlen("var.script:"); - std::string script_name(var_name_begin,var_name_end); - ScriptInterpreter* script_interpreter = valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - if (RunScriptFormatKeyword (s, script_interpreter, valobj, script_name)) - var_success = true; - break; - } - else if (IsToken (var_name_begin,"var%")) - { - was_var_format = true; - // this is a variable with some custom format applied to it - const char* percent_position; - target = valobj; - val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; - ScanFormatDescriptor (var_name_begin, - var_name_end, - &var_name_final, - &percent_position, - &custom_format, - &val_obj_display); - } - // this is ${var.something} or multiple .something nested - else if (IsToken (var_name_begin, "var")) - { - if (IsToken (var_name_begin, "var[")) - was_var_indexed = true; - const char* percent_position; - ScanFormatDescriptor (var_name_begin, - var_name_end, - &var_name_final, - &percent_position, - &custom_format, - &val_obj_display); - - const char* open_bracket_position; - const char* separator_position; - ScanBracketedRange (var_name_begin, - var_name_end, - var_name_final, - &open_bracket_position, - &separator_position, - &close_bracket_position, - &var_name_final_if_array_range, - &index_lower, - &index_higher); - - Error error; - - std::string expr_path(var_name_final-var_name_begin-1,0); - memcpy(&expr_path[0], var_name_begin+3,var_name_final-var_name_begin-3); - - if (log) - log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",expr_path.c_str()); - - target = valobj->GetValueForExpressionPath(expr_path.c_str(), - &first_unparsed, - &reason_to_stop, - &final_value_type, - options, - &what_next).get(); - - if (!target) - { - if (log) - log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d," - " final_value_type %d", - first_unparsed, reason_to_stop, final_value_type); - break; - } - else - { - if (log) - log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d," - " final_value_type %d", - first_unparsed, reason_to_stop, final_value_type); - target = target->GetQualifiedRepresentationIfAvailable(target->GetDynamicValueType(), true).get(); - } - } - else - break; - - is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange || - final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange); - - do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference); - - if (do_deref_pointer && !is_array_range) - { - // I have not deref-ed yet, let's do it - // this happens when we are not going through GetValueForVariableExpressionPath - // to get to the target ValueObject - Error error; - target = target->Dereference(error).get(); - if (error.Fail()) - { - if (log) - log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", error.AsCString("unknown")); \ - break; - } - do_deref_pointer = false; - } - - if (!target) - { - if (log) - log->Printf("[Debugger::FormatPrompt] could not calculate target for prompt expression"); - break; - } - - // we do not want to use the summary for a bitfield of type T:n - // if we were originally dealing with just a T - that would get - // us into an endless recursion - if (target->IsBitfield() && was_var_indexed) - { - // TODO: check for a (T:n)-specific summary - we should still obey that - StreamString bitfield_name; - bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize()); - lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false)); - if (!DataVisualization::GetSummaryForType(type_sp)) - val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; - } - - // TODO use flags for these - const uint32_t type_info_flags = target->GetClangType().GetTypeInfo(NULL); - bool is_array = (type_info_flags & eTypeIsArray) != 0; - bool is_pointer = (type_info_flags & eTypeIsPointer) != 0; - bool is_aggregate = target->GetClangType().IsAggregateType(); - - if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions - { - StreamString str_temp; - if (log) - log->Printf("[Debugger::FormatPrompt] I am into array || pointer && !range"); - - if (target->HasSpecialPrintableRepresentation(val_obj_display, custom_format)) - { - // try to use the special cases - var_success = target->DumpPrintableRepresentation(str_temp, - val_obj_display, - custom_format); - if (log) - log->Printf("[Debugger::FormatPrompt] special cases did%s match", var_success ? "" : "n't"); - - // should not happen - if (var_success) - s << str_temp.GetData(); - var_success = true; - break; - } - else - { - if (was_plain_var) // if ${var} - { - s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); - } - else if (is_pointer) // if pointer, value is the address stored - { - target->DumpPrintableRepresentation (s, - val_obj_display, - custom_format, - ValueObject::ePrintableRepresentationSpecialCasesDisable); - } - var_success = true; - break; - } - } - - // if directly trying to print ${var}, and this is an aggregate, display a nice - // type @ location message - if (is_aggregate && was_plain_var) - { - s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); - var_success = true; - break; - } - - // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it - if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue))) - { - s << "<invalid use of aggregate type>"; - var_success = true; - break; - } - - if (!is_array_range) - { - if (log) - log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output"); - var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format); - } - else - { - if (log) - log->Printf("[Debugger::FormatPrompt] checking if I can handle as array"); - if (!is_array && !is_pointer) - break; - if (log) - log->Printf("[Debugger::FormatPrompt] handle as array"); - const char* special_directions = NULL; - StreamString special_directions_writer; - if (close_bracket_position && (var_name_end-close_bracket_position > 1)) - { - ConstString additional_data; - additional_data.SetCStringWithLength(close_bracket_position+1, var_name_end-close_bracket_position-1); - special_directions_writer.Printf("${%svar%s}", - do_deref_pointer ? "*" : "", - additional_data.GetCString()); - special_directions = special_directions_writer.GetData(); - } - - // let us display items index_lower thru index_higher of this array - s.PutChar('['); - var_success = true; - - if (index_higher < 0) - index_higher = valobj->GetNumChildren() - 1; - - uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); - - for (;index_lower<=index_higher;index_lower++) - { - ValueObject* item = ExpandIndexedExpression (target, - index_lower, - exe_ctx->GetFramePtr(), - false).get(); - - if (!item) - { - if (log) - log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at index %" PRId64, index_lower); - } - else - { - if (log) - log->Printf("[Debugger::FormatPrompt] special_directions for child item: %s",special_directions); - } - - if (!special_directions) - var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); - else - var_success &= FormatPromptRecurse(special_directions, sc, exe_ctx, addr, s, NULL, item, function_changed, initial_function); - - if (--max_num_children == 0) - { - s.PutCString(", ..."); - break; - } - - if (index_lower < index_higher) - s.PutChar(','); - } - s.PutChar(']'); - } - } - break; - case 'a': - if (IsToken (var_name_begin, "addr-file-or-load}")) - { - print_file_addr_or_load_addr = true; - } - if (IsToken (var_name_begin, "addr}") - || IsToken (var_name_begin, "addr-file-or-load}")) - { - if (addr && addr->IsValid()) - { - var_success = true; - format_addr = *addr; - } - } - break; - - case 'p': - if (IsToken (var_name_begin, "process.")) - { - if (exe_ctx) - { - Process *process = exe_ctx->GetProcessPtr(); - if (process) - { - var_name_begin += ::strlen ("process."); - if (IsTokenWithFormat (var_name_begin, "id", token_format, "%" PRIu64, exe_ctx, sc)) - { - s.Printf(token_format.c_str(), process->GetID()); - var_success = true; - } - else if ((IsToken (var_name_begin, "name}")) || - (IsToken (var_name_begin, "file.basename}")) || - (IsToken (var_name_begin, "file.fullpath}"))) - { - Module *exe_module = process->GetTarget().GetExecutableModulePointer(); - if (exe_module) - { - if (var_name_begin[0] == 'n' || var_name_begin[5] == 'f') - { - format_file_spec.GetFilename() = exe_module->GetFileSpec().GetFilename(); - var_success = (bool)format_file_spec; - } - else - { - format_file_spec = exe_module->GetFileSpec(); - var_success = (bool)format_file_spec; - } - } - } - else if (IsToken (var_name_begin, "script:")) - { - var_name_begin += ::strlen("script:"); - std::string script_name(var_name_begin,var_name_end); - ScriptInterpreter* script_interpreter = process->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - if (RunScriptFormatKeyword (s, script_interpreter, process, script_name)) - var_success = true; - } - } - } - } - break; - - case 't': - if (IsToken (var_name_begin, "thread.")) - { - if (exe_ctx) - { - Thread *thread = exe_ctx->GetThreadPtr(); - if (thread) - { - var_name_begin += ::strlen ("thread."); - if (IsTokenWithFormat (var_name_begin, "id", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) - { - s.Printf(token_format.c_str(), thread->GetID()); - var_success = true; - } - else if (IsTokenWithFormat (var_name_begin, "protocol_id", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) - { - s.Printf(token_format.c_str(), thread->GetProtocolID()); - var_success = true; - } - else if (IsTokenWithFormat (var_name_begin, "index", token_format, "%" PRIu64, exe_ctx, sc)) - { - s.Printf(token_format.c_str(), (uint64_t)thread->GetIndexID()); - var_success = true; - } - else if (IsToken (var_name_begin, "name}")) - { - cstr = thread->GetName(); - var_success = cstr && cstr[0]; - if (var_success) - s.PutCString(cstr); - } - else if (IsToken (var_name_begin, "queue}")) - { - cstr = thread->GetQueueName(); - var_success = cstr && cstr[0]; - if (var_success) - s.PutCString(cstr); - } - else if (IsToken (var_name_begin, "stop-reason}")) - { - StopInfoSP stop_info_sp = thread->GetStopInfo (); - if (stop_info_sp && stop_info_sp->IsValid()) - { - cstr = stop_info_sp->GetDescription(); - if (cstr && cstr[0]) - { - s.PutCString(cstr); - var_success = true; - } - } - } - else if (IsToken (var_name_begin, "return-value}")) - { - StopInfoSP stop_info_sp = thread->GetStopInfo (); - if (stop_info_sp && stop_info_sp->IsValid()) - { - ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp); - if (return_valobj_sp) - { - return_valobj_sp->Dump(s); - var_success = true; - } - } - } - else if (IsToken (var_name_begin, "completed-expression}")) - { - StopInfoSP stop_info_sp = thread->GetStopInfo (); - if (stop_info_sp && stop_info_sp->IsValid()) - { - ClangExpressionVariableSP expression_var_sp = StopInfo::GetExpressionVariable (stop_info_sp); - if (expression_var_sp && expression_var_sp->GetValueObject()) - { - expression_var_sp->GetValueObject()->Dump(s); - var_success = true; - } - } - } - else if (IsToken (var_name_begin, "script:")) - { - var_name_begin += ::strlen("script:"); - std::string script_name(var_name_begin,var_name_end); - ScriptInterpreter* script_interpreter = thread->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - if (RunScriptFormatKeyword (s, script_interpreter, thread, script_name)) - var_success = true; - } - else if (IsToken (var_name_begin, "info.")) - { - var_name_begin += ::strlen("info."); - StructuredData::ObjectSP object_sp = thread->GetExtendedInfo(); - if (object_sp && object_sp->GetType() == StructuredData::Type::eTypeDictionary) - { - var_success = FormatThreadExtendedInfoRecurse (var_name_begin, object_sp, sc, exe_ctx, s); - } - } - } - } - } - else if (IsToken (var_name_begin, "target.")) - { - // TODO: hookup properties -// if (!target_properties_sp) -// { -// Target *target = Target::GetTargetFromContexts (exe_ctx, sc); -// if (target) -// target_properties_sp = target->GetProperties(); -// } -// -// if (target_properties_sp) -// { -// var_name_begin += ::strlen ("target."); -// const char *end_property = strchr(var_name_begin, '}'); -// if (end_property) -// { -// ConstString property_name(var_name_begin, end_property - var_name_begin); -// std::string property_value (target_properties_sp->GetPropertyValue(property_name)); -// if (!property_value.empty()) -// { -// s.PutCString (property_value.c_str()); -// var_success = true; -// } -// } -// } - Target *target = Target::GetTargetFromContexts (exe_ctx, sc); - if (target) - { - var_name_begin += ::strlen ("target."); - if (IsToken (var_name_begin, "arch}")) - { - ArchSpec arch (target->GetArchitecture ()); - if (arch.IsValid()) - { - s.PutCString (arch.GetArchitectureName()); - var_success = true; - } - } - else if (IsToken (var_name_begin, "script:")) - { - var_name_begin += ::strlen("script:"); - std::string script_name(var_name_begin,var_name_end); - ScriptInterpreter* script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - if (RunScriptFormatKeyword (s, script_interpreter, target, script_name)) - var_success = true; - } - } - } - break; - - case 'm': - if (IsToken (var_name_begin, "module.")) - { - if (sc && sc->module_sp.get()) - { - Module *module = sc->module_sp.get(); - var_name_begin += ::strlen ("module."); - - if (IsToken (var_name_begin, "file.")) - { - if (module->GetFileSpec()) - { - var_name_begin += ::strlen ("file."); - - if (IsToken (var_name_begin, "basename}")) - { - format_file_spec.GetFilename() = module->GetFileSpec().GetFilename(); - var_success = (bool)format_file_spec; - } - else if (IsToken (var_name_begin, "fullpath}")) - { - format_file_spec = module->GetFileSpec(); - var_success = (bool)format_file_spec; - } - } - } - } - } - break; - - - case 'f': - if (IsToken (var_name_begin, "file.")) - { - if (sc && sc->comp_unit != NULL) - { - var_name_begin += ::strlen ("file."); - - if (IsToken (var_name_begin, "basename}")) - { - format_file_spec.GetFilename() = sc->comp_unit->GetFilename(); - var_success = (bool)format_file_spec; - } - else if (IsToken (var_name_begin, "fullpath}")) - { - format_file_spec = *sc->comp_unit; - var_success = (bool)format_file_spec; - } - } - } - else if (IsToken (var_name_begin, "frame.")) - { - if (exe_ctx) - { - StackFrame *frame = exe_ctx->GetFramePtr(); - if (frame) - { - var_name_begin += ::strlen ("frame."); - if (IsToken (var_name_begin, "index}")) - { - s.Printf("%u", frame->GetFrameIndex()); - var_success = true; - } - else if (IsToken (var_name_begin, "pc}")) - { - reg_kind = eRegisterKindGeneric; - reg_num = LLDB_REGNUM_GENERIC_PC; - var_success = true; - } - else if (IsToken (var_name_begin, "sp}")) - { - reg_kind = eRegisterKindGeneric; - reg_num = LLDB_REGNUM_GENERIC_SP; - var_success = true; - } - else if (IsToken (var_name_begin, "fp}")) - { - reg_kind = eRegisterKindGeneric; - reg_num = LLDB_REGNUM_GENERIC_FP; - var_success = true; - } - else if (IsToken (var_name_begin, "flags}")) - { - reg_kind = eRegisterKindGeneric; - reg_num = LLDB_REGNUM_GENERIC_FLAGS; - var_success = true; - } - else if (IsToken (var_name_begin, "reg.")) - { - reg_ctx = frame->GetRegisterContext().get(); - if (reg_ctx) - { - var_name_begin += ::strlen ("reg."); - if (var_name_begin < var_name_end) - { - std::string reg_name (var_name_begin, var_name_end); - reg_info = reg_ctx->GetRegisterInfoByName (reg_name.c_str()); - if (reg_info) - var_success = true; - } - } - } - else if (IsToken (var_name_begin, "script:")) - { - var_name_begin += ::strlen("script:"); - std::string script_name(var_name_begin,var_name_end); - ScriptInterpreter* script_interpreter = frame->GetThread()->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - if (RunScriptFormatKeyword (s, script_interpreter, frame, script_name)) - var_success = true; - } - } - } - } - else if (IsToken (var_name_begin, "function.")) - { - if (sc && (sc->function != NULL || sc->symbol != NULL)) - { - var_name_begin += ::strlen ("function."); - if (IsToken (var_name_begin, "id}")) - { - if (sc->function) - s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID()); - else - s.Printf("symbol[%u]", sc->symbol->GetID()); - - var_success = true; - } - if (IsToken (var_name_begin, "changed}") && function_changed) - { - var_success = true; - } - if (IsToken (var_name_begin, "initial-function}") && initial_function) - { - var_success = true; - } - else if (IsToken (var_name_begin, "name}")) - { - if (sc->function) - cstr = sc->function->GetName().AsCString (NULL); - else if (sc->symbol) - cstr = sc->symbol->GetName().AsCString (NULL); - if (cstr) - { - s.PutCString(cstr); - - if (sc->block) - { - Block *inline_block = sc->block->GetContainingInlinedBlock (); - if (inline_block) - { - const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo(); - if (inline_info) - { - s.PutCString(" [inlined] "); - inline_info->GetName().Dump(&s); - } - } - } - var_success = true; - } - } - else if (IsToken (var_name_begin, "name-without-args}")) - { - ConstString name; - if (sc->function) - name = sc->function->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments); - else if (sc->symbol) - name = sc->symbol->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments); - if (name) - { - s.PutCString(name.GetCString()); - var_success = true; - } - } - else if (IsToken (var_name_begin, "name-with-args}")) - { - // Print the function name with arguments in it - - if (sc->function) - { - var_success = true; - ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL; - cstr = sc->function->GetName().AsCString (NULL); - if (cstr) - { - const InlineFunctionInfo *inline_info = NULL; - VariableListSP variable_list_sp; - bool get_function_vars = true; - if (sc->block) - { - Block *inline_block = sc->block->GetContainingInlinedBlock (); - - if (inline_block) - { - get_function_vars = false; - inline_info = sc->block->GetInlinedFunctionInfo(); - if (inline_info) - variable_list_sp = inline_block->GetBlockVariableList (true); - } - } - - if (get_function_vars) - { - variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true); - } - - if (inline_info) - { - s.PutCString (cstr); - s.PutCString (" [inlined] "); - cstr = inline_info->GetName().GetCString(); - } - - VariableList args; - if (variable_list_sp) - variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args); - if (args.GetSize() > 0) - { - const char *open_paren = strchr (cstr, '('); - const char *close_paren = nullptr; - const char *generic = strchr(cstr, '<'); - // if before the arguments list begins there is a template sign - // then scan to the end of the generic args before you try to find - // the arguments list - if (generic && open_paren && generic < open_paren) - { - int generic_depth = 1; - ++generic; - for (; - *generic && generic_depth > 0; - generic++) - { - if (*generic == '<') - generic_depth++; - if (*generic == '>') - generic_depth--; - } - if (*generic) - open_paren = strchr(generic, '('); - else - open_paren = nullptr; - } - if (open_paren) - { - if (IsToken (open_paren, "(anonymous namespace)")) - { - open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '('); - if (open_paren) - close_paren = strchr (open_paren, ')'); - } - else - close_paren = strchr (open_paren, ')'); - } - - if (open_paren) - s.Write(cstr, open_paren - cstr + 1); - else - { - s.PutCString (cstr); - s.PutChar ('('); - } - const size_t num_args = args.GetSize(); - for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) - { - std::string buffer; - - VariableSP var_sp (args.GetVariableAtIndex (arg_idx)); - ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp)); - const char *var_representation = nullptr; - const char *var_name = var_value_sp->GetName().GetCString(); - if (var_value_sp->GetClangType().IsAggregateType() && - DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get())) - { - static StringSummaryFormat format(TypeSummaryImpl::Flags() - .SetHideItemNames(false) - .SetShowMembersOneLiner(true), - ""); - format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions()); - var_representation = buffer.c_str(); - } - else - var_representation = var_value_sp->GetValueAsCString(); - if (arg_idx > 0) - s.PutCString (", "); - if (var_value_sp->GetError().Success()) - { - if (var_representation) - s.Printf ("%s=%s", var_name, var_representation); - else - s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString()); - } - else - s.Printf ("%s=<unavailable>", var_name); - } - - if (close_paren) - s.PutCString (close_paren); - else - s.PutChar(')'); - - } - else - { - s.PutCString(cstr); - } - } - } - else if (sc->symbol) - { - cstr = sc->symbol->GetName().AsCString (NULL); - if (cstr) - { - s.PutCString(cstr); - var_success = true; - } - } - } - else if (IsToken (var_name_begin, "addr-offset}") - || IsToken (var_name_begin, "concrete-only-addr-offset-no-padding}")) - { - if (IsToken (var_name_begin, "concrete-only-addr-offset-no-padding}")) - { - addr_offset_print_with_no_padding = true; - addr_offset_concrete_func_only = true; - } - var_success = addr != NULL; - if (var_success) - { - format_addr = *addr; - calculate_format_addr_function_offset = true; - } - } - else if (IsToken (var_name_begin, "line-offset}")) - { - var_success = sc->line_entry.range.GetBaseAddress().IsValid(); - if (var_success) - { - format_addr = sc->line_entry.range.GetBaseAddress(); - calculate_format_addr_function_offset = true; - } - } - else if (IsToken (var_name_begin, "pc-offset}")) - { - StackFrame *frame = exe_ctx->GetFramePtr(); - var_success = frame != NULL; - if (var_success) - { - format_addr = frame->GetFrameCodeAddress(); - calculate_format_addr_function_offset = true; - } - } - } - } - break; - - case 'l': - if (IsToken (var_name_begin, "line.")) - { - if (sc && sc->line_entry.IsValid()) - { - var_name_begin += ::strlen ("line."); - if (IsToken (var_name_begin, "file.")) - { - var_name_begin += ::strlen ("file."); - - if (IsToken (var_name_begin, "basename}")) - { - format_file_spec.GetFilename() = sc->line_entry.file.GetFilename(); - var_success = (bool)format_file_spec; - } - else if (IsToken (var_name_begin, "fullpath}")) - { - format_file_spec = sc->line_entry.file; - var_success = (bool)format_file_spec; - } - } - else if (IsTokenWithFormat (var_name_begin, "number", token_format, "%" PRIu64, exe_ctx, sc)) - { - var_success = true; - s.Printf(token_format.c_str(), (uint64_t)sc->line_entry.line); - } - else if ((IsToken (var_name_begin, "start-addr}")) || - (IsToken (var_name_begin, "end-addr}"))) - { - var_success = sc && sc->line_entry.range.GetBaseAddress().IsValid(); - if (var_success) - { - format_addr = sc->line_entry.range.GetBaseAddress(); - if (var_name_begin[0] == 'e') - format_addr.Slide (sc->line_entry.range.GetByteSize()); - } - } - } - } - break; - case 'c': - if (IsToken (var_name_begin, "current-pc-arrow")) - { - if (addr && exe_ctx && exe_ctx->GetFramePtr()) - { - RegisterContextSP reg_ctx = exe_ctx->GetFramePtr()->GetRegisterContextSP(); - if (reg_ctx.get()) - { - addr_t pc_loadaddr = reg_ctx->GetPC(); - if (pc_loadaddr != LLDB_INVALID_ADDRESS) - { - Address pc; - pc.SetLoadAddress (pc_loadaddr, exe_ctx->GetTargetPtr()); - if (pc == *addr) - { - s.Printf ("-> "); - var_success = true; - } - } - } - if (var_success == false) - { - s.Printf(" "); - var_success = true; - } - } - var_success = true; - } - break; - } - - if (var_success) - { - // If format addr is valid, then we need to print an address - if (reg_num != LLDB_INVALID_REGNUM) - { - StackFrame *frame = exe_ctx->GetFramePtr(); - // We have a register value to display... - if (reg_num == LLDB_REGNUM_GENERIC_PC && reg_kind == eRegisterKindGeneric) - { - format_addr = frame->GetFrameCodeAddress(); - } - else - { - if (reg_ctx == NULL) - reg_ctx = frame->GetRegisterContext().get(); - - if (reg_ctx) - { - if (reg_kind != kNumRegisterKinds) - reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); - reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num); - var_success = reg_info != NULL; - } - } - } - - if (reg_info != NULL) - { - RegisterValue reg_value; - var_success = reg_ctx->ReadRegister (reg_info, reg_value); - if (var_success) - { - reg_value.Dump(&s, reg_info, false, false, eFormatDefault); - } - } - - if (format_file_spec) - { - s << format_file_spec; - } - - // If format addr is valid, then we need to print an address - if (format_addr.IsValid()) - { - var_success = false; - - if (calculate_format_addr_function_offset) - { - Address func_addr; - - if (sc) - { - if (sc->function) - { - func_addr = sc->function->GetAddressRange().GetBaseAddress(); - if (sc->block && addr_offset_concrete_func_only == false) - { - // Check to make sure we aren't in an inline - // function. If we are, use the inline block - // range that contains "format_addr" since - // blocks can be discontiguous. - Block *inline_block = sc->block->GetContainingInlinedBlock (); - AddressRange inline_range; - if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range)) - func_addr = inline_range.GetBaseAddress(); - } - } - else if (sc->symbol && sc->symbol->ValueIsAddress()) - func_addr = sc->symbol->GetAddress(); - } - - if (func_addr.IsValid()) - { - const char *addr_offset_padding = " "; - if (addr_offset_print_with_no_padding) - { - addr_offset_padding = ""; - } - if (func_addr.GetSection() == format_addr.GetSection()) - { - addr_t func_file_addr = func_addr.GetFileAddress(); - addr_t addr_file_addr = format_addr.GetFileAddress(); - if (addr_file_addr > func_file_addr) - s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_file_addr - func_file_addr); - else if (addr_file_addr < func_file_addr) - s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_file_addr - addr_file_addr); - var_success = true; - } - else - { - Target *target = Target::GetTargetFromContexts (exe_ctx, sc); - if (target) - { - addr_t func_load_addr = func_addr.GetLoadAddress (target); - addr_t addr_load_addr = format_addr.GetLoadAddress (target); - if (addr_load_addr > func_load_addr) - s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_load_addr - func_load_addr); - else if (addr_load_addr < func_load_addr) - s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_load_addr - addr_load_addr); - var_success = true; - } - } - } - } - else - { - Target *target = Target::GetTargetFromContexts (exe_ctx, sc); - addr_t vaddr = LLDB_INVALID_ADDRESS; - if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) - vaddr = format_addr.GetLoadAddress (target); - if (vaddr == LLDB_INVALID_ADDRESS) - vaddr = format_addr.GetFileAddress (); - - if (vaddr != LLDB_INVALID_ADDRESS) - { - int addr_width = 0; - if (exe_ctx && target) - { - addr_width = target->GetArchitecture().GetAddressByteSize() * 2; - } - if (addr_width == 0) - addr_width = 16; - if (print_file_addr_or_load_addr) - { - format_addr.Dump (&s, exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0); - } - else - { - s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); - } - var_success = true; - } - } - } - } - - if (var_success == false) - success = false; - } - p = var_name_end; - } - else - break; - } - else - { - // We got a dollar sign with no '{' after it, it must just be a dollar sign - s.PutChar(*p); - } - } - else if (*p == '\\') - { - ++p; // skip the slash - switch (*p) - { - case 'a': s.PutChar ('\a'); break; - case 'b': s.PutChar ('\b'); break; - case 'f': s.PutChar ('\f'); break; - case 'n': s.PutChar ('\n'); break; - case 'r': s.PutChar ('\r'); break; - case 't': s.PutChar ('\t'); break; - case 'v': s.PutChar ('\v'); break; - case '\'': s.PutChar ('\''); break; - case '\\': s.PutChar ('\\'); break; - case '0': - // 1 to 3 octal chars - { - // Make a string that can hold onto the initial zero char, - // up to 3 octal digits, and a terminating NULL. - char oct_str[5] = { 0, 0, 0, 0, 0 }; - - int i; - for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i) - oct_str[i] = p[i]; - - // We don't want to consume the last octal character since - // the main for loop will do this for us, so we advance p by - // one less than i (even if i is zero) - p += i - 1; - unsigned long octal_value = ::strtoul (oct_str, NULL, 8); - if (octal_value <= UINT8_MAX) - { - s.PutChar((char)octal_value); - } - } - break; - - case 'x': - // hex number in the format - if (isxdigit(p[1])) - { - ++p; // Skip the 'x' - - // Make a string that can hold onto two hex chars plus a - // NULL terminator - char hex_str[3] = { 0,0,0 }; - hex_str[0] = *p; - if (isxdigit(p[1])) - { - ++p; // Skip the first of the two hex chars - hex_str[1] = *p; - } - - unsigned long hex_value = strtoul (hex_str, NULL, 16); - if (hex_value <= UINT8_MAX) - s.PutChar ((char)hex_value); - } - else - { - s.PutChar('x'); - } - break; - - default: - // Just desensitize any other character by just printing what - // came after the '\' - s << *p; - break; - - } - - } - } - if (end) - *end = p; - return success; -} - bool -Debugger::FormatPrompt -( - const char *format, - const SymbolContext *sc, - const ExecutionContext *exe_ctx, - const Address *addr, - Stream &s, - ValueObject* valobj -) -{ - bool use_color = exe_ctx ? exe_ctx->GetTargetRef().GetDebugger().GetUseColor() : true; - std::string format_str = lldb_utility::ansi::FormatAnsiTerminalCodes (format, use_color); - if (format_str.length()) - format = format_str.c_str(); - return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, valobj, false, false); -} - -bool -Debugger::FormatDisassemblerAddress (const char *format, +Debugger::FormatDisassemblerAddress (const FormatEntity::Entry *format, const SymbolContext *sc, const SymbolContext *prev_sc, const ExecutionContext *exe_ctx, const Address *addr, Stream &s) { - if (format == NULL && exe_ctx != NULL && exe_ctx->HasTargetScope()) + FormatEntity::Entry format_entry; + + if (format == NULL) { - format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); + if (exe_ctx != NULL && exe_ctx->HasTargetScope()) + format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); + if (format == NULL) + { + FormatEntity::Parse("${addr}: ", format_entry); + format = &format_entry; + } } bool function_changed = false; bool initial_function = false; @@ -2930,7 +1276,7 @@ Debugger::FormatDisassemblerAddress (const char *format, { initial_function = true; } - return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, NULL, function_changed, initial_function); + return FormatEntity::Format(*format, s, sc, exe_ctx, addr, NULL, function_changed, initial_function); } |