1 //===- DWARFDebugFrame.h - Parsing of .debug_frame ------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
10 #include "llvm/ADT/DenseMap.h"
11 #include "llvm/ADT/Optional.h"
12 #include "llvm/ADT/StringExtras.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/BinaryFormat/Dwarf.h"
15 #include "llvm/Support/Casting.h"
16 #include "llvm/Support/Compiler.h"
17 #include "llvm/Support/DataExtractor.h"
18 #include "llvm/Support/Errc.h"
19 #include "llvm/Support/ErrorHandling.h"
20 #include "llvm/Support/Format.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include <algorithm>
23 #include <cassert>
24 #include <cinttypes>
25 #include <cstdint>
26 #include <string>
27 #include <vector>
28 
29 using namespace llvm;
30 using namespace dwarf;
31 
32 
33 // See DWARF standard v3, section 7.23
34 const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
35 const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
36 
37 Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset,
38                         uint64_t EndOffset) {
39   while (*Offset < EndOffset) {
40     uint8_t Opcode = Data.getRelocatedValue(1, Offset);
41     // Some instructions have a primary opcode encoded in the top bits.
42     uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK;
43 
44     if (Primary) {
45       // If it's a primary opcode, the first operand is encoded in the bottom
46       // bits of the opcode itself.
47       uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
48       switch (Primary) {
49       default:
50         return createStringError(errc::illegal_byte_sequence,
51                                  "Invalid primary CFI opcode 0x%" PRIx8,
52                                  Primary);
53       case DW_CFA_advance_loc:
54       case DW_CFA_restore:
55         addInstruction(Primary, Op1);
56         break;
57       case DW_CFA_offset:
58         addInstruction(Primary, Op1, Data.getULEB128(Offset));
59         break;
60       }
61     } else {
62       // Extended opcode - its value is Opcode itself.
63       switch (Opcode) {
64       default:
65         return createStringError(errc::illegal_byte_sequence,
66                                  "Invalid extended CFI opcode 0x%" PRIx8,
67                                  Opcode);
68       case DW_CFA_nop:
69       case DW_CFA_remember_state:
70       case DW_CFA_restore_state:
71       case DW_CFA_GNU_window_save:
72         // No operands
73         addInstruction(Opcode);
74         break;
75       case DW_CFA_set_loc:
76         // Operands: Address
77         addInstruction(Opcode, Data.getRelocatedAddress(Offset));
78         break;
79       case DW_CFA_advance_loc1:
80         // Operands: 1-byte delta
81         addInstruction(Opcode, Data.getRelocatedValue(1, Offset));
82         break;
83       case DW_CFA_advance_loc2:
84         // Operands: 2-byte delta
85         addInstruction(Opcode, Data.getRelocatedValue(2, Offset));
86         break;
87       case DW_CFA_advance_loc4:
88         // Operands: 4-byte delta
89         addInstruction(Opcode, Data.getRelocatedValue(4, Offset));
90         break;
91       case DW_CFA_restore_extended:
92       case DW_CFA_undefined:
93       case DW_CFA_same_value:
94       case DW_CFA_def_cfa_register:
95       case DW_CFA_def_cfa_offset:
96       case DW_CFA_GNU_args_size:
97         // Operands: ULEB128
98         addInstruction(Opcode, Data.getULEB128(Offset));
99         break;
100       case DW_CFA_def_cfa_offset_sf:
101         // Operands: SLEB128
102         addInstruction(Opcode, Data.getSLEB128(Offset));
103         break;
104       case DW_CFA_offset_extended:
105       case DW_CFA_register:
106       case DW_CFA_def_cfa:
107       case DW_CFA_val_offset: {
108         // Operands: ULEB128, ULEB128
109         // Note: We can not embed getULEB128 directly into function
110         // argument list. getULEB128 changes Offset and order of evaluation
111         // for arguments is unspecified.
112         auto op1 = Data.getULEB128(Offset);
113         auto op2 = Data.getULEB128(Offset);
114         addInstruction(Opcode, op1, op2);
115         break;
116         }
117         case DW_CFA_offset_extended_sf:
118         case DW_CFA_def_cfa_sf:
119         case DW_CFA_val_offset_sf: {
120           // Operands: ULEB128, SLEB128
121           // Note: see comment for the previous case
122           auto op1 = Data.getULEB128(Offset);
123           auto op2 = (uint64_t)Data.getSLEB128(Offset);
124           addInstruction(Opcode, op1, op2);
125           break;
126         }
127         case DW_CFA_def_cfa_expression: {
128           uint32_t ExprLength = Data.getULEB128(Offset);
129           addInstruction(Opcode, 0);
130           DataExtractor Extractor(
131               Data.getData().slice(*Offset, *Offset + ExprLength),
132               Data.isLittleEndian(), Data.getAddressSize());
133           // Note. We do not pass the DWARF format to DWARFExpression, because
134           // DW_OP_call_ref, the only operation which depends on the format, is
135           // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
136           Instructions.back().Expression =
137               DWARFExpression(Extractor, Data.getAddressSize());
138           *Offset += ExprLength;
139           break;
140         }
141         case DW_CFA_expression:
142         case DW_CFA_val_expression: {
143           auto RegNum = Data.getULEB128(Offset);
144           auto BlockLength = Data.getULEB128(Offset);
145           addInstruction(Opcode, RegNum, 0);
146           DataExtractor Extractor(
147               Data.getData().slice(*Offset, *Offset + BlockLength),
148               Data.isLittleEndian(), Data.getAddressSize());
149           // Note. We do not pass the DWARF format to DWARFExpression, because
150           // DW_OP_call_ref, the only operation which depends on the format, is
151           // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
152           Instructions.back().Expression =
153               DWARFExpression(Extractor, Data.getAddressSize());
154           *Offset += BlockLength;
155           break;
156         }
157       }
158     }
159   }
160 
161   return Error::success();
162 }
163 
164 namespace {
165 
166 
167 } // end anonymous namespace
168 
169 ArrayRef<CFIProgram::OperandType[2]> CFIProgram::getOperandTypes() {
170   static OperandType OpTypes[DW_CFA_restore+1][2];
171   static bool Initialized = false;
172   if (Initialized) {
173     return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
174   }
175   Initialized = true;
176 
177 #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1)       \
178   do {                                          \
179     OpTypes[OP][0] = OPTYPE0;                   \
180     OpTypes[OP][1] = OPTYPE1;                   \
181   } while (false)
182 #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None)
183 #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None)
184 
185   DECLARE_OP1(DW_CFA_set_loc, OT_Address);
186   DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset);
187   DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset);
188   DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset);
189   DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset);
190   DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset);
191   DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset);
192   DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset);
193   DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register);
194   DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset);
195   DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset);
196   DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression);
197   DECLARE_OP1(DW_CFA_undefined, OT_Register);
198   DECLARE_OP1(DW_CFA_same_value, OT_Register);
199   DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset);
200   DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset);
201   DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset);
202   DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset);
203   DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset);
204   DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register);
205   DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression);
206   DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression);
207   DECLARE_OP1(DW_CFA_restore, OT_Register);
208   DECLARE_OP1(DW_CFA_restore_extended, OT_Register);
209   DECLARE_OP0(DW_CFA_remember_state);
210   DECLARE_OP0(DW_CFA_restore_state);
211   DECLARE_OP0(DW_CFA_GNU_window_save);
212   DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset);
213   DECLARE_OP0(DW_CFA_nop);
214 
215 #undef DECLARE_OP0
216 #undef DECLARE_OP1
217 #undef DECLARE_OP2
218 
219   return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
220 }
221 
222 /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
223 void CFIProgram::printOperand(raw_ostream &OS, const MCRegisterInfo *MRI,
224                               bool IsEH, const Instruction &Instr,
225                               unsigned OperandIdx, uint64_t Operand) const {
226   assert(OperandIdx < 2);
227   uint8_t Opcode = Instr.Opcode;
228   OperandType Type = getOperandTypes()[Opcode][OperandIdx];
229 
230   switch (Type) {
231   case OT_Unset: {
232     OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";
233     auto OpcodeName = CallFrameString(Opcode, Arch);
234     if (!OpcodeName.empty())
235       OS << " " << OpcodeName;
236     else
237       OS << format(" Opcode %x",  Opcode);
238     break;
239   }
240   case OT_None:
241     break;
242   case OT_Address:
243     OS << format(" %" PRIx64, Operand);
244     break;
245   case OT_Offset:
246     // The offsets are all encoded in a unsigned form, but in practice
247     // consumers use them signed. It's most certainly legacy due to
248     // the lack of signed variants in the first Dwarf standards.
249     OS << format(" %+" PRId64, int64_t(Operand));
250     break;
251   case OT_FactoredCodeOffset: // Always Unsigned
252     if (CodeAlignmentFactor)
253       OS << format(" %" PRId64, Operand * CodeAlignmentFactor);
254     else
255       OS << format(" %" PRId64 "*code_alignment_factor" , Operand);
256     break;
257   case OT_SignedFactDataOffset:
258     if (DataAlignmentFactor)
259       OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor);
260     else
261       OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand));
262     break;
263   case OT_UnsignedFactDataOffset:
264     if (DataAlignmentFactor)
265       OS << format(" %" PRId64, Operand * DataAlignmentFactor);
266     else
267       OS << format(" %" PRId64 "*data_alignment_factor" , Operand);
268     break;
269   case OT_Register:
270     OS << format(" reg%" PRId64, Operand);
271     break;
272   case OT_Expression:
273     assert(Instr.Expression && "missing DWARFExpression object");
274     OS << " ";
275     Instr.Expression->print(OS, MRI, nullptr, IsEH);
276     break;
277   }
278 }
279 
280 void CFIProgram::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
281                       unsigned IndentLevel) const {
282   for (const auto &Instr : Instructions) {
283     uint8_t Opcode = Instr.Opcode;
284     if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
285       Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
286     OS.indent(2 * IndentLevel);
287     OS << CallFrameString(Opcode, Arch) << ":";
288     for (unsigned i = 0; i < Instr.Ops.size(); ++i)
289       printOperand(OS, MRI, IsEH, Instr, i, Instr.Ops[i]);
290     OS << '\n';
291   }
292 }
293 
294 // Returns the CIE identifier to be used by the requested format.
295 // CIE ids for .debug_frame sections are defined in Section 7.24 of DWARFv5.
296 // For CIE ID in .eh_frame sections see
297 // https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
298 constexpr uint64_t getCIEId(bool IsDWARF64, bool IsEH) {
299   if (IsEH)
300     return 0;
301   if (IsDWARF64)
302     return DW64_CIE_ID;
303   return DW_CIE_ID;
304 }
305 
306 void CIE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const {
307   // A CIE with a zero length is a terminator entry in the .eh_frame section.
308   if (IsEH && Length == 0) {
309     OS << format("%08" PRIx64, Offset) << " ZERO terminator\n";
310     return;
311   }
312 
313   OS << format("%08" PRIx64, Offset)
314      << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length)
315      << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8,
316                getCIEId(IsDWARF64, IsEH))
317      << " CIE\n"
318      << "  Format:                " << FormatString(IsDWARF64) << "\n"
319      << format("  Version:               %d\n", Version)
320      << "  Augmentation:          \"" << Augmentation << "\"\n";
321   if (Version >= 4) {
322     OS << format("  Address size:          %u\n", (uint32_t)AddressSize);
323     OS << format("  Segment desc size:     %u\n",
324                  (uint32_t)SegmentDescriptorSize);
325   }
326   OS << format("  Code alignment factor: %u\n", (uint32_t)CodeAlignmentFactor);
327   OS << format("  Data alignment factor: %d\n", (int32_t)DataAlignmentFactor);
328   OS << format("  Return address column: %d\n", (int32_t)ReturnAddressRegister);
329   if (Personality)
330     OS << format("  Personality Address: %016" PRIx64 "\n", *Personality);
331   if (!AugmentationData.empty()) {
332     OS << "  Augmentation data:    ";
333     for (uint8_t Byte : AugmentationData)
334       OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf);
335     OS << "\n";
336   }
337   OS << "\n";
338   CFIs.dump(OS, MRI, IsEH);
339   OS << "\n";
340 }
341 
342 void FDE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const {
343   OS << format("%08" PRIx64, Offset)
344      << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length)
345      << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8, CIEPointer)
346      << " FDE cie=";
347   if (LinkedCIE)
348     OS << format("%08" PRIx64, LinkedCIE->getOffset());
349   else
350     OS << "<invalid offset>";
351   OS << format(" pc=%08" PRIx64 "...%08" PRIx64 "\n", InitialLocation,
352                InitialLocation + AddressRange);
353   OS << "  Format:       " << FormatString(IsDWARF64) << "\n";
354   if (LSDAAddress)
355     OS << format("  LSDA Address: %016" PRIx64 "\n", *LSDAAddress);
356   CFIs.dump(OS, MRI, IsEH);
357   OS << "\n";
358 }
359 
360 DWARFDebugFrame::DWARFDebugFrame(Triple::ArchType Arch,
361     bool IsEH, uint64_t EHFrameAddress)
362     : Arch(Arch), IsEH(IsEH), EHFrameAddress(EHFrameAddress) {}
363 
364 DWARFDebugFrame::~DWARFDebugFrame() = default;
365 
366 static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
367                                               uint64_t Offset, int Length) {
368   errs() << "DUMP: ";
369   for (int i = 0; i < Length; ++i) {
370     uint8_t c = Data.getU8(&Offset);
371     errs().write_hex(c); errs() << " ";
372   }
373   errs() << "\n";
374 }
375 
376 Error DWARFDebugFrame::parse(DWARFDataExtractor Data) {
377   uint64_t Offset = 0;
378   DenseMap<uint64_t, CIE *> CIEs;
379 
380   while (Data.isValidOffset(Offset)) {
381     uint64_t StartOffset = Offset;
382 
383     uint64_t Length;
384     DwarfFormat Format;
385     std::tie(Length, Format) = Data.getInitialLength(&Offset);
386     bool IsDWARF64 = Format == DWARF64;
387 
388     // If the Length is 0, then this CIE is a terminator. We add it because some
389     // dumper tools might need it to print something special for such entries
390     // (e.g. llvm-objdump --dwarf=frames prints "ZERO terminator").
391     if (Length == 0) {
392       auto Cie = std::make_unique<CIE>(
393           IsDWARF64, StartOffset, 0, 0, SmallString<8>(), 0, 0, 0, 0, 0,
394           SmallString<8>(), 0, 0, None, None, Arch);
395       CIEs[StartOffset] = Cie.get();
396       Entries.push_back(std::move(Cie));
397       break;
398     }
399 
400     // At this point, Offset points to the next field after Length.
401     // Length is the structure size excluding itself. Compute an offset one
402     // past the end of the structure (needed to know how many instructions to
403     // read).
404     uint64_t StartStructureOffset = Offset;
405     uint64_t EndStructureOffset = Offset + Length;
406 
407     // The Id field's size depends on the DWARF format
408     Error Err = Error::success();
409     uint64_t Id = Data.getRelocatedValue((IsDWARF64 && !IsEH) ? 8 : 4, &Offset,
410                                          /*SectionIndex=*/nullptr, &Err);
411     if (Err)
412       return Err;
413 
414     if (Id == getCIEId(IsDWARF64, IsEH)) {
415       uint8_t Version = Data.getU8(&Offset);
416       const char *Augmentation = Data.getCStr(&Offset);
417       StringRef AugmentationString(Augmentation ? Augmentation : "");
418       uint8_t AddressSize = Version < 4 ? Data.getAddressSize() :
419                                           Data.getU8(&Offset);
420       Data.setAddressSize(AddressSize);
421       uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset);
422       uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
423       int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
424       uint64_t ReturnAddressRegister =
425           Version == 1 ? Data.getU8(&Offset) : Data.getULEB128(&Offset);
426 
427       // Parse the augmentation data for EH CIEs
428       StringRef AugmentationData("");
429       uint32_t FDEPointerEncoding = DW_EH_PE_absptr;
430       uint32_t LSDAPointerEncoding = DW_EH_PE_omit;
431       Optional<uint64_t> Personality;
432       Optional<uint32_t> PersonalityEncoding;
433       if (IsEH) {
434         Optional<uint64_t> AugmentationLength;
435         uint64_t StartAugmentationOffset;
436         uint64_t EndAugmentationOffset;
437 
438         // Walk the augmentation string to get all the augmentation data.
439         for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) {
440           switch (AugmentationString[i]) {
441           default:
442             return createStringError(
443                 errc::invalid_argument,
444                 "unknown augmentation character in entry at 0x%" PRIx64,
445                 StartOffset);
446           case 'L':
447             LSDAPointerEncoding = Data.getU8(&Offset);
448             break;
449           case 'P': {
450             if (Personality)
451               return createStringError(
452                   errc::invalid_argument,
453                   "duplicate personality in entry at 0x%" PRIx64, StartOffset);
454             PersonalityEncoding = Data.getU8(&Offset);
455             Personality = Data.getEncodedPointer(
456                 &Offset, *PersonalityEncoding,
457                 EHFrameAddress ? EHFrameAddress + Offset : 0);
458             break;
459           }
460           case 'R':
461             FDEPointerEncoding = Data.getU8(&Offset);
462             break;
463           case 'S':
464             // Current frame is a signal trampoline.
465             break;
466           case 'z':
467             if (i)
468               return createStringError(
469                   errc::invalid_argument,
470                   "'z' must be the first character at 0x%" PRIx64, StartOffset);
471             // Parse the augmentation length first.  We only parse it if
472             // the string contains a 'z'.
473             AugmentationLength = Data.getULEB128(&Offset);
474             StartAugmentationOffset = Offset;
475             EndAugmentationOffset = Offset + *AugmentationLength;
476             break;
477           case 'B':
478             // B-Key is used for signing functions associated with this
479             // augmentation string
480             break;
481           }
482         }
483 
484         if (AugmentationLength.hasValue()) {
485           if (Offset != EndAugmentationOffset)
486             return createStringError(errc::invalid_argument,
487                                      "parsing augmentation data at 0x%" PRIx64
488                                      " failed",
489                                      StartOffset);
490           AugmentationData = Data.getData().slice(StartAugmentationOffset,
491                                                   EndAugmentationOffset);
492         }
493       }
494 
495       auto Cie = std::make_unique<CIE>(
496           IsDWARF64, StartOffset, Length, Version, AugmentationString,
497           AddressSize, SegmentDescriptorSize, CodeAlignmentFactor,
498           DataAlignmentFactor, ReturnAddressRegister, AugmentationData,
499           FDEPointerEncoding, LSDAPointerEncoding, Personality,
500           PersonalityEncoding, Arch);
501       CIEs[StartOffset] = Cie.get();
502       Entries.emplace_back(std::move(Cie));
503     } else {
504       // FDE
505       uint64_t CIEPointer = Id;
506       uint64_t InitialLocation = 0;
507       uint64_t AddressRange = 0;
508       Optional<uint64_t> LSDAAddress;
509       CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer];
510 
511       if (IsEH) {
512         // The address size is encoded in the CIE we reference.
513         if (!Cie)
514           return createStringError(errc::invalid_argument,
515                                    "parsing FDE data at 0x%" PRIx64
516                                    " failed due to missing CIE",
517                                    StartOffset);
518         if (auto Val = Data.getEncodedPointer(
519                 &Offset, Cie->getFDEPointerEncoding(),
520                 EHFrameAddress ? EHFrameAddress + Offset : 0)) {
521           InitialLocation = *Val;
522         }
523         if (auto Val = Data.getEncodedPointer(
524                 &Offset, Cie->getFDEPointerEncoding(), 0)) {
525           AddressRange = *Val;
526         }
527 
528         StringRef AugmentationString = Cie->getAugmentationString();
529         if (!AugmentationString.empty()) {
530           // Parse the augmentation length and data for this FDE.
531           uint64_t AugmentationLength = Data.getULEB128(&Offset);
532 
533           uint64_t EndAugmentationOffset = Offset + AugmentationLength;
534 
535           // Decode the LSDA if the CIE augmentation string said we should.
536           if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) {
537             LSDAAddress = Data.getEncodedPointer(
538                 &Offset, Cie->getLSDAPointerEncoding(),
539                 EHFrameAddress ? Offset + EHFrameAddress : 0);
540           }
541 
542           if (Offset != EndAugmentationOffset)
543             return createStringError(errc::invalid_argument,
544                                      "parsing augmentation data at 0x%" PRIx64
545                                      " failed",
546                                      StartOffset);
547         }
548       } else {
549         InitialLocation = Data.getRelocatedAddress(&Offset);
550         AddressRange = Data.getRelocatedAddress(&Offset);
551       }
552 
553       Entries.emplace_back(new FDE(IsDWARF64, StartOffset, Length, CIEPointer,
554                                    InitialLocation, AddressRange, Cie,
555                                    LSDAAddress, Arch));
556     }
557 
558     if (Error E =
559             Entries.back()->cfis().parse(Data, &Offset, EndStructureOffset))
560       return E;
561 
562     if (Offset != EndStructureOffset)
563       return createStringError(
564           errc::invalid_argument,
565           "parsing entry instructions at 0x%" PRIx64 " failed", StartOffset);
566   }
567 
568   return Error::success();
569 }
570 
571 FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const {
572   auto It = partition_point(Entries, [=](const std::unique_ptr<FrameEntry> &E) {
573     return E->getOffset() < Offset;
574   });
575   if (It != Entries.end() && (*It)->getOffset() == Offset)
576     return It->get();
577   return nullptr;
578 }
579 
580 void DWARFDebugFrame::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
581                            Optional<uint64_t> Offset) const {
582   if (Offset) {
583     if (auto *Entry = getEntryAtOffset(*Offset))
584       Entry->dump(OS, MRI, IsEH);
585     return;
586   }
587 
588   OS << "\n";
589   for (const auto &Entry : Entries)
590     Entry->dump(OS, MRI, IsEH);
591 }
592