Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 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 | |
Jonas Devlieghere | 672d2c1 | 2018-11-11 23:16:43 +0000 | [diff] [blame] | 12 | #include "lldb/Core/Value.h" |
Greg Clayton | a1e5dc8 | 2015-08-11 22:53:00 +0000 | [diff] [blame] | 13 | #include "lldb/Symbol/CompilerType.h" |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 14 | #include "lldb/Target/ExecutionContext.h" |
| 15 | #include "lldb/Target/Process.h" |
Jonas Devlieghere | 672d2c1 | 2018-11-11 23:16:43 +0000 | [diff] [blame] | 16 | #include "lldb/Utility/Flags.h" |
| 17 | #include "lldb/Utility/Scalar.h" |
| 18 | #include "lldb/Utility/Status.h" |
| 19 | #include "lldb/lldb-forward.h" |
Zachary Turner | 2f3df61 | 2017-04-06 21:28:29 +0000 | [diff] [blame] | 20 | |
Jonas Devlieghere | 672d2c1 | 2018-11-11 23:16:43 +0000 | [diff] [blame] | 21 | #include <functional> |
| 22 | #include <memory> |
| 23 | #include <vector> |
Zachary Turner | 2f3df61 | 2017-04-06 21:28:29 +0000 | [diff] [blame] | 24 | |
Jonas Devlieghere | 672d2c1 | 2018-11-11 23:16:43 +0000 | [diff] [blame] | 25 | #include <stdio.h> |
| 26 | #include <string.h> |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 27 | |
| 28 | using namespace lldb_private; |
| 29 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 45 | } |
| 46 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 47 | ValueObjectChild::~ValueObjectChild() {} |
| 48 | |
| 49 | lldb::ValueType ValueObjectChild::GetValueType() const { |
| 50 | return m_parent->GetValueType(); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 51 | } |
| 52 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 53 | size_t ValueObjectChild::CalculateNumChildren(uint32_t max) { |
Adrian Prantl | eca07c5 | 2018-11-05 20:49:07 +0000 | [diff] [blame] | 54 | ExecutionContext exe_ctx(GetExecutionContextRef()); |
| 55 | auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx); |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 56 | return children_count <= max ? children_count : max; |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 57 | } |
| 58 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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()); |
Enrico Granata | e8daa2f | 2014-05-17 19:14:17 +0000 | [diff] [blame] | 68 | } |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 69 | } |
Enrico Granata | e8daa2f | 2014-05-17 19:14:17 +0000 | [diff] [blame] | 70 | } |
| 71 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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; |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 78 | } |
| 79 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 80 | ConstString ValueObjectChild::GetQualifiedTypeName() { |
| 81 | ConstString qualified_name = GetCompilerType().GetConstTypeName(); |
| 82 | AdjustForBitfieldness(qualified_name, m_bitfield_bit_size); |
| 83 | return qualified_name; |
Greg Clayton | 84db910 | 2012-03-26 23:03:23 +0000 | [diff] [blame] | 84 | } |
| 85 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 86 | ConstString ValueObjectChild::GetDisplayTypeName() { |
| 87 | ConstString display_name = GetCompilerType().GetDisplayTypeName(); |
| 88 | AdjustForBitfieldness(display_name, m_bitfield_bit_size); |
| 89 | return display_name; |
Enrico Granata | e8daa2f | 2014-05-17 19:14:17 +0000 | [diff] [blame] | 90 | } |
| 91 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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); |
Enrico Granata | 2e9f299 | 2015-07-28 01:45:23 +0000 | [diff] [blame] | 100 | }); |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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(); |
Enrico Granata | 4518586 | 2015-05-19 18:53:13 +0000 | [diff] [blame] | 109 | } |
| 110 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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()); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 118 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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 == true) && |
| 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() == true) |
| 146 | m_value.SetValueType(Value::eValueTypeLoadAddress); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 147 | else |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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 | } |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 163 | } |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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 { |
Adrian Prantl | 0509724 | 2018-04-30 16:49:04 +0000 | [diff] [blame] | 176 | // Set this object's scalar value to the address of its value by |
| 177 | // adding its byte offset to the parent address |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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; |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 197 | } |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 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 | if (!is_instance_ptr_base) |
| 206 | m_error = |
| 207 | m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); |
| 208 | else |
| 209 | m_error = m_parent->GetValue().GetValueAsData(&exe_ctx, m_data, 0, |
| 210 | GetModule().get()); |
| 211 | } else { |
| 212 | m_error.Clear(); // No value so nothing to read... |
| 213 | } |
| 214 | } |
| 215 | |
| 216 | } else { |
| 217 | m_error.SetErrorStringWithFormat("parent failed to evaluate: %s", |
| 218 | parent->GetError().AsCString()); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 219 | } |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 220 | } else { |
| 221 | m_error.SetErrorString("ValueObjectChild has a NULL parent ValueObject."); |
| 222 | } |
| 223 | |
| 224 | return m_error.Success(); |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 225 | } |
| 226 | |
Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 227 | bool ValueObjectChild::IsInScope() { |
| 228 | ValueObject *root(GetRoot()); |
| 229 | if (root) |
| 230 | return root->IsInScope(); |
| 231 | return false; |
Chris Lattner | 30fdc8d | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 232 | } |