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_ = 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 private: 105 ValueObject *m_real_child; 106 }; 107 } // namespace formatters 108 } // namespace lldb_private 109 110 lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: 111 LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 112 : SyntheticChildrenFrontEnd(*valobj_sp), m_real_child(nullptr) {} 113 114 bool lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::Update() { 115 ValueObjectSP atomic_value = GetLibCxxAtomicValue(m_backend); 116 if (atomic_value) 117 m_real_child = GetLibCxxAtomicValue(m_backend).get(); 118 119 return false; 120 } 121 122 bool lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: 123 MightHaveChildren() { 124 return true; 125 } 126 127 size_t lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: 128 CalculateNumChildren() { 129 return m_real_child ? 1 : 0; 130 } 131 132 lldb::ValueObjectSP 133 lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::GetChildAtIndex( 134 size_t idx) { 135 if (idx == 0) 136 return m_real_child->GetSP()->Clone(ConstString("Value")); 137 return nullptr; 138 } 139 140 size_t lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd:: 141 GetIndexOfChildWithName(ConstString name) { 142 return formatters::ExtractIndexFromString(name.GetCString()); 143 } 144 145 SyntheticChildrenFrontEnd * 146 lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator( 147 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 148 if (valobj_sp) 149 return new LibcxxStdAtomicSyntheticFrontEnd(valobj_sp); 150 return nullptr; 151 } 152