1 //===-- MICmnLLDBUtilSBValue.cpp --------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Third party headers:
10 #include "lldb/API/SBTypeSummary.h"
14 #include "MICmnLLDBDebugSessionInfo.h"
15 #include "MICmnLLDBUtilSBValue.h"
16 #include "MICmnMIValueConst.h"
17 #include "MICmnMIValueTuple.h"
18 #include "MIUtilString.h"
20 static const char *kUnknownValue = "??";
21 static const char *kUnresolvedCompositeValue = "{...}";
24 // Details: CMICmnLLDBUtilSBValue constructor.
26 // Args: vrValue - (R) The LLDB value object.
27 // vbHandleCharType - (R) True = Yes return text molding to char
29 // False = just return data.
33 CMICmnLLDBUtilSBValue::CMICmnLLDBUtilSBValue(
34 const lldb::SBValue &vrValue, const bool vbHandleCharType /* = false */,
35 const bool vbHandleArrayType /* = true */)
36 : m_rValue(const_cast<lldb::SBValue &>(vrValue)),
37 m_bHandleCharType(vbHandleCharType),
38 m_bHandleArrayType(vbHandleArrayType) {
39 m_bValidSBValue = m_rValue.IsValid();
43 // Details: CMICmnLLDBUtilSBValue destructor.
49 CMICmnLLDBUtilSBValue::~CMICmnLLDBUtilSBValue() {}
52 // Details: Retrieve from the LLDB SB Value object the name of the variable. If
54 // is invalid (or the SBValue object invalid) then "??" is returned.
57 // Return: CMIUtilString - Name of the variable or "??" for unknown.
60 CMIUtilString CMICmnLLDBUtilSBValue::GetName() const {
61 const char *pName = m_bValidSBValue ? m_rValue.GetName() : nullptr;
62 const CMIUtilString text((pName != nullptr) ? pName : CMIUtilString());
68 // Details: Retrieve from the LLDB SB Value object the value of the variable
70 // text. If the value is invalid (or the SBValue object invalid) then
75 // Return: CMIUtilString - Text description of the variable's value or "??".
78 CMIUtilString CMICmnLLDBUtilSBValue::GetValue(
79 const bool vbExpandAggregates /* = false */) const {
83 CMICmnLLDBDebugSessionInfo &rSessionInfo(
84 CMICmnLLDBDebugSessionInfo::Instance());
85 bool bPrintExpandAggregates = false;
86 bPrintExpandAggregates = rSessionInfo.SharedDataRetrieve<bool>(
87 rSessionInfo.m_constStrPrintExpandAggregates,
88 bPrintExpandAggregates) &&
89 bPrintExpandAggregates;
91 const bool bHandleArrayTypeAsSimple =
92 m_bHandleArrayType && !vbExpandAggregates && !bPrintExpandAggregates;
94 const bool bIsSimpleValue = GetSimpleValue(bHandleArrayTypeAsSimple, value);
98 if (!vbExpandAggregates && !bPrintExpandAggregates)
99 return kUnresolvedCompositeValue;
101 bool bPrintAggregateFieldNames = false;
102 bPrintAggregateFieldNames =
103 !rSessionInfo.SharedDataRetrieve<bool>(
104 rSessionInfo.m_constStrPrintAggregateFieldNames,
105 bPrintAggregateFieldNames) ||
106 bPrintAggregateFieldNames;
108 CMICmnMIValueTuple miValueTuple;
109 const bool bOk = GetCompositeValue(bPrintAggregateFieldNames, miValueTuple);
111 return kUnknownValue;
113 value = miValueTuple.GetString();
118 // Details: Retrieve from the LLDB SB Value object the value of the variable
120 // text if it has a simple format (not composite).
122 // Args: vwrValue - (W) The SBValue in a string format.
123 // Return: MIstatus::success - Function succeeded.
124 // MIstatus::failure - Function failed.
127 bool CMICmnLLDBUtilSBValue::GetSimpleValue(const bool vbHandleArrayType,
128 CMIUtilString &vwrValue) const {
129 const MIuint nChildren = m_rValue.GetNumChildren();
130 if (nChildren == 0) {
131 vwrValue = GetValueSummary(!m_bHandleCharType && IsCharType(), kUnknownValue);
132 return MIstatus::success;
133 } else if (IsPointerType()) {
135 GetValueSummary(!m_bHandleCharType && IsPointeeCharType(), kUnknownValue);
136 return MIstatus::success;
137 } else if (IsArrayType()) {
138 CMICmnLLDBDebugSessionInfo &rSessionInfo(
139 CMICmnLLDBDebugSessionInfo::Instance());
140 bool bPrintCharArrayAsString = false;
141 bPrintCharArrayAsString = rSessionInfo.SharedDataRetrieve<bool>(
142 rSessionInfo.m_constStrPrintCharArrayAsString,
143 bPrintCharArrayAsString) &&
144 bPrintCharArrayAsString;
145 if (bPrintCharArrayAsString && m_bHandleCharType &&
146 IsFirstChildCharType()) {
147 vwrValue = GetValueSummary(false);
148 return MIstatus::success;
149 } else if (vbHandleArrayType) {
150 vwrValue = CMIUtilString::Format("[%u]", nChildren);
151 return MIstatus::success;
154 // Treat composite value which has registered summary
155 // (for example with AddCXXSummary) as simple value
156 vwrValue = GetValueSummary(false);
157 if (!vwrValue.empty())
158 return MIstatus::success;
161 // Composite variable type i.e. struct
162 return MIstatus::failure;
165 bool CMICmnLLDBUtilSBValue::GetCompositeValue(
166 const bool vbPrintFieldNames, CMICmnMIValueTuple &vwrMiValueTuple,
167 const MIuint vnDepth /* = 1 */) const {
168 const MIuint nMaxDepth = 10;
169 const MIuint nChildren = m_rValue.GetNumChildren();
170 for (MIuint i = 0; i < nChildren; ++i) {
171 const lldb::SBValue member = m_rValue.GetChildAtIndex(i);
172 const CMICmnLLDBUtilSBValue utilMember(member, m_bHandleCharType,
174 const bool bHandleArrayTypeAsSimple = false;
176 const bool bIsSimpleValue =
177 utilMember.GetSimpleValue(bHandleArrayTypeAsSimple, value);
178 if (bIsSimpleValue) {
179 // OK. Value is simple (not composite) and was successfully got
180 } else if (vnDepth < nMaxDepth) {
181 // Need to get value from composite type
182 CMICmnMIValueTuple miValueTuple;
183 const bool bOk = utilMember.GetCompositeValue(vbPrintFieldNames,
184 miValueTuple, vnDepth + 1);
186 // Can't obtain composite type
187 value = kUnknownValue;
189 // OK. Value is composite and was successfully got
190 value = miValueTuple.GetString();
192 // Need to get value from composite type, but vnMaxDepth is reached
193 value = kUnresolvedCompositeValue;
195 const bool bNoQuotes = true;
196 const CMICmnMIValueConst miValueConst(value, bNoQuotes);
197 if (vbPrintFieldNames) {
198 const bool bUseSpacing = true;
199 const CMICmnMIValueResult miValueResult(utilMember.GetName(),
200 miValueConst, bUseSpacing);
201 vwrMiValueTuple.Add(miValueResult, bUseSpacing);
203 const bool bUseSpacing = false;
204 vwrMiValueTuple.Add(miValueConst, bUseSpacing);
208 return MIstatus::success;
211 // Returns value or value + summary, depending on valueOnly parameter value.
212 // If result is an empty string returns failVal.
214 CMICmnLLDBUtilSBValue::GetValueSummary(bool valueOnly,
215 const CMIUtilString &failVal) const {
216 if (!m_rValue.IsValid())
219 CMIUtilString value, valSummary;
220 const char *c_value = m_rValue.GetValue();
222 return c_value == nullptr ? failVal : c_value;
224 const char *c_summary = m_rValue.GetSummary();
227 else if (c_summary == nullptr)
230 if (c_summary && c_summary[0]) {
231 valSummary = c_summary;
232 lldb::SBTypeSummary summary = m_rValue.GetTypeSummary();
233 if (summary.IsValid() && summary.DoesPrintValue(m_rValue) &&
235 valSummary.insert(0, value + " ");
239 // no summary - return just value
244 // Details: Check that basic type is a char type. Char type can be signed or
247 // Args: eType - type to check
248 // Return: bool - True = Yes is a char type, false = some other type.
251 bool CMICmnLLDBUtilSBValue::IsCharBasicType(lldb::BasicType eType) {
253 case lldb::eBasicTypeChar:
254 case lldb::eBasicTypeSignedChar:
255 case lldb::eBasicTypeUnsignedChar:
256 case lldb::eBasicTypeChar16:
257 case lldb::eBasicTypeChar32:
265 // Details: Retrieve the flag stating whether this value object is a char type
267 // other type. Char type can be signed or unsigned.
270 // Return: bool - True = Yes is a char type, false = some other type.
273 bool CMICmnLLDBUtilSBValue::IsCharType() const {
274 const lldb::BasicType eType = m_rValue.GetType().GetBasicType();
275 return IsCharBasicType(eType);
279 // Details: Retrieve the flag stating whether first child value object of *this
281 // a char type or some other type. Returns false if there are not
283 // type can be signed or unsigned.
286 // Return: bool - True = Yes is a char type, false = some other type.
289 bool CMICmnLLDBUtilSBValue::IsFirstChildCharType() const {
290 const MIuint nChildren = m_rValue.GetNumChildren();
292 // Is it a basic type
296 const lldb::SBValue member = m_rValue.GetChildAtIndex(0);
297 const CMICmnLLDBUtilSBValue utilValue(member);
298 return utilValue.IsCharType();
302 // Details: Retrieve the flag stating whether pointee object of *this object is
303 // a char type or some other type. Returns false if there are not
305 // type can be signed or unsigned.
308 // Return: bool - True = Yes is a char type, false = some other type.
311 bool CMICmnLLDBUtilSBValue::IsPointeeCharType() const {
312 const MIuint nChildren = m_rValue.GetNumChildren();
314 // Is it a basic type
318 const lldb::BasicType eType =
319 m_rValue.GetType().GetPointeeType().GetBasicType();
320 return IsCharBasicType(eType);
324 // Details: Retrieve the flag stating whether this value object is a integer
326 // other type. Char type can be signed or unsigned and short or
330 // Return: bool - True = Yes is a integer type, false = some other type.
333 bool CMICmnLLDBUtilSBValue::IsIntegerType() const {
334 const lldb::BasicType eType = m_rValue.GetType().GetBasicType();
335 return ((eType == lldb::eBasicTypeShort) ||
336 (eType == lldb::eBasicTypeUnsignedShort) ||
337 (eType == lldb::eBasicTypeInt) ||
338 (eType == lldb::eBasicTypeUnsignedInt) ||
339 (eType == lldb::eBasicTypeLong) ||
340 (eType == lldb::eBasicTypeUnsignedLong) ||
341 (eType == lldb::eBasicTypeLongLong) ||
342 (eType == lldb::eBasicTypeUnsignedLongLong) ||
343 (eType == lldb::eBasicTypeInt128) ||
344 (eType == lldb::eBasicTypeUnsignedInt128));
348 // Details: Retrieve the flag stating whether this value object is a pointer
353 // Return: bool - True = Yes is a pointer type, false = some other type.
356 bool CMICmnLLDBUtilSBValue::IsPointerType() const {
357 return m_rValue.GetType().IsPointerType();
361 // Details: Retrieve the flag stating whether this value object is an array type
366 // Return: bool - True = Yes is an array type, false = some other type.
369 bool CMICmnLLDBUtilSBValue::IsArrayType() const {
370 return m_rValue.GetType().IsArrayType();
374 // Details: Retrieve the C string data of value object by read the memory where
378 // Args: vrValue - (R) LLDB SBValue variable object.
379 // Return: CMIUtilString - Text description of the variable's value.
382 template <typename charT>
384 CMICmnLLDBUtilSBValue::ReadCStringFromHostMemory(lldb::SBValue &vrValue,
385 const MIuint vnMaxLen) const {
387 lldb::addr_t addr = vrValue.GetLoadAddress(),
388 end_addr = addr + vnMaxLen * sizeof(charT);
389 lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
391 while (addr < end_addr) {
393 const MIuint64 nReadBytes =
394 process.ReadMemory(addr, &ch, sizeof(ch), error);
395 if (error.Fail() || nReadBytes != sizeof(ch))
396 return kUnknownValue;
400 CMIUtilString::ConvertToPrintableASCII(ch, true /* bEscapeQuotes */));
408 // Details: Retrieve the state of the value object's name.
411 // Return: bool - True = yes name is indeterminate, false = name is valid.
414 bool CMICmnLLDBUtilSBValue::IsNameUnknown() const {
415 const CMIUtilString name(GetName());
416 return (name == kUnknownValue);
420 // Details: Retrieve the state of the value object's value data.
423 // Return: bool - True = yes value is indeterminate, false = value valid.
426 bool CMICmnLLDBUtilSBValue::IsValueUnknown() const {
427 const CMIUtilString value(GetValue());
428 return (value == kUnknownValue);
432 // Details: Retrieve the value object's type name if valid.
435 // Return: CMIUtilString - The type name or "??".
438 CMIUtilString CMICmnLLDBUtilSBValue::GetTypeName() const {
439 const char *pName = m_bValidSBValue ? m_rValue.GetTypeName() : nullptr;
440 const CMIUtilString text((pName != nullptr) ? pName : kUnknownValue);
446 // Details: Retrieve the value object's display type name if valid.
449 // Return: CMIUtilString - The type name or "??".
452 CMIUtilString CMICmnLLDBUtilSBValue::GetTypeNameDisplay() const {
453 const char *pName = m_bValidSBValue ? m_rValue.GetDisplayTypeName() : nullptr;
454 const CMIUtilString text((pName != nullptr) ? pName : kUnknownValue);
460 // Details: Retrieve whether the value object's is valid or not.
463 // Return: bool - True = valid, false = not valid.
466 bool CMICmnLLDBUtilSBValue::IsValid() const { return m_bValidSBValue; }
469 // Details: Retrieve the value object' has a name. A value object can be valid
471 // have no name which suggest it is not a variable.
474 // Return: bool - True = valid, false = not valid.
477 bool CMICmnLLDBUtilSBValue::HasName() const {
478 bool bHasAName = false;
480 const char *pName = m_bValidSBValue ? m_rValue.GetDisplayTypeName() : nullptr;
481 if (pName != nullptr) {
482 bHasAName = (CMIUtilString(pName).length() > 0);
489 // Details: Determine if the value object' represents a LLDB variable i.e. "$0".
492 // Return: bool - True = Yes LLDB variable, false = no.
495 bool CMICmnLLDBUtilSBValue::IsLLDBVariable() const {
496 return (GetName().at(0) == '$');