DWARFDebugFrame.cpp revision ba42625074aa7f4f1324a5d6666bd0e302b57f2b
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===//
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                     The LLVM Compiler Infrastructure
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "DWARFDebugFrame.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/ADT/SmallString.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Support/DataTypes.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Support/Dwarf.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "llvm/Support/Format.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace llvm;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace dwarf;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class llvm::FrameEntry {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  enum FrameKind {FK_CIE, FK_FDE};
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FrameEntry(FrameKind K, DataExtractor D, uint64_t Offset, uint64_t Length)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : Kind(K), Data(D), Offset(Offset), Length(Length) {}
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FrameKind getKind() const { return Kind; }
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void dumpHeader(raw_ostream &OS) const = 0;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)protected:
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const FrameKind Kind;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// \brief The data stream holding the section from which the entry was
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// parsed.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DataExtractor Data;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// \brief Offset of this entry in the section.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64_t Offset;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// \brief Entry length as specified in DWARF.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64_t Length;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CIE : public FrameEntry {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CIEs (and FDEs) are simply container classes, so the only sensible way to
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // create them is by providing the full parsed contents in the constructor.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CIE(DataExtractor D, uint64_t Offset, uint64_t Length, uint8_t Version,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SmallString<8> Augmentation, uint64_t CodeAlignmentFactor,
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister)
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)   : FrameEntry(FK_CIE, D, Offset, Length), Version(Version),
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     Augmentation(Augmentation), CodeAlignmentFactor(CodeAlignmentFactor),
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     DataAlignmentFactor(DataAlignmentFactor),
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     ReturnAddressRegister(ReturnAddressRegister) {}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void dumpHeader(raw_ostream &OS) const {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OS << format("%08x %08x %08x CIE", Offset, Length, DW_CIE_ID) << "\n";
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OS << format("  Version:               %d\n", Version);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OS << "  Augmentation:          \"" << Augmentation << "\"\n";
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OS << format("  Code alignment factor: %u\n", CodeAlignmentFactor);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OS << format("  Data alignment factor: %d\n", DataAlignmentFactor);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OS << format("  Return address column: %d\n", ReturnAddressRegister);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OS << "\n";
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool classof(const FrameEntry *FE) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return FE->getKind() == FK_CIE;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)private:
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// The following fields are defined in section 6.4.1 of the DWARF standard v3
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8_t Version;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SmallString<8> Augmentation;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64_t CodeAlignmentFactor;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64_t DataAlignmentFactor;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64_t ReturnAddressRegister;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FDE : public FrameEntry {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // an offset to the CIE (provided by parsing the FDE header). The CIE itself
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is obtained lazily once it's actually required.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FDE(DataExtractor D, uint64_t Offset, uint64_t Length,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int64_t LinkedCIEOffset, uint64_t InitialLocation, uint64_t AddressRange)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   : FrameEntry(FK_FDE, D, Offset, Length), LinkedCIEOffset(LinkedCIEOffset),
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     InitialLocation(InitialLocation), AddressRange(AddressRange),
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     LinkedCIE(NULL) {}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void dumpHeader(raw_ostream &OS) const {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OS << format("%08x %08x %08x FDE ", Offset, Length, LinkedCIEOffset);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OS << format("cie=%08x pc=%08x...%08x\n",
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 LinkedCIEOffset, InitialLocation,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 InitialLocation + AddressRange);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OS << "\n";
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool classof(const FrameEntry *FE) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return FE->getKind() == FK_FDE;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)private:
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// The following fields are defined in section 6.4.1 of the DWARF standard v3
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64_t LinkedCIEOffset;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64_t InitialLocation;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64_t AddressRange;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CIE *LinkedCIE;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DWARFDebugFrame::DWARFDebugFrame() {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DWARFDebugFrame::~DWARFDebugFrame() {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (EntryVector::iterator I = Entries.begin(), E = Entries.end();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       I != E; ++I) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete *I;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
126                                              uint32_t Offset, int Length) {
127  errs() << "DUMP: ";
128  for (int i = 0; i < Length; ++i) {
129    uint8_t c = Data.getU8(&Offset);
130    errs().write_hex(c); errs() << " ";
131  }
132  errs() << "\n";
133}
134
135
136void DWARFDebugFrame::parse(DataExtractor Data) {
137  uint32_t Offset = 0;
138
139  while (Data.isValidOffset(Offset)) {
140    uint32_t StartOffset = Offset;
141
142    bool IsDWARF64 = false;
143    uint64_t Length = Data.getU32(&Offset);
144    uint64_t Id;
145
146    if (Length == UINT32_MAX) {
147      // DWARF-64 is distinguished by the first 32 bits of the initial length
148      // field being 0xffffffff. Then, the next 64 bits are the actual entry
149      // length.
150      IsDWARF64 = true;
151      Length = Data.getU64(&Offset);
152    }
153
154    // At this point, Offset points to the next field after Length.
155    // Length is the structure size excluding itself. Compute an offset one
156    // past the end of the structure (needed to know how many instructions to
157    // read).
158    // TODO: For honest DWARF64 support, DataExtractor will have to treat
159    //       offset_ptr as uint64_t*
160    uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);
161
162    // The Id field's size depends on the DWARF format
163    Id = Data.getUnsigned(&Offset, IsDWARF64 ? 8 : 4);
164    bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID);
165
166    if (IsCIE) {
167      // Note: this is specifically DWARFv3 CIE header structure. It was
168      // changed in DWARFv4.
169      uint8_t Version = Data.getU8(&Offset);
170      const char *Augmentation = Data.getCStr(&Offset);
171      uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
172      int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
173      uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);
174
175      CIE *NewCIE = new CIE(Data, StartOffset, Length, Version,
176                            StringRef(Augmentation), CodeAlignmentFactor,
177                            DataAlignmentFactor, ReturnAddressRegister);
178      Entries.push_back(NewCIE);
179    } else {
180      // FDE
181      uint64_t CIEPointer = Id;
182      uint64_t InitialLocation = Data.getAddress(&Offset);
183      uint64_t AddressRange = Data.getAddress(&Offset);
184
185      FDE *NewFDE = new FDE(Data, StartOffset, Length, CIEPointer,
186                            InitialLocation, AddressRange);
187      Entries.push_back(NewFDE);
188    }
189
190    Offset = EndStructureOffset;
191  }
192}
193
194
195void DWARFDebugFrame::dump(raw_ostream &OS) const {
196  OS << "\n";
197  for (EntryVector::const_iterator I = Entries.begin(), E = Entries.end();
198       I != E; ++I) {
199    (*I)->dumpHeader(OS);
200  }
201}
202
203