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
14#include "llvm/Support/ErrorExtras.h"
15
16using namespace lldb;
17
18namespace lldb_private {
19namespace formatters {
20
22public:
24
25 llvm::Expected<uint32_t> CalculateNumChildren() override;
26
27 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
28
30
31 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
32
33private:
34 ValueObject *m_map = nullptr;
36
37 size_t m_block_size = 0;
38 size_t m_offset = 0;
39 size_t m_map_size = 0;
40
41 size_t m_element_size = 0;
43
44 uint32_t m_size = 0;
45};
46
47} // namespace formatters
48} // namespace lldb_private
49
56
57llvm::Expected<uint32_t> lldb_private::formatters::
59 if (!m_map)
60 return llvm::createStringError("failed to read size");
61 return m_size;
62}
63
66 uint32_t idx) {
67 if (idx >= m_size || !m_map)
68 return nullptr;
69 ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
70 if (!process_sp)
71 return nullptr;
72
73 // _EEN_DS = _Block_size
74 // _Map[(($i + _Myoff) / _EEN_DS) % _Mapsize][($i + _Myoff) % _EEN_DS]
75 size_t first_idx = ((idx + m_offset) / m_block_size) % m_map_size;
76 lldb::addr_t first_address = m_map->GetValueAsUnsigned(0) +
77 first_idx * process_sp->GetAddressByteSize();
78
79 Status err;
80 lldb::addr_t second_base =
81 process_sp->ReadPointerFromMemory(first_address, err);
82 if (err.Fail())
83 return nullptr;
84
85 size_t second_idx = (idx + m_offset) % m_block_size;
86 size_t second_address = second_base + second_idx * m_element_size;
87
88 StreamString name;
89 name.Printf("[%" PRIu64 "]", (uint64_t)idx);
90 return CreateChildValueObjectFromAddress(name.GetString(), second_address,
91 m_backend.GetExecutionContextRef(),
93}
94
97 m_size = 0;
98 m_map = nullptr;
99 m_element_type.Clear();
100
101 ValueObjectSP storage_sp =
102 m_backend.GetChildAtNamePath({"_Mypair", "_Myval2"});
103 if (!storage_sp)
104 return lldb::eRefetch;
105
106 CompilerType deque_type = m_backend.GetCompilerType();
107 if (!deque_type)
108 return lldb::eRefetch;
109
110 CompilerDecl block_size_decl =
111 deque_type.GetStaticFieldWithName("_Block_size");
112 if (!block_size_decl)
113 return lldb::eRefetch;
114 Scalar block_size = block_size_decl.GetConstantValue();
115 if (!block_size.IsValid() || block_size <= 0)
116 return lldb::eRefetch;
117
118 ValueObjectSP offset_sp = storage_sp->GetChildMemberWithName("_Myoff");
119 ValueObjectSP map_size_sp = storage_sp->GetChildMemberWithName("_Mapsize");
120 ValueObjectSP map_sp = storage_sp->GetChildMemberWithName("_Map");
121 ValueObjectSP size_sp = storage_sp->GetChildMemberWithName("_Mysize");
122 if (!offset_sp || !map_size_sp || !map_sp || !size_sp)
123 return lldb::eRefetch;
124
125 bool ok = false;
126 uint64_t offset = offset_sp->GetValueAsUnsigned(0, &ok);
127 if (!ok)
128 return lldb::eRefetch;
129
130 uint64_t map_size = map_size_sp->GetValueAsUnsigned(0, &ok);
131 if (!ok || map_size == 0)
132 return lldb::eRefetch;
133
134 uint64_t size = size_sp->GetValueAsUnsigned(0, &ok);
135 if (!ok)
136 return lldb::eRefetch;
137
138 CompilerType element_type = deque_type.GetTypeTemplateArgument(0);
139 if (!element_type) {
140 // PDB doesn't have the template type, so use the type of _Map (T**).
141 element_type = map_sp->GetCompilerType().GetPointeeType().GetPointeeType();
142 if (!element_type)
143 return lldb::eRefetch;
144 }
145 auto element_size_or_err = element_type.GetByteSize(nullptr);
146 if (!element_size_or_err) {
148 element_size_or_err.takeError(),
149 "failed to get deque element byte size: {0}");
150 return lldb::eRefetch;
151 }
152
153 m_map = map_sp.get();
154 m_exe_ctx_ref = m_backend.GetExecutionContextRef();
155 m_block_size = block_size.ULongLong();
156 m_offset = offset;
157 m_map_size = map_size;
158 m_element_size = *element_size_or_err;
159 m_element_type = element_type;
160 m_size = size;
161 return lldb::eRefetch;
162}
163
166 if (!m_map)
167 return llvm::createStringErrorV("type has no child named '{0}'", name);
168 if (auto optional_idx = ExtractIndexFromString(name.GetCString()))
169 return *optional_idx;
170
171 return llvm::createStringErrorV("type has no child named '{0}'", name);
172}
173
175 if (auto valobj_sp = valobj.GetNonSyntheticValue())
176 return valobj_sp->GetChildMemberWithName("_Mypair") != nullptr;
177 return false;
178}
179
183 return new MsvcStlDequeSyntheticFrontEnd(valobj_sp);
184}
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:394
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:134
lldb::ValueObjectSP CreateChildValueObjectFromAddress(llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx, CompilerType type, bool do_deref=true)
SyntheticChildrenFrontEnd(ValueObject &backend)
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.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:327
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