Index: lldb/trunk/test/tools/lldb-mi/data/TestMiData.py =================================================================== --- lldb/trunk/test/tools/lldb-mi/data/TestMiData.py +++ lldb/trunk/test/tools/lldb-mi/data/TestMiData.py @@ -33,8 +33,8 @@ # Get an address for disassembling: use main self.runCmd("-data-evaluate-expression main") - self.expect("\^done,value=\"0x[0-9a-f]+\"") - addr = int(self.child.after.split("\"")[1], 16) + self.expect("\^done,value=\"0x[0-9a-f]+ \(a.out`main at main.cpp:[0-9]+\)\"") + addr = int(self.child.after.split("\"")[1].split(" ")[0], 16) # Test -data-disassemble: try to disassemble some address self.runCmd("-data-disassemble -s %#x -e %#x -- 0" % (addr, addr + 0x10)) @@ -49,8 +49,8 @@ # Get an address for disassembling: use hello_world self.runCmd("-data-evaluate-expression hello_world") - self.expect("\^done,value=\"0x[0-9a-f]+\"") - addr = int(self.child.after.split("\"")[1], 16) + self.expect("\^done,value=\"0x[0-9a-f]+ \(a.out`hello_world\(\) at main.cpp:[0-9]+\)\"") + addr = int(self.child.after.split("\"")[1].split(" ")[0], 16) # Test -data-disassemble: try to disassemble some address self.runCmd("-data-disassemble -s %#x -e %#x -- 0" % (addr, addr + 0x10)) @@ -288,8 +288,8 @@ # Get the address of main and its line self.runCmd("-data-evaluate-expression main") - self.expect("\^done,value=\"0x[0-9a-f]+\"") - addr = int(self.child.after.split("\"")[1], 16) + self.expect("\^done,value=\"0x[0-9a-f]+ \(a.out`main at main.cpp:[0-9]+\)\"") + addr = int(self.child.after.split("\"")[1].split(" ")[0], 16) line = line_number('main.cpp', '// FUNC_main') # Test that -data-info-line works for address Index: lldb/trunk/test/tools/lldb-mi/symbol/TestMiSymbol.py =================================================================== --- lldb/trunk/test/tools/lldb-mi/symbol/TestMiSymbol.py +++ lldb/trunk/test/tools/lldb-mi/symbol/TestMiSymbol.py @@ -32,8 +32,8 @@ # Get address of main and its line self.runCmd("-data-evaluate-expression main") - self.expect("\^done,value=\"0x[0-9a-f]+\"") - addr = int(self.child.after.split("\"")[1], 16) + self.expect("\^done,value=\"0x[0-9a-f]+ \(a.out`main at main.cpp:[0-9]+\)\"") + addr = int(self.child.after.split("\"")[1].split(" ")[0], 16) line = line_number('main.cpp', '// FUNC_main') # Test that -symbol-list-lines works on valid data Index: lldb/trunk/tools/lldb-mi/MICmnLLDBDebugger.h =================================================================== --- lldb/trunk/tools/lldb-mi/MICmnLLDBDebugger.h +++ lldb/trunk/tools/lldb-mi/MICmnLLDBDebugger.h @@ -93,7 +93,8 @@ bool ClientSaveMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, const MIuint vEventMask); bool ClientRemoveTheirMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass); bool ClientGetTheirMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, MIuint &vwEventMask); - + bool LoadMIFormatters(lldb::SBTypeCategory miCategory); + bool RegisterMISummaryProviders(); // Overridden: private: // From CMICmnBase Index: lldb/trunk/tools/lldb-mi/MICmnLLDBDebugger.cpp =================================================================== --- lldb/trunk/tools/lldb-mi/MICmnLLDBDebugger.cpp +++ lldb/trunk/tools/lldb-mi/MICmnLLDBDebugger.cpp @@ -12,6 +12,11 @@ #include "lldb/API/SBThread.h" #include "lldb/API/SBProcess.h" #include "lldb/API/SBCommandInterpreter.h" +#include "lldb/API/SBTypeSummary.h" +#include "lldb/API/SBTypeCategory.h" +#include "lldb/API/SBTypeNameSpecifier.h" +#include "lldb/API/SBStream.h" +#include "lldb/API/SBType.h" // In-house headers: #include "MICmnLLDBDebugger.h" @@ -24,6 +29,40 @@ #include "MIUtilSingletonHelper.h" //++ ------------------------------------------------------------------------------------ +// MI private summary providers +static inline bool +MI_char_summary_provider(lldb::SBValue value, lldb::SBTypeSummaryOptions options, lldb::SBStream &stream) +{ + bool is_signed; + if (!value.IsValid()) + return false; + + lldb::SBType value_type = value.GetType(); + if(!value_type.IsValid()) + return false; + + lldb::BasicType type_code = value_type.GetBasicType(); + if (type_code == lldb::eBasicTypeSignedChar) + stream.Printf("%d %s", (int)value.GetValueAsSigned(), value.GetValue()); + else if (type_code == lldb::eBasicTypeUnsignedChar) + stream.Printf("%u %s", (unsigned)value.GetValueAsUnsigned(), value.GetValue()); + else + return false; + + return true; +} + +//++ ------------------------------------------------------------------------------------ +// MI summary helper routines +static inline bool +MI_add_summary(lldb::SBTypeCategory category, const char *typeName, lldb::SBTypeSummary::FormatCallback cb, + uint32_t options, bool regex = false) +{ + lldb::SBTypeSummary summary = lldb::SBTypeSummary::CreateWithCallback(cb, options); + return summary.IsValid() ? category.AddTypeSummary(lldb::SBTypeNameSpecifier(typeName, regex), summary) : false; +} + +//++ ------------------------------------------------------------------------------------ // Details: CMICmnLLDBDebugger constructor. // Type: Method. // Args: None. @@ -98,7 +137,7 @@ errMsg += GetErrorDescription().c_str(); } bOk = bOk && InitStdStreams(); - + bOk = bOk && RegisterMISummaryProviders(); m_bInitialized = bOk; if (!bOk && !HaveErrorDescription()) @@ -791,3 +830,54 @@ { return m_constStrThisThreadId; } + +//++ ------------------------------------------------------------------------------------ +// Details: Loads lldb-mi formatters +// Type: Method. +// Args: None. +// Return: true - Functionality succeeded. +// false - Functionality failed. +// Throws: None. +//-- +bool +CMICmnLLDBDebugger::LoadMIFormatters(lldb::SBTypeCategory miCategory) +{ + if (!MI_add_summary(miCategory, "char", MI_char_summary_provider, + lldb::eTypeOptionHideValue | lldb::eTypeOptionSkipPointers)) + return false; + + if (!MI_add_summary(miCategory, "unsigned char", MI_char_summary_provider, + lldb::eTypeOptionHideValue | lldb::eTypeOptionSkipPointers)) + return false; + + if (!MI_add_summary(miCategory, "signed char", MI_char_summary_provider, + lldb::eTypeOptionHideValue | lldb::eTypeOptionSkipPointers)) + return false; + + return true; +} + +//++ ------------------------------------------------------------------------------------ +// Details: Registers lldb-mi custom summary providers +// Type: Method. +// Args: None. +// Return: true - Functionality succeeded. +// false - Functionality failed. +// Throws: None. +//-- +bool +CMICmnLLDBDebugger::RegisterMISummaryProviders() +{ + static const char* miCategoryName = "lldb-mi"; + lldb::SBTypeCategory miCategory = m_lldbDebugger.CreateCategory(miCategoryName); + if (!miCategory.IsValid()) + return false; + + if (!LoadMIFormatters(miCategory)) + { + m_lldbDebugger.DeleteCategory(miCategoryName); + return false; + } + miCategory.SetEnabled(true); + return true; +} Index: lldb/trunk/tools/lldb-mi/MICmnLLDBUtilSBValue.h =================================================================== --- lldb/trunk/tools/lldb-mi/MICmnLLDBUtilSBValue.h +++ lldb/trunk/tools/lldb-mi/MICmnLLDBUtilSBValue.h @@ -51,11 +51,8 @@ private: template CMIUtilString ReadCStringFromHostMemory(lldb::SBValue &vrValue, const MIuint vnMaxLen = UINT32_MAX) const; bool GetSimpleValue(const bool vbHandleArrayType, CMIUtilString &vrValue) const; - CMIUtilString GetSimpleValueChar() const; - CMIUtilString GetSimpleValueCStringPointer() const; - CMIUtilString GetSimpleValueCStringArray() const; bool GetCompositeValue(const bool vbPrintFieldNames, CMICmnMIValueTuple &vwrMiValueTuple, const MIuint vnDepth = 1) const; - CMIUtilString GetValueSummary() const; + CMIUtilString GetValueSummary(bool valueOnly, const CMIUtilString& failVal = CMIUtilString()) const; // Statics: private: Index: lldb/trunk/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp =================================================================== --- lldb/trunk/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp +++ lldb/trunk/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp @@ -123,31 +123,13 @@ const MIuint nChildren = m_rValue.GetNumChildren(); if (nChildren == 0) { - if (m_bHandleCharType && IsCharType()) - { - vwrValue = GetSimpleValueChar(); - return MIstatus::success; - } - else - { - const char *pValue = m_rValue.GetValue(); - vwrValue = pValue != nullptr ? pValue : m_pUnkwn; - return MIstatus::success; - } + vwrValue = GetValueSummary(!m_bHandleCharType && IsCharType(), m_pUnkwn); + return MIstatus::success; } else if (IsPointerType()) { - if (m_bHandleCharType && IsPointeeCharType()) - { - vwrValue = GetSimpleValueCStringPointer(); - return MIstatus::success; - } - else - { - const char *pValue = m_rValue.GetValue(); - vwrValue = pValue != nullptr ? pValue : m_pUnkwn; - return MIstatus::success; - } + vwrValue = GetValueSummary(!m_bHandleCharType && IsPointeeCharType(), m_pUnkwn); + return MIstatus::success; } else if (IsArrayType()) { @@ -157,7 +139,7 @@ bPrintCharArrayAsString) && bPrintCharArrayAsString; if (bPrintCharArrayAsString && m_bHandleCharType && IsFirstChildCharType()) { - vwrValue = GetSimpleValueCStringArray(); + vwrValue = GetValueSummary(false); return MIstatus::success; } else if (vbHandleArrayType) @@ -170,7 +152,7 @@ { // Treat composite value which has registered summary // (for example with AddCXXSummary) as simple value - vwrValue = GetValueSummary(); + vwrValue = GetValueSummary(false); if (!vwrValue.empty()) return MIstatus::success; } @@ -179,143 +161,6 @@ return MIstatus::failure; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve from the LLDB SB Value object the char value of the variable. -// Type: Method. -// Args: None. -// Return: CMIUtilString - The char value of the variable. -// Throws: None. -//-- -CMIUtilString -CMICmnLLDBUtilSBValue::GetSimpleValueChar() const -{ - const CMIUtilString& summary = GetValueSummary(); - if (!summary.empty()) - return summary; - - const uint64_t value = m_rValue.GetValueAsUnsigned(); - if (value == 0) - { - const uint64_t nFailValue = 1; - if (nFailValue == m_rValue.GetValueAsUnsigned(nFailValue)) - return m_pUnkwn; - } - - const lldb::BasicType eType = m_rValue.GetType().GetBasicType(); - switch (eType) - { - default: - assert(0 && "value must be a char type"); - case lldb::eBasicTypeChar: - case lldb::eBasicTypeSignedChar: - case lldb::eBasicTypeUnsignedChar: - { - const CMIUtilString prefix(CMIUtilString::ConvertToPrintableASCII((char)value)); - return CMIUtilString::Format("%" PRIu8 " '%s'", (uint8_t)value, prefix.c_str()); - } - case lldb::eBasicTypeChar16: - { - const CMIUtilString prefix(CMIUtilString::ConvertToPrintableASCII((char16_t)value)); - return CMIUtilString::Format("U+%04" PRIx16 " u'%s'", (uint16_t)value, prefix.c_str()); - } - case lldb::eBasicTypeChar32: - { - const CMIUtilString prefix(CMIUtilString::ConvertToPrintableASCII((char32_t)value)); - return CMIUtilString::Format("U+%08" PRIx32 " U'%s'", (uint32_t)value, prefix.c_str()); - } - } -} - -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve from the LLDB SB Value object of type char* the c-string value. -// Type: Method. -// Args: None. -// Return: CMIUtilString - The c-string value of the variable. -// Throws: None. -//-- -CMIUtilString -CMICmnLLDBUtilSBValue::GetSimpleValueCStringPointer() const -{ - const CMIUtilString& summary = GetValueSummary(); - if (!summary.empty()) - return summary; - - const char *value = m_rValue.GetValue(); - if (value == nullptr) - return m_pUnkwn; - - lldb::SBValue child = m_rValue.GetChildAtIndex(0); - const lldb::BasicType eType = child.GetType().GetBasicType(); - switch (eType) - { - default: - assert(0 && "child must be a char type"); - case lldb::eBasicTypeChar: - case lldb::eBasicTypeSignedChar: - case lldb::eBasicTypeUnsignedChar: - { - const CMIUtilString prefix(ReadCStringFromHostMemory(child)); - // Note code that has const in will not show the text suffix to the string pointer - // i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this - // but char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this - return CMIUtilString::Format("%s \"%s\"", value, prefix.c_str()); - } - case lldb::eBasicTypeChar16: - { - const CMIUtilString prefix(ReadCStringFromHostMemory(child)); - return CMIUtilString::Format("%s u\"%s\"", value, prefix.c_str()); - } - case lldb::eBasicTypeChar32: - { - const CMIUtilString prefix(ReadCStringFromHostMemory(child)); - return CMIUtilString::Format("%s U\"%s\"", value, prefix.c_str()); - } - } -} - -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve from the LLDB SB Value object of type char[] the c-string value. -// Type: Method. -// Args: None. -// Return: CMIUtilString - The c-string value of the variable. -// Throws: None. -//-- -CMIUtilString -CMICmnLLDBUtilSBValue::GetSimpleValueCStringArray() const -{ - const CMIUtilString& summary = GetValueSummary(); - if (!summary.empty()) - return summary; - - const MIuint nChildren = m_rValue.GetNumChildren(); - lldb::SBValue child = m_rValue.GetChildAtIndex(0); - const lldb::BasicType eType = child.GetType().GetBasicType(); - switch (eType) - { - default: - assert(0 && "value must be a char[] type"); - case lldb::eBasicTypeChar: - case lldb::eBasicTypeSignedChar: - case lldb::eBasicTypeUnsignedChar: - { - const CMIUtilString prefix(ReadCStringFromHostMemory(m_rValue, nChildren)); - // TODO: to match char* it should be the following - // return CMIUtilString::Format("[%u] \"%s\"", nChildren, prefix.c_str()); - return CMIUtilString::Format("\"%s\"", prefix.c_str()); - } - case lldb::eBasicTypeChar16: - { - const CMIUtilString prefix(ReadCStringFromHostMemory(m_rValue, nChildren)); - return CMIUtilString::Format("u\"%s\"", prefix.c_str()); - } - case lldb::eBasicTypeChar32: - { - const CMIUtilString prefix(ReadCStringFromHostMemory(m_rValue, nChildren)); - return CMIUtilString::Format("U\"%s\"", prefix.c_str()); - } - } -} - bool CMICmnLLDBUtilSBValue::GetCompositeValue(const bool vbPrintFieldNames, CMICmnMIValueTuple &vwrMiValueTuple, const MIuint vnDepth /* = 1 */) const @@ -368,30 +213,37 @@ return MIstatus::success; } +// Returns value or value + summary, depending on valueOnly parameter value. +// If result is an empty string returns failVal. CMIUtilString -CMICmnLLDBUtilSBValue::GetValueSummary() const -{ - CMIUtilString valSummary; - if (m_rValue.IsValid()) - { -#ifndef LLDB_DISABLE_PYTHON - const char *c_str = m_rValue.GetSummary(); - if (c_str && c_str[0]) +CMICmnLLDBUtilSBValue::GetValueSummary(bool valueOnly, const CMIUtilString& failVal) const +{ + if (!m_rValue.IsValid()) + return failVal; + + CMIUtilString value, valSummary; + const char* c_value = m_rValue.GetValue(); + if (valueOnly) + return c_value == nullptr ? failVal : c_value; + + const char* c_summary = m_rValue.GetSummary(); + if (c_value) + value = c_value; + else if (c_summary == nullptr) + return failVal; + + if (c_summary && c_summary[0]) + { + valSummary = c_summary; + lldb::SBTypeSummary summary = m_rValue.GetTypeSummary(); + if (summary.IsValid() && summary.DoesPrintValue(m_rValue) && !value.empty()) { - valSummary = c_str; - lldb::SBTypeSummary summary = m_rValue.GetTypeSummary(); - if (summary.IsValid() && summary.DoesPrintValue(m_rValue)) - { - c_str = m_rValue.GetValue(); - if (c_str && c_str[0]) - { - valSummary.insert(0, std::string(c_str) + " "); - } - } + valSummary.insert(0, value + " "); } -#endif + return valSummary; } - return valSummary; + // no summary - return just value + return value; } //++ ------------------------------------------------------------------------------------