DWARFDebugFrame.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
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/Dwarf.h"
14#include "llvm/Support/ErrorHandling.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        case DW_CFA_GNU_window_save:
129          // No operands
130          addInstruction(Opcode);
131          break;
132        case DW_CFA_set_loc:
133          // Operands: Address
134          addInstruction(Opcode, Data.getAddress(Offset));
135          break;
136        case DW_CFA_advance_loc1:
137          // Operands: 1-byte delta
138          addInstruction(Opcode, Data.getU8(Offset));
139          break;
140        case DW_CFA_advance_loc2:
141          // Operands: 2-byte delta
142          addInstruction(Opcode, Data.getU16(Offset));
143          break;
144        case DW_CFA_advance_loc4:
145          // Operands: 4-byte delta
146          addInstruction(Opcode, Data.getU32(Offset));
147          break;
148        case DW_CFA_restore_extended:
149        case DW_CFA_undefined:
150        case DW_CFA_same_value:
151        case DW_CFA_def_cfa_register:
152        case DW_CFA_def_cfa_offset:
153          // Operands: ULEB128
154          addInstruction(Opcode, Data.getULEB128(Offset));
155          break;
156        case DW_CFA_def_cfa_offset_sf:
157          // Operands: SLEB128
158          addInstruction(Opcode, Data.getSLEB128(Offset));
159          break;
160        case DW_CFA_offset_extended:
161        case DW_CFA_register:
162        case DW_CFA_def_cfa:
163        case DW_CFA_val_offset:
164          // Operands: ULEB128, ULEB128
165          addInstruction(Opcode, Data.getULEB128(Offset),
166                                 Data.getULEB128(Offset));
167          break;
168        case DW_CFA_offset_extended_sf:
169        case DW_CFA_def_cfa_sf:
170        case DW_CFA_val_offset_sf:
171          // Operands: ULEB128, SLEB128
172          addInstruction(Opcode, Data.getULEB128(Offset),
173                                 Data.getSLEB128(Offset));
174          break;
175        case DW_CFA_def_cfa_expression:
176        case DW_CFA_expression:
177        case DW_CFA_val_expression:
178          // TODO: implement this
179          report_fatal_error("Values with expressions not implemented yet!");
180      }
181    }
182  }
183}
184
185
186void FrameEntry::dumpInstructions(raw_ostream &OS) const {
187  // TODO: at the moment only instruction names are dumped. Expand this to
188  // dump operands as well.
189  for (const auto &Instr : Instructions) {
190    uint8_t Opcode = Instr.Opcode;
191    if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
192      Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
193    OS << "  " << CallFrameString(Opcode) << ":\n";
194  }
195}
196
197
198namespace {
199/// \brief DWARF Common Information Entry (CIE)
200class CIE : public FrameEntry {
201public:
202  // CIEs (and FDEs) are simply container classes, so the only sensible way to
203  // create them is by providing the full parsed contents in the constructor.
204  CIE(DataExtractor D, uint64_t Offset, uint64_t Length, uint8_t Version,
205      SmallString<8> Augmentation, uint64_t CodeAlignmentFactor,
206      int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister)
207   : FrameEntry(FK_CIE, D, Offset, Length), Version(Version),
208     Augmentation(Augmentation), CodeAlignmentFactor(CodeAlignmentFactor),
209     DataAlignmentFactor(DataAlignmentFactor),
210     ReturnAddressRegister(ReturnAddressRegister) {}
211
212  ~CIE() {
213  }
214
215  void dumpHeader(raw_ostream &OS) const override {
216    OS << format("%08x %08x %08x CIE",
217                 (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID)
218       << "\n";
219    OS << format("  Version:               %d\n", Version);
220    OS << "  Augmentation:          \"" << Augmentation << "\"\n";
221    OS << format("  Code alignment factor: %u\n",
222                 (uint32_t)CodeAlignmentFactor);
223    OS << format("  Data alignment factor: %d\n",
224                 (int32_t)DataAlignmentFactor);
225    OS << format("  Return address column: %d\n",
226                 (int32_t)ReturnAddressRegister);
227    OS << "\n";
228  }
229
230  static bool classof(const FrameEntry *FE) {
231    return FE->getKind() == FK_CIE;
232  }
233
234private:
235  /// The following fields are defined in section 6.4.1 of the DWARF standard v3
236  uint8_t Version;
237  SmallString<8> Augmentation;
238  uint64_t CodeAlignmentFactor;
239  int64_t DataAlignmentFactor;
240  uint64_t ReturnAddressRegister;
241};
242
243
244/// \brief DWARF Frame Description Entry (FDE)
245class FDE : public FrameEntry {
246public:
247  // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
248  // an offset to the CIE (provided by parsing the FDE header). The CIE itself
249  // is obtained lazily once it's actually required.
250  FDE(DataExtractor D, uint64_t Offset, uint64_t Length,
251      int64_t LinkedCIEOffset, uint64_t InitialLocation, uint64_t AddressRange)
252   : FrameEntry(FK_FDE, D, Offset, Length), LinkedCIEOffset(LinkedCIEOffset),
253     InitialLocation(InitialLocation), AddressRange(AddressRange),
254     LinkedCIE(NULL) {}
255
256  ~FDE() {
257  }
258
259  void dumpHeader(raw_ostream &OS) const override {
260    OS << format("%08x %08x %08x FDE ",
261                 (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset);
262    OS << format("cie=%08x pc=%08x...%08x\n",
263                 (int32_t)LinkedCIEOffset,
264                 (uint32_t)InitialLocation,
265                 (uint32_t)InitialLocation + (uint32_t)AddressRange);
266    if (LinkedCIE) {
267      OS << format("%p\n", LinkedCIE);
268    }
269  }
270
271  static bool classof(const FrameEntry *FE) {
272    return FE->getKind() == FK_FDE;
273  }
274private:
275
276  /// The following fields are defined in section 6.4.1 of the DWARF standard v3
277  uint64_t LinkedCIEOffset;
278  uint64_t InitialLocation;
279  uint64_t AddressRange;
280  CIE *LinkedCIE;
281};
282} // end anonymous namespace
283
284
285DWARFDebugFrame::DWARFDebugFrame() {
286}
287
288
289DWARFDebugFrame::~DWARFDebugFrame() {
290  for (const auto &Entry : Entries) {
291    delete Entry;
292  }
293}
294
295
296static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
297                                              uint32_t Offset, int Length) {
298  errs() << "DUMP: ";
299  for (int i = 0; i < Length; ++i) {
300    uint8_t c = Data.getU8(&Offset);
301    errs().write_hex(c); errs() << " ";
302  }
303  errs() << "\n";
304}
305
306
307void DWARFDebugFrame::parse(DataExtractor Data) {
308  uint32_t Offset = 0;
309
310  while (Data.isValidOffset(Offset)) {
311    uint32_t StartOffset = Offset;
312
313    bool IsDWARF64 = false;
314    uint64_t Length = Data.getU32(&Offset);
315    uint64_t Id;
316
317    if (Length == UINT32_MAX) {
318      // DWARF-64 is distinguished by the first 32 bits of the initial length
319      // field being 0xffffffff. Then, the next 64 bits are the actual entry
320      // length.
321      IsDWARF64 = true;
322      Length = Data.getU64(&Offset);
323    }
324
325    // At this point, Offset points to the next field after Length.
326    // Length is the structure size excluding itself. Compute an offset one
327    // past the end of the structure (needed to know how many instructions to
328    // read).
329    // TODO: For honest DWARF64 support, DataExtractor will have to treat
330    //       offset_ptr as uint64_t*
331    uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);
332
333    // The Id field's size depends on the DWARF format
334    Id = Data.getUnsigned(&Offset, IsDWARF64 ? 8 : 4);
335    bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID);
336
337    FrameEntry *Entry = 0;
338    if (IsCIE) {
339      // Note: this is specifically DWARFv3 CIE header structure. It was
340      // changed in DWARFv4. We currently don't support reading DWARFv4
341      // here because LLVM itself does not emit it (and LLDB doesn't
342      // support it either).
343      uint8_t Version = Data.getU8(&Offset);
344      const char *Augmentation = Data.getCStr(&Offset);
345      uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
346      int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
347      uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);
348
349      Entry = new CIE(Data, StartOffset, Length, Version,
350                      StringRef(Augmentation), CodeAlignmentFactor,
351                      DataAlignmentFactor, ReturnAddressRegister);
352    } else {
353      // FDE
354      uint64_t CIEPointer = Id;
355      uint64_t InitialLocation = Data.getAddress(&Offset);
356      uint64_t AddressRange = Data.getAddress(&Offset);
357
358      Entry = new FDE(Data, StartOffset, Length, CIEPointer,
359                      InitialLocation, AddressRange);
360    }
361
362    assert(Entry && "Expected Entry to be populated with CIE or FDE");
363    Entry->parseInstructions(&Offset, EndStructureOffset);
364
365    if (Offset == EndStructureOffset) {
366      // Entry instrucitons parsed successfully.
367      Entries.push_back(Entry);
368    } else {
369      std::string Str;
370      raw_string_ostream OS(Str);
371      OS << format("Parsing entry instructions at %lx failed",
372                   Entry->getOffset());
373      report_fatal_error(Str);
374    }
375  }
376}
377
378
379void DWARFDebugFrame::dump(raw_ostream &OS) const {
380  OS << "\n";
381  for (const auto &Entry : Entries) {
382    Entry->dumpHeader(OS);
383    Entry->dumpInstructions(OS);
384    OS << "\n";
385  }
386}
387
388