xref: /freebsd-src/contrib/llvm-project/lldb/source/Core/ValueObjectConstResultImpl.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15ffd83dbSDimitry Andric //===-- ValueObjectConstResultImpl.cpp ------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Core/ValueObjectConstResultImpl.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Core/Value.h"
120b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h"
130b57cec5SDimitry Andric #include "lldb/Core/ValueObjectConstResult.h"
140b57cec5SDimitry Andric #include "lldb/Core/ValueObjectConstResultCast.h"
150b57cec5SDimitry Andric #include "lldb/Core/ValueObjectConstResultChild.h"
160b57cec5SDimitry Andric #include "lldb/Symbol/CompilerType.h"
170b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
180b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
190b57cec5SDimitry Andric #include "lldb/Utility/Endian.h"
20*0fca6ea1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
21*0fca6ea1SDimitry Andric #include "lldb/Utility/Log.h"
220b57cec5SDimitry Andric #include "lldb/Utility/Scalar.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric #include <string>
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric namespace lldb_private {
270b57cec5SDimitry Andric class DataExtractor;
280b57cec5SDimitry Andric }
290b57cec5SDimitry Andric namespace lldb_private {
300b57cec5SDimitry Andric class Status;
310b57cec5SDimitry Andric }
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric using namespace lldb;
340b57cec5SDimitry Andric using namespace lldb_private;
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric ValueObjectConstResultImpl::ValueObjectConstResultImpl(
370b57cec5SDimitry Andric     ValueObject *valobj, lldb::addr_t live_address)
380b57cec5SDimitry Andric     : m_impl_backend(valobj), m_live_address(live_address),
39349cc55cSDimitry Andric       m_live_address_type(eAddressTypeLoad),
400b57cec5SDimitry Andric       m_address_of_backend() {}
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric lldb::ValueObjectSP ValueObjectConstResultImpl::Dereference(Status &error) {
430b57cec5SDimitry Andric   if (m_impl_backend == nullptr)
440b57cec5SDimitry Andric     return lldb::ValueObjectSP();
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   return m_impl_backend->ValueObject::Dereference(error);
470b57cec5SDimitry Andric }
480b57cec5SDimitry Andric 
49*0fca6ea1SDimitry Andric ValueObject *ValueObjectConstResultImpl::CreateChildAtIndex(size_t idx) {
500b57cec5SDimitry Andric   if (m_impl_backend == nullptr)
510b57cec5SDimitry Andric     return nullptr;
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   m_impl_backend->UpdateValueIfNeeded(false);
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   bool omit_empty_base_classes = true;
56*0fca6ea1SDimitry Andric   bool ignore_array_bounds = false;
57*0fca6ea1SDimitry Andric   std::string child_name;
580b57cec5SDimitry Andric   uint32_t child_byte_size = 0;
590b57cec5SDimitry Andric   int32_t child_byte_offset = 0;
600b57cec5SDimitry Andric   uint32_t child_bitfield_bit_size = 0;
610b57cec5SDimitry Andric   uint32_t child_bitfield_bit_offset = 0;
620b57cec5SDimitry Andric   bool child_is_base_class = false;
630b57cec5SDimitry Andric   bool child_is_deref_of_parent = false;
640b57cec5SDimitry Andric   uint64_t language_flags;
65*0fca6ea1SDimitry Andric   const bool transparent_pointers = true;
660b57cec5SDimitry Andric   CompilerType compiler_type = m_impl_backend->GetCompilerType();
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef());
690b57cec5SDimitry Andric 
70*0fca6ea1SDimitry Andric   auto child_compiler_type_or_err = compiler_type.GetChildCompilerTypeAtIndex(
710b57cec5SDimitry Andric       &exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
72*0fca6ea1SDimitry Andric       ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
730b57cec5SDimitry Andric       child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
740b57cec5SDimitry Andric       child_is_deref_of_parent, m_impl_backend, language_flags);
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   // One might think we should check that the size of the children
770b57cec5SDimitry Andric   // is always strictly positive, hence we could avoid creating a
780b57cec5SDimitry Andric   // ValueObject if that's not the case, but it turns out there
790b57cec5SDimitry Andric   // are languages out there which allow zero-size types with
800b57cec5SDimitry Andric   // children (e.g. Swift).
81*0fca6ea1SDimitry Andric   if (!child_compiler_type_or_err || !child_compiler_type_or_err->IsValid()) {
82*0fca6ea1SDimitry Andric     LLDB_LOG_ERROR(GetLog(LLDBLog::Types),
83*0fca6ea1SDimitry Andric                    child_compiler_type_or_err.takeError(),
84*0fca6ea1SDimitry Andric                    "could not find child: {0}");
85*0fca6ea1SDimitry Andric     return nullptr;
86*0fca6ea1SDimitry Andric   }
870b57cec5SDimitry Andric 
88bdd1243dSDimitry Andric   lldb::addr_t child_live_addr = LLDB_INVALID_ADDRESS;
89bdd1243dSDimitry Andric   // Transfer the live address (with offset) to the child.  But if
90bdd1243dSDimitry Andric   // the parent is a pointer, the live address is where that pointer
91bdd1243dSDimitry Andric   // value lives in memory, so the children live addresses aren't
92bdd1243dSDimitry Andric   // offsets from that value, they are just other load addresses that
93bdd1243dSDimitry Andric   // are recorded in the Value of the child ValueObjects.
94*0fca6ea1SDimitry Andric   if (m_live_address != LLDB_INVALID_ADDRESS && !compiler_type.IsPointerType())
95bdd1243dSDimitry Andric     child_live_addr = m_live_address + child_byte_offset;
96*0fca6ea1SDimitry Andric 
97*0fca6ea1SDimitry Andric   return new ValueObjectConstResultChild(
98*0fca6ea1SDimitry Andric       *m_impl_backend, *child_compiler_type_or_err, ConstString(child_name),
99*0fca6ea1SDimitry Andric       child_byte_size, child_byte_offset, child_bitfield_bit_size,
100*0fca6ea1SDimitry Andric       child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent,
101*0fca6ea1SDimitry Andric       child_live_addr, language_flags);
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric 
104*0fca6ea1SDimitry Andric ValueObject *
105*0fca6ea1SDimitry Andric ValueObjectConstResultImpl::CreateSyntheticArrayMember(size_t idx) {
106*0fca6ea1SDimitry Andric   if (m_impl_backend == nullptr)
107*0fca6ea1SDimitry Andric     return nullptr;
108*0fca6ea1SDimitry Andric 
109*0fca6ea1SDimitry Andric   m_impl_backend->UpdateValueIfNeeded(false);
110*0fca6ea1SDimitry Andric 
111*0fca6ea1SDimitry Andric   bool omit_empty_base_classes = true;
112*0fca6ea1SDimitry Andric   bool ignore_array_bounds = true;
113*0fca6ea1SDimitry Andric   std::string child_name;
114*0fca6ea1SDimitry Andric   uint32_t child_byte_size = 0;
115*0fca6ea1SDimitry Andric   int32_t child_byte_offset = 0;
116*0fca6ea1SDimitry Andric   uint32_t child_bitfield_bit_size = 0;
117*0fca6ea1SDimitry Andric   uint32_t child_bitfield_bit_offset = 0;
118*0fca6ea1SDimitry Andric   bool child_is_base_class = false;
119*0fca6ea1SDimitry Andric   bool child_is_deref_of_parent = false;
120*0fca6ea1SDimitry Andric   uint64_t language_flags;
121*0fca6ea1SDimitry Andric 
122*0fca6ea1SDimitry Andric   const bool transparent_pointers = false;
123*0fca6ea1SDimitry Andric   CompilerType compiler_type = m_impl_backend->GetCompilerType();
124*0fca6ea1SDimitry Andric 
125*0fca6ea1SDimitry Andric   ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef());
126*0fca6ea1SDimitry Andric 
127*0fca6ea1SDimitry Andric   auto child_compiler_type_or_err = compiler_type.GetChildCompilerTypeAtIndex(
128*0fca6ea1SDimitry Andric       &exe_ctx, 0, transparent_pointers, omit_empty_base_classes,
129*0fca6ea1SDimitry Andric       ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
130*0fca6ea1SDimitry Andric       child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
131*0fca6ea1SDimitry Andric       child_is_deref_of_parent, m_impl_backend, language_flags);
132*0fca6ea1SDimitry Andric   // One might think we should check that the size of the children
133*0fca6ea1SDimitry Andric   // is always strictly positive, hence we could avoid creating a
134*0fca6ea1SDimitry Andric   // ValueObject if that's not the case, but it turns out there
135*0fca6ea1SDimitry Andric   // are languages out there which allow zero-size types with
136*0fca6ea1SDimitry Andric   // children (e.g. Swift).
137*0fca6ea1SDimitry Andric   if (!child_compiler_type_or_err || !child_compiler_type_or_err->IsValid()) {
138*0fca6ea1SDimitry Andric     LLDB_LOG_ERROR(GetLog(LLDBLog::Types),
139*0fca6ea1SDimitry Andric                    child_compiler_type_or_err.takeError(),
140*0fca6ea1SDimitry Andric                    "could not find child: {0}");
141*0fca6ea1SDimitry Andric     return nullptr;
142*0fca6ea1SDimitry Andric   }
143*0fca6ea1SDimitry Andric 
144*0fca6ea1SDimitry Andric   child_byte_offset += child_byte_size * idx;
145*0fca6ea1SDimitry Andric 
146*0fca6ea1SDimitry Andric   lldb::addr_t child_live_addr = LLDB_INVALID_ADDRESS;
147*0fca6ea1SDimitry Andric   // Transfer the live address (with offset) to the child.  But if
148*0fca6ea1SDimitry Andric   // the parent is a pointer, the live address is where that pointer
149*0fca6ea1SDimitry Andric   // value lives in memory, so the children live addresses aren't
150*0fca6ea1SDimitry Andric   // offsets from that value, they are just other load addresses that
151*0fca6ea1SDimitry Andric   // are recorded in the Value of the child ValueObjects.
152*0fca6ea1SDimitry Andric   if (m_live_address != LLDB_INVALID_ADDRESS && !compiler_type.IsPointerType())
153*0fca6ea1SDimitry Andric     child_live_addr = m_live_address + child_byte_offset;
154*0fca6ea1SDimitry Andric   return new ValueObjectConstResultChild(
155*0fca6ea1SDimitry Andric       *m_impl_backend, *child_compiler_type_or_err, ConstString(child_name),
156*0fca6ea1SDimitry Andric       child_byte_size, child_byte_offset, child_bitfield_bit_size,
157*0fca6ea1SDimitry Andric       child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent,
158*0fca6ea1SDimitry Andric       child_live_addr, language_flags);
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric lldb::ValueObjectSP ValueObjectConstResultImpl::GetSyntheticChildAtOffset(
1620b57cec5SDimitry Andric     uint32_t offset, const CompilerType &type, bool can_create,
1630b57cec5SDimitry Andric     ConstString name_const_str) {
1640b57cec5SDimitry Andric   if (m_impl_backend == nullptr)
1650b57cec5SDimitry Andric     return lldb::ValueObjectSP();
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric   return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(
1680b57cec5SDimitry Andric       offset, type, can_create, name_const_str);
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric lldb::ValueObjectSP ValueObjectConstResultImpl::AddressOf(Status &error) {
1720b57cec5SDimitry Andric   if (m_address_of_backend.get() != nullptr)
1730b57cec5SDimitry Andric     return m_address_of_backend;
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   if (m_impl_backend == nullptr)
1760b57cec5SDimitry Andric     return lldb::ValueObjectSP();
1770b57cec5SDimitry Andric   if (m_live_address != LLDB_INVALID_ADDRESS) {
1780b57cec5SDimitry Andric     CompilerType compiler_type(m_impl_backend->GetCompilerType());
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric     lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(
1810b57cec5SDimitry Andric         &m_live_address, sizeof(lldb::addr_t)));
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric     std::string new_name("&");
1840b57cec5SDimitry Andric     new_name.append(m_impl_backend->GetName().AsCString(""));
1850b57cec5SDimitry Andric     ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef());
1860b57cec5SDimitry Andric     m_address_of_backend = ValueObjectConstResult::Create(
1870b57cec5SDimitry Andric         exe_ctx.GetBestExecutionContextScope(), compiler_type.GetPointerType(),
1880b57cec5SDimitry Andric         ConstString(new_name.c_str()), buffer, endian::InlHostByteOrder(),
1890b57cec5SDimitry Andric         exe_ctx.GetAddressByteSize());
1900b57cec5SDimitry Andric 
191fe6060f1SDimitry Andric     m_address_of_backend->GetValue().SetValueType(Value::ValueType::Scalar);
1920b57cec5SDimitry Andric     m_address_of_backend->GetValue().GetScalar() = m_live_address;
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric     return m_address_of_backend;
1950b57cec5SDimitry Andric   } else
1960b57cec5SDimitry Andric     return m_impl_backend->ValueObject::AddressOf(error);
1970b57cec5SDimitry Andric }
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric lldb::ValueObjectSP
2000b57cec5SDimitry Andric ValueObjectConstResultImpl::Cast(const CompilerType &compiler_type) {
2010b57cec5SDimitry Andric   if (m_impl_backend == nullptr)
2020b57cec5SDimitry Andric     return lldb::ValueObjectSP();
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric   ValueObjectConstResultCast *result_cast =
2050b57cec5SDimitry Andric       new ValueObjectConstResultCast(*m_impl_backend, m_impl_backend->GetName(),
2060b57cec5SDimitry Andric                                      compiler_type, m_live_address);
2070b57cec5SDimitry Andric   return result_cast->GetSP();
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric lldb::addr_t
2110b57cec5SDimitry Andric ValueObjectConstResultImpl::GetAddressOf(bool scalar_is_load_address,
2120b57cec5SDimitry Andric                                          AddressType *address_type) {
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   if (m_impl_backend == nullptr)
2150b57cec5SDimitry Andric     return 0;
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric   if (m_live_address == LLDB_INVALID_ADDRESS) {
2180b57cec5SDimitry Andric     return m_impl_backend->ValueObject::GetAddressOf(scalar_is_load_address,
2190b57cec5SDimitry Andric                                                      address_type);
2200b57cec5SDimitry Andric   }
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric   if (address_type)
2230b57cec5SDimitry Andric     *address_type = m_live_address_type;
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric   return m_live_address;
2260b57cec5SDimitry Andric }
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric size_t ValueObjectConstResultImpl::GetPointeeData(DataExtractor &data,
2290b57cec5SDimitry Andric                                                   uint32_t item_idx,
2300b57cec5SDimitry Andric                                                   uint32_t item_count) {
2310b57cec5SDimitry Andric   if (m_impl_backend == nullptr)
2320b57cec5SDimitry Andric     return 0;
2330b57cec5SDimitry Andric   return m_impl_backend->ValueObject::GetPointeeData(data, item_idx,
2340b57cec5SDimitry Andric                                                      item_count);
2350b57cec5SDimitry Andric }
236