1 //===- DWARFDebugFrame.h - Parsing of .debug_frame --------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H 11 #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H 12 13 #include "llvm/ADT/ArrayRef.h" 14 #include "llvm/ADT/iterator.h" 15 #include "llvm/ADT/SmallString.h" 16 #include "llvm/ADT/Triple.h" 17 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" 18 #include "llvm/DebugInfo/DWARF/DWARFExpression.h" 19 #include "llvm/Support/Error.h" 20 #include <memory> 21 #include <vector> 22 23 namespace llvm { 24 25 class raw_ostream; 26 27 namespace dwarf { 28 29 /// Represent a sequence of Call Frame Information instructions that, when read 30 /// in order, construct a table mapping PC to frame state. This can also be 31 /// referred to as "CFI rules" in DWARF literature to avoid confusion with 32 /// computer programs in the broader sense, and in this context each instruction 33 /// would be a rule to establish the mapping. Refer to pg. 172 in the DWARF5 34 /// manual, "6.4.1 Structure of Call Frame Information". 35 class CFIProgram { 36 public: 37 typedef SmallVector<uint64_t, 2> Operands; 38 39 /// An instruction consists of a DWARF CFI opcode and an optional sequence of 40 /// operands. If it refers to an expression, then this expression has its own 41 /// sequence of operations and operands handled separately by DWARFExpression. 42 struct Instruction { InstructionInstruction43 Instruction(uint8_t Opcode) : Opcode(Opcode) {} 44 45 uint8_t Opcode; 46 Operands Ops; 47 // Associated DWARF expression in case this instruction refers to one 48 Optional<DWARFExpression> Expression; 49 }; 50 51 using InstrList = std::vector<Instruction>; 52 using iterator = InstrList::iterator; 53 using const_iterator = InstrList::const_iterator; 54 begin()55 iterator begin() { return Instructions.begin(); } begin()56 const_iterator begin() const { return Instructions.begin(); } end()57 iterator end() { return Instructions.end(); } end()58 const_iterator end() const { return Instructions.end(); } 59 size()60 unsigned size() const { return (unsigned)Instructions.size(); } empty()61 bool empty() const { return Instructions.empty(); } 62 CFIProgram(uint64_t CodeAlignmentFactor,int64_t DataAlignmentFactor,Triple::ArchType Arch)63 CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor, 64 Triple::ArchType Arch) 65 : CodeAlignmentFactor(CodeAlignmentFactor), 66 DataAlignmentFactor(DataAlignmentFactor), 67 Arch(Arch) {} 68 69 /// Parse and store a sequence of CFI instructions from Data, 70 /// starting at *Offset and ending at EndOffset. *Offset is updated 71 /// to EndOffset upon successful parsing, or indicates the offset 72 /// where a problem occurred in case an error is returned. 73 Error parse(DataExtractor Data, uint32_t *Offset, uint32_t EndOffset); 74 75 void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, 76 unsigned IndentLevel = 1) const; 77 78 private: 79 std::vector<Instruction> Instructions; 80 const uint64_t CodeAlignmentFactor; 81 const int64_t DataAlignmentFactor; 82 Triple::ArchType Arch; 83 84 /// Convenience method to add a new instruction with the given opcode. addInstruction(uint8_t Opcode)85 void addInstruction(uint8_t Opcode) { 86 Instructions.push_back(Instruction(Opcode)); 87 } 88 89 /// Add a new single-operand instruction. addInstruction(uint8_t Opcode,uint64_t Operand1)90 void addInstruction(uint8_t Opcode, uint64_t Operand1) { 91 Instructions.push_back(Instruction(Opcode)); 92 Instructions.back().Ops.push_back(Operand1); 93 } 94 95 /// Add a new instruction that has two operands. addInstruction(uint8_t Opcode,uint64_t Operand1,uint64_t Operand2)96 void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) { 97 Instructions.push_back(Instruction(Opcode)); 98 Instructions.back().Ops.push_back(Operand1); 99 Instructions.back().Ops.push_back(Operand2); 100 } 101 102 /// Types of operands to CFI instructions 103 /// In DWARF, this type is implicitly tied to a CFI instruction opcode and 104 /// thus this type doesn't need to be explictly written to the file (this is 105 /// not a DWARF encoding). The relationship of instrs to operand types can 106 /// be obtained from getOperandTypes() and is only used to simplify 107 /// instruction printing. 108 enum OperandType { 109 OT_Unset, 110 OT_None, 111 OT_Address, 112 OT_Offset, 113 OT_FactoredCodeOffset, 114 OT_SignedFactDataOffset, 115 OT_UnsignedFactDataOffset, 116 OT_Register, 117 OT_Expression 118 }; 119 120 /// Retrieve the array describing the types of operands according to the enum 121 /// above. This is indexed by opcode. 122 static ArrayRef<OperandType[2]> getOperandTypes(); 123 124 /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. 125 void printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, 126 const Instruction &Instr, unsigned OperandIdx, 127 uint64_t Operand) const; 128 }; 129 130 /// An entry in either debug_frame or eh_frame. This entry can be a CIE or an 131 /// FDE. 132 class FrameEntry { 133 public: 134 enum FrameKind { FK_CIE, FK_FDE }; 135 FrameEntry(FrameKind K,uint64_t Offset,uint64_t Length,uint64_t CodeAlign,int64_t DataAlign,Triple::ArchType Arch)136 FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length, uint64_t CodeAlign, 137 int64_t DataAlign, Triple::ArchType Arch) 138 : Kind(K), Offset(Offset), Length(Length), 139 CFIs(CodeAlign, DataAlign, Arch) {} 140 ~FrameEntry()141 virtual ~FrameEntry() {} 142 getKind()143 FrameKind getKind() const { return Kind; } getOffset()144 uint64_t getOffset() const { return Offset; } getLength()145 uint64_t getLength() const { return Length; } cfis()146 const CFIProgram &cfis() const { return CFIs; } cfis()147 CFIProgram &cfis() { return CFIs; } 148 149 /// Dump the instructions in this CFI fragment 150 virtual void dump(raw_ostream &OS, const MCRegisterInfo *MRI, 151 bool IsEH) const = 0; 152 153 protected: 154 const FrameKind Kind; 155 156 /// Offset of this entry in the section. 157 const uint64_t Offset; 158 159 /// Entry length as specified in DWARF. 160 const uint64_t Length; 161 162 CFIProgram CFIs; 163 }; 164 165 /// DWARF Common Information Entry (CIE) 166 class CIE : public FrameEntry { 167 public: 168 // CIEs (and FDEs) are simply container classes, so the only sensible way to 169 // create them is by providing the full parsed contents in the constructor. CIE(uint64_t Offset,uint64_t Length,uint8_t Version,SmallString<8> Augmentation,uint8_t AddressSize,uint8_t SegmentDescriptorSize,uint64_t CodeAlignmentFactor,int64_t DataAlignmentFactor,uint64_t ReturnAddressRegister,SmallString<8> AugmentationData,uint32_t FDEPointerEncoding,uint32_t LSDAPointerEncoding,Optional<uint64_t> Personality,Optional<uint32_t> PersonalityEnc,Triple::ArchType Arch)170 CIE(uint64_t Offset, uint64_t Length, uint8_t Version, 171 SmallString<8> Augmentation, uint8_t AddressSize, 172 uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor, 173 int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister, 174 SmallString<8> AugmentationData, uint32_t FDEPointerEncoding, 175 uint32_t LSDAPointerEncoding, Optional<uint64_t> Personality, 176 Optional<uint32_t> PersonalityEnc, Triple::ArchType Arch) 177 : FrameEntry(FK_CIE, Offset, Length, CodeAlignmentFactor, 178 DataAlignmentFactor, Arch), 179 Version(Version), Augmentation(std::move(Augmentation)), 180 AddressSize(AddressSize), SegmentDescriptorSize(SegmentDescriptorSize), 181 CodeAlignmentFactor(CodeAlignmentFactor), 182 DataAlignmentFactor(DataAlignmentFactor), 183 ReturnAddressRegister(ReturnAddressRegister), 184 AugmentationData(std::move(AugmentationData)), 185 FDEPointerEncoding(FDEPointerEncoding), 186 LSDAPointerEncoding(LSDAPointerEncoding), Personality(Personality), 187 PersonalityEnc(PersonalityEnc) {} 188 classof(const FrameEntry * FE)189 static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_CIE; } 190 getAugmentationString()191 StringRef getAugmentationString() const { return Augmentation; } getCodeAlignmentFactor()192 uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; } getDataAlignmentFactor()193 int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; } getVersion()194 uint8_t getVersion() const { return Version; } getReturnAddressRegister()195 uint64_t getReturnAddressRegister() const { return ReturnAddressRegister; } getPersonalityAddress()196 Optional<uint64_t> getPersonalityAddress() const { return Personality; } getPersonalityEncoding()197 Optional<uint32_t> getPersonalityEncoding() const { return PersonalityEnc; } 198 getFDEPointerEncoding()199 uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; } 200 getLSDAPointerEncoding()201 uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; } 202 203 void dump(raw_ostream &OS, const MCRegisterInfo *MRI, 204 bool IsEH) const override; 205 206 private: 207 /// The following fields are defined in section 6.4.1 of the DWARF standard v4 208 const uint8_t Version; 209 const SmallString<8> Augmentation; 210 const uint8_t AddressSize; 211 const uint8_t SegmentDescriptorSize; 212 const uint64_t CodeAlignmentFactor; 213 const int64_t DataAlignmentFactor; 214 const uint64_t ReturnAddressRegister; 215 216 // The following are used when the CIE represents an EH frame entry. 217 const SmallString<8> AugmentationData; 218 const uint32_t FDEPointerEncoding; 219 const uint32_t LSDAPointerEncoding; 220 const Optional<uint64_t> Personality; 221 const Optional<uint32_t> PersonalityEnc; 222 }; 223 224 /// DWARF Frame Description Entry (FDE) 225 class FDE : public FrameEntry { 226 public: 227 // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with 228 // an offset to the CIE (provided by parsing the FDE header). The CIE itself 229 // is obtained lazily once it's actually required. FDE(uint64_t Offset,uint64_t Length,int64_t LinkedCIEOffset,uint64_t InitialLocation,uint64_t AddressRange,CIE * Cie,Optional<uint64_t> LSDAAddress,Triple::ArchType Arch)230 FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset, 231 uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie, 232 Optional<uint64_t> LSDAAddress, Triple::ArchType Arch) 233 : FrameEntry(FK_FDE, Offset, Length, 234 Cie ? Cie->getCodeAlignmentFactor() : 0, 235 Cie ? Cie->getDataAlignmentFactor() : 0, 236 Arch), 237 LinkedCIEOffset(LinkedCIEOffset), InitialLocation(InitialLocation), 238 AddressRange(AddressRange), LinkedCIE(Cie), LSDAAddress(LSDAAddress) {} 239 240 ~FDE() override = default; 241 getLinkedCIE()242 const CIE *getLinkedCIE() const { return LinkedCIE; } getInitialLocation()243 uint64_t getInitialLocation() const { return InitialLocation; } getAddressRange()244 uint64_t getAddressRange() const { return AddressRange; } getLSDAAddress()245 Optional<uint64_t> getLSDAAddress() const { return LSDAAddress; } 246 247 void dump(raw_ostream &OS, const MCRegisterInfo *MRI, 248 bool IsEH) const override; 249 classof(const FrameEntry * FE)250 static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; } 251 252 private: 253 /// The following fields are defined in section 6.4.1 of the DWARF standard v3 254 const uint64_t LinkedCIEOffset; 255 const uint64_t InitialLocation; 256 const uint64_t AddressRange; 257 const CIE *LinkedCIE; 258 const Optional<uint64_t> LSDAAddress; 259 }; 260 261 } // end namespace dwarf 262 263 /// A parsed .debug_frame or .eh_frame section 264 class DWARFDebugFrame { 265 const Triple::ArchType Arch; 266 // True if this is parsing an eh_frame section. 267 const bool IsEH; 268 // Not zero for sane pointer values coming out of eh_frame 269 const uint64_t EHFrameAddress; 270 271 std::vector<std::unique_ptr<dwarf::FrameEntry>> Entries; 272 using iterator = pointee_iterator<decltype(Entries)::const_iterator>; 273 274 /// Return the entry at the given offset or nullptr. 275 dwarf::FrameEntry *getEntryAtOffset(uint64_t Offset) const; 276 277 public: 278 // If IsEH is true, assume it is a .eh_frame section. Otherwise, 279 // it is a .debug_frame section. EHFrameAddress should be different 280 // than zero for correct parsing of .eh_frame addresses when they 281 // use a PC-relative encoding. 282 DWARFDebugFrame(Triple::ArchType Arch, 283 bool IsEH = false, uint64_t EHFrameAddress = 0); 284 ~DWARFDebugFrame(); 285 286 /// Dump the section data into the given stream. 287 void dump(raw_ostream &OS, const MCRegisterInfo *MRI, 288 Optional<uint64_t> Offset) const; 289 290 /// Parse the section from raw data. \p Data is assumed to contain the whole 291 /// frame section contents to be parsed. 292 void parse(DWARFDataExtractor Data); 293 294 /// Return whether the section has any entries. empty()295 bool empty() const { return Entries.empty(); } 296 297 /// DWARF Frame entries accessors begin()298 iterator begin() const { return Entries.begin(); } end()299 iterator end() const { return Entries.end(); } entries()300 iterator_range<iterator> entries() const { 301 return iterator_range<iterator>(Entries.begin(), Entries.end()); 302 } 303 getEHFrameAddress()304 uint64_t getEHFrameAddress() const { return EHFrameAddress; } 305 }; 306 307 } // end namespace llvm 308 309 #endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H 310