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