brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.7 KiB · 3d8d80c Raw
241 lines · cpp
1//===-- ValueObjectMemory.cpp ---------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/ValueObject/ValueObjectMemory.h"10#include "lldb/Core/Value.h"11#include "lldb/Symbol/Type.h"12#include "lldb/Target/ExecutionContext.h"13#include "lldb/Target/Target.h"14#include "lldb/Utility/DataExtractor.h"15#include "lldb/Utility/Scalar.h"16#include "lldb/Utility/Status.h"17#include "lldb/ValueObject/ValueObject.h"18#include "lldb/lldb-types.h"19#include "llvm/Support/ErrorHandling.h"20 21#include <cassert>22#include <memory>23#include <optional>24 25namespace lldb_private {26class ExecutionContextScope;27}28 29using namespace lldb;30using namespace lldb_private;31 32ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope,33                                        llvm::StringRef name,34                                        const Address &address,35                                        lldb::TypeSP &type_sp) {36  auto manager_sp = ValueObjectManager::Create();37  return (new ValueObjectMemory(exe_scope, *manager_sp, name, address, type_sp))38      ->GetSP();39}40 41ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope,42                                        llvm::StringRef name,43                                        const Address &address,44                                        const CompilerType &ast_type) {45  auto manager_sp = ValueObjectManager::Create();46  return (new ValueObjectMemory(exe_scope, *manager_sp, name, address,47                                ast_type))48      ->GetSP();49}50 51ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope,52                                     ValueObjectManager &manager,53                                     llvm::StringRef name,54                                     const Address &address,55                                     lldb::TypeSP &type_sp)56    : ValueObject(exe_scope, manager), m_address(address), m_type_sp(type_sp),57      m_compiler_type() {58  // Do not attempt to construct one of these objects with no variable!59  assert(m_type_sp.get() != nullptr);60  SetName(ConstString(name));61  m_value.SetContext(Value::ContextType::LLDBType, m_type_sp.get());62  TargetSP target_sp(GetTargetSP());63  lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());64  if (load_address != LLDB_INVALID_ADDRESS) {65    m_value.SetValueType(Value::ValueType::LoadAddress);66    m_value.GetScalar() = load_address;67  } else {68    lldb::addr_t file_address = m_address.GetFileAddress();69    if (file_address != LLDB_INVALID_ADDRESS) {70      m_value.SetValueType(Value::ValueType::FileAddress);71      m_value.GetScalar() = file_address;72    } else {73      m_value.GetScalar() = m_address.GetOffset();74      m_value.SetValueType(Value::ValueType::Scalar);75    }76  }77}78 79ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope,80                                     ValueObjectManager &manager,81                                     llvm::StringRef name,82                                     const Address &address,83                                     const CompilerType &ast_type)84    : ValueObject(exe_scope, manager), m_address(address), m_type_sp(),85      m_compiler_type(ast_type) {86  // Do not attempt to construct one of these objects with no variable!87  assert(m_compiler_type.IsValid());88 89  TargetSP target_sp(GetTargetSP());90 91  SetName(ConstString(name));92  m_value.SetCompilerType(m_compiler_type);93  lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());94  if (load_address != LLDB_INVALID_ADDRESS) {95    m_value.SetValueType(Value::ValueType::LoadAddress);96    m_value.GetScalar() = load_address;97  } else {98    lldb::addr_t file_address = m_address.GetFileAddress();99    if (file_address != LLDB_INVALID_ADDRESS) {100      m_value.SetValueType(Value::ValueType::FileAddress);101      m_value.GetScalar() = file_address;102    } else {103      m_value.GetScalar() = m_address.GetOffset();104      m_value.SetValueType(Value::ValueType::Scalar);105    }106  }107}108 109ValueObjectMemory::~ValueObjectMemory() = default;110 111CompilerType ValueObjectMemory::GetCompilerTypeImpl() {112  if (m_type_sp)113    return m_type_sp->GetForwardCompilerType();114  return m_compiler_type;115}116 117ConstString ValueObjectMemory::GetTypeName() {118  if (m_type_sp)119    return m_type_sp->GetName();120  return m_compiler_type.GetTypeName();121}122 123ConstString ValueObjectMemory::GetDisplayTypeName() {124  if (m_type_sp)125    return m_type_sp->GetForwardCompilerType().GetDisplayTypeName();126  return m_compiler_type.GetDisplayTypeName();127}128 129llvm::Expected<uint32_t> ValueObjectMemory::CalculateNumChildren(uint32_t max) {130  if (m_type_sp) {131    auto child_count = m_type_sp->GetNumChildren(true);132    if (!child_count)133      return child_count;134    return *child_count <= max ? *child_count : max;135  }136 137  ExecutionContext exe_ctx(GetExecutionContextRef());138  const bool omit_empty_base_classes = true;139  auto child_count =140      m_compiler_type.GetNumChildren(omit_empty_base_classes, &exe_ctx);141  if (!child_count)142    return child_count;143  return *child_count <= max ? *child_count : max;144}145 146llvm::Expected<uint64_t> ValueObjectMemory::GetByteSize() {147  ExecutionContext exe_ctx(GetExecutionContextRef());148  if (m_type_sp) {149    if (auto size =150            m_type_sp->GetByteSize(exe_ctx.GetBestExecutionContextScope()))151      return *size;152    return llvm::createStringError("could not get byte size of memory object");153  }154  return m_compiler_type.GetByteSize(exe_ctx.GetBestExecutionContextScope());155}156 157lldb::ValueType ValueObjectMemory::GetValueType() const {158  // RETHINK: Should this be inherited from somewhere?159  return lldb::eValueTypeVariableGlobal;160}161 162bool ValueObjectMemory::UpdateValue() {163  SetValueIsValid(false);164  m_error.Clear();165 166  ExecutionContext exe_ctx(GetExecutionContextRef());167 168  Target *target = exe_ctx.GetTargetPtr();169  if (target) {170    m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());171    m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());172  }173 174  Value old_value(m_value);175  if (m_address.IsValid()) {176    Value::ValueType value_type = m_value.GetValueType();177 178    switch (value_type) {179    case Value::ValueType::Invalid:180      m_error = Status::FromErrorString("Invalid value");181      return false;182    case Value::ValueType::Scalar:183      // The variable value is in the Scalar value inside the m_value. We can184      // point our m_data right to it.185      m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());186      break;187 188    case Value::ValueType::FileAddress:189    case Value::ValueType::LoadAddress:190    case Value::ValueType::HostAddress:191      // The DWARF expression result was an address in the inferior process. If192      // this variable is an aggregate type, we just need the address as the193      // main value as all child variable objects will rely upon this location194      // and add an offset and then read their own values as needed. If this195      // variable is a simple type, we read all data for it into m_data. Make196      // sure this type has a value before we try and read it197 198      // If we have a file address, convert it to a load address if we can.199      if (value_type == Value::ValueType::FileAddress &&200          exe_ctx.GetProcessPtr()) {201        lldb::addr_t load_addr = m_address.GetLoadAddress(target);202        if (load_addr != LLDB_INVALID_ADDRESS) {203          m_value.SetValueType(Value::ValueType::LoadAddress);204          m_value.GetScalar() = load_addr;205        }206      }207 208      if (!CanProvideValue()) {209        // this value object represents an aggregate type whose children have210        // values, but this object does not. So we say we are changed if our211        // location has changed.212        SetValueDidChange(value_type != old_value.GetValueType() ||213                          m_value.GetScalar() != old_value.GetScalar());214      } else {215        // Copy the Value and set the context to use our Variable so it can216        // extract read its value into m_data appropriately217        Value value(m_value);218        if (m_type_sp)219          value.SetContext(Value::ContextType::LLDBType, m_type_sp.get());220        else {221          value.SetCompilerType(m_compiler_type);222        }223 224        m_error = value.GetValueAsData(&exe_ctx, m_data, GetModule().get());225      }226      break;227    }228 229    SetValueIsValid(m_error.Success());230  }231  return m_error.Success();232}233 234bool ValueObjectMemory::IsInScope() {235  // FIXME: Maybe try to read the memory address, and if that works, then236  // we are in scope?237  return true;238}239 240lldb::ModuleSP ValueObjectMemory::GetModule() { return m_address.GetModule(); }241