155 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "LibCxxAtomic.h"10#include "lldb/DataFormatters/FormattersHelpers.h"11 12using namespace lldb;13using namespace lldb_private;14using namespace lldb_private::formatters;15 16//17// We are supporting two versions of libc++ std::atomic18//19// Given std::atomic<int> i;20//21// The previous version of std::atomic was laid out like this22//23// (lldb) frame var -L -R i24// 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_ = 528// }29// }30// }31//32// In this case we need to obtain __a_ and the current version is laid out as so33//34// (lldb) frame var -L -R i35// 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 = 541// }42// }43// }44// }45//}46//47// In this case we need to obtain __a_value48//49// The below method covers both cases and returns the relevant member as a50// ValueObjectSP51//52ValueObjectSP53lldb_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 70bool 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 85namespace lldb_private {86namespace formatters {87class LibcxxStdAtomicSyntheticFrontEnd : public SyntheticChildrenFrontEnd {88public:89 LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);90 91 ~LibcxxStdAtomicSyntheticFrontEnd() override = default;92 93 llvm::Expected<uint32_t> CalculateNumChildren() override;94 95 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;96 97 lldb::ChildCacheState Update() override;98 99 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;100 101private:102 ValueObject *m_real_child = nullptr;103};104} // namespace formatters105} // namespace lldb_private106 107lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::108 LibcxxStdAtomicSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)109 : SyntheticChildrenFrontEnd(*valobj_sp) {}110 111lldb::ChildCacheState112lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::Update() {113 ValueObjectSP atomic_value = GetLibCxxAtomicValue(m_backend);114 if (atomic_value)115 m_real_child = GetLibCxxAtomicValue(m_backend).get();116 117 return lldb::ChildCacheState::eRefetch;118}119 120llvm::Expected<uint32_t> lldb_private::formatters::121 LibcxxStdAtomicSyntheticFrontEnd::CalculateNumChildren() {122 return m_real_child ? 1 : 0;123}124 125lldb::ValueObjectSP126lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::GetChildAtIndex(127 uint32_t idx) {128 if (idx == 0)129 return m_real_child->GetSP()->Clone(ConstString("Value"));130 return nullptr;131}132 133llvm::Expected<size_t>134lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::135 GetIndexOfChildWithName(ConstString name) {136 if (name == "Value")137 return 0;138 return llvm::createStringError("Type has no child named '%s'",139 name.AsCString());140}141 142SyntheticChildrenFrontEnd *143lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator(144 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {145 if (valobj_sp && IsLibCxxAtomic(*valobj_sp))146 return new LibcxxStdAtomicSyntheticFrontEnd(valobj_sp);147 return nullptr;148}149 150bool lldb_private::formatters::IsLibCxxAtomic(ValueObject &valobj) {151 if (auto valobj_sp = valobj.GetNonSyntheticValue())152 return valobj_sp->GetChildMemberWithName("__a_") != nullptr;153 return false;154}155