#include "lldb/API/SBTypeSummary.h"
#include <cinttypes>
#include "MICmnLLDBDebugSessionInfo.h"
#include "MICmnLLDBUtilSBValue.h"
#include "MICmnMIValueConst.h"
#include "MICmnMIValueTuple.h"
#include "MIUtilString.h"
static const char *kUnknownValue = "??";
static const char *kUnresolvedCompositeValue = "{...}";
CMICmnLLDBUtilSBValue::CMICmnLLDBUtilSBValue(
const lldb::SBValue &vrValue, const bool vbHandleCharType ,
const bool vbHandleArrayType )
: m_rValue(const_cast<lldb::SBValue &>(vrValue)),
m_bHandleCharType(vbHandleCharType),
m_bHandleArrayType(vbHandleArrayType) {
m_bValidSBValue = m_rValue.IsValid();
}
CMICmnLLDBUtilSBValue::~CMICmnLLDBUtilSBValue() {}
CMIUtilString CMICmnLLDBUtilSBValue::GetName() const {
const char *pName = m_bValidSBValue ? m_rValue.GetName() : nullptr;
const CMIUtilString text((pName != nullptr) ? pName : CMIUtilString());
return text;
}
CMIUtilString CMICmnLLDBUtilSBValue::GetValue(
const bool vbExpandAggregates ) const {
if (!m_bValidSBValue)
return kUnknownValue;
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 kUnresolvedCompositeValue;
bool bPrintAggregateFieldNames = false;
bPrintAggregateFieldNames =
!rSessionInfo.SharedDataRetrieve<bool>(
rSessionInfo.m_constStrPrintAggregateFieldNames,
bPrintAggregateFieldNames) ||
bPrintAggregateFieldNames;
CMICmnMIValueTuple miValueTuple;
const bool bOk = GetCompositeValue(bPrintAggregateFieldNames, miValueTuple);
if (!bOk)
return kUnknownValue;
value = miValueTuple.GetString();
return value;
}
bool CMICmnLLDBUtilSBValue::GetSimpleValue(const bool vbHandleArrayType,
CMIUtilString &vwrValue) const {
const MIuint nChildren = m_rValue.GetNumChildren();
if (nChildren == 0) {
vwrValue =
GetValueSummary(!m_bHandleCharType && IsCharType(), kUnknownValue);
return MIstatus::success;
} else if (IsPointerType()) {
vwrValue = GetValueSummary(!m_bHandleCharType && IsPointeeCharType(),
kUnknownValue);
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 {
vwrValue = GetValueSummary(false);
if (!vwrValue.empty())
return MIstatus::success;
}
return MIstatus::failure;
}
bool CMICmnLLDBUtilSBValue::GetCompositeValue(
const bool vbPrintFieldNames, CMICmnMIValueTuple &vwrMiValueTuple,
const MIuint vnDepth ) 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) {
} else if (vnDepth < nMaxDepth) {
CMICmnMIValueTuple miValueTuple;
const bool bOk = utilMember.GetCompositeValue(vbPrintFieldNames,
miValueTuple, vnDepth + 1);
if (!bOk)
value = kUnknownValue;
else
value = miValueTuple.GetString();
} else {
value = kUnresolvedCompositeValue;
}
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;
}
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;
}
return value;
}
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;
}
}
bool CMICmnLLDBUtilSBValue::IsCharType() const {
const lldb::BasicType eType = m_rValue.GetType().GetBasicType();
return IsCharBasicType(eType);
}
bool CMICmnLLDBUtilSBValue::IsFirstChildCharType() const {
const MIuint nChildren = m_rValue.GetNumChildren();
if (nChildren == 0)
return false;
const lldb::SBValue member = m_rValue.GetChildAtIndex(0);
const CMICmnLLDBUtilSBValue utilValue(member);
return utilValue.IsCharType();
}
bool CMICmnLLDBUtilSBValue::IsPointeeCharType() const {
const MIuint nChildren = m_rValue.GetNumChildren();
if (nChildren == 0)
return false;
const lldb::BasicType eType =
m_rValue.GetType().GetPointeeType().GetBasicType();
return IsCharBasicType(eType);
}
bool CMICmnLLDBUtilSBValue::IsIntegerType() const {
const lldb::BasicType eType =
m_rValue.GetType().GetCanonicalType().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));
}
bool CMICmnLLDBUtilSBValue::IsPointerType() const {
return m_rValue.GetType().IsPointerType();
}
bool CMICmnLLDBUtilSBValue::IsArrayType() const {
return m_rValue.GetType().IsArrayType();
}
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 kUnknownValue;
else if (ch == 0)
break;
result.append(
CMIUtilString::ConvertToPrintableASCII(ch, true ));
addr += sizeof(ch);
}
return result;
}
bool CMICmnLLDBUtilSBValue::IsNameUnknown() const {
const CMIUtilString name(GetName());
return (name == kUnknownValue);
}
bool CMICmnLLDBUtilSBValue::IsValueUnknown() const {
const CMIUtilString value(GetValue());
return (value == kUnknownValue);
}
CMIUtilString CMICmnLLDBUtilSBValue::GetTypeName() const {
const char *pName = m_bValidSBValue ? m_rValue.GetTypeName() : nullptr;
const CMIUtilString text((pName != nullptr) ? pName : kUnknownValue);
return text;
}
CMIUtilString CMICmnLLDBUtilSBValue::GetTypeNameDisplay() const {
const char *pName = m_bValidSBValue ? m_rValue.GetDisplayTypeName() : nullptr;
const CMIUtilString text((pName != nullptr) ? pName : kUnknownValue);
return text;
}
bool CMICmnLLDBUtilSBValue::IsValid() const { return m_bValidSBValue; }
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;
}
bool CMICmnLLDBUtilSBValue::IsLLDBVariable() const {
return (GetName().at(0) == '$');
}