brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.7 KiB · 91c1740 Raw
272 lines · cpp
1//===-- DWARFExpressionList.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/Expression/DWARFExpressionList.h"10#include "lldb/Core/AddressRange.h"11#include "lldb/Symbol/Function.h"12#include "lldb/Target/RegisterContext.h"13#include "lldb/Target/StackFrame.h"14#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"15#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"16 17using namespace lldb;18using namespace lldb_private;19 20bool DWARFExpressionList::IsAlwaysValidSingleExpr() const {21  return GetAlwaysValidExpr() != nullptr;22}23 24const DWARFExpression *DWARFExpressionList::GetAlwaysValidExpr() const {25  if (m_exprs.GetSize() != 1)26    return nullptr;27  const auto *expr = m_exprs.GetEntryAtIndex(0);28  if (expr->base == 0 && expr->size == LLDB_INVALID_ADDRESS)29    return &expr->data;30  return nullptr;31}32 33bool DWARFExpressionList::AddExpression(addr_t base, addr_t end,34                                        DWARFExpression expr) {35  if (IsAlwaysValidSingleExpr() || base >= end)36    return false;37  m_exprs.Append({base, end - base, expr});38  return true;39}40 41bool DWARFExpressionList::GetExpressionData(DataExtractor &data,42                                            lldb::addr_t func_load_addr,43                                            lldb::addr_t file_addr) const {44  if (const DWARFExpression *expr =45          GetExpressionAtAddress(func_load_addr, file_addr))46    return expr->GetExpressionData(data);47  return false;48}49 50bool DWARFExpressionList::ContainsAddress(lldb::addr_t func_load_addr,51                                          lldb::addr_t addr) const {52  if (IsAlwaysValidSingleExpr())53    return true;54  return GetExpressionAtAddress(func_load_addr, addr) != nullptr;55}56 57std::optional<DWARFExpressionList::DWARFExpressionEntry>58DWARFExpressionList::GetExpressionEntryAtAddress(lldb::addr_t func_load_addr,59                                                 lldb::addr_t load_addr) const {60  if (const DWARFExpression *always = GetAlwaysValidExpr()) {61    return DWARFExpressionEntry{std::nullopt, always};62  }63 64  if (func_load_addr == LLDB_INVALID_ADDRESS)65    func_load_addr = m_func_file_addr;66 67  // Guard against underflow when translating a load address back into file68  // space.69  if (load_addr < func_load_addr)70    return std::nullopt;71 72  // Guard against overflow.73  lldb::addr_t delta = load_addr - func_load_addr;74  if (delta > std::numeric_limits<lldb::addr_t>::max() - m_func_file_addr)75    return std::nullopt;76 77  lldb::addr_t file_pc = (load_addr - func_load_addr) + m_func_file_addr;78 79  if (const auto *entry = m_exprs.FindEntryThatContains(file_pc)) {80    AddressRange range_in_file(entry->GetRangeBase(),81                               entry->GetRangeEnd() - entry->GetRangeBase());82    return DWARFExpressionEntry{range_in_file, &entry->data};83  }84 85  // No entry covers this PC:86  return std::nullopt;87}88 89const DWARFExpression *90DWARFExpressionList::GetExpressionAtAddress(lldb::addr_t func_load_addr,91                                            lldb::addr_t load_addr) const {92  if (const DWARFExpression *expr = GetAlwaysValidExpr())93    return expr;94  if (func_load_addr == LLDB_INVALID_ADDRESS)95    func_load_addr = m_func_file_addr;96  addr_t addr = load_addr - func_load_addr + m_func_file_addr;97  uint32_t index = m_exprs.FindEntryIndexThatContains(addr);98  if (index == UINT32_MAX)99    return nullptr;100  return &m_exprs.GetEntryAtIndex(index)->data;101}102 103DWARFExpression *104DWARFExpressionList::GetMutableExpressionAtAddress(lldb::addr_t func_load_addr,105                                                   lldb::addr_t load_addr) {106  if (IsAlwaysValidSingleExpr())107    return &m_exprs.GetMutableEntryAtIndex(0)->data;108  if (func_load_addr == LLDB_INVALID_ADDRESS)109    func_load_addr = m_func_file_addr;110  addr_t addr = load_addr - func_load_addr + m_func_file_addr;111  uint32_t index = m_exprs.FindEntryIndexThatContains(addr);112  if (index == UINT32_MAX)113    return nullptr;114  return &m_exprs.GetMutableEntryAtIndex(index)->data;115}116 117bool DWARFExpressionList::ContainsThreadLocalStorage() const {118  // We are assuming for now that any thread local variable will not have a119  // location list. This has been true for all thread local variables we have120  // seen so far produced by any compiler.121  if (!IsAlwaysValidSingleExpr())122    return false;123 124  const DWARFExpression &expr = m_exprs.GetEntryRef(0).data;125  return expr.ContainsThreadLocalStorage(m_dwarf_cu);126}127 128bool DWARFExpressionList::LinkThreadLocalStorage(129    lldb::ModuleSP new_module_sp,130    std::function<lldb::addr_t(lldb::addr_t file_addr)> const131        &link_address_callback) {132  // We are assuming for now that any thread local variable will not have a133  // location list. This has been true for all thread local variables we have134  // seen so far produced by any compiler.135  if (!IsAlwaysValidSingleExpr())136    return false;137 138  DWARFExpression &expr = m_exprs.GetEntryRef(0).data;139  // If we linked the TLS address correctly, update the module so that when the140  // expression is evaluated it can resolve the file address to a load address141  // and read the TLS data142  if (expr.LinkThreadLocalStorage(m_dwarf_cu, link_address_callback))143    m_module_wp = new_module_sp;144  return true;145}146 147bool DWARFExpressionList::MatchesOperand(148    StackFrame &frame, const Instruction::Operand &operand) const {149  RegisterContextSP reg_ctx_sp = frame.GetRegisterContext();150  if (!reg_ctx_sp) {151    return false;152  }153  const DWARFExpression *expr = nullptr;154  if (IsAlwaysValidSingleExpr())155    expr = &m_exprs.GetEntryAtIndex(0)->data;156  else {157    SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction);158    if (!sc.function)159      return false;160 161    addr_t load_function_start = sc.function->GetAddress().GetFileAddress();162    if (load_function_start == LLDB_INVALID_ADDRESS)163      return false;164 165    addr_t pc = frame.GetFrameCodeAddressForSymbolication().GetFileAddress();166    expr = GetExpressionAtAddress(LLDB_INVALID_ADDRESS, pc);167  }168  if (!expr)169    return false;170  return expr->MatchesOperand(frame, operand);171}172 173bool DWARFExpressionList::DumpLocations(Stream *s, lldb::DescriptionLevel level,174                                        lldb::addr_t func_load_addr,175                                        lldb::addr_t file_addr,176                                        ABI *abi) const {177  llvm::raw_ostream &os = s->AsRawOstream();178  llvm::ListSeparator separator;179  if (const DWARFExpression *expr = GetAlwaysValidExpr()) {180    expr->DumpLocation(s, level, abi);181    return true;182  }183  for (const Entry &entry : *this) {184    addr_t load_base = entry.GetRangeBase() + func_load_addr - m_func_file_addr;185    addr_t load_end = entry.GetRangeEnd() + func_load_addr - m_func_file_addr;186    if (file_addr != LLDB_INVALID_ADDRESS &&187        (file_addr < load_base || file_addr >= load_end))188      continue;189    const auto &expr = entry.data;190    DataExtractor data;191    expr.GetExpressionData(data);192    uint32_t addr_size = data.GetAddressByteSize();193 194    os << separator;195    os << "[";196    os << llvm::format_hex(load_base, 2 + 2 * addr_size);197    os << ", ";198    os << llvm::format_hex(load_end, 2 + 2 * addr_size);199    os << ") -> ";200    expr.DumpLocation(s, level, abi);201    if (file_addr != LLDB_INVALID_ADDRESS)202      break;203  }204  return true;205}206 207void DWARFExpressionList::GetDescription(Stream *s,208                                         lldb::DescriptionLevel level,209                                         ABI *abi) const {210  llvm::raw_ostream &os = s->AsRawOstream();211  if (IsAlwaysValidSingleExpr()) {212    m_exprs.Back()->data.DumpLocation(s, level, abi);213    return;214  }215  os << llvm::format("0x%8.8" PRIx64 ": ", 0);216  for (const Entry &entry : *this) {217    const auto &expr = entry.data;218    DataExtractor data;219    expr.GetExpressionData(data);220    uint32_t addr_size = data.GetAddressByteSize();221    os << "\n";222    os.indent(s->GetIndentLevel() + 2);223    os << "[";224    llvm::DWARFFormValue::dumpAddress(os, addr_size, entry.GetRangeBase());225    os << ", ";226    llvm::DWARFFormValue::dumpAddress(os, addr_size, entry.GetRangeEnd());227    os << "): ";228    expr.DumpLocation(s, level, abi);229  }230}231 232llvm::Expected<Value> DWARFExpressionList::Evaluate(233    ExecutionContext *exe_ctx, RegisterContext *reg_ctx,234    lldb::addr_t func_load_addr, const Value *initial_value_ptr,235    const Value *object_address_ptr) const {236  ModuleSP module_sp = m_module_wp.lock();237  DataExtractor data;238  RegisterKind reg_kind;239  DWARFExpression expr;240  if (IsAlwaysValidSingleExpr()) {241    expr = m_exprs.Back()->data;242  } else {243    Address pc;244    StackFrame *frame = nullptr;245    if (!reg_ctx || !reg_ctx->GetPCForSymbolication(pc)) {246      if (exe_ctx)247        frame = exe_ctx->GetFramePtr();248      if (!frame)249        return llvm::createStringError("no frame");250      RegisterContextSP reg_ctx_sp = frame->GetRegisterContext();251      if (!reg_ctx_sp)252        return llvm::createStringError("no register context");253      reg_ctx_sp->GetPCForSymbolication(pc);254    }255 256    if (!pc.IsValid()) {257      return llvm::createStringError("invalid PC in frame");258    }259    addr_t pc_load_addr = pc.GetLoadAddress(exe_ctx->GetTargetPtr());260    const DWARFExpression *entry =261        GetExpressionAtAddress(func_load_addr, pc_load_addr);262    if (!entry)263      return llvm::createStringError("variable not available");264    expr = *entry;265  }266  expr.GetExpressionData(data);267  reg_kind = expr.GetRegisterKind();268  return DWARFExpression::Evaluate(exe_ctx, reg_ctx, module_sp, data,269                                   m_dwarf_cu, reg_kind, initial_value_ptr,270                                   object_address_ptr);271}272