LLDB mainline
LibStdcppUniquePointer.cpp
Go to the documentation of this file.
1//===-- LibStdcppUniquePointer.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 "LibStdcpp.h"
10
15
16#include <memory>
17#include <vector>
18
19using namespace lldb;
20using namespace lldb_private;
21using namespace lldb_private::formatters;
22
23namespace {
24
25class LibStdcppUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
26public:
27 explicit LibStdcppUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
28
29 llvm::Expected<uint32_t> CalculateNumChildren() override;
30
31 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
32
34
35 bool MightHaveChildren() override;
36
37 size_t GetIndexOfChildWithName(ConstString name) override;
38
39 bool GetSummary(Stream &stream, const TypeSummaryOptions &options);
40
41private:
42 // The lifetime of a ValueObject and all its derivative ValueObjects
43 // (children, clones, etc.) is managed by a ClusterManager. These
44 // objects are only destroyed when every shared pointer to any of them
45 // is destroyed, so we must not store a shared pointer to any ValueObject
46 // derived from our backend ValueObject (since we're in the same cluster).
47 ValueObject* m_ptr_obj = nullptr;
48 ValueObject* m_obj_obj = nullptr;
49 ValueObject* m_del_obj = nullptr;
50
51 ValueObjectSP GetTuple();
52};
53
54} // end of anonymous namespace
55
56LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd(
57 lldb::ValueObjectSP valobj_sp)
58 : SyntheticChildrenFrontEnd(*valobj_sp) {
59 Update();
60}
61
62ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetTuple() {
63 ValueObjectSP valobj_backend_sp = m_backend.GetSP();
64
65 if (!valobj_backend_sp)
66 return nullptr;
67
68 ValueObjectSP valobj_sp = valobj_backend_sp->GetNonSyntheticValue();
69 if (!valobj_sp)
70 return nullptr;
71
72 ValueObjectSP obj_child_sp = valobj_sp->GetChildMemberWithName("_M_t");
73 if (!obj_child_sp)
74 return nullptr;
75
76 ValueObjectSP obj_subchild_sp = obj_child_sp->GetChildMemberWithName("_M_t");
77
78 // if there is a _M_t subchild, the tuple is found in the obj_subchild_sp
79 // (for libstdc++ 6.0.23).
80 if (obj_subchild_sp) {
81 return obj_subchild_sp;
82 }
83
84 return obj_child_sp;
85}
86
87lldb::ChildCacheState LibStdcppUniquePtrSyntheticFrontEnd::Update() {
88 ValueObjectSP tuple_sp = GetTuple();
89
90 if (!tuple_sp)
92
93 std::unique_ptr<SyntheticChildrenFrontEnd> tuple_frontend(
95
96 ValueObjectSP ptr_obj = tuple_frontend->GetChildAtIndex(0);
97 if (ptr_obj)
98 m_ptr_obj = ptr_obj->Clone(ConstString("pointer")).get();
99
100 // Add a 'deleter' child if there was a non-empty deleter type specified.
101 //
102 // The object might have size=1 in the TypeSystem but occupies no dedicated
103 // storage due to no_unique_address, so infer the actual size from the total
104 // size of the unique_ptr class. If sizeof(unique_ptr) == sizeof(void*) then
105 // the deleter is empty and should be hidden.
106 if (tuple_sp->GetByteSize() > ptr_obj->GetByteSize()) {
107 ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1);
108 if (del_obj)
109 m_del_obj = del_obj->Clone(ConstString("deleter")).get();
110 }
111 m_obj_obj = nullptr;
112
114}
115
116bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; }
117
119LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
120 if (idx == 0 && m_ptr_obj)
121 return m_ptr_obj->GetSP();
122 if (idx == 1 && m_del_obj)
123 return m_del_obj->GetSP();
124 if (idx == 2) {
125 if (m_ptr_obj && !m_obj_obj) {
127 ValueObjectSP obj_obj = m_ptr_obj->Dereference(error);
128 if (error.Success()) {
129 m_obj_obj = obj_obj->Clone(ConstString("object")).get();
130 }
131 }
132 if (m_obj_obj)
133 return m_obj_obj->GetSP();
134 }
135 return lldb::ValueObjectSP();
136}
137
138llvm::Expected<uint32_t>
139LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() {
140 if (m_del_obj)
141 return 2;
142 return 1;
143}
144
145size_t LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName(
146 ConstString name) {
147 if (name == "ptr" || name == "pointer")
148 return 0;
149 if (name == "del" || name == "deleter")
150 return 1;
151 if (name == "obj" || name == "object" || name == "$$dereference$$")
152 return 2;
153 return UINT32_MAX;
154}
155
156bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary(
157 Stream &stream, const TypeSummaryOptions &options) {
158 if (!m_ptr_obj)
159 return false;
160
161 bool success;
162 uint64_t ptr_value = m_ptr_obj->GetValueAsUnsigned(0, &success);
163 if (!success)
164 return false;
165 if (ptr_value == 0)
166 stream.Printf("nullptr");
167 else
168 stream.Printf("0x%" PRIx64, ptr_value);
169 return true;
170}
171
175 return (valobj_sp ? new LibStdcppUniquePtrSyntheticFrontEnd(valobj_sp)
176 : nullptr);
177}
178
180 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
181 LibStdcppUniquePtrSyntheticFrontEnd formatter(valobj.GetSP());
182 return formatter.GetSummary(stream, options);
183}
static llvm::raw_ostream & error(Stream &strm)
A uniqued constant string class.
Definition: ConstString.h:40
An error handling class.
Definition: Status.h:44
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:134
virtual lldb::ValueObjectSP GetChildAtIndex(uint32_t idx)=0
virtual lldb::ChildCacheState Update()=0
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
virtual size_t GetIndexOfChildWithName(ConstString name)=0
virtual llvm::Expected< uint32_t > CalculateNumChildren()=0
lldb::ValueObjectSP GetSP()
Definition: ValueObject.h:569
#define UINT32_MAX
Definition: lldb-defines.h:19
SyntheticChildrenFrontEnd * LibStdcppUniquePtrSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
SyntheticChildrenFrontEnd * LibStdcppTupleSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
bool LibStdcppUniquePointerSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
A class that represents a running process on the host machine.
Definition: SBAddress.h:15
ChildCacheState
Specifies if children need to be re-computed after a call to SyntheticChildrenFrontEnd::Update.
@ eRefetch
Children need to be recomputed dynamically.
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Definition: lldb-forward.h:480