# 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))
# 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))
# 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
#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"
#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.
errMsg += GetErrorDescription().c_str();
}
bOk = bOk && InitStdStreams();
-
+ bOk = bOk && RegisterMISummaryProviders();
m_bInitialized = bOk;
if (!bOk && !HaveErrorDescription())
{
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;
+}
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())
{
bPrintCharArrayAsString) && bPrintCharArrayAsString;
if (bPrintCharArrayAsString && m_bHandleCharType && IsFirstChildCharType())
{
- vwrValue = GetSimpleValueCStringArray();
+ vwrValue = GetValueSummary(false);
return MIstatus::success;
}
else if (vbHandleArrayType)
{
// 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;
}
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<char>(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<char16_t>(child));
- return CMIUtilString::Format("%s u\"%s\"", value, prefix.c_str());
- }
- case lldb::eBasicTypeChar32:
- {
- const CMIUtilString prefix(ReadCStringFromHostMemory<char32_t>(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<char>(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<char16_t>(m_rValue, nChildren));
- return CMIUtilString::Format("u\"%s\"", prefix.c_str());
- }
- case lldb::eBasicTypeChar32:
- {
- const CMIUtilString prefix(ReadCStringFromHostMemory<char32_t>(m_rValue, nChildren));
- return CMIUtilString::Format("U\"%s\"", prefix.c_str());
- }
- }
-}
-
bool
CMICmnLLDBUtilSBValue::GetCompositeValue(const bool vbPrintFieldNames, CMICmnMIValueTuple &vwrMiValueTuple,
const MIuint vnDepth /* = 1 */) const
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())
+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])
{
-#ifndef LLDB_DISABLE_PYTHON
- const char *c_str = m_rValue.GetSummary();
- if (c_str && c_str[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;
}
//++ ------------------------------------------------------------------------------------