1 //===-- LibCxxAtomic.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 "LibCxxAtomic.h" 10 #include "lldb/DataFormatters/FormattersHelpers.h" 11 12 using namespace lldb; 13 using namespace lldb_private; 14 using namespace lldb_private::formatters; 15 16 // 17 // We are supporting two versions of libc++ std::atomic 18 // 19 // Given std::atomic<int> i; 20 // 21 // The previous version of std::atomic was laid out like this 22 // 23 // (lldb) frame var -L -R i 24 // 0x00007ffeefbff9a0: (std::__1::atomic<int>) i = { 25 // 0x00007ffeefbff9a0: std::__1::__atomic_base<int, true> = { 26 // 0x00007ffeefbff9a0: std::__1::__atomic_base<int, false> = { 27 // 0x00007ffeefbff9a0: __a_ = 5 28 // } 29 // } 30 // } 31 // 32 // In this case we need to obtain __a_ and the current version is laid out as so 33 // 34 // (lldb) frame var -L -R i 35 // 0x00007ffeefbff9b0: (std::__1::atomic<int>) i = { 36 // 0x00007ffeefbff9b0: std::__1::__atomic_base<int, true> = { 37 // 0x00007ffeefbff9b0: std::__1::__atomic_base<int, false> = { 38 // 0x00007ffeefbff9b0: __a_ = { 39 // 0x00007ffeefbff9b0: std::__1::__cxx_atomic_base_impl<int> = { 40 // 0x00007ffeefbff9b0: __a_value = 5 41 // } 42 // } 43 // } 44 // } 45 //} 46 // 47 // In this case we need to obtain __a_value 48 // 49 // The below method covers both cases and returns the relevant member as a 50 // ValueObjectSP 51 // 52 ValueObjectSP 53 lldb_private::formatters::GetLibCxxAtomicValue(ValueObject &valobj) { 54 ValueObjectSP non_sythetic = valobj.GetNonSyntheticValue(); 55 if (!non_sythetic) 56 return {}; 57 58 ValueObjectSP member__a_ = non_sythetic->GetChildMemberWithName("__a_"); 59 if (!member__a_) 60 return {}; 61 62 ValueObjectSP member__a_value = 63 member__a_->GetChildMemberWithName("__a_value"); 64 if (!member__a_value) 65 return member__a_; 66 67 return member__a_value; 68 } 69 70 bool lldb_private::formatters::LibCxxAtomicSummaryProvider( 71 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { 72 73 if (ValueObjectSP atomic_value = GetLibCxxAtomicValue(valobj)) { 74 std::string summary; 75 if (atomic_value->GetSummaryAsCString(summary, options) && 76 summary.size() > 0) { 77 stream.Printf("%s", summary.c_str()); 78 return true; 79 } 80 } 81 82 return false; 83 } 84 85 namespace lldb_private { 86 namespace formatters { 87 class LibcxxStdAtomicSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 88 public: 89 LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 90 91 ~LibcxxStdAtomicSyntheticFrontEnd() override = default; 92 93 size_t CalculateNumChildren() override; 94 95 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; 96 97 bool Update() override; 98 99 bool MightHaveChildren() override; 100 101 size_t GetIndexOfChildWithName(ConstString name) override; 102 103 private: 104 ValueObject *m_real_child = nullptr; 105 }; 106 } // namespace formatters 107 } // namespace lldb_private 108 109 lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: 110 LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 111 : SyntheticChildrenFrontEnd(*valobj_sp) {} 112 113 bool lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::Update() { 114 ValueObjectSP atomic_value = GetLibCxxAtomicValue(m_backend); 115 if (atomic_value) 116 m_real_child = GetLibCxxAtomicValue(m_backend).get(); 117 118 return false; 119 } 120 121 bool lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: 122 MightHaveChildren() { 123 return true; 124 } 125 126 size_t lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: 127 CalculateNumChildren() { 128 return m_real_child ? 1 : 0; 129 } 130 131 lldb::ValueObjectSP 132 lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::GetChildAtIndex( 133 size_t idx) { 134 if (idx == 0) 135 return m_real_child->GetSP()->Clone(ConstString("Value")); 136 return nullptr; 137 } 138 139 size_t lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: 140 GetIndexOfChildWithName(ConstString name) { 141 return name == "Value" ? 0 : UINT32_MAX; 142 } 143 144 SyntheticChildrenFrontEnd * 145 lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator( 146 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 147 if (valobj_sp) 148 return new LibcxxStdAtomicSyntheticFrontEnd(valobj_sp); 149 return nullptr; 150 } 151