1249259Sdim//===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim
10249259Sdim#include "DWARFDebugFrame.h"
11249259Sdim#include "llvm/ADT/SmallString.h"
12249259Sdim#include "llvm/Support/DataTypes.h"
13249259Sdim#include "llvm/Support/ErrorHandling.h"
14249259Sdim#include "llvm/Support/Dwarf.h"
15249259Sdim#include "llvm/Support/Format.h"
16249259Sdim#include "llvm/Support/raw_ostream.h"
17249259Sdim#include <string>
18249259Sdim#include <vector>
19249259Sdim
20249259Sdimusing namespace llvm;
21249259Sdimusing namespace dwarf;
22249259Sdim
23249259Sdim
24249259Sdim/// \brief Abstract frame entry defining the common interface concrete
25249259Sdim/// entries implement.
26249259Sdimclass llvm::FrameEntry {
27249259Sdimpublic:
28249259Sdim  enum FrameKind {FK_CIE, FK_FDE};
29249259Sdim  FrameEntry(FrameKind K, DataExtractor D, uint64_t Offset, uint64_t Length)
30249259Sdim    : Kind(K), Data(D), Offset(Offset), Length(Length) {}
31249259Sdim
32249259Sdim  virtual ~FrameEntry() {
33249259Sdim  }
34249259Sdim
35249259Sdim  FrameKind getKind() const { return Kind; }
36249259Sdim  virtual uint64_t getOffset() const { return Offset; }
37249259Sdim
38249259Sdim  /// \brief Parse and store a sequence of CFI instructions from our data
39249259Sdim  /// stream, starting at *Offset and ending at EndOffset. If everything
40249259Sdim  /// goes well, *Offset should be equal to EndOffset when this method
41249259Sdim  /// returns. Otherwise, an error occurred.
42249259Sdim  virtual void parseInstructions(uint32_t *Offset, uint32_t EndOffset);
43249259Sdim
44249259Sdim  /// \brief Dump the entry header to the given output stream.
45249259Sdim  virtual void dumpHeader(raw_ostream &OS) const = 0;
46249259Sdim
47249259Sdim  /// \brief Dump the entry's instructions to the given output stream.
48249259Sdim  virtual void dumpInstructions(raw_ostream &OS) const;
49249259Sdim
50249259Sdimprotected:
51249259Sdim  const FrameKind Kind;
52249259Sdim
53249259Sdim  /// \brief The data stream holding the section from which the entry was
54249259Sdim  /// parsed.
55249259Sdim  DataExtractor Data;
56249259Sdim
57249259Sdim  /// \brief Offset of this entry in the section.
58249259Sdim  uint64_t Offset;
59249259Sdim
60249259Sdim  /// \brief Entry length as specified in DWARF.
61249259Sdim  uint64_t Length;
62249259Sdim
63249259Sdim  /// An entry may contain CFI instructions. An instruction consists of an
64249259Sdim  /// opcode and an optional sequence of operands.
65249259Sdim  typedef std::vector<uint64_t> Operands;
66249259Sdim  struct Instruction {
67249259Sdim    Instruction(uint8_t Opcode)
68249259Sdim      : Opcode(Opcode)
69249259Sdim    {}
70249259Sdim
71249259Sdim    uint8_t Opcode;
72249259Sdim    Operands Ops;
73249259Sdim  };
74249259Sdim
75249259Sdim  std::vector<Instruction> Instructions;
76249259Sdim
77249259Sdim  /// Convenience methods to add a new instruction with the given opcode and
78249259Sdim  /// operands to the Instructions vector.
79249259Sdim  void addInstruction(uint8_t Opcode) {
80249259Sdim    Instructions.push_back(Instruction(Opcode));
81249259Sdim  }
82249259Sdim
83249259Sdim  void addInstruction(uint8_t Opcode, uint64_t Operand1) {
84249259Sdim    Instructions.push_back(Instruction(Opcode));
85249259Sdim    Instructions.back().Ops.push_back(Operand1);
86249259Sdim  }
87249259Sdim
88249259Sdim  void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
89249259Sdim    Instructions.push_back(Instruction(Opcode));
90249259Sdim    Instructions.back().Ops.push_back(Operand1);
91249259Sdim    Instructions.back().Ops.push_back(Operand2);
92249259Sdim  }
93249259Sdim};
94249259Sdim
95249259Sdim
96249259Sdim// See DWARF standard v3, section 7.23
97249259Sdimconst uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
98249259Sdimconst uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
99249259Sdim
100249259Sdim
101249259Sdimvoid FrameEntry::parseInstructions(uint32_t *Offset, uint32_t EndOffset) {
102249259Sdim  while (*Offset < EndOffset) {
103249259Sdim    uint8_t Opcode = Data.getU8(Offset);
104249259Sdim    // Some instructions have a primary opcode encoded in the top bits.
105249259Sdim    uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK;
106249259Sdim
107249259Sdim    if (Primary) {
108249259Sdim      // If it's a primary opcode, the first operand is encoded in the bottom
109249259Sdim      // bits of the opcode itself.
110249259Sdim      uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
111249259Sdim      switch (Primary) {
112249259Sdim        default: llvm_unreachable("Impossible primary CFI opcode");
113249259Sdim        case DW_CFA_advance_loc:
114249259Sdim        case DW_CFA_restore:
115249259Sdim          addInstruction(Primary, Op1);
116249259Sdim          break;
117249259Sdim        case DW_CFA_offset:
118249259Sdim          addInstruction(Primary, Op1, Data.getULEB128(Offset));
119249259Sdim          break;
120249259Sdim      }
121249259Sdim    } else {
122249259Sdim      // Extended opcode - its value is Opcode itself.
123249259Sdim      switch (Opcode) {
124249259Sdim        default: llvm_unreachable("Invalid extended CFI opcode");
125249259Sdim        case DW_CFA_nop:
126249259Sdim        case DW_CFA_remember_state:
127249259Sdim        case DW_CFA_restore_state:
128249259Sdim          // No operands
129249259Sdim          addInstruction(Opcode);
130249259Sdim          break;
131249259Sdim        case DW_CFA_set_loc:
132249259Sdim          // Operands: Address
133249259Sdim          addInstruction(Opcode, Data.getAddress(Offset));
134249259Sdim          break;
135249259Sdim        case DW_CFA_advance_loc1:
136249259Sdim          // Operands: 1-byte delta
137249259Sdim          addInstruction(Opcode, Data.getU8(Offset));
138249259Sdim          break;
139249259Sdim        case DW_CFA_advance_loc2:
140249259Sdim          // Operands: 2-byte delta
141249259Sdim          addInstruction(Opcode, Data.getU16(Offset));
142249259Sdim          break;
143249259Sdim        case DW_CFA_advance_loc4:
144249259Sdim          // Operands: 4-byte delta
145249259Sdim          addInstruction(Opcode, Data.getU32(Offset));
146249259Sdim          break;
147249259Sdim        case DW_CFA_restore_extended:
148249259Sdim        case DW_CFA_undefined:
149249259Sdim        case DW_CFA_same_value:
150249259Sdim        case DW_CFA_def_cfa_register:
151249259Sdim        case DW_CFA_def_cfa_offset:
152249259Sdim          // Operands: ULEB128
153249259Sdim          addInstruction(Opcode, Data.getULEB128(Offset));
154249259Sdim          break;
155249259Sdim        case DW_CFA_def_cfa_offset_sf:
156249259Sdim          // Operands: SLEB128
157249259Sdim          addInstruction(Opcode, Data.getSLEB128(Offset));
158249259Sdim          break;
159249259Sdim        case DW_CFA_offset_extended:
160249259Sdim        case DW_CFA_register:
161249259Sdim        case DW_CFA_def_cfa:
162249259Sdim        case DW_CFA_val_offset:
163249259Sdim          // Operands: ULEB128, ULEB128
164249259Sdim          addInstruction(Opcode, Data.getULEB128(Offset),
165249259Sdim                                 Data.getULEB128(Offset));
166249259Sdim          break;
167249259Sdim        case DW_CFA_offset_extended_sf:
168249259Sdim        case DW_CFA_def_cfa_sf:
169249259Sdim        case DW_CFA_val_offset_sf:
170249259Sdim          // Operands: ULEB128, SLEB128
171249259Sdim          addInstruction(Opcode, Data.getULEB128(Offset),
172249259Sdim                                 Data.getSLEB128(Offset));
173249259Sdim          break;
174249259Sdim        case DW_CFA_def_cfa_expression:
175249259Sdim        case DW_CFA_expression:
176249259Sdim        case DW_CFA_val_expression:
177249259Sdim          // TODO: implement this
178249259Sdim          report_fatal_error("Values with expressions not implemented yet!");
179249259Sdim      }
180249259Sdim    }
181249259Sdim  }
182249259Sdim}
183249259Sdim
184249259Sdim
185249259Sdimvoid FrameEntry::dumpInstructions(raw_ostream &OS) const {
186249259Sdim  // TODO: at the moment only instruction names are dumped. Expand this to
187249259Sdim  // dump operands as well.
188249259Sdim  for (std::vector<Instruction>::const_iterator I = Instructions.begin(),
189249259Sdim                                                E = Instructions.end();
190249259Sdim       I != E; ++I) {
191249259Sdim    uint8_t Opcode = I->Opcode;
192249259Sdim    if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
193249259Sdim      Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
194249259Sdim    OS << "  " << CallFrameString(Opcode) << ":\n";
195249259Sdim  }
196249259Sdim}
197249259Sdim
198249259Sdim
199249259Sdimnamespace {
200249259Sdim/// \brief DWARF Common Information Entry (CIE)
201249259Sdimclass CIE : public FrameEntry {
202249259Sdimpublic:
203249259Sdim  // CIEs (and FDEs) are simply container classes, so the only sensible way to
204249259Sdim  // create them is by providing the full parsed contents in the constructor.
205249259Sdim  CIE(DataExtractor D, uint64_t Offset, uint64_t Length, uint8_t Version,
206249259Sdim      SmallString<8> Augmentation, uint64_t CodeAlignmentFactor,
207249259Sdim      int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister)
208249259Sdim   : FrameEntry(FK_CIE, D, Offset, Length), Version(Version),
209249259Sdim     Augmentation(Augmentation), CodeAlignmentFactor(CodeAlignmentFactor),
210249259Sdim     DataAlignmentFactor(DataAlignmentFactor),
211249259Sdim     ReturnAddressRegister(ReturnAddressRegister) {}
212249259Sdim
213249259Sdim  ~CIE() {
214249259Sdim  }
215249259Sdim
216249259Sdim  void dumpHeader(raw_ostream &OS) const {
217249259Sdim    OS << format("%08x %08x %08x CIE",
218249259Sdim                 (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID)
219249259Sdim       << "\n";
220249259Sdim    OS << format("  Version:               %d\n", Version);
221249259Sdim    OS << "  Augmentation:          \"" << Augmentation << "\"\n";
222249259Sdim    OS << format("  Code alignment factor: %u\n",
223249259Sdim                 (uint32_t)CodeAlignmentFactor);
224249259Sdim    OS << format("  Data alignment factor: %d\n",
225249259Sdim                 (int32_t)DataAlignmentFactor);
226249259Sdim    OS << format("  Return address column: %d\n",
227249259Sdim                 (int32_t)ReturnAddressRegister);
228249259Sdim    OS << "\n";
229249259Sdim  }
230249259Sdim
231249259Sdim  static bool classof(const FrameEntry *FE) {
232249259Sdim    return FE->getKind() == FK_CIE;
233249259Sdim  }
234249259Sdim
235249259Sdimprivate:
236249259Sdim  /// The following fields are defined in section 6.4.1 of the DWARF standard v3
237249259Sdim  uint8_t Version;
238249259Sdim  SmallString<8> Augmentation;
239249259Sdim  uint64_t CodeAlignmentFactor;
240249259Sdim  int64_t DataAlignmentFactor;
241249259Sdim  uint64_t ReturnAddressRegister;
242249259Sdim};
243249259Sdim
244249259Sdim
245249259Sdim/// \brief DWARF Frame Description Entry (FDE)
246249259Sdimclass FDE : public FrameEntry {
247249259Sdimpublic:
248249259Sdim  // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
249249259Sdim  // an offset to the CIE (provided by parsing the FDE header). The CIE itself
250249259Sdim  // is obtained lazily once it's actually required.
251249259Sdim  FDE(DataExtractor D, uint64_t Offset, uint64_t Length,
252249259Sdim      int64_t LinkedCIEOffset, uint64_t InitialLocation, uint64_t AddressRange)
253249259Sdim   : FrameEntry(FK_FDE, D, Offset, Length), LinkedCIEOffset(LinkedCIEOffset),
254249259Sdim     InitialLocation(InitialLocation), AddressRange(AddressRange),
255249259Sdim     LinkedCIE(NULL) {}
256249259Sdim
257249259Sdim  ~FDE() {
258249259Sdim  }
259249259Sdim
260249259Sdim  void dumpHeader(raw_ostream &OS) const {
261249259Sdim    OS << format("%08x %08x %08x FDE ",
262249259Sdim                 (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset);
263249259Sdim    OS << format("cie=%08x pc=%08x...%08x\n",
264249259Sdim                 (int32_t)LinkedCIEOffset,
265249259Sdim                 (uint32_t)InitialLocation,
266249259Sdim                 (uint32_t)InitialLocation + (uint32_t)AddressRange);
267249259Sdim    if (LinkedCIE) {
268249259Sdim      OS << format("%p\n", LinkedCIE);
269249259Sdim    }
270249259Sdim  }
271249259Sdim
272249259Sdim  static bool classof(const FrameEntry *FE) {
273249259Sdim    return FE->getKind() == FK_FDE;
274249259Sdim  }
275249259Sdimprivate:
276249259Sdim
277249259Sdim  /// The following fields are defined in section 6.4.1 of the DWARF standard v3
278249259Sdim  uint64_t LinkedCIEOffset;
279249259Sdim  uint64_t InitialLocation;
280249259Sdim  uint64_t AddressRange;
281249259Sdim  CIE *LinkedCIE;
282249259Sdim};
283249259Sdim} // end anonymous namespace
284249259Sdim
285249259Sdim
286249259SdimDWARFDebugFrame::DWARFDebugFrame() {
287249259Sdim}
288249259Sdim
289249259Sdim
290249259SdimDWARFDebugFrame::~DWARFDebugFrame() {
291249259Sdim  for (EntryVector::iterator I = Entries.begin(), E = Entries.end();
292249259Sdim       I != E; ++I) {
293249259Sdim    delete *I;
294249259Sdim  }
295249259Sdim}
296249259Sdim
297249259Sdim
298249259Sdimstatic void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
299249259Sdim                                              uint32_t Offset, int Length) {
300249259Sdim  errs() << "DUMP: ";
301249259Sdim  for (int i = 0; i < Length; ++i) {
302249259Sdim    uint8_t c = Data.getU8(&Offset);
303249259Sdim    errs().write_hex(c); errs() << " ";
304249259Sdim  }
305249259Sdim  errs() << "\n";
306249259Sdim}
307249259Sdim
308249259Sdim
309249259Sdimvoid DWARFDebugFrame::parse(DataExtractor Data) {
310249259Sdim  uint32_t Offset = 0;
311249259Sdim
312249259Sdim  while (Data.isValidOffset(Offset)) {
313249259Sdim    uint32_t StartOffset = Offset;
314249259Sdim
315249259Sdim    bool IsDWARF64 = false;
316249259Sdim    uint64_t Length = Data.getU32(&Offset);
317249259Sdim    uint64_t Id;
318249259Sdim
319249259Sdim    if (Length == UINT32_MAX) {
320249259Sdim      // DWARF-64 is distinguished by the first 32 bits of the initial length
321249259Sdim      // field being 0xffffffff. Then, the next 64 bits are the actual entry
322249259Sdim      // length.
323249259Sdim      IsDWARF64 = true;
324249259Sdim      Length = Data.getU64(&Offset);
325249259Sdim    }
326249259Sdim
327249259Sdim    // At this point, Offset points to the next field after Length.
328249259Sdim    // Length is the structure size excluding itself. Compute an offset one
329249259Sdim    // past the end of the structure (needed to know how many instructions to
330249259Sdim    // read).
331249259Sdim    // TODO: For honest DWARF64 support, DataExtractor will have to treat
332249259Sdim    //       offset_ptr as uint64_t*
333249259Sdim    uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);
334249259Sdim
335249259Sdim    // The Id field's size depends on the DWARF format
336249259Sdim    Id = Data.getUnsigned(&Offset, IsDWARF64 ? 8 : 4);
337249259Sdim    bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID);
338249259Sdim
339249259Sdim    FrameEntry *Entry = 0;
340249259Sdim    if (IsCIE) {
341249259Sdim      // Note: this is specifically DWARFv3 CIE header structure. It was
342249259Sdim      // changed in DWARFv4. We currently don't support reading DWARFv4
343249259Sdim      // here because LLVM itself does not emit it (and LLDB doesn't
344249259Sdim      // support it either).
345249259Sdim      uint8_t Version = Data.getU8(&Offset);
346249259Sdim      const char *Augmentation = Data.getCStr(&Offset);
347249259Sdim      uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
348249259Sdim      int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
349249259Sdim      uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);
350249259Sdim
351249259Sdim      Entry = new CIE(Data, StartOffset, Length, Version,
352249259Sdim                      StringRef(Augmentation), CodeAlignmentFactor,
353249259Sdim                      DataAlignmentFactor, ReturnAddressRegister);
354249259Sdim    } else {
355249259Sdim      // FDE
356249259Sdim      uint64_t CIEPointer = Id;
357249259Sdim      uint64_t InitialLocation = Data.getAddress(&Offset);
358249259Sdim      uint64_t AddressRange = Data.getAddress(&Offset);
359249259Sdim
360249259Sdim      Entry = new FDE(Data, StartOffset, Length, CIEPointer,
361249259Sdim                      InitialLocation, AddressRange);
362249259Sdim    }
363249259Sdim
364249259Sdim    assert(Entry && "Expected Entry to be populated with CIE or FDE");
365249259Sdim    Entry->parseInstructions(&Offset, EndStructureOffset);
366249259Sdim
367249259Sdim    if (Offset == EndStructureOffset) {
368249259Sdim      // Entry instrucitons parsed successfully.
369249259Sdim      Entries.push_back(Entry);
370249259Sdim    } else {
371249259Sdim      std::string Str;
372249259Sdim      raw_string_ostream OS(Str);
373249259Sdim      OS << format("Parsing entry instructions at %lx failed",
374249259Sdim                   Entry->getOffset());
375249259Sdim      report_fatal_error(Str);
376249259Sdim    }
377249259Sdim  }
378249259Sdim}
379249259Sdim
380249259Sdim
381249259Sdimvoid DWARFDebugFrame::dump(raw_ostream &OS) const {
382249259Sdim  OS << "\n";
383249259Sdim  for (EntryVector::const_iterator I = Entries.begin(), E = Entries.end();
384249259Sdim       I != E; ++I) {
385249259Sdim    FrameEntry *Entry = *I;
386249259Sdim    Entry->dumpHeader(OS);
387249259Sdim    Entry->dumpInstructions(OS);
388249259Sdim    OS << "\n";
389249259Sdim  }
390249259Sdim}
391249259Sdim
392