Coverage Report

Created: 2022-01-18 06:27

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- LibStdcpp.cpp -----------------------------------------------------===//
2
//
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
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "LibStdcpp.h"
10
11
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
12
#include "lldb/Core/ValueObject.h"
13
#include "lldb/Core/ValueObjectConstResult.h"
14
#include "lldb/DataFormatters/StringPrinter.h"
15
#include "lldb/DataFormatters/VectorIterator.h"
16
#include "lldb/Target/Target.h"
17
#include "lldb/Utility/DataBufferHeap.h"
18
#include "lldb/Utility/Endian.h"
19
#include "lldb/Utility/Status.h"
20
#include "lldb/Utility/Stream.h"
21
22
using namespace lldb;
23
using namespace lldb_private;
24
using namespace lldb_private::formatters;
25
26
namespace {
27
28
class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
29
  /*
30
   (std::_Rb_tree_iterator<std::pair<const int, std::basic_string<char,
31
   std::char_traits<char>, std::allocator<char> > > >) ibeg = {
32
   (_Base_ptr) _M_node = 0x0000000100103910 {
33
   (std::_Rb_tree_color) _M_color = _S_black
34
   (std::_Rb_tree_node_base::_Base_ptr) _M_parent = 0x00000001001038c0
35
   (std::_Rb_tree_node_base::_Base_ptr) _M_left = 0x0000000000000000
36
   (std::_Rb_tree_node_base::_Base_ptr) _M_right = 0x0000000000000000
37
   }
38
   }
39
   */
40
41
public:
42
  explicit LibstdcppMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
43
44
  size_t CalculateNumChildren() override;
45
46
  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
47
48
  bool Update() override;
49
50
  bool MightHaveChildren() override;
51
52
  size_t GetIndexOfChildWithName(ConstString name) override;
53
54
private:
55
  ExecutionContextRef m_exe_ctx_ref;
56
  lldb::addr_t m_pair_address;
57
  CompilerType m_pair_type;
58
  lldb::ValueObjectSP m_pair_sp;
59
};
60
61
class LibStdcppSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
62
public:
63
  explicit LibStdcppSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
64
65
  size_t CalculateNumChildren() override;
66
67
  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
68
69
  bool Update() override;
70
71
  bool MightHaveChildren() override;
72
73
  size_t GetIndexOfChildWithName(ConstString name) override;
74
};
75
76
} // end of anonymous namespace
77
78
LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIteratorSyntheticFrontEnd(
79
    lldb::ValueObjectSP valobj_sp)
80
    : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_pair_address(0),
81
0
      m_pair_type(), m_pair_sp() {
82
0
  if (valobj_sp)
83
0
    Update();
84
0
}
85
86
0
bool LibstdcppMapIteratorSyntheticFrontEnd::Update() {
87
0
  ValueObjectSP valobj_sp = m_backend.GetSP();
88
0
  if (!valobj_sp)
89
0
    return false;
90
91
0
  TargetSP target_sp(valobj_sp->GetTargetSP());
92
93
0
  if (!target_sp)
94
0
    return false;
95
96
0
  bool is_64bit = (target_sp->GetArchitecture().GetAddressByteSize() == 8);
97
98
0
  if (!valobj_sp)
99
0
    return false;
100
0
  m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
101
102
0
  ValueObjectSP _M_node_sp(
103
0
      valobj_sp->GetChildMemberWithName(ConstString("_M_node"), true));
104
0
  if (!_M_node_sp)
105
0
    return false;
106
107
0
  m_pair_address = _M_node_sp->GetValueAsUnsigned(0);
108
0
  if (m_pair_address == 0)
109
0
    return false;
110
111
0
  m_pair_address += (is_64bit ? 32 : 16);
112
113
0
  CompilerType my_type(valobj_sp->GetCompilerType());
114
0
  if (my_type.GetNumTemplateArguments() >= 1) {
115
0
    CompilerType pair_type = my_type.GetTypeTemplateArgument(0);
116
0
    if (!pair_type)
117
0
      return false;
118
0
    m_pair_type = pair_type;
119
0
  } else
120
0
    return false;
121
122
0
  return true;
123
0
}
124
125
0
size_t LibstdcppMapIteratorSyntheticFrontEnd::CalculateNumChildren() {
126
0
  return 2;
127
0
}
128
129
lldb::ValueObjectSP
130
0
LibstdcppMapIteratorSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
131
0
  if (m_pair_address != 0 && m_pair_type) {
132
0
    if (!m_pair_sp)
133
0
      m_pair_sp = CreateValueObjectFromAddress("pair", m_pair_address,
134
0
                                               m_exe_ctx_ref, m_pair_type);
135
0
    if (m_pair_sp)
136
0
      return m_pair_sp->GetChildAtIndex(idx, true);
137
0
  }
