LLDB  mainline
LibCxxUnorderedMap.cpp
Go to the documentation of this file.
1 //===-- LibCxxUnorderedMap.cpp ----------------------------------*- C++ -*-===//
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 "LibCxx.h"
10 
11 #include "lldb/Core/ValueObject.h"
15 #include "lldb/Target/Target.h"
17 #include "lldb/Utility/Endian.h"
18 #include "lldb/Utility/Status.h"
19 #include "lldb/Utility/Stream.h"
20 
21 using namespace lldb;
22 using namespace lldb_private;
23 using namespace lldb_private::formatters;
24 
25 namespace lldb_private {
26 namespace formatters {
28  : public SyntheticChildrenFrontEnd {
29 public:
30  LibcxxStdUnorderedMapSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
31 
32  ~LibcxxStdUnorderedMapSyntheticFrontEnd() override = default;
33 
34  size_t CalculateNumChildren() override;
35 
36  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
37 
38  bool Update() override;
39 
40  bool MightHaveChildren() override;
41 
42  size_t GetIndexOfChildWithName(ConstString name) override;
43 
44 private:
45  CompilerType m_element_type;
46  CompilerType m_node_type;
47  ValueObject *m_tree;
48  size_t m_num_elements;
49  ValueObject *m_next_element;
50  std::vector<std::pair<ValueObject *, uint64_t>> m_elements_cache;
51 };
52 } // namespace formatters
53 } // namespace lldb_private
54 
56  LibcxxStdUnorderedMapSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
57  : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type(), m_tree(nullptr),
58  m_num_elements(0), m_next_element(nullptr), m_elements_cache() {
59  if (valobj_sp)
60  Update();
61 }
62 
65  if (m_num_elements != UINT32_MAX)
66  return m_num_elements;
67  return 0;
68 }
69 
70 lldb::ValueObjectSP lldb_private::formatters::
72  if (idx >= CalculateNumChildren())
73  return lldb::ValueObjectSP();
74  if (m_tree == nullptr)
75  return lldb::ValueObjectSP();
76 
77  while (idx >= m_elements_cache.size()) {
78  if (m_next_element == nullptr)
79  return lldb::ValueObjectSP();
80 
81  Status error;
82  ValueObjectSP node_sp = m_next_element->Dereference(error);
83  if (!node_sp || error.Fail())
84  return lldb::ValueObjectSP();
85 
86  ValueObjectSP value_sp =
87  node_sp->GetChildMemberWithName(ConstString("__value_"), true);
88  ValueObjectSP hash_sp =
89  node_sp->GetChildMemberWithName(ConstString("__hash_"), true);
90  if (!hash_sp || !value_sp) {
91  if (!m_element_type) {
92  auto p1_sp = m_backend.GetChildAtNamePath({ConstString("__table_"),
93  ConstString("__p1_")});
94  if (!p1_sp)
95  return nullptr;
96 
97  ValueObjectSP first_sp = nullptr;
98  switch (p1_sp->GetCompilerType().GetNumDirectBaseClasses()) {
99  case 1:
100  // Assume a pre llvm r300140 __compressed_pair implementation:
101  first_sp = p1_sp->GetChildMemberWithName(ConstString("__first_"),
102  true);
103  break;
104  case 2: {
105  // Assume a post llvm r300140 __compressed_pair implementation:
106  ValueObjectSP first_elem_parent_sp =
107  p1_sp->GetChildAtIndex(0, true);
108  first_sp = p1_sp->GetChildMemberWithName(ConstString("__value_"),
109  true);
110  break;
111  }
112  default:
113  return nullptr;
114  }
115 
116  if (!first_sp)
117  return nullptr;
118  m_element_type = first_sp->GetCompilerType();
119  m_element_type = m_element_type.GetTypeTemplateArgument(0);
120  m_element_type = m_element_type.GetPointeeType();
121  m_node_type = m_element_type;
122  m_element_type = m_element_type.GetTypeTemplateArgument(0);
123  std::string name;
124  m_element_type =
125  m_element_type.GetFieldAtIndex(0, name, nullptr, nullptr, nullptr);
126  m_element_type = m_element_type.GetTypedefedType();
127  }
128  if (!m_node_type)
129  return nullptr;
130  node_sp = node_sp->Cast(m_node_type);
131  value_sp = node_sp->GetChildMemberWithName(ConstString("__value_"), true);
132  hash_sp = node_sp->GetChildMemberWithName(ConstString("__hash_"), true);
133  if (!value_sp || !hash_sp)
134  return nullptr;
135  }
136  m_elements_cache.push_back(
137  {value_sp.get(), hash_sp->GetValueAsUnsigned(0)});
138  m_next_element =
139  node_sp->GetChildMemberWithName(ConstString("__next_"), true).get();
140  if (!m_next_element || m_next_element->GetValueAsUnsigned(0) == 0)
141  m_next_element = nullptr;
142  }
143 
144  std::pair<ValueObject *, uint64_t> val_hash = m_elements_cache[idx];
145  if (!val_hash.first)
146  return lldb::ValueObjectSP();
147  StreamString stream;
148  stream.Printf("[%" PRIu64 "]", (uint64_t)idx);
149  DataExtractor data;
150  Status error;
151  val_hash.first->GetData(data, error);
152  if (error.Fail())
153  return lldb::ValueObjectSP();
154  const bool thread_and_frame_only_if_stopped = true;
155  ExecutionContext exe_ctx = val_hash.first->GetExecutionContextRef().Lock(
156  thread_and_frame_only_if_stopped);
157  return CreateValueObjectFromData(stream.GetString(), data, exe_ctx,
158  val_hash.first->GetCompilerType());
159 }
160 
163  m_num_elements = UINT32_MAX;
164  m_next_element = nullptr;
165  m_elements_cache.clear();
166  ValueObjectSP table_sp =
167  m_backend.GetChildMemberWithName(ConstString("__table_"), true);
168  if (!table_sp)
169  return false;
170 
171  ValueObjectSP p2_sp = table_sp->GetChildMemberWithName(
172  ConstString("__p2_"), true);
173  ValueObjectSP num_elements_sp = nullptr;
174  llvm::SmallVector<ConstString, 3> next_path;
175  switch (p2_sp->GetCompilerType().GetNumDirectBaseClasses()) {
176  case 1:
177  // Assume a pre llvm r300140 __compressed_pair implementation:
178  num_elements_sp = p2_sp->GetChildMemberWithName(
179  ConstString("__first_"), true);
180  next_path.append({ConstString("__p1_"), ConstString("__first_"),
181  ConstString("__next_")});
182  break;
183  case 2: {
184  // Assume a post llvm r300140 __compressed_pair implementation:
185  ValueObjectSP first_elem_parent = p2_sp->GetChildAtIndex(0, true);
186  num_elements_sp = first_elem_parent->GetChildMemberWithName(
187  ConstString("__value_"), true);
188  next_path.append({ConstString("__p1_"), ConstString("__value_"),
189  ConstString("__next_")});
190  break;
191  }
192  default:
193  return false;
194  }
195 
196  if (!num_elements_sp)
197  return false;
198  m_num_elements = num_elements_sp->GetValueAsUnsigned(0);
199  m_tree = table_sp->GetChildAtNamePath(next_path).get();
200  if (m_num_elements > 0)
201  m_next_element =
202  table_sp->GetChildAtNamePath(next_path).get();
203  return false;
204 }
205 
208  return true;
209 }
210 
213  return ExtractIndexFromString(name.GetCString());
214 }
215 
218  CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
219  return (valobj_sp ? new LibcxxStdUnorderedMapSyntheticFrontEnd(valobj_sp)
220  : nullptr);
221 }
An data extractor class.
Definition: DataExtractor.h:47
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
virtual lldb::ValueObjectSP Dereference(Status &error)
virtual lldb::ValueObjectSP GetChildMemberWithName(ConstString name, bool can_create)
lldb::ValueObjectSP GetChildAtNamePath(llvm::ArrayRef< ConstString > names, ConstString *name_of_error=nullptr)
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
CompilerType GetPointeeType() const
size_t ExtractIndexFromString(const char *item_name)
#define UINT32_MAX
Definition: lldb-defines.h:31
lldb::ValueObjectSP CreateValueObjectFromData(llvm::StringRef name, const DataExtractor &data, const ExecutionContext &exe_ctx, CompilerType type)
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
static size_t CalculateNumChildren(CompilerType container_type, CompilerType element_type, lldb_private::ExecutionContextScope *exe_scope=nullptr)
Definition: VectorType.cpp:168
SyntheticChildrenFrontEnd * LibcxxStdUnorderedMapSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
A uniqued constant string class.
Definition: ConstString.h:38
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:247
virtual uint64_t GetValueAsUnsigned(uint64_t fail_value, bool *success=nullptr)
Definition: SBAddress.h:15
CompilerType GetTypedefedType() const
CompilerType GetTypeTemplateArgument(size_t idx) const
CompilerType GetFieldAtIndex(size_t idx, std::string &name, uint64_t *bit_offset_ptr, uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr) const
An error handling class.
Definition: Status.h:44