Path: blob/main/contrib/llvm-project/lldb/source/Expression/DWARFExpressionList.cpp
39587 views
//===-- DWARFExpressionList.cpp -------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Expression/DWARFExpressionList.h"9#include "Plugins/SymbolFile/DWARF/DWARFUnit.h"10#include "lldb/Symbol/Function.h"11#include "lldb/Target/RegisterContext.h"12#include "lldb/Target/StackFrame.h"13#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"14#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"1516using namespace lldb;17using namespace lldb_private;1819bool DWARFExpressionList::IsAlwaysValidSingleExpr() const {20return GetAlwaysValidExpr() != nullptr;21}2223const DWARFExpression * DWARFExpressionList::GetAlwaysValidExpr() const {24if (m_exprs.GetSize() != 1)25return nullptr;26const auto *expr = m_exprs.GetEntryAtIndex(0);27if (expr->base == 0 && expr->size == LLDB_INVALID_ADDRESS)28return &expr->data;29return nullptr;30}3132bool DWARFExpressionList::AddExpression(addr_t base, addr_t end,33DWARFExpression expr) {34if (IsAlwaysValidSingleExpr() || base >= end)35return false;36m_exprs.Append({base, end - base, expr});37return true;38}3940bool DWARFExpressionList::GetExpressionData(DataExtractor &data,41lldb::addr_t func_load_addr,42lldb::addr_t file_addr) const {43if (const DWARFExpression *expr =44GetExpressionAtAddress(func_load_addr, file_addr))45return expr->GetExpressionData(data);46return false;47}4849bool DWARFExpressionList::ContainsAddress(lldb::addr_t func_load_addr,50lldb::addr_t addr) const {51if (IsAlwaysValidSingleExpr())52return true;53return GetExpressionAtAddress(func_load_addr, addr) != nullptr;54}5556const DWARFExpression *57DWARFExpressionList::GetExpressionAtAddress(lldb::addr_t func_load_addr,58lldb::addr_t load_addr) const {59if (const DWARFExpression *expr = GetAlwaysValidExpr())60return expr;61if (func_load_addr == LLDB_INVALID_ADDRESS)62func_load_addr = m_func_file_addr;63addr_t addr = load_addr - func_load_addr + m_func_file_addr;64uint32_t index = m_exprs.FindEntryIndexThatContains(addr);65if (index == UINT32_MAX)66return nullptr;67return &m_exprs.GetEntryAtIndex(index)->data;68}6970DWARFExpression *71DWARFExpressionList::GetMutableExpressionAtAddress(lldb::addr_t func_load_addr,72lldb::addr_t load_addr) {73if (IsAlwaysValidSingleExpr())74return &m_exprs.GetMutableEntryAtIndex(0)->data;75if (func_load_addr == LLDB_INVALID_ADDRESS)76func_load_addr = m_func_file_addr;77addr_t addr = load_addr - func_load_addr + m_func_file_addr;78uint32_t index = m_exprs.FindEntryIndexThatContains(addr);79if (index == UINT32_MAX)80return nullptr;81return &m_exprs.GetMutableEntryAtIndex(index)->data;82}8384bool DWARFExpressionList::ContainsThreadLocalStorage() const {85// We are assuming for now that any thread local variable will not have a86// location list. This has been true for all thread local variables we have87// seen so far produced by any compiler.88if (!IsAlwaysValidSingleExpr())89return false;9091const DWARFExpression &expr = m_exprs.GetEntryRef(0).data;92return expr.ContainsThreadLocalStorage(m_dwarf_cu);93}9495bool DWARFExpressionList::LinkThreadLocalStorage(96lldb::ModuleSP new_module_sp,97std::function<lldb::addr_t(lldb::addr_t file_addr)> const98&link_address_callback) {99// We are assuming for now that any thread local variable will not have a100// location list. This has been true for all thread local variables we have101// seen so far produced by any compiler.102if (!IsAlwaysValidSingleExpr())103return false;104105DWARFExpression &expr = m_exprs.GetEntryRef(0).data;106// If we linked the TLS address correctly, update the module so that when the107// expression is evaluated it can resolve the file address to a load address108// and read the TLS data109if (expr.LinkThreadLocalStorage(m_dwarf_cu, link_address_callback))110m_module_wp = new_module_sp;111return true;112}113114bool DWARFExpressionList::MatchesOperand(115StackFrame &frame, const Instruction::Operand &operand) const {116RegisterContextSP reg_ctx_sp = frame.GetRegisterContext();117if (!reg_ctx_sp) {118return false;119}120const DWARFExpression *expr = nullptr;121if (IsAlwaysValidSingleExpr())122expr = &m_exprs.GetEntryAtIndex(0)->data;123else {124SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction);125if (!sc.function)126return false;127128addr_t load_function_start =129sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();130if (load_function_start == LLDB_INVALID_ADDRESS)131return false;132133addr_t pc = frame.GetFrameCodeAddressForSymbolication().GetFileAddress();134expr = GetExpressionAtAddress(LLDB_INVALID_ADDRESS, pc);135}136if (!expr)137return false;138return expr->MatchesOperand(frame, operand);139}140141bool DWARFExpressionList::DumpLocations(Stream *s, lldb::DescriptionLevel level,142lldb::addr_t func_load_addr,143lldb::addr_t file_addr,144ABI *abi) const {145llvm::raw_ostream &os = s->AsRawOstream();146llvm::ListSeparator separator;147if (const DWARFExpression *expr = GetAlwaysValidExpr()) {148expr->DumpLocation(s, level, abi);149return true;150}151for (const Entry &entry : *this) {152addr_t load_base = entry.GetRangeBase() + func_load_addr - m_func_file_addr;153addr_t load_end = entry.GetRangeEnd() + func_load_addr - m_func_file_addr;154if (file_addr != LLDB_INVALID_ADDRESS &&155(file_addr < load_base || file_addr >= load_end))156continue;157const auto &expr = entry.data;158DataExtractor data;159expr.GetExpressionData(data);160uint32_t addr_size = data.GetAddressByteSize();161162os << separator;163os << "[";164os << llvm::format_hex(load_base, 2 + 2 * addr_size);165os << ", ";166os << llvm::format_hex(load_end, 2 + 2 * addr_size);167os << ") -> ";168expr.DumpLocation(s, level, abi);169if (file_addr != LLDB_INVALID_ADDRESS)170break;171}172return true;173}174175void DWARFExpressionList::GetDescription(Stream *s,176lldb::DescriptionLevel level,177ABI *abi) const {178llvm::raw_ostream &os = s->AsRawOstream();179if (IsAlwaysValidSingleExpr()) {180m_exprs.Back()->data.DumpLocation(s, level, abi);181return;182}183os << llvm::format("0x%8.8" PRIx64 ": ", 0);184for (const Entry &entry : *this) {185const auto &expr = entry.data;186DataExtractor data;187expr.GetExpressionData(data);188uint32_t addr_size = data.GetAddressByteSize();189os << "\n";190os.indent(s->GetIndentLevel() + 2);191os << "[";192llvm::DWARFFormValue::dumpAddress(os, addr_size, entry.GetRangeBase());193os << ", ";194llvm::DWARFFormValue::dumpAddress(os, addr_size, entry.GetRangeEnd());195os << "): ";196expr.DumpLocation(s, level, abi);197}198}199200llvm::Expected<Value> DWARFExpressionList::Evaluate(201ExecutionContext *exe_ctx, RegisterContext *reg_ctx,202lldb::addr_t func_load_addr, const Value *initial_value_ptr,203const Value *object_address_ptr) const {204ModuleSP module_sp = m_module_wp.lock();205DataExtractor data;206RegisterKind reg_kind;207DWARFExpression expr;208if (IsAlwaysValidSingleExpr()) {209expr = m_exprs.Back()->data;210} else {211Address pc;212StackFrame *frame = nullptr;213if (!reg_ctx || !reg_ctx->GetPCForSymbolication(pc)) {214if (exe_ctx)215frame = exe_ctx->GetFramePtr();216if (!frame)217return llvm::createStringError("no frame");218RegisterContextSP reg_ctx_sp = frame->GetRegisterContext();219if (!reg_ctx_sp)220return llvm::createStringError("no register context");221reg_ctx_sp->GetPCForSymbolication(pc);222}223224if (!pc.IsValid()) {225return llvm::createStringError("Invalid PC in frame.");226}227addr_t pc_load_addr = pc.GetLoadAddress(exe_ctx->GetTargetPtr());228const DWARFExpression *entry =229GetExpressionAtAddress(func_load_addr, pc_load_addr);230if (!entry)231return llvm::createStringError("variable not available");232expr = *entry;233}234expr.GetExpressionData(data);235reg_kind = expr.GetRegisterKind();236return DWARFExpression::Evaluate(exe_ctx, reg_ctx, module_sp, data,237m_dwarf_cu, reg_kind, initial_value_ptr,238object_address_ptr);239}240241242