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