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