138
0
  return lldb::ValueObjectSP();
139
0
}
140
141
0
bool LibstdcppMapIteratorSyntheticFrontEnd::MightHaveChildren() { return true; }
142
143
size_t LibstdcppMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName(
144
0
    ConstString name) {
145
0
  if (name == "first")
146
0
    return 0;
147
0
  if (name == "second")
148
0
    return 1;
149
0
  return UINT32_MAX;
150
0
}
151
152
SyntheticChildrenFrontEnd *
153
lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator(
154
0
    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
155
0
  return (valobj_sp ? new LibstdcppMapIteratorSyntheticFrontEnd(valobj_sp)
156
0
                    : nullptr);
157
0
}
158
159
/*
160
 (lldb) fr var ibeg --ptr-depth 1
161
 (__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >)
162
 ibeg = {
163
 _M_current = 0x00000001001037a0 {
164
 *_M_current = 1
165
 }
166
 }
167
 */
168
169
SyntheticChildrenFrontEnd *
170
lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator(
171
0
    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
172
0
  static ConstString g_item_name;
173
0
  if (!g_item_name)
174
0
    g_item_name.SetCString("_M_current");
175
0
  return (valobj_sp
176
0
              ? new VectorIteratorSyntheticFrontEnd(valobj_sp, g_item_name)
177
0
              : nullptr);
178
0
}
179
180
lldb_private::formatters::VectorIteratorSyntheticFrontEnd::
181
    VectorIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp,
182
                                    ConstString item_name)
183
    : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(),
184
39
      m_item_name(item_name), m_item_sp() {
185
39
  if (valobj_sp)
186
39
    Update();
187
39
}
188
189
75
bool VectorIteratorSyntheticFrontEnd::Update() {
190
75
  m_item_sp.reset();
191
192
75
  ValueObjectSP valobj_sp = m_backend.GetSP();
193
75
  if (!valobj_sp)
194
0
    return false;
195
196
75
  if (!valobj_sp)
197
0
    return false;
198
199
75
  ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name, true));
200
75
  if (!item_ptr)
201
0
    return false;
202
75
  if (item_ptr->GetValueAsUnsigned(0) == 0)
203
0
    return false;
204
75
  Status err;
205
75
  m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
206
75
  m_item_sp = CreateValueObjectFromAddress(
207
75
      "item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref,
208
75
      item_ptr->GetCompilerType().GetPointeeType());
209
75
  if (err.Fail())
210
0
    m_item_sp.reset();
211
75
  return false;
212
75
}
213
214
36
size_t VectorIteratorSyntheticFrontEnd::CalculateNumChildren() { return 1; }
215
216
lldb::ValueObjectSP
217
36
VectorIteratorSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
218
36
  if (idx == 0)
219
36
    return m_item_sp;
220
0
  return lldb::ValueObjectSP();
