17
17
#include " lldb/Utility/Endian.h"
18
18
#include " lldb/Utility/Status.h"
19
19
#include " lldb/Utility/Stream.h"
20
+ #include " lldb/lldb-enumerations.h"
20
21
#include " lldb/lldb-forward.h"
21
22
22
23
using namespace lldb ;
@@ -223,11 +224,10 @@ class LibCxxMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
223
224
224
225
size_t GetIndexOfChildWithName (ConstString name) override ;
225
226
226
- ~LibCxxMapIteratorSyntheticFrontEnd () override ;
227
+ ~LibCxxMapIteratorSyntheticFrontEnd () override = default ;
227
228
228
229
private:
229
- ValueObject *m_pair_ptr;
230
- lldb::ValueObjectSP m_pair_sp;
230
+ ValueObjectSP m_pair_sp = nullptr ;
231
231
};
232
232
} // namespace formatters
233
233
} // namespace lldb_private
@@ -464,125 +464,71 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator(
464
464
465
465
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
466
466
LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp)
467
- : SyntheticChildrenFrontEnd(*valobj_sp), m_pair_ptr(), m_pair_sp() {
467
+ : SyntheticChildrenFrontEnd(*valobj_sp) {
468
468
if (valobj_sp)
469
469
Update ();
470
470
}
471
471
472
472
lldb::ChildCacheState
473
473
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update () {
474
474
m_pair_sp.reset ();
475
- m_pair_ptr = nullptr ;
476
475
477
476
ValueObjectSP valobj_sp = m_backend.GetSP ();
478
477
if (!valobj_sp)
479
478
return lldb::ChildCacheState::eRefetch;
480
479
481
480
TargetSP target_sp (valobj_sp->GetTargetSP ());
482
-
483
481
if (!target_sp)
484
482
return lldb::ChildCacheState::eRefetch;
485
483
486
- // this must be a ValueObject* because it is a child of the ValueObject we
487
- // are producing children for it if were a ValueObjectSP, we would end up
488
- // with a loop (iterator -> synthetic -> child -> parent == iterator) and
489
- // that would in turn leak memory by never allowing the ValueObjects to die
490
- // and free their memory
491
- m_pair_ptr = valobj_sp
492
- ->GetValueForExpressionPath (
493
- " .__i_.__ptr_->__value_" , nullptr , nullptr ,
494
- ValueObject::GetValueForExpressionPathOptions ()
495
- .DontCheckDotVsArrowSyntax ()
496
- .SetSyntheticChildrenTraversal (
497
- ValueObject::GetValueForExpressionPathOptions::
498
- SyntheticChildrenTraversal::None),
499
- nullptr )
500
- .get ();
501
-
502
- if (!m_pair_ptr) {
503
- m_pair_ptr = valobj_sp
504
- ->GetValueForExpressionPath (
505
- " .__i_.__ptr_" , nullptr , nullptr ,
506
- ValueObject::GetValueForExpressionPathOptions ()
507
- .DontCheckDotVsArrowSyntax ()
508
- .SetSyntheticChildrenTraversal (
509
- ValueObject::GetValueForExpressionPathOptions::
510
- SyntheticChildrenTraversal::None),
511
- nullptr )
512
- .get ();
513
- if (m_pair_ptr) {
514
- auto __i_ (valobj_sp->GetChildMemberWithName (" __i_" ));
515
- if (!__i_) {
516
- m_pair_ptr = nullptr ;
517
- return lldb::ChildCacheState::eRefetch;
518
- }
519
- CompilerType pair_type (
520
- __i_->GetCompilerType ().GetTypeTemplateArgument (0 ));
521
- std::string name;
522
- uint64_t bit_offset_ptr;
523
- uint32_t bitfield_bit_size_ptr;
524
- bool is_bitfield_ptr;
525
- pair_type = pair_type.GetFieldAtIndex (
526
- 0 , name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
527
- if (!pair_type) {
528
- m_pair_ptr = nullptr ;
529
- return lldb::ChildCacheState::eRefetch;
530
- }
484
+ // m_backend is a std::map::iterator
485
+ // ...which is a __map_iterator<__tree_iterator<..., __node_pointer, ...>>
486
+ //
487
+ // Then, __map_iterator::__i_ is a __tree_iterator
488
+ auto tree_iter_sp = valobj_sp->GetChildMemberWithName (" __i_" );
489
+ if (!tree_iter_sp)
490
+ return lldb::ChildCacheState::eRefetch;
531
491
532
- auto addr (m_pair_ptr->GetValueAsUnsigned (LLDB_INVALID_ADDRESS));
533
- m_pair_ptr = nullptr ;
534
- if (addr && addr != LLDB_INVALID_ADDRESS) {
535
- auto ts = pair_type.GetTypeSystem ();
536
- auto ast_ctx = ts.dyn_cast_or_null <TypeSystemClang>();
537
- if (!ast_ctx)
538
- return lldb::ChildCacheState::eRefetch;
539
-
540
- // Mimick layout of std::__tree_iterator::__ptr_ and read it in
541
- // from process memory.
542
- //
543
- // The following shows the contiguous block of memory:
544
- //
545
- // +-----------------------------+ class __tree_end_node
546
- // __ptr_ | pointer __left_; |
547
- // +-----------------------------+ class __tree_node_base
548
- // | pointer __right_; |
549
- // | __parent_pointer __parent_; |
550
- // | bool __is_black_; |
551
- // +-----------------------------+ class __tree_node
552
- // | __node_value_type __value_; | <<< our key/value pair
553
- // +-----------------------------+
554
- //
555
- CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier (
556
- llvm::StringRef (),
557
- {{" ptr0" ,
558
- ast_ctx->GetBasicType (lldb::eBasicTypeVoid).GetPointerType ()},
559
- {" ptr1" ,
560
- ast_ctx->GetBasicType (lldb::eBasicTypeVoid).GetPointerType ()},
561
- {" ptr2" ,
562
- ast_ctx->GetBasicType (lldb::eBasicTypeVoid).GetPointerType ()},
563
- {" cw" , ast_ctx->GetBasicType (lldb::eBasicTypeBool)},
564
- {" payload" , pair_type}});
565
- std::optional<uint64_t > size = tree_node_type.GetByteSize (nullptr );
566
- if (!size)
567
- return lldb::ChildCacheState::eRefetch;
568
- WritableDataBufferSP buffer_sp (new DataBufferHeap (*size, 0 ));
569
- ProcessSP process_sp (target_sp->GetProcessSP ());
570
- Status error;
571
- process_sp->ReadMemory (addr, buffer_sp->GetBytes (),
572
- buffer_sp->GetByteSize (), error);
573
- if (error.Fail ())
574
- return lldb::ChildCacheState::eRefetch;
575
- DataExtractor extractor (buffer_sp, process_sp->GetByteOrder (),
576
- process_sp->GetAddressByteSize ());
577
- auto pair_sp = CreateValueObjectFromData (
578
- " pair" , extractor, valobj_sp->GetExecutionContextRef (),
579
- tree_node_type);
580
- if (pair_sp)
581
- m_pair_sp = pair_sp->GetChildAtIndex (4 );
582
- }
583
- }
492
+ // Type is __tree_iterator::__node_pointer
493
+ // (We could alternatively also get this from the template argument)
494
+ auto node_pointer_type =
495
+ tree_iter_sp->GetCompilerType ().GetDirectNestedTypeWithName (
496
+ " __node_pointer" );
497
+ if (!node_pointer_type.IsValid ())
498
+ return lldb::ChildCacheState::eRefetch;
499
+
500
+ // __ptr_ is a __tree_iterator::__iter_pointer
501
+ auto iter_pointer_sp = tree_iter_sp->GetChildMemberWithName (" __ptr_" );
502
+ if (!iter_pointer_sp)
503
+ return lldb::ChildCacheState::eRefetch;
504
+
505
+ // Cast the __iter_pointer to a __node_pointer (which stores our key/value
506
+ // pair)
507
+ auto node_pointer_sp = iter_pointer_sp->Cast (node_pointer_type);
508
+ if (!node_pointer_sp)
509
+ return lldb::ChildCacheState::eRefetch;
510
+
511
+ auto key_value_sp = node_pointer_sp->GetChildMemberWithName (" __value_" );
512
+ if (!key_value_sp)
513
+ return lldb::ChildCacheState::eRefetch;
514
+
515
+ // Create the synthetic child, which is a pair where the key and value can be
516
+ // retrieved by querying the synthetic frontend for
517
+ // GetIndexOfChildWithName("first") and GetIndexOfChildWithName("second")
518
+ // respectively.
519
+ //
520
+ // std::map stores the actual key/value pair in value_type::__cc_ (or
521
+ // previously __cc).
522
+ key_value_sp = key_value_sp->Clone (ConstString (" pair" ));
523
+ if (key_value_sp->GetNumChildrenIgnoringErrors () == 1 ) {
524
+ auto child0_sp = key_value_sp->GetChildAtIndex (0 );
525
+ if (child0_sp &&
526
+ (child0_sp->GetName () == " __cc_" || child0_sp->GetName () == " __cc" ))
527
+ key_value_sp = child0_sp->Clone (ConstString (" pair" ));
584
528
}
585
529
530
+ m_pair_sp = key_value_sp;
531
+
586
532
return lldb::ChildCacheState::eRefetch;
587
533
}
588
534
@@ -594,11 +540,10 @@ llvm::Expected<uint32_t> lldb_private::formatters::
594
540
lldb::ValueObjectSP
595
541
lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex (
596
542
uint32_t idx) {
597
- if (m_pair_ptr)
598
- return m_pair_ptr->GetChildAtIndex (idx);
599
- if (m_pair_sp)
600
- return m_pair_sp->GetChildAtIndex (idx);
601
- return lldb::ValueObjectSP ();
543
+ if (!m_pair_sp)
544
+ return nullptr ;
545
+
546
+ return m_pair_sp->GetChildAtIndex (idx);
602
547
}
603
548
604
549
bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
@@ -608,17 +553,10 @@ bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
608
553
609
554
size_t lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
610
555
GetIndexOfChildWithName (ConstString name) {
611
- if (name == " first" )
612
- return 0 ;
613
- if (name == " second" )
614
- return 1 ;
615
- return UINT32_MAX;
616
- }
556
+ if (!m_pair_sp)
557
+ return UINT32_MAX;
617
558
618
- lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
619
- ~LibCxxMapIteratorSyntheticFrontEnd () {
620
- // this will be deleted when its parent dies (since it's a child object)
621
- // delete m_pair_ptr;
559
+ return m_pair_sp->GetIndexOfChildWithName (name);
622
560
}
623
561
624
562
SyntheticChildrenFrontEnd *
0 commit comments