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:
47  ValueObject *m_tree = nullptr;
48  size_t m_num_elements = 0;
49  ValueObject *m_next_element = nullptr;
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(),
58  m_elements_cache() {
59  if (valobj_sp)
60  Update();
61 }
62 
65  return m_num_elements;
66 }
67 
68 lldb::ValueObjectSP lldb_private::formatters::
70  if (idx >= CalculateNumChildren())
71  return lldb::ValueObjectSP();
72  if (m_tree == nullptr)
73  return lldb::ValueObjectSP();
74 
75  while (idx >= m_elements_cache.size()) {
76  if (m_next_element == nullptr)
77  return lldb::ValueObjectSP();
78 
79  Status error;
80  ValueObjectSP node_sp = m_next_element->Dereference(error);
81  if (!node_sp || error.Fail())
82  return lldb::ValueObjectSP();
83 
84  ValueObjectSP value_sp =
85  node_sp->GetChildMemberWithName(ConstString("__value_"), true);
86  ValueObjectSP hash_sp =
87  node_sp->GetChildMemberWithName(ConstString("__hash_"), true);
88  if (!hash_sp || !value_sp) {
89  if (!m_element_type) {
90  auto p1_sp = m_backend.GetChildAtNamePath({ConstString("__table_"),
91  ConstString("__p1_")});
92  if (!p1_sp)
93  return nullptr;
94 
95  ValueObjectSP first_sp = nullptr;
96  switch (p1_sp->GetCompilerType().GetNumDirectBaseClasses()) {
97  case 1:
98  // Assume a pre llvm r300140 __compressed_pair implementation:
99  first_sp = p1_sp->GetChildMemberWithName(ConstString("__first_"),
100  true);
101  break;
102  case 2: {
103  // Assume a post llvm r300140 __compressed_pair implementation:
104  ValueObjectSP first_elem_parent_sp =
105  p1_sp->GetChildAtIndex(0, true);
106  first_sp = p1_sp->GetChildMemberWithName(ConstString("__value_"),
107  true);
108  break;
109  }
110  default:
111  return nullptr;
112  }
113 
114  if (!first_sp)
115  return nullptr;
116  m_element_type = first_sp->GetCompilerType();
117  m_element_type = m_element_type.GetTypeTemplateArgument(0);
118  m_element_type = m_element_type.GetPointeeType();
119  m_node_type = m_element_type;
120  m_element_type = m_element_type.GetTypeTemplateArgument(0);
121  std::string name;
122  m_element_type =
123  m_element_type.GetFieldAtIndex(0, name, nullptr, nullptr, nullptr);
124  m_element_type = m_element_type.GetTypedefedType();
125  }
126  if (!m_node_type)
127  return nullptr;
128  node_sp = node_sp->Cast(m_node_type);
129  value_sp = node_sp->GetChildMemberWithName(ConstString("__value_"), true);
130  hash_sp = node_sp->GetChildMemberWithName(ConstString("__hash_"), true);
131  if (!value_sp || !hash_sp)
132  return nullptr;
133  }
134  m_elements_cache.push_back(
135  {value_sp.get(), hash_sp->GetValueAsUnsigned(0)});
136  m_next_element =
137  node_sp->GetChildMemberWithName(ConstString("__next_"), true).get();
138  if (!m_next_element || m_next_element->GetValueAsUnsigned(0) == 0)
139  m_next_element = nullptr;
140  }
141 
142  std::pair<ValueObject *, uint64_t> val_hash = m_elements_cache[idx];
143  if (!val_hash.first)
144  return lldb::ValueObjectSP();
145  StreamString stream;
146  stream.Printf("[%" PRIu64 "]", (uint64_t)idx);
147  DataExtractor data;
148  Status error;
149  val_hash.first->GetData(data, error);
150  if (error.Fail())
151  return lldb::ValueObjectSP();
152  const bool thread_and_frame_only_if_stopped = true;
153  ExecutionContext exe_ctx = val_hash.first->GetExecutionContextRef().Lock(
154  thread_and_frame_only_if_stopped);
155  return CreateValueObjectFromData(stream.GetString(), data, exe_ctx,
156  val_hash.first->GetCompilerType());
157 }
158 
161  m_num_elements = 0;
162  m_next_element = nullptr;
163  m_elements_cache.clear();
164  ValueObjectSP table_sp =
165  m_backend.GetChildMemberWithName(ConstString("__table_"), true);
166  if (!table_sp)
167  return false;
168 
169  ValueObjectSP p2_sp = table_sp->GetChildMemberWithName(
170  ConstString("__p2_"), true);
171  ValueObjectSP num_elements_sp = nullptr;
172  llvm::SmallVector<ConstString, 3> next_path;
173  switch (p2_sp->GetCompilerType().GetNumDirectBaseClasses()) {
174  case 1:
175  // Assume a pre llvm r300140 __compressed_pair implementation:
176  num_elements_sp = p2_sp->GetChildMemberWithName(
177  ConstString("__first_"), true);
178  next_path.append({ConstString("__p1_"), ConstString("__first_"),
179  ConstString("__next_")});
180  break;
181  case 2: {
182  // Assume a post llvm r300140 __compressed_pair implementation:
183  ValueObjectSP first_elem_parent = p2_sp->GetChildAtIndex(0, true);
184  num_elements_sp = first_elem_parent->GetChildMemberWithName(
185  ConstString("__value_"), true);
186  next_path.append({ConstString("__p1_"), ConstString("__value_"),
187  ConstString("__next_")});
188  break;
189  }
190  default:
191  return false;
192  }
193 
194  if (!num_elements_sp)
195  return false;
196 
197  m_tree = table_sp->GetChildAtNamePath(next_path).get();
198  if (m_tree == nullptr)
199  return false;
200 
201  m_num_elements = num_elements_sp->GetValueAsUnsigned(0);
202 
203  if (m_num_elements > 0)
204  m_next_element =
205  table_sp->GetChildAtNamePath(next_path).get();
206  return false;
207 }
208 
211  return true;
212 }
213 
216  return ExtractIndexFromString(name.GetCString());
217 }
218 
221  CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
222  return (valobj_sp ? new LibcxxStdUnorderedMapSyntheticFrontEnd(valobj_sp)
223  : nullptr);
224 }
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:220
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::Update
bool Update() override
Definition: LibCxxUnorderedMap.cpp:160
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:210
lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetChildAtIndex
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override
Definition: LibCxxUnorderedMap.cpp:69
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
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
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:215
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