1 //===-- ValueObjectChild.cpp ------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Core/ValueObjectChild.h"
11 
12 #include "lldb/Core/Module.h"
13 #include "lldb/Core/ValueObjectList.h"
14 
15 #include "lldb/Symbol/CompilerType.h"
16 #include "lldb/Symbol/ObjectFile.h"
17 #include "lldb/Symbol/SymbolContext.h"
18 #include "lldb/Symbol/Type.h"
19 #include "lldb/Symbol/Variable.h"
20 
21 #include "lldb/Target/ExecutionContext.h"
22 #include "lldb/Target/Process.h"
23 #include "lldb/Target/Target.h"
24 
25 using namespace lldb_private;
26 
27 ValueObjectChild::ValueObjectChild(
28     ValueObject &parent, const CompilerType &compiler_type,
29     const ConstString &name, uint64_t byte_size, int32_t byte_offset,
30     uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
31     bool is_base_class, bool is_deref_of_parent,
32     AddressType child_ptr_or_ref_addr_type, uint64_t language_flags)
33     : ValueObject(parent), m_compiler_type(compiler_type),
34       m_byte_size(byte_size), m_byte_offset(byte_offset),
35       m_bitfield_bit_size(bitfield_bit_size),
36       m_bitfield_bit_offset(bitfield_bit_offset),
37       m_is_base_class(is_base_class), m_is_deref_of_parent(is_deref_of_parent),
38       m_can_update_with_invalid_exe_ctx() {
39   m_name = name;
40   SetAddressTypeOfChildren(child_ptr_or_ref_addr_type);
41   SetLanguageFlags(language_flags);
42 }
43 
44 ValueObjectChild::~ValueObjectChild() {}
45 
46 lldb::ValueType ValueObjectChild::GetValueType() const {
47   return m_parent->GetValueType();
48 }
49 
50 size_t ValueObjectChild::CalculateNumChildren(uint32_t max) {
51   auto children_count = GetCompilerType().GetNumChildren(true);
52   return children_count <= max ? children_count : max;
53 }
54 
55 static void AdjustForBitfieldness(ConstString &name,
56                                   uint8_t bitfield_bit_size) {
57   if (name && bitfield_bit_size) {
58     const char *compiler_type_name = name.AsCString();
59     if (compiler_type_name) {
60       std::vector<char> bitfield_type_name(strlen(compiler_type_name) + 32, 0);
61       ::snprintf(&bitfield_type_name.front(), bitfield_type_name.size(),
62                  "%s:%u", compiler_type_name, bitfield_bit_size);
63       name.SetCString(&bitfield_type_name.front());
64     }
65   }
66 }
67 
68 ConstString ValueObjectChild::GetTypeName() {
69   if (m_type_name.IsEmpty()) {
70     m_type_name = GetCompilerType().GetConstTypeName();
71     AdjustForBitfieldness(m_type_name, m_bitfield_bit_size);
72   }
73   return m_type_name;
74 }
75 
76 ConstString ValueObjectChild::GetQualifiedTypeName() {
77   ConstString qualified_name = GetCompilerType().GetConstTypeName();
78   AdjustForBitfieldness(qualified_name, m_bitfield_bit_size);
79   return qualified_name;
80 }
81 
82 ConstString ValueObjectChild::GetDisplayTypeName() {
83   ConstString display_name = GetCompilerType().GetDisplayTypeName();
84   AdjustForBitfieldness(display_name, m_bitfield_bit_size);
85   return display_name;
86 }
87 
88 LazyBool ValueObjectChild::CanUpdateWithInvalidExecutionContext() {
89   if (m_can_update_with_invalid_exe_ctx.hasValue())
90     return m_can_update_with_invalid_exe_ctx.getValue();
91   if (m_parent) {
92     ValueObject *opinionated_parent =
93         m_parent->FollowParentChain([](ValueObject *valobj) -> bool {
94           return (valobj->CanUpdateWithInvalidExecutionContext() ==
95                   eLazyBoolCalculate);
96         });
97     if (opinionated_parent)
98       return (m_can_update_with_invalid_exe_ctx =
99                   opinionated_parent->CanUpdateWithInvalidExecutionContext())
100           .getValue();
101   }
102   return (m_can_update_with_invalid_exe_ctx =
103               this->ValueObject::CanUpdateWithInvalidExecutionContext())
104       .getValue();
105 }
106 
107 bool ValueObjectChild::UpdateValue() {
108   m_error.Clear();
109   SetValueIsValid(false);
110   ValueObject *parent = m_parent;
111   if (parent) {
112     if (parent->UpdateValueIfNeeded(false)) {
113       m_value.SetCompilerType(GetCompilerType());
114 
115       CompilerType parent_type(parent->GetCompilerType());
116       // Copy the parent scalar value and the scalar value type
117       m_value.GetScalar() = parent->GetValue().GetScalar();
118       Value::ValueType value_type = parent->GetValue().GetValueType();
119       m_value.SetValueType(value_type);
120 
121       Flags parent_type_flags(parent_type.GetTypeInfo());
122       const bool is_instance_ptr_base =
123           ((m_is_base_class == true) &&
124            (parent_type_flags.AnySet(lldb::eTypeInstanceIsPointer)));
125 
126       if (parent->GetCompilerType().ShouldTreatScalarValueAsAddress()) {
127         lldb::addr_t addr = parent->GetPointerValue();
128         m_value.GetScalar() = addr;
129 
130         if (addr == LLDB_INVALID_ADDRESS) {
131           m_error.SetErrorString("parent address is invalid.");
132         } else if (addr == 0) {
133           m_error.SetErrorString("parent is NULL");
134         } else {
135           m_value.GetScalar() += m_byte_offset;
136           AddressType addr_type = parent->GetAddressTypeOfChildren();
137 
138           switch (addr_type) {
139           case eAddressTypeFile: {
140             lldb::ProcessSP process_sp(GetProcessSP());
141             if (process_sp && process_sp->IsAlive() == true)
142               m_value.SetValueType(Value::eValueTypeLoadAddress);
143             else
144               m_value.SetValueType(Value::eValueTypeFileAddress);
145           } break;
146           case eAddressTypeLoad:
147             m_value.SetValueType(is_instance_ptr_base
148                                      ? Value::eValueTypeScalar
149                                      : Value::eValueTypeLoadAddress);
150             break;
151           case eAddressTypeHost:
152             m_value.SetValueType(Value::eValueTypeHostAddress);
153             break;
154           case eAddressTypeInvalid:
155             // TODO: does this make sense?
156             m_value.SetValueType(Value::eValueTypeScalar);
157             break;
158           }
159         }
160       } else {
161         switch (value_type) {
162         case Value::eValueTypeLoadAddress:
163         case Value::eValueTypeFileAddress:
164         case Value::eValueTypeHostAddress: {
165           lldb::addr_t addr =
166               m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
167           if (addr == LLDB_INVALID_ADDRESS) {
168             m_error.SetErrorString("parent address is invalid.");
169           } else if (addr == 0) {
170             m_error.SetErrorString("parent is NULL");
171           } else {
172             // Set this object's scalar value to the address of its
173             // value by adding its byte offset to the parent address
174             m_value.GetScalar() += GetByteOffset();
175           }
176         } break;
177 
178         case Value::eValueTypeScalar:
179           // try to extract the child value from the parent's scalar value
180           {
181             Scalar scalar(m_value.GetScalar());
182             if (m_bitfield_bit_size)
183               scalar.ExtractBitfield(m_bitfield_bit_size,
184                                      m_bitfield_bit_offset);
185             else
186               scalar.ExtractBitfield(8 * m_byte_size, 8 * m_byte_offset);
187             m_value.GetScalar() = scalar;
188           }
189           break;
190         default:
191           m_error.SetErrorString("parent has invalid value.");
192           break;
193         }
194       }
195 
196       if (m_error.Success()) {
197         const bool thread_and_frame_only_if_stopped = true;
198         ExecutionContext exe_ctx(
199             GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped));
200         if (GetCompilerType().GetTypeInfo() & lldb::eTypeHasValue) {
201           if (!is_instance_ptr_base)
202             m_error =
203                 m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
204           else
205             m_error = m_parent->GetValue().GetValueAsData(&exe_ctx, m_data, 0,
206                                                           GetModule().get());
207         } else {
208           m_error.Clear(); // No value so nothing to read...
209         }
210       }
211 
212     } else {
213       m_error.SetErrorStringWithFormat("parent failed to evaluate: %s",
214                                        parent->GetError().AsCString());
215     }
216   } else {
217     m_error.SetErrorString("ValueObjectChild has a NULL parent ValueObject.");
218   }
219 
220   return m_error.Success();
221 }
222 
223 bool ValueObjectChild::IsInScope() {
224   ValueObject *root(GetRoot());
225   if (root)
226     return root->IsInScope();
227   return false;
228 }
229