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 11 using namespace lldb; 12 using namespace lldb_private; 13 using namespace lldb_private::formatters; 14 15 // 16 // We are supporting two versions of libc++ std::atomic 17 // 18 // Given std::atomic<int> i; 19 // 20 // The previous version of std::atomic was laid out like this 21 // 22 // (lldb) frame var -L -R i 23 // 0x00007ffeefbff9a0: (std::__1::atomic<int>) i = { 24 // 0x00007ffeefbff9a0: std::__1::__atomic_base<int, true> = { 25 // 0x00007ffeefbff9a0: std::__1::__atomic_base<int, false> = { 26 // 0x00007ffeefbff9a0: __a_ = 5 27 // } 28 // } 29 // } 30 // 31 // In this case we need to obtain __a_ and the current version is laid out as so 32 // 33 // (lldb) frame var -L -R i 34 // 0x00007ffeefbff9b0: (std::__1::atomic<int>) i = { 35 // 0x00007ffeefbff9b0: std::__1::__atomic_base<int, true> = { 36 // 0x00007ffeefbff9b0: std::__1::__atomic_base<int, false> = { 37 // 0x00007ffeefbff9b0: __a_ = { 38 // 0x00007ffeefbff9b0: std::__1::__cxx_atomic_base_impl<int> = { 39 // 0x00007ffeefbff9b0: __a_value = 5 40 // } 41 // } 42 // } 43 // } 44 //} 45 // 46 // In this case we need to obtain __a_value 47 // 48 // The below method covers both cases and returns the relevant member as a 49 // ValueObjectSP 50 // 51 ValueObjectSP 52 lldb_private::formatters::GetLibCxxAtomicValue(ValueObject &valobj) { 53 ValueObjectSP non_sythetic = valobj.GetNonSyntheticValue(); 54 if (!non_sythetic) 55 return {}; 56 57 ValueObjectSP member__a_ = 58 non_sythetic->GetChildMemberWithName(ConstString("__a_"), true); 59 if (!member__a_) 60 return {}; 61 62 ValueObjectSP member__a_value = 63 member__a_->GetChildMemberWithName(ConstString("__a_value"), true); 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 lldb::ValueObjectSP GetSyntheticValue() override; 104 105 private: 106 ValueObject *m_real_child; 107 }; 108 } // namespace formatters 109 } // namespace lldb_private 110 111 lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: 112 LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 113 : SyntheticChildrenFrontEnd(*valobj_sp), m_real_child(nullptr) {} 114 115 bool lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::Update() { 116 ValueObjectSP atomic_value = GetLibCxxAtomicValue(m_backend); 117 if (atomic_value) 118 m_real_child = GetLibCxxAtomicValue(m_backend).get(); 119 120 return false; 121 } 122 123 bool lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: 124 MightHaveChildren() { 125 return true; 126 } 127 128 size_t lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: 129 CalculateNumChildren() { 130 return m_real_child ? m_real_child->GetNumChildren() : 0; 131 } 132 133 lldb::ValueObjectSP 134 lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::GetChildAtIndex( 135 size_t idx) { 136 return m_real_child ? m_real_child->GetChildAtIndex(idx, true) : nullptr; 137 } 138 139 size_t lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: 140 GetIndexOfChildWithName(ConstString name) { 141 return m_real_child ? m_real_child->GetIndexOfChildWithName(name) 142 : UINT32_MAX; 143 } 144 145 lldb::ValueObjectSP lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: 146 GetSyntheticValue() { 147 if (m_real_child && m_real_child->CanProvideValue()) 148 return m_real_child->GetSP(); 149 return nullptr; 150 } 151 152 SyntheticChildrenFrontEnd * 153 lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator( 154 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 155 if (valobj_sp) 156 return new LibcxxStdAtomicSyntheticFrontEnd(valobj_sp); 157 return nullptr; 158 } 159