llvm.org GIT mirror llvm / ed6b821
Reland "[DebugInfo] Support DWARF expressions in eh_frame" Summary: Original change was D43313 (r326932) and reverted by r326953 because it broke an LLD test and a windows build. The LLD test was already fixed in lld commit r326944 (thanks maskray). This is the original change with the windows build fixed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@326970 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 uint64_t 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 uint64_t 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 uint64_t 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