DWARFDebugFrame.cpp revision 46e0d1d58c9c1f288cbf943e4c930efd1a2968af
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#include "DWARFDebugFrame.h"
11#include "llvm/ADT/SmallString.h"
12#include "llvm/Support/DataTypes.h"
13#include "llvm/Support/ErrorHandling.h"
14#include "llvm/Support/Dwarf.h"
15#include "llvm/Support/Format.h"
16#include "llvm/Support/raw_ostream.h"
17#include <string>
18#include <vector>
19
20using namespace llvm;
21using namespace dwarf;
22
23
24/// \brief Abstract frame entry defining the common interface concrete
25/// entries implement.
26class llvm::FrameEntry {
27public:
28  enum FrameKind {FK_CIE, FK_FDE};
29  FrameEntry(FrameKind K, DataExtractor D, uint64_t Offset, uint64_t Length)
30    : Kind(K), Data(D), Offset(Offset), Length(Length) {}
31
32  virtual ~FrameEntry() {
33  }
34
35  FrameKind getKind() const { return Kind; }
36  virtual uint64_t getOffset() const { return Offset; }
37
38  /// \brief Parse and store a sequence of CFI instructions from our data
39  /// stream, starting at *Offset and ending at EndOffset. If everything
40  /// goes well, *Offset should be equal to EndOffset when this method
41  /// returns. Otherwise, an error occurred.
42  virtual void parseInstructions(uint32_t *Offset, uint32_t EndOffset);
43
44  /// \brief Dump the entry header to the given output stream.
45  virtual void dumpHeader(raw_ostream &OS) const = 0;
46
47  /// \brief Dump the entry's instructions to the given output stream.
48  virtual void dumpInstructions(raw_ostream &OS) const;
49
50protected:
51  const FrameKind Kind;
52
53  /// \brief The data stream holding the section from which the entry was
54  /// parsed.
55  DataExtractor Data;
56
57  /// \brief Offset of this entry in the section.
58  uint64_t Offset;
59
60  /// \brief Entry length as specified in DWARF.
61  uint64_t Length;
62
63  /// An entry may contain CFI instructions. An instruction consists of an
64  /// opcode and an optional sequence of operands.
65  typedef std::vector<uint64_t> Operands;
66  struct Instruction {
67    Instruction(uint8_t Opcode)
68      : Opcode(Opcode)
69    {}
70
71    uint8_t Opcode;
72    Operands Ops;
73  };
74
75  std::vector<Instruction> Instructions;
76
77  /// Convenience methods to add a new instruction with the given opcode and
78  /// operands to the Instructions vector.
79  void addInstruction(uint8_t Opcode) {
80    Instructions.push_back(Instruction(Opcode));
81  }
82
83  void addInstruction(uint8_t Opcode, uint64_t Operand1) {
84    Instructions.push_back(Instruction(Opcode));
85    Instructions.back().Ops.push_back(Operand1);
86  }
87
88  void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
89    Instructions.push_back(Instruction(Opcode));
90    Instructions.back().Ops.push_back(Operand1);
91    Instructions.back().Ops.push_back(Operand2);
92  }
93};
94
95
96// See DWARF standard v3, section 7.23
97const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
98const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
99
100
101void FrameEntry::parseInstructions(uint32_t *Offset, uint32_t EndOffset) {
102  while (*Offset < EndOffset) {
103    uint8_t Opcode = Data.getU8(Offset);
104    // Some instructions have a primary opcode encoded in the top bits.
105    uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK;
106
107    if (Primary) {
108      // If it's a primary opcode, the first operand is encoded in the bottom
109      // bits of the opcode itself.
110      uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
111      switch (Primary) {
112        default: llvm_unreachable("Impossible primary CFI opcode");
113        case DW_CFA_advance_loc:
114        case DW_CFA_restore:
115          addInstruction(Primary, Op1);
116          break;
117        case DW_CFA_offset:
118          addInstruction(Primary, Op1, Data.getULEB128(Offset));
119          break;
120      }
121    } else {
122      // Extended opcode - its value is Opcode itself.
123      switch (Opcode) {
124        default: llvm_unreachable("Invalid extended CFI opcode");
125        case DW_CFA_nop:
126        case DW_CFA_remember_state:
127        case DW_CFA_restore_state:
128          // No operands
129          addInstruction(Opcode);
130          break;
131        case DW_CFA_set_loc:
132          // Operands: Address
133          addInstruction(Opcode, Data.getAddress(Offset));
134          break;
135        case DW_CFA_advance_loc1:
136          // Operands: 1-byte delta
137          addInstruction(Opcode, Data.getU8(Offset));
138          break;
139        case DW_CFA_advance_loc2:
140          // Operands: 2-byte delta
141          addInstruction(Opcode, Data.getU16(Offset));
142          break;
143        case DW_CFA_advance_loc4:
144          // Operands: 4-byte delta
145          addInstruction(Opcode, Data.getU32(Offset));
146          break;
147        case DW_CFA_restore_extended:
148        case DW_CFA_undefined:
149        case DW_CFA_same_value:
150        case DW_CFA_def_cfa_register:
151        case DW_CFA_def_cfa_offset:
152          // Operands: ULEB128
153          addInstruction(Opcode, Data.getULEB128(Offset));
154          break;
155        case DW_CFA_def_cfa_offset_sf:
156          // Operands: SLEB128
157          addInstruction(Opcode, Data.getSLEB128(Offset));
158          break;
159        case DW_CFA_offset_extended:
160        case DW_CFA_register:
161        case DW_CFA_def_cfa:
162        case DW_CFA_val_offset:
163          // Operands: ULEB128, ULEB128
164          addInstruction(Opcode, Data.getULEB128(Offset),
165                                 Data.getULEB128(Offset));
166          break;
167        case DW_CFA_offset_extended_sf:
168        case DW_CFA_def_cfa_sf:
169        case DW_CFA_val_offset_sf:
170          // Operands: ULEB128, SLEB128
171          addInstruction(Opcode, Data.getULEB128(Offset),
172                                 Data.getSLEB128(Offset));
173          break;
174        case DW_CFA_def_cfa_expression:
175        case DW_CFA_expression:
176        case DW_CFA_val_expression:
177          // TODO: implement this
178          report_fatal_error("Values with expressions not implemented yet!");
179      }
180    }
181  }
182}
183
184
185void FrameEntry::dumpInstructions(raw_ostream &OS) const {
186  // TODO: at the moment only instruction names are dumped. Expand this to
187  // dump operands as well.
188  for (std::vector<Instruction>::const_iterator I = Instructions.begin(),
189                                                E = Instructions.end();
190       I != E; ++I) {
191    uint8_t Opcode = I->Opcode;
192    if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
193      Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
194    OS << "  " << CallFrameString(Opcode) << ":\n";
195  }
196}
197
198
199namespace {
200/// \brief DWARF Common Information Entry (CIE)
201class CIE : public FrameEntry {
202public:
203  // CIEs (and FDEs) are simply container classes, so the only sensible way to
204  // create them is by providing the full parsed contents in the constructor.
205  CIE(DataExtractor D, uint64_t Offset, uint64_t Length, uint8_t Version,
206      SmallString<8> Augmentation, uint64_t CodeAlignmentFactor,
207      int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister)
208   : FrameEntry(FK_CIE, D, Offset, Length), Version(Version),
209     Augmentation(Augmentation), CodeAlignmentFactor(CodeAlignmentFactor),
210     DataAlignmentFactor(DataAlignmentFactor),
211     ReturnAddressRegister(ReturnAddressRegister) {}
212
213  ~CIE() {
214  }
215
216  void dumpHeader(raw_ostream &OS) const {
217    OS << format("%08x %08x %08x CIE",
218                 (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID)
219       << "\n";
220    OS << format("  Version:               %d\n", Version);
221    OS << "  Augmentation:          \"" << Augmentation << "\"\n";
222    OS << format("  Code alignment factor: %u\n",
223                 (uint32_t)CodeAlignmentFactor);
224    OS << format("  Data alignment factor: %d\n",
225                 (int32_t)DataAlignmentFactor);
226    OS << format("  Return address column: %d\n",
227                 (int32_t)ReturnAddressRegister);
228    OS << "\n";
229  }
230
231  static bool classof(const FrameEntry *FE) {
232    return FE->getKind() == FK_CIE;
233  }
234
235private:
236  /// The following fields are defined in section 6.4.1 of the DWARF standard v3
237  uint8_t Version;
238  SmallString<8> Augmentation;
239  uint64_t CodeAlignmentFactor;
240  int64_t DataAlignmentFactor;
241  uint64_t ReturnAddressRegister;
242};
243
244
245/// \brief DWARF Frame Description Entry (FDE)
246class FDE : public FrameEntry {
247public:
248  // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
249  // an offset to the CIE (provided by parsing the FDE header). The CIE itself
250  // is obtained lazily once it's actually required.
251  FDE(DataExtractor D, uint64_t Offset, uint64_t Length,
252      int64_t LinkedCIEOffset, uint64_t InitialLocation, uint64_t AddressRange)
253   : FrameEntry(FK_FDE, D, Offset, Length), LinkedCIEOffset(LinkedCIEOffset),
254     InitialLocation(InitialLocation), AddressRange(AddressRange),
255     LinkedCIE(NULL) {}
256
257  ~FDE() {
258  }
259
260  void dumpHeader(raw_ostream &OS) const {
261    OS << format("%08x %08x %08x FDE ",
262                 (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset);
263    OS << format("cie=%08x pc=%08x...%08x\n",
264                 (int32_t)LinkedCIEOffset,
265                 (uint32_t)InitialLocation,
266                 (uint32_t)InitialLocation + (uint32_t)AddressRange);
267    if (LinkedCIE) {
268      OS << format("%p\n", LinkedCIE);
269    }
270  }
271
272  static bool classof(const FrameEntry *FE) {
273    return FE->getKind() == FK_FDE;
274  }
275private:
276
277  /// The following fields are defined in section 6.4.1 of the DWARF standard v3
278  uint64_t LinkedCIEOffset;
279  uint64_t InitialLocation;
280  uint64_t AddressRange;
281  CIE *LinkedCIE;
282};
283} // end anonymous namespace
284
285
286DWARFDebugFrame::DWARFDebugFrame() {
287}
288
289
290DWARFDebugFrame::~DWARFDebugFrame() {
291  for (EntryVector::iterator I = Entries.begin(), E = Entries.end();
292       I != E; ++I) {
293    delete *I;
294  }
295}
296
297
298static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
299                                              uint32_t Offset, int Length) {
300  errs() << "DUMP: ";
301  for (int i = 0; i < Length; ++i) {
302    uint8_t c = Data.getU8(&Offset);
303    errs().write_hex(c); errs() << " ";
304  }
305  errs() << "\n";
306}
307
308
309void DWARFDebugFrame::parse(DataExtractor Data) {
310  uint32_t Offset = 0;
311
312  while (Data.isValidOffset(Offset)) {
313    uint32_t StartOffset = Offset;
314
315    bool IsDWARF64 = false;
316    uint64_t Length = Data.getU32(&Offset);
317    uint64_t Id;
318
319    if (Length == UINT32_MAX) {
320      // DWARF-64 is distinguished by the first 32 bits of the initial length
321      // field being 0xffffffff. Then, the next 64 bits are the actual entry
322      // length.
323      IsDWARF64 = true;
324      Length = Data.getU64(&Offset);
325    }
326
327    // At this point, Offset points to the next field after Length.
328    // Length is the structure size excluding itself. Compute an offset one
329    // past the end of the structure (needed to know how many instructions to
330    // read).
331    // TODO: For honest DWARF64 support, DataExtractor will have to treat
332    //       offset_ptr as uint64_t*
333    uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);
334
335    // The Id field's size depends on the DWARF format
336    Id = Data.getUnsigned(&Offset, IsDWARF64 ? 8 : 4);
337    bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID);
338
339    FrameEntry *Entry = 0;
340    if (IsCIE) {
341      // Note: this is specifically DWARFv3 CIE header structure. It was
342      // changed in DWARFv4. We currently don't support reading DWARFv4
343      // here because LLVM itself does not emit it (and LLDB doesn't
344      // support it either).
345      uint8_t Version = Data.getU8(&Offset);
346      const char *Augmentation = Data.getCStr(&Offset);
347      uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
348      int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
349      uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);
350
351      Entry = new CIE(Data, StartOffset, Length, Version,
352                      StringRef(Augmentation), CodeAlignmentFactor,
353                      DataAlignmentFactor, ReturnAddressRegister);
354    } else {
355      // FDE
356      uint64_t CIEPointer = Id;
357      uint64_t InitialLocation = Data.getAddress(&Offset);
358      uint64_t AddressRange = Data.getAddress(&Offset);
359
360      Entry = new FDE(Data, StartOffset, Length, CIEPointer,
361                      InitialLocation, AddressRange);
362    }
363
364    assert(Entry && "Expected Entry to be populated with CIE or FDE");
365    Entry->parseInstructions(&Offset, EndStructureOffset);
366
367    if (Offset == EndStructureOffset) {
368      // Entry instrucitons parsed successfully.
369      Entries.push_back(Entry);
370    } else {
371      std::string Str;
372      raw_string_ostream OS(Str);
373      OS << format("Parsing entry instructions at %lx failed",
374                   Entry->getOffset());
375      report_fatal_error(Str);
376    }
377  }
378}
379
380
381void DWARFDebugFrame::dump(raw_ostream &OS) const {
382  OS << "\n";
383  for (EntryVector::const_iterator I = Entries.begin(), E = Entries.end();
384       I != E; ++I) {
385    FrameEntry *Entry = *I;
386    Entry->dumpHeader(OS);
387    Entry->dumpInstructions(OS);
388    OS << "\n";
389  }
390}
391
392