1753f127fSDimitry Andric //===-- DWARFExpressionList.cpp -------------------------------------------===// 2753f127fSDimitry Andric // 3753f127fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4753f127fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5753f127fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6753f127fSDimitry Andric // 7753f127fSDimitry Andric //===----------------------------------------------------------------------===// 8753f127fSDimitry Andric 9753f127fSDimitry Andric #include "lldb/Expression/DWARFExpressionList.h" 10753f127fSDimitry Andric #include "Plugins/SymbolFile/DWARF/DWARFUnit.h" 11753f127fSDimitry Andric #include "lldb/Symbol/Function.h" 12753f127fSDimitry Andric #include "lldb/Target/RegisterContext.h" 13753f127fSDimitry Andric #include "lldb/Target/StackFrame.h" 14753f127fSDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" 15753f127fSDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 16753f127fSDimitry Andric 17753f127fSDimitry Andric using namespace lldb; 18753f127fSDimitry Andric using namespace lldb_private; 19753f127fSDimitry Andric 20753f127fSDimitry Andric bool DWARFExpressionList::IsAlwaysValidSingleExpr() const { 21753f127fSDimitry Andric return GetAlwaysValidExpr() != nullptr; 22753f127fSDimitry Andric } 23753f127fSDimitry Andric 24753f127fSDimitry Andric const DWARFExpression * DWARFExpressionList::GetAlwaysValidExpr() const { 25753f127fSDimitry Andric if (m_exprs.GetSize() != 1) 26753f127fSDimitry Andric return nullptr; 27753f127fSDimitry Andric const auto *expr = m_exprs.GetEntryAtIndex(0); 28753f127fSDimitry Andric if (expr->base == 0 && expr->size == LLDB_INVALID_ADDRESS) 29753f127fSDimitry Andric return &expr->data; 30753f127fSDimitry Andric return nullptr; 31753f127fSDimitry Andric } 32753f127fSDimitry Andric 33753f127fSDimitry Andric bool DWARFExpressionList::AddExpression(addr_t base, addr_t end, 34753f127fSDimitry Andric DWARFExpression expr) { 35753f127fSDimitry Andric if (IsAlwaysValidSingleExpr() || base >= end) 36753f127fSDimitry Andric return false; 37753f127fSDimitry Andric m_exprs.Append({base, end - base, expr}); 38753f127fSDimitry Andric return true; 39753f127fSDimitry Andric } 40753f127fSDimitry Andric 41753f127fSDimitry Andric bool DWARFExpressionList::GetExpressionData(DataExtractor &data, 42753f127fSDimitry Andric lldb::addr_t func_load_addr, 43753f127fSDimitry Andric lldb::addr_t file_addr) const { 44753f127fSDimitry Andric if (const DWARFExpression *expr = 45753f127fSDimitry Andric GetExpressionAtAddress(func_load_addr, file_addr)) 46753f127fSDimitry Andric return expr->GetExpressionData(data); 47753f127fSDimitry Andric return false; 48753f127fSDimitry Andric } 49753f127fSDimitry Andric 50753f127fSDimitry Andric bool DWARFExpressionList::ContainsAddress(lldb::addr_t func_load_addr, 51753f127fSDimitry Andric lldb::addr_t addr) const { 52753f127fSDimitry Andric if (IsAlwaysValidSingleExpr()) 53753f127fSDimitry Andric return true; 54753f127fSDimitry Andric return GetExpressionAtAddress(func_load_addr, addr) != nullptr; 55753f127fSDimitry Andric } 56753f127fSDimitry Andric 57753f127fSDimitry Andric const DWARFExpression * 58753f127fSDimitry Andric DWARFExpressionList::GetExpressionAtAddress(lldb::addr_t func_load_addr, 59753f127fSDimitry Andric lldb::addr_t load_addr) const { 60753f127fSDimitry Andric if (const DWARFExpression *expr = GetAlwaysValidExpr()) 61753f127fSDimitry Andric return expr; 62753f127fSDimitry Andric if (func_load_addr == LLDB_INVALID_ADDRESS) 63753f127fSDimitry Andric func_load_addr = m_func_file_addr; 64753f127fSDimitry Andric addr_t addr = load_addr - func_load_addr + m_func_file_addr; 65753f127fSDimitry Andric uint32_t index = m_exprs.FindEntryIndexThatContains(addr); 66753f127fSDimitry Andric if (index == UINT32_MAX) 67753f127fSDimitry Andric return nullptr; 68753f127fSDimitry Andric return &m_exprs.GetEntryAtIndex(index)->data; 69753f127fSDimitry Andric } 70753f127fSDimitry Andric 71753f127fSDimitry Andric DWARFExpression * 72753f127fSDimitry Andric DWARFExpressionList::GetMutableExpressionAtAddress(lldb::addr_t func_load_addr, 73753f127fSDimitry Andric lldb::addr_t load_addr) { 74753f127fSDimitry Andric if (IsAlwaysValidSingleExpr()) 75753f127fSDimitry Andric return &m_exprs.GetMutableEntryAtIndex(0)->data; 76753f127fSDimitry Andric if (func_load_addr == LLDB_INVALID_ADDRESS) 77753f127fSDimitry Andric func_load_addr = m_func_file_addr; 78753f127fSDimitry Andric addr_t addr = load_addr - func_load_addr + m_func_file_addr; 79753f127fSDimitry Andric uint32_t index = m_exprs.FindEntryIndexThatContains(addr); 80753f127fSDimitry Andric if (index == UINT32_MAX) 81753f127fSDimitry Andric return nullptr; 82753f127fSDimitry Andric return &m_exprs.GetMutableEntryAtIndex(index)->data; 83753f127fSDimitry Andric } 84753f127fSDimitry Andric 85753f127fSDimitry Andric bool DWARFExpressionList::ContainsThreadLocalStorage() const { 86753f127fSDimitry Andric // We are assuming for now that any thread local variable will not have a 87753f127fSDimitry Andric // location list. This has been true for all thread local variables we have 88753f127fSDimitry Andric // seen so far produced by any compiler. 89753f127fSDimitry Andric if (!IsAlwaysValidSingleExpr()) 90753f127fSDimitry Andric return false; 91753f127fSDimitry Andric 92753f127fSDimitry Andric const DWARFExpression &expr = m_exprs.GetEntryRef(0).data; 93bdd1243dSDimitry Andric return expr.ContainsThreadLocalStorage(m_dwarf_cu); 94753f127fSDimitry Andric } 95753f127fSDimitry Andric 96753f127fSDimitry Andric bool DWARFExpressionList::LinkThreadLocalStorage( 97753f127fSDimitry Andric lldb::ModuleSP new_module_sp, 98753f127fSDimitry Andric std::function<lldb::addr_t(lldb::addr_t file_addr)> const 99753f127fSDimitry Andric &link_address_callback) { 100753f127fSDimitry Andric // We are assuming for now that any thread local variable will not have a 101753f127fSDimitry Andric // location list. This has been true for all thread local variables we have 102753f127fSDimitry Andric // seen so far produced by any compiler. 103753f127fSDimitry Andric if (!IsAlwaysValidSingleExpr()) 104753f127fSDimitry Andric return false; 105753f127fSDimitry Andric 106753f127fSDimitry Andric DWARFExpression &expr = m_exprs.GetEntryRef(0).data; 107753f127fSDimitry Andric // If we linked the TLS address correctly, update the module so that when the 108753f127fSDimitry Andric // expression is evaluated it can resolve the file address to a load address 109753f127fSDimitry Andric // and read the TLS data 110bdd1243dSDimitry Andric if (expr.LinkThreadLocalStorage(m_dwarf_cu, link_address_callback)) 111753f127fSDimitry Andric m_module_wp = new_module_sp; 112753f127fSDimitry Andric return true; 113753f127fSDimitry Andric } 114753f127fSDimitry Andric 115753f127fSDimitry Andric bool DWARFExpressionList::MatchesOperand( 116753f127fSDimitry Andric StackFrame &frame, const Instruction::Operand &operand) const { 117753f127fSDimitry Andric RegisterContextSP reg_ctx_sp = frame.GetRegisterContext(); 118753f127fSDimitry Andric if (!reg_ctx_sp) { 119753f127fSDimitry Andric return false; 120753f127fSDimitry Andric } 121753f127fSDimitry Andric const DWARFExpression *expr = nullptr; 122753f127fSDimitry Andric if (IsAlwaysValidSingleExpr()) 123753f127fSDimitry Andric expr = &m_exprs.GetEntryAtIndex(0)->data; 124753f127fSDimitry Andric else { 125753f127fSDimitry Andric SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction); 126753f127fSDimitry Andric if (!sc.function) 127753f127fSDimitry Andric return false; 128753f127fSDimitry Andric 129753f127fSDimitry Andric addr_t load_function_start = 130753f127fSDimitry Andric sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); 131753f127fSDimitry Andric if (load_function_start == LLDB_INVALID_ADDRESS) 132753f127fSDimitry Andric return false; 133753f127fSDimitry Andric 134753f127fSDimitry Andric addr_t pc = frame.GetFrameCodeAddressForSymbolication().GetFileAddress(); 135753f127fSDimitry Andric expr = GetExpressionAtAddress(LLDB_INVALID_ADDRESS, pc); 136753f127fSDimitry Andric } 137753f127fSDimitry Andric if (!expr) 138753f127fSDimitry Andric return false; 139753f127fSDimitry Andric return expr->MatchesOperand(frame, operand); 140753f127fSDimitry Andric } 141753f127fSDimitry Andric 142753f127fSDimitry Andric bool DWARFExpressionList::DumpLocations(Stream *s, lldb::DescriptionLevel level, 143753f127fSDimitry Andric lldb::addr_t func_load_addr, 144753f127fSDimitry Andric lldb::addr_t file_addr, 145753f127fSDimitry Andric ABI *abi) const { 146753f127fSDimitry Andric llvm::raw_ostream &os = s->AsRawOstream(); 147753f127fSDimitry Andric llvm::ListSeparator separator; 148753f127fSDimitry Andric if (const DWARFExpression *expr = GetAlwaysValidExpr()) { 149753f127fSDimitry Andric expr->DumpLocation(s, level, abi); 150753f127fSDimitry Andric return true; 151753f127fSDimitry Andric } 152753f127fSDimitry Andric for (const Entry &entry : *this) { 153753f127fSDimitry Andric addr_t load_base = entry.GetRangeBase() + func_load_addr - m_func_file_addr; 154753f127fSDimitry Andric addr_t load_end = entry.GetRangeEnd() + func_load_addr - m_func_file_addr; 155753f127fSDimitry Andric if (file_addr != LLDB_INVALID_ADDRESS && 156753f127fSDimitry Andric (file_addr < load_base || file_addr >= load_end)) 157753f127fSDimitry Andric continue; 158753f127fSDimitry Andric const auto &expr = entry.data; 159753f127fSDimitry Andric DataExtractor data; 160753f127fSDimitry Andric expr.GetExpressionData(data); 161753f127fSDimitry Andric uint32_t addr_size = data.GetAddressByteSize(); 162753f127fSDimitry Andric 163753f127fSDimitry Andric os << separator; 164753f127fSDimitry Andric os << "["; 165753f127fSDimitry Andric os << llvm::format_hex(load_base, 2 + 2 * addr_size); 166753f127fSDimitry Andric os << ", "; 167753f127fSDimitry Andric os << llvm::format_hex(load_end, 2 + 2 * addr_size); 168753f127fSDimitry Andric os << ") -> "; 169753f127fSDimitry Andric expr.DumpLocation(s, level, abi); 170753f127fSDimitry Andric if (file_addr != LLDB_INVALID_ADDRESS) 171753f127fSDimitry Andric break; 172753f127fSDimitry Andric } 173753f127fSDimitry Andric return true; 174753f127fSDimitry Andric } 175753f127fSDimitry Andric 176753f127fSDimitry Andric void DWARFExpressionList::GetDescription(Stream *s, 177753f127fSDimitry Andric lldb::DescriptionLevel level, 178753f127fSDimitry Andric ABI *abi) const { 179753f127fSDimitry Andric llvm::raw_ostream &os = s->AsRawOstream(); 180753f127fSDimitry Andric if (IsAlwaysValidSingleExpr()) { 181753f127fSDimitry Andric m_exprs.Back()->data.DumpLocation(s, level, abi); 182753f127fSDimitry Andric return; 183753f127fSDimitry Andric } 184753f127fSDimitry Andric os << llvm::format("0x%8.8" PRIx64 ": ", 0); 185753f127fSDimitry Andric for (const Entry &entry : *this) { 186753f127fSDimitry Andric const auto &expr = entry.data; 187753f127fSDimitry Andric DataExtractor data; 188753f127fSDimitry Andric expr.GetExpressionData(data); 189753f127fSDimitry Andric uint32_t addr_size = data.GetAddressByteSize(); 190753f127fSDimitry Andric os << "\n"; 191753f127fSDimitry Andric os.indent(s->GetIndentLevel() + 2); 192753f127fSDimitry Andric os << "["; 193753f127fSDimitry Andric llvm::DWARFFormValue::dumpAddress(os, addr_size, entry.GetRangeBase()); 194753f127fSDimitry Andric os << ", "; 195753f127fSDimitry Andric llvm::DWARFFormValue::dumpAddress(os, addr_size, entry.GetRangeEnd()); 196753f127fSDimitry Andric os << "): "; 197753f127fSDimitry Andric expr.DumpLocation(s, level, abi); 198753f127fSDimitry Andric } 199753f127fSDimitry Andric } 200753f127fSDimitry Andric 201*0fca6ea1SDimitry Andric llvm::Expected<Value> DWARFExpressionList::Evaluate( 202*0fca6ea1SDimitry Andric ExecutionContext *exe_ctx, RegisterContext *reg_ctx, 203*0fca6ea1SDimitry Andric lldb::addr_t func_load_addr, const Value *initial_value_ptr, 204*0fca6ea1SDimitry Andric const Value *object_address_ptr) const { 205753f127fSDimitry Andric ModuleSP module_sp = m_module_wp.lock(); 206753f127fSDimitry Andric DataExtractor data; 207753f127fSDimitry Andric RegisterKind reg_kind; 208753f127fSDimitry Andric DWARFExpression expr; 209753f127fSDimitry Andric if (IsAlwaysValidSingleExpr()) { 210753f127fSDimitry Andric expr = m_exprs.Back()->data; 211753f127fSDimitry Andric } else { 212753f127fSDimitry Andric Address pc; 213753f127fSDimitry Andric StackFrame *frame = nullptr; 214753f127fSDimitry Andric if (!reg_ctx || !reg_ctx->GetPCForSymbolication(pc)) { 215753f127fSDimitry Andric if (exe_ctx) 216753f127fSDimitry Andric frame = exe_ctx->GetFramePtr(); 217753f127fSDimitry Andric if (!frame) 218*0fca6ea1SDimitry Andric return llvm::createStringError("no frame"); 219753f127fSDimitry Andric RegisterContextSP reg_ctx_sp = frame->GetRegisterContext(); 220753f127fSDimitry Andric if (!reg_ctx_sp) 221*0fca6ea1SDimitry Andric return llvm::createStringError("no register context"); 222753f127fSDimitry Andric reg_ctx_sp->GetPCForSymbolication(pc); 223753f127fSDimitry Andric } 224753f127fSDimitry Andric 225753f127fSDimitry Andric if (!pc.IsValid()) { 226*0fca6ea1SDimitry Andric return llvm::createStringError("Invalid PC in frame."); 227753f127fSDimitry Andric } 228753f127fSDimitry Andric addr_t pc_load_addr = pc.GetLoadAddress(exe_ctx->GetTargetPtr()); 229753f127fSDimitry Andric const DWARFExpression *entry = 230753f127fSDimitry Andric GetExpressionAtAddress(func_load_addr, pc_load_addr); 231*0fca6ea1SDimitry Andric if (!entry) 232*0fca6ea1SDimitry Andric return llvm::createStringError("variable not available"); 233753f127fSDimitry Andric expr = *entry; 234753f127fSDimitry Andric } 235753f127fSDimitry Andric expr.GetExpressionData(data); 236753f127fSDimitry Andric reg_kind = expr.GetRegisterKind(); 237753f127fSDimitry Andric return DWARFExpression::Evaluate(exe_ctx, reg_ctx, module_sp, data, 238753f127fSDimitry Andric m_dwarf_cu, reg_kind, initial_value_ptr, 239*0fca6ea1SDimitry Andric object_address_ptr); 240753f127fSDimitry Andric } 241