llvm-project/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp
Jonas Devlieghere 8b3af63b89 [NFC] Remove ASCII lines from comments
A lot of comments in LLDB are surrounded by an ASCII line to delimit the
begging and end of the comment.

Its use is not really consistent across the code base, sometimes the
lines are longer, sometimes they are shorter and sometimes they are
omitted. Furthermore, it looks kind of weird with the 80 column limit,
where the comment actually extends past the line, but not by much.
Furthermore, when /// is used for Doxygen comments, it looks
particularly odd. And when // is used, it incorrectly gives the
impression that it's actually a Doxygen comment.

I assume these lines were added to improve distinguishing between
comments and code. However, given that todays editors and IDEs do a
great job at highlighting comments, I think it's worth to drop this for
the sake of consistency. The alternative is fixing all the
inconsistencies, which would create a lot more churn.

Differential revision: https://reviews.llvm.org/D60508

llvm-svn: 358135
2019-04-10 20:48:55 +00:00

498 lines
16 KiB
C++

//===-- MICmnLLDBUtilSBValue.cpp --------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// Third party headers:
#include "lldb/API/SBTypeSummary.h"
#include <cinttypes>
// In-house headers:
#include "MICmnLLDBDebugSessionInfo.h"
#include "MICmnLLDBUtilSBValue.h"
#include "MICmnMIValueConst.h"
#include "MICmnMIValueTuple.h"
#include "MIUtilString.h"
static const char *kUnknownValue = "??";
static const char *kUnresolvedCompositeValue = "{...}";
//++
// 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_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 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;
}
//++
// 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(), 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 {
// 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 = kUnknownValue;
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 = 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;
}
// 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 kUnknownValue;
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 == kUnknownValue);
}
//++
// 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 == kUnknownValue);
}
//++
// 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 : kUnknownValue);
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 : kUnknownValue);
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) == '$');
}