LLDB mainline
MsvcStlDeque.cpp
Go to the documentation of this file.
1//===-- MsvcStlDeque.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 "MsvcStl.h"
10
13#include "llvm/Support/ErrorExtras.h"
14
15using namespace lldb;
16
17namespace lldb_private {
18namespace formatters {
19
21public:
23
24 llvm::Expected<uint32_t> CalculateNumChildren() override;
25
26 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
27
29
30 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
31
32private:
33 ValueObject *m_map = nullptr;
35
36 size_t m_block_size = 0;
37 size_t m_offset = 0;
38 size_t m_map_size = 0;
39
40 size_t m_element_size = 0;
42
43 uint32_t m_size = 0;
44};
45
46} // namespace formatters
47} // namespace lldb_private
48
55
56llvm::Expected<uint32_t> lldb_private::formatters::
58 if (!m_map)
59 return llvm::createStringError("failed to read size");
60 return m_size;
61}
62
65 uint32_t idx) {
66 if (idx >= m_size || !m_map)
67 return nullptr;
68 ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
69 if (!process_sp)
70 return nullptr;
71
72 // _EEN_DS = _Block_size
73 // _Map[(($i + _Myoff) / _EEN_DS) % _Mapsize][($i + _Myoff) % _EEN_DS]
74 size_t first_idx = ((idx + m_offset) / m_block_size) % m_map_size;
75 lldb::addr_t first_address = m_map->GetValueAsUnsigned(0) +
76 first_idx * process_sp->GetAddressByteSize();
77
78 Status err;
79 lldb::addr_t second_base =
80 process_sp->ReadPointerFromMemory(first_address, err);
81 if (err.Fail())
82 return nullptr;
83
84 size_t second_idx = (idx + m_offset) % m_block_size;
85 size_t second_address = second_base + second_idx * m_element_size;
86
87 StreamString name;
88 name.Printf("[%" PRIu64 "]", (uint64_t)idx);
89 return CreateValueObjectFromAddress(name.GetString(), second_address,
90 m_backend.GetExecutionContextRef(),
92}
93
96 m_size = 0;
97 m_map = nullptr;
98 m_element_type.Clear();
99
100 ValueObjectSP storage_sp =
101 m_backend.GetChildAtNamePath({"_Mypair", "_Myval2"});
102 if (!storage_sp)
103 return lldb::eRefetch;
104
105 CompilerType deque_type = m_backend.GetCompilerType();
106 if (!deque_type)
107 return lldb::eRefetch;
108
109 CompilerDecl block_size_decl =
110 deque_type.GetStaticFieldWithName("_Block_size");
111 if (!block_size_decl)
112 return lldb::eRefetch;
113 Scalar block_size = block_size_decl.GetConstantValue();
114 if (!block_size.IsValid() || block_size <= 0)
115 return lldb::eRefetch;
116
117 ValueObjectSP offset_sp = storage_sp->GetChildMemberWithName("_Myoff");
118 ValueObjectSP map_size_sp = storage_sp->GetChildMemberWithName("_Mapsize");
119 ValueObjectSP map_sp = storage_sp->GetChildMemberWithName("_Map");
120 ValueObjectSP size_sp = storage_sp->GetChildMemberWithName("_Mysize");
121 if (!offset_sp || !map_size_sp || !map_sp || !size_sp)
122 return lldb::eRefetch;
123
124 bool ok = false;
125 uint64_t offset = offset_sp->GetValueAsUnsigned(0, &ok);
126 if (!ok)
127 return lldb::eRefetch;
128
129 uint64_t map_size = map_size_sp->GetValueAsUnsigned(0, &ok);
130 if (!ok || map_size == 0)
131 return lldb::eRefetch;
132
133 uint64_t size = size_sp->GetValueAsUnsigned(0, &ok);
134 if (!ok)
135 return lldb::eRefetch;
136
137 CompilerType element_type = deque_type.GetTypeTemplateArgument(0);
138 if (!element_type) {
139 // PDB doesn't have the template type, so use the type of _Map (T**).
140 element_type = map_sp->GetCompilerType().GetPointeeType().GetPointeeType();
141 if (!element_type)
142 return lldb::eRefetch;
143 }
144 auto element_size = element_type.GetByteSize(nullptr);
145 if (!element_size)
146 return lldb::eRefetch;
147
148 m_map = map_sp.get();
149 m_exe_ctx_ref = m_backend.GetExecutionContextRef();
150 m_block_size = block_size.ULongLong();
151 m_offset = offset;
152 m_map_size = map_size;
153 m_element_size = *element_size;
154 m_element_type = element_type;
155 m_size = size;
156 return lldb::eRefetch;
157}
158
161 if (!m_map)
162 return llvm::createStringErrorV("type has no child named '{0}'", name);
163 if (auto optional_idx = ExtractIndexFromString(name.GetCString()))
164 return *optional_idx;
165
166 return llvm::createStringErrorV("type has no child named '{0}'", name);
167}
168
170 if (auto valobj_sp = valobj.GetNonSyntheticValue())
171 return valobj_sp->GetChildMemberWithName("_Mypair") != nullptr;
172 return false;
173}
174
178 return new MsvcStlDequeSyntheticFrontEnd(valobj_sp);
179}
Represents a generic declaration such as a function declaration.
Scalar GetConstantValue() const
Generic representation of a type in a programming language.
CompilerType GetTypeTemplateArgument(size_t idx, bool expand_pack=false) const
llvm::Expected< uint64_t > GetByteSize(ExecutionContextScope *exe_scope) const
Return the size of the type in bytes.
CompilerDecl GetStaticFieldWithName(llvm::StringRef name) const
A uniqued constant string class.
Definition ConstString.h:40
const char * GetCString() const
Get the string value as a C string.
Execution context objects refer to objects in the execution of the program that is being debugged.
unsigned long long ULongLong(unsigned long long fail_value=0) const
Definition Scalar.cpp:365
bool IsValid() const
Definition Scalar.h:111
An error handling class.
Definition Status.h:118
bool Fail() const
Test for error condition.
Definition Status.cpp:293
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:132
SyntheticChildrenFrontEnd(ValueObject &backend)
lldb::ValueObjectSP CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx, CompilerType type, bool do_deref=true)
virtual lldb::ValueObjectSP GetNonSyntheticValue()
MsvcStlDequeSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
llvm::Expected< uint32_t > CalculateNumChildren() override
llvm::Expected< size_t > GetIndexOfChildWithName(ConstString name) override
Determine the index of a named child.
bool IsMsvcStlDeque(ValueObject &valobj)
std::optional< size_t > ExtractIndexFromString(const char *item_name)
SyntheticChildrenFrontEnd * MsvcStlDequeSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp)
A class that represents a running process on the host machine.
ChildCacheState
Specifies if children need to be re-computed after a call to SyntheticChildrenFrontEnd::Update.
@ eRefetch
Children need to be recomputed dynamically.
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
std::shared_ptr< lldb_private::Process > ProcessSP
uint64_t addr_t
Definition lldb-types.h:80