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