1 //===-- LibCxxAtomic.cpp ------------------------------------------*- C++ 2 //-*-===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "LibCxxAtomic.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_ = 59 non_sythetic->GetChildMemberWithName(ConstString("__a_"), true); 60 if (!member__a_) 61 return {}; 62 63 ValueObjectSP member__a_value = 64 member__a_->GetChildMemberWithName(ConstString("__a_value"), true); 65 if (!member__a_value) 66 return member__a_; 67 68 return member__a_value; 69 } 70 71 bool lldb_private::formatters::LibCxxAtomicSummaryProvider( 72 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { 73 74 if (ValueObjectSP atomic_value = GetLibCxxAtomicValue(valobj)) { 75 std::string summary; 76 if (atomic_value->GetSummaryAsCString(summary, options) && 77 summary.size() > 0) { 78 stream.Printf("%s", summary.c_str()); 79 return true; 80 } 81 } 82 83 return false; 84 } 85 86 namespace lldb_private { 87 namespace formatters { 88 class LibcxxStdAtomicSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 89 public: 90 LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 91 92 ~LibcxxStdAtomicSyntheticFrontEnd() override = default; 93 94 size_t CalculateNumChildren() override; 95 96 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; 97 98 bool Update() override; 99 100 bool MightHaveChildren() override; 101 102 size_t GetIndexOfChildWithName(ConstString name) override; 103 104 lldb::ValueObjectSP GetSyntheticValue() override; 105 106 private: 107 ValueObject *m_real_child; 108 }; 109 } // namespace formatters 110 } // namespace lldb_private 111 112 lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: 113 LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 114 : SyntheticChildrenFrontEnd(*valobj_sp), m_real_child(nullptr) {} 115 116 bool lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::Update() { 117 ValueObjectSP atomic_value = GetLibCxxAtomicValue(m_backend); 118 if (atomic_value) 119 m_real_child = GetLibCxxAtomicValue(m_backend).get(); 120 121 return false; 122 } 123 124 bool lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: 125 MightHaveChildren() { 126 return true; 127 } 128 129 size_t lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: 130 CalculateNumChildren() { 131 return m_real_child ? m_real_child->GetNumChildren() : 0; 132 } 133 134 lldb::ValueObjectSP 135 lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::GetChildAtIndex( 136 size_t idx) { 137 return m_real_child ? m_real_child->GetChildAtIndex(idx, true) : nullptr; 138 } 139 140 size_t lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: 141 GetIndexOfChildWithName(ConstString name) { 142 return m_real_child ? m_real_child->GetIndexOfChildWithName(name) 143 : UINT32_MAX; 144 } 145 146 lldb::ValueObjectSP lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: 147 GetSyntheticValue() { 148 if (m_real_child && m_real_child->CanProvideValue()) 149 return m_real_child->GetSP(); 150 return nullptr; 151 } 152 153 SyntheticChildrenFrontEnd * 154 lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator( 155 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 156 if (valobj_sp) 157 return new LibcxxStdAtomicSyntheticFrontEnd(valobj_sp); 158 return nullptr; 159 } 160