]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Core/ValueObjectChild.cpp
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Core / ValueObjectChild.cpp
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/Scalar.h" // for Scalar
13 #include "lldb/Core/Value.h"  // for Value, Value::ValueType::e...
14 #include "lldb/Symbol/CompilerType.h"
15 #include "lldb/Target/ExecutionContext.h"
16 #include "lldb/Target/Process.h"
17 #include "lldb/Utility/Flags.h"  // for Flags
18 #include "lldb/Utility/Status.h" // for Status
19 #include "lldb/lldb-forward.h"   // for ProcessSP, ModuleSP
20
21 #include <functional> // for _Func_impl<>::_Mybase
22 #include <memory>     // for shared_ptr
23 #include <vector>     // for vector
24
25 #include <stdio.h>  // for snprintf, size_t
26 #include <string.h> // for strlen
27
28 using namespace lldb_private;
29
30 ValueObjectChild::ValueObjectChild(
31     ValueObject &parent, const CompilerType &compiler_type,
32     const ConstString &name, uint64_t byte_size, int32_t byte_offset,
33     uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
34     bool is_base_class, bool is_deref_of_parent,
35     AddressType child_ptr_or_ref_addr_type, uint64_t language_flags)
36     : ValueObject(parent), m_compiler_type(compiler_type),
37       m_byte_size(byte_size), m_byte_offset(byte_offset),
38       m_bitfield_bit_size(bitfield_bit_size),
39       m_bitfield_bit_offset(bitfield_bit_offset),
40       m_is_base_class(is_base_class), m_is_deref_of_parent(is_deref_of_parent),
41       m_can_update_with_invalid_exe_ctx() {
42   m_name = name;
43   SetAddressTypeOfChildren(child_ptr_or_ref_addr_type);
44   SetLanguageFlags(language_flags);
45 }
46
47 ValueObjectChild::~ValueObjectChild() {}
48
49 lldb::ValueType ValueObjectChild::GetValueType() const {
50   return m_parent->GetValueType();
51 }
52
53 size_t ValueObjectChild::CalculateNumChildren(uint32_t max) {
54   auto children_count = GetCompilerType().GetNumChildren(true);
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 == true) &&
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() == true)
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           if (!is_instance_ptr_base)
205             m_error =
206                 m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
207           else
208             m_error = m_parent->GetValue().GetValueAsData(&exe_ctx, m_data, 0,
209                                                           GetModule().get());
210         } else {
211           m_error.Clear(); // No value so nothing to read...
212         }
213       }
214
215     } else {
216       m_error.SetErrorStringWithFormat("parent failed to evaluate: %s",
217                                        parent->GetError().AsCString());
218     }
219   } else {
220     m_error.SetErrorString("ValueObjectChild has a NULL parent ValueObject.");
221   }
222
223   return m_error.Success();
224 }
225
226 bool ValueObjectChild::IsInScope() {
227   ValueObject *root(GetRoot());
228   if (root)
229     return root->IsInScope();
230   return false;
231 }