1*9880d681SAndroid Build Coastguard Worker //===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
11*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/ArrayRef.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/DenseMap.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Optional.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallString.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringExtras.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Casting.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/DataTypes.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Dwarf.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Format.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
22*9880d681SAndroid Build Coastguard Worker #include <string>
23*9880d681SAndroid Build Coastguard Worker #include <utility>
24*9880d681SAndroid Build Coastguard Worker #include <vector>
25*9880d681SAndroid Build Coastguard Worker
26*9880d681SAndroid Build Coastguard Worker using namespace llvm;
27*9880d681SAndroid Build Coastguard Worker using namespace dwarf;
28*9880d681SAndroid Build Coastguard Worker
29*9880d681SAndroid Build Coastguard Worker
30*9880d681SAndroid Build Coastguard Worker /// \brief Abstract frame entry defining the common interface concrete
31*9880d681SAndroid Build Coastguard Worker /// entries implement.
32*9880d681SAndroid Build Coastguard Worker class llvm::FrameEntry {
33*9880d681SAndroid Build Coastguard Worker public:
34*9880d681SAndroid Build Coastguard Worker enum FrameKind {FK_CIE, FK_FDE};
FrameEntry(FrameKind K,uint64_t Offset,uint64_t Length)35*9880d681SAndroid Build Coastguard Worker FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length)
36*9880d681SAndroid Build Coastguard Worker : Kind(K), Offset(Offset), Length(Length) {}
37*9880d681SAndroid Build Coastguard Worker
~FrameEntry()38*9880d681SAndroid Build Coastguard Worker virtual ~FrameEntry() {
39*9880d681SAndroid Build Coastguard Worker }
40*9880d681SAndroid Build Coastguard Worker
getKind() const41*9880d681SAndroid Build Coastguard Worker FrameKind getKind() const { return Kind; }
getOffset() const42*9880d681SAndroid Build Coastguard Worker virtual uint64_t getOffset() const { return Offset; }
43*9880d681SAndroid Build Coastguard Worker
44*9880d681SAndroid Build Coastguard Worker /// \brief Parse and store a sequence of CFI instructions from Data,
45*9880d681SAndroid Build Coastguard Worker /// starting at *Offset and ending at EndOffset. If everything
46*9880d681SAndroid Build Coastguard Worker /// goes well, *Offset should be equal to EndOffset when this method
47*9880d681SAndroid Build Coastguard Worker /// returns. Otherwise, an error occurred.
48*9880d681SAndroid Build Coastguard Worker virtual void parseInstructions(DataExtractor Data, uint32_t *Offset,
49*9880d681SAndroid Build Coastguard Worker uint32_t EndOffset);
50*9880d681SAndroid Build Coastguard Worker
51*9880d681SAndroid Build Coastguard Worker /// \brief Dump the entry header to the given output stream.
52*9880d681SAndroid Build Coastguard Worker virtual void dumpHeader(raw_ostream &OS) const = 0;
53*9880d681SAndroid Build Coastguard Worker
54*9880d681SAndroid Build Coastguard Worker /// \brief Dump the entry's instructions to the given output stream.
55*9880d681SAndroid Build Coastguard Worker virtual void dumpInstructions(raw_ostream &OS) const;
56*9880d681SAndroid Build Coastguard Worker
57*9880d681SAndroid Build Coastguard Worker protected:
58*9880d681SAndroid Build Coastguard Worker const FrameKind Kind;
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard Worker /// \brief Offset of this entry in the section.
61*9880d681SAndroid Build Coastguard Worker uint64_t Offset;
62*9880d681SAndroid Build Coastguard Worker
63*9880d681SAndroid Build Coastguard Worker /// \brief Entry length as specified in DWARF.
64*9880d681SAndroid Build Coastguard Worker uint64_t Length;
65*9880d681SAndroid Build Coastguard Worker
66*9880d681SAndroid Build Coastguard Worker /// An entry may contain CFI instructions. An instruction consists of an
67*9880d681SAndroid Build Coastguard Worker /// opcode and an optional sequence of operands.
68*9880d681SAndroid Build Coastguard Worker typedef std::vector<uint64_t> Operands;
69*9880d681SAndroid Build Coastguard Worker struct Instruction {
Instructionllvm::FrameEntry::Instruction70*9880d681SAndroid Build Coastguard Worker Instruction(uint8_t Opcode)
71*9880d681SAndroid Build Coastguard Worker : Opcode(Opcode)
72*9880d681SAndroid Build Coastguard Worker {}
73*9880d681SAndroid Build Coastguard Worker
74*9880d681SAndroid Build Coastguard Worker uint8_t Opcode;
75*9880d681SAndroid Build Coastguard Worker Operands Ops;
76*9880d681SAndroid Build Coastguard Worker };
77*9880d681SAndroid Build Coastguard Worker
78*9880d681SAndroid Build Coastguard Worker std::vector<Instruction> Instructions;
79*9880d681SAndroid Build Coastguard Worker
80*9880d681SAndroid Build Coastguard Worker /// Convenience methods to add a new instruction with the given opcode and
81*9880d681SAndroid Build Coastguard Worker /// operands to the Instructions vector.
addInstruction(uint8_t Opcode)82*9880d681SAndroid Build Coastguard Worker void addInstruction(uint8_t Opcode) {
83*9880d681SAndroid Build Coastguard Worker Instructions.push_back(Instruction(Opcode));
84*9880d681SAndroid Build Coastguard Worker }
85*9880d681SAndroid Build Coastguard Worker
addInstruction(uint8_t Opcode,uint64_t Operand1)86*9880d681SAndroid Build Coastguard Worker void addInstruction(uint8_t Opcode, uint64_t Operand1) {
87*9880d681SAndroid Build Coastguard Worker Instructions.push_back(Instruction(Opcode));
88*9880d681SAndroid Build Coastguard Worker Instructions.back().Ops.push_back(Operand1);
89*9880d681SAndroid Build Coastguard Worker }
90*9880d681SAndroid Build Coastguard Worker
addInstruction(uint8_t Opcode,uint64_t Operand1,uint64_t Operand2)91*9880d681SAndroid Build Coastguard Worker void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
92*9880d681SAndroid Build Coastguard Worker Instructions.push_back(Instruction(Opcode));
93*9880d681SAndroid Build Coastguard Worker Instructions.back().Ops.push_back(Operand1);
94*9880d681SAndroid Build Coastguard Worker Instructions.back().Ops.push_back(Operand2);
95*9880d681SAndroid Build Coastguard Worker }
96*9880d681SAndroid Build Coastguard Worker };
97*9880d681SAndroid Build Coastguard Worker
98*9880d681SAndroid Build Coastguard Worker
99*9880d681SAndroid Build Coastguard Worker // See DWARF standard v3, section 7.23
100*9880d681SAndroid Build Coastguard Worker const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
101*9880d681SAndroid Build Coastguard Worker const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
102*9880d681SAndroid Build Coastguard Worker
parseInstructions(DataExtractor Data,uint32_t * Offset,uint32_t EndOffset)103*9880d681SAndroid Build Coastguard Worker void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset,
104*9880d681SAndroid Build Coastguard Worker uint32_t EndOffset) {
105*9880d681SAndroid Build Coastguard Worker while (*Offset < EndOffset) {
106*9880d681SAndroid Build Coastguard Worker uint8_t Opcode = Data.getU8(Offset);
107*9880d681SAndroid Build Coastguard Worker // Some instructions have a primary opcode encoded in the top bits.
108*9880d681SAndroid Build Coastguard Worker uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK;
109*9880d681SAndroid Build Coastguard Worker
110*9880d681SAndroid Build Coastguard Worker if (Primary) {
111*9880d681SAndroid Build Coastguard Worker // If it's a primary opcode, the first operand is encoded in the bottom
112*9880d681SAndroid Build Coastguard Worker // bits of the opcode itself.
113*9880d681SAndroid Build Coastguard Worker uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
114*9880d681SAndroid Build Coastguard Worker switch (Primary) {
115*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Impossible primary CFI opcode");
116*9880d681SAndroid Build Coastguard Worker case DW_CFA_advance_loc:
117*9880d681SAndroid Build Coastguard Worker case DW_CFA_restore:
118*9880d681SAndroid Build Coastguard Worker addInstruction(Primary, Op1);
119*9880d681SAndroid Build Coastguard Worker break;
120*9880d681SAndroid Build Coastguard Worker case DW_CFA_offset:
121*9880d681SAndroid Build Coastguard Worker addInstruction(Primary, Op1, Data.getULEB128(Offset));
122*9880d681SAndroid Build Coastguard Worker break;
123*9880d681SAndroid Build Coastguard Worker }
124*9880d681SAndroid Build Coastguard Worker } else {
125*9880d681SAndroid Build Coastguard Worker // Extended opcode - its value is Opcode itself.
126*9880d681SAndroid Build Coastguard Worker switch (Opcode) {
127*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Invalid extended CFI opcode");
128*9880d681SAndroid Build Coastguard Worker case DW_CFA_nop:
129*9880d681SAndroid Build Coastguard Worker case DW_CFA_remember_state:
130*9880d681SAndroid Build Coastguard Worker case DW_CFA_restore_state:
131*9880d681SAndroid Build Coastguard Worker case DW_CFA_GNU_window_save:
132*9880d681SAndroid Build Coastguard Worker // No operands
133*9880d681SAndroid Build Coastguard Worker addInstruction(Opcode);
134*9880d681SAndroid Build Coastguard Worker break;
135*9880d681SAndroid Build Coastguard Worker case DW_CFA_set_loc:
136*9880d681SAndroid Build Coastguard Worker // Operands: Address
137*9880d681SAndroid Build Coastguard Worker addInstruction(Opcode, Data.getAddress(Offset));
138*9880d681SAndroid Build Coastguard Worker break;
139*9880d681SAndroid Build Coastguard Worker case DW_CFA_advance_loc1:
140*9880d681SAndroid Build Coastguard Worker // Operands: 1-byte delta
141*9880d681SAndroid Build Coastguard Worker addInstruction(Opcode, Data.getU8(Offset));
142*9880d681SAndroid Build Coastguard Worker break;
143*9880d681SAndroid Build Coastguard Worker case DW_CFA_advance_loc2:
144*9880d681SAndroid Build Coastguard Worker // Operands: 2-byte delta
145*9880d681SAndroid Build Coastguard Worker addInstruction(Opcode, Data.getU16(Offset));
146*9880d681SAndroid Build Coastguard Worker break;
147*9880d681SAndroid Build Coastguard Worker case DW_CFA_advance_loc4:
148*9880d681SAndroid Build Coastguard Worker // Operands: 4-byte delta
149*9880d681SAndroid Build Coastguard Worker addInstruction(Opcode, Data.getU32(Offset));
150*9880d681SAndroid Build Coastguard Worker break;
151*9880d681SAndroid Build Coastguard Worker case DW_CFA_restore_extended:
152*9880d681SAndroid Build Coastguard Worker case DW_CFA_undefined:
153*9880d681SAndroid Build Coastguard Worker case DW_CFA_same_value:
154*9880d681SAndroid Build Coastguard Worker case DW_CFA_def_cfa_register:
155*9880d681SAndroid Build Coastguard Worker case DW_CFA_def_cfa_offset:
156*9880d681SAndroid Build Coastguard Worker // Operands: ULEB128
157*9880d681SAndroid Build Coastguard Worker addInstruction(Opcode, Data.getULEB128(Offset));
158*9880d681SAndroid Build Coastguard Worker break;
159*9880d681SAndroid Build Coastguard Worker case DW_CFA_def_cfa_offset_sf:
160*9880d681SAndroid Build Coastguard Worker // Operands: SLEB128
161*9880d681SAndroid Build Coastguard Worker addInstruction(Opcode, Data.getSLEB128(Offset));
162*9880d681SAndroid Build Coastguard Worker break;
163*9880d681SAndroid Build Coastguard Worker case DW_CFA_offset_extended:
164*9880d681SAndroid Build Coastguard Worker case DW_CFA_register:
165*9880d681SAndroid Build Coastguard Worker case DW_CFA_def_cfa:
166*9880d681SAndroid Build Coastguard Worker case DW_CFA_val_offset: {
167*9880d681SAndroid Build Coastguard Worker // Operands: ULEB128, ULEB128
168*9880d681SAndroid Build Coastguard Worker // Note: We can not embed getULEB128 directly into function
169*9880d681SAndroid Build Coastguard Worker // argument list. getULEB128 changes Offset and order of evaluation
170*9880d681SAndroid Build Coastguard Worker // for arguments is unspecified.
171*9880d681SAndroid Build Coastguard Worker auto op1 = Data.getULEB128(Offset);
172*9880d681SAndroid Build Coastguard Worker auto op2 = Data.getULEB128(Offset);
173*9880d681SAndroid Build Coastguard Worker addInstruction(Opcode, op1, op2);
174*9880d681SAndroid Build Coastguard Worker break;
175*9880d681SAndroid Build Coastguard Worker }
176*9880d681SAndroid Build Coastguard Worker case DW_CFA_offset_extended_sf:
177*9880d681SAndroid Build Coastguard Worker case DW_CFA_def_cfa_sf:
178*9880d681SAndroid Build Coastguard Worker case DW_CFA_val_offset_sf: {
179*9880d681SAndroid Build Coastguard Worker // Operands: ULEB128, SLEB128
180*9880d681SAndroid Build Coastguard Worker // Note: see comment for the previous case
181*9880d681SAndroid Build Coastguard Worker auto op1 = Data.getULEB128(Offset);
182*9880d681SAndroid Build Coastguard Worker auto op2 = (uint64_t)Data.getSLEB128(Offset);
183*9880d681SAndroid Build Coastguard Worker addInstruction(Opcode, op1, op2);
184*9880d681SAndroid Build Coastguard Worker break;
185*9880d681SAndroid Build Coastguard Worker }
186*9880d681SAndroid Build Coastguard Worker case DW_CFA_def_cfa_expression:
187*9880d681SAndroid Build Coastguard Worker case DW_CFA_expression:
188*9880d681SAndroid Build Coastguard Worker case DW_CFA_val_expression:
189*9880d681SAndroid Build Coastguard Worker // TODO: implement this
190*9880d681SAndroid Build Coastguard Worker report_fatal_error("Values with expressions not implemented yet!");
191*9880d681SAndroid Build Coastguard Worker }
192*9880d681SAndroid Build Coastguard Worker }
193*9880d681SAndroid Build Coastguard Worker }
194*9880d681SAndroid Build Coastguard Worker }
195*9880d681SAndroid Build Coastguard Worker
196*9880d681SAndroid Build Coastguard Worker namespace {
197*9880d681SAndroid Build Coastguard Worker /// \brief DWARF Common Information Entry (CIE)
198*9880d681SAndroid Build Coastguard Worker class CIE : public FrameEntry {
199*9880d681SAndroid Build Coastguard Worker public:
200*9880d681SAndroid Build Coastguard Worker // CIEs (and FDEs) are simply container classes, so the only sensible way to
201*9880d681SAndroid Build Coastguard Worker // create them is by providing the full parsed contents in the constructor.
CIE(uint64_t Offset,uint64_t Length,uint8_t Version,SmallString<8> Augmentation,uint8_t AddressSize,uint8_t SegmentDescriptorSize,uint64_t CodeAlignmentFactor,int64_t DataAlignmentFactor,uint64_t ReturnAddressRegister,SmallString<8> AugmentationData,uint32_t FDEPointerEncoding,uint32_t LSDAPointerEncoding)202*9880d681SAndroid Build Coastguard Worker CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
203*9880d681SAndroid Build Coastguard Worker SmallString<8> Augmentation, uint8_t AddressSize,
204*9880d681SAndroid Build Coastguard Worker uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor,
205*9880d681SAndroid Build Coastguard Worker int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister,
206*9880d681SAndroid Build Coastguard Worker SmallString<8> AugmentationData, uint32_t FDEPointerEncoding,
207*9880d681SAndroid Build Coastguard Worker uint32_t LSDAPointerEncoding)
208*9880d681SAndroid Build Coastguard Worker : FrameEntry(FK_CIE, Offset, Length), Version(Version),
209*9880d681SAndroid Build Coastguard Worker Augmentation(std::move(Augmentation)), AddressSize(AddressSize),
210*9880d681SAndroid Build Coastguard Worker SegmentDescriptorSize(SegmentDescriptorSize),
211*9880d681SAndroid Build Coastguard Worker CodeAlignmentFactor(CodeAlignmentFactor),
212*9880d681SAndroid Build Coastguard Worker DataAlignmentFactor(DataAlignmentFactor),
213*9880d681SAndroid Build Coastguard Worker ReturnAddressRegister(ReturnAddressRegister),
214*9880d681SAndroid Build Coastguard Worker AugmentationData(std::move(AugmentationData)),
215*9880d681SAndroid Build Coastguard Worker FDEPointerEncoding(FDEPointerEncoding),
216*9880d681SAndroid Build Coastguard Worker LSDAPointerEncoding(LSDAPointerEncoding) {}
217*9880d681SAndroid Build Coastguard Worker
~CIE()218*9880d681SAndroid Build Coastguard Worker ~CIE() override {}
219*9880d681SAndroid Build Coastguard Worker
getAugmentationString() const220*9880d681SAndroid Build Coastguard Worker StringRef getAugmentationString() const { return Augmentation; }
getCodeAlignmentFactor() const221*9880d681SAndroid Build Coastguard Worker uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
getDataAlignmentFactor() const222*9880d681SAndroid Build Coastguard Worker int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
getFDEPointerEncoding() const223*9880d681SAndroid Build Coastguard Worker uint32_t getFDEPointerEncoding() const {
224*9880d681SAndroid Build Coastguard Worker return FDEPointerEncoding;
225*9880d681SAndroid Build Coastguard Worker }
getLSDAPointerEncoding() const226*9880d681SAndroid Build Coastguard Worker uint32_t getLSDAPointerEncoding() const {
227*9880d681SAndroid Build Coastguard Worker return LSDAPointerEncoding;
228*9880d681SAndroid Build Coastguard Worker }
229*9880d681SAndroid Build Coastguard Worker
dumpHeader(raw_ostream & OS) const230*9880d681SAndroid Build Coastguard Worker void dumpHeader(raw_ostream &OS) const override {
231*9880d681SAndroid Build Coastguard Worker OS << format("%08x %08x %08x CIE",
232*9880d681SAndroid Build Coastguard Worker (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID)
233*9880d681SAndroid Build Coastguard Worker << "\n";
234*9880d681SAndroid Build Coastguard Worker OS << format(" Version: %d\n", Version);
235*9880d681SAndroid Build Coastguard Worker OS << " Augmentation: \"" << Augmentation << "\"\n";
236*9880d681SAndroid Build Coastguard Worker if (Version >= 4) {
237*9880d681SAndroid Build Coastguard Worker OS << format(" Address size: %u\n",
238*9880d681SAndroid Build Coastguard Worker (uint32_t)AddressSize);
239*9880d681SAndroid Build Coastguard Worker OS << format(" Segment desc size: %u\n",
240*9880d681SAndroid Build Coastguard Worker (uint32_t)SegmentDescriptorSize);
241*9880d681SAndroid Build Coastguard Worker }
242*9880d681SAndroid Build Coastguard Worker OS << format(" Code alignment factor: %u\n",
243*9880d681SAndroid Build Coastguard Worker (uint32_t)CodeAlignmentFactor);
244*9880d681SAndroid Build Coastguard Worker OS << format(" Data alignment factor: %d\n",
245*9880d681SAndroid Build Coastguard Worker (int32_t)DataAlignmentFactor);
246*9880d681SAndroid Build Coastguard Worker OS << format(" Return address column: %d\n",
247*9880d681SAndroid Build Coastguard Worker (int32_t)ReturnAddressRegister);
248*9880d681SAndroid Build Coastguard Worker if (!AugmentationData.empty()) {
249*9880d681SAndroid Build Coastguard Worker OS << " Augmentation data: ";
250*9880d681SAndroid Build Coastguard Worker for (uint8_t Byte : AugmentationData)
251*9880d681SAndroid Build Coastguard Worker OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf);
252*9880d681SAndroid Build Coastguard Worker OS << "\n";
253*9880d681SAndroid Build Coastguard Worker }
254*9880d681SAndroid Build Coastguard Worker OS << "\n";
255*9880d681SAndroid Build Coastguard Worker }
256*9880d681SAndroid Build Coastguard Worker
classof(const FrameEntry * FE)257*9880d681SAndroid Build Coastguard Worker static bool classof(const FrameEntry *FE) {
258*9880d681SAndroid Build Coastguard Worker return FE->getKind() == FK_CIE;
259*9880d681SAndroid Build Coastguard Worker }
260*9880d681SAndroid Build Coastguard Worker
261*9880d681SAndroid Build Coastguard Worker private:
262*9880d681SAndroid Build Coastguard Worker /// The following fields are defined in section 6.4.1 of the DWARF standard v4
263*9880d681SAndroid Build Coastguard Worker uint8_t Version;
264*9880d681SAndroid Build Coastguard Worker SmallString<8> Augmentation;
265*9880d681SAndroid Build Coastguard Worker uint8_t AddressSize;
266*9880d681SAndroid Build Coastguard Worker uint8_t SegmentDescriptorSize;
267*9880d681SAndroid Build Coastguard Worker uint64_t CodeAlignmentFactor;
268*9880d681SAndroid Build Coastguard Worker int64_t DataAlignmentFactor;
269*9880d681SAndroid Build Coastguard Worker uint64_t ReturnAddressRegister;
270*9880d681SAndroid Build Coastguard Worker
271*9880d681SAndroid Build Coastguard Worker // The following are used when the CIE represents an EH frame entry.
272*9880d681SAndroid Build Coastguard Worker SmallString<8> AugmentationData;
273*9880d681SAndroid Build Coastguard Worker uint32_t FDEPointerEncoding;
274*9880d681SAndroid Build Coastguard Worker uint32_t LSDAPointerEncoding;
275*9880d681SAndroid Build Coastguard Worker };
276*9880d681SAndroid Build Coastguard Worker
277*9880d681SAndroid Build Coastguard Worker
278*9880d681SAndroid Build Coastguard Worker /// \brief DWARF Frame Description Entry (FDE)
279*9880d681SAndroid Build Coastguard Worker class FDE : public FrameEntry {
280*9880d681SAndroid Build Coastguard Worker public:
281*9880d681SAndroid Build Coastguard Worker // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
282*9880d681SAndroid Build Coastguard Worker // an offset to the CIE (provided by parsing the FDE header). The CIE itself
283*9880d681SAndroid Build Coastguard Worker // is obtained lazily once it's actually required.
FDE(uint64_t Offset,uint64_t Length,int64_t LinkedCIEOffset,uint64_t InitialLocation,uint64_t AddressRange,CIE * Cie)284*9880d681SAndroid Build Coastguard Worker FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
285*9880d681SAndroid Build Coastguard Worker uint64_t InitialLocation, uint64_t AddressRange,
286*9880d681SAndroid Build Coastguard Worker CIE *Cie)
287*9880d681SAndroid Build Coastguard Worker : FrameEntry(FK_FDE, Offset, Length), LinkedCIEOffset(LinkedCIEOffset),
288*9880d681SAndroid Build Coastguard Worker InitialLocation(InitialLocation), AddressRange(AddressRange),
289*9880d681SAndroid Build Coastguard Worker LinkedCIE(Cie) {}
290*9880d681SAndroid Build Coastguard Worker
~FDE()291*9880d681SAndroid Build Coastguard Worker ~FDE() override {}
292*9880d681SAndroid Build Coastguard Worker
getLinkedCIE() const293*9880d681SAndroid Build Coastguard Worker CIE *getLinkedCIE() const { return LinkedCIE; }
294*9880d681SAndroid Build Coastguard Worker
dumpHeader(raw_ostream & OS) const295*9880d681SAndroid Build Coastguard Worker void dumpHeader(raw_ostream &OS) const override {
296*9880d681SAndroid Build Coastguard Worker OS << format("%08x %08x %08x FDE ",
297*9880d681SAndroid Build Coastguard Worker (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset);
298*9880d681SAndroid Build Coastguard Worker OS << format("cie=%08x pc=%08x...%08x\n",
299*9880d681SAndroid Build Coastguard Worker (int32_t)LinkedCIEOffset,
300*9880d681SAndroid Build Coastguard Worker (uint32_t)InitialLocation,
301*9880d681SAndroid Build Coastguard Worker (uint32_t)InitialLocation + (uint32_t)AddressRange);
302*9880d681SAndroid Build Coastguard Worker }
303*9880d681SAndroid Build Coastguard Worker
classof(const FrameEntry * FE)304*9880d681SAndroid Build Coastguard Worker static bool classof(const FrameEntry *FE) {
305*9880d681SAndroid Build Coastguard Worker return FE->getKind() == FK_FDE;
306*9880d681SAndroid Build Coastguard Worker }
307*9880d681SAndroid Build Coastguard Worker
308*9880d681SAndroid Build Coastguard Worker private:
309*9880d681SAndroid Build Coastguard Worker /// The following fields are defined in section 6.4.1 of the DWARF standard v3
310*9880d681SAndroid Build Coastguard Worker uint64_t LinkedCIEOffset;
311*9880d681SAndroid Build Coastguard Worker uint64_t InitialLocation;
312*9880d681SAndroid Build Coastguard Worker uint64_t AddressRange;
313*9880d681SAndroid Build Coastguard Worker CIE *LinkedCIE;
314*9880d681SAndroid Build Coastguard Worker };
315*9880d681SAndroid Build Coastguard Worker
316*9880d681SAndroid Build Coastguard Worker /// \brief Types of operands to CF instructions.
317*9880d681SAndroid Build Coastguard Worker enum OperandType {
318*9880d681SAndroid Build Coastguard Worker OT_Unset,
319*9880d681SAndroid Build Coastguard Worker OT_None,
320*9880d681SAndroid Build Coastguard Worker OT_Address,
321*9880d681SAndroid Build Coastguard Worker OT_Offset,
322*9880d681SAndroid Build Coastguard Worker OT_FactoredCodeOffset,
323*9880d681SAndroid Build Coastguard Worker OT_SignedFactDataOffset,
324*9880d681SAndroid Build Coastguard Worker OT_UnsignedFactDataOffset,
325*9880d681SAndroid Build Coastguard Worker OT_Register,
326*9880d681SAndroid Build Coastguard Worker OT_Expression
327*9880d681SAndroid Build Coastguard Worker };
328*9880d681SAndroid Build Coastguard Worker
329*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
330*9880d681SAndroid Build Coastguard Worker
331*9880d681SAndroid Build Coastguard Worker /// \brief Initialize the array describing the types of operands.
getOperandTypes()332*9880d681SAndroid Build Coastguard Worker static ArrayRef<OperandType[2]> getOperandTypes() {
333*9880d681SAndroid Build Coastguard Worker static OperandType OpTypes[DW_CFA_restore+1][2];
334*9880d681SAndroid Build Coastguard Worker
335*9880d681SAndroid Build Coastguard Worker #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \
336*9880d681SAndroid Build Coastguard Worker do { \
337*9880d681SAndroid Build Coastguard Worker OpTypes[OP][0] = OPTYPE0; \
338*9880d681SAndroid Build Coastguard Worker OpTypes[OP][1] = OPTYPE1; \
339*9880d681SAndroid Build Coastguard Worker } while (0)
340*9880d681SAndroid Build Coastguard Worker #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None)
341*9880d681SAndroid Build Coastguard Worker #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None)
342*9880d681SAndroid Build Coastguard Worker
343*9880d681SAndroid Build Coastguard Worker DECLARE_OP1(DW_CFA_set_loc, OT_Address);
344*9880d681SAndroid Build Coastguard Worker DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset);
345*9880d681SAndroid Build Coastguard Worker DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset);
346*9880d681SAndroid Build Coastguard Worker DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset);
347*9880d681SAndroid Build Coastguard Worker DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset);
348*9880d681SAndroid Build Coastguard Worker DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset);
349*9880d681SAndroid Build Coastguard Worker DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset);
350*9880d681SAndroid Build Coastguard Worker DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset);
351*9880d681SAndroid Build Coastguard Worker DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register);
352*9880d681SAndroid Build Coastguard Worker DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset);
353*9880d681SAndroid Build Coastguard Worker DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset);
354*9880d681SAndroid Build Coastguard Worker DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression);
355*9880d681SAndroid Build Coastguard Worker DECLARE_OP1(DW_CFA_undefined, OT_Register);
356*9880d681SAndroid Build Coastguard Worker DECLARE_OP1(DW_CFA_same_value, OT_Register);
357*9880d681SAndroid Build Coastguard Worker DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset);
358*9880d681SAndroid Build Coastguard Worker DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset);
359*9880d681SAndroid Build Coastguard Worker DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset);
360*9880d681SAndroid Build Coastguard Worker DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset);
361*9880d681SAndroid Build Coastguard Worker DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset);
362*9880d681SAndroid Build Coastguard Worker DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register);
363*9880d681SAndroid Build Coastguard Worker DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression);
364*9880d681SAndroid Build Coastguard Worker DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression);
365*9880d681SAndroid Build Coastguard Worker DECLARE_OP1(DW_CFA_restore, OT_Register);
366*9880d681SAndroid Build Coastguard Worker DECLARE_OP1(DW_CFA_restore_extended, OT_Register);
367*9880d681SAndroid Build Coastguard Worker DECLARE_OP0(DW_CFA_remember_state);
368*9880d681SAndroid Build Coastguard Worker DECLARE_OP0(DW_CFA_restore_state);
369*9880d681SAndroid Build Coastguard Worker DECLARE_OP0(DW_CFA_GNU_window_save);
370*9880d681SAndroid Build Coastguard Worker DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset);
371*9880d681SAndroid Build Coastguard Worker DECLARE_OP0(DW_CFA_nop);
372*9880d681SAndroid Build Coastguard Worker
373*9880d681SAndroid Build Coastguard Worker #undef DECLARE_OP0
374*9880d681SAndroid Build Coastguard Worker #undef DECLARE_OP1
375*9880d681SAndroid Build Coastguard Worker #undef DECLARE_OP2
376*9880d681SAndroid Build Coastguard Worker return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
377*9880d681SAndroid Build Coastguard Worker }
378*9880d681SAndroid Build Coastguard Worker
379*9880d681SAndroid Build Coastguard Worker static ArrayRef<OperandType[2]> OpTypes = getOperandTypes();
380*9880d681SAndroid Build Coastguard Worker
381*9880d681SAndroid Build Coastguard Worker /// \brief Print \p Opcode's operand number \p OperandIdx which has
382*9880d681SAndroid Build Coastguard Worker /// value \p Operand.
printOperand(raw_ostream & OS,uint8_t Opcode,unsigned OperandIdx,uint64_t Operand,uint64_t CodeAlignmentFactor,int64_t DataAlignmentFactor)383*9880d681SAndroid Build Coastguard Worker static void printOperand(raw_ostream &OS, uint8_t Opcode, unsigned OperandIdx,
384*9880d681SAndroid Build Coastguard Worker uint64_t Operand, uint64_t CodeAlignmentFactor,
385*9880d681SAndroid Build Coastguard Worker int64_t DataAlignmentFactor) {
386*9880d681SAndroid Build Coastguard Worker assert(OperandIdx < 2);
387*9880d681SAndroid Build Coastguard Worker OperandType Type = OpTypes[Opcode][OperandIdx];
388*9880d681SAndroid Build Coastguard Worker
389*9880d681SAndroid Build Coastguard Worker switch (Type) {
390*9880d681SAndroid Build Coastguard Worker case OT_Unset:
391*9880d681SAndroid Build Coastguard Worker OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";
392*9880d681SAndroid Build Coastguard Worker if (const char *OpcodeName = CallFrameString(Opcode))
393*9880d681SAndroid Build Coastguard Worker OS << " " << OpcodeName;
394*9880d681SAndroid Build Coastguard Worker else
395*9880d681SAndroid Build Coastguard Worker OS << format(" Opcode %x", Opcode);
396*9880d681SAndroid Build Coastguard Worker break;
397*9880d681SAndroid Build Coastguard Worker case OT_None:
398*9880d681SAndroid Build Coastguard Worker break;
399*9880d681SAndroid Build Coastguard Worker case OT_Address:
400*9880d681SAndroid Build Coastguard Worker OS << format(" %" PRIx64, Operand);
401*9880d681SAndroid Build Coastguard Worker break;
402*9880d681SAndroid Build Coastguard Worker case OT_Offset:
403*9880d681SAndroid Build Coastguard Worker // The offsets are all encoded in a unsigned form, but in practice
404*9880d681SAndroid Build Coastguard Worker // consumers use them signed. It's most certainly legacy due to
405*9880d681SAndroid Build Coastguard Worker // the lack of signed variants in the first Dwarf standards.
406*9880d681SAndroid Build Coastguard Worker OS << format(" %+" PRId64, int64_t(Operand));
407*9880d681SAndroid Build Coastguard Worker break;
408*9880d681SAndroid Build Coastguard Worker case OT_FactoredCodeOffset: // Always Unsigned
409*9880d681SAndroid Build Coastguard Worker if (CodeAlignmentFactor)
410*9880d681SAndroid Build Coastguard Worker OS << format(" %" PRId64, Operand * CodeAlignmentFactor);
411*9880d681SAndroid Build Coastguard Worker else
412*9880d681SAndroid Build Coastguard Worker OS << format(" %" PRId64 "*code_alignment_factor" , Operand);
413*9880d681SAndroid Build Coastguard Worker break;
414*9880d681SAndroid Build Coastguard Worker case OT_SignedFactDataOffset:
415*9880d681SAndroid Build Coastguard Worker if (DataAlignmentFactor)
416*9880d681SAndroid Build Coastguard Worker OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor);
417*9880d681SAndroid Build Coastguard Worker else
418*9880d681SAndroid Build Coastguard Worker OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand));
419*9880d681SAndroid Build Coastguard Worker break;
420*9880d681SAndroid Build Coastguard Worker case OT_UnsignedFactDataOffset:
421*9880d681SAndroid Build Coastguard Worker if (DataAlignmentFactor)
422*9880d681SAndroid Build Coastguard Worker OS << format(" %" PRId64, Operand * DataAlignmentFactor);
423*9880d681SAndroid Build Coastguard Worker else
424*9880d681SAndroid Build Coastguard Worker OS << format(" %" PRId64 "*data_alignment_factor" , Operand);
425*9880d681SAndroid Build Coastguard Worker break;
426*9880d681SAndroid Build Coastguard Worker case OT_Register:
427*9880d681SAndroid Build Coastguard Worker OS << format(" reg%" PRId64, Operand);
428*9880d681SAndroid Build Coastguard Worker break;
429*9880d681SAndroid Build Coastguard Worker case OT_Expression:
430*9880d681SAndroid Build Coastguard Worker OS << " expression";
431*9880d681SAndroid Build Coastguard Worker break;
432*9880d681SAndroid Build Coastguard Worker }
433*9880d681SAndroid Build Coastguard Worker }
434*9880d681SAndroid Build Coastguard Worker
dumpInstructions(raw_ostream & OS) const435*9880d681SAndroid Build Coastguard Worker void FrameEntry::dumpInstructions(raw_ostream &OS) const {
436*9880d681SAndroid Build Coastguard Worker uint64_t CodeAlignmentFactor = 0;
437*9880d681SAndroid Build Coastguard Worker int64_t DataAlignmentFactor = 0;
438*9880d681SAndroid Build Coastguard Worker const CIE *Cie = dyn_cast<CIE>(this);
439*9880d681SAndroid Build Coastguard Worker
440*9880d681SAndroid Build Coastguard Worker if (!Cie)
441*9880d681SAndroid Build Coastguard Worker Cie = cast<FDE>(this)->getLinkedCIE();
442*9880d681SAndroid Build Coastguard Worker if (Cie) {
443*9880d681SAndroid Build Coastguard Worker CodeAlignmentFactor = Cie->getCodeAlignmentFactor();
444*9880d681SAndroid Build Coastguard Worker DataAlignmentFactor = Cie->getDataAlignmentFactor();
445*9880d681SAndroid Build Coastguard Worker }
446*9880d681SAndroid Build Coastguard Worker
447*9880d681SAndroid Build Coastguard Worker for (const auto &Instr : Instructions) {
448*9880d681SAndroid Build Coastguard Worker uint8_t Opcode = Instr.Opcode;
449*9880d681SAndroid Build Coastguard Worker if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
450*9880d681SAndroid Build Coastguard Worker Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
451*9880d681SAndroid Build Coastguard Worker OS << " " << CallFrameString(Opcode) << ":";
452*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < Instr.Ops.size(); ++i)
453*9880d681SAndroid Build Coastguard Worker printOperand(OS, Opcode, i, Instr.Ops[i], CodeAlignmentFactor,
454*9880d681SAndroid Build Coastguard Worker DataAlignmentFactor);
455*9880d681SAndroid Build Coastguard Worker OS << '\n';
456*9880d681SAndroid Build Coastguard Worker }
457*9880d681SAndroid Build Coastguard Worker }
458*9880d681SAndroid Build Coastguard Worker
DWARFDebugFrame(bool IsEH)459*9880d681SAndroid Build Coastguard Worker DWARFDebugFrame::DWARFDebugFrame(bool IsEH) : IsEH(IsEH) {
460*9880d681SAndroid Build Coastguard Worker }
461*9880d681SAndroid Build Coastguard Worker
~DWARFDebugFrame()462*9880d681SAndroid Build Coastguard Worker DWARFDebugFrame::~DWARFDebugFrame() {
463*9880d681SAndroid Build Coastguard Worker }
464*9880d681SAndroid Build Coastguard Worker
dumpDataAux(DataExtractor Data,uint32_t Offset,int Length)465*9880d681SAndroid Build Coastguard Worker static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
466*9880d681SAndroid Build Coastguard Worker uint32_t Offset, int Length) {
467*9880d681SAndroid Build Coastguard Worker errs() << "DUMP: ";
468*9880d681SAndroid Build Coastguard Worker for (int i = 0; i < Length; ++i) {
469*9880d681SAndroid Build Coastguard Worker uint8_t c = Data.getU8(&Offset);
470*9880d681SAndroid Build Coastguard Worker errs().write_hex(c); errs() << " ";
471*9880d681SAndroid Build Coastguard Worker }
472*9880d681SAndroid Build Coastguard Worker errs() << "\n";
473*9880d681SAndroid Build Coastguard Worker }
474*9880d681SAndroid Build Coastguard Worker
getSizeForEncoding(const DataExtractor & Data,unsigned symbolEncoding)475*9880d681SAndroid Build Coastguard Worker static unsigned getSizeForEncoding(const DataExtractor &Data,
476*9880d681SAndroid Build Coastguard Worker unsigned symbolEncoding) {
477*9880d681SAndroid Build Coastguard Worker unsigned format = symbolEncoding & 0x0f;
478*9880d681SAndroid Build Coastguard Worker switch (format) {
479*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Unknown Encoding");
480*9880d681SAndroid Build Coastguard Worker case dwarf::DW_EH_PE_absptr:
481*9880d681SAndroid Build Coastguard Worker case dwarf::DW_EH_PE_signed:
482*9880d681SAndroid Build Coastguard Worker return Data.getAddressSize();
483*9880d681SAndroid Build Coastguard Worker case dwarf::DW_EH_PE_udata2:
484*9880d681SAndroid Build Coastguard Worker case dwarf::DW_EH_PE_sdata2:
485*9880d681SAndroid Build Coastguard Worker return 2;
486*9880d681SAndroid Build Coastguard Worker case dwarf::DW_EH_PE_udata4:
487*9880d681SAndroid Build Coastguard Worker case dwarf::DW_EH_PE_sdata4:
488*9880d681SAndroid Build Coastguard Worker return 4;
489*9880d681SAndroid Build Coastguard Worker case dwarf::DW_EH_PE_udata8:
490*9880d681SAndroid Build Coastguard Worker case dwarf::DW_EH_PE_sdata8:
491*9880d681SAndroid Build Coastguard Worker return 8;
492*9880d681SAndroid Build Coastguard Worker }
493*9880d681SAndroid Build Coastguard Worker }
494*9880d681SAndroid Build Coastguard Worker
readPointer(const DataExtractor & Data,uint32_t & Offset,unsigned Encoding)495*9880d681SAndroid Build Coastguard Worker static uint64_t readPointer(const DataExtractor &Data, uint32_t &Offset,
496*9880d681SAndroid Build Coastguard Worker unsigned Encoding) {
497*9880d681SAndroid Build Coastguard Worker switch (getSizeForEncoding(Data, Encoding)) {
498*9880d681SAndroid Build Coastguard Worker case 2:
499*9880d681SAndroid Build Coastguard Worker return Data.getU16(&Offset);
500*9880d681SAndroid Build Coastguard Worker case 4:
501*9880d681SAndroid Build Coastguard Worker return Data.getU32(&Offset);
502*9880d681SAndroid Build Coastguard Worker case 8:
503*9880d681SAndroid Build Coastguard Worker return Data.getU64(&Offset);
504*9880d681SAndroid Build Coastguard Worker default:
505*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Illegal data size");
506*9880d681SAndroid Build Coastguard Worker }
507*9880d681SAndroid Build Coastguard Worker }
508*9880d681SAndroid Build Coastguard Worker
parse(DataExtractor Data)509*9880d681SAndroid Build Coastguard Worker void DWARFDebugFrame::parse(DataExtractor Data) {
510*9880d681SAndroid Build Coastguard Worker uint32_t Offset = 0;
511*9880d681SAndroid Build Coastguard Worker DenseMap<uint32_t, CIE *> CIEs;
512*9880d681SAndroid Build Coastguard Worker
513*9880d681SAndroid Build Coastguard Worker while (Data.isValidOffset(Offset)) {
514*9880d681SAndroid Build Coastguard Worker uint32_t StartOffset = Offset;
515*9880d681SAndroid Build Coastguard Worker
516*9880d681SAndroid Build Coastguard Worker auto ReportError = [StartOffset](const char *ErrorMsg) {
517*9880d681SAndroid Build Coastguard Worker std::string Str;
518*9880d681SAndroid Build Coastguard Worker raw_string_ostream OS(Str);
519*9880d681SAndroid Build Coastguard Worker OS << format(ErrorMsg, StartOffset);
520*9880d681SAndroid Build Coastguard Worker OS.flush();
521*9880d681SAndroid Build Coastguard Worker report_fatal_error(Str);
522*9880d681SAndroid Build Coastguard Worker };
523*9880d681SAndroid Build Coastguard Worker
524*9880d681SAndroid Build Coastguard Worker bool IsDWARF64 = false;
525*9880d681SAndroid Build Coastguard Worker uint64_t Length = Data.getU32(&Offset);
526*9880d681SAndroid Build Coastguard Worker uint64_t Id;
527*9880d681SAndroid Build Coastguard Worker
528*9880d681SAndroid Build Coastguard Worker if (Length == UINT32_MAX) {
529*9880d681SAndroid Build Coastguard Worker // DWARF-64 is distinguished by the first 32 bits of the initial length
530*9880d681SAndroid Build Coastguard Worker // field being 0xffffffff. Then, the next 64 bits are the actual entry
531*9880d681SAndroid Build Coastguard Worker // length.
532*9880d681SAndroid Build Coastguard Worker IsDWARF64 = true;
533*9880d681SAndroid Build Coastguard Worker Length = Data.getU64(&Offset);
534*9880d681SAndroid Build Coastguard Worker }
535*9880d681SAndroid Build Coastguard Worker
536*9880d681SAndroid Build Coastguard Worker // At this point, Offset points to the next field after Length.
537*9880d681SAndroid Build Coastguard Worker // Length is the structure size excluding itself. Compute an offset one
538*9880d681SAndroid Build Coastguard Worker // past the end of the structure (needed to know how many instructions to
539*9880d681SAndroid Build Coastguard Worker // read).
540*9880d681SAndroid Build Coastguard Worker // TODO: For honest DWARF64 support, DataExtractor will have to treat
541*9880d681SAndroid Build Coastguard Worker // offset_ptr as uint64_t*
542*9880d681SAndroid Build Coastguard Worker uint32_t StartStructureOffset = Offset;
543*9880d681SAndroid Build Coastguard Worker uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);
544*9880d681SAndroid Build Coastguard Worker
545*9880d681SAndroid Build Coastguard Worker // The Id field's size depends on the DWARF format
546*9880d681SAndroid Build Coastguard Worker Id = Data.getUnsigned(&Offset, (IsDWARF64 && !IsEH) ? 8 : 4);
547*9880d681SAndroid Build Coastguard Worker bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) ||
548*9880d681SAndroid Build Coastguard Worker Id == DW_CIE_ID ||
549*9880d681SAndroid Build Coastguard Worker (IsEH && !Id));
550*9880d681SAndroid Build Coastguard Worker
551*9880d681SAndroid Build Coastguard Worker if (IsCIE) {
552*9880d681SAndroid Build Coastguard Worker uint8_t Version = Data.getU8(&Offset);
553*9880d681SAndroid Build Coastguard Worker const char *Augmentation = Data.getCStr(&Offset);
554*9880d681SAndroid Build Coastguard Worker StringRef AugmentationString(Augmentation ? Augmentation : "");
555*9880d681SAndroid Build Coastguard Worker uint8_t AddressSize = Version < 4 ? Data.getAddressSize() :
556*9880d681SAndroid Build Coastguard Worker Data.getU8(&Offset);
557*9880d681SAndroid Build Coastguard Worker Data.setAddressSize(AddressSize);
558*9880d681SAndroid Build Coastguard Worker uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset);
559*9880d681SAndroid Build Coastguard Worker uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
560*9880d681SAndroid Build Coastguard Worker int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
561*9880d681SAndroid Build Coastguard Worker uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);
562*9880d681SAndroid Build Coastguard Worker
563*9880d681SAndroid Build Coastguard Worker // Parse the augmentation data for EH CIEs
564*9880d681SAndroid Build Coastguard Worker StringRef AugmentationData("");
565*9880d681SAndroid Build Coastguard Worker uint32_t FDEPointerEncoding = DW_EH_PE_omit;
566*9880d681SAndroid Build Coastguard Worker uint32_t LSDAPointerEncoding = DW_EH_PE_omit;
567*9880d681SAndroid Build Coastguard Worker if (IsEH) {
568*9880d681SAndroid Build Coastguard Worker Optional<uint32_t> PersonalityEncoding;
569*9880d681SAndroid Build Coastguard Worker Optional<uint64_t> Personality;
570*9880d681SAndroid Build Coastguard Worker
571*9880d681SAndroid Build Coastguard Worker Optional<uint64_t> AugmentationLength;
572*9880d681SAndroid Build Coastguard Worker uint32_t StartAugmentationOffset;
573*9880d681SAndroid Build Coastguard Worker uint32_t EndAugmentationOffset;
574*9880d681SAndroid Build Coastguard Worker
575*9880d681SAndroid Build Coastguard Worker // Walk the augmentation string to get all the augmentation data.
576*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) {
577*9880d681SAndroid Build Coastguard Worker switch (AugmentationString[i]) {
578*9880d681SAndroid Build Coastguard Worker default:
579*9880d681SAndroid Build Coastguard Worker ReportError("Unknown augmentation character in entry at %lx");
580*9880d681SAndroid Build Coastguard Worker case 'L':
581*9880d681SAndroid Build Coastguard Worker LSDAPointerEncoding = Data.getU8(&Offset);
582*9880d681SAndroid Build Coastguard Worker break;
583*9880d681SAndroid Build Coastguard Worker case 'P': {
584*9880d681SAndroid Build Coastguard Worker if (Personality)
585*9880d681SAndroid Build Coastguard Worker ReportError("Duplicate personality in entry at %lx");
586*9880d681SAndroid Build Coastguard Worker PersonalityEncoding = Data.getU8(&Offset);
587*9880d681SAndroid Build Coastguard Worker Personality = readPointer(Data, Offset, *PersonalityEncoding);
588*9880d681SAndroid Build Coastguard Worker break;
589*9880d681SAndroid Build Coastguard Worker }
590*9880d681SAndroid Build Coastguard Worker case 'R':
591*9880d681SAndroid Build Coastguard Worker FDEPointerEncoding = Data.getU8(&Offset);
592*9880d681SAndroid Build Coastguard Worker break;
593*9880d681SAndroid Build Coastguard Worker case 'z':
594*9880d681SAndroid Build Coastguard Worker if (i)
595*9880d681SAndroid Build Coastguard Worker ReportError("'z' must be the first character at %lx");
596*9880d681SAndroid Build Coastguard Worker // Parse the augmentation length first. We only parse it if
597*9880d681SAndroid Build Coastguard Worker // the string contains a 'z'.
598*9880d681SAndroid Build Coastguard Worker AugmentationLength = Data.getULEB128(&Offset);
599*9880d681SAndroid Build Coastguard Worker StartAugmentationOffset = Offset;
600*9880d681SAndroid Build Coastguard Worker EndAugmentationOffset = Offset +
601*9880d681SAndroid Build Coastguard Worker static_cast<uint32_t>(*AugmentationLength);
602*9880d681SAndroid Build Coastguard Worker }
603*9880d681SAndroid Build Coastguard Worker }
604*9880d681SAndroid Build Coastguard Worker
605*9880d681SAndroid Build Coastguard Worker if (AugmentationLength.hasValue()) {
606*9880d681SAndroid Build Coastguard Worker if (Offset != EndAugmentationOffset)
607*9880d681SAndroid Build Coastguard Worker ReportError("Parsing augmentation data at %lx failed");
608*9880d681SAndroid Build Coastguard Worker
609*9880d681SAndroid Build Coastguard Worker AugmentationData = Data.getData().slice(StartAugmentationOffset,
610*9880d681SAndroid Build Coastguard Worker EndAugmentationOffset);
611*9880d681SAndroid Build Coastguard Worker }
612*9880d681SAndroid Build Coastguard Worker }
613*9880d681SAndroid Build Coastguard Worker
614*9880d681SAndroid Build Coastguard Worker auto Cie = make_unique<CIE>(StartOffset, Length, Version,
615*9880d681SAndroid Build Coastguard Worker AugmentationString, AddressSize,
616*9880d681SAndroid Build Coastguard Worker SegmentDescriptorSize, CodeAlignmentFactor,
617*9880d681SAndroid Build Coastguard Worker DataAlignmentFactor, ReturnAddressRegister,
618*9880d681SAndroid Build Coastguard Worker AugmentationData, FDEPointerEncoding,
619*9880d681SAndroid Build Coastguard Worker LSDAPointerEncoding);
620*9880d681SAndroid Build Coastguard Worker CIEs[StartOffset] = Cie.get();
621*9880d681SAndroid Build Coastguard Worker Entries.emplace_back(std::move(Cie));
622*9880d681SAndroid Build Coastguard Worker } else {
623*9880d681SAndroid Build Coastguard Worker // FDE
624*9880d681SAndroid Build Coastguard Worker uint64_t CIEPointer = Id;
625*9880d681SAndroid Build Coastguard Worker uint64_t InitialLocation = 0;
626*9880d681SAndroid Build Coastguard Worker uint64_t AddressRange = 0;
627*9880d681SAndroid Build Coastguard Worker CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer];
628*9880d681SAndroid Build Coastguard Worker
629*9880d681SAndroid Build Coastguard Worker if (IsEH) {
630*9880d681SAndroid Build Coastguard Worker // The address size is encoded in the CIE we reference.
631*9880d681SAndroid Build Coastguard Worker if (!Cie)
632*9880d681SAndroid Build Coastguard Worker ReportError("Parsing FDE data at %lx failed due to missing CIE");
633*9880d681SAndroid Build Coastguard Worker
634*9880d681SAndroid Build Coastguard Worker InitialLocation = readPointer(Data, Offset,
635*9880d681SAndroid Build Coastguard Worker Cie->getFDEPointerEncoding());
636*9880d681SAndroid Build Coastguard Worker AddressRange = readPointer(Data, Offset,
637*9880d681SAndroid Build Coastguard Worker Cie->getFDEPointerEncoding());
638*9880d681SAndroid Build Coastguard Worker
639*9880d681SAndroid Build Coastguard Worker StringRef AugmentationString = Cie->getAugmentationString();
640*9880d681SAndroid Build Coastguard Worker if (!AugmentationString.empty()) {
641*9880d681SAndroid Build Coastguard Worker // Parse the augmentation length and data for this FDE.
642*9880d681SAndroid Build Coastguard Worker uint64_t AugmentationLength = Data.getULEB128(&Offset);
643*9880d681SAndroid Build Coastguard Worker
644*9880d681SAndroid Build Coastguard Worker uint32_t EndAugmentationOffset =
645*9880d681SAndroid Build Coastguard Worker Offset + static_cast<uint32_t>(AugmentationLength);
646*9880d681SAndroid Build Coastguard Worker
647*9880d681SAndroid Build Coastguard Worker // Decode the LSDA if the CIE augmentation string said we should.
648*9880d681SAndroid Build Coastguard Worker if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit)
649*9880d681SAndroid Build Coastguard Worker readPointer(Data, Offset, Cie->getLSDAPointerEncoding());
650*9880d681SAndroid Build Coastguard Worker
651*9880d681SAndroid Build Coastguard Worker if (Offset != EndAugmentationOffset)
652*9880d681SAndroid Build Coastguard Worker ReportError("Parsing augmentation data at %lx failed");
653*9880d681SAndroid Build Coastguard Worker }
654*9880d681SAndroid Build Coastguard Worker } else {
655*9880d681SAndroid Build Coastguard Worker InitialLocation = Data.getAddress(&Offset);
656*9880d681SAndroid Build Coastguard Worker AddressRange = Data.getAddress(&Offset);
657*9880d681SAndroid Build Coastguard Worker }
658*9880d681SAndroid Build Coastguard Worker
659*9880d681SAndroid Build Coastguard Worker Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,
660*9880d681SAndroid Build Coastguard Worker InitialLocation, AddressRange,
661*9880d681SAndroid Build Coastguard Worker Cie));
662*9880d681SAndroid Build Coastguard Worker }
663*9880d681SAndroid Build Coastguard Worker
664*9880d681SAndroid Build Coastguard Worker Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);
665*9880d681SAndroid Build Coastguard Worker
666*9880d681SAndroid Build Coastguard Worker if (Offset != EndStructureOffset)
667*9880d681SAndroid Build Coastguard Worker ReportError("Parsing entry instructions at %lx failed");
668*9880d681SAndroid Build Coastguard Worker }
669*9880d681SAndroid Build Coastguard Worker }
670*9880d681SAndroid Build Coastguard Worker
671*9880d681SAndroid Build Coastguard Worker
dump(raw_ostream & OS) const672*9880d681SAndroid Build Coastguard Worker void DWARFDebugFrame::dump(raw_ostream &OS) const {
673*9880d681SAndroid Build Coastguard Worker OS << "\n";
674*9880d681SAndroid Build Coastguard Worker for (const auto &Entry : Entries) {
675*9880d681SAndroid Build Coastguard Worker Entry->dumpHeader(OS);
676*9880d681SAndroid Build Coastguard Worker Entry->dumpInstructions(OS);
677*9880d681SAndroid Build Coastguard Worker OS << "\n";
678*9880d681SAndroid Build Coastguard Worker }
679*9880d681SAndroid Build Coastguard Worker }
680*9880d681SAndroid Build Coastguard Worker
681