1 //===----------------------------------------------------------------------===// 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/DWARFUnwindTablePrinter.h" 10 #include "llvm/DebugInfo/DIContext.h" 11 #include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h" 12 #include "llvm/Support/ErrorHandling.h" 13 #include "llvm/Support/Format.h" 14 #include "llvm/Support/raw_ostream.h" 15 #include <cassert> 16 #include <cinttypes> 17 #include <cstdint> 18 #include <optional> 19 20 using namespace llvm; 21 using namespace dwarf; 22 23 static void printRegister(raw_ostream &OS, DIDumpOptions DumpOpts, 24 unsigned RegNum) { 25 if (DumpOpts.GetNameForDWARFReg) { 26 auto RegName = DumpOpts.GetNameForDWARFReg(RegNum, DumpOpts.IsEH); 27 if (!RegName.empty()) { 28 OS << RegName; 29 return; 30 } 31 } 32 OS << "reg" << RegNum; 33 } 34 35 /// Print an unwind location expression as text and use the register information 36 /// if some is provided. 37 /// 38 /// \param R the unwind location to print. 39 /// 40 /// \param OS the stream to use for output. 41 /// 42 /// \param MRI register information that helps emit register names insteead 43 /// of raw register numbers. 44 /// 45 /// \param IsEH true if the DWARF Call Frame Information is from .eh_frame 46 /// instead of from .debug_frame. This is needed for register number 47 /// conversion because some register numbers differ between the two sections 48 /// for certain architectures like x86. 49 static void printUnwindLocation(const UnwindLocation &UL, raw_ostream &OS, 50 DIDumpOptions DumpOpts) { 51 if (UL.getDereference()) 52 OS << '['; 53 switch (UL.getLocation()) { 54 case UnwindLocation::Unspecified: 55 OS << "unspecified"; 56 break; 57 case UnwindLocation::Undefined: 58 OS << "undefined"; 59 break; 60 case UnwindLocation::Same: 61 OS << "same"; 62 break; 63 case UnwindLocation::CFAPlusOffset: 64 OS << "CFA"; 65 if (UL.getOffset() == 0) 66 break; 67 if (UL.getOffset() > 0) 68 OS << "+"; 69 OS << UL.getOffset(); 70 break; 71 case UnwindLocation::RegPlusOffset: 72 printRegister(OS, DumpOpts, UL.getRegister()); 73 if (UL.getOffset() == 0 && !UL.hasAddressSpace()) 74 break; 75 if (UL.getOffset() >= 0) 76 OS << "+"; 77 OS << UL.getOffset(); 78 if (UL.hasAddressSpace()) 79 OS << " in addrspace" << UL.getAddressSpace(); 80 break; 81 case UnwindLocation::DWARFExpr: { 82 if (UL.getDWARFExpressionBytes()) { 83 auto Expr = *UL.getDWARFExpressionBytes(); 84 printDwarfExpression(&Expr, OS, DumpOpts, nullptr); 85 } 86 break; 87 } 88 case UnwindLocation::Constant: 89 OS << UL.getOffset(); 90 break; 91 } 92 if (UL.getDereference()) 93 OS << ']'; 94 } 95 96 raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, 97 const UnwindLocation &UL) { 98 auto DumpOpts = DIDumpOptions(); 99 printUnwindLocation(UL, OS, DumpOpts); 100 return OS; 101 } 102 103 /// Print all registers + locations that are currently defined in a register 104 /// locations. 105 /// 106 /// \param RL the register locations to print. 107 /// 108 /// \param OS the stream to use for output. 109 /// 110 /// \param MRI register information that helps emit register names insteead 111 /// of raw register numbers. 112 /// 113 /// \param IsEH true if the DWARF Call Frame Information is from .eh_frame 114 /// instead of from .debug_frame. This is needed for register number 115 /// conversion because some register numbers differ between the two sections 116 /// for certain architectures like x86. 117 static void printRegisterLocations(const RegisterLocations &RL, raw_ostream &OS, 118 DIDumpOptions DumpOpts) { 119 bool First = true; 120 for (uint32_t Reg : RL.getRegisters()) { 121 auto Loc = *RL.getRegisterLocation(Reg); 122 if (First) 123 First = false; 124 else 125 OS << ", "; 126 printRegister(OS, DumpOpts, Reg); 127 OS << '='; 128 printUnwindLocation(Loc, OS, DumpOpts); 129 } 130 } 131 132 raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, 133 const RegisterLocations &RL) { 134 auto DumpOpts = DIDumpOptions(); 135 printRegisterLocations(RL, OS, DumpOpts); 136 return OS; 137 } 138 139 /// Print an UnwindRow to the stream. 140 /// 141 /// \param Row the UnwindRow to print. 142 /// 143 /// \param OS the stream to use for output. 144 /// 145 /// \param MRI register information that helps emit register names insteead 146 /// of raw register numbers. 147 /// 148 /// \param IsEH true if the DWARF Call Frame Information is from .eh_frame 149 /// instead of from .debug_frame. This is needed for register number 150 /// conversion because some register numbers differ between the two sections 151 /// for certain architectures like x86. 152 /// 153 /// \param IndentLevel specify the indent level as an integer. The UnwindRow 154 /// will be output to the stream preceded by 2 * IndentLevel number of spaces. 155 static void printUnwindRow(const UnwindRow &Row, raw_ostream &OS, 156 DIDumpOptions DumpOpts, unsigned IndentLevel) { 157 OS.indent(2 * IndentLevel); 158 if (Row.hasAddress()) 159 OS << format("0x%" PRIx64 ": ", Row.getAddress()); 160 OS << "CFA="; 161 printUnwindLocation(Row.getCFAValue(), OS, DumpOpts); 162 if (Row.getRegisterLocations().hasLocations()) { 163 OS << ": "; 164 printRegisterLocations(Row.getRegisterLocations(), OS, DumpOpts); 165 } 166 OS << "\n"; 167 } 168 169 raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindRow &Row) { 170 auto DumpOpts = DIDumpOptions(); 171 printUnwindRow(Row, OS, DumpOpts, 0); 172 return OS; 173 } 174 175 void llvm::dwarf::printUnwindTable(const UnwindTable &Rows, raw_ostream &OS, 176 DIDumpOptions DumpOpts, 177 unsigned IndentLevel) { 178 for (const UnwindRow &Row : Rows) 179 printUnwindRow(Row, OS, DumpOpts, IndentLevel); 180 } 181 182 raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindTable &Rows) { 183 auto DumpOpts = DIDumpOptions(); 184 printUnwindTable(Rows, OS, DumpOpts, 0); 185 return OS; 186 } 187