221
36
}
222
223
15
bool VectorIteratorSyntheticFrontEnd::MightHaveChildren() { return true; }
224
225
size_t VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName(
226
0
    ConstString name) {
227
0
  if (name == "item")
228
0
    return 0;
229
0
  return UINT32_MAX;
230
0
}
231
232
bool lldb_private::formatters::LibStdcppStringSummaryProvider(
233
0
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
234
0
  const bool scalar_is_load_addr = true;
235
0
  AddressType addr_type;
236
0
  lldb::addr_t addr_of_string =
237
0
      valobj.GetAddressOf(scalar_is_load_addr, &addr_type);
238
0
  if (addr_of_string != LLDB_INVALID_ADDRESS) {
239
0
    switch (addr_type) {
240
0
    case eAddressTypeLoad: {
241
0
      ProcessSP process_sp(valobj.GetProcessSP());
242
0
      if (!process_sp)
243
0
        return false;
244
245
0
      StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
246
0
      Status error;
247
0
      lldb::addr_t addr_of_data =
248
0
          process_sp->ReadPointerFromMemory(addr_of_string, error);
249
0
      if (error.Fail() || addr_of_data == 0 ||
250
0
          addr_of_data == LLDB_INVALID_ADDRESS)
251
0
        return false;
252
0
      options.SetLocation(addr_of_data);
253
0
      options.SetTargetSP(valobj.GetTargetSP());
254
0
      options.SetStream(&stream);
255
0
      options.SetNeedsZeroTermination(false);
256
0
      options.SetBinaryZeroIsTerminator(true);
257
0
      lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(
258
0
          addr_of_string + process_sp->GetAddressByteSize(), error);
259
0
      if (error.Fail())
260
0
        return false;
261
0
      options.SetSourceSize(size_of_data);
262
0
      options.SetHasSourceSize(true);
263
264
0
      if (!StringPrinter::ReadStringAndDumpToStream<
265
0
              StringPrinter::StringElementType::UTF8>(options)) {
266
0
        stream.Printf("Summary Unavailable");
267
0
        return true;
268
0
      } else
269
0
        return true;
270
0
    } break;
271
0
    case eAddressTypeHost:
272
0
      break;
273
0
    case eAddressTypeInvalid:
274
0
    case eAddressTypeFile:
275
0
      break;
276
0
    }
277
0
  }
278
0
  return false;
279
0
}
280
281
bool lldb_private::formatters::LibStdcppWStringSummaryProvider(
282
0
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
283
0
  const bool scalar_is_load_addr = true;
284
0
  AddressType addr_type;
285
0
  lldb::addr_t addr_of_string =
286
0
      valobj.GetAddressOf(scalar_is_load_addr, &addr_type);
287
0
  if (addr_of_string != LLDB_INVALID_ADDRESS) {
288
0
    switch (addr_type) {
289
0
    case eAddressTypeLoad: {
290
0
      ProcessSP process_sp(valobj.GetProcessSP());
291
0
      if (!process_sp)
292
0
        return false;
293
294
0
      CompilerType wchar_compiler_type =
295
0
          valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar);
296
297
0
      if (!wchar_compiler_type)
298
0
        return false;
299
300
      // Safe to pass nullptr for exe_scope here.
301
0
      llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr);
302
0
      if (!size)
303
0
        return false;
304
0
      const uint32_t wchar_size = *size;
305
306
0
      StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
307
0
      Status error;
308
0
      lldb::addr_t addr_of_data =
309
0
          process_sp->ReadPointerFromMemory(addr_of_string, error);
310
0
      if (error.Fail() || addr_of_data == 0 ||
311
0
          addr_of_data == LLDB_INVALID_ADDRESS)
312
0
        return false;
313
0
      options.SetLocation(addr_of_data);
314
0
      options.SetTargetSP(valobj.GetTargetSP());
315
0
      options.SetStream(&stream);
316
0
      options.SetNeedsZeroTermination(false);
317
0
      options.SetBinaryZeroIsTerminator(false);
318
0
      lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(
319
0
          addr_of_string + process_sp->GetAddressByteSize(), error);
320
0
      if (error.Fail())
321
0
        return false;
322
0
      options.SetSourceSize(size_of_data);
323
0
      options.SetHasSourceSize(true);
324
0
      options.SetPrefixToken("L");
325
326
0
      switch (wchar_size) {
327
0
      case 8:
328
0
        return StringPrinter::ReadStringAndDumpToStream<
329
0
            StringPrinter::StringElementType::UTF8>(options);
330
0
      case 16:
331
0
        return StringPrinter::ReadStringAndDumpToStream<
332
0
            StringPrinter::StringElementType::UTF16>(options);
333
0
      case 32:
334
0
        return StringPrinter::ReadStringAndDumpToStream<
335
0
            StringPrinter::StringElementType::UTF32>(options);
336
0
      default:
337
0
        stream.Printf("size for wchar_t is not valid");
338
0
        return true;
339
0
      }
340
0
      return true;
341
0
    } break;
342
0
    case eAddressTypeHost:
343
0
      break;
344
0
    case eAddressTypeInvalid:
345
0
    case eAddressTypeFile:
346
0
      break;
347
0
    }
