brintos

brintos / llvm-project-archived public Read only

0
0
Text · 22.4 KiB · f9e65d3 Raw
706 lines · cpp
1//===-- Value.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/Core/Value.h"10 11#include "lldb/Core/Address.h"12#include "lldb/Core/Module.h"13#include "lldb/Symbol/CompilerType.h"14#include "lldb/Symbol/ObjectFile.h"15#include "lldb/Symbol/SymbolContext.h"16#include "lldb/Symbol/Type.h"17#include "lldb/Symbol/Variable.h"18#include "lldb/Target/ExecutionContext.h"19#include "lldb/Target/Process.h"20#include "lldb/Target/SectionLoadList.h"21#include "lldb/Target/Target.h"22#include "lldb/Utility/ConstString.h"23#include "lldb/Utility/DataBufferHeap.h"24#include "lldb/Utility/DataExtractor.h"25#include "lldb/Utility/Endian.h"26#include "lldb/Utility/FileSpec.h"27#include "lldb/Utility/LLDBLog.h"28#include "lldb/Utility/Log.h"29#include "lldb/Utility/State.h"30#include "lldb/Utility/Stream.h"31#include "lldb/lldb-defines.h"32#include "lldb/lldb-forward.h"33#include "lldb/lldb-types.h"34 35#include <memory>36#include <optional>37#include <string>38 39#include <cinttypes>40 41using namespace lldb;42using namespace lldb_private;43 44Value::Value() : m_value(), m_compiler_type(), m_data_buffer() {}45 46Value::Value(const Scalar &scalar)47    : m_value(scalar), m_compiler_type(), m_data_buffer() {}48 49Value::Value(const void *bytes, int len)50    : m_value(), m_compiler_type(), m_value_type(ValueType::HostAddress),51      m_data_buffer() {52  SetBytes(bytes, len);53}54 55Value::Value(const Value &v)56    : m_value(v.m_value), m_compiler_type(v.m_compiler_type),57      m_context(v.m_context), m_value_type(v.m_value_type),58      m_context_type(v.m_context_type), m_data_buffer() {59  const uintptr_t rhs_value =60      (uintptr_t)v.m_value.ULongLong(LLDB_INVALID_ADDRESS);61  if ((rhs_value != 0) &&62      (rhs_value == (uintptr_t)v.m_data_buffer.GetBytes())) {63    m_data_buffer.CopyData(v.m_data_buffer.GetBytes(),64                           v.m_data_buffer.GetByteSize());65 66    m_value = (uintptr_t)m_data_buffer.GetBytes();67  }68}69 70Value &Value::operator=(const Value &rhs) {71  if (this != &rhs) {72    m_value = rhs.m_value;73    m_compiler_type = rhs.m_compiler_type;74    m_context = rhs.m_context;75    m_value_type = rhs.m_value_type;76    m_context_type = rhs.m_context_type;77    const uintptr_t rhs_value =78        (uintptr_t)rhs.m_value.ULongLong(LLDB_INVALID_ADDRESS);79    if ((rhs_value != 0) &&80        (rhs_value == (uintptr_t)rhs.m_data_buffer.GetBytes())) {81      m_data_buffer.CopyData(rhs.m_data_buffer.GetBytes(),82                             rhs.m_data_buffer.GetByteSize());83 84      m_value = (uintptr_t)m_data_buffer.GetBytes();85    }86  }87  return *this;88}89 90void Value::SetBytes(const void *bytes, int len) {91  m_value_type = ValueType::HostAddress;92  m_data_buffer.CopyData(bytes, len);93  m_value = (uintptr_t)m_data_buffer.GetBytes();94}95 96void Value::AppendBytes(const void *bytes, int len) {97  m_value_type = ValueType::HostAddress;98  m_data_buffer.AppendData(bytes, len);99  m_value = (uintptr_t)m_data_buffer.GetBytes();100}101 102void Value::Dump(Stream *strm) {103  if (!strm)104    return;105  m_value.GetValue(*strm, true);106  strm->Printf(", value_type = %s, context = %p, context_type = %s",107               Value::GetValueTypeAsCString(m_value_type), m_context,108               Value::GetContextTypeAsCString(m_context_type));109}110 111Value::ValueType Value::GetValueType() const { return m_value_type; }112 113AddressType Value::GetValueAddressType() const {114  switch (m_value_type) {115  case ValueType::Invalid:116  case ValueType::Scalar:117    break;118  case ValueType::LoadAddress:119    return eAddressTypeLoad;120  case ValueType::FileAddress:121    return eAddressTypeFile;122  case ValueType::HostAddress:123    return eAddressTypeHost;124  }125  return eAddressTypeInvalid;126}127 128Value::ValueType Value::GetValueTypeFromAddressType(AddressType address_type) {129  switch (address_type) {130    case eAddressTypeFile:131      return Value::ValueType::FileAddress;132    case eAddressTypeLoad:133      return Value::ValueType::LoadAddress;134    case eAddressTypeHost:135      return Value::ValueType::HostAddress;136    case eAddressTypeInvalid:137      return Value::ValueType::Invalid;138  }139  llvm_unreachable("Unexpected address type!");140}141 142RegisterInfo *Value::GetRegisterInfo() const {143  if (m_context_type == ContextType::RegisterInfo)144    return static_cast<RegisterInfo *>(m_context);145  return nullptr;146}147 148Type *Value::GetType() {149  if (m_context_type == ContextType::LLDBType)150    return static_cast<Type *>(m_context);151  return nullptr;152}153 154size_t Value::AppendDataToHostBuffer(const Value &rhs) {155  if (this == &rhs)156    return 0;157 158  size_t curr_size = m_data_buffer.GetByteSize();159  Status error;160  switch (rhs.GetValueType()) {161  case ValueType::Invalid:162    return 0;163  case ValueType::Scalar: {164    const size_t scalar_size = rhs.m_value.GetByteSize();165    if (scalar_size > 0) {166      const size_t new_size = curr_size + scalar_size;167      if (ResizeData(new_size) == new_size) {168        rhs.m_value.GetAsMemoryData(m_data_buffer.GetBytes() + curr_size,169                                    scalar_size, endian::InlHostByteOrder(),170                                    error);171        return scalar_size;172      }173    }174  } break;175  case ValueType::FileAddress:176  case ValueType::LoadAddress:177  case ValueType::HostAddress: {178    const uint8_t *src = rhs.GetBuffer().GetBytes();179    const size_t src_len = rhs.GetBuffer().GetByteSize();180    if (src && src_len > 0) {181      const size_t new_size = curr_size + src_len;182      if (ResizeData(new_size) == new_size) {183        ::memcpy(m_data_buffer.GetBytes() + curr_size, src, src_len);184        return src_len;185      }186    }187  } break;188  }189  return 0;190}191 192size_t Value::ResizeData(size_t len) {193  m_value_type = ValueType::HostAddress;194  m_data_buffer.SetByteSize(len);195  m_value = (uintptr_t)m_data_buffer.GetBytes();196  return m_data_buffer.GetByteSize();197}198 199bool Value::ValueOf(ExecutionContext *exe_ctx) {200  switch (m_context_type) {201  case ContextType::Invalid:202  case ContextType::RegisterInfo: // RegisterInfo *203  case ContextType::LLDBType:     // Type *204    break;205 206  case ContextType::Variable: // Variable *207    ResolveValue(exe_ctx);208    return true;209  }210  return false;211}212 213uint64_t Value::GetValueByteSize(Status *error_ptr, ExecutionContext *exe_ctx) {214  switch (m_context_type) {215  case ContextType::RegisterInfo: // RegisterInfo *216    if (GetRegisterInfo()) {217      if (error_ptr)218        error_ptr->Clear();219      return GetRegisterInfo()->byte_size;220    }221    break;222 223  case ContextType::Invalid:224  case ContextType::LLDBType: // Type *225  case ContextType::Variable: // Variable *226  {227    auto *scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;228    auto size_or_err = GetCompilerType().GetByteSize(scope);229    if (!size_or_err) {230      if (error_ptr && error_ptr->Success())231        *error_ptr = Status::FromError(size_or_err.takeError());232      else233        LLDB_LOG_ERRORV(GetLog(LLDBLog::Types), size_or_err.takeError(), "{0}");234    } else {235      if (error_ptr)236        error_ptr->Clear();237      return *size_or_err;238    }239    break;240  }241  }242  if (error_ptr && error_ptr->Success())243    *error_ptr = Status::FromErrorString("Unable to determine byte size.");244  return 0;245}246 247const CompilerType &Value::GetCompilerType() {248  if (!m_compiler_type.IsValid()) {249    switch (m_context_type) {250    case ContextType::Invalid:251      break;252 253    case ContextType::RegisterInfo:254      break; // TODO: Eventually convert into a compiler type?255 256    case ContextType::LLDBType: {257      Type *lldb_type = GetType();258      if (lldb_type)259        m_compiler_type = lldb_type->GetForwardCompilerType();260    } break;261 262    case ContextType::Variable: {263      Variable *variable = GetVariable();264      if (variable) {265        Type *variable_type = variable->GetType();266        if (variable_type)267          m_compiler_type = variable_type->GetForwardCompilerType();268      }269    } break;270    }271  }272 273  return m_compiler_type;274}275 276void Value::SetCompilerType(const CompilerType &compiler_type) {277  m_compiler_type = compiler_type;278}279 280lldb::Format Value::GetValueDefaultFormat() {281  switch (m_context_type) {282  case ContextType::RegisterInfo:283    if (GetRegisterInfo())284      return GetRegisterInfo()->format;285    break;286 287  case ContextType::Invalid:288  case ContextType::LLDBType:289  case ContextType::Variable: {290    const CompilerType &ast_type = GetCompilerType();291    if (ast_type.IsValid())292      return ast_type.GetFormat();293  } break;294  }295 296  // Return a good default in case we can't figure anything out297  return eFormatHex;298}299 300bool Value::GetData(DataExtractor &data) {301  switch (m_value_type) {302  case ValueType::Invalid:303    return false;304  case ValueType::Scalar:305    if (m_value.GetData(data))306      return true;307    break;308 309  case ValueType::LoadAddress:310  case ValueType::FileAddress:311  case ValueType::HostAddress:312    if (m_data_buffer.GetByteSize()) {313      data.SetData(m_data_buffer.GetBytes(), m_data_buffer.GetByteSize(),314                   data.GetByteOrder());315      return true;316    }317    break;318  }319 320  return false;321}322 323Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,324                             Module *module) {325  data.Clear();326 327  Status error;328  lldb::addr_t address = LLDB_INVALID_ADDRESS;329  AddressType address_type = eAddressTypeFile;330  Address file_so_addr;331  const CompilerType &ast_type = GetCompilerType();332  std::optional<uint64_t> type_size =333      llvm::expectedToOptional(ast_type.GetByteSize(334          exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr));335  // Nothing to be done for a zero-sized type.336  if (type_size && *type_size == 0)337    return error;338 339  switch (m_value_type) {340  case ValueType::Invalid:341    error = Status::FromErrorString("invalid value");342    break;343  case ValueType::Scalar: {344    data.SetByteOrder(endian::InlHostByteOrder());345    if (ast_type.IsValid())346      data.SetAddressByteSize(ast_type.GetPointerByteSize());347    else348      data.SetAddressByteSize(sizeof(void *));349 350    if (!type_size)351      return Status::FromErrorString("type does not have a size");352 353    uint32_t result_byte_size = *type_size;354    if (m_value.GetData(data, result_byte_size))355      return error; // Success;356 357    error = Status::FromErrorString("extracting data from value failed");358    break;359  }360  case ValueType::LoadAddress:361    if (exe_ctx == nullptr) {362      error = Status::FromErrorString(363          "can't read load address (no execution context)");364    } else {365      Process *process = exe_ctx->GetProcessPtr();366      if (process == nullptr || !process->IsAlive()) {367        Target *target = exe_ctx->GetTargetPtr();368        if (target) {369          // Allow expressions to run and evaluate things when the target has370          // memory sections loaded. This allows you to use "target modules371          // load" to load your executable and any shared libraries, then372          // execute commands where you can look at types in data sections.373          if (target->HasLoadedSections()) {374            address = m_value.ULongLong(LLDB_INVALID_ADDRESS);375            if (target->ResolveLoadAddress(address, file_so_addr)) {376              address_type = eAddressTypeLoad;377              data.SetByteOrder(target->GetArchitecture().GetByteOrder());378              data.SetAddressByteSize(379                  target->GetArchitecture().GetAddressByteSize());380            } else381              address = LLDB_INVALID_ADDRESS;382          }383        } else {384          error = Status::FromErrorString(385              "can't read load address (invalid process)");386        }387      } else {388        address = m_value.ULongLong(LLDB_INVALID_ADDRESS);389        address_type = eAddressTypeLoad;390        data.SetByteOrder(391            process->GetTarget().GetArchitecture().GetByteOrder());392        data.SetAddressByteSize(393            process->GetTarget().GetArchitecture().GetAddressByteSize());394      }395    }396    break;397 398  case ValueType::FileAddress:399    if (exe_ctx == nullptr) {400      error = Status::FromErrorString(401          "can't read file address (no execution context)");402    } else if (exe_ctx->GetTargetPtr() == nullptr) {403      error =404          Status::FromErrorString("can't read file address (invalid target)");405    } else {406      address = m_value.ULongLong(LLDB_INVALID_ADDRESS);407      if (address == LLDB_INVALID_ADDRESS) {408        error = Status::FromErrorString("invalid file address");409      } else {410        if (module == nullptr) {411          // The only thing we can currently lock down to a module so that we412          // can resolve a file address, is a variable.413          Variable *variable = GetVariable();414          if (variable) {415            SymbolContext var_sc;416            variable->CalculateSymbolContext(&var_sc);417            module = var_sc.module_sp.get();418          }419        }420 421        if (module) {422          bool resolved = false;423          ObjectFile *objfile = module->GetObjectFile();424          if (objfile) {425            Address so_addr(address, objfile->GetSectionList());426            addr_t load_address =427                so_addr.GetLoadAddress(exe_ctx->GetTargetPtr());428            bool process_launched_and_stopped =429                exe_ctx->GetProcessPtr()430                    ? StateIsStoppedState(exe_ctx->GetProcessPtr()->GetState(),431                                          true /* must_exist */)432                    : false;433            // Don't use the load address if the process has exited.434            if (load_address != LLDB_INVALID_ADDRESS &&435                process_launched_and_stopped) {436              resolved = true;437              address = load_address;438              address_type = eAddressTypeLoad;439              data.SetByteOrder(440                  exe_ctx->GetTargetRef().GetArchitecture().GetByteOrder());441              data.SetAddressByteSize(exe_ctx->GetTargetRef()442                                          .GetArchitecture()443                                          .GetAddressByteSize());444            } else {445              if (so_addr.IsSectionOffset()) {446                resolved = true;447                file_so_addr = so_addr;448                data.SetByteOrder(objfile->GetByteOrder());449                data.SetAddressByteSize(objfile->GetAddressByteSize());450              }451            }452          }453          if (!resolved) {454            Variable *variable = GetVariable();455 456            if (module) {457              if (variable)458                error = Status::FromErrorStringWithFormat(459                    "unable to resolve the module for file address 0x%" PRIx64460                    " for variable '%s' in %s",461                    address, variable->GetName().AsCString(""),462                    module->GetFileSpec().GetPath().c_str());463              else464                error = Status::FromErrorStringWithFormat(465                    "unable to resolve the module for file address 0x%" PRIx64466                    " in %s",467                    address, module->GetFileSpec().GetPath().c_str());468            } else {469              if (variable)470                error = Status::FromErrorStringWithFormat(471                    "unable to resolve the module for file address 0x%" PRIx64472                    " for variable '%s'",473                    address, variable->GetName().AsCString(""));474              else475                error = Status::FromErrorStringWithFormat(476                    "unable to resolve the module for file address 0x%" PRIx64,477                    address);478            }479          }480        } else {481          // Can't convert a file address to anything valid without more482          // context (which Module it came from)483          error = Status::FromErrorString(484              "can't read memory from file address without more context");485        }486      }487    }488    break;489 490  case ValueType::HostAddress:491    address = m_value.ULongLong(LLDB_INVALID_ADDRESS);492    address_type = eAddressTypeHost;493    if (exe_ctx) {494      if (Target *target = exe_ctx->GetTargetPtr()) {495        // Registers are always stored in host endian.496        data.SetByteOrder(m_context_type == ContextType::RegisterInfo497                              ? endian::InlHostByteOrder()498                              : target->GetArchitecture().GetByteOrder());499        data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());500        break;501      }502    }503    // fallback to host settings504    data.SetByteOrder(endian::InlHostByteOrder());505    data.SetAddressByteSize(sizeof(void *));506    break;507  }508 509  // Bail if we encountered any errors510  if (error.Fail())511    return error;512 513  if (address == LLDB_INVALID_ADDRESS) {514    error = Status::FromErrorStringWithFormat(515        "invalid %s address",516        address_type == eAddressTypeHost ? "host" : "load");517    return error;518  }519 520  // If we got here, we need to read the value from memory.521  size_t byte_size = GetValueByteSize(&error, exe_ctx);522 523  // Bail if we encountered any errors getting the byte size.524  if (error.Fail())525    return error;526 527  // No memory to read for zero-sized types.528  if (byte_size == 0)529    return error;530 531  // Make sure we have enough room within "data", and if we don't make532  // something large enough that does533  if (!data.ValidOffsetForDataOfSize(0, byte_size)) {534    auto data_sp = std::make_shared<DataBufferHeap>(byte_size, '\0');535    data.SetData(data_sp);536  }537 538  uint8_t *dst = const_cast<uint8_t *>(data.PeekData(0, byte_size));539  if (dst != nullptr) {540    if (address_type == eAddressTypeHost) {541      // The address is an address in this process, so just copy it.542      if (address == 0) {543        error =544            Status::FromErrorString("trying to read from host address of 0.");545        return error;546      }547      memcpy(dst, reinterpret_cast<uint8_t *>(address), byte_size);548    } else if ((address_type == eAddressTypeLoad) ||549               (address_type == eAddressTypeFile)) {550      if (file_so_addr.IsValid()) {551        const bool force_live_memory = true;552        if (exe_ctx->GetTargetRef().ReadMemory(file_so_addr, dst, byte_size,553                                               error, force_live_memory) !=554            byte_size) {555          error = Status::FromErrorStringWithFormat(556              "read memory from 0x%" PRIx64 " failed", (uint64_t)address);557        }558      } else {559        // The execution context might have a NULL process, but it might have a560        // valid process in the exe_ctx->target, so use the561        // ExecutionContext::GetProcess accessor to ensure we get the process562        // if there is one.563        Process *process = exe_ctx->GetProcessPtr();564 565        if (process) {566          const size_t bytes_read =567              process->ReadMemory(address, dst, byte_size, error);568          if (bytes_read != byte_size)569            error = Status::FromErrorStringWithFormat(570                "read memory from 0x%" PRIx64 " failed (%u of %u bytes read)",571                (uint64_t)address, (uint32_t)bytes_read, (uint32_t)byte_size);572        } else {573          error = Status::FromErrorStringWithFormat(574              "read memory from 0x%" PRIx64 " failed (invalid process)",575              (uint64_t)address);576        }577      }578    } else {579      error = Status::FromErrorStringWithFormat(580          "unsupported AddressType value (%i)", address_type);581    }582  } else {583    error = Status::FromErrorString("out of memory");584  }585 586  return error;587}588 589Scalar &Value::ResolveValue(ExecutionContext *exe_ctx, Module *module) {590  const CompilerType &compiler_type = GetCompilerType();591  if (compiler_type.IsValid()) {592    switch (m_value_type) {593    case ValueType::Invalid:594    case ValueType::Scalar: // raw scalar value595      break;596 597    case ValueType::FileAddress:598    case ValueType::LoadAddress: // load address value599    case ValueType::HostAddress: // host address value (for memory in the process600                                // that is using liblldb)601    {602      DataExtractor data;603      lldb::addr_t addr = m_value.ULongLong(LLDB_INVALID_ADDRESS);604      Status error(GetValueAsData(exe_ctx, data, module));605      if (error.Success()) {606        Scalar scalar;607        if (compiler_type.GetValueAsScalar(608                data, 0, data.GetByteSize(), scalar,609                exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr)) {610          m_value = scalar;611          m_value_type = ValueType::Scalar;612        } else {613          if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes()) {614            m_value.Clear();615            m_value_type = ValueType::Scalar;616          }617        }618      } else {619        if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes()) {620          m_value.Clear();621          m_value_type = ValueType::Scalar;622        }623      }624    } break;625    }626  }627  return m_value;628}629 630Variable *Value::GetVariable() {631  if (m_context_type == ContextType::Variable)632    return static_cast<Variable *>(m_context);633  return nullptr;634}635 636void Value::Clear() {637  m_value.Clear();638  m_compiler_type.Clear();639  m_value_type = ValueType::Scalar;640  m_context = nullptr;641  m_context_type = ContextType::Invalid;642  m_data_buffer.Clear();643}644 645const char *Value::GetValueTypeAsCString(ValueType value_type) {646  switch (value_type) {647  case ValueType::Invalid:648    return "invalid";649  case ValueType::Scalar:650    return "scalar";651  case ValueType::FileAddress:652    return "file address";653  case ValueType::LoadAddress:654    return "load address";655  case ValueType::HostAddress:656    return "host address";657  };658  llvm_unreachable("enum cases exhausted.");659}660 661const char *Value::GetContextTypeAsCString(ContextType context_type) {662  switch (context_type) {663  case ContextType::Invalid:664    return "invalid";665  case ContextType::RegisterInfo:666    return "RegisterInfo *";667  case ContextType::LLDBType:668    return "Type *";669  case ContextType::Variable:670    return "Variable *";671  };672  llvm_unreachable("enum cases exhausted.");673}674 675void Value::ConvertToLoadAddress(Module *module, Target *target) {676  if (!module || !target || (GetValueType() != ValueType::FileAddress))677    return;678 679  lldb::addr_t file_addr = GetScalar().ULongLong(LLDB_INVALID_ADDRESS);680  if (file_addr == LLDB_INVALID_ADDRESS)681    return;682 683  Address so_addr;684  if (!module->ResolveFileAddress(file_addr, so_addr))685    return;686  lldb::addr_t load_addr = so_addr.GetLoadAddress(target);687  if (load_addr == LLDB_INVALID_ADDRESS)688    return;689 690  SetValueType(Value::ValueType::LoadAddress);691  GetScalar() = load_addr;692}693 694void ValueList::PushValue(const Value &value) { m_values.push_back(value); }695 696size_t ValueList::GetSize() { return m_values.size(); }697 698Value *ValueList::GetValueAtIndex(size_t idx) {699  if (idx < GetSize()) {700    return &(m_values[idx]);701  } else702    return nullptr;703}704 705void ValueList::Clear() { m_values.clear(); }706