llvm.org GIT mirror llvm / 44f97b9
[DebugInfo] Support DWARF expressions in eh_frame This patch enhances DWARFDebugFrame with the capability of parsing and printing DWARF expressions in CFI instructions. It also makes FDEs and CIEs accessible to lib users, so they can process them in client tools that rely on LLVM. To make it self-contained with a test case, it teaches llvm-readobj to be able to dump EH frames and checks they are correct in a unit test. The llvm-readobj code is Maksim Panchenko's work (maksfb). Reviewers: JDevlieghere, espindola Reviewed By: JDevlieghere Differential Revision: https://reviews.llvm.org/D43313 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@326932 91177308-0d34-0410-b5e6-96231b3b80d8 Rafael Auler 2 years ago
14 changed file(s) with 1020 addition(s) and 398 deletion(s). Raw diff Collapse all Expand all
4343 uint64_t getRelocatedAddress(uint32_t *Off, uint64_t *SecIx = nullptr) const {
4444 return getRelocatedValue(getAddressSize(), Off, SecIx);
4545 }
46
47 /// Extracts a DWARF-encoded pointer in \p Offset using \p Encoding.
48 /// There is a DWARF encoding that uses a PC-relative adjustment.
49 /// For these values, \p AbsPosOffset is used to fix them, which should
50 /// reflect the absolute address of this pointer.
51 Optional getEncodedPointer(uint32_t *Offset, uint8_t Encoding,
52 uint64_t AbsPosOffset = 0) const;
4653 };
4754
4855 } // end namespace llvm
99 #ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
1010 #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
1111
12 #include "llvm/Support/DataExtractor.h"
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/iterator.h"
14 #include "llvm/ADT/SmallString.h"
15 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
16 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
17 #include "llvm/Support/Error.h"
1318 #include
1419 #include
1520
1621 namespace llvm {
1722
18 class FrameEntry;
1923 class raw_ostream;
2024
21 /// \brief A parsed .debug_frame or .eh_frame section
22 ///
25 namespace dwarf {
26
27 /// Represent a sequence of Call Frame Information instructions that, when read
28 /// in order, construct a table mapping PC to frame state. This can also be
29 /// referred to as "CFI rules" in DWARF literature to avoid confusion with
30 /// computer programs in the broader sense, and in this context each instruction
31 /// would be a rule to establish the mapping. Refer to pg. 172 in the DWARF5
32 /// manual, "6.4.1 Structure of Call Frame Information".
33 class CFIProgram {
34 public:
35 typedef SmallVector Operands;
36
37 /// An instruction consists of a DWARF CFI opcode and an optional sequence of
38 /// operands. If it refers to an expression, then this expression has its own
39 /// sequence of operations and operands handled separately by DWARFExpression.
40 struct Instruction {
41 Instruction(uint8_t Opcode) : Opcode(Opcode) {}
42
43 uint8_t Opcode;
44 Operands Ops;
45 // Associated DWARF expression in case this instruction refers to one
46 Optional Expression;
47 };
48
49 using InstrList = std::vector;
50 using iterator = InstrList::iterator;
51 using const_iterator = InstrList::const_iterator;
52
53 iterator begin() { return Instructions.begin(); }
54 const_iterator begin() const { return Instructions.begin(); }
55 iterator end() { return Instructions.end(); }
56 const_iterator end() const { return Instructions.end(); }
57
58 unsigned size() const { return (unsigned)Instructions.size(); }
59 bool empty() const { return Instructions.empty(); }
60
61 CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor)
62 : CodeAlignmentFactor(CodeAlignmentFactor),
63 DataAlignmentFactor(DataAlignmentFactor) {}
64
65 /// Parse and store a sequence of CFI instructions from Data,
66 /// starting at *Offset and ending at EndOffset. *Offset is updated
67 /// to EndOffset upon successful parsing, or indicates the offset
68 /// where a problem occurred in case an error is returned.
69 Error parse(DataExtractor Data, uint32_t *Offset, uint32_t EndOffset);
70
71 void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
72 unsigned IndentLevel = 1) const;
73
74 private:
75 std::vector Instructions;
76 const uint64_t CodeAlignmentFactor;
77 const int64_t DataAlignmentFactor;
78
79 /// Convenience method to add a new instruction with the given opcode.
80 void addInstruction(uint8_t Opcode) {
81 Instructions.push_back(Instruction(Opcode));
82 }
83
84 /// Add a new single-operand instruction.
85 void addInstruction(uint8_t Opcode, uint64_t Operand1) {
86 Instructions.push_back(Instruction(Opcode));
87 Instructions.back().Ops.push_back(Operand1);
88 }
89
90 /// Add a new instruction that has two operands.
91 void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
92 Instructions.push_back(Instruction(Opcode));
93 Instructions.back().Ops.push_back(Operand1);
94 Instructions.back().Ops.push_back(Operand2);
95 }
96
97 /// Types of operands to CFI instructions
98 /// In DWARF, this type is implicitly tied to a CFI instruction opcode and
99 /// thus this type doesn't need to be explictly written to the file (this is
100 /// not a DWARF encoding). The relationship of instrs to operand types can
101 /// be obtained from getOperandTypes() and is only used to simplify
102 /// instruction printing.
103 enum OperandType {
104 OT_Unset,
105 OT_None,
106 OT_Address,
107 OT_Offset,
108 OT_FactoredCodeOffset,
109 OT_SignedFactDataOffset,
110 OT_UnsignedFactDataOffset,
111 OT_Register,
112 OT_Expression
113 };
114
115 /// Retrieve the array describing the types of operands according to the enum
116 /// above. This is indexed by opcode.
117 static ArrayRef getOperandTypes();
118
119 /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
120 void printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
121 const Instruction &Instr, unsigned OperandIdx,
122 uint64_t Operand) const;
123 };
124
125 /// An entry in either debug_frame or eh_frame. This entry can be a CIE or an
126 /// FDE.
127 class FrameEntry {
128 public:
129 enum FrameKind { FK_CIE, FK_FDE };
130
131 FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length, uint64_t CodeAlign,
132 int64_t DataAlign)
133 : Kind(K), Offset(Offset), Length(Length), CFIs(CodeAlign, DataAlign) {}
134
135 virtual ~FrameEntry() {}
136
137 FrameKind getKind() const { return Kind; }
138 uint64_t getOffset() const { return Offset; }
139 uint64_t getLength() const { return Length; }
140 const CFIProgram &cfis() const { return CFIs; }
141 CFIProgram &cfis() { return CFIs; }
142
143 /// Dump the instructions in this CFI fragment
144 virtual void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
145 bool IsEH) const = 0;
146
147 protected:
148 const FrameKind Kind;
149
150 /// Offset of this entry in the section.
151 const uint64_t Offset;
152
153 /// Entry length as specified in DWARF.
154 const uint64_t Length;
155
156 CFIProgram CFIs;
157 };
158
159 /// DWARF Common Information Entry (CIE)
160 class CIE : public FrameEntry {
161 public:
162 // CIEs (and FDEs) are simply container classes, so the only sensible way to
163 // create them is by providing the full parsed contents in the constructor.
164 CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
165 SmallString<8> Augmentation, uint8_t AddressSize,
166 uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor,
167 int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister,
168 SmallString<8> AugmentationData, uint32_t FDEPointerEncoding,
169 uint32_t LSDAPointerEncoding, Optional Personality,
170 Optional PersonalityEnc)
171 : FrameEntry(FK_CIE, Offset, Length, CodeAlignmentFactor,
172 DataAlignmentFactor),
173 Version(Version), Augmentation(std::move(Augmentation)),
174 AddressSize(AddressSize), SegmentDescriptorSize(SegmentDescriptorSize),
175 CodeAlignmentFactor(CodeAlignmentFactor),
176 DataAlignmentFactor(DataAlignmentFactor),
177 ReturnAddressRegister(ReturnAddressRegister),
178 AugmentationData(std::move(AugmentationData)),
179 FDEPointerEncoding(FDEPointerEncoding),
180 LSDAPointerEncoding(LSDAPointerEncoding), Personality(Personality),
181 PersonalityEnc(PersonalityEnc) {}
182
183 static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_CIE; }
184
185 StringRef getAugmentationString() const { return Augmentation; }
186 uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
187 int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
188 uint8_t getVersion() const { return Version; }
189 uint64_t getReturnAddressRegister() const { return ReturnAddressRegister; }
190 Optional getPersonalityAddress() const { return Personality; }
191 Optional getPersonalityEncoding() const { return PersonalityEnc; }
192
193 uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; }
194
195 uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; }
196
197 void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
198 bool IsEH) const override;
199
200 private:
201 /// The following fields are defined in section 6.4.1 of the DWARF standard v4
202 const uint8_t Version;
203 const SmallString<8> Augmentation;
204 const uint8_t AddressSize;
205 const uint8_t SegmentDescriptorSize;
206 const uint64_t CodeAlignmentFactor;
207 const int64_t DataAlignmentFactor;
208 const uint64_t ReturnAddressRegister;
209
210 // The following are used when the CIE represents an EH frame entry.
211 const SmallString<8> AugmentationData;
212 const uint32_t FDEPointerEncoding;
213 const uint32_t LSDAPointerEncoding;
214 const Optional Personality;
215 const Optional PersonalityEnc;
216 };
217
218 /// DWARF Frame Description Entry (FDE)
219 class FDE : public FrameEntry {
220 public:
221 // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
222 // an offset to the CIE (provided by parsing the FDE header). The CIE itself
223 // is obtained lazily once it's actually required.
224 FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
225 uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie,
226 Optional LSDAAddress)
227 : FrameEntry(FK_FDE, Offset, Length,
228 Cie ? Cie->getCodeAlignmentFactor() : 0,
229 Cie ? Cie->getDataAlignmentFactor() : 0),
230 LinkedCIEOffset(LinkedCIEOffset), InitialLocation(InitialLocation),
231 AddressRange(AddressRange), LinkedCIE(Cie), LSDAAddress(LSDAAddress) {}
232
233 ~FDE() override = default;
234
235 const CIE *getLinkedCIE() const { return LinkedCIE; }
236 uint64_t getInitialLocation() const { return InitialLocation; }
237 uint64_t getAddressRange() const { return AddressRange; }
238 Optional getLSDAAddress() const { return LSDAAddress; }
239
240 void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
241 bool IsEH) const override;
242
243 static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; }
244
245 private:
246 /// The following fields are defined in section 6.4.1 of the DWARF standard v3
247 const uint64_t LinkedCIEOffset;
248 const uint64_t InitialLocation;
249 const uint64_t AddressRange;
250 const CIE *LinkedCIE;
251 const Optional LSDAAddress;
252 };
253
254 } // end namespace dwarf
255
256 /// A parsed .debug_frame or .eh_frame section
23257 class DWARFDebugFrame {
24258 // True if this is parsing an eh_frame section.
25 bool IsEH;
26
27 public:
28 DWARFDebugFrame(bool IsEH);
259 const bool IsEH;
260 // Not zero for sane pointer values coming out of eh_frame
261 const uint64_t EHFrameAddress;
262
263 std::vector> Entries;
264 using iterator = pointee_iterator;
265
266 /// Return the entry at the given offset or nullptr.
267 dwarf::FrameEntry *getEntryAtOffset(uint64_t Offset) const;
268
269 public:
270 // If IsEH is true, assume it is a .eh_frame section. Otherwise,
271 // it is a .debug_frame section. EHFrameAddress should be different
272 // than zero for correct parsing of .eh_frame addresses when they
273 // use a PC-relative encoding.
274 DWARFDebugFrame(bool IsEH = false, uint64_t EHFrameAddress = 0);
29275 ~DWARFDebugFrame();
30276
31277 /// Dump the section data into the given stream.
32 void dump(raw_ostream &OS, Optional Offset) const;
33
34 /// \brief Parse the section from raw data.
35 /// data is assumed to be pointing to the beginning of the section.
36 void parse(DataExtractor Data);
278 void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
279 Optional Offset) const;
280
281 /// Parse the section from raw data. \p Data is assumed to contain the whole
282 /// frame section contents to be parsed.
283 void parse(DWARFDataExtractor Data);
37284
38285 /// Return whether the section has any entries.
39286 bool empty() const { return Entries.empty(); }
40287
41 /// Return the entry at the given offset or nullptr.
42 FrameEntry *getEntryAtOffset(uint64_t Offset) const;
43
44 private:
45 std::vector> Entries;
288 /// DWARF Frame entries accessors
289 iterator begin() const { return Entries.begin(); }
290 iterator end() const { return Entries.end(); }
291 iterator_range entries() const {
292 return iterator_range(Entries.begin(), Entries.end());
293 }
294
295 uint64_t getEHFrameAddress() const { return EHFrameAddress; }
46296 };
47297
48298 } // end namespace llvm
9292
9393 /// An iterator to go through the expression operations.
9494 class iterator
95 : public iterator_facade_base Operation> {
95 : public iterator_facade_base
96 Operation> {
9697 friend class DWARFExpression;
97 DWARFExpression *Expr;
98 const DWARFExpression *Expr;
9899 uint32_t Offset;
99100 Operation Op;
100 iterator(DWARFExpression *Expr, uint32_t Offset)
101 iterator(const DWARFExpression *Expr, uint32_t Offset)
101102 : Expr(Expr), Offset(Offset) {
102103 Op.Error =
103104 Offset >= Expr->Data.getData().size() ||
126127 assert(AddressSize == 8 || AddressSize == 4);
127128 }
128129
129 iterator begin() { return iterator(this, 0); }
130 iterator end() { return iterator(this, Data.getData().size()); }
130 iterator begin() const { return iterator(this, 0); }
131 iterator end() const { return iterator(this, Data.getData().size()); }
131132
132 void print(raw_ostream &OS, const MCRegisterInfo *RegInfo);
133 void print(raw_ostream &OS, const MCRegisterInfo *RegInfo,
134 bool IsEH = false) const;
133135
134136 private:
135137 DataExtractor Data;
7979
8080 void resetIndent() { IndentLevel = 0; }
8181
82 int getIndentLevel() { return IndentLevel; }
83
8284 void setPrefix(StringRef P) { Prefix = P; }
8385
8486 void printIndent() {
348348
349349 if (shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame,
350350 DObj->getDebugFrameSection()))
351 getDebugFrame()->dump(OS, DumpOffset);
351 getDebugFrame()->dump(OS, getRegisterInfo(), DumpOffset);
352352
353353 if (shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame,
354354 DObj->getEHFrameSection()))
355 getEHFrame()->dump(OS, DumpOffset);
355 getEHFrame()->dump(OS, getRegisterInfo(), DumpOffset);
356356
357357 if (DumpType & DIDT_DebugMacro) {
358358 if (Explicit || !getDebugMacro()->empty()) {
711711 // provides this information). This problem is fixed in DWARFv4
712712 // See this dwarf-discuss discussion for more details:
713713 // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html
714 DataExtractor debugFrameData(DObj->getDebugFrameSection(), isLittleEndian(),
715 DObj->getAddressSize());
714 DWARFDataExtractor debugFrameData(DObj->getDebugFrameSection(),
715 isLittleEndian(), DObj->getAddressSize());
716716 DebugFrame.reset(new DWARFDebugFrame(false /* IsEH */));
717717 DebugFrame->parse(debugFrameData);
718718 return DebugFrame.get();
722722 if (EHFrame)
723723 return EHFrame.get();
724724
725 DataExtractor debugFrameData(DObj->getEHFrameSection(), isLittleEndian(),
726 DObj->getAddressSize());
725 DWARFDataExtractor debugFrameData(DObj->getEHFrameSection(), isLittleEndian(),
726 DObj->getAddressSize());
727727 DebugFrame.reset(new DWARFDebugFrame(true /* IsEH */));
728728 DebugFrame->parse(debugFrameData);
729729 return DebugFrame.get();
77 //===----------------------------------------------------------------------===//
88
99 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
10 #include "llvm/BinaryFormat/Dwarf.h"
1011 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
1112
1213 using namespace llvm;
2425 *SecNdx = Rel->SectionIndex;
2526 return getUnsigned(Off, Size) + Rel->Value;
2627 }
28
29 Optional
30 DWARFDataExtractor::getEncodedPointer(uint32_t *Offset, uint8_t Encoding,
31 uint64_t PCRelOffset) const {
32 if (Encoding == dwarf::DW_EH_PE_omit)
33 return None;
34
35 uint64_t Result = 0;
36 uint32_t OldOffset = *Offset;
37 // First get value
38 switch (Encoding & 0x0F) {
39 case dwarf::DW_EH_PE_absptr:
40 switch (getAddressSize()) {
41 case 2:
42 case 4:
43 case 8:
44 Result = getUnsigned(Offset, getAddressSize());
45 break;
46 default:
47 return None;
48 }
49 break;
50 case dwarf::DW_EH_PE_uleb128:
51 Result = getULEB128(Offset);
52 break;
53 case dwarf::DW_EH_PE_sleb128:
54 Result = getSLEB128(Offset);
55 break;
56 case dwarf::DW_EH_PE_udata2:
57 Result = getUnsigned(Offset, 2);
58 break;
59 case dwarf::DW_EH_PE_udata4:
60 Result = getUnsigned(Offset, 4);
61 break;
62 case dwarf::DW_EH_PE_udata8:
63 Result = getUnsigned(Offset, 8);
64 break;
65 case dwarf::DW_EH_PE_sdata2:
66 Result = getSigned(Offset, 2);
67 break;
68 case dwarf::DW_EH_PE_sdata4:
69 Result = getSigned(Offset, 4);
70 break;
71 case dwarf::DW_EH_PE_sdata8:
72 Result = getSigned(Offset, 8);
73 break;
74 default:
75 return None;
76 }
77 // Then add relative offset, if required
78 switch (Encoding & 0x70) {
79 case dwarf::DW_EH_PE_absptr:
80 // do nothing
81 break;
82 case dwarf::DW_EH_PE_pcrel:
83 Result += PCRelOffset;
84 break;
85 case dwarf::DW_EH_PE_datarel:
86 case dwarf::DW_EH_PE_textrel:
87 case dwarf::DW_EH_PE_funcrel:
88 case dwarf::DW_EH_PE_aligned:
89 default:
90 *Offset = OldOffset;
91 return None;
92 }
93
94 return Result;
95 }
77 //===----------------------------------------------------------------------===//
88
99 #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
10 #include "llvm/ADT/ArrayRef.h"
1110 #include "llvm/ADT/DenseMap.h"
1211 #include "llvm/ADT/Optional.h"
13 #include "llvm/ADT/SmallString.h"
1412 #include "llvm/ADT/StringExtras.h"
1513 #include "llvm/ADT/StringRef.h"
1614 #include "llvm/BinaryFormat/Dwarf.h"
3028 using namespace llvm;
3129 using namespace dwarf;
3230
33 /// \brief Abstract frame entry defining the common interface concrete
34 /// entries implement.
35 class llvm::FrameEntry {
36 public:
37 enum FrameKind {FK_CIE, FK_FDE};
38
39 FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length)
40 : Kind(K), Offset(Offset), Length(Length) {}
41
42 virtual ~FrameEntry() = default;
43
44 FrameKind getKind() const { return Kind; }
45 virtual uint64_t getOffset() const { return Offset; }
46
47 /// Parse and store a sequence of CFI instructions from Data,
48 /// starting at *Offset and ending at EndOffset. If everything
49 /// goes well, *Offset should be equal to EndOffset when this method
50 /// returns. Otherwise, an error occurred.
51 virtual void parseInstructions(DataExtractor Data, uint32_t *Offset,
52 uint32_t EndOffset);
53
54 /// Dump the entry header to the given output stream.
55 virtual void dumpHeader(raw_ostream &OS) const = 0;
56
57 /// Dump the entry's instructions to the given output stream.
58 virtual void dumpInstructions(raw_ostream &OS) const;
59
60 /// Dump the entire entry to the given output stream.
61 void dump(raw_ostream &OS) const {
62 dumpHeader(OS);
63 dumpInstructions(OS);
64 OS << "\n";
65 }
66
67 protected:
68 const FrameKind Kind;
69
70 /// \brief Offset of this entry in the section.
71 uint64_t Offset;
72
73 /// \brief Entry length as specified in DWARF.
74 uint64_t Length;
75
76 /// An entry may contain CFI instructions. An instruction consists of an
77 /// opcode and an optional sequence of operands.
78 using Operands = std::vector;
79 struct Instruction {
80 Instruction(uint8_t Opcode)
81 : Opcode(Opcode)
82 {}
83
84 uint8_t Opcode;
85 Operands Ops;
86 };
87
88 std::vector Instructions;
89
90 /// Convenience methods to add a new instruction with the given opcode and
91 /// operands to the Instructions vector.
92 void addInstruction(uint8_t Opcode) {
93 Instructions.push_back(Instruction(Opcode));
94 }
95
96 void addInstruction(uint8_t Opcode, uint64_t Operand1) {
97 Instructions.push_back(Instruction(Opcode));
98 Instructions.back().Ops.push_back(Operand1);
99 }
100
101 void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
102 Instructions.push_back(Instruction(Opcode));
103 Instructions.back().Ops.push_back(Operand1);
104 Instructions.back().Ops.push_back(Operand2);
105 }
106 };
10731
10832 // See DWARF standard v3, section 7.23
10933 const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
11034 const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
11135
112 void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset,
113 uint32_t EndOffset) {
36 Error CFIProgram::parse(DataExtractor Data, uint32_t *Offset,
37 uint32_t EndOffset) {
11438 while (*Offset < EndOffset) {
11539 uint8_t Opcode = Data.getU8(Offset);
11640 // Some instructions have a primary opcode encoded in the top bits.
12145 // bits of the opcode itself.
12246 uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
12347 switch (Primary) {
124 default: llvm_unreachable("Impossible primary CFI opcode");
125 case DW_CFA_advance_loc:
126 case DW_CFA_restore:
127 addInstruction(Primary, Op1);
128 break;
129 case DW_CFA_offset:
130 addInstruction(Primary, Op1, Data.getULEB128(Offset));
131 break;
48 default:
49 return make_error(
50 "Invalid primary CFI opcode",
51 std::make_error_code(std::errc::illegal_byte_sequence));
52 case DW_CFA_advance_loc:
53 case DW_CFA_restore:
54 addInstruction(Primary, Op1);
55 break;
56 case DW_CFA_offset:
57 addInstruction(Primary, Op1, Data.getULEB128(Offset));
58 break;
13259 }
13360 } else {
13461 // Extended opcode - its value is Opcode itself.
13562 switch (Opcode) {
136 default: llvm_unreachable("Invalid extended CFI opcode");
137 case DW_CFA_nop:
138 case DW_CFA_remember_state:
139 case DW_CFA_restore_state:
140 case DW_CFA_GNU_window_save:
141 // No operands
142 addInstruction(Opcode);
143 break;
144 case DW_CFA_set_loc:
145 // Operands: Address
146 addInstruction(Opcode, Data.getAddress(Offset));
147 break;
148 case DW_CFA_advance_loc1:
149 // Operands: 1-byte delta
150 addInstruction(Opcode, Data.getU8(Offset));
151 break;
152 case DW_CFA_advance_loc2:
153 // Operands: 2-byte delta
154 addInstruction(Opcode, Data.getU16(Offset));
155 break;
156 case DW_CFA_advance_loc4:
157 // Operands: 4-byte delta
158 addInstruction(Opcode, Data.getU32(Offset));
159 break;
160 case DW_CFA_restore_extended:
161 case DW_CFA_undefined:
162 case DW_CFA_same_value:
163 case DW_CFA_def_cfa_register:
164 case DW_CFA_def_cfa_offset:
165 case DW_CFA_GNU_args_size:
166 // Operands: ULEB128
167 addInstruction(Opcode, Data.getULEB128(Offset));
168 break;
169 case DW_CFA_def_cfa_offset_sf:
170 // Operands: SLEB128
171 addInstruction(Opcode, Data.getSLEB128(Offset));
172 break;
173 case DW_CFA_offset_extended:
174 case DW_CFA_register:
175 case DW_CFA_def_cfa:
176 case DW_CFA_val_offset: {
177 // Operands: ULEB128, ULEB128
178 // Note: We can not embed getULEB128 directly into function
179 // argument list. getULEB128 changes Offset and order of evaluation
180 // for arguments is unspecified.
181 auto op1 = Data.getULEB128(Offset);
182 auto op2 = Data.getULEB128(Offset);
183 addInstruction(Opcode, op1, op2);
184 break;
63 default:
64 return make_error(
65 "Invalid extended CFI opcode",
66 std::make_error_code(std::errc::illegal_byte_sequence));
67 case DW_CFA_nop:
68 case DW_CFA_remember_state:
69 case DW_CFA_restore_state:
70 case DW_CFA_GNU_window_save:
71 // No operands
72 addInstruction(Opcode);
73 break;
74 case DW_CFA_set_loc:
75 // Operands: Address
76 addInstruction(Opcode, Data.getAddress(Offset));
77 break;
78 case DW_CFA_advance_loc1:
79 // Operands: 1-byte delta
80 addInstruction(Opcode, Data.getU8(Offset));
81 break;
82 case DW_CFA_advance_loc2:
83 // Operands: 2-byte delta
84 addInstruction(Opcode, Data.getU16(Offset));
85 break;
86 case DW_CFA_advance_loc4:
87 // Operands: 4-byte delta
88 addInstruction(Opcode, Data.getU32(Offset));
89 break;
90 case DW_CFA_restore_extended:
91 case DW_CFA_undefined:
92 case DW_CFA_same_value:
93 case DW_CFA_def_cfa_register:
94 case DW_CFA_def_cfa_offset:
95 case DW_CFA_GNU_args_size:
96 // Operands: ULEB128
97 addInstruction(Opcode, Data.getULEB128(Offset));
98 break;
99 case DW_CFA_def_cfa_offset_sf:
100 // Operands: SLEB128
101 addInstruction(Opcode, Data.getSLEB128(Offset));
102 break;
103 case DW_CFA_offset_extended:
104 case DW_CFA_register:
105 case DW_CFA_def_cfa:
106 case DW_CFA_val_offset: {
107 // Operands: ULEB128, ULEB128
108 // Note: We can not embed getULEB128 directly into function
109 // argument list. getULEB128 changes Offset and order of evaluation
110 // for arguments is unspecified.
111 auto op1 = Data.getULEB128(Offset);
112 auto op2 = Data.getULEB128(Offset);
113 addInstruction(Opcode, op1, op2);
114 break;
185115 }
186116 case DW_CFA_offset_extended_sf:
187117 case DW_CFA_def_cfa_sf:
193123 addInstruction(Opcode, op1, op2);
194124 break;
195125 }
196 case DW_CFA_def_cfa_expression:
197 // FIXME: Parse the actual instruction.
198 *Offset += Data.getULEB128(Offset);
126 case DW_CFA_def_cfa_expression: {
127 uint32_t ExprLength = Data.getULEB128(Offset);
128 addInstruction(Opcode, 0);
129 DataExtractor Extractor(
130 Data.getData().slice(*Offset, *Offset + ExprLength),
131 Data.isLittleEndian(), Data.getAddressSize());
132 Instructions.back().Expression = DWARFExpression(
133 Extractor, Data.getAddressSize(), dwarf::DWARF_VERSION);
134 *Offset += ExprLength;
199135 break;
136 }
200137 case DW_CFA_expression:
201138 case DW_CFA_val_expression: {
202 // FIXME: Parse the actual instruction.
203 Data.getULEB128(Offset);
204 *Offset += Data.getULEB128(Offset);
139 auto RegNum = Data.getULEB128(Offset);
140 auto BlockLength = Data.getULEB128(Offset);
141 addInstruction(Opcode, RegNum, 0);
142 DataExtractor Extractor(
143 Data.getData().slice(*Offset, *Offset + BlockLength),
144 Data.isLittleEndian(), Data.getAddressSize());
145 Instructions.back().Expression = DWARFExpression(
146 Extractor, Data.getAddressSize(), dwarf::DWARF_VERSION);
147 *Offset += BlockLength;
205148 break;
206149 }
207150 }
208151 }
209152 }
153
154 return Error::success();
210155 }
211156
212157 namespace {
213158
214 /// \brief DWARF Common Information Entry (CIE)
215 class CIE : public FrameEntry {
216 public:
217 // CIEs (and FDEs) are simply container classes, so the only sensible way to
218 // create them is by providing the full parsed contents in the constructor.
219 CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
220 SmallString<8> Augmentation, uint8_t AddressSize,
221 uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor,
222 int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister,
223 SmallString<8> AugmentationData, uint32_t FDEPointerEncoding,
224 uint32_t LSDAPointerEncoding)
225 : FrameEntry(FK_CIE, Offset, Length), Version(Version),
226 Augmentation(std::move(Augmentation)), AddressSize(AddressSize),
227 SegmentDescriptorSize(SegmentDescriptorSize),
228 CodeAlignmentFactor(CodeAlignmentFactor),
229 DataAlignmentFactor(DataAlignmentFactor),
230 ReturnAddressRegister(ReturnAddressRegister),
231 AugmentationData(std::move(AugmentationData)),
232 FDEPointerEncoding(FDEPointerEncoding),
233 LSDAPointerEncoding(LSDAPointerEncoding) {}
234
235 ~CIE() override = default;
236
237 StringRef getAugmentationString() const { return Augmentation; }
238 uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
239 int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
240
241 uint32_t getFDEPointerEncoding() const {
242 return FDEPointerEncoding;
243 }
244
245 uint32_t getLSDAPointerEncoding() const {
246 return LSDAPointerEncoding;
247 }
248
249 void dumpHeader(raw_ostream &OS) const override {
250 OS << format("%08x %08x %08x CIE",
251 (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID)
252 << "\n";
253 OS << format(" Version: %d\n", Version);
254 OS << " Augmentation: \"" << Augmentation << "\"\n";
255 if (Version >= 4) {
256 OS << format(" Address size: %u\n",
257 (uint32_t)AddressSize);
258 OS << format(" Segment desc size: %u\n",
259 (uint32_t)SegmentDescriptorSize);
260 }
261 OS << format(" Code alignment factor: %u\n",
262 (uint32_t)CodeAlignmentFactor);
263 OS << format(" Data alignment factor: %d\n",
264 (int32_t)DataAlignmentFactor);
265 OS << format(" Return address column: %d\n",
266 (int32_t)ReturnAddressRegister);
267 if (!AugmentationData.empty()) {
268 OS << " Augmentation data: ";
269 for (uint8_t Byte : AugmentationData)
270 OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf);
271 OS << "\n";
272 }
273 OS << "\n";
274 }
275
276 static bool classof(const FrameEntry *FE) {
277 return FE->getKind() == FK_CIE;
278 }
279
280 private:
281 /// The following fields are defined in section 6.4.1 of the DWARF standard v4
282 uint8_t Version;
283 SmallString<8> Augmentation;
284 uint8_t AddressSize;
285 uint8_t SegmentDescriptorSize;
286 uint64_t CodeAlignmentFactor;
287 int64_t DataAlignmentFactor;
288 uint64_t ReturnAddressRegister;
289
290 // The following are used when the CIE represents an EH frame entry.
291 SmallString<8> AugmentationData;
292 uint32_t FDEPointerEncoding;
293 uint32_t LSDAPointerEncoding;
294 };
295
296 /// \brief DWARF Frame Description Entry (FDE)
297 class FDE : public FrameEntry {
298 public:
299 // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
300 // an offset to the CIE (provided by parsing the FDE header). The CIE itself
301 // is obtained lazily once it's actually required.
302 FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
303 uint64_t InitialLocation, uint64_t AddressRange,
304 CIE *Cie)
305 : FrameEntry(FK_FDE, Offset, Length), LinkedCIEOffset(LinkedCIEOffset),
306 InitialLocation(InitialLocation), AddressRange(AddressRange),
307 LinkedCIE(Cie) {}
308
309 ~FDE() override = default;
310
311 CIE *getLinkedCIE() const { return LinkedCIE; }
312
313 void dumpHeader(raw_ostream &OS) const override {
314 OS << format("%08x %08x %08x FDE ",
315 (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset);
316 OS << format("cie=%08x pc=%08x...%08x\n",
317 (int32_t)LinkedCIEOffset,
318 (uint32_t)InitialLocation,
319 (uint32_t)InitialLocation + (uint32_t)AddressRange);
320 }
321
322 static bool classof(const FrameEntry *FE) {
323 return FE->getKind() == FK_FDE;
324 }
325
326 private:
327 /// The following fields are defined in section 6.4.1 of the DWARF standard v3
328 uint64_t LinkedCIEOffset;
329 uint64_t InitialLocation;
330 uint64_t AddressRange;
331 CIE *LinkedCIE;
332 };
333
334 /// \brief Types of operands to CF instructions.
335 enum OperandType {
336 OT_Unset,
337 OT_None,
338 OT_Address,
339 OT_Offset,
340 OT_FactoredCodeOffset,
341 OT_SignedFactDataOffset,
342 OT_UnsignedFactDataOffset,
343 OT_Register,
344 OT_Expression
345 };
346159
347160 } // end anonymous namespace
348161
349 /// \brief Initialize the array describing the types of operands.
350 static ArrayRef getOperandTypes() {
162 ArrayRef CFIProgram::getOperandTypes() {
351163 static OperandType OpTypes[DW_CFA_restore+1][2];
164 static bool Initialized = false;
165 if (Initialized) {
166 return ArrayRef(&OpTypes[0], DW_CFA_restore+1);
167 }
168 Initialized = true;
352169
353170 #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \
354171 do { \
395212 return ArrayRef(&OpTypes[0], DW_CFA_restore+1);
396213 }
397214
398 static ArrayRef OpTypes = getOperandTypes();
399
400 /// \brief Print \p Opcode's operand number \p OperandIdx which has
401 /// value \p Operand.
402 static void printOperand(raw_ostream &OS, uint8_t Opcode, unsigned OperandIdx,
403 uint64_t Operand, uint64_t CodeAlignmentFactor,
404 int64_t DataAlignmentFactor) {
215 /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
216 void CFIProgram::printOperand(raw_ostream &OS, const MCRegisterInfo *MRI,
217 bool IsEH, const Instruction &Instr,
218 unsigned OperandIdx, uint64_t Operand) const {
405219 assert(OperandIdx < 2);
406 OperandType Type = OpTypes[Opcode][OperandIdx];
220 uint8_t Opcode = Instr.Opcode;
221 OperandType Type = getOperandTypes()[Opcode][OperandIdx];
407222
408223 switch (Type) {
409224 case OT_Unset: {
448263 OS << format(" reg%" PRId64, Operand);
449264 break;
450265 case OT_Expression:
451 OS << " expression";
452 break;
453 }
454 }
455
456 void FrameEntry::dumpInstructions(raw_ostream &OS) const {
457 uint64_t CodeAlignmentFactor = 0;
458 int64_t DataAlignmentFactor = 0;
459 const CIE *Cie = dyn_cast(this);
460
461 if (!Cie)
462 Cie = cast(this)->getLinkedCIE();
463 if (Cie) {
464 CodeAlignmentFactor = Cie->getCodeAlignmentFactor();
465 DataAlignmentFactor = Cie->getDataAlignmentFactor();
466 }
467
266 assert(Instr.Expression && "missing DWARFExpression object");
267 OS << " ";
268 Instr.Expression->print(OS, MRI, IsEH);
269 break;
270 }
271 }
272
273 void CFIProgram::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
274 unsigned IndentLevel) const {
468275 for (const auto &Instr : Instructions) {
469276 uint8_t Opcode = Instr.Opcode;
470277 if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
471278 Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
472 OS << " " << CallFrameString(Opcode) << ":";
279 OS.indent(2 * IndentLevel);
280 OS << CallFrameString(Opcode) << ":";
473281 for (unsigned i = 0; i < Instr.Ops.size(); ++i)
474 printOperand(OS, Opcode, i, Instr.Ops[i], CodeAlignmentFactor,
475 DataAlignmentFactor);
282 printOperand(OS, MRI, IsEH, Instr, i, Instr.Ops[i]);
476283 OS << '\n';
477284 }
478285 }
479286
480 DWARFDebugFrame::DWARFDebugFrame(bool IsEH) : IsEH(IsEH) {}
287 void CIE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const {
288 OS << format("%08x %08x %08x CIE", (uint32_t)Offset, (uint32_t)Length,
289 DW_CIE_ID)
290 << "\n";
291 OS << format(" Version: %d\n", Version);
292 OS << " Augmentation: \"" << Augmentation << "\"\n";
293 if (Version >= 4) {
294 OS << format(" Address size: %u\n", (uint32_t)AddressSize);
295 OS << format(" Segment desc size: %u\n",
296 (uint32_t)SegmentDescriptorSize);
297 }
298 OS << format(" Code alignment factor: %u\n", (uint32_t)CodeAlignmentFactor);
299 OS << format(" Data alignment factor: %d\n", (int32_t)DataAlignmentFactor);
300 OS << format(" Return address column: %d\n", (int32_t)ReturnAddressRegister);
301 if (Personality)
302 OS << format(" Personality Address: %08x\n", *Personality);
303 if (!AugmentationData.empty()) {
304 OS << " Augmentation data: ";
305 for (uint8_t Byte : AugmentationData)
306 OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf);
307 OS << "\n";
308 }
309 OS << "\n";
310 CFIs.dump(OS, MRI, IsEH);
311 OS << "\n";
312 }
313
314 void FDE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const {
315 OS << format("%08x %08x %08x FDE ", (uint32_t)Offset, (uint32_t)Length,
316 (int32_t)LinkedCIEOffset);
317 OS << format("cie=%08x pc=%08x...%08x\n", (int32_t)LinkedCIEOffset,
318 (uint32_t)InitialLocation,
319 (uint32_t)InitialLocation + (uint32_t)AddressRange);
320 if (LSDAAddress)
321 OS << format(" LSDA Address: %08x\n", *LSDAAddress);
322 CFIs.dump(OS, MRI, IsEH);
323 OS << "\n";
324 }
325
326 DWARFDebugFrame::DWARFDebugFrame(bool IsEH, uint64_t EHFrameAddress)
327 : IsEH(IsEH), EHFrameAddress(EHFrameAddress) {}
481328
482329 DWARFDebugFrame::~DWARFDebugFrame() = default;
483330
489336 errs().write_hex(c); errs() << " ";
490337 }
491338 errs() << "\n";
492 }
493
494 static unsigned getSizeForEncoding(const DataExtractor &Data,
495 unsigned symbolEncoding) {
496 unsigned format = symbolEncoding & 0x0f;
497 switch (format) {
498 default: llvm_unreachable("Unknown Encoding");
499 case DW_EH_PE_absptr:
500 case DW_EH_PE_signed:
501 return Data.getAddressSize();
502 case DW_EH_PE_udata2:
503 case DW_EH_PE_sdata2:
504 return 2;
505 case DW_EH_PE_udata4:
506 case DW_EH_PE_sdata4:
507 return 4;
508 case DW_EH_PE_udata8:
509 case DW_EH_PE_sdata8:
510 return 8;
511 }
512 }
513
514 static uint64_t readPointer(const DataExtractor &Data, uint32_t &Offset,
515 unsigned Encoding) {
516 switch (getSizeForEncoding(Data, Encoding)) {
517 case 2:
518 return Data.getU16(&Offset);
519 case 4:
520 return Data.getU32(&Offset);
521 case 8:
522 return Data.getU64(&Offset);
523 default:
524 llvm_unreachable("Illegal data size");
525 }
526339 }
527340
528341 // This is a workaround for old compilers which do not allow
538351 report_fatal_error(Str);
539352 }
540353
541 void DWARFDebugFrame::parse(DataExtractor Data) {
354 void DWARFDebugFrame::parse(DWARFDataExtractor Data) {
542355 uint32_t Offset = 0;
543356 DenseMap CIEs;
544357
568381
569382 // The Id field's size depends on the DWARF format
570383 Id = Data.getUnsigned(&Offset, (IsDWARF64 && !IsEH) ? 8 : 4);
571 bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) ||
572 Id == DW_CIE_ID ||
573 (IsEH && !Id));
384 bool IsCIE =
385 ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID || (IsEH && !Id));
574386
575387 if (IsCIE) {
576388 uint8_t Version = Data.getU8(&Offset);
588400 StringRef AugmentationData("");
589401 uint32_t FDEPointerEncoding = DW_EH_PE_omit;
590402 uint32_t LSDAPointerEncoding = DW_EH_PE_omit;
403 Optional Personality;
404 Optional PersonalityEncoding;
591405 if (IsEH) {
592 Optional PersonalityEncoding;
593 Optional Personality;
594
595406 Optional AugmentationLength;
596407 uint32_t StartAugmentationOffset;
597408 uint32_t EndAugmentationOffset;
610421 ReportError(StartOffset,
611422 "Duplicate personality in entry at %lx");
612423 PersonalityEncoding = Data.getU8(&Offset);
613 Personality = readPointer(Data, Offset, *PersonalityEncoding);
424 Personality = Data.getEncodedPointer(
425 &Offset, *PersonalityEncoding,
426 EHFrameAddress ? EHFrameAddress + Offset : 0);
614427 break;
615428 }
616429 case 'R':
638451 }
639452 }
640453
641 auto Cie = llvm::make_unique(StartOffset, Length, Version,
642 AugmentationString, AddressSize,
643 SegmentDescriptorSize,
644 CodeAlignmentFactor,
645 DataAlignmentFactor,
646 ReturnAddressRegister,
647 AugmentationData, FDEPointerEncoding,
648 LSDAPointerEncoding);
454 auto Cie = llvm::make_unique(
455 StartOffset, Length, Version, AugmentationString, AddressSize,
456 SegmentDescriptorSize, CodeAlignmentFactor, DataAlignmentFactor,
457 ReturnAddressRegister, AugmentationData, FDEPointerEncoding,
458 LSDAPointerEncoding, Personality, PersonalityEncoding);
649459 CIEs[StartOffset] = Cie.get();
650460 Entries.emplace_back(std::move(Cie));
651461 } else {
653463 uint64_t CIEPointer = Id;
654464 uint64_t InitialLocation = 0;
655465 uint64_t AddressRange = 0;
466 Optional LSDAAddress;
656467 CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer];
657468
658469 if (IsEH) {
661472 ReportError(StartOffset,
662473 "Parsing FDE data at %lx failed due to missing CIE");
663474
664 InitialLocation = readPointer(Data, Offset,
665 Cie->getFDEPointerEncoding());
666 AddressRange = readPointer(Data, Offset,
667 Cie->getFDEPointerEncoding());
475 if (auto Val = Data.getEncodedPointer(
476 &Offset, Cie->getFDEPointerEncoding(),
477 EHFrameAddress ? EHFrameAddress + Offset : 0)) {
478 InitialLocation = *Val;
479 }
480 if (auto Val = Data.getEncodedPointer(
481 &Offset, Cie->getFDEPointerEncoding(), 0)) {
482 AddressRange = *Val;
483 }
668484
669485 StringRef AugmentationString = Cie->getAugmentationString();
670486 if (!AugmentationString.empty()) {
675491 Offset + static_cast(AugmentationLength);
676492
677493 // Decode the LSDA if the CIE augmentation string said we should.
678 if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit)
679 readPointer(Data, Offset, Cie->getLSDAPointerEncoding());
494 if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) {
495 LSDAAddress = Data.getEncodedPointer(
496 &Offset, Cie->getLSDAPointerEncoding(),
497 EHFrameAddress ? Offset + EHFrameAddress : 0);
498 }
680499
681500 if (Offset != EndAugmentationOffset)
682501 ReportError(StartOffset, "Parsing augmentation data at %lx failed");
688507
689508 Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,
690509 InitialLocation, AddressRange,
691 Cie));
510 Cie, LSDAAddress));
692511 }
693512
694 Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);
513 if (Error E =
514 Entries.back()->cfis().parse(Data, &Offset, EndStructureOffset)) {
515 report_fatal_error(toString(std::move(E)));
516 }
695517
696518 if (Offset != EndStructureOffset)
697519 ReportError(StartOffset, "Parsing entry instructions at %lx failed");
708530 return nullptr;
709531 }
710532
711 void DWARFDebugFrame::dump(raw_ostream &OS, Optional Offset) const {
533 void DWARFDebugFrame::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
534 Optional Offset) const {
712535 if (Offset) {
713536 if (auto *Entry = getEntryAtOffset(*Offset))
714 Entry->dump(OS);
537 Entry->dump(OS, MRI, IsEH);
715538 return;
716539 }
717540
718541 OS << "\n";
719542 for (const auto &Entry : Entries)
720 Entry->dump(OS);
721 }
543 Entry->dump(OS, MRI, IsEH);
544 }
257257 return true;
258258 }
259259
260 void DWARFExpression::print(raw_ostream &OS, const MCRegisterInfo *RegInfo) {
260 void DWARFExpression::print(raw_ostream &OS, const MCRegisterInfo *RegInfo,
261 bool IsEH) const {
261262 for (auto &Op : *this) {
262 if (!Op.print(OS, this, RegInfo, /* isEH */ false)) {
263 if (!Op.print(OS, this, RegInfo, IsEH)) {
263264 uint32_t FailOffset = Op.getEndOffset();
264265 while (FailOffset < Data.getData().size())
265266 OS << format(" %02x", Data.getU8(&FailOffset));
4949 ECase(PT_SHLIB);
5050 ECase(PT_PHDR);
5151 ECase(PT_TLS);
52 ECase(PT_GNU_EH_FRAME);
5253 #undef ECase
5354 IO.enumFallback(Value);
5455 }
0 --- !ELF
1 FileHeader:
2 Class: ELFCLASS64
3 Data: ELFDATA2LSB
4 Type: ET_EXEC
5 Machine: EM_X86_64
6 Entry: 0x0000000000400000
7 Sections:
8 - Name: .text
9 Type: SHT_PROGBITS
10 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
11 Address: 0x0000000000400000
12 AddressAlign: 16
13 Content: 50C704240020400031C05AC3
14 - Name: .eh_frame_hdr
15 Type: SHT_PROGBITS
16 Flags: [ SHF_ALLOC ]
17 Address: 0x00000000004013c0
18 AddressAlign: 4
19 Content: 011B033B3C00000006000000E0F0FFFF8800000010F1FFFF58000000F6F1FFFFB000000010F2FFFFD000000090FEFFFF0001000000FFFFFF30010000
20 - Name: .eh_frame
21 Type: SHT_PROGBITS
22 Flags: [ SHF_ALLOC ]
23 Address: 0x0000000000401400
24 AddressAlign: 8
25 Content: 1400000000000000017A5200017810011B0C070890010710140000001C000000B0F0FFFF2A00000000000000000000001400000000000000017A5200017810011B0C070890010000240000001C00000050F0FFFF20000000000E10460E184A0F0B770880003F1A3B2A332422000000001C000000440000003EF1FFFF1000000000410E108602430D064B0C07080000002C0000006400000038F1FFFF7F0C000000450C0A00491006027600450F0376780603660C0C0A00450C070800000000002C0000009400000088FDFFFF6600000000410E108602430D06428F03458E04478D058C06488307024B0C07080000000014000000C4000000C8FDFFFF01000000000000000000000000000000
26 Symbols:
27 Global:
28 - Name: myfunc
29 Type: STT_FUNC
30 Section: .text
31 Value: 0x0000000000400000
32 ProgramHeaders:
33 - Type: PT_LOAD
34 Flags: [ PF_X, PF_R ]
35 VAddr: 0x00400000
36 PAddr: 0x00400000
37 Sections:
38 - Section: .text
39 - Type: PT_GNU_EH_FRAME
40 Flags: [ PF_X, PF_R ]
41 VAddr: 0x004013C0
42 PAddr: 0x004013C0
43 Sections:
44 - Section: .eh_frame_hdr
45 ...
0 RUN: yaml2obj %p/Inputs/dwarf-exprs.exe-x86-64.yaml > %t.exe
1 RUN: llvm-readobj -unwind %t.exe | FileCheck %s
2
3 CHECK: EH_FRAME Header [
4 CHECK-NEXT: Address: 0x4013c0
5 CHECK-NEXT: Offset: 0x27c
6 CHECK-NEXT: Size: 0x3c
7 CHECK-NEXT: Corresponding Section: .eh_frame_hdr
8 CHECK-NEXT: Header {
9 CHECK-NEXT: version: 1
10 CHECK-NEXT: eh_frame_ptr_enc: 0x1b
11 CHECK-NEXT: fde_count_enc: 0x3
12 CHECK-NEXT: table_enc: 0x3b
13 CHECK-NEXT: eh_frame_ptr: 0x401400
14 CHECK-NEXT: fde_count: 6
15 CHECK-NEXT: entry 0 {
16 CHECK-NEXT: initial_location: 0x4004a0
17 CHECK-NEXT: address: 0x401448
18 CHECK-NEXT: }
19 CHECK-NEXT: entry 1 {
20 CHECK-NEXT: initial_location: 0x4004d0
21 CHECK-NEXT: address: 0x401418
22 CHECK-NEXT: }
23 CHECK-NEXT: entry 2 {
24 CHECK-NEXT: initial_location: 0x4005b6
25 CHECK-NEXT: address: 0x401470
26 CHECK-NEXT: }
27 CHECK-NEXT: entry 3 {
28 CHECK-NEXT: initial_location: 0x4005d0
29 CHECK-NEXT: address: 0x401490
30 CHECK-NEXT: }
31 CHECK-NEXT: entry 4 {
32 CHECK-NEXT: initial_location: 0x401250
33 CHECK-NEXT: address: 0x4014c0
34 CHECK-NEXT: }
35 CHECK-NEXT: entry 5 {
36 CHECK-NEXT: initial_location: 0x4012c0
37 CHECK-NEXT: address: 0x4014f0
38 CHECK-NEXT: }
39 CHECK-NEXT: }
40 CHECK-NEXT:]
41
42 CHECK: .eh_frame section at offset 0x2b8 address 0x401400:
43 CHECK-NEXT: [0x401400] CIE length=20
44 CHECK-NEXT: version: 1
45 CHECK-NEXT: augmentation: zR
46 CHECK-NEXT: code_alignment_factor: 1
47 CHECK-NEXT: data_alignment_factor: -8
48 CHECK-NEXT: return_address_register: 16
49
50 CHECK: Program:
51 CHECK-NEXT: DW_CFA_def_cfa: reg7 +8
52 CHECK-NEXT: DW_CFA_offset: reg16 -8
53 CHECK-NEXT: DW_CFA_undefined: reg16
54
55 CHECK: [0x401418] FDE length=20 cie=[0x401400]
56 CHECK-NEXT: initial_location: 0x4004d0
57 CHECK-NEXT: address_range: 0x2a (end : 0x4004fa)
58
59 CHECK: Program:
60 CHECK-NEXT: DW_CFA_nop:
61 CHECK-NEXT: DW_CFA_nop:
62 CHECK-NEXT: DW_CFA_nop:
63 CHECK-NEXT: DW_CFA_nop:
64 CHECK-NEXT: DW_CFA_nop:
65 CHECK-NEXT: DW_CFA_nop:
66 CHECK-NEXT: DW_CFA_nop:
67
68 CHECK: [0x401430] CIE length=20
69 CHECK-NEXT: version: 1
70 CHECK-NEXT: augmentation: zR
71 CHECK-NEXT: code_alignment_factor: 1
72 CHECK-NEXT: data_alignment_factor: -8
73 CHECK-NEXT: return_address_register: 16
74
75 CHECK: Program:
76 CHECK-NEXT: DW_CFA_def_cfa: reg7 +8
77 CHECK-NEXT: DW_CFA_offset: reg16 -8
78 CHECK-NEXT: DW_CFA_nop:
79 CHECK-NEXT: DW_CFA_nop:
80
81 CHECK: [0x401448] FDE length=36 cie=[0x401430]
82 CHECK-NEXT: initial_location: 0x4004a0
83 CHECK-NEXT: address_range: 0x20 (end : 0x4004c0)
84
85 CHECK: Program:
86 CHECK-NEXT: DW_CFA_def_cfa_offset: +16
87 CHECK-NEXT: DW_CFA_advance_loc: 6
88 CHECK-NEXT: DW_CFA_def_cfa_offset: +24
89 CHECK-NEXT: DW_CFA_advance_loc: 10
90 CHECK-NEXT: DW_CFA_def_cfa_expression: DW_OP_breg7 +8, DW_OP_breg16 +0, DW_OP_lit15, DW_OP_and, DW_OP_lit11, DW_OP_ge, DW_OP_lit3, DW_OP_shl, DW_OP_plus
91 CHECK-NEXT: DW_CFA_nop:
92 CHECK-NEXT: DW_CFA_nop:
93 CHECK-NEXT: DW_CFA_nop:
94 CHECK-NEXT: DW_CFA_nop:
95
96 CHECK: [0x401470] FDE length=28 cie=[0x401430]
97 CHECK-NEXT: initial_location: 0x4005b6
98 CHECK-NEXT: address_range: 0x10 (end : 0x4005c6)
99
100 CHECK: Program:
101 CHECK-NEXT: DW_CFA_advance_loc: 1
102 CHECK-NEXT: DW_CFA_def_cfa_offset: +16
103 CHECK-NEXT: DW_CFA_offset: reg6 -16
104 CHECK-NEXT: DW_CFA_advance_loc: 3
105 CHECK-NEXT: DW_CFA_def_cfa_register: reg6
106 CHECK-NEXT: DW_CFA_advance_loc: 11
107 CHECK-NEXT: DW_CFA_def_cfa: reg7 +8
108 CHECK-NEXT: DW_CFA_nop:
109 CHECK-NEXT: DW_CFA_nop:
110 CHECK-NEXT: DW_CFA_nop:
111
112 CHECK: [0x401490] FDE length=44 cie=[0x401430]
113 CHECK-NEXT: initial_location: 0x4005d0
114 CHECK-NEXT: address_range: 0xc7f (end : 0x40124f)
115
116 CHECK: Program:
117 CHECK-NEXT: DW_CFA_advance_loc: 5
118 CHECK-NEXT: DW_CFA_def_cfa: reg10 +0
119 CHECK-NEXT: DW_CFA_advance_loc: 9
120 CHECK-NEXT: DW_CFA_expression: reg6 DW_OP_breg6 +0
121 CHECK-NEXT: DW_CFA_advance_loc: 5
122 CHECK-NEXT: DW_CFA_def_cfa_expression: DW_OP_breg6 -8, DW_OP_deref
123 CHECK-NEXT: DW_CFA_advance_loc2: 3174
124 CHECK-NEXT: DW_CFA_def_cfa: reg10 +0
125 CHECK-NEXT: DW_CFA_advance_loc: 5
126 CHECK-NEXT: DW_CFA_def_cfa: reg7 +8
127 CHECK-NEXT: DW_CFA_nop:
128 CHECK-NEXT: DW_CFA_nop:
129 CHECK-NEXT: DW_CFA_nop:
130 CHECK-NEXT: DW_CFA_nop:
131
132 CHECK: [0x4014c0] FDE length=44 cie=[0x401430]
133 CHECK-NEXT: initial_location: 0x401250
134 CHECK-NEXT: address_range: 0x66 (end : 0x4012b6)
135
136 CHECK: Program:
137 CHECK-NEXT: DW_CFA_advance_loc: 1
138 CHECK-NEXT: DW_CFA_def_cfa_offset: +16
139 CHECK-NEXT: DW_CFA_offset: reg6 -16
140 CHECK-NEXT: DW_CFA_advance_loc: 3
141 CHECK-NEXT: DW_CFA_def_cfa_register: reg6
142 CHECK-NEXT: DW_CFA_advance_loc: 2
143 CHECK-NEXT: DW_CFA_offset: reg15 -24
144 CHECK-NEXT: DW_CFA_advance_loc: 5
145 CHECK-NEXT: DW_CFA_offset: reg14 -32
146 CHECK-NEXT: DW_CFA_advance_loc: 7
147 CHECK-NEXT: DW_CFA_offset: reg13 -40
148 CHECK-NEXT: DW_CFA_offset: reg12 -48
149 CHECK-NEXT: DW_CFA_advance_loc: 8
150 CHECK-NEXT: DW_CFA_offset: reg3 -56
151 CHECK-NEXT: DW_CFA_advance_loc1: 75
152 CHECK-NEXT: DW_CFA_def_cfa: reg7 +8
153 CHECK-NEXT: DW_CFA_nop:
154 CHECK-NEXT: DW_CFA_nop:
155 CHECK-NEXT: DW_CFA_nop:
156 CHECK-NEXT: DW_CFA_nop:
157
158 CHECK: [0x4014f0] FDE length=20 cie=[0x401430]
159 CHECK-NEXT: initial_location: 0x4012c0
160 CHECK-NEXT: address_range: 0x1 (end : 0x4012c1)
161
162 CHECK: Program:
163 CHECK-NEXT: DW_CFA_nop:
164 CHECK-NEXT: DW_CFA_nop:
165 CHECK-NEXT: DW_CFA_nop:
166 CHECK-NEXT: DW_CFA_nop:
167 CHECK-NEXT: DW_CFA_nop:
168 CHECK-NEXT: DW_CFA_nop:
169 CHECK-NEXT: DW_CFA_nop:
0 set(LLVM_LINK_COMPONENTS
11 DebugInfoCodeView
2 DebugInfoDWARF
23 Object
34 BinaryFormat
45 Support
0 //===--- DwarfCFIEHPrinter.h - DWARF-based Unwind Information Printer -----===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_TOOLS_LLVM_READOBJ_DWARFCFIEHPRINTER_H
10 #define LLVM_TOOLS_LLVM_READOBJ_DWARFCFIEHPRINTER_H
11
12 #include "Error.h"
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/BinaryFormat/Dwarf.h"
15 #include "llvm/Object/ELF.h"
16 #include "llvm/Object/ELFTypes.h"
17 #include "llvm/Support/Casting.h"
18 #include "llvm/Support/ScopedPrinter.h"
19 #include "llvm/Support/Debug.h"
20 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
21 #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
22 #include "llvm/Support/Endian.h"
23 #include "llvm/Support/Format.h"
24 #include "llvm/Support/type_traits.h"
25
26 namespace llvm {
27 namespace DwarfCFIEH {
28
29 template
30 class PrinterContext {
31 ScopedPrinter &W;
32 const object::ELFFile *Obj;
33
34 void printEHFrameHdr(uint64_t Offset, uint64_t Address, uint64_t Size) const;
35
36 void printEHFrame(const typename ELFT::Shdr *EHFrameShdr) const;
37
38 public:
39 PrinterContext(ScopedPrinter &W, const object::ELFFile *Obj)
40 : W(W), Obj(Obj) {}
41
42 void printUnwindInformation() const;
43 };
44
45 template
46 static const typename ELFO::Elf_Shdr *findSectionByAddress(const ELFO *Obj,
47 uint64_t Addr) {
48 auto Sections = Obj->sections();
49 if (Error E = Sections.takeError())
50 reportError(toString(std::move(E)));
51
52 for (const auto &Shdr : *Sections)
53 if (Shdr.sh_addr == Addr)
54 return &Shdr;
55 return nullptr;
56 }
57
58 template
59 void PrinterContext::printUnwindInformation() const {
60 const typename ELFT::Phdr *EHFramePhdr = nullptr;
61
62 auto PHs = Obj->program_headers();
63 if (Error E = PHs.takeError())
64 reportError(toString(std::move(E)));
65
66 for (const auto &Phdr : *PHs) {
67 if (Phdr.p_type == ELF::PT_GNU_EH_FRAME) {
68 EHFramePhdr = &Phdr;
69 if (Phdr.p_memsz != Phdr.p_filesz)
70 reportError("p_memsz does not match p_filesz for GNU_EH_FRAME");
71 break;
72 }
73 }
74
75 if (EHFramePhdr)
76 printEHFrameHdr(EHFramePhdr->p_offset, EHFramePhdr->p_vaddr,
77 EHFramePhdr->p_memsz);
78
79 auto Sections = Obj->sections();
80 if (Error E = Sections.takeError())
81 reportError(toString(std::move(E)));
82
83 for (const auto &Shdr : *Sections) {
84 auto SectionName = Obj->getSectionName(&Shdr);
85 if (Error E = SectionName.takeError())
86 reportError(toString(std::move(E)));
87
88 if (*SectionName == ".eh_frame")
89 printEHFrame(&Shdr);
90 }
91 }
92
93 template
94 void PrinterContext::printEHFrameHdr(uint64_t EHFrameHdrOffset,
95 uint64_t EHFrameHdrAddress,
96 uint64_t EHFrameHdrSize) const {
97 ListScope L(W, "EH_FRAME Header");
98 W.startLine() << format("Address: 0x%" PRIx64 "\n", EHFrameHdrAddress);
99 W.startLine() << format("Offset: 0x%" PRIx64 "\n", EHFrameHdrOffset);
100 W.startLine() << format("Size: 0x%" PRIx64 "\n", EHFrameHdrSize);
101
102 const auto *EHFrameHdrShdr = findSectionByAddress(Obj, EHFrameHdrAddress);
103 if (EHFrameHdrShdr) {
104 auto SectionName = Obj->getSectionName(EHFrameHdrShdr);
105 if (Error E = SectionName.takeError())
106 reportError(toString(std::move(E)));
107
108 W.printString("Corresponding Section", *SectionName);
109 }
110
111 DataExtractor DE(
112 StringRef(reinterpret_cast(Obj->base()) + EHFrameHdrOffset,
113 EHFrameHdrSize),
114 ELFT::TargetEndianness == support::endianness::little,
115 ELFT::Is64Bits ? 8 : 4);
116
117 DictScope D(W, "Header");
118 uint32_t Offset = 0;
119
120 auto Version = DE.getU8(&Offset);
121 W.printNumber("version", Version);
122 if (Version != 1)
123 reportError("only version 1 of .eh_frame_hdr is supported");
124
125 auto EHFramePtrEnc = DE.getU8(&Offset);
126 W.startLine() << format("eh_frame_ptr_enc: 0x%" PRIx64 "\n", EHFramePtrEnc);
127 if (EHFramePtrEnc != (dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4))
128 reportError("unexpected encoding eh_frame_ptr_enc");
129
130 auto FDECountEnc = DE.getU8(&Offset);
131 W.startLine() << format("fde_count_enc: 0x%" PRIx64 "\n", FDECountEnc);
132 if (FDECountEnc != dwarf::DW_EH_PE_udata4)
133 reportError("unexpected encoding fde_count_enc");
134
135 auto TableEnc = DE.getU8(&Offset);
136 W.startLine() << format("table_enc: 0x%" PRIx64 "\n", TableEnc);
137 if (TableEnc != (dwarf::DW_EH_PE_datarel | dwarf::DW_EH_PE_sdata4))
138 reportError("unexpected encoding table_enc");
139
140 auto EHFramePtr = DE.getSigned(&Offset, 4) + EHFrameHdrAddress + 4;
141 W.startLine() << format("eh_frame_ptr: 0x%" PRIx64 "\n", EHFramePtr);
142
143 auto FDECount = DE.getUnsigned(&Offset, 4);
144 W.printNumber("fde_count", FDECount);
145
146 unsigned NumEntries = 0;
147 uint64_t PrevPC = 0;
148 while (Offset + 8 <= EHFrameHdrSize && NumEntries < FDECount) {
149 DictScope D(W, std::string("entry ") + std::to_string(NumEntries));
150
151 auto InitialPC = DE.getSigned(&Offset, 4) + EHFrameHdrAddress;
152 W.startLine() << format("initial_location: 0x%" PRIx64 "\n", InitialPC);
153 auto Address = DE.getSigned(&Offset, 4) + EHFrameHdrAddress;
154 W.startLine() << format("address: 0x%" PRIx64 "\n", Address);
155
156 if (InitialPC < PrevPC)
157 reportError("initial_location is out of order");
158
159 PrevPC = InitialPC;
160 ++NumEntries;
161 }
162 }
163
164 template
165 void PrinterContext::printEHFrame(
166 const typename ELFT::Shdr *EHFrameShdr) const {
167 uint64_t Address = EHFrameShdr->sh_addr;
168 uint64_t ShOffset = EHFrameShdr->sh_offset;
169 W.startLine() << format(".eh_frame section at offset 0x%" PRIx64
170 " address 0x%" PRIx64 ":\n",
171 ShOffset, Address);
172 W.indent();
173
174 auto Result = Obj->getSectionContents(EHFrameShdr);
175 if (Error E = Result.takeError())
176 reportError(toString(std::move(E)));
177
178 auto Contents = Result.get();
179 DWARFDataExtractor DE(
180 StringRef(reinterpret_cast(Contents.data()),
181 Contents.size()),
182 ELFT::TargetEndianness == support::endianness::little,
183 ELFT::Is64Bits ? 8 : 4);
184 DWARFDebugFrame EHFrame(/*IsEH=*/true, /*EHFrameAddress=*/Address);
185 EHFrame.parse(DE);
186
187 for (const auto &Entry : EHFrame) {
188 if (const auto *CIE = dyn_cast(&Entry)) {
189 W.startLine() << format("[0x%" PRIx64 "] CIE length=%" PRIu64 "\n",
190 Address + CIE->getOffset(),
191 CIE->getLength());
192 W.indent();
193
194 W.printNumber("version", CIE->getVersion());
195 W.printString("augmentation", CIE->getAugmentationString());
196 W.printNumber("code_alignment_factor", CIE->getCodeAlignmentFactor());
197 W.printNumber("data_alignment_factor", CIE->getDataAlignmentFactor());
198 W.printNumber("return_address_register", CIE->getReturnAddressRegister());
199
200 W.getOStream() << "\n";
201 W.startLine() << "Program:\n";
202 W.indent();
203 CIE->cfis().dump(W.getOStream(), nullptr, W.getIndentLevel());
204 W.unindent();
205
206 W.unindent();
207 W.getOStream() << "\n";
208
209 } else if (const auto *FDE = dyn_cast(&Entry)) {
210 W.startLine() << format("[0x%" PRIx64 "] FDE length=%" PRIu64
211 " cie=[0x%" PRIx64 "]\n",
212 Address + FDE->getOffset(),
213 FDE->getLength(),
214 Address + FDE->getLinkedCIE()->getOffset());
215 W.indent();
216
217 W.startLine() << format("initial_location: 0x%" PRIx64 "\n",
218 FDE->getInitialLocation());
219 W.startLine()
220 << format("address_range: 0x%" PRIx64 " (end : 0x%" PRIx64 ")\n",
221 FDE->getAddressRange(),
222 FDE->getInitialLocation() + FDE->getAddressRange());
223
224 W.getOStream() << "\n";
225 W.startLine() << "Program:\n";
226 W.indent();
227 FDE->cfis().dump(W.getOStream(), nullptr, W.getIndentLevel());
228 W.unindent();
229
230 W.unindent();
231 W.getOStream() << "\n";
232 } else {
233 llvm_unreachable("unexpected DWARF frame kind");
234 }
235 }
236
237 W.unindent();
238 }
239
240 }
241 }
242
243 #endif
1212 //===----------------------------------------------------------------------===//
1313
1414 #include "ARMEHABIPrinter.h"
15 #include "DwarfCFIEHPrinter.h"
1516 #include "Error.h"
1617 #include "ObjDumper.h"
1718 #include "StackMapPrinter.h"
18071808
18081809 template
18091810 void ELFDumper::printUnwindInfo() {
1811 const unsigned Machine = Obj->getHeader()->e_machine;
1812 if (Machine == EM_386 || Machine == EM_X86_64) {
1813 DwarfCFIEH::PrinterContext Ctx(W, Obj);
1814 return Ctx.printUnwindInformation();
1815 }
18101816 W.startLine() << "UnwindInfo not implemented.\n";
18111817 }
18121818