180814287SRaphael Isemann //===-- LibCxxList.cpp ----------------------------------------------------===//
233e97e63SEnrico Granata //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
633e97e63SEnrico Granata //
733e97e63SEnrico Granata //===----------------------------------------------------------------------===//
833e97e63SEnrico Granata
933e97e63SEnrico Granata #include "LibCxx.h"
1033e97e63SEnrico Granata
118be30215SAlex Langford #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
1233e97e63SEnrico Granata #include "lldb/Core/ValueObject.h"
1333e97e63SEnrico Granata #include "lldb/Core/ValueObjectConstResult.h"
1433e97e63SEnrico Granata #include "lldb/DataFormatters/FormattersHelpers.h"
1533e97e63SEnrico Granata #include "lldb/Target/Target.h"
16666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h"
1701c3243fSZachary Turner #include "lldb/Utility/Endian.h"
1897206d57SZachary Turner #include "lldb/Utility/Status.h"
19bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
2033e97e63SEnrico Granata
2133e97e63SEnrico Granata using namespace lldb;
2233e97e63SEnrico Granata using namespace lldb_private;
2333e97e63SEnrico Granata using namespace lldb_private::formatters;
2433e97e63SEnrico Granata
2565a16e56SPavel Labath namespace {
2633e97e63SEnrico Granata
27b9c1b51eSKate Stone class ListEntry {
2833e97e63SEnrico Granata public:
298d15f33bSEugene Zelenko ListEntry() = default;
ListEntry(ValueObjectSP entry_sp)306dc2a6a8SDavid Blaikie ListEntry(ValueObjectSP entry_sp) : m_entry_sp(std::move(entry_sp)) {}
ListEntry(ValueObject * entry)31b9c1b51eSKate Stone ListEntry(ValueObject *entry)
32b9c1b51eSKate Stone : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}
3333e97e63SEnrico Granata
next()34b9c1b51eSKate Stone ListEntry next() {
35e555763fSEnrico Granata static ConstString g_next("__next_");
36e555763fSEnrico Granata
3733e97e63SEnrico Granata if (!m_entry_sp)
3833e97e63SEnrico Granata return ListEntry();
39e555763fSEnrico Granata return ListEntry(m_entry_sp->GetChildMemberWithName(g_next, true));
4033e97e63SEnrico Granata }
4133e97e63SEnrico Granata
prev()42b9c1b51eSKate Stone ListEntry prev() {
43e555763fSEnrico Granata static ConstString g_prev("__prev_");
44e555763fSEnrico Granata
4533e97e63SEnrico Granata if (!m_entry_sp)
4633e97e63SEnrico Granata return ListEntry();
47e555763fSEnrico Granata return ListEntry(m_entry_sp->GetChildMemberWithName(g_prev, true));
4833e97e63SEnrico Granata }
4933e97e63SEnrico Granata
value() const50b9c1b51eSKate Stone uint64_t value() const {
5133e97e63SEnrico Granata if (!m_entry_sp)
5233e97e63SEnrico Granata return 0;
5333e97e63SEnrico Granata return m_entry_sp->GetValueAsUnsigned(0);
5433e97e63SEnrico Granata }
5533e97e63SEnrico Granata
null()56b9c1b51eSKate Stone bool null() { return (value() == 0); }
5733e97e63SEnrico Granata
operator bool()58b9c1b51eSKate Stone explicit operator bool() { return GetEntry() && !null(); }
5933e97e63SEnrico Granata
GetEntry()60b9c1b51eSKate Stone ValueObjectSP GetEntry() { return m_entry_sp; }
6133e97e63SEnrico Granata
SetEntry(ValueObjectSP entry)62b9c1b51eSKate Stone void SetEntry(ValueObjectSP entry) { m_entry_sp = entry; }
6333e97e63SEnrico Granata
operator ==(const ListEntry & rhs) const64b9c1b51eSKate Stone bool operator==(const ListEntry &rhs) const { return value() == rhs.value(); }
6565a16e56SPavel Labath
operator !=(const ListEntry & rhs) const66b9c1b51eSKate Stone bool operator!=(const ListEntry &rhs) const { return !(*this == rhs); }
6733e97e63SEnrico Granata
6833e97e63SEnrico Granata private:
6933e97e63SEnrico Granata ValueObjectSP m_entry_sp;
7033e97e63SEnrico Granata };
7133e97e63SEnrico Granata
72b9c1b51eSKate Stone class ListIterator {
7333e97e63SEnrico Granata public:
748d15f33bSEugene Zelenko ListIterator() = default;
ListIterator(ListEntry entry)756dc2a6a8SDavid Blaikie ListIterator(ListEntry entry) : m_entry(std::move(entry)) {}
ListIterator(ValueObjectSP entry)766dc2a6a8SDavid Blaikie ListIterator(ValueObjectSP entry) : m_entry(std::move(entry)) {}
ListIterator(ValueObject * entry)7733e97e63SEnrico Granata ListIterator(ValueObject *entry) : m_entry(entry) {}
7833e97e63SEnrico Granata
value()79b9c1b51eSKate Stone ValueObjectSP value() { return m_entry.GetEntry(); }
8033e97e63SEnrico Granata
advance(size_t count)81b9c1b51eSKate Stone ValueObjectSP advance(size_t count) {
8233e97e63SEnrico Granata if (count == 0)
8333e97e63SEnrico Granata return m_entry.GetEntry();
84b9c1b51eSKate Stone if (count == 1) {
8533e97e63SEnrico Granata next();
8633e97e63SEnrico Granata return m_entry.GetEntry();
8733e97e63SEnrico Granata }
88b9c1b51eSKate Stone while (count > 0) {
8933e97e63SEnrico Granata next();
9033e97e63SEnrico Granata count--;
9133e97e63SEnrico Granata if (m_entry.null())
9233e97e63SEnrico Granata return lldb::ValueObjectSP();
9333e97e63SEnrico Granata }
9433e97e63SEnrico Granata return m_entry.GetEntry();
9533e97e63SEnrico Granata }
9633e97e63SEnrico Granata
operator ==(const ListIterator & rhs) const97b9c1b51eSKate Stone bool operator==(const ListIterator &rhs) const {
9833e97e63SEnrico Granata return (rhs.m_entry == m_entry);
9933e97e63SEnrico Granata }
10033e97e63SEnrico Granata
10133e97e63SEnrico Granata protected:
next()102b9c1b51eSKate Stone void next() { m_entry = m_entry.next(); }
10333e97e63SEnrico Granata
prev()104b9c1b51eSKate Stone void prev() { m_entry = m_entry.prev(); }
1058d15f33bSEugene Zelenko
10633e97e63SEnrico Granata private:
10733e97e63SEnrico Granata ListEntry m_entry;
10833e97e63SEnrico Granata };
10933e97e63SEnrico Granata
11089ac0c7dSPavel Labath class AbstractListFrontEnd : public SyntheticChildrenFrontEnd {
11126935d9aSEnrico Granata public:
GetIndexOfChildWithName(ConstString name)1120e4c4821SAdrian Prantl size_t GetIndexOfChildWithName(ConstString name) override {
11389ac0c7dSPavel Labath return ExtractIndexFromString(name.GetCString());
11489ac0c7dSPavel Labath }
MightHaveChildren()11589ac0c7dSPavel Labath bool MightHaveChildren() override { return true; }
11689ac0c7dSPavel Labath bool Update() override;
11726935d9aSEnrico Granata
11889ac0c7dSPavel Labath protected:
AbstractListFrontEnd(ValueObject & valobj)11989ac0c7dSPavel Labath AbstractListFrontEnd(ValueObject &valobj)
12089ac0c7dSPavel Labath : SyntheticChildrenFrontEnd(valobj) {}
12189ac0c7dSPavel Labath
122*459cfa5eSSlava Gurevich size_t m_count = 0;
123*459cfa5eSSlava Gurevich ValueObject *m_head = nullptr;
12489ac0c7dSPavel Labath
12589ac0c7dSPavel Labath static constexpr bool g_use_loop_detect = true;
126*459cfa5eSSlava Gurevich size_t m_loop_detected = 0; // The number of elements that have had loop
127*459cfa5eSSlava Gurevich // detection run over them.
12889ac0c7dSPavel Labath ListEntry m_slow_runner; // Used for loop detection
12989ac0c7dSPavel Labath ListEntry m_fast_runner; // Used for loop detection
13089ac0c7dSPavel Labath
131*459cfa5eSSlava Gurevich size_t m_list_capping_size = 0;
13289ac0c7dSPavel Labath CompilerType m_element_type;
13389ac0c7dSPavel Labath std::map<size_t, ListIterator> m_iterators;
13489ac0c7dSPavel Labath
13589ac0c7dSPavel Labath bool HasLoop(size_t count);
13689ac0c7dSPavel Labath ValueObjectSP GetItem(size_t idx);
13789ac0c7dSPavel Labath };
13889ac0c7dSPavel Labath
13989ac0c7dSPavel Labath class ForwardListFrontEnd : public AbstractListFrontEnd {
14089ac0c7dSPavel Labath public:
14189ac0c7dSPavel Labath ForwardListFrontEnd(ValueObject &valobj);
14289ac0c7dSPavel Labath
14389ac0c7dSPavel Labath size_t CalculateNumChildren() override;
14489ac0c7dSPavel Labath ValueObjectSP GetChildAtIndex(size_t idx) override;
14589ac0c7dSPavel Labath bool Update() override;
14689ac0c7dSPavel Labath };
14789ac0c7dSPavel Labath
14889ac0c7dSPavel Labath class ListFrontEnd : public AbstractListFrontEnd {
14989ac0c7dSPavel Labath public:
15089ac0c7dSPavel Labath ListFrontEnd(lldb::ValueObjectSP valobj_sp);
15189ac0c7dSPavel Labath
15289ac0c7dSPavel Labath ~ListFrontEnd() override = default;
15326935d9aSEnrico Granata
154b9c1b51eSKate Stone size_t CalculateNumChildren() override;
15526935d9aSEnrico Granata
156b9c1b51eSKate Stone lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
15726935d9aSEnrico Granata
158b9c1b51eSKate Stone bool Update() override;
15926935d9aSEnrico Granata
16026935d9aSEnrico Granata private:
16128c878aeSShafik Yaghmour lldb::addr_t m_node_address = 0;
16228c878aeSShafik Yaghmour ValueObject *m_tail = nullptr;
16326935d9aSEnrico Granata };
16426935d9aSEnrico Granata
16589ac0c7dSPavel Labath } // end anonymous namespace
16689ac0c7dSPavel Labath
Update()16789ac0c7dSPavel Labath bool AbstractListFrontEnd::Update() {
16889ac0c7dSPavel Labath m_loop_detected = 0;
16989ac0c7dSPavel Labath m_count = UINT32_MAX;
17089ac0c7dSPavel Labath m_head = nullptr;
17189ac0c7dSPavel Labath m_list_capping_size = 0;
17289ac0c7dSPavel Labath m_slow_runner.SetEntry(nullptr);
17389ac0c7dSPavel Labath m_fast_runner.SetEntry(nullptr);
17489ac0c7dSPavel Labath m_iterators.clear();
17589ac0c7dSPavel Labath
17689ac0c7dSPavel Labath if (m_backend.GetTargetSP())
17789ac0c7dSPavel Labath m_list_capping_size =
17889ac0c7dSPavel Labath m_backend.GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
17989ac0c7dSPavel Labath if (m_list_capping_size == 0)
18089ac0c7dSPavel Labath m_list_capping_size = 255;
18189ac0c7dSPavel Labath
18289ac0c7dSPavel Labath CompilerType list_type = m_backend.GetCompilerType();
18389ac0c7dSPavel Labath if (list_type.IsReferenceType())
18489ac0c7dSPavel Labath list_type = list_type.GetNonReferenceType();
18589ac0c7dSPavel Labath
18689ac0c7dSPavel Labath if (list_type.GetNumTemplateArguments() == 0)
18789ac0c7dSPavel Labath return false;
188769b21eaSPavel Labath m_element_type = list_type.GetTypeTemplateArgument(0);
18989ac0c7dSPavel Labath
19089ac0c7dSPavel Labath return false;
19133e97e63SEnrico Granata }
19233e97e63SEnrico Granata
HasLoop(size_t count)19389ac0c7dSPavel Labath bool AbstractListFrontEnd::HasLoop(size_t count) {
194bbd16815SEugene Zelenko if (!g_use_loop_detect)
19533e97e63SEnrico Granata return false;
19633e97e63SEnrico Granata // don't bother checking for a loop if we won't actually need to jump nodes
19733e97e63SEnrico Granata if (m_count < 2)
19833e97e63SEnrico Granata return false;
19965a16e56SPavel Labath
200b9c1b51eSKate Stone if (m_loop_detected == 0) {
201b9c1b51eSKate Stone // This is the first time we are being run (after the last update). Set up
20205097246SAdrian Prantl // the loop invariant for the first element.
20365a16e56SPavel Labath m_slow_runner = ListEntry(m_head).next();
20465a16e56SPavel Labath m_fast_runner = m_slow_runner.next();
20565a16e56SPavel Labath m_loop_detected = 1;
20633e97e63SEnrico Granata }
20765a16e56SPavel Labath
20865a16e56SPavel Labath // Loop invariant:
209b9c1b51eSKate Stone // Loop detection has been run over the first m_loop_detected elements. If
21005097246SAdrian Prantl // m_slow_runner == m_fast_runner then the loop has been detected after
21105097246SAdrian Prantl // m_loop_detected elements.
21265a16e56SPavel Labath const size_t steps_to_run = std::min(count, m_count);
213b9c1b51eSKate Stone while (m_loop_detected < steps_to_run && m_slow_runner && m_fast_runner &&
214b9c1b51eSKate Stone m_slow_runner != m_fast_runner) {
21565a16e56SPavel Labath
21665a16e56SPavel Labath m_slow_runner = m_slow_runner.next();
21765a16e56SPavel Labath m_fast_runner = m_fast_runner.next().next();
21865a16e56SPavel Labath m_loop_detected++;
21965a16e56SPavel Labath }
22065a16e56SPavel Labath if (count <= m_loop_detected)
22165a16e56SPavel Labath return false; // No loop in the first m_loop_detected elements.
22265a16e56SPavel Labath if (!m_slow_runner || !m_fast_runner)
22365a16e56SPavel Labath return false; // Reached the end of the list. Definitely no loops.
22465a16e56SPavel Labath return m_slow_runner == m_fast_runner;
22533e97e63SEnrico Granata }
22633e97e63SEnrico Granata
GetItem(size_t idx)22789ac0c7dSPavel Labath ValueObjectSP AbstractListFrontEnd::GetItem(size_t idx) {
22889ac0c7dSPavel Labath size_t advance = idx;
22989ac0c7dSPavel Labath ListIterator current(m_head);
23089ac0c7dSPavel Labath if (idx > 0) {
23189ac0c7dSPavel Labath auto cached_iterator = m_iterators.find(idx - 1);
23289ac0c7dSPavel Labath if (cached_iterator != m_iterators.end()) {
23389ac0c7dSPavel Labath current = cached_iterator->second;
23489ac0c7dSPavel Labath advance = 1;
23589ac0c7dSPavel Labath }
23689ac0c7dSPavel Labath }
23789ac0c7dSPavel Labath ValueObjectSP value_sp = current.advance(advance);
23889ac0c7dSPavel Labath m_iterators[idx] = current;
23989ac0c7dSPavel Labath return value_sp;
24089ac0c7dSPavel Labath }
24189ac0c7dSPavel Labath
ForwardListFrontEnd(ValueObject & valobj)24289ac0c7dSPavel Labath ForwardListFrontEnd::ForwardListFrontEnd(ValueObject &valobj)
24389ac0c7dSPavel Labath : AbstractListFrontEnd(valobj) {
24489ac0c7dSPavel Labath Update();
24589ac0c7dSPavel Labath }
24689ac0c7dSPavel Labath
CalculateNumChildren()24789ac0c7dSPavel Labath size_t ForwardListFrontEnd::CalculateNumChildren() {
24889ac0c7dSPavel Labath if (m_count != UINT32_MAX)
24989ac0c7dSPavel Labath return m_count;
25089ac0c7dSPavel Labath
25189ac0c7dSPavel Labath ListEntry current(m_head);
25289ac0c7dSPavel Labath m_count = 0;
25389ac0c7dSPavel Labath while (current && m_count < m_list_capping_size) {
25489ac0c7dSPavel Labath ++m_count;
25589ac0c7dSPavel Labath current = current.next();
25689ac0c7dSPavel Labath }
25789ac0c7dSPavel Labath return m_count;
25889ac0c7dSPavel Labath }
25989ac0c7dSPavel Labath
GetChildAtIndex(size_t idx)26089ac0c7dSPavel Labath ValueObjectSP ForwardListFrontEnd::GetChildAtIndex(size_t idx) {
26189ac0c7dSPavel Labath if (idx >= CalculateNumChildren())
26289ac0c7dSPavel Labath return nullptr;
26389ac0c7dSPavel Labath
26489ac0c7dSPavel Labath if (!m_head)
26589ac0c7dSPavel Labath return nullptr;
26689ac0c7dSPavel Labath
26789ac0c7dSPavel Labath if (HasLoop(idx + 1))
26889ac0c7dSPavel Labath return nullptr;
26989ac0c7dSPavel Labath
27089ac0c7dSPavel Labath ValueObjectSP current_sp = GetItem(idx);
27189ac0c7dSPavel Labath if (!current_sp)
27289ac0c7dSPavel Labath return nullptr;
27389ac0c7dSPavel Labath
27489ac0c7dSPavel Labath current_sp = current_sp->GetChildAtIndex(1, true); // get the __value_ child
27589ac0c7dSPavel Labath if (!current_sp)
27689ac0c7dSPavel Labath return nullptr;
27789ac0c7dSPavel Labath
27889ac0c7dSPavel Labath // we need to copy current_sp into a new object otherwise we will end up with
27989ac0c7dSPavel Labath // all items named __value_
28089ac0c7dSPavel Labath DataExtractor data;
28189ac0c7dSPavel Labath Status error;
28289ac0c7dSPavel Labath current_sp->GetData(data, error);
28389ac0c7dSPavel Labath if (error.Fail())
28489ac0c7dSPavel Labath return nullptr;
28589ac0c7dSPavel Labath
28689ac0c7dSPavel Labath return CreateValueObjectFromData(llvm::formatv("[{0}]", idx).str(), data,
28789ac0c7dSPavel Labath m_backend.GetExecutionContextRef(),
28889ac0c7dSPavel Labath m_element_type);
28989ac0c7dSPavel Labath }
29089ac0c7dSPavel Labath
Update()29189ac0c7dSPavel Labath bool ForwardListFrontEnd::Update() {
29289ac0c7dSPavel Labath AbstractListFrontEnd::Update();
29389ac0c7dSPavel Labath
29489ac0c7dSPavel Labath Status err;
29589ac0c7dSPavel Labath ValueObjectSP backend_addr(m_backend.AddressOf(err));
29689ac0c7dSPavel Labath if (err.Fail() || !backend_addr)
29789ac0c7dSPavel Labath return false;
29889ac0c7dSPavel Labath
29989ac0c7dSPavel Labath ValueObjectSP impl_sp(
30089ac0c7dSPavel Labath m_backend.GetChildMemberWithName(ConstString("__before_begin_"), true));
30189ac0c7dSPavel Labath if (!impl_sp)
30289ac0c7dSPavel Labath return false;
303a567d680Sshafik impl_sp = GetValueOfLibCXXCompressedPair(*impl_sp);
30489ac0c7dSPavel Labath if (!impl_sp)
30589ac0c7dSPavel Labath return false;
30689ac0c7dSPavel Labath m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get();
30789ac0c7dSPavel Labath return false;
30889ac0c7dSPavel Labath }
30989ac0c7dSPavel Labath
ListFrontEnd(lldb::ValueObjectSP valobj_sp)31089ac0c7dSPavel Labath ListFrontEnd::ListFrontEnd(lldb::ValueObjectSP valobj_sp)
31128c878aeSShafik Yaghmour : AbstractListFrontEnd(*valobj_sp) {
31289ac0c7dSPavel Labath if (valobj_sp)
31389ac0c7dSPavel Labath Update();
31489ac0c7dSPavel Labath }
31589ac0c7dSPavel Labath
CalculateNumChildren()31689ac0c7dSPavel Labath size_t ListFrontEnd::CalculateNumChildren() {
31733e97e63SEnrico Granata if (m_count != UINT32_MAX)
31833e97e63SEnrico Granata return m_count;
31933e97e63SEnrico Granata if (!m_head || !m_tail || m_node_address == 0)
32033e97e63SEnrico Granata return 0;
321b9c1b51eSKate Stone ValueObjectSP size_alloc(
322b9c1b51eSKate Stone m_backend.GetChildMemberWithName(ConstString("__size_alloc_"), true));
323b9c1b51eSKate Stone if (size_alloc) {
324a567d680Sshafik ValueObjectSP value = GetValueOfLibCXXCompressedPair(*size_alloc);
3254c0461f8SPavel Labath if (value) {
3264c0461f8SPavel Labath m_count = value->GetValueAsUnsigned(UINT32_MAX);
32733e97e63SEnrico Granata }
32833e97e63SEnrico Granata }
329b9c1b51eSKate Stone if (m_count != UINT32_MAX) {
33033e97e63SEnrico Granata return m_count;
331b9c1b51eSKate Stone } else {
33233e97e63SEnrico Granata uint64_t next_val = m_head->GetValueAsUnsigned(0);
33333e97e63SEnrico Granata uint64_t prev_val = m_tail->GetValueAsUnsigned(0);
33433e97e63SEnrico Granata if (next_val == 0 || prev_val == 0)
33533e97e63SEnrico Granata return 0;
33633e97e63SEnrico Granata if (next_val == m_node_address)
33733e97e63SEnrico Granata return 0;
33833e97e63SEnrico Granata if (next_val == prev_val)
33933e97e63SEnrico Granata return 1;
34033e97e63SEnrico Granata uint64_t size = 2;
34133e97e63SEnrico Granata ListEntry current(m_head);
342b9c1b51eSKate Stone while (current.next() && current.next().value() != m_node_address) {
34333e97e63SEnrico Granata size++;
34433e97e63SEnrico Granata current = current.next();
34533e97e63SEnrico Granata if (size > m_list_capping_size)
34633e97e63SEnrico Granata break;
34733e97e63SEnrico Granata }
34833e97e63SEnrico Granata return m_count = (size - 1);
34933e97e63SEnrico Granata }
35033e97e63SEnrico Granata }
35133e97e63SEnrico Granata
GetChildAtIndex(size_t idx)35289ac0c7dSPavel Labath lldb::ValueObjectSP ListFrontEnd::GetChildAtIndex(size_t idx) {
353e555763fSEnrico Granata static ConstString g_value("__value_");
354e555763fSEnrico Granata static ConstString g_next("__next_");
355e555763fSEnrico Granata
35633e97e63SEnrico Granata if (idx >= CalculateNumChildren())
35733e97e63SEnrico Granata return lldb::ValueObjectSP();
35833e97e63SEnrico Granata
35933e97e63SEnrico Granata if (!m_head || !m_tail || m_node_address == 0)
36033e97e63SEnrico Granata return lldb::ValueObjectSP();
36133e97e63SEnrico Granata
36265a16e56SPavel Labath if (HasLoop(idx + 1))
36333e97e63SEnrico Granata return lldb::ValueObjectSP();
36433e97e63SEnrico Granata
36589ac0c7dSPavel Labath ValueObjectSP current_sp = GetItem(idx);
36633e97e63SEnrico Granata if (!current_sp)
36733e97e63SEnrico Granata return lldb::ValueObjectSP();
36826935d9aSEnrico Granata
369367e2fe1SEnrico Granata current_sp = current_sp->GetChildAtIndex(1, true); // get the __value_ child
37033e97e63SEnrico Granata if (!current_sp)
37133e97e63SEnrico Granata return lldb::ValueObjectSP();
372e555763fSEnrico Granata
373b9c1b51eSKate Stone if (current_sp->GetName() == g_next) {
374e555763fSEnrico Granata ProcessSP process_sp(current_sp->GetProcessSP());
375e555763fSEnrico Granata if (!process_sp)
376027bf760SJim Ingham return lldb::ValueObjectSP();
377e555763fSEnrico Granata
378e555763fSEnrico Granata // if we grabbed the __next_ pointer, then the child is one pointer deep-er
379e555763fSEnrico Granata lldb::addr_t addr = current_sp->GetParent()->GetPointerValue();
380e555763fSEnrico Granata addr = addr + 2 * process_sp->GetAddressByteSize();
381e555763fSEnrico Granata ExecutionContext exe_ctx(process_sp);
382b9c1b51eSKate Stone current_sp =
383b9c1b51eSKate Stone CreateValueObjectFromAddress("__value_", addr, exe_ctx, m_element_type);
384027bf760SJim Ingham if (!current_sp)
385027bf760SJim Ingham return lldb::ValueObjectSP();
386e555763fSEnrico Granata }
387e555763fSEnrico Granata
388b9c1b51eSKate Stone // we need to copy current_sp into a new object otherwise we will end up with
389b9c1b51eSKate Stone // all items named __value_
39033e97e63SEnrico Granata DataExtractor data;
39197206d57SZachary Turner Status error;
39233e97e63SEnrico Granata current_sp->GetData(data, error);
39333e97e63SEnrico Granata if (error.Fail())
39433e97e63SEnrico Granata return lldb::ValueObjectSP();
39533e97e63SEnrico Granata
39633e97e63SEnrico Granata StreamString name;
39733e97e63SEnrico Granata name.Printf("[%" PRIu64 "]", (uint64_t)idx);
398c156427dSZachary Turner return CreateValueObjectFromData(name.GetString(), data,
399c156427dSZachary Turner m_backend.GetExecutionContextRef(),
400c156427dSZachary Turner m_element_type);
40133e97e63SEnrico Granata }
40233e97e63SEnrico Granata
Update()40389ac0c7dSPavel Labath bool ListFrontEnd::Update() {
40489ac0c7dSPavel Labath AbstractListFrontEnd::Update();
40589ac0c7dSPavel Labath m_tail = nullptr;
40633e97e63SEnrico Granata m_node_address = 0;
40765a16e56SPavel Labath
40897206d57SZachary Turner Status err;
40933e97e63SEnrico Granata ValueObjectSP backend_addr(m_backend.AddressOf(err));
410bbd16815SEugene Zelenko if (err.Fail() || !backend_addr)
41133e97e63SEnrico Granata return false;
41233e97e63SEnrico Granata m_node_address = backend_addr->GetValueAsUnsigned(0);
41333e97e63SEnrico Granata if (!m_node_address || m_node_address == LLDB_INVALID_ADDRESS)
41433e97e63SEnrico Granata return false;
415b9c1b51eSKate Stone ValueObjectSP impl_sp(
416b9c1b51eSKate Stone m_backend.GetChildMemberWithName(ConstString("__end_"), true));
41733e97e63SEnrico Granata if (!impl_sp)
41833e97e63SEnrico Granata return false;
41933e97e63SEnrico Granata m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get();
42033e97e63SEnrico Granata m_tail = impl_sp->GetChildMemberWithName(ConstString("__prev_"), true).get();
42133e97e63SEnrico Granata return false;
42233e97e63SEnrico Granata }
42333e97e63SEnrico Granata
LibcxxStdListSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)42489ac0c7dSPavel Labath SyntheticChildrenFrontEnd *formatters::LibcxxStdListSyntheticFrontEndCreator(
42589ac0c7dSPavel Labath CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
42689ac0c7dSPavel Labath return (valobj_sp ? new ListFrontEnd(valobj_sp) : nullptr);
42733e97e63SEnrico Granata }
42833e97e63SEnrico Granata
42933e97e63SEnrico Granata SyntheticChildrenFrontEnd *
LibcxxStdForwardListSyntheticFrontEndCreator(CXXSyntheticChildren *,lldb::ValueObjectSP valobj_sp)43089ac0c7dSPavel Labath formatters::LibcxxStdForwardListSyntheticFrontEndCreator(
431b9c1b51eSKate Stone CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
43289ac0c7dSPavel Labath return valobj_sp ? new ForwardListFrontEnd(*valobj_sp) : nullptr;
43333e97e63SEnrico Granata }
434