Skip to content

Commit fbd1b65

Browse files
authored
[lldb][DataFormatter][NFC] Move std::map iterator formatter into LibCxxMap.cpp (#97687)
The two formatters follow very similar techniques to retrieve data out of the map. We're changing this for `std::map` in #97579 and plan to change it in the same way for the iterator formatter. Having them in the same place will allow us to re-use some of the logic (and we won't have to repeat some of the clarification comments).
1 parent 34fe032 commit fbd1b65

File tree

3 files changed

+191
-213
lines changed

3 files changed

+191
-213
lines changed

lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp

Lines changed: 0 additions & 188 deletions
Original file line numberDiff line numberDiff line change
@@ -202,194 +202,6 @@ bool lldb_private::formatters::LibcxxUniquePointerSummaryProvider(
202202
return true;
203203
}
204204

205-
/*
206-
(lldb) fr var ibeg --raw --ptr-depth 1
207-
(std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::pair<int,
208-
std::__1::basic_string<char, std::__1::char_traits<char>,
209-
std::__1::allocator<char> > >, std::__1::__tree_node<std::__1::pair<int,
210-
std::__1::basic_string<char, std::__1::char_traits<char>,
211-
std::__1::allocator<char> > >, void *> *, long> >) ibeg = {
212-
__i_ = {
213-
__ptr_ = 0x0000000100103870 {
214-
std::__1::__tree_node_base<void *> = {
215-
std::__1::__tree_end_node<std::__1::__tree_node_base<void *> *> = {
216-
__left_ = 0x0000000000000000
217-
}
218-
__right_ = 0x0000000000000000
219-
__parent_ = 0x00000001001038b0
220-
__is_black_ = true
221-
}
222-
__value_ = {
223-
first = 0
224-
second = { std::string }
225-
*/
226-
227-
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
228-
LibCxxMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
229-
: SyntheticChildrenFrontEnd(*valobj_sp), m_pair_ptr(), m_pair_sp() {
230-
if (valobj_sp)
231-
Update();
232-
}
233-
234-
lldb::ChildCacheState
235-
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() {
236-
m_pair_sp.reset();
237-
m_pair_ptr = nullptr;
238-
239-
ValueObjectSP valobj_sp = m_backend.GetSP();
240-
if (!valobj_sp)
241-
return lldb::ChildCacheState::eRefetch;
242-
243-
TargetSP target_sp(valobj_sp->GetTargetSP());
244-
245-
if (!target_sp)
246-
return lldb::ChildCacheState::eRefetch;
247-
248-
// this must be a ValueObject* because it is a child of the ValueObject we
249-
// are producing children for it if were a ValueObjectSP, we would end up
250-
// with a loop (iterator -> synthetic -> child -> parent == iterator) and
251-
// that would in turn leak memory by never allowing the ValueObjects to die
252-
// and free their memory
253-
m_pair_ptr = valobj_sp
254-
->GetValueForExpressionPath(
255-
".__i_.__ptr_->__value_", nullptr, nullptr,
256-
ValueObject::GetValueForExpressionPathOptions()
257-
.DontCheckDotVsArrowSyntax()
258-
.SetSyntheticChildrenTraversal(
259-
ValueObject::GetValueForExpressionPathOptions::
260-
SyntheticChildrenTraversal::None),
261-
nullptr)
262-
.get();
263-
264-
if (!m_pair_ptr) {
265-
m_pair_ptr = valobj_sp
266-
->GetValueForExpressionPath(
267-
".__i_.__ptr_", nullptr, nullptr,
268-
ValueObject::GetValueForExpressionPathOptions()
269-
.DontCheckDotVsArrowSyntax()
270-
.SetSyntheticChildrenTraversal(
271-
ValueObject::GetValueForExpressionPathOptions::
272-
SyntheticChildrenTraversal::None),
273-
nullptr)
274-
.get();
275-
if (m_pair_ptr) {
276-
auto __i_(valobj_sp->GetChildMemberWithName("__i_"));
277-
if (!__i_) {
278-
m_pair_ptr = nullptr;
279-
return lldb::ChildCacheState::eRefetch;
280-
}
281-
CompilerType pair_type(
282-
__i_->GetCompilerType().GetTypeTemplateArgument(0));
283-
std::string name;
284-
uint64_t bit_offset_ptr;
285-
uint32_t bitfield_bit_size_ptr;
286-
bool is_bitfield_ptr;
287-
pair_type = pair_type.GetFieldAtIndex(
288-
0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
289-
if (!pair_type) {
290-
m_pair_ptr = nullptr;
291-
return lldb::ChildCacheState::eRefetch;
292-
}
293-
294-
auto addr(m_pair_ptr->GetValueAsUnsigned(LLDB_INVALID_ADDRESS));
295-
m_pair_ptr = nullptr;
296-
if (addr && addr != LLDB_INVALID_ADDRESS) {
297-
auto ts = pair_type.GetTypeSystem();
298-
auto ast_ctx = ts.dyn_cast_or_null<TypeSystemClang>();
299-
if (!ast_ctx)
300-
return lldb::ChildCacheState::eRefetch;
301-
302-
// Mimick layout of std::__tree_iterator::__ptr_ and read it in
303-
// from process memory.
304-
//
305-
// The following shows the contiguous block of memory:
306-
//
307-
// +-----------------------------+ class __tree_end_node
308-
// __ptr_ | pointer __left_; |
309-
// +-----------------------------+ class __tree_node_base
310-
// | pointer __right_; |
311-
// | __parent_pointer __parent_; |
312-
// | bool __is_black_; |
313-
// +-----------------------------+ class __tree_node
314-
// | __node_value_type __value_; | <<< our key/value pair
315-
// +-----------------------------+
316-
//
317-
CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(
318-
llvm::StringRef(),
319-
{{"ptr0",
320-
ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
321-
{"ptr1",
322-
ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
323-
{"ptr2",
324-
ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
325-
{"cw", ast_ctx->GetBasicType(lldb::eBasicTypeBool)},
326-
{"payload", pair_type}});
327-
std::optional<uint64_t> size = tree_node_type.GetByteSize(nullptr);
328-
if (!size)
329-
return lldb::ChildCacheState::eRefetch;
330-
WritableDataBufferSP buffer_sp(new DataBufferHeap(*size, 0));
331-
ProcessSP process_sp(target_sp->GetProcessSP());
332-
Status error;
333-
process_sp->ReadMemory(addr, buffer_sp->GetBytes(),
334-
buffer_sp->GetByteSize(), error);
335-
if (error.Fail())
336-
return lldb::ChildCacheState::eRefetch;
337-
DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(),
338-
process_sp->GetAddressByteSize());
339-
auto pair_sp = CreateValueObjectFromData(
340-
"pair", extractor, valobj_sp->GetExecutionContextRef(),
341-
tree_node_type);
342-
if (pair_sp)
343-
m_pair_sp = pair_sp->GetChildAtIndex(4);
344-
}
345-
}
346-
}
347-
348-
return lldb::ChildCacheState::eRefetch;
349-
}
350-
351-
llvm::Expected<uint32_t> lldb_private::formatters::
352-
LibCxxMapIteratorSyntheticFrontEnd::CalculateNumChildren() {
353-
return 2;
354-
}
355-
356-
lldb::ValueObjectSP
357-
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex(
358-
uint32_t idx) {
359-
if (m_pair_ptr)
360-
return m_pair_ptr->GetChildAtIndex(idx);
361-
if (m_pair_sp)
362-
return m_pair_sp->GetChildAtIndex(idx);
363-
return lldb::ValueObjectSP();
364-
}
365-
366-
bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
367-
MightHaveChildren() {
368-
return true;
369-
}
370-
371-
size_t lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
372-
GetIndexOfChildWithName(ConstString name) {
373-
if (name == "first")
374-
return 0;
375-
if (name == "second")
376-
return 1;
377-
return UINT32_MAX;
378-
}
379-
380-
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
381-
~LibCxxMapIteratorSyntheticFrontEnd() {
382-
// this will be deleted when its parent dies (since it's a child object)
383-
// delete m_pair_ptr;
384-
}
385-
386-
SyntheticChildrenFrontEnd *
387-
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator(
388-
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
389-
return (valobj_sp ? new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp)
390-
: nullptr);
391-
}
392-
393205
lldb_private::formatters::LibCxxUnorderedMapIteratorSyntheticFrontEnd::
394206
LibCxxUnorderedMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
395207
: SyntheticChildrenFrontEnd(*valobj_sp) {

lldb/source/Plugins/Language/CPlusPlus/LibCxx.h

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -87,31 +87,6 @@ bool LibcxxContainerSummaryProvider(ValueObject &valobj, Stream &stream,
8787
bool LibcxxSpanSummaryProvider(ValueObject &valobj, Stream &stream,
8888
const TypeSummaryOptions &options);
8989

90-
class LibCxxMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
91-
public:
92-
LibCxxMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
93-
94-
llvm::Expected<uint32_t> CalculateNumChildren() override;
95-
96-
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
97-
98-
lldb::ChildCacheState Update() override;
99-
100-
bool MightHaveChildren() override;
101-
102-
size_t GetIndexOfChildWithName(ConstString name) override;
103-
104-
~LibCxxMapIteratorSyntheticFrontEnd() override;
105-
106-
private:
107-
ValueObject *m_pair_ptr;
108-
lldb::ValueObjectSP m_pair_sp;
109-
};
110-
111-
SyntheticChildrenFrontEnd *
112-
LibCxxMapIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *,
113-
lldb::ValueObjectSP);
114-
11590
/// Formats libcxx's std::unordered_map iterators
11691
///
11792
/// In raw form a std::unordered_map::iterator is represented as follows:
@@ -247,6 +222,10 @@ SyntheticChildrenFrontEnd *
247222
LibcxxStdMapSyntheticFrontEndCreator(CXXSyntheticChildren *,
248223
lldb::ValueObjectSP);
249224

225+
SyntheticChildrenFrontEnd *
226+
LibCxxMapIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *,
227+
lldb::ValueObjectSP);
228+
250229
SyntheticChildrenFrontEnd *
251230
LibcxxStdUnorderedMapSyntheticFrontEndCreator(CXXSyntheticChildren *,
252231
lldb::ValueObjectSP);

0 commit comments

Comments
 (0)