180814287SRaphael Isemann //===-- ValueObjectChild.cpp ----------------------------------------------===//
230fdc8d8SChris Lattner //
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
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner
930fdc8d8SChris Lattner #include "lldb/Core/ValueObjectChild.h"
1030fdc8d8SChris Lattner
11672d2c12SJonas Devlieghere #include "lldb/Core/Value.h"
12a1e5dc86SGreg Clayton #include "lldb/Symbol/CompilerType.h"
1330fdc8d8SChris Lattner #include "lldb/Target/ExecutionContext.h"
1430fdc8d8SChris Lattner #include "lldb/Target/Process.h"
15672d2c12SJonas Devlieghere #include "lldb/Utility/Flags.h"
16672d2c12SJonas Devlieghere #include "lldb/Utility/Scalar.h"
17672d2c12SJonas Devlieghere #include "lldb/Utility/Status.h"
18672d2c12SJonas Devlieghere #include "lldb/lldb-forward.h"
192f3df613SZachary Turner
20672d2c12SJonas Devlieghere #include <functional>
21672d2c12SJonas Devlieghere #include <memory>
22672d2c12SJonas Devlieghere #include <vector>
232f3df613SZachary Turner
2476e47d48SRaphael Isemann #include <cstdio>
2576e47d48SRaphael Isemann #include <cstring>
2630fdc8d8SChris Lattner
2730fdc8d8SChris Lattner using namespace lldb_private;
2830fdc8d8SChris Lattner
ValueObjectChild(ValueObject & parent,const CompilerType & compiler_type,ConstString name,uint64_t byte_size,int32_t byte_offset,uint32_t bitfield_bit_size,uint32_t bitfield_bit_offset,bool is_base_class,bool is_deref_of_parent,AddressType child_ptr_or_ref_addr_type,uint64_t language_flags)29b9c1b51eSKate Stone ValueObjectChild::ValueObjectChild(
30b9c1b51eSKate Stone ValueObject &parent, const CompilerType &compiler_type,
310e4c4821SAdrian Prantl ConstString name, uint64_t byte_size, int32_t byte_offset,
32b9c1b51eSKate Stone uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
33b9c1b51eSKate Stone bool is_base_class, bool is_deref_of_parent,
34b9c1b51eSKate Stone AddressType child_ptr_or_ref_addr_type, uint64_t language_flags)
35b9c1b51eSKate Stone : ValueObject(parent), m_compiler_type(compiler_type),
36b9c1b51eSKate Stone m_byte_size(byte_size), m_byte_offset(byte_offset),
3730fdc8d8SChris Lattner m_bitfield_bit_size(bitfield_bit_size),
388f92f0a3SGreg Clayton m_bitfield_bit_offset(bitfield_bit_offset),
39b9c1b51eSKate Stone m_is_base_class(is_base_class), m_is_deref_of_parent(is_deref_of_parent),
40b9c1b51eSKate Stone m_can_update_with_invalid_exe_ctx() {
4130fdc8d8SChris Lattner m_name = name;
429128ee2fSEnrico Granata SetAddressTypeOfChildren(child_ptr_or_ref_addr_type);
43dc62ffd3SEnrico Granata SetLanguageFlags(language_flags);
4430fdc8d8SChris Lattner }
4530fdc8d8SChris Lattner
46fd2433e1SJonas Devlieghere ValueObjectChild::~ValueObjectChild() = default;
4730fdc8d8SChris Lattner
GetValueType() const48b9c1b51eSKate Stone lldb::ValueType ValueObjectChild::GetValueType() const {
4930fdc8d8SChris Lattner return m_parent->GetValueType();
5030fdc8d8SChris Lattner }
5130fdc8d8SChris Lattner
CalculateNumChildren(uint32_t max)52b9c1b51eSKate Stone size_t ValueObjectChild::CalculateNumChildren(uint32_t max) {
53eca07c59SAdrian Prantl ExecutionContext exe_ctx(GetExecutionContextRef());
54eca07c59SAdrian Prantl auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
559ac7a6c5SSiva Chandra return children_count <= max ? children_count : max;
5630fdc8d8SChris Lattner }
5730fdc8d8SChris Lattner
AdjustForBitfieldness(ConstString & name,uint8_t bitfield_bit_size)58b9c1b51eSKate Stone static void AdjustForBitfieldness(ConstString &name,
59b9c1b51eSKate Stone uint8_t bitfield_bit_size) {
60db203e02SRaphael Isemann if (name && bitfield_bit_size)
61db203e02SRaphael Isemann name.SetString(llvm::formatv("{0}:{1}", name, bitfield_bit_size).str());
62e8daa2f8SEnrico Granata }
63e8daa2f8SEnrico Granata
GetTypeName()64b9c1b51eSKate Stone ConstString ValueObjectChild::GetTypeName() {
65b9c1b51eSKate Stone if (m_type_name.IsEmpty()) {
6630ce956aSRaphael Isemann m_type_name = GetCompilerType().GetTypeName();
67e8daa2f8SEnrico Granata AdjustForBitfieldness(m_type_name, m_bitfield_bit_size);
6830fdc8d8SChris Lattner }
6930fdc8d8SChris Lattner return m_type_name;
7030fdc8d8SChris Lattner }
7130fdc8d8SChris Lattner
GetQualifiedTypeName()72b9c1b51eSKate Stone ConstString ValueObjectChild::GetQualifiedTypeName() {
7330ce956aSRaphael Isemann ConstString qualified_name = GetCompilerType().GetTypeName();
74e8daa2f8SEnrico Granata AdjustForBitfieldness(qualified_name, m_bitfield_bit_size);
7584db9105SGreg Clayton return qualified_name;
7684db9105SGreg Clayton }
7784db9105SGreg Clayton
GetDisplayTypeName()78b9c1b51eSKate Stone ConstString ValueObjectChild::GetDisplayTypeName() {
7999558cc4SGreg Clayton ConstString display_name = GetCompilerType().GetDisplayTypeName();
80e8daa2f8SEnrico Granata AdjustForBitfieldness(display_name, m_bitfield_bit_size);
81e8daa2f8SEnrico Granata return display_name;
82e8daa2f8SEnrico Granata }
83e8daa2f8SEnrico Granata
CanUpdateWithInvalidExecutionContext()84b9c1b51eSKate Stone LazyBool ValueObjectChild::CanUpdateWithInvalidExecutionContext() {
8596d1b4ddSKazu Hirata if (m_can_update_with_invalid_exe_ctx)
86*5cff5142SKazu Hirata return m_can_update_with_invalid_exe_ctx.value();
87b9c1b51eSKate Stone if (m_parent) {
88b9c1b51eSKate Stone ValueObject *opinionated_parent =
89b9c1b51eSKate Stone m_parent->FollowParentChain([](ValueObject *valobj) -> bool {
90b9c1b51eSKate Stone return (valobj->CanUpdateWithInvalidExecutionContext() ==
91b9c1b51eSKate Stone eLazyBoolCalculate);
922e9f2993SEnrico Granata });
932e9f2993SEnrico Granata if (opinionated_parent)
94b9c1b51eSKate Stone return (m_can_update_with_invalid_exe_ctx =
95b9c1b51eSKate Stone opinionated_parent->CanUpdateWithInvalidExecutionContext())
96*5cff5142SKazu Hirata .value();
972e9f2993SEnrico Granata }
98b9c1b51eSKate Stone return (m_can_update_with_invalid_exe_ctx =
99b9c1b51eSKate Stone this->ValueObject::CanUpdateWithInvalidExecutionContext())
100*5cff5142SKazu Hirata .value();
10145185862SEnrico Granata }
10245185862SEnrico Granata
UpdateValue()103b9c1b51eSKate Stone bool ValueObjectChild::UpdateValue() {
10430fdc8d8SChris Lattner m_error.Clear();
10530fdc8d8SChris Lattner SetValueIsValid(false);
10630fdc8d8SChris Lattner ValueObject *parent = m_parent;
107b9c1b51eSKate Stone if (parent) {
108b9c1b51eSKate Stone if (parent->UpdateValueIfNeeded(false)) {
10999558cc4SGreg Clayton m_value.SetCompilerType(GetCompilerType());
11030fdc8d8SChris Lattner
1115696085aSEnrico Granata CompilerType parent_type(parent->GetCompilerType());
11230fdc8d8SChris Lattner // Copy the parent scalar value and the scalar value type
11330fdc8d8SChris Lattner m_value.GetScalar() = parent->GetValue().GetScalar();
11497ca9ca1SPavel Labath m_value.SetValueType(parent->GetValue().GetValueType());
11530fdc8d8SChris Lattner
1165696085aSEnrico Granata Flags parent_type_flags(parent_type.GetTypeInfo());
117b9c1b51eSKate Stone const bool is_instance_ptr_base =
118a6682a41SJonas Devlieghere ((m_is_base_class) &&
119b9c1b51eSKate Stone (parent_type_flags.AnySet(lldb::eTypeInstanceIsPointer)));
1205696085aSEnrico Granata
121b9c1b51eSKate Stone if (parent->GetCompilerType().ShouldTreatScalarValueAsAddress()) {
12297ca9ca1SPavel Labath m_value.GetScalar() = parent->GetPointerValue();
1237c8a9664SGreg Clayton
12497ca9ca1SPavel Labath switch (parent->GetAddressTypeOfChildren()) {
125b9c1b51eSKate Stone case eAddressTypeFile: {
126cc4d0146SGreg Clayton lldb::ProcessSP process_sp(GetProcessSP());
127a6682a41SJonas Devlieghere if (process_sp && process_sp->IsAlive())
128057efa99SAdrian Prantl m_value.SetValueType(Value::ValueType::LoadAddress);
1299128ee2fSEnrico Granata else
130057efa99SAdrian Prantl m_value.SetValueType(Value::ValueType::FileAddress);
131b9c1b51eSKate Stone } break;
1329128ee2fSEnrico Granata case eAddressTypeLoad:
133b9c1b51eSKate Stone m_value.SetValueType(is_instance_ptr_base
134057efa99SAdrian Prantl ? Value::ValueType::Scalar
135057efa99SAdrian Prantl : Value::ValueType::LoadAddress);
1369128ee2fSEnrico Granata break;
1379128ee2fSEnrico Granata case eAddressTypeHost:
138057efa99SAdrian Prantl m_value.SetValueType(Value::ValueType::HostAddress);
1399128ee2fSEnrico Granata break;
1409128ee2fSEnrico Granata case eAddressTypeInvalid:
1419128ee2fSEnrico Granata // TODO: does this make sense?
142057efa99SAdrian Prantl m_value.SetValueType(Value::ValueType::Scalar);
1439128ee2fSEnrico Granata break;
1449128ee2fSEnrico Granata }
14530fdc8d8SChris Lattner }
14697ca9ca1SPavel Labath switch (m_value.GetValueType()) {
147057efa99SAdrian Prantl case Value::ValueType::Invalid:
148057efa99SAdrian Prantl break;
149057efa99SAdrian Prantl case Value::ValueType::LoadAddress:
150057efa99SAdrian Prantl case Value::ValueType::FileAddress:
151057efa99SAdrian Prantl case Value::ValueType::HostAddress: {
15297ca9ca1SPavel Labath lldb::addr_t addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
153b9c1b51eSKate Stone if (addr == LLDB_INVALID_ADDRESS) {
1547c8a9664SGreg Clayton m_error.SetErrorString("parent address is invalid.");
155b9c1b51eSKate Stone } else if (addr == 0) {
1567c8a9664SGreg Clayton m_error.SetErrorString("parent is NULL");
157b9c1b51eSKate Stone } else {
15897ca9ca1SPavel Labath // If a bitfield doesn't fit into the child_byte_size'd window at
15997ca9ca1SPavel Labath // child_byte_offset, move the window forward until it fits. The
16097ca9ca1SPavel Labath // problem here is that Value has no notion of bitfields and thus the
16197ca9ca1SPavel Labath // Value's DataExtractor is sized like the bitfields CompilerType; a
16297ca9ca1SPavel Labath // sequence of bitfields, however, can be larger than their underlying
163f81d6fe7SAdrian Prantl // type.
164f81d6fe7SAdrian Prantl if (m_bitfield_bit_offset) {
165f81d6fe7SAdrian Prantl const bool thread_and_frame_only_if_stopped = true;
166f81d6fe7SAdrian Prantl ExecutionContext exe_ctx(GetExecutionContextRef().Lock(
167f81d6fe7SAdrian Prantl thread_and_frame_only_if_stopped));
168f81d6fe7SAdrian Prantl if (auto type_bit_size = GetCompilerType().GetBitSize(
169f81d6fe7SAdrian Prantl exe_ctx.GetBestExecutionContextScope())) {
170f81d6fe7SAdrian Prantl uint64_t bitfield_end =
171f81d6fe7SAdrian Prantl m_bitfield_bit_size + m_bitfield_bit_offset;
172f81d6fe7SAdrian Prantl if (bitfield_end > *type_bit_size) {
173f81d6fe7SAdrian Prantl uint64_t overhang_bytes =
174f81d6fe7SAdrian Prantl (bitfield_end - *type_bit_size + 7) / 8;
17519d64138SPavel Labath m_byte_offset += overhang_bytes;
176f81d6fe7SAdrian Prantl m_bitfield_bit_offset -= overhang_bytes * 8;
177f81d6fe7SAdrian Prantl }
178f81d6fe7SAdrian Prantl }
179f81d6fe7SAdrian Prantl }
18019d64138SPavel Labath
18119d64138SPavel Labath // Set this object's scalar value to the address of its value by
18219d64138SPavel Labath // adding its byte offset to the parent address
18319d64138SPavel Labath m_value.GetScalar() += m_byte_offset;
18430fdc8d8SChris Lattner }
185b9c1b51eSKate Stone } break;
18630fdc8d8SChris Lattner
187057efa99SAdrian Prantl case Value::ValueType::Scalar:
1885696085aSEnrico Granata // try to extract the child value from the parent's scalar value
1895696085aSEnrico Granata {
1905696085aSEnrico Granata Scalar scalar(m_value.GetScalar());
1915696085aSEnrico Granata scalar.ExtractBitfield(8 * m_byte_size, 8 * m_byte_offset);
1925696085aSEnrico Granata m_value.GetScalar() = scalar;
1935696085aSEnrico Granata }
1945696085aSEnrico Granata break;
19530fdc8d8SChris Lattner }
19630fdc8d8SChris Lattner
197b9c1b51eSKate Stone if (m_error.Success()) {
19844d93782SGreg Clayton const bool thread_and_frame_only_if_stopped = true;
199b9c1b51eSKate Stone ExecutionContext exe_ctx(
200b9c1b51eSKate Stone GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped));
201b9c1b51eSKate Stone if (GetCompilerType().GetTypeInfo() & lldb::eTypeHasValue) {
20203bd1838SAdrian Prantl Value &value = is_instance_ptr_base ? m_parent->GetValue() : m_value;
203b9c1b51eSKate Stone m_error =
204d9cbd2acSAdrian Prantl value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
205b9c1b51eSKate Stone } else {
2061e3be5baSGreg Clayton m_error.Clear(); // No value so nothing to read...
20730fdc8d8SChris Lattner }
20830fdc8d8SChris Lattner }
2095696085aSEnrico Granata
210b9c1b51eSKate Stone } else {
211b9c1b51eSKate Stone m_error.SetErrorStringWithFormat("parent failed to evaluate: %s",
212b9c1b51eSKate Stone parent->GetError().AsCString());
2135696085aSEnrico Granata }
214b9c1b51eSKate Stone } else {
21530fdc8d8SChris Lattner m_error.SetErrorString("ValueObjectChild has a NULL parent ValueObject.");
21630fdc8d8SChris Lattner }
2176035b67dSJim Ingham
2186035b67dSJim Ingham return m_error.Success();
21930fdc8d8SChris Lattner }
22030fdc8d8SChris Lattner
IsInScope()221b9c1b51eSKate Stone bool ValueObjectChild::IsInScope() {
2224873e527SEnrico Granata ValueObject *root(GetRoot());
2234873e527SEnrico Granata if (root)
2244873e527SEnrico Granata return root->IsInScope();
2254873e527SEnrico Granata return false;
22630fdc8d8SChris Lattner }
227