348
0
  }
349
0
  return false;
350
0
}
351
352
LibStdcppSharedPtrSyntheticFrontEnd::LibStdcppSharedPtrSyntheticFrontEnd(
353
    lldb::ValueObjectSP valobj_sp)
354
0
    : SyntheticChildrenFrontEnd(*valobj_sp) {
355
0
  if (valobj_sp)
356
0
    Update();
357
0
}
358
359
0
size_t LibStdcppSharedPtrSyntheticFrontEnd::CalculateNumChildren() { return 1; }
360
361
lldb::ValueObjectSP
362
0
LibStdcppSharedPtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
363
0
  ValueObjectSP valobj_sp = m_backend.GetSP();
364
0
  if (!valobj_sp)
365
0
    return lldb::ValueObjectSP();
366
367
0
  if (idx == 0)
368
0
    return valobj_sp->GetChildMemberWithName(ConstString("_M_ptr"), true);
369
0
  else
370
0
    return lldb::ValueObjectSP();
371
0
}
372
373
0
bool LibStdcppSharedPtrSyntheticFrontEnd::Update() { return false; }
374
375
0
bool LibStdcppSharedPtrSyntheticFrontEnd::MightHaveChildren() { return true; }
376
377
size_t LibStdcppSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName(
378
0
    ConstString name) {
379
0
  if (name == "_M_ptr")
380
0
    return 0;
381
0
  return UINT32_MAX;
382
0
}
383
384
SyntheticChildrenFrontEnd *
385
lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator(
386
0
    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
387
0
  return (valobj_sp ? new LibStdcppSharedPtrSyntheticFrontEnd(valobj_sp)
388
0
                    : nullptr);
389
0
}
390
391
bool lldb_private::formatters::LibStdcppSmartPointerSummaryProvider(
392
0
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
393
0
  ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
394
0
  if (!valobj_sp)
395
0
    return false;
396
397
0
  ValueObjectSP ptr_sp(
398
0
      valobj_sp->GetChildMemberWithName(ConstString("_M_ptr"), true));
399
0
  if (!ptr_sp)
400
0
    return false;
401
402
0
  ValueObjectSP usecount_sp(valobj_sp->GetChildAtNamePath(
403
0
      {ConstString("_M_refcount"), ConstString("_M_pi"),
404
0
       ConstString("_M_use_count")}));
405
0
  if (!usecount_sp)
406
0
    return false;
407
408
0
  if (ptr_sp->GetValueAsUnsigned(0) == 0 ||
409
0
      usecount_sp->GetValueAsUnsigned(0) == 0) {
410
0
    stream.Printf("nullptr");
411
0
    return true;
412
0
  }
413
414
0
  Status error;
415
0
  ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
416
0
  if (pointee_sp && error.Success()) {
417
0
    if (pointee_sp->DumpPrintableRepresentation(
418
0
            stream, ValueObject::eValueObjectRepresentationStyleSummary,
419
0
            lldb::eFormatInvalid,
420
0
            ValueObject::PrintableRepresentationSpecialCases::eDisable,
421
0
            false)) {
422
0
      return true;
423
0
    }
424
0
  }
425
426
0
  stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
427
0
  return true;
428
0
}