hanchenye-llvm-project/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp

517 lines
18 KiB
C++

//===-- MICmnLLDBUtilSBValue.cpp --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Third party headers:
#include <cinttypes>
#include "lldb/API/SBTypeSummary.h"
// In-house headers:
#include "MICmnLLDBUtilSBValue.h"
#include "MICmnLLDBDebugSessionInfo.h"
#include "MICmnMIValueConst.h"
#include "MICmnMIValueTuple.h"
#include "MIUtilString.h"
//++ ------------------------------------------------------------------------------------
// Details: CMICmnLLDBUtilSBValue constructor.
// Type: Method.
// Args: vrValue - (R) The LLDB value object.
// vbHandleCharType - (R) True = Yes return text molding to char type,
// False = just return data.
// Return: None.
// Throws: None.
//--
CMICmnLLDBUtilSBValue::CMICmnLLDBUtilSBValue(const lldb::SBValue &vrValue, const bool vbHandleCharType /* = false */,
const bool vbHandleArrayType /* = true */)
: m_rValue(const_cast<lldb::SBValue &>(vrValue))
, m_pUnkwn("??")
, m_pComposite("{...}")
, m_bHandleCharType(vbHandleCharType)
, m_bHandleArrayType(vbHandleArrayType)
{
m_bValidSBValue = m_rValue.IsValid();
}
//++ ------------------------------------------------------------------------------------
// Details: CMICmnLLDBUtilSBValue destructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmnLLDBUtilSBValue::~CMICmnLLDBUtilSBValue()
{
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve from the LLDB SB Value object the name of the variable. If the name
// is invalid (or the SBValue object invalid) then "??" is returned.
// Type: Method.
// Args: None.
// Return: CMIUtilString - Name of the variable or "??" for unknown.
// Throws: None.
//--
CMIUtilString
CMICmnLLDBUtilSBValue::GetName() const
{
const char *pName = m_bValidSBValue ? m_rValue.GetName() : nullptr;
const CMIUtilString text((pName != nullptr) ? pName : CMIUtilString());
return text;
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve from the LLDB SB Value object the value of the variable described in
// text. If the value is invalid (or the SBValue object invalid) then "??" is
// returned.
// Type: Method.
// Args: None.
// Return: CMIUtilString - Text description of the variable's value or "??".
// Throws: None.
//--
CMIUtilString
CMICmnLLDBUtilSBValue::GetValue(const bool vbExpandAggregates /* = false */) const
{
if (!m_bValidSBValue)
return m_pUnkwn;
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
bool bPrintExpandAggregates = false;
bPrintExpandAggregates = rSessionInfo.SharedDataRetrieve<bool>(rSessionInfo.m_constStrPrintExpandAggregates,
bPrintExpandAggregates) && bPrintExpandAggregates;
const bool bHandleArrayTypeAsSimple = m_bHandleArrayType && !vbExpandAggregates && !bPrintExpandAggregates;
CMIUtilString value;
const bool bIsSimpleValue = GetSimpleValue(bHandleArrayTypeAsSimple, value);
if (bIsSimpleValue)
return value;
if (!vbExpandAggregates && !bPrintExpandAggregates)
return m_pComposite;
bool bPrintAggregateFieldNames = false;
bPrintAggregateFieldNames = !rSessionInfo.SharedDataRetrieve<bool>(rSessionInfo.m_constStrPrintAggregateFieldNames,
bPrintAggregateFieldNames) || bPrintAggregateFieldNames;
CMICmnMIValueTuple miValueTuple;
const bool bOk = GetCompositeValue(bPrintAggregateFieldNames, miValueTuple);
if (!bOk)
return m_pUnkwn;
value = miValueTuple.GetString();
return value;
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve from the LLDB SB Value object the value of the variable described in
// text if it has a simple format (not composite).
// Type: Method.
// Args: vwrValue - (W) The SBValue in a string format.
// Return: MIstatus::success - Function succeeded.
// MIstatus::failure - Function failed.
// Throws: None.
//--
bool
CMICmnLLDBUtilSBValue::GetSimpleValue(const bool vbHandleArrayType, CMIUtilString &vwrValue) const
{
const MIuint nChildren = m_rValue.GetNumChildren();
if (nChildren == 0)
{
vwrValue = GetValueSummary(!m_bHandleCharType && IsCharType(), m_pUnkwn);
return MIstatus::success;
}
else if (IsPointerType())
{
vwrValue = GetValueSummary(!m_bHandleCharType && IsPointeeCharType(), m_pUnkwn);
return MIstatus::success;
}
else if (IsArrayType())
{
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
bool bPrintCharArrayAsString = false;
bPrintCharArrayAsString = rSessionInfo.SharedDataRetrieve<bool>(rSessionInfo.m_constStrPrintCharArrayAsString,
bPrintCharArrayAsString) && bPrintCharArrayAsString;
if (bPrintCharArrayAsString && m_bHandleCharType && IsFirstChildCharType())
{
vwrValue = GetValueSummary(false);
return MIstatus::success;
}
else if (vbHandleArrayType)
{
vwrValue = CMIUtilString::Format("[%u]", nChildren);
return MIstatus::success;
}
}
else
{
// Treat composite value which has registered summary
// (for example with AddCXXSummary) as simple value
vwrValue = GetValueSummary(false);
if (!vwrValue.empty())
return MIstatus::success;
}
// Composite variable type i.e. struct
return MIstatus::failure;
}
bool
CMICmnLLDBUtilSBValue::GetCompositeValue(const bool vbPrintFieldNames, CMICmnMIValueTuple &vwrMiValueTuple,
const MIuint vnDepth /* = 1 */) const
{
const MIuint nMaxDepth = 10;
const MIuint nChildren = m_rValue.GetNumChildren();
for (MIuint i = 0; i < nChildren; ++i)
{
const lldb::SBValue member = m_rValue.GetChildAtIndex(i);
const CMICmnLLDBUtilSBValue utilMember(member, m_bHandleCharType, m_bHandleArrayType);
const bool bHandleArrayTypeAsSimple = false;
CMIUtilString value;
const bool bIsSimpleValue = utilMember.GetSimpleValue(bHandleArrayTypeAsSimple, value);
if (bIsSimpleValue)
{
// OK. Value is simple (not composite) and was successfully got
}
else if (vnDepth < nMaxDepth)
{
// Need to get value from composite type
CMICmnMIValueTuple miValueTuple;
const bool bOk = utilMember.GetCompositeValue(vbPrintFieldNames, miValueTuple, vnDepth + 1);
if (!bOk)
// Can't obtain composite type
value = m_pUnkwn;
else
// OK. Value is composite and was successfully got
value = miValueTuple.GetString();
}
else
{
// Need to get value from composite type, but vnMaxDepth is reached
value = m_pComposite;
}
const bool bNoQuotes = true;
const CMICmnMIValueConst miValueConst(value, bNoQuotes);
if (vbPrintFieldNames)
{
const bool bUseSpacing = true;
const CMICmnMIValueResult miValueResult(utilMember.GetName(), miValueConst, bUseSpacing);
vwrMiValueTuple.Add(miValueResult, bUseSpacing);
}
else
{
const bool bUseSpacing = false;
vwrMiValueTuple.Add(miValueConst, bUseSpacing);
}
}
return MIstatus::success;
}
// Returns value or value + summary, depending on valueOnly parameter value.
// If result is an empty string returns failVal.
CMIUtilString
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.insert(0, value + " ");
}
return valSummary;
}
// no summary - return just value
return value;
}
//++ ------------------------------------------------------------------------------------
// Details: Check that basic type is a char type. Char type can be signed or unsigned.
// Type: Static.
// Args: eType - type to check
// Return: bool - True = Yes is a char type, false = some other type.
// Throws: None.
//--
bool
CMICmnLLDBUtilSBValue::IsCharBasicType(lldb::BasicType eType)
{
switch (eType)
{
case lldb::eBasicTypeChar:
case lldb::eBasicTypeSignedChar:
case lldb::eBasicTypeUnsignedChar:
case lldb::eBasicTypeChar16:
case lldb::eBasicTypeChar32:
return true;
default:
return false;
}
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve the flag stating whether this value object is a char type or some
// other type. Char type can be signed or unsigned.
// Type: Method.
// Args: None.
// Return: bool - True = Yes is a char type, false = some other type.
// Throws: None.
//--
bool
CMICmnLLDBUtilSBValue::IsCharType() const
{
const lldb::BasicType eType = m_rValue.GetType().GetBasicType();
return IsCharBasicType(eType);
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve the flag stating whether first child value object of *this object is
// a char type or some other type. Returns false if there are not children. Char
// type can be signed or unsigned.
// Type: Method.
// Args: None.
// Return: bool - True = Yes is a char type, false = some other type.
// Throws: None.
//--
bool
CMICmnLLDBUtilSBValue::IsFirstChildCharType() const
{
const MIuint nChildren = m_rValue.GetNumChildren();
// Is it a basic type
if (nChildren == 0)
return false;
const lldb::SBValue member = m_rValue.GetChildAtIndex(0);
const CMICmnLLDBUtilSBValue utilValue(member);
return utilValue.IsCharType();
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve the flag stating whether pointee object of *this object is
// a char type or some other type. Returns false if there are not children. Char
// type can be signed or unsigned.
// Type: Method.
// Args: None.
// Return: bool - True = Yes is a char type, false = some other type.
// Throws: None.
//--
bool
CMICmnLLDBUtilSBValue::IsPointeeCharType() const
{
const MIuint nChildren = m_rValue.GetNumChildren();
// Is it a basic type
if (nChildren == 0)
return false;
const lldb::BasicType eType = m_rValue.GetType().GetPointeeType().GetBasicType();
return IsCharBasicType(eType);
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve the flag stating whether this value object is a integer type or some
// other type. Char type can be signed or unsigned and short or long/very long.
// Type: Method.
// Args: None.
// Return: bool - True = Yes is a integer type, false = some other type.
// Throws: None.
//--
bool
CMICmnLLDBUtilSBValue::IsIntegerType() const
{
const lldb::BasicType eType = m_rValue.GetType().GetBasicType();
return ((eType == lldb::eBasicTypeShort) || (eType == lldb::eBasicTypeUnsignedShort) ||
(eType == lldb::eBasicTypeInt) || (eType == lldb::eBasicTypeUnsignedInt) ||
(eType == lldb::eBasicTypeLong) || (eType == lldb::eBasicTypeUnsignedLong) ||
(eType == lldb::eBasicTypeLongLong) || (eType == lldb::eBasicTypeUnsignedLongLong) ||
(eType == lldb::eBasicTypeInt128) || (eType == lldb::eBasicTypeUnsignedInt128));
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve the flag stating whether this value object is a pointer type or some
// other type.
// Type: Method.
// Args: None.
// Return: bool - True = Yes is a pointer type, false = some other type.
// Throws: None.
//--
bool
CMICmnLLDBUtilSBValue::IsPointerType() const
{
return m_rValue.GetType().IsPointerType();
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve the flag stating whether this value object is an array type or some
// other type.
// Type: Method.
// Args: None.
// Return: bool - True = Yes is an array type, false = some other type.
// Throws: None.
//--
bool
CMICmnLLDBUtilSBValue::IsArrayType() const
{
return m_rValue.GetType().IsArrayType();
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve the C string data of value object by read the memory where the
// variable is held.
// Type: Method.
// Args: vrValue - (R) LLDB SBValue variable object.
// Return: CMIUtilString - Text description of the variable's value.
// Throws: None.
//--
template <typename charT>
CMIUtilString
CMICmnLLDBUtilSBValue::ReadCStringFromHostMemory(lldb::SBValue &vrValue, const MIuint vnMaxLen) const
{
std::string result;
lldb::addr_t addr = vrValue.GetLoadAddress(), end_addr = addr + vnMaxLen * sizeof(charT);
lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
lldb::SBError error;
while (addr < end_addr)
{
charT ch;
const MIuint64 nReadBytes = process.ReadMemory(addr, &ch, sizeof(ch), error);
if (error.Fail() || nReadBytes != sizeof(ch))
return m_pUnkwn;
else if (ch == 0)
break;
result.append(CMIUtilString::ConvertToPrintableASCII(ch, true /* bEscapeQuotes */));
addr += sizeof(ch);
}
return result;
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve the state of the value object's name.
// Type: Method.
// Args: None.
// Return: bool - True = yes name is indeterminate, false = name is valid.
// Throws: None.
//--
bool
CMICmnLLDBUtilSBValue::IsNameUnknown() const
{
const CMIUtilString name(GetName());
return (name == m_pUnkwn);
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve the state of the value object's value data.
// Type: Method.
// Args: None.
// Return: bool - True = yes value is indeterminate, false = value valid.
// Throws: None.
//--
bool
CMICmnLLDBUtilSBValue::IsValueUnknown() const
{
const CMIUtilString value(GetValue());
return (value == m_pUnkwn);
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve the value object's type name if valid.
// Type: Method.
// Args: None.
// Return: CMIUtilString - The type name or "??".
// Throws: None.
//--
CMIUtilString
CMICmnLLDBUtilSBValue::GetTypeName() const
{
const char *pName = m_bValidSBValue ? m_rValue.GetTypeName() : nullptr;
const CMIUtilString text((pName != nullptr) ? pName : m_pUnkwn);
return text;
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve the value object's display type name if valid.
// Type: Method.
// Args: None.
// Return: CMIUtilString - The type name or "??".
// Throws: None.
//--
CMIUtilString
CMICmnLLDBUtilSBValue::GetTypeNameDisplay() const
{
const char *pName = m_bValidSBValue ? m_rValue.GetDisplayTypeName() : nullptr;
const CMIUtilString text((pName != nullptr) ? pName : m_pUnkwn);
return text;
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve whether the value object's is valid or not.
// Type: Method.
// Args: None.
// Return: bool - True = valid, false = not valid.
// Throws: None.
//--
bool
CMICmnLLDBUtilSBValue::IsValid() const
{
return m_bValidSBValue;
}
//++ ------------------------------------------------------------------------------------
// Details: Retrieve the value object' has a name. A value object can be valid but still
// have no name which suggest it is not a variable.
// Type: Method.
// Args: None.
// Return: bool - True = valid, false = not valid.
// Throws: None.
//--
bool
CMICmnLLDBUtilSBValue::HasName() const
{
bool bHasAName = false;
const char *pName = m_bValidSBValue ? m_rValue.GetDisplayTypeName() : nullptr;
if (pName != nullptr)
{
bHasAName = (CMIUtilString(pName).length() > 0);
}
return bHasAName;
}
//++ ------------------------------------------------------------------------------------
// Details: Determine if the value object' represents a LLDB variable i.e. "$0".
// Type: Method.
// Args: None.
// Return: bool - True = Yes LLDB variable, false = no.
// Throws: None.
//--
bool
CMICmnLLDBUtilSBValue::IsLLDBVariable() const
{
return (GetName().at(0) == '$');
}