LLDB  mainline
LibCxxUnorderedMap.cpp
Go to the documentation of this file.
1 //===-- LibCxxUnorderedMap.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 "LibCxx.h"
10 
12 #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:
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 }
lldb_private::ExecutionContext
Definition: ExecutionContext.h:292
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd
Definition: LibCxxUnorderedMap.cpp:27
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator
SyntheticChildrenFrontEnd * LibcxxStdUnorderedMapSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: LibCxxUnorderedMap.cpp:217
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::m_node_type
CompilerType m_node_type
Definition: LibCxxUnorderedMap.cpp:46
CalculateNumChildren
static size_t CalculateNumChildren(CompilerType container_type, CompilerType element_type, lldb_private::ExecutionContextScope *exe_scope=nullptr)
Definition: VectorType.cpp:169
lldb_private::SyntheticChildrenFrontEnd
Definition: TypeSynthetic.h:27
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::m_num_elements
size_t m_num_elements
Definition: LibCxxUnorderedMap.cpp:48
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::Update
bool Update() override
Definition: LibCxxUnorderedMap.cpp:162
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::m_tree
ValueObject * m_tree
Definition: LibCxxUnorderedMap.cpp:47
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::m_elements_cache
std::vector< std::pair< ValueObject *, uint64_t > > m_elements_cache
Definition: LibCxxUnorderedMap.cpp:50
lldb_private::StreamString::GetString
llvm::StringRef GetString() const
Definition: StreamString.cpp:51
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::MightHaveChildren
bool MightHaveChildren() override
Definition: LibCxxUnorderedMap.cpp:207
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetChildAtIndex
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override
Definition: LibCxxUnorderedMap.cpp:71
Target.h
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::DataExtractor
Definition: DataExtractor.h:48
TypeSystemClang.h
lldb_private::ConstString
Definition: ConstString.h:40
lldb_private::StreamString
Definition: StreamString.h:23
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::m_element_type
CompilerType m_element_type
Definition: LibCxxUnorderedMap.cpp:45
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:40
ValueObject.h
ValueObjectConstResult.h
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::LibcxxStdUnorderedMapSyntheticFrontEnd
LibcxxStdUnorderedMapSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
Definition: LibCxxUnorderedMap.cpp:56
lldb_private::Status
Definition: Status.h:44
lldb_private::ValueObject
ValueObject:
Definition: ValueObject.h:105
UINT32_MAX
#define UINT32_MAX
Definition: lldb-defines.h:31
lldb_private::ConstString::GetCString
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:216
lldb_private::CompilerType
Generic representation of a type in a programming language.
Definition: CompilerType.h:33
lldb_private::Stream::Printf
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
Status.h
lldb_private::formatters
Definition: CXXFunctionPointer.h:15
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::m_next_element
ValueObject * m_next_element
Definition: LibCxxUnorderedMap.cpp:49
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
LibCxx.h
Stream.h
lldb_private::CXXSyntheticChildren
Definition: TypeSynthetic.h:358
FormattersHelpers.h
lldb
Definition: SBAddress.h:15
Endian.h
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetIndexOfChildWithName
size_t GetIndexOfChildWithName(ConstString name) override
Definition: LibCxxUnorderedMap.cpp:212
lldb_private::formatters::ExtractIndexFromString
size_t ExtractIndexFromString(const char *item_name)
Definition: FormattersHelpers.cpp:119
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::CalculateNumChildren
size_t CalculateNumChildren() override
Definition: LibCxxUnorderedMap.cpp:64
DataBufferHeap.h