1 //===-- DWARFExpression.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 "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h" 10 #include "llvm/ADT/SmallString.h" 11 #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 12 #include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" 13 #include "llvm/Support/Format.h" 14 #include <cassert> 15 #include <cstdint> 16 17 using namespace llvm; 18 using namespace dwarf; 19 20 namespace llvm { 21 22 typedef DWARFExpression::Operation Op; 23 typedef Op::Description Desc; 24 25 static void prettyPrintBaseTypeRef(DWARFUnit *U, raw_ostream &OS, 26 DIDumpOptions DumpOpts, 27 ArrayRef<uint64_t> Operands, 28 unsigned Operand) { 29 assert(Operand < Operands.size() && "operand out of bounds"); 30 if (!U) { 31 OS << format(" <base_type ref: 0x%" PRIx64 ">", Operands[Operand]); 32 return; 33 } 34 auto Die = U->getDIEForOffset(U->getOffset() + Operands[Operand]); 35 if (Die && Die.getTag() == dwarf::DW_TAG_base_type) { 36 OS << " ("; 37 if (DumpOpts.Verbose) 38 OS << format("0x%08" PRIx64 " -> ", Operands[Operand]); 39 OS << format("0x%08" PRIx64 ")", U->getOffset() + Operands[Operand]); 40 if (auto Name = dwarf::toString(Die.find(dwarf::DW_AT_name))) 41 OS << " \"" << *Name << "\""; 42 } else { 43 OS << format(" <invalid base_type ref: 0x%" PRIx64 ">", Operands[Operand]); 44 } 45 } 46 47 static bool printOp(const DWARFExpression::Operation *Op, raw_ostream &OS, 48 DIDumpOptions DumpOpts, const DWARFExpression *Expr, 49 DWARFUnit *U) { 50 if (Op->isError()) { 51 OS << "<decoding error>"; 52 return false; 53 } 54 55 StringRef Name = OperationEncodingString(Op->getCode()); 56 assert(!Name.empty() && "DW_OP has no name!"); 57 OS << Name; 58 59 if ((Op->getCode() >= DW_OP_breg0 && Op->getCode() <= DW_OP_breg31) || 60 (Op->getCode() >= DW_OP_reg0 && Op->getCode() <= DW_OP_reg31) || 61 Op->getCode() == DW_OP_bregx || Op->getCode() == DW_OP_regx || 62 Op->getCode() == DW_OP_regval_type) 63 if (prettyPrintRegisterOp(U, OS, DumpOpts, Op->getCode(), 64 Op->getRawOperands())) 65 return true; 66 67 for (unsigned Operand = 0; Operand < Op->getDescription().Op.size(); 68 ++Operand) { 69 unsigned Size = Op->getDescription().Op[Operand]; 70 unsigned Signed = Size & DWARFExpression::Operation::SignBit; 71 72 if (Size == DWARFExpression::Operation::SizeSubOpLEB) { 73 StringRef SubName = 74 SubOperationEncodingString(Op->getCode(), Op->getRawOperand(Operand)); 75 assert(!SubName.empty() && "DW_OP SubOp has no name!"); 76 OS << " " << SubName; 77 } else if (Size == DWARFExpression::Operation::BaseTypeRef && U) { 78 // For DW_OP_convert the operand may be 0 to indicate that conversion to 79 // the generic type should be done. The same holds for DW_OP_reinterpret, 80 // which is currently not supported. 81 if (Op->getCode() == DW_OP_convert && Op->getRawOperand(Operand) == 0) 82 OS << " 0x0"; 83 else 84 prettyPrintBaseTypeRef(U, OS, DumpOpts, Op->getRawOperands(), Operand); 85 } else if (Size == DWARFExpression::Operation::WasmLocationArg) { 86 assert(Operand == 1); 87 switch (Op->getRawOperand(0)) { 88 case 0: 89 case 1: 90 case 2: 91 case 3: // global as uint32 92 case 4: 93 OS << format(" 0x%" PRIx64, Op->getRawOperand(Operand)); 94 break; 95 default: 96 assert(false); 97 } 98 } else if (Size == DWARFExpression::Operation::SizeBlock) { 99 uint64_t Offset = Op->getRawOperand(Operand); 100 for (unsigned i = 0; i < Op->getRawOperand(Operand - 1); ++i) 101 OS << format(" 0x%02x", 102 static_cast<uint8_t>(Expr->getData()[Offset++])); 103 } else { 104 if (Signed) 105 OS << format(" %+" PRId64, (int64_t)Op->getRawOperand(Operand)); 106 else if (Op->getCode() != DW_OP_entry_value && 107 Op->getCode() != DW_OP_GNU_entry_value) 108 OS << format(" 0x%" PRIx64, Op->getRawOperand(Operand)); 109 } 110 } 111 return true; 112 } 113 114 void printDwarfExpression(const DWARFExpression *E, raw_ostream &OS, 115 DIDumpOptions DumpOpts, DWARFUnit *U, bool IsEH) { 116 uint32_t EntryValExprSize = 0; 117 uint64_t EntryValStartOffset = 0; 118 if (E->getData().empty()) 119 OS << "<empty>"; 120 121 for (auto &Op : *E) { 122 DumpOpts.IsEH = IsEH; 123 if (!printOp(&Op, OS, DumpOpts, E, U)) { 124 uint64_t FailOffset = Op.getEndOffset(); 125 while (FailOffset < E->getData().size()) 126 OS << format(" %02x", static_cast<uint8_t>(E->getData()[FailOffset++])); 127 return; 128 } 129 130 if (Op.getCode() == DW_OP_entry_value || 131 Op.getCode() == DW_OP_GNU_entry_value) { 132 OS << "("; 133 EntryValExprSize = Op.getRawOperand(0); 134 EntryValStartOffset = Op.getEndOffset(); 135 continue; 136 } 137 138 if (EntryValExprSize) { 139 EntryValExprSize -= Op.getEndOffset() - EntryValStartOffset; 140 if (EntryValExprSize == 0) 141 OS << ")"; 142 } 143 144 if (Op.getEndOffset() < E->getData().size()) 145 OS << ", "; 146 } 147 } 148 149 /// A user-facing string representation of a DWARF expression. This might be an 150 /// Address expression, in which case it will be implicitly dereferenced, or a 151 /// Value expression. 152 struct PrintedExpr { 153 enum ExprKind { 154 Address, 155 Value, 156 }; 157 ExprKind Kind; 158 SmallString<16> String; 159 160 PrintedExpr(ExprKind K = Address) : Kind(K) {} 161 }; 162 163 static bool printCompactDWARFExpr( 164 raw_ostream &OS, DWARFExpression::iterator I, 165 const DWARFExpression::iterator E, 166 std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg = 167 nullptr) { 168 SmallVector<PrintedExpr, 4> Stack; 169 170 while (I != E) { 171 const DWARFExpression::Operation &Op = *I; 172 uint8_t Opcode = Op.getCode(); 173 switch (Opcode) { 174 case dwarf::DW_OP_regx: { 175 // DW_OP_regx: A register, with the register num given as an operand. 176 // Printed as the plain register name. 177 uint64_t DwarfRegNum = Op.getRawOperand(0); 178 auto RegName = GetNameForDWARFReg(DwarfRegNum, false); 179 if (RegName.empty()) 180 return false; 181 raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String); 182 S << RegName; 183 break; 184 } 185 case dwarf::DW_OP_bregx: { 186 int DwarfRegNum = Op.getRawOperand(0); 187 int64_t Offset = Op.getRawOperand(1); 188 auto RegName = GetNameForDWARFReg(DwarfRegNum, false); 189 if (RegName.empty()) 190 return false; 191 raw_svector_ostream S(Stack.emplace_back().String); 192 S << RegName; 193 if (Offset) 194 S << format("%+" PRId64, Offset); 195 break; 196 } 197 case dwarf::DW_OP_entry_value: 198 case dwarf::DW_OP_GNU_entry_value: { 199 // DW_OP_entry_value contains a sub-expression which must be rendered 200 // separately. 201 uint64_t SubExprLength = Op.getRawOperand(0); 202 DWARFExpression::iterator SubExprEnd = I.skipBytes(SubExprLength); 203 ++I; 204 raw_svector_ostream S(Stack.emplace_back().String); 205 S << "entry("; 206 printCompactDWARFExpr(S, I, SubExprEnd, GetNameForDWARFReg); 207 S << ")"; 208 I = SubExprEnd; 209 continue; 210 } 211 case dwarf::DW_OP_stack_value: { 212 // The top stack entry should be treated as the actual value of tne 213 // variable, rather than the address of the variable in memory. 214 assert(!Stack.empty()); 215 Stack.back().Kind = PrintedExpr::Value; 216 break; 217 } 218 case dwarf::DW_OP_nop: { 219 break; 220 } 221 case dwarf::DW_OP_LLVM_user: { 222 assert(Op.getSubCode() == dwarf::DW_OP_LLVM_nop); 223 break; 224 } 225 default: 226 if (Opcode >= dwarf::DW_OP_reg0 && Opcode <= dwarf::DW_OP_reg31) { 227 // DW_OP_reg<N>: A register, with the register num implied by the 228 // opcode. Printed as the plain register name. 229 uint64_t DwarfRegNum = Opcode - dwarf::DW_OP_reg0; 230 auto RegName = GetNameForDWARFReg(DwarfRegNum, false); 231 if (RegName.empty()) 232 return false; 233 raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String); 234 S << RegName; 235 } else if (Opcode >= dwarf::DW_OP_breg0 && 236 Opcode <= dwarf::DW_OP_breg31) { 237 int DwarfRegNum = Opcode - dwarf::DW_OP_breg0; 238 int64_t Offset = Op.getRawOperand(0); 239 auto RegName = GetNameForDWARFReg(DwarfRegNum, false); 240 if (RegName.empty()) 241 return false; 242 raw_svector_ostream S(Stack.emplace_back().String); 243 S << RegName; 244 if (Offset) 245 S << format("%+" PRId64, Offset); 246 } else { 247 // If we hit an unknown operand, we don't know its effect on the stack, 248 // so bail out on the whole expression. 249 OS << "<unknown op " << dwarf::OperationEncodingString(Opcode) << " (" 250 << (int)Opcode << ")>"; 251 return false; 252 } 253 break; 254 } 255 ++I; 256 } 257 258 if (Stack.size() != 1) { 259 OS << "<stack of size " << Stack.size() << ", expected 1>"; 260 return false; 261 } 262 263 if (Stack.front().Kind == PrintedExpr::Address) 264 OS << "[" << Stack.front().String << "]"; 265 else 266 OS << Stack.front().String; 267 268 return true; 269 } 270 271 bool printDwarfExpressionCompact( 272 const DWARFExpression *E, raw_ostream &OS, 273 std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) { 274 return printCompactDWARFExpr(OS, E->begin(), E->end(), GetNameForDWARFReg); 275 } 276 277 bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS, 278 DIDumpOptions DumpOpts, uint8_t Opcode, 279 ArrayRef<uint64_t> Operands) { 280 if (!DumpOpts.GetNameForDWARFReg) 281 return false; 282 283 uint64_t DwarfRegNum; 284 unsigned OpNum = 0; 285 286 if (Opcode == DW_OP_bregx || Opcode == DW_OP_regx || 287 Opcode == DW_OP_regval_type) 288 DwarfRegNum = Operands[OpNum++]; 289 else if (Opcode >= DW_OP_breg0 && Opcode < DW_OP_bregx) 290 DwarfRegNum = Opcode - DW_OP_breg0; 291 else 292 DwarfRegNum = Opcode - DW_OP_reg0; 293 294 auto RegName = DumpOpts.GetNameForDWARFReg(DwarfRegNum, DumpOpts.IsEH); 295 if (!RegName.empty()) { 296 if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) || 297 Opcode == DW_OP_bregx) 298 OS << ' ' << RegName << format("%+" PRId64, Operands[OpNum]); 299 else 300 OS << ' ' << RegName.data(); 301 302 if (Opcode == DW_OP_regval_type) 303 prettyPrintBaseTypeRef(U, OS, DumpOpts, Operands, 1); 304 return true; 305 } 306 307 return false; 308 } 309 310 } // namespace llvm 311