1 //===-- MICmnLLDBUtilSBValue.cpp --------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // Third party headers:
11 #include "lldb/API/SBTypeSummary.h"
12 #include <cinttypes>
13
14 // In-house headers:
15 #include "MICmnLLDBDebugSessionInfo.h"
16 #include "MICmnLLDBUtilSBValue.h"
17 #include "MICmnMIValueConst.h"
18 #include "MICmnMIValueTuple.h"
19 #include "MIUtilString.h"
20
21 static const char *kUnknownValue = "??";
22 static const char *kUnresolvedCompositeValue = "{...}";
23
24 //++
25 //------------------------------------------------------------------------------------
26 // Details: CMICmnLLDBUtilSBValue constructor.
27 // Type: Method.
28 // Args: vrValue - (R) The LLDB value object.
29 // vbHandleCharType - (R) True = Yes return text molding to char
30 // type,
31 // False = just return data.
32 // Return: None.
33 // Throws: None.
34 //--
CMICmnLLDBUtilSBValue(const lldb::SBValue & vrValue,const bool vbHandleCharType,const bool vbHandleArrayType)35 CMICmnLLDBUtilSBValue::CMICmnLLDBUtilSBValue(
36 const lldb::SBValue &vrValue, const bool vbHandleCharType /* = false */,
37 const bool vbHandleArrayType /* = true */)
38 : m_rValue(const_cast<lldb::SBValue &>(vrValue)),
39 m_bHandleCharType(vbHandleCharType),
40 m_bHandleArrayType(vbHandleArrayType) {
41 m_bValidSBValue = m_rValue.IsValid();
42 }
43
44 //++
45 //------------------------------------------------------------------------------------
46 // Details: CMICmnLLDBUtilSBValue destructor.
47 // Type: Method.
48 // Args: None.
49 // Return: None.
50 // Throws: None.
51 //--
~CMICmnLLDBUtilSBValue()52 CMICmnLLDBUtilSBValue::~CMICmnLLDBUtilSBValue() {}
53
54 //++
55 //------------------------------------------------------------------------------------
56 // Details: Retrieve from the LLDB SB Value object the name of the variable. If
57 // the name
58 // is invalid (or the SBValue object invalid) then "??" is returned.
59 // Type: Method.
60 // Args: None.
61 // Return: CMIUtilString - Name of the variable or "??" for unknown.
62 // Throws: None.
63 //--
GetName() const64 CMIUtilString CMICmnLLDBUtilSBValue::GetName() const {
65 const char *pName = m_bValidSBValue ? m_rValue.GetName() : nullptr;
66 const CMIUtilString text((pName != nullptr) ? pName : CMIUtilString());
67
68 return text;
69 }
70
71 //++
72 //------------------------------------------------------------------------------------
73 // Details: Retrieve from the LLDB SB Value object the value of the variable
74 // described in
75 // text. If the value is invalid (or the SBValue object invalid) then
76 // "??" is
77 // returned.
78 // Type: Method.
79 // Args: None.
80 // Return: CMIUtilString - Text description of the variable's value or "??".
81 // Throws: None.
82 //--
GetValue(const bool vbExpandAggregates) const83 CMIUtilString CMICmnLLDBUtilSBValue::GetValue(
84 const bool vbExpandAggregates /* = false */) const {
85 if (!m_bValidSBValue)
86 return kUnknownValue;
87
88 CMICmnLLDBDebugSessionInfo &rSessionInfo(
89 CMICmnLLDBDebugSessionInfo::Instance());
90 bool bPrintExpandAggregates = false;
91 bPrintExpandAggregates = rSessionInfo.SharedDataRetrieve<bool>(
92 rSessionInfo.m_constStrPrintExpandAggregates,
93 bPrintExpandAggregates) &&
94 bPrintExpandAggregates;
95
96 const bool bHandleArrayTypeAsSimple =
97 m_bHandleArrayType && !vbExpandAggregates && !bPrintExpandAggregates;
98 CMIUtilString value;
99 const bool bIsSimpleValue = GetSimpleValue(bHandleArrayTypeAsSimple, value);
100 if (bIsSimpleValue)
101 return value;
102
103 if (!vbExpandAggregates && !bPrintExpandAggregates)
104 return kUnresolvedCompositeValue;
105
106 bool bPrintAggregateFieldNames = false;
107 bPrintAggregateFieldNames =
108 !rSessionInfo.SharedDataRetrieve<bool>(
109 rSessionInfo.m_constStrPrintAggregateFieldNames,
110 bPrintAggregateFieldNames) ||
111 bPrintAggregateFieldNames;
112
113 CMICmnMIValueTuple miValueTuple;
114 const bool bOk = GetCompositeValue(bPrintAggregateFieldNames, miValueTuple);
115 if (!bOk)
116 return kUnknownValue;
117
118 value = miValueTuple.GetString();
119 return value;
120 }
121
122 //++
123 //------------------------------------------------------------------------------------
124 // Details: Retrieve from the LLDB SB Value object the value of the variable
125 // described in
126 // text if it has a simple format (not composite).
127 // Type: Method.
128 // Args: vwrValue - (W) The SBValue in a string format.
129 // Return: MIstatus::success - Function succeeded.
130 // MIstatus::failure - Function failed.
131 // Throws: None.
132 //--
GetSimpleValue(const bool vbHandleArrayType,CMIUtilString & vwrValue) const133 bool CMICmnLLDBUtilSBValue::GetSimpleValue(const bool vbHandleArrayType,
134 CMIUtilString &vwrValue) const {
135 const MIuint nChildren = m_rValue.GetNumChildren();
136 if (nChildren == 0) {
137 vwrValue = GetValueSummary(!m_bHandleCharType && IsCharType(), kUnknownValue);
138 return MIstatus::success;
139 } else if (IsPointerType()) {
140 vwrValue =
141 GetValueSummary(!m_bHandleCharType && IsPointeeCharType(), kUnknownValue);
142 return MIstatus::success;
143 } else if (IsArrayType()) {
144 CMICmnLLDBDebugSessionInfo &rSessionInfo(
145 CMICmnLLDBDebugSessionInfo::Instance());
146 bool bPrintCharArrayAsString = false;
147 bPrintCharArrayAsString = rSessionInfo.SharedDataRetrieve<bool>(
148 rSessionInfo.m_constStrPrintCharArrayAsString,
149 bPrintCharArrayAsString) &&
150 bPrintCharArrayAsString;
151 if (bPrintCharArrayAsString && m_bHandleCharType &&
152 IsFirstChildCharType()) {
153 vwrValue = GetValueSummary(false);
154 return MIstatus::success;
155 } else if (vbHandleArrayType) {
156 vwrValue = CMIUtilString::Format("[%u]", nChildren);
157 return MIstatus::success;
158 }
159 } else {
160 // Treat composite value which has registered summary
161 // (for example with AddCXXSummary) as simple value
162 vwrValue = GetValueSummary(false);
163 if (!vwrValue.empty())
164 return MIstatus::success;
165 }
166
167 // Composite variable type i.e. struct
168 return MIstatus::failure;
169 }
170
GetCompositeValue(const bool vbPrintFieldNames,CMICmnMIValueTuple & vwrMiValueTuple,const MIuint vnDepth) const171 bool CMICmnLLDBUtilSBValue::GetCompositeValue(
172 const bool vbPrintFieldNames, CMICmnMIValueTuple &vwrMiValueTuple,
173 const MIuint vnDepth /* = 1 */) const {
174 const MIuint nMaxDepth = 10;
175 const MIuint nChildren = m_rValue.GetNumChildren();
176 for (MIuint i = 0; i < nChildren; ++i) {
177 const lldb::SBValue member = m_rValue.GetChildAtIndex(i);
178 const CMICmnLLDBUtilSBValue utilMember(member, m_bHandleCharType,
179 m_bHandleArrayType);
180 const bool bHandleArrayTypeAsSimple = false;
181 CMIUtilString value;
182 const bool bIsSimpleValue =
183 utilMember.GetSimpleValue(bHandleArrayTypeAsSimple, value);
184 if (bIsSimpleValue) {
185 // OK. Value is simple (not composite) and was successfully got
186 } else if (vnDepth < nMaxDepth) {
187 // Need to get value from composite type
188 CMICmnMIValueTuple miValueTuple;
189 const bool bOk = utilMember.GetCompositeValue(vbPrintFieldNames,
190 miValueTuple, vnDepth + 1);
191 if (!bOk)
192 // Can't obtain composite type
193 value = kUnknownValue;
194 else
195 // OK. Value is composite and was successfully got
196 value = miValueTuple.GetString();
197 } else {
198 // Need to get value from composite type, but vnMaxDepth is reached
199 value = kUnresolvedCompositeValue;
200 }
201 const bool bNoQuotes = true;
202 const CMICmnMIValueConst miValueConst(value, bNoQuotes);
203 if (vbPrintFieldNames) {
204 const bool bUseSpacing = true;
205 const CMICmnMIValueResult miValueResult(utilMember.GetName(),
206 miValueConst, bUseSpacing);
207 vwrMiValueTuple.Add(miValueResult, bUseSpacing);
208 } else {
209 const bool bUseSpacing = false;
210 vwrMiValueTuple.Add(miValueConst, bUseSpacing);
211 }
212 }
213
214 return MIstatus::success;
215 }
216
217 // Returns value or value + summary, depending on valueOnly parameter value.
218 // If result is an empty string returns failVal.
219 CMIUtilString
GetValueSummary(bool valueOnly,const CMIUtilString & failVal) const220 CMICmnLLDBUtilSBValue::GetValueSummary(bool valueOnly,
221 const CMIUtilString &failVal) const {
222 if (!m_rValue.IsValid())
223 return failVal;
224
225 CMIUtilString value, valSummary;
226 const char *c_value = m_rValue.GetValue();
227 if (valueOnly)
228 return c_value == nullptr ? failVal : c_value;
229
230 const char *c_summary = m_rValue.GetSummary();
231 if (c_value)
232 value = c_value;
233 else if (c_summary == nullptr)
234 return failVal;
235
236 if (c_summary && c_summary[0]) {
237 valSummary = c_summary;
238 lldb::SBTypeSummary summary = m_rValue.GetTypeSummary();
239 if (summary.IsValid() && summary.DoesPrintValue(m_rValue) &&
240 !value.empty()) {
241 valSummary.insert(0, value + " ");
242 }
243 return valSummary;
244 }
245 // no summary - return just value
246 return value;
247 }
248
249 //++
250 //------------------------------------------------------------------------------------
251 // Details: Check that basic type is a char type. Char type can be signed or
252 // unsigned.
253 // Type: Static.
254 // Args: eType - type to check
255 // Return: bool - True = Yes is a char type, false = some other type.
256 // Throws: None.
257 //--
IsCharBasicType(lldb::BasicType eType)258 bool CMICmnLLDBUtilSBValue::IsCharBasicType(lldb::BasicType eType) {
259 switch (eType) {
260 case lldb::eBasicTypeChar:
261 case lldb::eBasicTypeSignedChar:
262 case lldb::eBasicTypeUnsignedChar:
263 case lldb::eBasicTypeChar16:
264 case lldb::eBasicTypeChar32:
265 return true;
266 default:
267 return false;
268 }
269 }
270
271 //++
272 //------------------------------------------------------------------------------------
273 // Details: Retrieve the flag stating whether this value object is a char type
274 // or some
275 // other type. Char type can be signed or unsigned.
276 // Type: Method.
277 // Args: None.
278 // Return: bool - True = Yes is a char type, false = some other type.
279 // Throws: None.
280 //--
IsCharType() const281 bool CMICmnLLDBUtilSBValue::IsCharType() const {
282 const lldb::BasicType eType = m_rValue.GetType().GetBasicType();
283 return IsCharBasicType(eType);
284 }
285
286 //++
287 //------------------------------------------------------------------------------------
288 // Details: Retrieve the flag stating whether first child value object of *this
289 // object is
290 // a char type or some other type. Returns false if there are not
291 // children. Char
292 // type can be signed or unsigned.
293 // Type: Method.
294 // Args: None.
295 // Return: bool - True = Yes is a char type, false = some other type.
296 // Throws: None.
297 //--
IsFirstChildCharType() const298 bool CMICmnLLDBUtilSBValue::IsFirstChildCharType() const {
299 const MIuint nChildren = m_rValue.GetNumChildren();
300
301 // Is it a basic type
302 if (nChildren == 0)
303 return false;
304
305 const lldb::SBValue member = m_rValue.GetChildAtIndex(0);
306 const CMICmnLLDBUtilSBValue utilValue(member);
307 return utilValue.IsCharType();
308 }
309
310 //++
311 //------------------------------------------------------------------------------------
312 // Details: Retrieve the flag stating whether pointee object of *this object is
313 // a char type or some other type. Returns false if there are not
314 // children. Char
315 // type can be signed or unsigned.
316 // Type: Method.
317 // Args: None.
318 // Return: bool - True = Yes is a char type, false = some other type.
319 // Throws: None.
320 //--
IsPointeeCharType() const321 bool CMICmnLLDBUtilSBValue::IsPointeeCharType() const {
322 const MIuint nChildren = m_rValue.GetNumChildren();
323
324 // Is it a basic type
325 if (nChildren == 0)
326 return false;
327
328 const lldb::BasicType eType =
329 m_rValue.GetType().GetPointeeType().GetBasicType();
330 return IsCharBasicType(eType);
331 }
332
333 //++
334 //------------------------------------------------------------------------------------
335 // Details: Retrieve the flag stating whether this value object is a integer
336 // type or some
337 // other type. Char type can be signed or unsigned and short or
338 // long/very long.
339 // Type: Method.
340 // Args: None.
341 // Return: bool - True = Yes is a integer type, false = some other type.
342 // Throws: None.
343 //--
IsIntegerType() const344 bool CMICmnLLDBUtilSBValue::IsIntegerType() const {
345 const lldb::BasicType eType = m_rValue.GetType().GetBasicType();
346 return ((eType == lldb::eBasicTypeShort) ||
347 (eType == lldb::eBasicTypeUnsignedShort) ||
348 (eType == lldb::eBasicTypeInt) ||
349 (eType == lldb::eBasicTypeUnsignedInt) ||
350 (eType == lldb::eBasicTypeLong) ||
351 (eType == lldb::eBasicTypeUnsignedLong) ||
352 (eType == lldb::eBasicTypeLongLong) ||
353 (eType == lldb::eBasicTypeUnsignedLongLong) ||
354 (eType == lldb::eBasicTypeInt128) ||
355 (eType == lldb::eBasicTypeUnsignedInt128));
356 }
357
358 //++
359 //------------------------------------------------------------------------------------
360 // Details: Retrieve the flag stating whether this value object is a pointer
361 // type or some
362 // other type.
363 // Type: Method.
364 // Args: None.
365 // Return: bool - True = Yes is a pointer type, false = some other type.
366 // Throws: None.
367 //--
IsPointerType() const368 bool CMICmnLLDBUtilSBValue::IsPointerType() const {
369 return m_rValue.GetType().IsPointerType();
370 }
371
372 //++
373 //------------------------------------------------------------------------------------
374 // Details: Retrieve the flag stating whether this value object is an array type
375 // or some
376 // other type.
377 // Type: Method.
378 // Args: None.
379 // Return: bool - True = Yes is an array type, false = some other type.
380 // Throws: None.
381 //--
IsArrayType() const382 bool CMICmnLLDBUtilSBValue::IsArrayType() const {
383 return m_rValue.GetType().IsArrayType();
384 }
385
386 //++
387 //------------------------------------------------------------------------------------
388 // Details: Retrieve the C string data of value object by read the memory where
389 // the
390 // variable is held.
391 // Type: Method.
392 // Args: vrValue - (R) LLDB SBValue variable object.
393 // Return: CMIUtilString - Text description of the variable's value.
394 // Throws: None.
395 //--
396 template <typename charT>
397 CMIUtilString
ReadCStringFromHostMemory(lldb::SBValue & vrValue,const MIuint vnMaxLen) const398 CMICmnLLDBUtilSBValue::ReadCStringFromHostMemory(lldb::SBValue &vrValue,
399 const MIuint vnMaxLen) const {
400 std::string result;
401 lldb::addr_t addr = vrValue.GetLoadAddress(),
402 end_addr = addr + vnMaxLen * sizeof(charT);
403 lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
404 lldb::SBError error;
405 while (addr < end_addr) {
406 charT ch;
407 const MIuint64 nReadBytes =
408 process.ReadMemory(addr, &ch, sizeof(ch), error);
409 if (error.Fail() || nReadBytes != sizeof(ch))
410 return kUnknownValue;
411 else if (ch == 0)
412 break;
413 result.append(
414 CMIUtilString::ConvertToPrintableASCII(ch, true /* bEscapeQuotes */));
415 addr += sizeof(ch);
416 }
417
418 return result;
419 }
420
421 //++
422 //------------------------------------------------------------------------------------
423 // Details: Retrieve the state of the value object's name.
424 // Type: Method.
425 // Args: None.
426 // Return: bool - True = yes name is indeterminate, false = name is valid.
427 // Throws: None.
428 //--
IsNameUnknown() const429 bool CMICmnLLDBUtilSBValue::IsNameUnknown() const {
430 const CMIUtilString name(GetName());
431 return (name == kUnknownValue);
432 }
433
434 //++
435 //------------------------------------------------------------------------------------
436 // Details: Retrieve the state of the value object's value data.
437 // Type: Method.
438 // Args: None.
439 // Return: bool - True = yes value is indeterminate, false = value valid.
440 // Throws: None.
441 //--
IsValueUnknown() const442 bool CMICmnLLDBUtilSBValue::IsValueUnknown() const {
443 const CMIUtilString value(GetValue());
444 return (value == kUnknownValue);
445 }
446
447 //++
448 //------------------------------------------------------------------------------------
449 // Details: Retrieve the value object's type name if valid.
450 // Type: Method.
451 // Args: None.
452 // Return: CMIUtilString - The type name or "??".
453 // Throws: None.
454 //--
GetTypeName() const455 CMIUtilString CMICmnLLDBUtilSBValue::GetTypeName() const {
456 const char *pName = m_bValidSBValue ? m_rValue.GetTypeName() : nullptr;
457 const CMIUtilString text((pName != nullptr) ? pName : kUnknownValue);
458
459 return text;
460 }
461
462 //++
463 //------------------------------------------------------------------------------------
464 // Details: Retrieve the value object's display type name if valid.
465 // Type: Method.
466 // Args: None.
467 // Return: CMIUtilString - The type name or "??".
468 // Throws: None.
469 //--
GetTypeNameDisplay() const470 CMIUtilString CMICmnLLDBUtilSBValue::GetTypeNameDisplay() const {
471 const char *pName = m_bValidSBValue ? m_rValue.GetDisplayTypeName() : nullptr;
472 const CMIUtilString text((pName != nullptr) ? pName : kUnknownValue);
473
474 return text;
475 }
476
477 //++
478 //------------------------------------------------------------------------------------
479 // Details: Retrieve whether the value object's is valid or not.
480 // Type: Method.
481 // Args: None.
482 // Return: bool - True = valid, false = not valid.
483 // Throws: None.
484 //--
IsValid() const485 bool CMICmnLLDBUtilSBValue::IsValid() const { return m_bValidSBValue; }
486
487 //++
488 //------------------------------------------------------------------------------------
489 // Details: Retrieve the value object' has a name. A value object can be valid
490 // but still
491 // have no name which suggest it is not a variable.
492 // Type: Method.
493 // Args: None.
494 // Return: bool - True = valid, false = not valid.
495 // Throws: None.
496 //--
HasName() const497 bool CMICmnLLDBUtilSBValue::HasName() const {
498 bool bHasAName = false;
499
500 const char *pName = m_bValidSBValue ? m_rValue.GetDisplayTypeName() : nullptr;
501 if (pName != nullptr) {
502 bHasAName = (CMIUtilString(pName).length() > 0);
503 }
504
505 return bHasAName;
506 }
507
508 //++
509 //------------------------------------------------------------------------------------
510 // Details: Determine if the value object' represents a LLDB variable i.e. "$0".
511 // Type: Method.
512 // Args: None.
513 // Return: bool - True = Yes LLDB variable, false = no.
514 // Throws: None.
515 //--
IsLLDBVariable() const516 bool CMICmnLLDBUtilSBValue::IsLLDBVariable() const {
517 return (GetName().at(0) == '$');
518 }
519