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
14using namespace lldb;
15
16namespace lldb_private {
17namespace formatters {
18
20public:
22
23 llvm::Expected<uint32_t> CalculateNumChildren() override;
24
25 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
26
28
29 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
30
31private:
32 ValueObject *m_map = nullptr;
34
35 size_t m_block_size = 0;
36 size_t m_offset = 0;
37 size_t m_map_size = 0;
38
39 size_t m_element_size = 0;
41
42 uint32_t m_size = 0;
43};
44
45} // namespace formatters
46} // namespace lldb_private
47
54
55llvm::Expected<uint32_t> lldb_private::formatters::
57 if (!m_map)
58 return llvm::createStringError("Failed to read size");
59 return m_size;
60}
61
64 uint32_t idx) {
65 if (idx >= m_size || !m_map)
66 return nullptr;
67 ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
68 if (!process_sp)
69 return nullptr;
70
71 // _EEN_DS = _Block_size
72 // _Map[(($i + _Myoff) / _EEN_DS) % _Mapsize][($i + _Myoff) % _EEN_DS]
73 size_t first_idx = ((idx + m_offset) / m_block_size) % m_map_size;
74 lldb::addr_t first_address = m_map->GetValueAsUnsigned(0) +
75 first_idx * process_sp->GetAddressByteSize();
76
77 Status err;
78 lldb::addr_t second_base =
79 process_sp->ReadPointerFromMemory(first_address, err);
80 if (err.Fail())
81 return nullptr;
82
83 size_t second_idx = (idx + m_offset) % m_block_size;
84 size_t second_address = second_base + second_idx * m_element_size;
85
86 StreamString name;
87 name.Printf("[%" PRIu64 "]", (uint64_t)idx);
88 return CreateValueObjectFromAddress(name.GetString(), second_address,
89 m_backend.GetExecutionContextRef(),
91}
92
95 m_size = 0;
96 m_map = nullptr;
97 m_element_type.Clear();
98
99 ValueObjectSP storage_sp =
100 m_backend.GetChildAtNamePath({"_Mypair", "_Myval2"});
101 if (!storage_sp)
102 return lldb::eRefetch;
103
104 CompilerType deque_type = m_backend.GetCompilerType();
105 if (!deque_type)
106 return lldb::eRefetch;
107
108 CompilerDecl block_size_decl =
109 deque_type.GetStaticFieldWithName("_Block_size");
110 if (!block_size_decl)
111 return lldb::eRefetch;
112 Scalar block_size = block_size_decl.GetConstantValue();
113 if (!block_size.IsValid())
114 return lldb::eRefetch;
115
116 ValueObjectSP offset_sp = storage_sp->GetChildMemberWithName("_Myoff");
117 ValueObjectSP map_size_sp = storage_sp->GetChildMemberWithName("_Mapsize");
118 ValueObjectSP map_sp = storage_sp->GetChildMemberWithName("_Map");
119 ValueObjectSP size_sp = storage_sp->GetChildMemberWithName("_Mysize");
120 if (!offset_sp || !map_size_sp || !map_sp || !size_sp)
121 return lldb::eRefetch;
122
123 bool ok = false;
124 uint64_t offset = offset_sp->GetValueAsUnsigned(0, &ok);
125 if (!ok)
126 return lldb::eRefetch;
127
128 uint64_t map_size = map_size_sp->GetValueAsUnsigned(0, &ok);
129 if (!ok)
130 return lldb::eRefetch;
131
132 uint64_t size = size_sp->GetValueAsUnsigned(0, &ok);
133 if (!ok)
134 return lldb::eRefetch;
135
136 CompilerType element_type = deque_type.GetTypeTemplateArgument(0);
137 if (!element_type) {
138 // PDB doesn't have the template type, so use the type of _Map (T**).
139 element_type = map_sp->GetCompilerType().GetPointeeType().GetPointeeType();
140 if (!element_type)
141 return lldb::eRefetch;
142 }
143 auto element_size = element_type.GetByteSize(nullptr);
144 if (!element_size)
145 return lldb::eRefetch;
146
147 m_map = map_sp.get();
148 m_exe_ctx_ref = m_backend.GetExecutionContextRef();
149 m_block_size = block_size.ULongLong();
150 m_offset = offset;
151 m_map_size = map_size;
152 m_element_size = *element_size;
153 m_element_type = element_type;
154 m_size = size;
155 return lldb::eRefetch;
156}
157
160 if (!m_map)
161 return llvm::createStringError("Type has no child named '%s'",
162 name.AsCString());
163 if (auto optional_idx = ExtractIndexFromString(name.GetCString()))
164 return *optional_idx;
165
166 return llvm::createStringError("Type has no child named '%s'",
167 name.AsCString());
168}
169
171 if (auto valobj_sp = valobj.GetNonSyntheticValue())
172 return valobj_sp->GetChildMemberWithName("_Mypair") != nullptr;
173 return false;
174}
175
179 return new MsvcStlDequeSyntheticFrontEnd(valobj_sp);
180}
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 * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
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:294
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
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
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