]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Core/ValueObjectChild.cpp
Import libxo-1.0.2
[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/Value.h"
13 #include "lldb/Symbol/CompilerType.h"
14 #include "lldb/Target/ExecutionContext.h"
15 #include "lldb/Target/Process.h"
16 #include "lldb/Utility/Flags.h"
17 #include "lldb/Utility/Scalar.h"
18 #include "lldb/Utility/Status.h"
19 #include "lldb/lldb-forward.h"
20
21 #include <functional>
22 #include <memory>
23 #include <vector>
24
25 #include <stdio.h>
26 #include <string.h>
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   ExecutionContext exe_ctx(GetExecutionContextRef());
55   auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
56   return children_count <= max ? children_count : max;
57 }
58
59 static void AdjustForBitfieldness(ConstString &name,
60                                   uint8_t bitfield_bit_size) {
61   if (name && bitfield_bit_size) {
62     const char *compiler_type_name = name.AsCString();
63     if (compiler_type_name) {
64       std::vector<char> bitfield_type_name(strlen(compiler_type_name) + 32, 0);
65       ::snprintf(&bitfield_type_name.front(), bitfield_type_name.size(),
66                  "%s:%u", compiler_type_name, bitfield_bit_size);
67       name.SetCString(&bitfield_type_name.front());
68     }
69   }
70 }
71
72 ConstString ValueObjectChild::GetTypeName() {
73   if (m_type_name.IsEmpty()) {
74     m_type_name = GetCompilerType().GetConstTypeName();
75     AdjustForBitfieldness(m_type_name, m_bitfield_bit_size);
76   }
77   return m_type_name;
78 }
79
80 ConstString ValueObjectChild::GetQualifiedTypeName() {
81   ConstString qualified_name = GetCompilerType().GetConstTypeName();
82   AdjustForBitfieldness(qualified_name, m_bitfield_bit_size);
83   return qualified_name;
84 }
85
86 ConstString ValueObjectChild::GetDisplayTypeName() {
87   ConstString display_name = GetCompilerType().GetDisplayTypeName();
88   AdjustForBitfieldness(display_name, m_bitfield_bit_size);
89   return display_name;
90 }
91
92 LazyBool ValueObjectChild::CanUpdateWithInvalidExecutionContext() {
93   if (m_can_update_with_invalid_exe_ctx.hasValue())
94     return m_can_update_with_invalid_exe_ctx.getValue();
95   if (m_parent) {
96     ValueObject *opinionated_parent =
97         m_parent->FollowParentChain([](ValueObject *valobj) -> bool {
98           return (valobj->CanUpdateWithInvalidExecutionContext() ==
99                   eLazyBoolCalculate);
100         });
101     if (opinionated_parent)
102       return (m_can_update_with_invalid_exe_ctx =
103                   opinionated_parent->CanUpdateWithInvalidExecutionContext())
104           .getValue();
105   }
106   return (m_can_update_with_invalid_exe_ctx =
107               this->ValueObject::CanUpdateWithInvalidExecutionContext())
108       .getValue();
109 }
110
111 bool ValueObjectChild::UpdateValue() {
112   m_error.Clear();
113   SetValueIsValid(false);
114   ValueObject *parent = m_parent;
115   if (parent) {
116     if (parent->UpdateValueIfNeeded(false)) {
117       m_value.SetCompilerType(GetCompilerType());
118
119       CompilerType parent_type(parent->GetCompilerType());
120       // Copy the parent scalar value and the scalar value type
121       m_value.GetScalar() = parent->GetValue().GetScalar();
122       Value::ValueType value_type = parent->GetValue().GetValueType();
123       m_value.SetValueType(value_type);
124
125       Flags parent_type_flags(parent_type.GetTypeInfo());
126       const bool is_instance_ptr_base =
127           ((m_is_base_class) &&
128            (parent_type_flags.AnySet(lldb::eTypeInstanceIsPointer)));
129
130       if (parent->GetCompilerType().ShouldTreatScalarValueAsAddress()) {
131         lldb::addr_t addr = parent->GetPointerValue();
132         m_value.GetScalar() = addr;
133
134         if (addr == LLDB_INVALID_ADDRESS) {
135           m_error.SetErrorString("parent address is invalid.");
136         } else if (addr == 0) {
137           m_error.SetErrorString("parent is NULL");
138         } else {
139           m_value.GetScalar() += m_byte_offset;
140           AddressType addr_type = parent->GetAddressTypeOfChildren();
141
142           switch (addr_type) {
143           case eAddressTypeFile: {
144             lldb::ProcessSP process_sp(GetProcessSP());
145             if (process_sp && process_sp->IsAlive())
146               m_value.SetValueType(Value::eValueTypeLoadAddress);
147             else
148               m_value.SetValueType(Value::eValueTypeFileAddress);
149           } break;
150           case eAddressTypeLoad:
151             m_value.SetValueType(is_instance_ptr_base
152                                      ? Value::eValueTypeScalar
153                                      : Value::eValueTypeLoadAddress);
154             break;
155           case eAddressTypeHost:
156             m_value.SetValueType(Value::eValueTypeHostAddress);
157             break;
158           case eAddressTypeInvalid:
159             // TODO: does this make sense?
160             m_value.SetValueType(Value::eValueTypeScalar);
161             break;
162           }
163         }
164       } else {
165         switch (value_type) {
166         case Value::eValueTypeLoadAddress:
167         case Value::eValueTypeFileAddress:
168         case Value::eValueTypeHostAddress: {
169           lldb::addr_t addr =
170               m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
171           if (addr == LLDB_INVALID_ADDRESS) {
172             m_error.SetErrorString("parent address is invalid.");
173           } else if (addr == 0) {
174             m_error.SetErrorString("parent is NULL");
175           } else {
176             // Set this object's scalar value to the address of its value by
177             // adding its byte offset to the parent address
178             m_value.GetScalar() += GetByteOffset();
179           }
180         } break;
181
182         case Value::eValueTypeScalar:
183           // try to extract the child value from the parent's scalar value
184           {
185             Scalar scalar(m_value.GetScalar());
186             if (m_bitfield_bit_size)
187               scalar.ExtractBitfield(m_bitfield_bit_size,
188                                      m_bitfield_bit_offset);
189             else
190               scalar.ExtractBitfield(8 * m_byte_size, 8 * m_byte_offset);
191             m_value.GetScalar() = scalar;
192           }
193           break;
194         default:
195           m_error.SetErrorString("parent has invalid value.");
196           break;
197         }
198       }
199
200       if (m_error.Success()) {
201         const bool thread_and_frame_only_if_stopped = true;
202         ExecutionContext exe_ctx(
203             GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped));
204         if (GetCompilerType().GetTypeInfo() & lldb::eTypeHasValue) {
205           Value &value = is_instance_ptr_base ? m_parent->GetValue() : m_value;
206           m_error =
207               value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
208         } else {
209           m_error.Clear(); // No value so nothing to read...
210         }
211       }
212
213     } else {
214       m_error.SetErrorStringWithFormat("parent failed to evaluate: %s",
215                                        parent->GetError().AsCString());
216     }
217   } else {
218     m_error.SetErrorString("ValueObjectChild has a NULL parent ValueObject.");
219   }
220
221   return m_error.Success();
222 }
223
224 bool ValueObjectChild::IsInScope() {
225   ValueObject *root(GetRoot());
226   if (root)
227     return root->IsInScope();
228   return false;
229 }