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