10b57cec5SDimitry Andric //===- DWARFDebugFrame.h - Parsing of .debug_frame ------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" 100b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 110b57cec5SDimitry Andric #include "llvm/ADT/Optional.h" 120b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 130b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 140b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h" 15e8d8bef9SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 160b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 170b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 180b57cec5SDimitry Andric #include "llvm/Support/DataExtractor.h" 190b57cec5SDimitry Andric #include "llvm/Support/Errc.h" 200b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 210b57cec5SDimitry Andric #include "llvm/Support/Format.h" 220b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 230b57cec5SDimitry Andric #include <algorithm> 240b57cec5SDimitry Andric #include <cassert> 250b57cec5SDimitry Andric #include <cinttypes> 260b57cec5SDimitry Andric #include <cstdint> 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric using namespace llvm; 290b57cec5SDimitry Andric using namespace dwarf; 300b57cec5SDimitry Andric 31e8d8bef9SDimitry Andric static void printRegister(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, 32e8d8bef9SDimitry Andric unsigned RegNum) { 33e8d8bef9SDimitry Andric if (MRI) { 34e8d8bef9SDimitry Andric if (Optional<unsigned> LLVMRegNum = MRI->getLLVMRegNum(RegNum, IsEH)) { 35e8d8bef9SDimitry Andric if (const char *RegName = MRI->getName(*LLVMRegNum)) { 36e8d8bef9SDimitry Andric OS << RegName; 37e8d8bef9SDimitry Andric return; 38e8d8bef9SDimitry Andric } 39e8d8bef9SDimitry Andric } 40e8d8bef9SDimitry Andric } 41e8d8bef9SDimitry Andric OS << "reg" << RegNum; 42e8d8bef9SDimitry Andric } 430b57cec5SDimitry Andric 44*fe6060f1SDimitry Andric UnwindLocation UnwindLocation::createUnspecified() { return {Unspecified}; } 45*fe6060f1SDimitry Andric 46*fe6060f1SDimitry Andric UnwindLocation UnwindLocation::createUndefined() { return {Undefined}; } 47*fe6060f1SDimitry Andric 48*fe6060f1SDimitry Andric UnwindLocation UnwindLocation::createSame() { return {Same}; } 49*fe6060f1SDimitry Andric 50*fe6060f1SDimitry Andric UnwindLocation UnwindLocation::createIsConstant(int32_t Value) { 51*fe6060f1SDimitry Andric return {Constant, InvalidRegisterNumber, Value, None, false}; 52*fe6060f1SDimitry Andric } 53*fe6060f1SDimitry Andric 54*fe6060f1SDimitry Andric UnwindLocation UnwindLocation::createIsCFAPlusOffset(int32_t Offset) { 55*fe6060f1SDimitry Andric return {CFAPlusOffset, InvalidRegisterNumber, Offset, None, false}; 56*fe6060f1SDimitry Andric } 57*fe6060f1SDimitry Andric 58*fe6060f1SDimitry Andric UnwindLocation UnwindLocation::createAtCFAPlusOffset(int32_t Offset) { 59*fe6060f1SDimitry Andric return {CFAPlusOffset, InvalidRegisterNumber, Offset, None, true}; 60*fe6060f1SDimitry Andric } 61*fe6060f1SDimitry Andric 62*fe6060f1SDimitry Andric UnwindLocation 63*fe6060f1SDimitry Andric UnwindLocation::createIsRegisterPlusOffset(uint32_t RegNum, int32_t Offset, 64*fe6060f1SDimitry Andric Optional<uint32_t> AddrSpace) { 65*fe6060f1SDimitry Andric return {RegPlusOffset, RegNum, Offset, AddrSpace, false}; 66*fe6060f1SDimitry Andric } 67*fe6060f1SDimitry Andric 68*fe6060f1SDimitry Andric UnwindLocation 69*fe6060f1SDimitry Andric UnwindLocation::createAtRegisterPlusOffset(uint32_t RegNum, int32_t Offset, 70*fe6060f1SDimitry Andric Optional<uint32_t> AddrSpace) { 71*fe6060f1SDimitry Andric return {RegPlusOffset, RegNum, Offset, AddrSpace, true}; 72*fe6060f1SDimitry Andric } 73*fe6060f1SDimitry Andric 74*fe6060f1SDimitry Andric UnwindLocation UnwindLocation::createIsDWARFExpression(DWARFExpression Expr) { 75*fe6060f1SDimitry Andric return {Expr, false}; 76*fe6060f1SDimitry Andric } 77*fe6060f1SDimitry Andric 78*fe6060f1SDimitry Andric UnwindLocation UnwindLocation::createAtDWARFExpression(DWARFExpression Expr) { 79*fe6060f1SDimitry Andric return {Expr, true}; 80*fe6060f1SDimitry Andric } 81*fe6060f1SDimitry Andric 82*fe6060f1SDimitry Andric void UnwindLocation::dump(raw_ostream &OS, const MCRegisterInfo *MRI, 83*fe6060f1SDimitry Andric bool IsEH) const { 84*fe6060f1SDimitry Andric if (Dereference) 85*fe6060f1SDimitry Andric OS << '['; 86*fe6060f1SDimitry Andric switch (Kind) { 87*fe6060f1SDimitry Andric case Unspecified: 88*fe6060f1SDimitry Andric OS << "unspecified"; 89*fe6060f1SDimitry Andric break; 90*fe6060f1SDimitry Andric case Undefined: 91*fe6060f1SDimitry Andric OS << "undefined"; 92*fe6060f1SDimitry Andric break; 93*fe6060f1SDimitry Andric case Same: 94*fe6060f1SDimitry Andric OS << "same"; 95*fe6060f1SDimitry Andric break; 96*fe6060f1SDimitry Andric case CFAPlusOffset: 97*fe6060f1SDimitry Andric OS << "CFA"; 98*fe6060f1SDimitry Andric if (Offset == 0) 99*fe6060f1SDimitry Andric break; 100*fe6060f1SDimitry Andric if (Offset > 0) 101*fe6060f1SDimitry Andric OS << "+"; 102*fe6060f1SDimitry Andric OS << Offset; 103*fe6060f1SDimitry Andric break; 104*fe6060f1SDimitry Andric case RegPlusOffset: 105*fe6060f1SDimitry Andric printRegister(OS, MRI, IsEH, RegNum); 106*fe6060f1SDimitry Andric if (Offset == 0 && !AddrSpace) 107*fe6060f1SDimitry Andric break; 108*fe6060f1SDimitry Andric if (Offset >= 0) 109*fe6060f1SDimitry Andric OS << "+"; 110*fe6060f1SDimitry Andric OS << Offset; 111*fe6060f1SDimitry Andric if (AddrSpace) 112*fe6060f1SDimitry Andric OS << " in addrspace" << *AddrSpace; 113*fe6060f1SDimitry Andric break; 114*fe6060f1SDimitry Andric case DWARFExpr: 115*fe6060f1SDimitry Andric Expr->print(OS, DIDumpOptions(), MRI, nullptr, IsEH); 116*fe6060f1SDimitry Andric break; 117*fe6060f1SDimitry Andric case Constant: 118*fe6060f1SDimitry Andric OS << Offset; 119*fe6060f1SDimitry Andric break; 120*fe6060f1SDimitry Andric } 121*fe6060f1SDimitry Andric if (Dereference) 122*fe6060f1SDimitry Andric OS << ']'; 123*fe6060f1SDimitry Andric } 124*fe6060f1SDimitry Andric 125*fe6060f1SDimitry Andric raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, 126*fe6060f1SDimitry Andric const UnwindLocation &UL) { 127*fe6060f1SDimitry Andric UL.dump(OS, nullptr, false); 128*fe6060f1SDimitry Andric return OS; 129*fe6060f1SDimitry Andric } 130*fe6060f1SDimitry Andric 131*fe6060f1SDimitry Andric bool UnwindLocation::operator==(const UnwindLocation &RHS) const { 132*fe6060f1SDimitry Andric if (Kind != RHS.Kind) 133*fe6060f1SDimitry Andric return false; 134*fe6060f1SDimitry Andric switch (Kind) { 135*fe6060f1SDimitry Andric case Unspecified: 136*fe6060f1SDimitry Andric case Undefined: 137*fe6060f1SDimitry Andric case Same: 138*fe6060f1SDimitry Andric return true; 139*fe6060f1SDimitry Andric case CFAPlusOffset: 140*fe6060f1SDimitry Andric return Offset == RHS.Offset && Dereference == RHS.Dereference; 141*fe6060f1SDimitry Andric case RegPlusOffset: 142*fe6060f1SDimitry Andric return RegNum == RHS.RegNum && Offset == RHS.Offset && 143*fe6060f1SDimitry Andric Dereference == RHS.Dereference; 144*fe6060f1SDimitry Andric case DWARFExpr: 145*fe6060f1SDimitry Andric return *Expr == *RHS.Expr && Dereference == RHS.Dereference; 146*fe6060f1SDimitry Andric case Constant: 147*fe6060f1SDimitry Andric return Offset == RHS.Offset; 148*fe6060f1SDimitry Andric } 149*fe6060f1SDimitry Andric return false; 150*fe6060f1SDimitry Andric } 151*fe6060f1SDimitry Andric 152*fe6060f1SDimitry Andric void RegisterLocations::dump(raw_ostream &OS, const MCRegisterInfo *MRI, 153*fe6060f1SDimitry Andric bool IsEH) const { 154*fe6060f1SDimitry Andric bool First = true; 155*fe6060f1SDimitry Andric for (const auto &RegLocPair : Locations) { 156*fe6060f1SDimitry Andric if (First) 157*fe6060f1SDimitry Andric First = false; 158*fe6060f1SDimitry Andric else 159*fe6060f1SDimitry Andric OS << ", "; 160*fe6060f1SDimitry Andric printRegister(OS, MRI, IsEH, RegLocPair.first); 161*fe6060f1SDimitry Andric OS << '='; 162*fe6060f1SDimitry Andric RegLocPair.second.dump(OS, MRI, IsEH); 163*fe6060f1SDimitry Andric } 164*fe6060f1SDimitry Andric } 165*fe6060f1SDimitry Andric 166*fe6060f1SDimitry Andric raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, 167*fe6060f1SDimitry Andric const RegisterLocations &RL) { 168*fe6060f1SDimitry Andric RL.dump(OS, nullptr, false); 169*fe6060f1SDimitry Andric return OS; 170*fe6060f1SDimitry Andric } 171*fe6060f1SDimitry Andric 172*fe6060f1SDimitry Andric void UnwindRow::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, 173*fe6060f1SDimitry Andric unsigned IndentLevel) const { 174*fe6060f1SDimitry Andric OS.indent(2 * IndentLevel); 175*fe6060f1SDimitry Andric if (hasAddress()) 176*fe6060f1SDimitry Andric OS << format("0x%" PRIx64 ": ", *Address); 177*fe6060f1SDimitry Andric OS << "CFA="; 178*fe6060f1SDimitry Andric CFAValue.dump(OS, MRI, IsEH); 179*fe6060f1SDimitry Andric if (RegLocs.hasLocations()) { 180*fe6060f1SDimitry Andric OS << ": "; 181*fe6060f1SDimitry Andric RegLocs.dump(OS, MRI, IsEH); 182*fe6060f1SDimitry Andric } 183*fe6060f1SDimitry Andric OS << "\n"; 184*fe6060f1SDimitry Andric } 185*fe6060f1SDimitry Andric 186*fe6060f1SDimitry Andric raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindRow &Row) { 187*fe6060f1SDimitry Andric Row.dump(OS, nullptr, false, 0); 188*fe6060f1SDimitry Andric return OS; 189*fe6060f1SDimitry Andric } 190*fe6060f1SDimitry Andric 191*fe6060f1SDimitry Andric void UnwindTable::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, 192*fe6060f1SDimitry Andric unsigned IndentLevel) const { 193*fe6060f1SDimitry Andric for (const UnwindRow &Row : Rows) 194*fe6060f1SDimitry Andric Row.dump(OS, MRI, IsEH, IndentLevel); 195*fe6060f1SDimitry Andric } 196*fe6060f1SDimitry Andric 197*fe6060f1SDimitry Andric raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindTable &Rows) { 198*fe6060f1SDimitry Andric Rows.dump(OS, nullptr, false, 0); 199*fe6060f1SDimitry Andric return OS; 200*fe6060f1SDimitry Andric } 201*fe6060f1SDimitry Andric 202*fe6060f1SDimitry Andric Expected<UnwindTable> UnwindTable::create(const FDE *Fde) { 203*fe6060f1SDimitry Andric const CIE *Cie = Fde->getLinkedCIE(); 204*fe6060f1SDimitry Andric if (Cie == nullptr) 205*fe6060f1SDimitry Andric return createStringError(errc::invalid_argument, 206*fe6060f1SDimitry Andric "unable to get CIE for FDE at offset 0x%" PRIx64, 207*fe6060f1SDimitry Andric Fde->getOffset()); 208*fe6060f1SDimitry Andric 209*fe6060f1SDimitry Andric // Rows will be empty if there are no CFI instructions. 210*fe6060f1SDimitry Andric if (Cie->cfis().empty() && Fde->cfis().empty()) 211*fe6060f1SDimitry Andric return UnwindTable(); 212*fe6060f1SDimitry Andric 213*fe6060f1SDimitry Andric UnwindTable UT; 214*fe6060f1SDimitry Andric UnwindRow Row; 215*fe6060f1SDimitry Andric Row.setAddress(Fde->getInitialLocation()); 216*fe6060f1SDimitry Andric UT.EndAddress = Fde->getInitialLocation() + Fde->getAddressRange(); 217*fe6060f1SDimitry Andric if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr)) 218*fe6060f1SDimitry Andric return std::move(CieError); 219*fe6060f1SDimitry Andric // We need to save the initial locations of registers from the CIE parsing 220*fe6060f1SDimitry Andric // in case we run into DW_CFA_restore or DW_CFA_restore_extended opcodes. 221*fe6060f1SDimitry Andric const RegisterLocations InitialLocs = Row.getRegisterLocations(); 222*fe6060f1SDimitry Andric if (Error FdeError = UT.parseRows(Fde->cfis(), Row, &InitialLocs)) 223*fe6060f1SDimitry Andric return std::move(FdeError); 224*fe6060f1SDimitry Andric // May be all the CFI instructions were DW_CFA_nop amd Row becomes empty. 225*fe6060f1SDimitry Andric // Do not add that to the unwind table. 226*fe6060f1SDimitry Andric if (Row.getRegisterLocations().hasLocations() || 227*fe6060f1SDimitry Andric Row.getCFAValue().getLocation() != UnwindLocation::Unspecified) 228*fe6060f1SDimitry Andric UT.Rows.push_back(Row); 229*fe6060f1SDimitry Andric return UT; 230*fe6060f1SDimitry Andric } 231*fe6060f1SDimitry Andric 232*fe6060f1SDimitry Andric Expected<UnwindTable> UnwindTable::create(const CIE *Cie) { 233*fe6060f1SDimitry Andric // Rows will be empty if there are no CFI instructions. 234*fe6060f1SDimitry Andric if (Cie->cfis().empty()) 235*fe6060f1SDimitry Andric return UnwindTable(); 236*fe6060f1SDimitry Andric 237*fe6060f1SDimitry Andric UnwindTable UT; 238*fe6060f1SDimitry Andric UnwindRow Row; 239*fe6060f1SDimitry Andric if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr)) 240*fe6060f1SDimitry Andric return std::move(CieError); 241*fe6060f1SDimitry Andric // May be all the CFI instructions were DW_CFA_nop amd Row becomes empty. 242*fe6060f1SDimitry Andric // Do not add that to the unwind table. 243*fe6060f1SDimitry Andric if (Row.getRegisterLocations().hasLocations() || 244*fe6060f1SDimitry Andric Row.getCFAValue().getLocation() != UnwindLocation::Unspecified) 245*fe6060f1SDimitry Andric UT.Rows.push_back(Row); 246*fe6060f1SDimitry Andric return UT; 247*fe6060f1SDimitry Andric } 248*fe6060f1SDimitry Andric 2490b57cec5SDimitry Andric // See DWARF standard v3, section 7.23 2500b57cec5SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0; 2510b57cec5SDimitry Andric const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f; 2520b57cec5SDimitry Andric 2538bcb0991SDimitry Andric Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset, 2548bcb0991SDimitry Andric uint64_t EndOffset) { 2555ffd83dbSDimitry Andric DataExtractor::Cursor C(*Offset); 2565ffd83dbSDimitry Andric while (C && C.tell() < EndOffset) { 2575ffd83dbSDimitry Andric uint8_t Opcode = Data.getRelocatedValue(C, 1); 2585ffd83dbSDimitry Andric if (!C) 2595ffd83dbSDimitry Andric break; 2600b57cec5SDimitry Andric 2615ffd83dbSDimitry Andric // Some instructions have a primary opcode encoded in the top bits. 2625ffd83dbSDimitry Andric if (uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) { 2630b57cec5SDimitry Andric // If it's a primary opcode, the first operand is encoded in the bottom 2640b57cec5SDimitry Andric // bits of the opcode itself. 2650b57cec5SDimitry Andric uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK; 2660b57cec5SDimitry Andric switch (Primary) { 2670b57cec5SDimitry Andric case DW_CFA_advance_loc: 2680b57cec5SDimitry Andric case DW_CFA_restore: 2690b57cec5SDimitry Andric addInstruction(Primary, Op1); 2700b57cec5SDimitry Andric break; 2710b57cec5SDimitry Andric case DW_CFA_offset: 2725ffd83dbSDimitry Andric addInstruction(Primary, Op1, Data.getULEB128(C)); 2730b57cec5SDimitry Andric break; 2745ffd83dbSDimitry Andric default: 2755ffd83dbSDimitry Andric llvm_unreachable("invalid primary CFI opcode"); 2760b57cec5SDimitry Andric } 2775ffd83dbSDimitry Andric continue; 2785ffd83dbSDimitry Andric } 2795ffd83dbSDimitry Andric 2800b57cec5SDimitry Andric // Extended opcode - its value is Opcode itself. 2810b57cec5SDimitry Andric switch (Opcode) { 2820b57cec5SDimitry Andric default: 2830b57cec5SDimitry Andric return createStringError(errc::illegal_byte_sequence, 2845ffd83dbSDimitry Andric "invalid extended CFI opcode 0x%" PRIx8, Opcode); 2850b57cec5SDimitry Andric case DW_CFA_nop: 2860b57cec5SDimitry Andric case DW_CFA_remember_state: 2870b57cec5SDimitry Andric case DW_CFA_restore_state: 2880b57cec5SDimitry Andric case DW_CFA_GNU_window_save: 2890b57cec5SDimitry Andric // No operands 2900b57cec5SDimitry Andric addInstruction(Opcode); 2910b57cec5SDimitry Andric break; 2920b57cec5SDimitry Andric case DW_CFA_set_loc: 2930b57cec5SDimitry Andric // Operands: Address 2945ffd83dbSDimitry Andric addInstruction(Opcode, Data.getRelocatedAddress(C)); 2950b57cec5SDimitry Andric break; 2960b57cec5SDimitry Andric case DW_CFA_advance_loc1: 2970b57cec5SDimitry Andric // Operands: 1-byte delta 2985ffd83dbSDimitry Andric addInstruction(Opcode, Data.getRelocatedValue(C, 1)); 2990b57cec5SDimitry Andric break; 3000b57cec5SDimitry Andric case DW_CFA_advance_loc2: 3010b57cec5SDimitry Andric // Operands: 2-byte delta 3025ffd83dbSDimitry Andric addInstruction(Opcode, Data.getRelocatedValue(C, 2)); 3030b57cec5SDimitry Andric break; 3040b57cec5SDimitry Andric case DW_CFA_advance_loc4: 3050b57cec5SDimitry Andric // Operands: 4-byte delta 3065ffd83dbSDimitry Andric addInstruction(Opcode, Data.getRelocatedValue(C, 4)); 3070b57cec5SDimitry Andric break; 3080b57cec5SDimitry Andric case DW_CFA_restore_extended: 3090b57cec5SDimitry Andric case DW_CFA_undefined: 3100b57cec5SDimitry Andric case DW_CFA_same_value: 3110b57cec5SDimitry Andric case DW_CFA_def_cfa_register: 3120b57cec5SDimitry Andric case DW_CFA_def_cfa_offset: 3130b57cec5SDimitry Andric case DW_CFA_GNU_args_size: 3140b57cec5SDimitry Andric // Operands: ULEB128 3155ffd83dbSDimitry Andric addInstruction(Opcode, Data.getULEB128(C)); 3160b57cec5SDimitry Andric break; 3170b57cec5SDimitry Andric case DW_CFA_def_cfa_offset_sf: 3180b57cec5SDimitry Andric // Operands: SLEB128 3195ffd83dbSDimitry Andric addInstruction(Opcode, Data.getSLEB128(C)); 3200b57cec5SDimitry Andric break; 321*fe6060f1SDimitry Andric case DW_CFA_LLVM_def_aspace_cfa: 322*fe6060f1SDimitry Andric case DW_CFA_LLVM_def_aspace_cfa_sf: { 323*fe6060f1SDimitry Andric auto RegNum = Data.getULEB128(C); 324*fe6060f1SDimitry Andric auto CfaOffset = Opcode == DW_CFA_LLVM_def_aspace_cfa 325*fe6060f1SDimitry Andric ? Data.getULEB128(C) 326*fe6060f1SDimitry Andric : Data.getSLEB128(C); 327*fe6060f1SDimitry Andric auto AddressSpace = Data.getULEB128(C); 328*fe6060f1SDimitry Andric addInstruction(Opcode, RegNum, CfaOffset, AddressSpace); 329*fe6060f1SDimitry Andric break; 330*fe6060f1SDimitry Andric } 3310b57cec5SDimitry Andric case DW_CFA_offset_extended: 3320b57cec5SDimitry Andric case DW_CFA_register: 3330b57cec5SDimitry Andric case DW_CFA_def_cfa: 3340b57cec5SDimitry Andric case DW_CFA_val_offset: { 3350b57cec5SDimitry Andric // Operands: ULEB128, ULEB128 3360b57cec5SDimitry Andric // Note: We can not embed getULEB128 directly into function 3370b57cec5SDimitry Andric // argument list. getULEB128 changes Offset and order of evaluation 3380b57cec5SDimitry Andric // for arguments is unspecified. 3395ffd83dbSDimitry Andric uint64_t op1 = Data.getULEB128(C); 3405ffd83dbSDimitry Andric uint64_t op2 = Data.getULEB128(C); 3410b57cec5SDimitry Andric addInstruction(Opcode, op1, op2); 3420b57cec5SDimitry Andric break; 3430b57cec5SDimitry Andric } 3440b57cec5SDimitry Andric case DW_CFA_offset_extended_sf: 3450b57cec5SDimitry Andric case DW_CFA_def_cfa_sf: 3460b57cec5SDimitry Andric case DW_CFA_val_offset_sf: { 3470b57cec5SDimitry Andric // Operands: ULEB128, SLEB128 3480b57cec5SDimitry Andric // Note: see comment for the previous case 3495ffd83dbSDimitry Andric uint64_t op1 = Data.getULEB128(C); 3505ffd83dbSDimitry Andric uint64_t op2 = (uint64_t)Data.getSLEB128(C); 3510b57cec5SDimitry Andric addInstruction(Opcode, op1, op2); 3520b57cec5SDimitry Andric break; 3530b57cec5SDimitry Andric } 3540b57cec5SDimitry Andric case DW_CFA_def_cfa_expression: { 3555ffd83dbSDimitry Andric uint64_t ExprLength = Data.getULEB128(C); 3560b57cec5SDimitry Andric addInstruction(Opcode, 0); 3575ffd83dbSDimitry Andric StringRef Expression = Data.getBytes(C, ExprLength); 3585ffd83dbSDimitry Andric 3595ffd83dbSDimitry Andric DataExtractor Extractor(Expression, Data.isLittleEndian(), 3605ffd83dbSDimitry Andric Data.getAddressSize()); 3615ffd83dbSDimitry Andric // Note. We do not pass the DWARF format to DWARFExpression, because 3625ffd83dbSDimitry Andric // DW_OP_call_ref, the only operation which depends on the format, is 3635ffd83dbSDimitry Andric // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5. 3645ffd83dbSDimitry Andric Instructions.back().Expression = 3655ffd83dbSDimitry Andric DWARFExpression(Extractor, Data.getAddressSize()); 3660b57cec5SDimitry Andric break; 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric case DW_CFA_expression: 3690b57cec5SDimitry Andric case DW_CFA_val_expression: { 3705ffd83dbSDimitry Andric uint64_t RegNum = Data.getULEB128(C); 3710b57cec5SDimitry Andric addInstruction(Opcode, RegNum, 0); 3725ffd83dbSDimitry Andric 3735ffd83dbSDimitry Andric uint64_t BlockLength = Data.getULEB128(C); 3745ffd83dbSDimitry Andric StringRef Expression = Data.getBytes(C, BlockLength); 3755ffd83dbSDimitry Andric DataExtractor Extractor(Expression, Data.isLittleEndian(), 3765ffd83dbSDimitry Andric Data.getAddressSize()); 3775ffd83dbSDimitry Andric // Note. We do not pass the DWARF format to DWARFExpression, because 3785ffd83dbSDimitry Andric // DW_OP_call_ref, the only operation which depends on the format, is 3795ffd83dbSDimitry Andric // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5. 3805ffd83dbSDimitry Andric Instructions.back().Expression = 3815ffd83dbSDimitry Andric DWARFExpression(Extractor, Data.getAddressSize()); 3820b57cec5SDimitry Andric break; 3830b57cec5SDimitry Andric } 3840b57cec5SDimitry Andric } 3850b57cec5SDimitry Andric } 3860b57cec5SDimitry Andric 3875ffd83dbSDimitry Andric *Offset = C.tell(); 3885ffd83dbSDimitry Andric return C.takeError(); 3890b57cec5SDimitry Andric } 3900b57cec5SDimitry Andric 391*fe6060f1SDimitry Andric StringRef CFIProgram::callFrameString(unsigned Opcode) const { 392*fe6060f1SDimitry Andric return dwarf::CallFrameString(Opcode, Arch); 393*fe6060f1SDimitry Andric } 3940b57cec5SDimitry Andric 395*fe6060f1SDimitry Andric const char *CFIProgram::operandTypeString(CFIProgram::OperandType OT) { 396*fe6060f1SDimitry Andric #define ENUM_TO_CSTR(e) \ 397*fe6060f1SDimitry Andric case e: \ 398*fe6060f1SDimitry Andric return #e; 399*fe6060f1SDimitry Andric switch (OT) { 400*fe6060f1SDimitry Andric ENUM_TO_CSTR(OT_Unset); 401*fe6060f1SDimitry Andric ENUM_TO_CSTR(OT_None); 402*fe6060f1SDimitry Andric ENUM_TO_CSTR(OT_Address); 403*fe6060f1SDimitry Andric ENUM_TO_CSTR(OT_Offset); 404*fe6060f1SDimitry Andric ENUM_TO_CSTR(OT_FactoredCodeOffset); 405*fe6060f1SDimitry Andric ENUM_TO_CSTR(OT_SignedFactDataOffset); 406*fe6060f1SDimitry Andric ENUM_TO_CSTR(OT_UnsignedFactDataOffset); 407*fe6060f1SDimitry Andric ENUM_TO_CSTR(OT_Register); 408*fe6060f1SDimitry Andric ENUM_TO_CSTR(OT_AddressSpace); 409*fe6060f1SDimitry Andric ENUM_TO_CSTR(OT_Expression); 410*fe6060f1SDimitry Andric } 411*fe6060f1SDimitry Andric return "<unknown CFIProgram::OperandType>"; 412*fe6060f1SDimitry Andric } 4130b57cec5SDimitry Andric 414*fe6060f1SDimitry Andric llvm::Expected<uint64_t> 415*fe6060f1SDimitry Andric CFIProgram::Instruction::getOperandAsUnsigned(const CFIProgram &CFIP, 416*fe6060f1SDimitry Andric uint32_t OperandIdx) const { 417*fe6060f1SDimitry Andric if (OperandIdx >= MaxOperands) 418*fe6060f1SDimitry Andric return createStringError(errc::invalid_argument, 419*fe6060f1SDimitry Andric "operand index %" PRIu32 " is not valid", 420*fe6060f1SDimitry Andric OperandIdx); 421*fe6060f1SDimitry Andric OperandType Type = CFIP.getOperandTypes()[Opcode][OperandIdx]; 422*fe6060f1SDimitry Andric uint64_t Operand = Ops[OperandIdx]; 423*fe6060f1SDimitry Andric switch (Type) { 424*fe6060f1SDimitry Andric case OT_Unset: 425*fe6060f1SDimitry Andric case OT_None: 426*fe6060f1SDimitry Andric case OT_Expression: 427*fe6060f1SDimitry Andric return createStringError(errc::invalid_argument, 428*fe6060f1SDimitry Andric "op[%" PRIu32 "] has type %s which has no value", 429*fe6060f1SDimitry Andric OperandIdx, CFIProgram::operandTypeString(Type)); 4300b57cec5SDimitry Andric 431*fe6060f1SDimitry Andric case OT_Offset: 432*fe6060f1SDimitry Andric case OT_SignedFactDataOffset: 433*fe6060f1SDimitry Andric case OT_UnsignedFactDataOffset: 434*fe6060f1SDimitry Andric return createStringError( 435*fe6060f1SDimitry Andric errc::invalid_argument, 436*fe6060f1SDimitry Andric "op[%" PRIu32 "] has OperandType OT_Offset which produces a signed " 437*fe6060f1SDimitry Andric "result, call getOperandAsSigned instead", 438*fe6060f1SDimitry Andric OperandIdx); 439*fe6060f1SDimitry Andric 440*fe6060f1SDimitry Andric case OT_Address: 441*fe6060f1SDimitry Andric case OT_Register: 442*fe6060f1SDimitry Andric case OT_AddressSpace: 443*fe6060f1SDimitry Andric return Operand; 444*fe6060f1SDimitry Andric 445*fe6060f1SDimitry Andric case OT_FactoredCodeOffset: { 446*fe6060f1SDimitry Andric const uint64_t CodeAlignmentFactor = CFIP.codeAlign(); 447*fe6060f1SDimitry Andric if (CodeAlignmentFactor == 0) 448*fe6060f1SDimitry Andric return createStringError( 449*fe6060f1SDimitry Andric errc::invalid_argument, 450*fe6060f1SDimitry Andric "op[%" PRIu32 "] has type OT_FactoredCodeOffset but code alignment " 451*fe6060f1SDimitry Andric "is zero", 452*fe6060f1SDimitry Andric OperandIdx); 453*fe6060f1SDimitry Andric return Operand * CodeAlignmentFactor; 454*fe6060f1SDimitry Andric } 455*fe6060f1SDimitry Andric } 456*fe6060f1SDimitry Andric llvm_unreachable("invalid operand type"); 457*fe6060f1SDimitry Andric } 458*fe6060f1SDimitry Andric 459*fe6060f1SDimitry Andric llvm::Expected<int64_t> 460*fe6060f1SDimitry Andric CFIProgram::Instruction::getOperandAsSigned(const CFIProgram &CFIP, 461*fe6060f1SDimitry Andric uint32_t OperandIdx) const { 462*fe6060f1SDimitry Andric if (OperandIdx >= MaxOperands) 463*fe6060f1SDimitry Andric return createStringError(errc::invalid_argument, 464*fe6060f1SDimitry Andric "operand index %" PRIu32 " is not valid", 465*fe6060f1SDimitry Andric OperandIdx); 466*fe6060f1SDimitry Andric OperandType Type = CFIP.getOperandTypes()[Opcode][OperandIdx]; 467*fe6060f1SDimitry Andric uint64_t Operand = Ops[OperandIdx]; 468*fe6060f1SDimitry Andric switch (Type) { 469*fe6060f1SDimitry Andric case OT_Unset: 470*fe6060f1SDimitry Andric case OT_None: 471*fe6060f1SDimitry Andric case OT_Expression: 472*fe6060f1SDimitry Andric return createStringError(errc::invalid_argument, 473*fe6060f1SDimitry Andric "op[%" PRIu32 "] has type %s which has no value", 474*fe6060f1SDimitry Andric OperandIdx, CFIProgram::operandTypeString(Type)); 475*fe6060f1SDimitry Andric 476*fe6060f1SDimitry Andric case OT_Address: 477*fe6060f1SDimitry Andric case OT_Register: 478*fe6060f1SDimitry Andric case OT_AddressSpace: 479*fe6060f1SDimitry Andric return createStringError( 480*fe6060f1SDimitry Andric errc::invalid_argument, 481*fe6060f1SDimitry Andric "op[%" PRIu32 "] has OperandType %s which produces an unsigned result, " 482*fe6060f1SDimitry Andric "call getOperandAsUnsigned instead", 483*fe6060f1SDimitry Andric OperandIdx, CFIProgram::operandTypeString(Type)); 484*fe6060f1SDimitry Andric 485*fe6060f1SDimitry Andric case OT_Offset: 486*fe6060f1SDimitry Andric return (int64_t)Operand; 487*fe6060f1SDimitry Andric 488*fe6060f1SDimitry Andric case OT_FactoredCodeOffset: 489*fe6060f1SDimitry Andric case OT_SignedFactDataOffset: { 490*fe6060f1SDimitry Andric const int64_t DataAlignmentFactor = CFIP.dataAlign(); 491*fe6060f1SDimitry Andric if (DataAlignmentFactor == 0) 492*fe6060f1SDimitry Andric return createStringError(errc::invalid_argument, 493*fe6060f1SDimitry Andric "op[%" PRIu32 "] has type %s but data " 494*fe6060f1SDimitry Andric "alignment is zero", 495*fe6060f1SDimitry Andric OperandIdx, CFIProgram::operandTypeString(Type)); 496*fe6060f1SDimitry Andric return int64_t(Operand) * DataAlignmentFactor; 497*fe6060f1SDimitry Andric } 498*fe6060f1SDimitry Andric 499*fe6060f1SDimitry Andric case OT_UnsignedFactDataOffset: { 500*fe6060f1SDimitry Andric const int64_t DataAlignmentFactor = CFIP.dataAlign(); 501*fe6060f1SDimitry Andric if (DataAlignmentFactor == 0) 502*fe6060f1SDimitry Andric return createStringError(errc::invalid_argument, 503*fe6060f1SDimitry Andric "op[%" PRIu32 504*fe6060f1SDimitry Andric "] has type OT_UnsignedFactDataOffset but data " 505*fe6060f1SDimitry Andric "alignment is zero", 506*fe6060f1SDimitry Andric OperandIdx); 507*fe6060f1SDimitry Andric return Operand * DataAlignmentFactor; 508*fe6060f1SDimitry Andric } 509*fe6060f1SDimitry Andric } 510*fe6060f1SDimitry Andric llvm_unreachable("invalid operand type"); 511*fe6060f1SDimitry Andric } 512*fe6060f1SDimitry Andric 513*fe6060f1SDimitry Andric Error UnwindTable::parseRows(const CFIProgram &CFIP, UnwindRow &Row, 514*fe6060f1SDimitry Andric const RegisterLocations *InitialLocs) { 515*fe6060f1SDimitry Andric std::vector<RegisterLocations> RegisterStates; 516*fe6060f1SDimitry Andric for (const CFIProgram::Instruction &Inst : CFIP) { 517*fe6060f1SDimitry Andric switch (Inst.Opcode) { 518*fe6060f1SDimitry Andric case dwarf::DW_CFA_set_loc: { 519*fe6060f1SDimitry Andric // The DW_CFA_set_loc instruction takes a single operand that 520*fe6060f1SDimitry Andric // represents a target address. The required action is to create a new 521*fe6060f1SDimitry Andric // table row using the specified address as the location. All other 522*fe6060f1SDimitry Andric // values in the new row are initially identical to the current row. 523*fe6060f1SDimitry Andric // The new location value is always greater than the current one. If 524*fe6060f1SDimitry Andric // the segment_size field of this FDE's CIE is non- zero, the initial 525*fe6060f1SDimitry Andric // location is preceded by a segment selector of the given length 526*fe6060f1SDimitry Andric llvm::Expected<uint64_t> NewAddress = Inst.getOperandAsUnsigned(CFIP, 0); 527*fe6060f1SDimitry Andric if (!NewAddress) 528*fe6060f1SDimitry Andric return NewAddress.takeError(); 529*fe6060f1SDimitry Andric if (*NewAddress <= Row.getAddress()) 530*fe6060f1SDimitry Andric return createStringError( 531*fe6060f1SDimitry Andric errc::invalid_argument, 532*fe6060f1SDimitry Andric "%s with adrress 0x%" PRIx64 " which must be greater than the " 533*fe6060f1SDimitry Andric "current row address 0x%" PRIx64, 534*fe6060f1SDimitry Andric CFIP.callFrameString(Inst.Opcode).str().c_str(), *NewAddress, 535*fe6060f1SDimitry Andric Row.getAddress()); 536*fe6060f1SDimitry Andric Rows.push_back(Row); 537*fe6060f1SDimitry Andric Row.setAddress(*NewAddress); 538*fe6060f1SDimitry Andric break; 539*fe6060f1SDimitry Andric } 540*fe6060f1SDimitry Andric 541*fe6060f1SDimitry Andric case dwarf::DW_CFA_advance_loc: 542*fe6060f1SDimitry Andric case dwarf::DW_CFA_advance_loc1: 543*fe6060f1SDimitry Andric case dwarf::DW_CFA_advance_loc2: 544*fe6060f1SDimitry Andric case dwarf::DW_CFA_advance_loc4: { 545*fe6060f1SDimitry Andric // The DW_CFA_advance instruction takes a single operand that 546*fe6060f1SDimitry Andric // represents a constant delta. The required action is to create a new 547*fe6060f1SDimitry Andric // table row with a location value that is computed by taking the 548*fe6060f1SDimitry Andric // current entry’s location value and adding the value of delta * 549*fe6060f1SDimitry Andric // code_alignment_factor. All other values in the new row are initially 550*fe6060f1SDimitry Andric // identical to the current row. 551*fe6060f1SDimitry Andric Rows.push_back(Row); 552*fe6060f1SDimitry Andric llvm::Expected<uint64_t> Offset = Inst.getOperandAsUnsigned(CFIP, 0); 553*fe6060f1SDimitry Andric if (!Offset) 554*fe6060f1SDimitry Andric return Offset.takeError(); 555*fe6060f1SDimitry Andric Row.slideAddress(*Offset); 556*fe6060f1SDimitry Andric break; 557*fe6060f1SDimitry Andric } 558*fe6060f1SDimitry Andric 559*fe6060f1SDimitry Andric case dwarf::DW_CFA_restore: 560*fe6060f1SDimitry Andric case dwarf::DW_CFA_restore_extended: { 561*fe6060f1SDimitry Andric // The DW_CFA_restore instruction takes a single operand (encoded with 562*fe6060f1SDimitry Andric // the opcode) that represents a register number. The required action 563*fe6060f1SDimitry Andric // is to change the rule for the indicated register to the rule 564*fe6060f1SDimitry Andric // assigned it by the initial_instructions in the CIE. 565*fe6060f1SDimitry Andric if (InitialLocs == nullptr) 566*fe6060f1SDimitry Andric return createStringError( 567*fe6060f1SDimitry Andric errc::invalid_argument, "%s encountered while parsing a CIE", 568*fe6060f1SDimitry Andric CFIP.callFrameString(Inst.Opcode).str().c_str()); 569*fe6060f1SDimitry Andric llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); 570*fe6060f1SDimitry Andric if (!RegNum) 571*fe6060f1SDimitry Andric return RegNum.takeError(); 572*fe6060f1SDimitry Andric if (Optional<UnwindLocation> O = 573*fe6060f1SDimitry Andric InitialLocs->getRegisterLocation(*RegNum)) 574*fe6060f1SDimitry Andric Row.getRegisterLocations().setRegisterLocation(*RegNum, *O); 575*fe6060f1SDimitry Andric else 576*fe6060f1SDimitry Andric Row.getRegisterLocations().removeRegisterLocation(*RegNum); 577*fe6060f1SDimitry Andric break; 578*fe6060f1SDimitry Andric } 579*fe6060f1SDimitry Andric 580*fe6060f1SDimitry Andric case dwarf::DW_CFA_offset: 581*fe6060f1SDimitry Andric case dwarf::DW_CFA_offset_extended: 582*fe6060f1SDimitry Andric case dwarf::DW_CFA_offset_extended_sf: { 583*fe6060f1SDimitry Andric llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); 584*fe6060f1SDimitry Andric if (!RegNum) 585*fe6060f1SDimitry Andric return RegNum.takeError(); 586*fe6060f1SDimitry Andric llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1); 587*fe6060f1SDimitry Andric if (!Offset) 588*fe6060f1SDimitry Andric return Offset.takeError(); 589*fe6060f1SDimitry Andric Row.getRegisterLocations().setRegisterLocation( 590*fe6060f1SDimitry Andric *RegNum, UnwindLocation::createAtCFAPlusOffset(*Offset)); 591*fe6060f1SDimitry Andric break; 592*fe6060f1SDimitry Andric } 593*fe6060f1SDimitry Andric 594*fe6060f1SDimitry Andric case dwarf::DW_CFA_nop: 595*fe6060f1SDimitry Andric break; 596*fe6060f1SDimitry Andric 597*fe6060f1SDimitry Andric case dwarf::DW_CFA_remember_state: 598*fe6060f1SDimitry Andric RegisterStates.push_back(Row.getRegisterLocations()); 599*fe6060f1SDimitry Andric break; 600*fe6060f1SDimitry Andric 601*fe6060f1SDimitry Andric case dwarf::DW_CFA_restore_state: 602*fe6060f1SDimitry Andric if (RegisterStates.empty()) 603*fe6060f1SDimitry Andric return createStringError(errc::invalid_argument, 604*fe6060f1SDimitry Andric "DW_CFA_restore_state without a matching " 605*fe6060f1SDimitry Andric "previous DW_CFA_remember_state"); 606*fe6060f1SDimitry Andric Row.getRegisterLocations() = RegisterStates.back(); 607*fe6060f1SDimitry Andric RegisterStates.pop_back(); 608*fe6060f1SDimitry Andric break; 609*fe6060f1SDimitry Andric 610*fe6060f1SDimitry Andric case dwarf::DW_CFA_GNU_window_save: 611*fe6060f1SDimitry Andric switch (CFIP.triple()) { 612*fe6060f1SDimitry Andric case Triple::aarch64: 613*fe6060f1SDimitry Andric case Triple::aarch64_be: 614*fe6060f1SDimitry Andric case Triple::aarch64_32: { 615*fe6060f1SDimitry Andric // DW_CFA_GNU_window_save is used for different things on different 616*fe6060f1SDimitry Andric // architectures. For aarch64 it is known as 617*fe6060f1SDimitry Andric // DW_CFA_AARCH64_negate_ra_state. The action is to toggle the 618*fe6060f1SDimitry Andric // value of the return address state between 1 and 0. If there is 619*fe6060f1SDimitry Andric // no rule for the AARCH64_DWARF_PAUTH_RA_STATE register, then it 620*fe6060f1SDimitry Andric // should be initially set to 1. 621*fe6060f1SDimitry Andric constexpr uint32_t AArch64DWARFPAuthRaState = 34; 622*fe6060f1SDimitry Andric auto LRLoc = Row.getRegisterLocations().getRegisterLocation( 623*fe6060f1SDimitry Andric AArch64DWARFPAuthRaState); 624*fe6060f1SDimitry Andric if (LRLoc) { 625*fe6060f1SDimitry Andric if (LRLoc->getLocation() == UnwindLocation::Constant) { 626*fe6060f1SDimitry Andric // Toggle the constant value from 0 to 1 or 1 to 0. 627*fe6060f1SDimitry Andric LRLoc->setConstant(LRLoc->getConstant() ^ 1); 628*fe6060f1SDimitry Andric } else { 629*fe6060f1SDimitry Andric return createStringError( 630*fe6060f1SDimitry Andric errc::invalid_argument, 631*fe6060f1SDimitry Andric "%s encountered when existing rule for this register is not " 632*fe6060f1SDimitry Andric "a constant", 633*fe6060f1SDimitry Andric CFIP.callFrameString(Inst.Opcode).str().c_str()); 634*fe6060f1SDimitry Andric } 635*fe6060f1SDimitry Andric } else { 636*fe6060f1SDimitry Andric Row.getRegisterLocations().setRegisterLocation( 637*fe6060f1SDimitry Andric AArch64DWARFPAuthRaState, UnwindLocation::createIsConstant(1)); 638*fe6060f1SDimitry Andric } 639*fe6060f1SDimitry Andric break; 640*fe6060f1SDimitry Andric } 641*fe6060f1SDimitry Andric 642*fe6060f1SDimitry Andric case Triple::sparc: 643*fe6060f1SDimitry Andric case Triple::sparcv9: 644*fe6060f1SDimitry Andric case Triple::sparcel: 645*fe6060f1SDimitry Andric for (uint32_t RegNum = 16; RegNum < 32; ++RegNum) { 646*fe6060f1SDimitry Andric Row.getRegisterLocations().setRegisterLocation( 647*fe6060f1SDimitry Andric RegNum, UnwindLocation::createAtCFAPlusOffset((RegNum - 16) * 8)); 648*fe6060f1SDimitry Andric } 649*fe6060f1SDimitry Andric break; 650*fe6060f1SDimitry Andric 651*fe6060f1SDimitry Andric default: { 652*fe6060f1SDimitry Andric return createStringError( 653*fe6060f1SDimitry Andric errc::not_supported, 654*fe6060f1SDimitry Andric "DW_CFA opcode %#x is not supported for architecture %s", 655*fe6060f1SDimitry Andric Inst.Opcode, Triple::getArchTypeName(CFIP.triple()).str().c_str()); 656*fe6060f1SDimitry Andric 657*fe6060f1SDimitry Andric break; 658*fe6060f1SDimitry Andric } 659*fe6060f1SDimitry Andric } 660*fe6060f1SDimitry Andric break; 661*fe6060f1SDimitry Andric 662*fe6060f1SDimitry Andric case dwarf::DW_CFA_undefined: { 663*fe6060f1SDimitry Andric llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); 664*fe6060f1SDimitry Andric if (!RegNum) 665*fe6060f1SDimitry Andric return RegNum.takeError(); 666*fe6060f1SDimitry Andric Row.getRegisterLocations().setRegisterLocation( 667*fe6060f1SDimitry Andric *RegNum, UnwindLocation::createUndefined()); 668*fe6060f1SDimitry Andric break; 669*fe6060f1SDimitry Andric } 670*fe6060f1SDimitry Andric 671*fe6060f1SDimitry Andric case dwarf::DW_CFA_same_value: { 672*fe6060f1SDimitry Andric llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); 673*fe6060f1SDimitry Andric if (!RegNum) 674*fe6060f1SDimitry Andric return RegNum.takeError(); 675*fe6060f1SDimitry Andric Row.getRegisterLocations().setRegisterLocation( 676*fe6060f1SDimitry Andric *RegNum, UnwindLocation::createSame()); 677*fe6060f1SDimitry Andric break; 678*fe6060f1SDimitry Andric } 679*fe6060f1SDimitry Andric 680*fe6060f1SDimitry Andric case dwarf::DW_CFA_GNU_args_size: 681*fe6060f1SDimitry Andric break; 682*fe6060f1SDimitry Andric 683*fe6060f1SDimitry Andric case dwarf::DW_CFA_register: { 684*fe6060f1SDimitry Andric llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); 685*fe6060f1SDimitry Andric if (!RegNum) 686*fe6060f1SDimitry Andric return RegNum.takeError(); 687*fe6060f1SDimitry Andric llvm::Expected<uint64_t> NewRegNum = Inst.getOperandAsUnsigned(CFIP, 1); 688*fe6060f1SDimitry Andric if (!NewRegNum) 689*fe6060f1SDimitry Andric return NewRegNum.takeError(); 690*fe6060f1SDimitry Andric Row.getRegisterLocations().setRegisterLocation( 691*fe6060f1SDimitry Andric *RegNum, UnwindLocation::createIsRegisterPlusOffset(*NewRegNum, 0)); 692*fe6060f1SDimitry Andric break; 693*fe6060f1SDimitry Andric } 694*fe6060f1SDimitry Andric 695*fe6060f1SDimitry Andric case dwarf::DW_CFA_val_offset: 696*fe6060f1SDimitry Andric case dwarf::DW_CFA_val_offset_sf: { 697*fe6060f1SDimitry Andric llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); 698*fe6060f1SDimitry Andric if (!RegNum) 699*fe6060f1SDimitry Andric return RegNum.takeError(); 700*fe6060f1SDimitry Andric llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1); 701*fe6060f1SDimitry Andric if (!Offset) 702*fe6060f1SDimitry Andric return Offset.takeError(); 703*fe6060f1SDimitry Andric Row.getRegisterLocations().setRegisterLocation( 704*fe6060f1SDimitry Andric *RegNum, UnwindLocation::createIsCFAPlusOffset(*Offset)); 705*fe6060f1SDimitry Andric break; 706*fe6060f1SDimitry Andric } 707*fe6060f1SDimitry Andric 708*fe6060f1SDimitry Andric case dwarf::DW_CFA_expression: { 709*fe6060f1SDimitry Andric llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); 710*fe6060f1SDimitry Andric if (!RegNum) 711*fe6060f1SDimitry Andric return RegNum.takeError(); 712*fe6060f1SDimitry Andric Row.getRegisterLocations().setRegisterLocation( 713*fe6060f1SDimitry Andric *RegNum, UnwindLocation::createAtDWARFExpression(*Inst.Expression)); 714*fe6060f1SDimitry Andric break; 715*fe6060f1SDimitry Andric } 716*fe6060f1SDimitry Andric 717*fe6060f1SDimitry Andric case dwarf::DW_CFA_val_expression: { 718*fe6060f1SDimitry Andric llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); 719*fe6060f1SDimitry Andric if (!RegNum) 720*fe6060f1SDimitry Andric return RegNum.takeError(); 721*fe6060f1SDimitry Andric Row.getRegisterLocations().setRegisterLocation( 722*fe6060f1SDimitry Andric *RegNum, UnwindLocation::createIsDWARFExpression(*Inst.Expression)); 723*fe6060f1SDimitry Andric break; 724*fe6060f1SDimitry Andric } 725*fe6060f1SDimitry Andric 726*fe6060f1SDimitry Andric case dwarf::DW_CFA_def_cfa_register: { 727*fe6060f1SDimitry Andric llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); 728*fe6060f1SDimitry Andric if (!RegNum) 729*fe6060f1SDimitry Andric return RegNum.takeError(); 730*fe6060f1SDimitry Andric if (Row.getCFAValue().getLocation() != UnwindLocation::RegPlusOffset) 731*fe6060f1SDimitry Andric Row.getCFAValue() = 732*fe6060f1SDimitry Andric UnwindLocation::createIsRegisterPlusOffset(*RegNum, 0); 733*fe6060f1SDimitry Andric else 734*fe6060f1SDimitry Andric Row.getCFAValue().setRegister(*RegNum); 735*fe6060f1SDimitry Andric break; 736*fe6060f1SDimitry Andric } 737*fe6060f1SDimitry Andric 738*fe6060f1SDimitry Andric case dwarf::DW_CFA_def_cfa_offset: 739*fe6060f1SDimitry Andric case dwarf::DW_CFA_def_cfa_offset_sf: { 740*fe6060f1SDimitry Andric llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 0); 741*fe6060f1SDimitry Andric if (!Offset) 742*fe6060f1SDimitry Andric return Offset.takeError(); 743*fe6060f1SDimitry Andric if (Row.getCFAValue().getLocation() != UnwindLocation::RegPlusOffset) { 744*fe6060f1SDimitry Andric return createStringError( 745*fe6060f1SDimitry Andric errc::invalid_argument, 746*fe6060f1SDimitry Andric "%s found when CFA rule was not RegPlusOffset", 747*fe6060f1SDimitry Andric CFIP.callFrameString(Inst.Opcode).str().c_str()); 748*fe6060f1SDimitry Andric } 749*fe6060f1SDimitry Andric Row.getCFAValue().setOffset(*Offset); 750*fe6060f1SDimitry Andric break; 751*fe6060f1SDimitry Andric } 752*fe6060f1SDimitry Andric 753*fe6060f1SDimitry Andric case dwarf::DW_CFA_def_cfa: 754*fe6060f1SDimitry Andric case dwarf::DW_CFA_def_cfa_sf: { 755*fe6060f1SDimitry Andric llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); 756*fe6060f1SDimitry Andric if (!RegNum) 757*fe6060f1SDimitry Andric return RegNum.takeError(); 758*fe6060f1SDimitry Andric llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1); 759*fe6060f1SDimitry Andric if (!Offset) 760*fe6060f1SDimitry Andric return Offset.takeError(); 761*fe6060f1SDimitry Andric Row.getCFAValue() = 762*fe6060f1SDimitry Andric UnwindLocation::createIsRegisterPlusOffset(*RegNum, *Offset); 763*fe6060f1SDimitry Andric break; 764*fe6060f1SDimitry Andric } 765*fe6060f1SDimitry Andric 766*fe6060f1SDimitry Andric case dwarf::DW_CFA_LLVM_def_aspace_cfa: 767*fe6060f1SDimitry Andric case dwarf::DW_CFA_LLVM_def_aspace_cfa_sf: { 768*fe6060f1SDimitry Andric llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0); 769*fe6060f1SDimitry Andric if (!RegNum) 770*fe6060f1SDimitry Andric return RegNum.takeError(); 771*fe6060f1SDimitry Andric llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1); 772*fe6060f1SDimitry Andric if (!Offset) 773*fe6060f1SDimitry Andric return Offset.takeError(); 774*fe6060f1SDimitry Andric llvm::Expected<uint32_t> CFAAddrSpace = 775*fe6060f1SDimitry Andric Inst.getOperandAsUnsigned(CFIP, 2); 776*fe6060f1SDimitry Andric if (!CFAAddrSpace) 777*fe6060f1SDimitry Andric return CFAAddrSpace.takeError(); 778*fe6060f1SDimitry Andric Row.getCFAValue() = UnwindLocation::createIsRegisterPlusOffset( 779*fe6060f1SDimitry Andric *RegNum, *Offset, *CFAAddrSpace); 780*fe6060f1SDimitry Andric break; 781*fe6060f1SDimitry Andric } 782*fe6060f1SDimitry Andric 783*fe6060f1SDimitry Andric case dwarf::DW_CFA_def_cfa_expression: 784*fe6060f1SDimitry Andric Row.getCFAValue() = 785*fe6060f1SDimitry Andric UnwindLocation::createIsDWARFExpression(*Inst.Expression); 786*fe6060f1SDimitry Andric break; 787*fe6060f1SDimitry Andric } 788*fe6060f1SDimitry Andric } 789*fe6060f1SDimitry Andric return Error::success(); 790*fe6060f1SDimitry Andric } 791*fe6060f1SDimitry Andric 792*fe6060f1SDimitry Andric ArrayRef<CFIProgram::OperandType[CFIProgram::MaxOperands]> 793*fe6060f1SDimitry Andric CFIProgram::getOperandTypes() { 794*fe6060f1SDimitry Andric static OperandType OpTypes[DW_CFA_restore + 1][MaxOperands]; 7950b57cec5SDimitry Andric static bool Initialized = false; 7960b57cec5SDimitry Andric if (Initialized) { 797*fe6060f1SDimitry Andric return ArrayRef<OperandType[MaxOperands]>(&OpTypes[0], DW_CFA_restore + 1); 7980b57cec5SDimitry Andric } 7990b57cec5SDimitry Andric Initialized = true; 8000b57cec5SDimitry Andric 801*fe6060f1SDimitry Andric #define DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OPTYPE2) \ 8020b57cec5SDimitry Andric do { \ 8030b57cec5SDimitry Andric OpTypes[OP][0] = OPTYPE0; \ 8040b57cec5SDimitry Andric OpTypes[OP][1] = OPTYPE1; \ 805*fe6060f1SDimitry Andric OpTypes[OP][2] = OPTYPE2; \ 8060b57cec5SDimitry Andric } while (false) 807*fe6060f1SDimitry Andric #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \ 808*fe6060f1SDimitry Andric DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OT_None) 8090b57cec5SDimitry Andric #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None) 8100b57cec5SDimitry Andric #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None) 8110b57cec5SDimitry Andric 8120b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_set_loc, OT_Address); 8130b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset); 8140b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset); 8150b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset); 8160b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset); 8170b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset); 8180b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset); 8190b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset); 8200b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register); 821*fe6060f1SDimitry Andric DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa, OT_Register, OT_Offset, 822*fe6060f1SDimitry Andric OT_AddressSpace); 823*fe6060f1SDimitry Andric DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa_sf, OT_Register, 824*fe6060f1SDimitry Andric OT_SignedFactDataOffset, OT_AddressSpace); 8250b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset); 8260b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset); 8270b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression); 8280b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_undefined, OT_Register); 8290b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_same_value, OT_Register); 8300b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset); 8310b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset); 8320b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset); 8330b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset); 8340b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset); 8350b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register); 8360b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression); 8370b57cec5SDimitry Andric DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression); 8380b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_restore, OT_Register); 8390b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_restore_extended, OT_Register); 8400b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_remember_state); 8410b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_restore_state); 8420b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_GNU_window_save); 8430b57cec5SDimitry Andric DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset); 8440b57cec5SDimitry Andric DECLARE_OP0(DW_CFA_nop); 8450b57cec5SDimitry Andric 8460b57cec5SDimitry Andric #undef DECLARE_OP0 8470b57cec5SDimitry Andric #undef DECLARE_OP1 8480b57cec5SDimitry Andric #undef DECLARE_OP2 8490b57cec5SDimitry Andric 850*fe6060f1SDimitry Andric return ArrayRef<OperandType[MaxOperands]>(&OpTypes[0], DW_CFA_restore + 1); 8510b57cec5SDimitry Andric } 8520b57cec5SDimitry Andric 8530b57cec5SDimitry Andric /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. 854e8d8bef9SDimitry Andric void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts, 855e8d8bef9SDimitry Andric const MCRegisterInfo *MRI, bool IsEH, 856e8d8bef9SDimitry Andric const Instruction &Instr, unsigned OperandIdx, 857e8d8bef9SDimitry Andric uint64_t Operand) const { 858*fe6060f1SDimitry Andric assert(OperandIdx < MaxOperands); 8590b57cec5SDimitry Andric uint8_t Opcode = Instr.Opcode; 8600b57cec5SDimitry Andric OperandType Type = getOperandTypes()[Opcode][OperandIdx]; 8610b57cec5SDimitry Andric 8620b57cec5SDimitry Andric switch (Type) { 8630b57cec5SDimitry Andric case OT_Unset: { 8640b57cec5SDimitry Andric OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to"; 865*fe6060f1SDimitry Andric auto OpcodeName = callFrameString(Opcode); 8660b57cec5SDimitry Andric if (!OpcodeName.empty()) 8670b57cec5SDimitry Andric OS << " " << OpcodeName; 8680b57cec5SDimitry Andric else 8690b57cec5SDimitry Andric OS << format(" Opcode %x", Opcode); 8700b57cec5SDimitry Andric break; 8710b57cec5SDimitry Andric } 8720b57cec5SDimitry Andric case OT_None: 8730b57cec5SDimitry Andric break; 8740b57cec5SDimitry Andric case OT_Address: 8750b57cec5SDimitry Andric OS << format(" %" PRIx64, Operand); 8760b57cec5SDimitry Andric break; 8770b57cec5SDimitry Andric case OT_Offset: 8780b57cec5SDimitry Andric // The offsets are all encoded in a unsigned form, but in practice 8790b57cec5SDimitry Andric // consumers use them signed. It's most certainly legacy due to 8800b57cec5SDimitry Andric // the lack of signed variants in the first Dwarf standards. 8810b57cec5SDimitry Andric OS << format(" %+" PRId64, int64_t(Operand)); 8820b57cec5SDimitry Andric break; 8830b57cec5SDimitry Andric case OT_FactoredCodeOffset: // Always Unsigned 8840b57cec5SDimitry Andric if (CodeAlignmentFactor) 8850b57cec5SDimitry Andric OS << format(" %" PRId64, Operand * CodeAlignmentFactor); 8860b57cec5SDimitry Andric else 8870b57cec5SDimitry Andric OS << format(" %" PRId64 "*code_alignment_factor" , Operand); 8880b57cec5SDimitry Andric break; 8890b57cec5SDimitry Andric case OT_SignedFactDataOffset: 8900b57cec5SDimitry Andric if (DataAlignmentFactor) 8910b57cec5SDimitry Andric OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor); 8920b57cec5SDimitry Andric else 8930b57cec5SDimitry Andric OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand)); 8940b57cec5SDimitry Andric break; 8950b57cec5SDimitry Andric case OT_UnsignedFactDataOffset: 8960b57cec5SDimitry Andric if (DataAlignmentFactor) 8970b57cec5SDimitry Andric OS << format(" %" PRId64, Operand * DataAlignmentFactor); 8980b57cec5SDimitry Andric else 8990b57cec5SDimitry Andric OS << format(" %" PRId64 "*data_alignment_factor" , Operand); 9000b57cec5SDimitry Andric break; 9010b57cec5SDimitry Andric case OT_Register: 902e8d8bef9SDimitry Andric OS << ' '; 903e8d8bef9SDimitry Andric printRegister(OS, MRI, IsEH, Operand); 9040b57cec5SDimitry Andric break; 905*fe6060f1SDimitry Andric case OT_AddressSpace: 906*fe6060f1SDimitry Andric OS << format(" in addrspace%" PRId64, Operand); 907*fe6060f1SDimitry Andric break; 9080b57cec5SDimitry Andric case OT_Expression: 9090b57cec5SDimitry Andric assert(Instr.Expression && "missing DWARFExpression object"); 9100b57cec5SDimitry Andric OS << " "; 911e8d8bef9SDimitry Andric Instr.Expression->print(OS, DumpOpts, MRI, nullptr, IsEH); 9120b57cec5SDimitry Andric break; 9130b57cec5SDimitry Andric } 9140b57cec5SDimitry Andric } 9150b57cec5SDimitry Andric 916e8d8bef9SDimitry Andric void CFIProgram::dump(raw_ostream &OS, DIDumpOptions DumpOpts, 917e8d8bef9SDimitry Andric const MCRegisterInfo *MRI, bool IsEH, 9180b57cec5SDimitry Andric unsigned IndentLevel) const { 9190b57cec5SDimitry Andric for (const auto &Instr : Instructions) { 9200b57cec5SDimitry Andric uint8_t Opcode = Instr.Opcode; 9210b57cec5SDimitry Andric OS.indent(2 * IndentLevel); 922*fe6060f1SDimitry Andric OS << callFrameString(Opcode) << ":"; 9230b57cec5SDimitry Andric for (unsigned i = 0; i < Instr.Ops.size(); ++i) 924e8d8bef9SDimitry Andric printOperand(OS, DumpOpts, MRI, IsEH, Instr, i, Instr.Ops[i]); 9250b57cec5SDimitry Andric OS << '\n'; 9260b57cec5SDimitry Andric } 9270b57cec5SDimitry Andric } 9280b57cec5SDimitry Andric 9295ffd83dbSDimitry Andric // Returns the CIE identifier to be used by the requested format. 9305ffd83dbSDimitry Andric // CIE ids for .debug_frame sections are defined in Section 7.24 of DWARFv5. 9315ffd83dbSDimitry Andric // For CIE ID in .eh_frame sections see 9325ffd83dbSDimitry Andric // https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html 9335ffd83dbSDimitry Andric constexpr uint64_t getCIEId(bool IsDWARF64, bool IsEH) { 9345ffd83dbSDimitry Andric if (IsEH) 9355ffd83dbSDimitry Andric return 0; 9365ffd83dbSDimitry Andric if (IsDWARF64) 9375ffd83dbSDimitry Andric return DW64_CIE_ID; 9385ffd83dbSDimitry Andric return DW_CIE_ID; 9395ffd83dbSDimitry Andric } 9405ffd83dbSDimitry Andric 941e8d8bef9SDimitry Andric void CIE::dump(raw_ostream &OS, DIDumpOptions DumpOpts, 942e8d8bef9SDimitry Andric const MCRegisterInfo *MRI, bool IsEH) const { 9435ffd83dbSDimitry Andric // A CIE with a zero length is a terminator entry in the .eh_frame section. 9445ffd83dbSDimitry Andric if (IsEH && Length == 0) { 9455ffd83dbSDimitry Andric OS << format("%08" PRIx64, Offset) << " ZERO terminator\n"; 9465ffd83dbSDimitry Andric return; 9475ffd83dbSDimitry Andric } 9485ffd83dbSDimitry Andric 9495ffd83dbSDimitry Andric OS << format("%08" PRIx64, Offset) 9505ffd83dbSDimitry Andric << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length) 9515ffd83dbSDimitry Andric << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8, 9525ffd83dbSDimitry Andric getCIEId(IsDWARF64, IsEH)) 9535ffd83dbSDimitry Andric << " CIE\n" 954*fe6060f1SDimitry Andric << " Format: " << FormatString(IsDWARF64) << "\n"; 955*fe6060f1SDimitry Andric if (IsEH && Version != 1) 956*fe6060f1SDimitry Andric OS << "WARNING: unsupported CIE version\n"; 957*fe6060f1SDimitry Andric OS << format(" Version: %d\n", Version) 9585ffd83dbSDimitry Andric << " Augmentation: \"" << Augmentation << "\"\n"; 9590b57cec5SDimitry Andric if (Version >= 4) { 9600b57cec5SDimitry Andric OS << format(" Address size: %u\n", (uint32_t)AddressSize); 9610b57cec5SDimitry Andric OS << format(" Segment desc size: %u\n", 9620b57cec5SDimitry Andric (uint32_t)SegmentDescriptorSize); 9630b57cec5SDimitry Andric } 9640b57cec5SDimitry Andric OS << format(" Code alignment factor: %u\n", (uint32_t)CodeAlignmentFactor); 9650b57cec5SDimitry Andric OS << format(" Data alignment factor: %d\n", (int32_t)DataAlignmentFactor); 9660b57cec5SDimitry Andric OS << format(" Return address column: %d\n", (int32_t)ReturnAddressRegister); 9670b57cec5SDimitry Andric if (Personality) 9680b57cec5SDimitry Andric OS << format(" Personality Address: %016" PRIx64 "\n", *Personality); 9690b57cec5SDimitry Andric if (!AugmentationData.empty()) { 9700b57cec5SDimitry Andric OS << " Augmentation data: "; 9710b57cec5SDimitry Andric for (uint8_t Byte : AugmentationData) 9720b57cec5SDimitry Andric OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf); 9730b57cec5SDimitry Andric OS << "\n"; 9740b57cec5SDimitry Andric } 9750b57cec5SDimitry Andric OS << "\n"; 976e8d8bef9SDimitry Andric CFIs.dump(OS, DumpOpts, MRI, IsEH); 9770b57cec5SDimitry Andric OS << "\n"; 978*fe6060f1SDimitry Andric 979*fe6060f1SDimitry Andric if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this)) 980*fe6060f1SDimitry Andric RowsOrErr->dump(OS, MRI, IsEH, 1); 981*fe6060f1SDimitry Andric else { 982*fe6060f1SDimitry Andric DumpOpts.RecoverableErrorHandler(joinErrors( 983*fe6060f1SDimitry Andric createStringError(errc::invalid_argument, 984*fe6060f1SDimitry Andric "decoding the CIE opcodes into rows failed"), 985*fe6060f1SDimitry Andric RowsOrErr.takeError())); 986*fe6060f1SDimitry Andric } 987*fe6060f1SDimitry Andric OS << "\n"; 9880b57cec5SDimitry Andric } 9890b57cec5SDimitry Andric 990e8d8bef9SDimitry Andric void FDE::dump(raw_ostream &OS, DIDumpOptions DumpOpts, 991e8d8bef9SDimitry Andric const MCRegisterInfo *MRI, bool IsEH) const { 9925ffd83dbSDimitry Andric OS << format("%08" PRIx64, Offset) 9935ffd83dbSDimitry Andric << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length) 9945ffd83dbSDimitry Andric << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8, CIEPointer) 9955ffd83dbSDimitry Andric << " FDE cie="; 9965ffd83dbSDimitry Andric if (LinkedCIE) 9975ffd83dbSDimitry Andric OS << format("%08" PRIx64, LinkedCIE->getOffset()); 9985ffd83dbSDimitry Andric else 9995ffd83dbSDimitry Andric OS << "<invalid offset>"; 10005ffd83dbSDimitry Andric OS << format(" pc=%08" PRIx64 "...%08" PRIx64 "\n", InitialLocation, 10015ffd83dbSDimitry Andric InitialLocation + AddressRange); 10025ffd83dbSDimitry Andric OS << " Format: " << FormatString(IsDWARF64) << "\n"; 10030b57cec5SDimitry Andric if (LSDAAddress) 10040b57cec5SDimitry Andric OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress); 1005e8d8bef9SDimitry Andric CFIs.dump(OS, DumpOpts, MRI, IsEH); 10060b57cec5SDimitry Andric OS << "\n"; 1007*fe6060f1SDimitry Andric 1008*fe6060f1SDimitry Andric if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this)) 1009*fe6060f1SDimitry Andric RowsOrErr->dump(OS, MRI, IsEH, 1); 1010*fe6060f1SDimitry Andric else { 1011*fe6060f1SDimitry Andric DumpOpts.RecoverableErrorHandler(joinErrors( 1012*fe6060f1SDimitry Andric createStringError(errc::invalid_argument, 1013*fe6060f1SDimitry Andric "decoding the FDE opcodes into rows failed"), 1014*fe6060f1SDimitry Andric RowsOrErr.takeError())); 1015*fe6060f1SDimitry Andric } 1016*fe6060f1SDimitry Andric OS << "\n"; 10170b57cec5SDimitry Andric } 10180b57cec5SDimitry Andric 10190b57cec5SDimitry Andric DWARFDebugFrame::DWARFDebugFrame(Triple::ArchType Arch, 10200b57cec5SDimitry Andric bool IsEH, uint64_t EHFrameAddress) 10210b57cec5SDimitry Andric : Arch(Arch), IsEH(IsEH), EHFrameAddress(EHFrameAddress) {} 10220b57cec5SDimitry Andric 10230b57cec5SDimitry Andric DWARFDebugFrame::~DWARFDebugFrame() = default; 10240b57cec5SDimitry Andric 10250b57cec5SDimitry Andric static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data, 10268bcb0991SDimitry Andric uint64_t Offset, int Length) { 10270b57cec5SDimitry Andric errs() << "DUMP: "; 10280b57cec5SDimitry Andric for (int i = 0; i < Length; ++i) { 10290b57cec5SDimitry Andric uint8_t c = Data.getU8(&Offset); 10300b57cec5SDimitry Andric errs().write_hex(c); errs() << " "; 10310b57cec5SDimitry Andric } 10320b57cec5SDimitry Andric errs() << "\n"; 10330b57cec5SDimitry Andric } 10340b57cec5SDimitry Andric 10355ffd83dbSDimitry Andric Error DWARFDebugFrame::parse(DWARFDataExtractor Data) { 10368bcb0991SDimitry Andric uint64_t Offset = 0; 10378bcb0991SDimitry Andric DenseMap<uint64_t, CIE *> CIEs; 10380b57cec5SDimitry Andric 10390b57cec5SDimitry Andric while (Data.isValidOffset(Offset)) { 10408bcb0991SDimitry Andric uint64_t StartOffset = Offset; 10410b57cec5SDimitry Andric 10425ffd83dbSDimitry Andric uint64_t Length; 10435ffd83dbSDimitry Andric DwarfFormat Format; 10445ffd83dbSDimitry Andric std::tie(Length, Format) = Data.getInitialLength(&Offset); 10455ffd83dbSDimitry Andric bool IsDWARF64 = Format == DWARF64; 10460b57cec5SDimitry Andric 10475ffd83dbSDimitry Andric // If the Length is 0, then this CIE is a terminator. We add it because some 10485ffd83dbSDimitry Andric // dumper tools might need it to print something special for such entries 10495ffd83dbSDimitry Andric // (e.g. llvm-objdump --dwarf=frames prints "ZERO terminator"). 10505ffd83dbSDimitry Andric if (Length == 0) { 10515ffd83dbSDimitry Andric auto Cie = std::make_unique<CIE>( 10525ffd83dbSDimitry Andric IsDWARF64, StartOffset, 0, 0, SmallString<8>(), 0, 0, 0, 0, 0, 10535ffd83dbSDimitry Andric SmallString<8>(), 0, 0, None, None, Arch); 10545ffd83dbSDimitry Andric CIEs[StartOffset] = Cie.get(); 10555ffd83dbSDimitry Andric Entries.push_back(std::move(Cie)); 10565ffd83dbSDimitry Andric break; 10570b57cec5SDimitry Andric } 10580b57cec5SDimitry Andric 10590b57cec5SDimitry Andric // At this point, Offset points to the next field after Length. 10600b57cec5SDimitry Andric // Length is the structure size excluding itself. Compute an offset one 10610b57cec5SDimitry Andric // past the end of the structure (needed to know how many instructions to 10620b57cec5SDimitry Andric // read). 10638bcb0991SDimitry Andric uint64_t StartStructureOffset = Offset; 10648bcb0991SDimitry Andric uint64_t EndStructureOffset = Offset + Length; 10650b57cec5SDimitry Andric 10660b57cec5SDimitry Andric // The Id field's size depends on the DWARF format 10675ffd83dbSDimitry Andric Error Err = Error::success(); 10685ffd83dbSDimitry Andric uint64_t Id = Data.getRelocatedValue((IsDWARF64 && !IsEH) ? 8 : 4, &Offset, 10695ffd83dbSDimitry Andric /*SectionIndex=*/nullptr, &Err); 10705ffd83dbSDimitry Andric if (Err) 10715ffd83dbSDimitry Andric return Err; 10720b57cec5SDimitry Andric 10735ffd83dbSDimitry Andric if (Id == getCIEId(IsDWARF64, IsEH)) { 10740b57cec5SDimitry Andric uint8_t Version = Data.getU8(&Offset); 10750b57cec5SDimitry Andric const char *Augmentation = Data.getCStr(&Offset); 10760b57cec5SDimitry Andric StringRef AugmentationString(Augmentation ? Augmentation : ""); 10770b57cec5SDimitry Andric uint8_t AddressSize = Version < 4 ? Data.getAddressSize() : 10780b57cec5SDimitry Andric Data.getU8(&Offset); 10790b57cec5SDimitry Andric Data.setAddressSize(AddressSize); 10800b57cec5SDimitry Andric uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset); 10810b57cec5SDimitry Andric uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset); 10820b57cec5SDimitry Andric int64_t DataAlignmentFactor = Data.getSLEB128(&Offset); 10830b57cec5SDimitry Andric uint64_t ReturnAddressRegister = 10840b57cec5SDimitry Andric Version == 1 ? Data.getU8(&Offset) : Data.getULEB128(&Offset); 10850b57cec5SDimitry Andric 10860b57cec5SDimitry Andric // Parse the augmentation data for EH CIEs 10870b57cec5SDimitry Andric StringRef AugmentationData(""); 10880b57cec5SDimitry Andric uint32_t FDEPointerEncoding = DW_EH_PE_absptr; 10890b57cec5SDimitry Andric uint32_t LSDAPointerEncoding = DW_EH_PE_omit; 10900b57cec5SDimitry Andric Optional<uint64_t> Personality; 10910b57cec5SDimitry Andric Optional<uint32_t> PersonalityEncoding; 10920b57cec5SDimitry Andric if (IsEH) { 10930b57cec5SDimitry Andric Optional<uint64_t> AugmentationLength; 10948bcb0991SDimitry Andric uint64_t StartAugmentationOffset; 10958bcb0991SDimitry Andric uint64_t EndAugmentationOffset; 10960b57cec5SDimitry Andric 10970b57cec5SDimitry Andric // Walk the augmentation string to get all the augmentation data. 10980b57cec5SDimitry Andric for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) { 10990b57cec5SDimitry Andric switch (AugmentationString[i]) { 11000b57cec5SDimitry Andric default: 11015ffd83dbSDimitry Andric return createStringError( 11025ffd83dbSDimitry Andric errc::invalid_argument, 11035ffd83dbSDimitry Andric "unknown augmentation character in entry at 0x%" PRIx64, 11045ffd83dbSDimitry Andric StartOffset); 11050b57cec5SDimitry Andric case 'L': 11060b57cec5SDimitry Andric LSDAPointerEncoding = Data.getU8(&Offset); 11070b57cec5SDimitry Andric break; 11080b57cec5SDimitry Andric case 'P': { 11090b57cec5SDimitry Andric if (Personality) 11105ffd83dbSDimitry Andric return createStringError( 11115ffd83dbSDimitry Andric errc::invalid_argument, 11125ffd83dbSDimitry Andric "duplicate personality in entry at 0x%" PRIx64, StartOffset); 11130b57cec5SDimitry Andric PersonalityEncoding = Data.getU8(&Offset); 11140b57cec5SDimitry Andric Personality = Data.getEncodedPointer( 11150b57cec5SDimitry Andric &Offset, *PersonalityEncoding, 11160b57cec5SDimitry Andric EHFrameAddress ? EHFrameAddress + Offset : 0); 11170b57cec5SDimitry Andric break; 11180b57cec5SDimitry Andric } 11190b57cec5SDimitry Andric case 'R': 11200b57cec5SDimitry Andric FDEPointerEncoding = Data.getU8(&Offset); 11210b57cec5SDimitry Andric break; 11220b57cec5SDimitry Andric case 'S': 11230b57cec5SDimitry Andric // Current frame is a signal trampoline. 11240b57cec5SDimitry Andric break; 11250b57cec5SDimitry Andric case 'z': 11260b57cec5SDimitry Andric if (i) 11275ffd83dbSDimitry Andric return createStringError( 11285ffd83dbSDimitry Andric errc::invalid_argument, 11295ffd83dbSDimitry Andric "'z' must be the first character at 0x%" PRIx64, StartOffset); 11300b57cec5SDimitry Andric // Parse the augmentation length first. We only parse it if 11310b57cec5SDimitry Andric // the string contains a 'z'. 11320b57cec5SDimitry Andric AugmentationLength = Data.getULEB128(&Offset); 11330b57cec5SDimitry Andric StartAugmentationOffset = Offset; 11348bcb0991SDimitry Andric EndAugmentationOffset = Offset + *AugmentationLength; 11350b57cec5SDimitry Andric break; 11360b57cec5SDimitry Andric case 'B': 11370b57cec5SDimitry Andric // B-Key is used for signing functions associated with this 11380b57cec5SDimitry Andric // augmentation string 11390b57cec5SDimitry Andric break; 11400b57cec5SDimitry Andric } 11410b57cec5SDimitry Andric } 11420b57cec5SDimitry Andric 11430b57cec5SDimitry Andric if (AugmentationLength.hasValue()) { 11440b57cec5SDimitry Andric if (Offset != EndAugmentationOffset) 11455ffd83dbSDimitry Andric return createStringError(errc::invalid_argument, 11465ffd83dbSDimitry Andric "parsing augmentation data at 0x%" PRIx64 11475ffd83dbSDimitry Andric " failed", 11485ffd83dbSDimitry Andric StartOffset); 11490b57cec5SDimitry Andric AugmentationData = Data.getData().slice(StartAugmentationOffset, 11500b57cec5SDimitry Andric EndAugmentationOffset); 11510b57cec5SDimitry Andric } 11520b57cec5SDimitry Andric } 11530b57cec5SDimitry Andric 11548bcb0991SDimitry Andric auto Cie = std::make_unique<CIE>( 11555ffd83dbSDimitry Andric IsDWARF64, StartOffset, Length, Version, AugmentationString, 11565ffd83dbSDimitry Andric AddressSize, SegmentDescriptorSize, CodeAlignmentFactor, 11575ffd83dbSDimitry Andric DataAlignmentFactor, ReturnAddressRegister, AugmentationData, 11585ffd83dbSDimitry Andric FDEPointerEncoding, LSDAPointerEncoding, Personality, 11595ffd83dbSDimitry Andric PersonalityEncoding, Arch); 11600b57cec5SDimitry Andric CIEs[StartOffset] = Cie.get(); 11610b57cec5SDimitry Andric Entries.emplace_back(std::move(Cie)); 11620b57cec5SDimitry Andric } else { 11630b57cec5SDimitry Andric // FDE 11640b57cec5SDimitry Andric uint64_t CIEPointer = Id; 11650b57cec5SDimitry Andric uint64_t InitialLocation = 0; 11660b57cec5SDimitry Andric uint64_t AddressRange = 0; 11670b57cec5SDimitry Andric Optional<uint64_t> LSDAAddress; 11680b57cec5SDimitry Andric CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer]; 11690b57cec5SDimitry Andric 11700b57cec5SDimitry Andric if (IsEH) { 11710b57cec5SDimitry Andric // The address size is encoded in the CIE we reference. 11720b57cec5SDimitry Andric if (!Cie) 11735ffd83dbSDimitry Andric return createStringError(errc::invalid_argument, 11745ffd83dbSDimitry Andric "parsing FDE data at 0x%" PRIx64 11755ffd83dbSDimitry Andric " failed due to missing CIE", 11765ffd83dbSDimitry Andric StartOffset); 1177e8d8bef9SDimitry Andric if (auto Val = 1178e8d8bef9SDimitry Andric Data.getEncodedPointer(&Offset, Cie->getFDEPointerEncoding(), 1179e8d8bef9SDimitry Andric EHFrameAddress + Offset)) { 11800b57cec5SDimitry Andric InitialLocation = *Val; 11810b57cec5SDimitry Andric } 11820b57cec5SDimitry Andric if (auto Val = Data.getEncodedPointer( 11830b57cec5SDimitry Andric &Offset, Cie->getFDEPointerEncoding(), 0)) { 11840b57cec5SDimitry Andric AddressRange = *Val; 11850b57cec5SDimitry Andric } 11860b57cec5SDimitry Andric 11870b57cec5SDimitry Andric StringRef AugmentationString = Cie->getAugmentationString(); 11880b57cec5SDimitry Andric if (!AugmentationString.empty()) { 11890b57cec5SDimitry Andric // Parse the augmentation length and data for this FDE. 11900b57cec5SDimitry Andric uint64_t AugmentationLength = Data.getULEB128(&Offset); 11910b57cec5SDimitry Andric 11928bcb0991SDimitry Andric uint64_t EndAugmentationOffset = Offset + AugmentationLength; 11930b57cec5SDimitry Andric 11940b57cec5SDimitry Andric // Decode the LSDA if the CIE augmentation string said we should. 11950b57cec5SDimitry Andric if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) { 11960b57cec5SDimitry Andric LSDAAddress = Data.getEncodedPointer( 11970b57cec5SDimitry Andric &Offset, Cie->getLSDAPointerEncoding(), 11980b57cec5SDimitry Andric EHFrameAddress ? Offset + EHFrameAddress : 0); 11990b57cec5SDimitry Andric } 12000b57cec5SDimitry Andric 12010b57cec5SDimitry Andric if (Offset != EndAugmentationOffset) 12025ffd83dbSDimitry Andric return createStringError(errc::invalid_argument, 12035ffd83dbSDimitry Andric "parsing augmentation data at 0x%" PRIx64 12045ffd83dbSDimitry Andric " failed", 12055ffd83dbSDimitry Andric StartOffset); 12060b57cec5SDimitry Andric } 12070b57cec5SDimitry Andric } else { 12080b57cec5SDimitry Andric InitialLocation = Data.getRelocatedAddress(&Offset); 12090b57cec5SDimitry Andric AddressRange = Data.getRelocatedAddress(&Offset); 12100b57cec5SDimitry Andric } 12110b57cec5SDimitry Andric 12125ffd83dbSDimitry Andric Entries.emplace_back(new FDE(IsDWARF64, StartOffset, Length, CIEPointer, 12135ffd83dbSDimitry Andric InitialLocation, AddressRange, Cie, 12145ffd83dbSDimitry Andric LSDAAddress, Arch)); 12150b57cec5SDimitry Andric } 12160b57cec5SDimitry Andric 12170b57cec5SDimitry Andric if (Error E = 12185ffd83dbSDimitry Andric Entries.back()->cfis().parse(Data, &Offset, EndStructureOffset)) 12195ffd83dbSDimitry Andric return E; 12200b57cec5SDimitry Andric 12210b57cec5SDimitry Andric if (Offset != EndStructureOffset) 12225ffd83dbSDimitry Andric return createStringError( 12235ffd83dbSDimitry Andric errc::invalid_argument, 12245ffd83dbSDimitry Andric "parsing entry instructions at 0x%" PRIx64 " failed", StartOffset); 12250b57cec5SDimitry Andric } 12265ffd83dbSDimitry Andric 12275ffd83dbSDimitry Andric return Error::success(); 12280b57cec5SDimitry Andric } 12290b57cec5SDimitry Andric 12300b57cec5SDimitry Andric FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const { 12310b57cec5SDimitry Andric auto It = partition_point(Entries, [=](const std::unique_ptr<FrameEntry> &E) { 12320b57cec5SDimitry Andric return E->getOffset() < Offset; 12330b57cec5SDimitry Andric }); 12340b57cec5SDimitry Andric if (It != Entries.end() && (*It)->getOffset() == Offset) 12350b57cec5SDimitry Andric return It->get(); 12360b57cec5SDimitry Andric return nullptr; 12370b57cec5SDimitry Andric } 12380b57cec5SDimitry Andric 1239e8d8bef9SDimitry Andric void DWARFDebugFrame::dump(raw_ostream &OS, DIDumpOptions DumpOpts, 1240e8d8bef9SDimitry Andric const MCRegisterInfo *MRI, 12410b57cec5SDimitry Andric Optional<uint64_t> Offset) const { 12420b57cec5SDimitry Andric if (Offset) { 12430b57cec5SDimitry Andric if (auto *Entry = getEntryAtOffset(*Offset)) 1244e8d8bef9SDimitry Andric Entry->dump(OS, DumpOpts, MRI, IsEH); 12450b57cec5SDimitry Andric return; 12460b57cec5SDimitry Andric } 12470b57cec5SDimitry Andric 12480b57cec5SDimitry Andric OS << "\n"; 12490b57cec5SDimitry Andric for (const auto &Entry : Entries) 1250e8d8bef9SDimitry Andric Entry->dump(OS, DumpOpts, MRI, IsEH); 12510b57cec5SDimitry Andric } 1252