1 //===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/DebugInfo/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"
21 using namespace dwarf
;
24 /// \brief Abstract frame entry defining the common interface concrete
25 /// entries implement.
26 class llvm::FrameEntry
{
28 enum FrameKind
{FK_CIE
, FK_FDE
};
29 FrameEntry(FrameKind K
, uint64_t Offset
, uint64_t Length
)
30 : Kind(K
), Offset(Offset
), Length(Length
) {}
32 virtual ~FrameEntry() {
35 FrameKind
getKind() const { return Kind
; }
36 virtual uint64_t getOffset() const { return Offset
; }
38 /// \brief Parse and store a sequence of CFI instructions from Data,
39 /// 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(DataExtractor Data
, uint32_t *Offset
,
45 /// \brief Dump the entry header to the given output stream.
46 virtual void dumpHeader(raw_ostream
&OS
) const = 0;
48 /// \brief Dump the entry's instructions to the given output stream.
49 virtual void dumpInstructions(raw_ostream
&OS
) const;
54 /// \brief Offset of this entry in the section.
57 /// \brief Entry length as specified in DWARF.
60 /// An entry may contain CFI instructions. An instruction consists of an
61 /// opcode and an optional sequence of operands.
62 typedef std::vector
<uint64_t> Operands
;
64 Instruction(uint8_t Opcode
)
72 std::vector
<Instruction
> Instructions
;
74 /// Convenience methods to add a new instruction with the given opcode and
75 /// operands to the Instructions vector.
76 void addInstruction(uint8_t Opcode
) {
77 Instructions
.push_back(Instruction(Opcode
));
80 void addInstruction(uint8_t Opcode
, uint64_t Operand1
) {
81 Instructions
.push_back(Instruction(Opcode
));
82 Instructions
.back().Ops
.push_back(Operand1
);
85 void addInstruction(uint8_t Opcode
, uint64_t Operand1
, uint64_t Operand2
) {
86 Instructions
.push_back(Instruction(Opcode
));
87 Instructions
.back().Ops
.push_back(Operand1
);
88 Instructions
.back().Ops
.push_back(Operand2
);
93 // See DWARF standard v3, section 7.23
94 const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK
= 0xc0;
95 const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK
= 0x3f;
97 void FrameEntry::parseInstructions(DataExtractor Data
, uint32_t *Offset
,
99 while (*Offset
< EndOffset
) {
100 uint8_t Opcode
= Data
.getU8(Offset
);
101 // Some instructions have a primary opcode encoded in the top bits.
102 uint8_t Primary
= Opcode
& DWARF_CFI_PRIMARY_OPCODE_MASK
;
105 // If it's a primary opcode, the first operand is encoded in the bottom
106 // bits of the opcode itself.
107 uint64_t Op1
= Opcode
& DWARF_CFI_PRIMARY_OPERAND_MASK
;
109 default: llvm_unreachable("Impossible primary CFI opcode");
110 case DW_CFA_advance_loc
:
112 addInstruction(Primary
, Op1
);
115 addInstruction(Primary
, Op1
, Data
.getULEB128(Offset
));
119 // Extended opcode - its value is Opcode itself.
121 default: llvm_unreachable("Invalid extended CFI opcode");
123 case DW_CFA_remember_state
:
124 case DW_CFA_restore_state
:
125 case DW_CFA_GNU_window_save
:
127 addInstruction(Opcode
);
131 addInstruction(Opcode
, Data
.getAddress(Offset
));
133 case DW_CFA_advance_loc1
:
134 // Operands: 1-byte delta
135 addInstruction(Opcode
, Data
.getU8(Offset
));
137 case DW_CFA_advance_loc2
:
138 // Operands: 2-byte delta
139 addInstruction(Opcode
, Data
.getU16(Offset
));
141 case DW_CFA_advance_loc4
:
142 // Operands: 4-byte delta
143 addInstruction(Opcode
, Data
.getU32(Offset
));
145 case DW_CFA_restore_extended
:
146 case DW_CFA_undefined
:
147 case DW_CFA_same_value
:
148 case DW_CFA_def_cfa_register
:
149 case DW_CFA_def_cfa_offset
:
151 addInstruction(Opcode
, Data
.getULEB128(Offset
));
153 case DW_CFA_def_cfa_offset_sf
:
155 addInstruction(Opcode
, Data
.getSLEB128(Offset
));
157 case DW_CFA_offset_extended
:
158 case DW_CFA_register
:
160 case DW_CFA_val_offset
:
161 // Operands: ULEB128, ULEB128
162 addInstruction(Opcode
, Data
.getULEB128(Offset
),
163 Data
.getULEB128(Offset
));
165 case DW_CFA_offset_extended_sf
:
166 case DW_CFA_def_cfa_sf
:
167 case DW_CFA_val_offset_sf
:
168 // Operands: ULEB128, SLEB128
169 addInstruction(Opcode
, Data
.getULEB128(Offset
),
170 Data
.getSLEB128(Offset
));
172 case DW_CFA_def_cfa_expression
:
173 case DW_CFA_expression
:
174 case DW_CFA_val_expression
:
175 // TODO: implement this
176 report_fatal_error("Values with expressions not implemented yet!");
183 void FrameEntry::dumpInstructions(raw_ostream
&OS
) const {
184 // TODO: at the moment only instruction names are dumped. Expand this to
185 // dump operands as well.
186 for (const auto &Instr
: Instructions
) {
187 uint8_t Opcode
= Instr
.Opcode
;
188 if (Opcode
& DWARF_CFI_PRIMARY_OPCODE_MASK
)
189 Opcode
&= DWARF_CFI_PRIMARY_OPCODE_MASK
;
190 OS
<< " " << CallFrameString(Opcode
) << ":\n";
196 /// \brief DWARF Common Information Entry (CIE)
197 class CIE
: public FrameEntry
{
199 // CIEs (and FDEs) are simply container classes, so the only sensible way to
200 // create them is by providing the full parsed contents in the constructor.
201 CIE(uint64_t Offset
, uint64_t Length
, uint8_t Version
,
202 SmallString
<8> Augmentation
, uint64_t CodeAlignmentFactor
,
203 int64_t DataAlignmentFactor
, uint64_t ReturnAddressRegister
)
204 : FrameEntry(FK_CIE
, Offset
, Length
), Version(Version
),
205 Augmentation(std::move(Augmentation
)),
206 CodeAlignmentFactor(CodeAlignmentFactor
),
207 DataAlignmentFactor(DataAlignmentFactor
),
208 ReturnAddressRegister(ReturnAddressRegister
) {}
213 void dumpHeader(raw_ostream
&OS
) const override
{
214 OS
<< format("%08x %08x %08x CIE",
215 (uint32_t)Offset
, (uint32_t)Length
, DW_CIE_ID
)
217 OS
<< format(" Version: %d\n", Version
);
218 OS
<< " Augmentation: \"" << Augmentation
<< "\"\n";
219 OS
<< format(" Code alignment factor: %u\n",
220 (uint32_t)CodeAlignmentFactor
);
221 OS
<< format(" Data alignment factor: %d\n",
222 (int32_t)DataAlignmentFactor
);
223 OS
<< format(" Return address column: %d\n",
224 (int32_t)ReturnAddressRegister
);
228 static bool classof(const FrameEntry
*FE
) {
229 return FE
->getKind() == FK_CIE
;
233 /// The following fields are defined in section 6.4.1 of the DWARF standard v3
235 SmallString
<8> Augmentation
;
236 uint64_t CodeAlignmentFactor
;
237 int64_t DataAlignmentFactor
;
238 uint64_t ReturnAddressRegister
;
242 /// \brief DWARF Frame Description Entry (FDE)
243 class FDE
: public FrameEntry
{
245 // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
246 // an offset to the CIE (provided by parsing the FDE header). The CIE itself
247 // is obtained lazily once it's actually required.
248 FDE(uint64_t Offset
, uint64_t Length
, int64_t LinkedCIEOffset
,
249 uint64_t InitialLocation
, uint64_t AddressRange
)
250 : FrameEntry(FK_FDE
, Offset
, Length
), LinkedCIEOffset(LinkedCIEOffset
),
251 InitialLocation(InitialLocation
), AddressRange(AddressRange
),
252 LinkedCIE(nullptr) {}
257 void dumpHeader(raw_ostream
&OS
) const override
{
258 OS
<< format("%08x %08x %08x FDE ",
259 (uint32_t)Offset
, (uint32_t)Length
, (int32_t)LinkedCIEOffset
);
260 OS
<< format("cie=%08x pc=%08x...%08x\n",
261 (int32_t)LinkedCIEOffset
,
262 (uint32_t)InitialLocation
,
263 (uint32_t)InitialLocation
+ (uint32_t)AddressRange
);
265 OS
<< format("%p\n", LinkedCIE
);
269 static bool classof(const FrameEntry
*FE
) {
270 return FE
->getKind() == FK_FDE
;
274 /// The following fields are defined in section 6.4.1 of the DWARF standard v3
275 uint64_t LinkedCIEOffset
;
276 uint64_t InitialLocation
;
277 uint64_t AddressRange
;
280 } // end anonymous namespace
283 DWARFDebugFrame::DWARFDebugFrame() {
286 DWARFDebugFrame::~DWARFDebugFrame() {
289 static void LLVM_ATTRIBUTE_UNUSED
dumpDataAux(DataExtractor Data
,
290 uint32_t Offset
, int Length
) {
292 for (int i
= 0; i
< Length
; ++i
) {
293 uint8_t c
= Data
.getU8(&Offset
);
294 errs().write_hex(c
); errs() << " ";
300 void DWARFDebugFrame::parse(DataExtractor Data
) {
303 while (Data
.isValidOffset(Offset
)) {
304 uint32_t StartOffset
= Offset
;
306 bool IsDWARF64
= false;
307 uint64_t Length
= Data
.getU32(&Offset
);
310 if (Length
== UINT32_MAX
) {
311 // DWARF-64 is distinguished by the first 32 bits of the initial length
312 // field being 0xffffffff. Then, the next 64 bits are the actual entry
315 Length
= Data
.getU64(&Offset
);
318 // At this point, Offset points to the next field after Length.
319 // Length is the structure size excluding itself. Compute an offset one
320 // past the end of the structure (needed to know how many instructions to
322 // TODO: For honest DWARF64 support, DataExtractor will have to treat
323 // offset_ptr as uint64_t*
324 uint32_t EndStructureOffset
= Offset
+ static_cast<uint32_t>(Length
);
326 // The Id field's size depends on the DWARF format
327 Id
= Data
.getUnsigned(&Offset
, IsDWARF64
? 8 : 4);
328 bool IsCIE
= ((IsDWARF64
&& Id
== DW64_CIE_ID
) || Id
== DW_CIE_ID
);
331 // Note: this is specifically DWARFv3 CIE header structure. It was
332 // changed in DWARFv4. We currently don't support reading DWARFv4
333 // here because LLVM itself does not emit it (and LLDB doesn't
334 // support it either).
335 uint8_t Version
= Data
.getU8(&Offset
);
336 const char *Augmentation
= Data
.getCStr(&Offset
);
337 uint64_t CodeAlignmentFactor
= Data
.getULEB128(&Offset
);
338 int64_t DataAlignmentFactor
= Data
.getSLEB128(&Offset
);
339 uint64_t ReturnAddressRegister
= Data
.getULEB128(&Offset
);
341 Entries
.emplace_back(new CIE(StartOffset
, Length
, Version
,
342 StringRef(Augmentation
), CodeAlignmentFactor
,
343 DataAlignmentFactor
, ReturnAddressRegister
));
346 uint64_t CIEPointer
= Id
;
347 uint64_t InitialLocation
= Data
.getAddress(&Offset
);
348 uint64_t AddressRange
= Data
.getAddress(&Offset
);
350 Entries
.emplace_back(new FDE(StartOffset
, Length
, CIEPointer
,
351 InitialLocation
, AddressRange
));
354 Entries
.back()->parseInstructions(Data
, &Offset
, EndStructureOffset
);
356 if (Offset
!= EndStructureOffset
) {
358 raw_string_ostream
OS(Str
);
359 OS
<< format("Parsing entry instructions at %lx failed", StartOffset
);
360 report_fatal_error(Str
);
366 void DWARFDebugFrame::dump(raw_ostream
&OS
) const {
368 for (const auto &Entry
: Entries
) {
369 Entry
->dumpHeader(OS
);
370 Entry
->dumpInstructions(OS
);