1321369Sdim//===- DWARFDebugFrame.h - Parsing of .debug_frame --------------*- C++ -*-===// 2283625Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6283625Sdim// 7283625Sdim//===----------------------------------------------------------------------===// 8283625Sdim 9321369Sdim#ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H 10321369Sdim#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H 11283625Sdim 12341825Sdim#include "llvm/ADT/ArrayRef.h" 13341825Sdim#include "llvm/ADT/iterator.h" 14341825Sdim#include "llvm/ADT/SmallString.h" 15344779Sdim#include "llvm/ADT/Triple.h" 16341825Sdim#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" 17341825Sdim#include "llvm/DebugInfo/DWARF/DWARFExpression.h" 18341825Sdim#include "llvm/Support/Error.h" 19283625Sdim#include <memory> 20283625Sdim#include <vector> 21283625Sdim 22283625Sdimnamespace llvm { 23283625Sdim 24321369Sdimclass raw_ostream; 25283625Sdim 26341825Sdimnamespace dwarf { 27341825Sdim 28341825Sdim/// Represent a sequence of Call Frame Information instructions that, when read 29341825Sdim/// in order, construct a table mapping PC to frame state. This can also be 30341825Sdim/// referred to as "CFI rules" in DWARF literature to avoid confusion with 31341825Sdim/// computer programs in the broader sense, and in this context each instruction 32341825Sdim/// would be a rule to establish the mapping. Refer to pg. 172 in the DWARF5 33341825Sdim/// manual, "6.4.1 Structure of Call Frame Information". 34341825Sdimclass CFIProgram { 35341825Sdimpublic: 36341825Sdim typedef SmallVector<uint64_t, 2> Operands; 37341825Sdim 38341825Sdim /// An instruction consists of a DWARF CFI opcode and an optional sequence of 39341825Sdim /// operands. If it refers to an expression, then this expression has its own 40341825Sdim /// sequence of operations and operands handled separately by DWARFExpression. 41341825Sdim struct Instruction { 42341825Sdim Instruction(uint8_t Opcode) : Opcode(Opcode) {} 43341825Sdim 44341825Sdim uint8_t Opcode; 45341825Sdim Operands Ops; 46341825Sdim // Associated DWARF expression in case this instruction refers to one 47341825Sdim Optional<DWARFExpression> Expression; 48341825Sdim }; 49341825Sdim 50341825Sdim using InstrList = std::vector<Instruction>; 51341825Sdim using iterator = InstrList::iterator; 52341825Sdim using const_iterator = InstrList::const_iterator; 53341825Sdim 54341825Sdim iterator begin() { return Instructions.begin(); } 55341825Sdim const_iterator begin() const { return Instructions.begin(); } 56341825Sdim iterator end() { return Instructions.end(); } 57341825Sdim const_iterator end() const { return Instructions.end(); } 58341825Sdim 59341825Sdim unsigned size() const { return (unsigned)Instructions.size(); } 60341825Sdim bool empty() const { return Instructions.empty(); } 61341825Sdim 62344779Sdim CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor, 63344779Sdim Triple::ArchType Arch) 64341825Sdim : CodeAlignmentFactor(CodeAlignmentFactor), 65344779Sdim DataAlignmentFactor(DataAlignmentFactor), 66344779Sdim Arch(Arch) {} 67341825Sdim 68341825Sdim /// Parse and store a sequence of CFI instructions from Data, 69341825Sdim /// starting at *Offset and ending at EndOffset. *Offset is updated 70341825Sdim /// to EndOffset upon successful parsing, or indicates the offset 71341825Sdim /// where a problem occurred in case an error is returned. 72360784Sdim Error parse(DWARFDataExtractor Data, uint64_t *Offset, uint64_t EndOffset); 73341825Sdim 74341825Sdim void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, 75341825Sdim unsigned IndentLevel = 1) const; 76341825Sdim 77341825Sdimprivate: 78341825Sdim std::vector<Instruction> Instructions; 79341825Sdim const uint64_t CodeAlignmentFactor; 80341825Sdim const int64_t DataAlignmentFactor; 81344779Sdim Triple::ArchType Arch; 82341825Sdim 83341825Sdim /// Convenience method to add a new instruction with the given opcode. 84341825Sdim void addInstruction(uint8_t Opcode) { 85341825Sdim Instructions.push_back(Instruction(Opcode)); 86341825Sdim } 87341825Sdim 88341825Sdim /// Add a new single-operand instruction. 89341825Sdim void addInstruction(uint8_t Opcode, uint64_t Operand1) { 90341825Sdim Instructions.push_back(Instruction(Opcode)); 91341825Sdim Instructions.back().Ops.push_back(Operand1); 92341825Sdim } 93341825Sdim 94341825Sdim /// Add a new instruction that has two operands. 95341825Sdim void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) { 96341825Sdim Instructions.push_back(Instruction(Opcode)); 97341825Sdim Instructions.back().Ops.push_back(Operand1); 98341825Sdim Instructions.back().Ops.push_back(Operand2); 99341825Sdim } 100341825Sdim 101341825Sdim /// Types of operands to CFI instructions 102341825Sdim /// In DWARF, this type is implicitly tied to a CFI instruction opcode and 103341825Sdim /// thus this type doesn't need to be explictly written to the file (this is 104341825Sdim /// not a DWARF encoding). The relationship of instrs to operand types can 105341825Sdim /// be obtained from getOperandTypes() and is only used to simplify 106341825Sdim /// instruction printing. 107341825Sdim enum OperandType { 108341825Sdim OT_Unset, 109341825Sdim OT_None, 110341825Sdim OT_Address, 111341825Sdim OT_Offset, 112341825Sdim OT_FactoredCodeOffset, 113341825Sdim OT_SignedFactDataOffset, 114341825Sdim OT_UnsignedFactDataOffset, 115341825Sdim OT_Register, 116341825Sdim OT_Expression 117341825Sdim }; 118341825Sdim 119341825Sdim /// Retrieve the array describing the types of operands according to the enum 120341825Sdim /// above. This is indexed by opcode. 121341825Sdim static ArrayRef<OperandType[2]> getOperandTypes(); 122341825Sdim 123341825Sdim /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. 124341825Sdim void printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, 125341825Sdim const Instruction &Instr, unsigned OperandIdx, 126341825Sdim uint64_t Operand) const; 127341825Sdim}; 128341825Sdim 129341825Sdim/// An entry in either debug_frame or eh_frame. This entry can be a CIE or an 130341825Sdim/// FDE. 131341825Sdimclass FrameEntry { 132341825Sdimpublic: 133341825Sdim enum FrameKind { FK_CIE, FK_FDE }; 134341825Sdim 135341825Sdim FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length, uint64_t CodeAlign, 136344779Sdim int64_t DataAlign, Triple::ArchType Arch) 137344779Sdim : Kind(K), Offset(Offset), Length(Length), 138344779Sdim CFIs(CodeAlign, DataAlign, Arch) {} 139341825Sdim 140341825Sdim virtual ~FrameEntry() {} 141341825Sdim 142341825Sdim FrameKind getKind() const { return Kind; } 143341825Sdim uint64_t getOffset() const { return Offset; } 144341825Sdim uint64_t getLength() const { return Length; } 145341825Sdim const CFIProgram &cfis() const { return CFIs; } 146341825Sdim CFIProgram &cfis() { return CFIs; } 147341825Sdim 148341825Sdim /// Dump the instructions in this CFI fragment 149341825Sdim virtual void dump(raw_ostream &OS, const MCRegisterInfo *MRI, 150341825Sdim bool IsEH) const = 0; 151341825Sdim 152341825Sdimprotected: 153341825Sdim const FrameKind Kind; 154341825Sdim 155341825Sdim /// Offset of this entry in the section. 156341825Sdim const uint64_t Offset; 157341825Sdim 158341825Sdim /// Entry length as specified in DWARF. 159341825Sdim const uint64_t Length; 160341825Sdim 161341825Sdim CFIProgram CFIs; 162341825Sdim}; 163341825Sdim 164341825Sdim/// DWARF Common Information Entry (CIE) 165341825Sdimclass CIE : public FrameEntry { 166341825Sdimpublic: 167341825Sdim // CIEs (and FDEs) are simply container classes, so the only sensible way to 168341825Sdim // create them is by providing the full parsed contents in the constructor. 169341825Sdim CIE(uint64_t Offset, uint64_t Length, uint8_t Version, 170341825Sdim SmallString<8> Augmentation, uint8_t AddressSize, 171341825Sdim uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor, 172341825Sdim int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister, 173341825Sdim SmallString<8> AugmentationData, uint32_t FDEPointerEncoding, 174341825Sdim uint32_t LSDAPointerEncoding, Optional<uint64_t> Personality, 175344779Sdim Optional<uint32_t> PersonalityEnc, Triple::ArchType Arch) 176341825Sdim : FrameEntry(FK_CIE, Offset, Length, CodeAlignmentFactor, 177344779Sdim DataAlignmentFactor, Arch), 178341825Sdim Version(Version), Augmentation(std::move(Augmentation)), 179341825Sdim AddressSize(AddressSize), SegmentDescriptorSize(SegmentDescriptorSize), 180341825Sdim CodeAlignmentFactor(CodeAlignmentFactor), 181341825Sdim DataAlignmentFactor(DataAlignmentFactor), 182341825Sdim ReturnAddressRegister(ReturnAddressRegister), 183341825Sdim AugmentationData(std::move(AugmentationData)), 184341825Sdim FDEPointerEncoding(FDEPointerEncoding), 185341825Sdim LSDAPointerEncoding(LSDAPointerEncoding), Personality(Personality), 186341825Sdim PersonalityEnc(PersonalityEnc) {} 187341825Sdim 188341825Sdim static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_CIE; } 189341825Sdim 190341825Sdim StringRef getAugmentationString() const { return Augmentation; } 191341825Sdim uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; } 192341825Sdim int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; } 193341825Sdim uint8_t getVersion() const { return Version; } 194341825Sdim uint64_t getReturnAddressRegister() const { return ReturnAddressRegister; } 195341825Sdim Optional<uint64_t> getPersonalityAddress() const { return Personality; } 196341825Sdim Optional<uint32_t> getPersonalityEncoding() const { return PersonalityEnc; } 197341825Sdim 198341825Sdim uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; } 199341825Sdim 200341825Sdim uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; } 201341825Sdim 202341825Sdim void dump(raw_ostream &OS, const MCRegisterInfo *MRI, 203341825Sdim bool IsEH) const override; 204341825Sdim 205341825Sdimprivate: 206341825Sdim /// The following fields are defined in section 6.4.1 of the DWARF standard v4 207341825Sdim const uint8_t Version; 208341825Sdim const SmallString<8> Augmentation; 209341825Sdim const uint8_t AddressSize; 210341825Sdim const uint8_t SegmentDescriptorSize; 211341825Sdim const uint64_t CodeAlignmentFactor; 212341825Sdim const int64_t DataAlignmentFactor; 213341825Sdim const uint64_t ReturnAddressRegister; 214341825Sdim 215341825Sdim // The following are used when the CIE represents an EH frame entry. 216341825Sdim const SmallString<8> AugmentationData; 217341825Sdim const uint32_t FDEPointerEncoding; 218341825Sdim const uint32_t LSDAPointerEncoding; 219341825Sdim const Optional<uint64_t> Personality; 220341825Sdim const Optional<uint32_t> PersonalityEnc; 221341825Sdim}; 222341825Sdim 223341825Sdim/// DWARF Frame Description Entry (FDE) 224341825Sdimclass FDE : public FrameEntry { 225341825Sdimpublic: 226341825Sdim // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with 227341825Sdim // an offset to the CIE (provided by parsing the FDE header). The CIE itself 228341825Sdim // is obtained lazily once it's actually required. 229341825Sdim FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset, 230341825Sdim uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie, 231344779Sdim Optional<uint64_t> LSDAAddress, Triple::ArchType Arch) 232341825Sdim : FrameEntry(FK_FDE, Offset, Length, 233341825Sdim Cie ? Cie->getCodeAlignmentFactor() : 0, 234344779Sdim Cie ? Cie->getDataAlignmentFactor() : 0, 235344779Sdim Arch), 236341825Sdim LinkedCIEOffset(LinkedCIEOffset), InitialLocation(InitialLocation), 237341825Sdim AddressRange(AddressRange), LinkedCIE(Cie), LSDAAddress(LSDAAddress) {} 238341825Sdim 239341825Sdim ~FDE() override = default; 240341825Sdim 241341825Sdim const CIE *getLinkedCIE() const { return LinkedCIE; } 242341825Sdim uint64_t getInitialLocation() const { return InitialLocation; } 243341825Sdim uint64_t getAddressRange() const { return AddressRange; } 244341825Sdim Optional<uint64_t> getLSDAAddress() const { return LSDAAddress; } 245341825Sdim 246341825Sdim void dump(raw_ostream &OS, const MCRegisterInfo *MRI, 247341825Sdim bool IsEH) const override; 248341825Sdim 249341825Sdim static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; } 250341825Sdim 251341825Sdimprivate: 252341825Sdim /// The following fields are defined in section 6.4.1 of the DWARF standard v3 253341825Sdim const uint64_t LinkedCIEOffset; 254341825Sdim const uint64_t InitialLocation; 255341825Sdim const uint64_t AddressRange; 256341825Sdim const CIE *LinkedCIE; 257341825Sdim const Optional<uint64_t> LSDAAddress; 258341825Sdim}; 259341825Sdim 260341825Sdim} // end namespace dwarf 261341825Sdim 262341825Sdim/// A parsed .debug_frame or .eh_frame section 263283625Sdimclass DWARFDebugFrame { 264344779Sdim const Triple::ArchType Arch; 265309124Sdim // True if this is parsing an eh_frame section. 266341825Sdim const bool IsEH; 267341825Sdim // Not zero for sane pointer values coming out of eh_frame 268341825Sdim const uint64_t EHFrameAddress; 269321369Sdim 270341825Sdim std::vector<std::unique_ptr<dwarf::FrameEntry>> Entries; 271341825Sdim using iterator = pointee_iterator<decltype(Entries)::const_iterator>; 272341825Sdim 273341825Sdim /// Return the entry at the given offset or nullptr. 274341825Sdim dwarf::FrameEntry *getEntryAtOffset(uint64_t Offset) const; 275341825Sdim 276283625Sdimpublic: 277341825Sdim // If IsEH is true, assume it is a .eh_frame section. Otherwise, 278341825Sdim // it is a .debug_frame section. EHFrameAddress should be different 279341825Sdim // than zero for correct parsing of .eh_frame addresses when they 280341825Sdim // use a PC-relative encoding. 281344779Sdim DWARFDebugFrame(Triple::ArchType Arch, 282344779Sdim bool IsEH = false, uint64_t EHFrameAddress = 0); 283283625Sdim ~DWARFDebugFrame(); 284283625Sdim 285327952Sdim /// Dump the section data into the given stream. 286341825Sdim void dump(raw_ostream &OS, const MCRegisterInfo *MRI, 287341825Sdim Optional<uint64_t> Offset) const; 288283625Sdim 289341825Sdim /// Parse the section from raw data. \p Data is assumed to contain the whole 290341825Sdim /// frame section contents to be parsed. 291341825Sdim void parse(DWARFDataExtractor Data); 292283625Sdim 293327952Sdim /// Return whether the section has any entries. 294327952Sdim bool empty() const { return Entries.empty(); } 295327952Sdim 296341825Sdim /// DWARF Frame entries accessors 297341825Sdim iterator begin() const { return Entries.begin(); } 298341825Sdim iterator end() const { return Entries.end(); } 299341825Sdim iterator_range<iterator> entries() const { 300341825Sdim return iterator_range<iterator>(Entries.begin(), Entries.end()); 301341825Sdim } 302327952Sdim 303341825Sdim uint64_t getEHFrameAddress() const { return EHFrameAddress; } 304283625Sdim}; 305283625Sdim 306321369Sdim} // end namespace llvm 307283625Sdim 308321369Sdim#endif // LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H 309