1*753f127fSDimitry Andric //===-- DWARFExpressionList.cpp -------------------------------------------===// 2*753f127fSDimitry Andric // 3*753f127fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*753f127fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*753f127fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*753f127fSDimitry Andric // 7*753f127fSDimitry Andric //===----------------------------------------------------------------------===// 8*753f127fSDimitry Andric 9*753f127fSDimitry Andric #include "lldb/Expression/DWARFExpressionList.h" 10*753f127fSDimitry Andric #include "Plugins/SymbolFile/DWARF/DWARFUnit.h" 11*753f127fSDimitry Andric #include "lldb/Symbol/Function.h" 12*753f127fSDimitry Andric #include "lldb/Target/RegisterContext.h" 13*753f127fSDimitry Andric #include "lldb/Target/StackFrame.h" 14*753f127fSDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" 15*753f127fSDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 16*753f127fSDimitry Andric 17*753f127fSDimitry Andric using namespace lldb; 18*753f127fSDimitry Andric using namespace lldb_private; 19*753f127fSDimitry Andric 20*753f127fSDimitry Andric bool DWARFExpressionList::IsAlwaysValidSingleExpr() const { 21*753f127fSDimitry Andric return GetAlwaysValidExpr() != nullptr; 22*753f127fSDimitry Andric } 23*753f127fSDimitry Andric 24*753f127fSDimitry Andric const DWARFExpression * DWARFExpressionList::GetAlwaysValidExpr() const { 25*753f127fSDimitry Andric if (m_exprs.GetSize() != 1) 26*753f127fSDimitry Andric return nullptr; 27*753f127fSDimitry Andric const auto *expr = m_exprs.GetEntryAtIndex(0); 28*753f127fSDimitry Andric if (expr->base == 0 && expr->size == LLDB_INVALID_ADDRESS) 29*753f127fSDimitry Andric return &expr->data; 30*753f127fSDimitry Andric return nullptr; 31*753f127fSDimitry Andric } 32*753f127fSDimitry Andric 33*753f127fSDimitry Andric bool DWARFExpressionList::AddExpression(addr_t base, addr_t end, 34*753f127fSDimitry Andric DWARFExpression expr) { 35*753f127fSDimitry Andric if (IsAlwaysValidSingleExpr() || base >= end) 36*753f127fSDimitry Andric return false; 37*753f127fSDimitry Andric m_exprs.Append({base, end - base, expr}); 38*753f127fSDimitry Andric return true; 39*753f127fSDimitry Andric } 40*753f127fSDimitry Andric 41*753f127fSDimitry Andric bool DWARFExpressionList::GetExpressionData(DataExtractor &data, 42*753f127fSDimitry Andric lldb::addr_t func_load_addr, 43*753f127fSDimitry Andric lldb::addr_t file_addr) const { 44*753f127fSDimitry Andric if (const DWARFExpression *expr = 45*753f127fSDimitry Andric GetExpressionAtAddress(func_load_addr, file_addr)) 46*753f127fSDimitry Andric return expr->GetExpressionData(data); 47*753f127fSDimitry Andric return false; 48*753f127fSDimitry Andric } 49*753f127fSDimitry Andric 50*753f127fSDimitry Andric bool DWARFExpressionList::ContainsAddress(lldb::addr_t func_load_addr, 51*753f127fSDimitry Andric lldb::addr_t addr) const { 52*753f127fSDimitry Andric if (IsAlwaysValidSingleExpr()) 53*753f127fSDimitry Andric return true; 54*753f127fSDimitry Andric return GetExpressionAtAddress(func_load_addr, addr) != nullptr; 55*753f127fSDimitry Andric } 56*753f127fSDimitry Andric 57*753f127fSDimitry Andric const DWARFExpression * 58*753f127fSDimitry Andric DWARFExpressionList::GetExpressionAtAddress(lldb::addr_t func_load_addr, 59*753f127fSDimitry Andric lldb::addr_t load_addr) const { 60*753f127fSDimitry Andric if (const DWARFExpression *expr = GetAlwaysValidExpr()) 61*753f127fSDimitry Andric return expr; 62*753f127fSDimitry Andric if (func_load_addr == LLDB_INVALID_ADDRESS) 63*753f127fSDimitry Andric func_load_addr = m_func_file_addr; 64*753f127fSDimitry Andric addr_t addr = load_addr - func_load_addr + m_func_file_addr; 65*753f127fSDimitry Andric uint32_t index = m_exprs.FindEntryIndexThatContains(addr); 66*753f127fSDimitry Andric if (index == UINT32_MAX) 67*753f127fSDimitry Andric return nullptr; 68*753f127fSDimitry Andric return &m_exprs.GetEntryAtIndex(index)->data; 69*753f127fSDimitry Andric } 70*753f127fSDimitry Andric 71*753f127fSDimitry Andric DWARFExpression * 72*753f127fSDimitry Andric DWARFExpressionList::GetMutableExpressionAtAddress(lldb::addr_t func_load_addr, 73*753f127fSDimitry Andric lldb::addr_t load_addr) { 74*753f127fSDimitry Andric if (IsAlwaysValidSingleExpr()) 75*753f127fSDimitry Andric return &m_exprs.GetMutableEntryAtIndex(0)->data; 76*753f127fSDimitry Andric if (func_load_addr == LLDB_INVALID_ADDRESS) 77*753f127fSDimitry Andric func_load_addr = m_func_file_addr; 78*753f127fSDimitry Andric addr_t addr = load_addr - func_load_addr + m_func_file_addr; 79*753f127fSDimitry Andric uint32_t index = m_exprs.FindEntryIndexThatContains(addr); 80*753f127fSDimitry Andric if (index == UINT32_MAX) 81*753f127fSDimitry Andric return nullptr; 82*753f127fSDimitry Andric return &m_exprs.GetMutableEntryAtIndex(index)->data; 83*753f127fSDimitry Andric } 84*753f127fSDimitry Andric 85*753f127fSDimitry Andric bool DWARFExpressionList::ContainsThreadLocalStorage() const { 86*753f127fSDimitry Andric // We are assuming for now that any thread local variable will not have a 87*753f127fSDimitry Andric // location list. This has been true for all thread local variables we have 88*753f127fSDimitry Andric // seen so far produced by any compiler. 89*753f127fSDimitry Andric if (!IsAlwaysValidSingleExpr()) 90*753f127fSDimitry Andric return false; 91*753f127fSDimitry Andric 92*753f127fSDimitry Andric const DWARFExpression &expr = m_exprs.GetEntryRef(0).data; 93*753f127fSDimitry Andric return expr.ContainsThreadLocalStorage(); 94*753f127fSDimitry Andric } 95*753f127fSDimitry Andric 96*753f127fSDimitry Andric bool DWARFExpressionList::LinkThreadLocalStorage( 97*753f127fSDimitry Andric lldb::ModuleSP new_module_sp, 98*753f127fSDimitry Andric std::function<lldb::addr_t(lldb::addr_t file_addr)> const 99*753f127fSDimitry Andric &link_address_callback) { 100*753f127fSDimitry Andric // We are assuming for now that any thread local variable will not have a 101*753f127fSDimitry Andric // location list. This has been true for all thread local variables we have 102*753f127fSDimitry Andric // seen so far produced by any compiler. 103*753f127fSDimitry Andric if (!IsAlwaysValidSingleExpr()) 104*753f127fSDimitry Andric return false; 105*753f127fSDimitry Andric 106*753f127fSDimitry Andric DWARFExpression &expr = m_exprs.GetEntryRef(0).data; 107*753f127fSDimitry Andric // If we linked the TLS address correctly, update the module so that when the 108*753f127fSDimitry Andric // expression is evaluated it can resolve the file address to a load address 109*753f127fSDimitry Andric // and read the TLS data 110*753f127fSDimitry Andric if (expr.LinkThreadLocalStorage(link_address_callback)) 111*753f127fSDimitry Andric m_module_wp = new_module_sp; 112*753f127fSDimitry Andric return true; 113*753f127fSDimitry Andric } 114*753f127fSDimitry Andric 115*753f127fSDimitry Andric bool DWARFExpressionList::MatchesOperand( 116*753f127fSDimitry Andric StackFrame &frame, const Instruction::Operand &operand) const { 117*753f127fSDimitry Andric RegisterContextSP reg_ctx_sp = frame.GetRegisterContext(); 118*753f127fSDimitry Andric if (!reg_ctx_sp) { 119*753f127fSDimitry Andric return false; 120*753f127fSDimitry Andric } 121*753f127fSDimitry Andric const DWARFExpression *expr = nullptr; 122*753f127fSDimitry Andric if (IsAlwaysValidSingleExpr()) 123*753f127fSDimitry Andric expr = &m_exprs.GetEntryAtIndex(0)->data; 124*753f127fSDimitry Andric else { 125*753f127fSDimitry Andric SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction); 126*753f127fSDimitry Andric if (!sc.function) 127*753f127fSDimitry Andric return false; 128*753f127fSDimitry Andric 129*753f127fSDimitry Andric addr_t load_function_start = 130*753f127fSDimitry Andric sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); 131*753f127fSDimitry Andric if (load_function_start == LLDB_INVALID_ADDRESS) 132*753f127fSDimitry Andric return false; 133*753f127fSDimitry Andric 134*753f127fSDimitry Andric addr_t pc = frame.GetFrameCodeAddressForSymbolication().GetFileAddress(); 135*753f127fSDimitry Andric expr = GetExpressionAtAddress(LLDB_INVALID_ADDRESS, pc); 136*753f127fSDimitry Andric } 137*753f127fSDimitry Andric if (!expr) 138*753f127fSDimitry Andric return false; 139*753f127fSDimitry Andric return expr->MatchesOperand(frame, operand); 140*753f127fSDimitry Andric } 141*753f127fSDimitry Andric 142*753f127fSDimitry Andric bool DWARFExpressionList::DumpLocations(Stream *s, lldb::DescriptionLevel level, 143*753f127fSDimitry Andric lldb::addr_t func_load_addr, 144*753f127fSDimitry Andric lldb::addr_t file_addr, 145*753f127fSDimitry Andric ABI *abi) const { 146*753f127fSDimitry Andric llvm::raw_ostream &os = s->AsRawOstream(); 147*753f127fSDimitry Andric llvm::ListSeparator separator; 148*753f127fSDimitry Andric if (const DWARFExpression *expr = GetAlwaysValidExpr()) { 149*753f127fSDimitry Andric expr->DumpLocation(s, level, abi); 150*753f127fSDimitry Andric return true; 151*753f127fSDimitry Andric } 152*753f127fSDimitry Andric for (const Entry &entry : *this) { 153*753f127fSDimitry Andric addr_t load_base = entry.GetRangeBase() + func_load_addr - m_func_file_addr; 154*753f127fSDimitry Andric addr_t load_end = entry.GetRangeEnd() + func_load_addr - m_func_file_addr; 155*753f127fSDimitry Andric if (file_addr != LLDB_INVALID_ADDRESS && 156*753f127fSDimitry Andric (file_addr < load_base || file_addr >= load_end)) 157*753f127fSDimitry Andric continue; 158*753f127fSDimitry Andric const auto &expr = entry.data; 159*753f127fSDimitry Andric DataExtractor data; 160*753f127fSDimitry Andric expr.GetExpressionData(data); 161*753f127fSDimitry Andric uint32_t addr_size = data.GetAddressByteSize(); 162*753f127fSDimitry Andric 163*753f127fSDimitry Andric os << separator; 164*753f127fSDimitry Andric os << "["; 165*753f127fSDimitry Andric os << llvm::format_hex(load_base, 2 + 2 * addr_size); 166*753f127fSDimitry Andric os << ", "; 167*753f127fSDimitry Andric os << llvm::format_hex(load_end, 2 + 2 * addr_size); 168*753f127fSDimitry Andric os << ") -> "; 169*753f127fSDimitry Andric expr.DumpLocation(s, level, abi); 170*753f127fSDimitry Andric if (file_addr != LLDB_INVALID_ADDRESS) 171*753f127fSDimitry Andric break; 172*753f127fSDimitry Andric } 173*753f127fSDimitry Andric return true; 174*753f127fSDimitry Andric } 175*753f127fSDimitry Andric 176*753f127fSDimitry Andric void DWARFExpressionList::GetDescription(Stream *s, 177*753f127fSDimitry Andric lldb::DescriptionLevel level, 178*753f127fSDimitry Andric ABI *abi) const { 179*753f127fSDimitry Andric llvm::raw_ostream &os = s->AsRawOstream(); 180*753f127fSDimitry Andric if (IsAlwaysValidSingleExpr()) { 181*753f127fSDimitry Andric m_exprs.Back()->data.DumpLocation(s, level, abi); 182*753f127fSDimitry Andric return; 183*753f127fSDimitry Andric } 184*753f127fSDimitry Andric os << llvm::format("0x%8.8" PRIx64 ": ", 0); 185*753f127fSDimitry Andric for (const Entry &entry : *this) { 186*753f127fSDimitry Andric const auto &expr = entry.data; 187*753f127fSDimitry Andric DataExtractor data; 188*753f127fSDimitry Andric expr.GetExpressionData(data); 189*753f127fSDimitry Andric uint32_t addr_size = data.GetAddressByteSize(); 190*753f127fSDimitry Andric os << "\n"; 191*753f127fSDimitry Andric os.indent(s->GetIndentLevel() + 2); 192*753f127fSDimitry Andric os << "["; 193*753f127fSDimitry Andric llvm::DWARFFormValue::dumpAddress(os, addr_size, entry.GetRangeBase()); 194*753f127fSDimitry Andric os << ", "; 195*753f127fSDimitry Andric llvm::DWARFFormValue::dumpAddress(os, addr_size, entry.GetRangeEnd()); 196*753f127fSDimitry Andric os << "): "; 197*753f127fSDimitry Andric expr.DumpLocation(s, level, abi); 198*753f127fSDimitry Andric } 199*753f127fSDimitry Andric } 200*753f127fSDimitry Andric 201*753f127fSDimitry Andric bool DWARFExpressionList::Evaluate(ExecutionContext *exe_ctx, 202*753f127fSDimitry Andric RegisterContext *reg_ctx, 203*753f127fSDimitry Andric lldb::addr_t func_load_addr, 204*753f127fSDimitry Andric const Value *initial_value_ptr, 205*753f127fSDimitry Andric const Value *object_address_ptr, 206*753f127fSDimitry Andric Value &result, Status *error_ptr) const { 207*753f127fSDimitry Andric ModuleSP module_sp = m_module_wp.lock(); 208*753f127fSDimitry Andric DataExtractor data; 209*753f127fSDimitry Andric RegisterKind reg_kind; 210*753f127fSDimitry Andric DWARFExpression expr; 211*753f127fSDimitry Andric if (IsAlwaysValidSingleExpr()) { 212*753f127fSDimitry Andric expr = m_exprs.Back()->data; 213*753f127fSDimitry Andric } else { 214*753f127fSDimitry Andric Address pc; 215*753f127fSDimitry Andric StackFrame *frame = nullptr; 216*753f127fSDimitry Andric if (!reg_ctx || !reg_ctx->GetPCForSymbolication(pc)) { 217*753f127fSDimitry Andric if (exe_ctx) 218*753f127fSDimitry Andric frame = exe_ctx->GetFramePtr(); 219*753f127fSDimitry Andric if (!frame) 220*753f127fSDimitry Andric return false; 221*753f127fSDimitry Andric RegisterContextSP reg_ctx_sp = frame->GetRegisterContext(); 222*753f127fSDimitry Andric if (!reg_ctx_sp) 223*753f127fSDimitry Andric return false; 224*753f127fSDimitry Andric reg_ctx_sp->GetPCForSymbolication(pc); 225*753f127fSDimitry Andric } 226*753f127fSDimitry Andric 227*753f127fSDimitry Andric if (!pc.IsValid()) { 228*753f127fSDimitry Andric if (error_ptr) 229*753f127fSDimitry Andric error_ptr->SetErrorString("Invalid PC in frame."); 230*753f127fSDimitry Andric return false; 231*753f127fSDimitry Andric } 232*753f127fSDimitry Andric addr_t pc_load_addr = pc.GetLoadAddress(exe_ctx->GetTargetPtr()); 233*753f127fSDimitry Andric const DWARFExpression *entry = 234*753f127fSDimitry Andric GetExpressionAtAddress(func_load_addr, pc_load_addr); 235*753f127fSDimitry Andric if (!entry) { 236*753f127fSDimitry Andric if (error_ptr) { 237*753f127fSDimitry Andric error_ptr->SetErrorString("variable not available"); 238*753f127fSDimitry Andric } 239*753f127fSDimitry Andric return false; 240*753f127fSDimitry Andric } 241*753f127fSDimitry Andric expr = *entry; 242*753f127fSDimitry Andric } 243*753f127fSDimitry Andric expr.GetExpressionData(data); 244*753f127fSDimitry Andric reg_kind = expr.GetRegisterKind(); 245*753f127fSDimitry Andric return DWARFExpression::Evaluate(exe_ctx, reg_ctx, module_sp, data, 246*753f127fSDimitry Andric m_dwarf_cu, reg_kind, initial_value_ptr, 247*753f127fSDimitry Andric object_address_ptr, result, error_ptr); 248*753f127fSDimitry Andric } 249