128db7e65SEugene Zelenko //===- DWARFDebugFrame.h - Parsing of .debug_frame ------------------------===//
282af9438SZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
682af9438SZachary Turner //
782af9438SZachary Turner //===----------------------------------------------------------------------===//
882af9438SZachary Turner 
96bda14b3SChandler Carruth #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
1016132e6fSBenjamin Kramer #include "llvm/ADT/DenseMap.h"
1103a670c0SIgor Laevsky #include "llvm/ADT/Optional.h"
12f69c7e53SSimon Atanasyan #include "llvm/ADT/StringExtras.h"
1361a72d88SEugene Zelenko #include "llvm/ADT/StringRef.h"
14264b5d9eSZachary Turner #include "llvm/BinaryFormat/Dwarf.h"
15290e4823Sserge-sans-paille #include "llvm/DebugInfo/DIContext.h"
16290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
17a4b842e2SGreg Clayton #include "llvm/MC/MCRegisterInfo.h"
1861a72d88SEugene Zelenko #include "llvm/Support/Compiler.h"
1961a72d88SEugene Zelenko #include "llvm/Support/DataExtractor.h"
20cba595daSVictor Leschuk #include "llvm/Support/Errc.h"
2182af9438SZachary Turner #include "llvm/Support/ErrorHandling.h"
2282af9438SZachary Turner #include "llvm/Support/Format.h"
2382af9438SZachary Turner #include "llvm/Support/raw_ostream.h"
2461a72d88SEugene Zelenko #include <algorithm>
2561a72d88SEugene Zelenko #include <cassert>
2661a72d88SEugene Zelenko #include <cinttypes>
2761a72d88SEugene Zelenko #include <cstdint>
2882af9438SZachary Turner 
2982af9438SZachary Turner using namespace llvm;
3082af9438SZachary Turner using namespace dwarf;
3182af9438SZachary Turner 
printRegister(raw_ostream & OS,const MCRegisterInfo * MRI,bool IsEH,unsigned RegNum)32a4b842e2SGreg Clayton static void printRegister(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
33a4b842e2SGreg Clayton                           unsigned RegNum) {
34a4b842e2SGreg Clayton   if (MRI) {
35a4b842e2SGreg Clayton     if (Optional<unsigned> LLVMRegNum = MRI->getLLVMRegNum(RegNum, IsEH)) {
36a4b842e2SGreg Clayton       if (const char *RegName = MRI->getName(*LLVMRegNum)) {
37a4b842e2SGreg Clayton         OS << RegName;
38a4b842e2SGreg Clayton         return;
39a4b842e2SGreg Clayton       }
40a4b842e2SGreg Clayton     }
41a4b842e2SGreg Clayton   }
42a4b842e2SGreg Clayton   OS << "reg" << RegNum;
43a4b842e2SGreg Clayton }
4482af9438SZachary Turner 
createUnspecified()45f8122d35SGreg Clayton UnwindLocation UnwindLocation::createUnspecified() { return {Unspecified}; }
46f8122d35SGreg Clayton 
createUndefined()47f8122d35SGreg Clayton UnwindLocation UnwindLocation::createUndefined() { return {Undefined}; }
48f8122d35SGreg Clayton 
createSame()49f8122d35SGreg Clayton UnwindLocation UnwindLocation::createSame() { return {Same}; }
50f8122d35SGreg Clayton 
createIsConstant(int32_t Value)51f8122d35SGreg Clayton UnwindLocation UnwindLocation::createIsConstant(int32_t Value) {
52167e7afcSRamNalamothu   return {Constant, InvalidRegisterNumber, Value, None, false};
53f8122d35SGreg Clayton }
54f8122d35SGreg Clayton 
createIsCFAPlusOffset(int32_t Offset)55f8122d35SGreg Clayton UnwindLocation UnwindLocation::createIsCFAPlusOffset(int32_t Offset) {
56167e7afcSRamNalamothu   return {CFAPlusOffset, InvalidRegisterNumber, Offset, None, false};
57f8122d35SGreg Clayton }
58f8122d35SGreg Clayton 
createAtCFAPlusOffset(int32_t Offset)59f8122d35SGreg Clayton UnwindLocation UnwindLocation::createAtCFAPlusOffset(int32_t Offset) {
60167e7afcSRamNalamothu   return {CFAPlusOffset, InvalidRegisterNumber, Offset, None, true};
61f8122d35SGreg Clayton }
62f8122d35SGreg Clayton 
63167e7afcSRamNalamothu UnwindLocation
createIsRegisterPlusOffset(uint32_t RegNum,int32_t Offset,Optional<uint32_t> AddrSpace)64167e7afcSRamNalamothu UnwindLocation::createIsRegisterPlusOffset(uint32_t RegNum, int32_t Offset,
65167e7afcSRamNalamothu                                            Optional<uint32_t> AddrSpace) {
66167e7afcSRamNalamothu   return {RegPlusOffset, RegNum, Offset, AddrSpace, false};
67f8122d35SGreg Clayton }
68167e7afcSRamNalamothu 
69167e7afcSRamNalamothu UnwindLocation
createAtRegisterPlusOffset(uint32_t RegNum,int32_t Offset,Optional<uint32_t> AddrSpace)70167e7afcSRamNalamothu UnwindLocation::createAtRegisterPlusOffset(uint32_t RegNum, int32_t Offset,
71167e7afcSRamNalamothu                                            Optional<uint32_t> AddrSpace) {
72167e7afcSRamNalamothu   return {RegPlusOffset, RegNum, Offset, AddrSpace, true};
73f8122d35SGreg Clayton }
74f8122d35SGreg Clayton 
createIsDWARFExpression(DWARFExpression Expr)75f8122d35SGreg Clayton UnwindLocation UnwindLocation::createIsDWARFExpression(DWARFExpression Expr) {
76f8122d35SGreg Clayton   return {Expr, false};
77f8122d35SGreg Clayton }
78f8122d35SGreg Clayton 
createAtDWARFExpression(DWARFExpression Expr)79f8122d35SGreg Clayton UnwindLocation UnwindLocation::createAtDWARFExpression(DWARFExpression Expr) {
80f8122d35SGreg Clayton   return {Expr, true};
81f8122d35SGreg Clayton }
82f8122d35SGreg Clayton 
dump(raw_ostream & OS,const MCRegisterInfo * MRI,bool IsEH) const83f8122d35SGreg Clayton void UnwindLocation::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
84f8122d35SGreg Clayton                           bool IsEH) const {
85f8122d35SGreg Clayton   if (Dereference)
86f8122d35SGreg Clayton     OS << '[';
87f8122d35SGreg Clayton   switch (Kind) {
88f8122d35SGreg Clayton   case Unspecified:
89f8122d35SGreg Clayton     OS << "unspecified";
90f8122d35SGreg Clayton     break;
91f8122d35SGreg Clayton   case Undefined:
92f8122d35SGreg Clayton     OS << "undefined";
93f8122d35SGreg Clayton     break;
94f8122d35SGreg Clayton   case Same:
95f8122d35SGreg Clayton     OS << "same";
96f8122d35SGreg Clayton     break;
97f8122d35SGreg Clayton   case CFAPlusOffset:
98f8122d35SGreg Clayton     OS << "CFA";
99f8122d35SGreg Clayton     if (Offset == 0)
100f8122d35SGreg Clayton       break;
101f8122d35SGreg Clayton     if (Offset > 0)
102f8122d35SGreg Clayton       OS << "+";
103f8122d35SGreg Clayton     OS << Offset;
104f8122d35SGreg Clayton     break;
105f8122d35SGreg Clayton   case RegPlusOffset:
106f8122d35SGreg Clayton     printRegister(OS, MRI, IsEH, RegNum);
107167e7afcSRamNalamothu     if (Offset == 0 && !AddrSpace)
108f8122d35SGreg Clayton       break;
109167e7afcSRamNalamothu     if (Offset >= 0)
110f8122d35SGreg Clayton       OS << "+";
111f8122d35SGreg Clayton     OS << Offset;
112167e7afcSRamNalamothu     if (AddrSpace)
113167e7afcSRamNalamothu       OS << " in addrspace" << *AddrSpace;
114f8122d35SGreg Clayton     break;
115f8122d35SGreg Clayton   case DWARFExpr:
116f8122d35SGreg Clayton     Expr->print(OS, DIDumpOptions(), MRI, nullptr, IsEH);
117f8122d35SGreg Clayton     break;
118f8122d35SGreg Clayton   case Constant:
119f8122d35SGreg Clayton     OS << Offset;
120f8122d35SGreg Clayton     break;
121f8122d35SGreg Clayton   }
122f8122d35SGreg Clayton   if (Dereference)
123f8122d35SGreg Clayton     OS << ']';
124f8122d35SGreg Clayton }
125f8122d35SGreg Clayton 
operator <<(raw_ostream & OS,const UnwindLocation & UL)126f8122d35SGreg Clayton raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS,
127f8122d35SGreg Clayton                                      const UnwindLocation &UL) {
128f8122d35SGreg Clayton   UL.dump(OS, nullptr, false);
129f8122d35SGreg Clayton   return OS;
130f8122d35SGreg Clayton }
131f8122d35SGreg Clayton 
operator ==(const UnwindLocation & RHS) const132f8122d35SGreg Clayton bool UnwindLocation::operator==(const UnwindLocation &RHS) const {
133f8122d35SGreg Clayton   if (Kind != RHS.Kind)
134f8122d35SGreg Clayton     return false;
135f8122d35SGreg Clayton   switch (Kind) {
136f8122d35SGreg Clayton   case Unspecified:
137f8122d35SGreg Clayton   case Undefined:
138f8122d35SGreg Clayton   case Same:
139f8122d35SGreg Clayton     return true;
140f8122d35SGreg Clayton   case CFAPlusOffset:
141f8122d35SGreg Clayton     return Offset == RHS.Offset && Dereference == RHS.Dereference;
142f8122d35SGreg Clayton   case RegPlusOffset:
143f8122d35SGreg Clayton     return RegNum == RHS.RegNum && Offset == RHS.Offset &&
144f8122d35SGreg Clayton            Dereference == RHS.Dereference;
145f8122d35SGreg Clayton   case DWARFExpr:
146f8122d35SGreg Clayton     return *Expr == *RHS.Expr && Dereference == RHS.Dereference;
147f8122d35SGreg Clayton   case Constant:
148f8122d35SGreg Clayton     return Offset == RHS.Offset;
149f8122d35SGreg Clayton   }
150f8122d35SGreg Clayton   return false;
151f8122d35SGreg Clayton }
152f8122d35SGreg Clayton 
dump(raw_ostream & OS,const MCRegisterInfo * MRI,bool IsEH) const153f8122d35SGreg Clayton void RegisterLocations::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
154f8122d35SGreg Clayton                              bool IsEH) const {
155f8122d35SGreg Clayton   bool First = true;
156f8122d35SGreg Clayton   for (const auto &RegLocPair : Locations) {
157f8122d35SGreg Clayton     if (First)
158f8122d35SGreg Clayton       First = false;
159f8122d35SGreg Clayton     else
160f8122d35SGreg Clayton       OS << ", ";
161f8122d35SGreg Clayton     printRegister(OS, MRI, IsEH, RegLocPair.first);
162f8122d35SGreg Clayton     OS << '=';
163f8122d35SGreg Clayton     RegLocPair.second.dump(OS, MRI, IsEH);
164f8122d35SGreg Clayton   }
165f8122d35SGreg Clayton }
166f8122d35SGreg Clayton 
operator <<(raw_ostream & OS,const RegisterLocations & RL)167f8122d35SGreg Clayton raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS,
168f8122d35SGreg Clayton                                      const RegisterLocations &RL) {
169f8122d35SGreg Clayton   RL.dump(OS, nullptr, false);
170f8122d35SGreg Clayton   return OS;
171f8122d35SGreg Clayton }
172f8122d35SGreg Clayton 
dump(raw_ostream & OS,const MCRegisterInfo * MRI,bool IsEH,unsigned IndentLevel) const173f8122d35SGreg Clayton void UnwindRow::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
174f8122d35SGreg Clayton                      unsigned IndentLevel) const {
175f8122d35SGreg Clayton   OS.indent(2 * IndentLevel);
176f8122d35SGreg Clayton   if (hasAddress())
177f8122d35SGreg Clayton     OS << format("0x%" PRIx64 ": ", *Address);
178f8122d35SGreg Clayton   OS << "CFA=";
179f8122d35SGreg Clayton   CFAValue.dump(OS, MRI, IsEH);
180f8122d35SGreg Clayton   if (RegLocs.hasLocations()) {
181f8122d35SGreg Clayton     OS << ": ";
182f8122d35SGreg Clayton     RegLocs.dump(OS, MRI, IsEH);
183f8122d35SGreg Clayton   }
184f8122d35SGreg Clayton   OS << "\n";
185f8122d35SGreg Clayton }
186f8122d35SGreg Clayton 
operator <<(raw_ostream & OS,const UnwindRow & Row)187f8122d35SGreg Clayton raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindRow &Row) {
188f8122d35SGreg Clayton   Row.dump(OS, nullptr, false, 0);
189f8122d35SGreg Clayton   return OS;
190f8122d35SGreg Clayton }
191f8122d35SGreg Clayton 
dump(raw_ostream & OS,const MCRegisterInfo * MRI,bool IsEH,unsigned IndentLevel) const192f8122d35SGreg Clayton void UnwindTable::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
193f8122d35SGreg Clayton                        unsigned IndentLevel) const {
194f8122d35SGreg Clayton   for (const UnwindRow &Row : Rows)
195f8122d35SGreg Clayton     Row.dump(OS, MRI, IsEH, IndentLevel);
196f8122d35SGreg Clayton }
197f8122d35SGreg Clayton 
operator <<(raw_ostream & OS,const UnwindTable & Rows)198f8122d35SGreg Clayton raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindTable &Rows) {
199f8122d35SGreg Clayton   Rows.dump(OS, nullptr, false, 0);
200f8122d35SGreg Clayton   return OS;
201f8122d35SGreg Clayton }
202f8122d35SGreg Clayton 
create(const FDE * Fde)203f8122d35SGreg Clayton Expected<UnwindTable> UnwindTable::create(const FDE *Fde) {
204f8122d35SGreg Clayton   const CIE *Cie = Fde->getLinkedCIE();
205f8122d35SGreg Clayton   if (Cie == nullptr)
206f8122d35SGreg Clayton     return createStringError(errc::invalid_argument,
207f8122d35SGreg Clayton                              "unable to get CIE for FDE at offset 0x%" PRIx64,
208f8122d35SGreg Clayton                              Fde->getOffset());
209f8122d35SGreg Clayton 
210223852d7SRamNalamothu   // Rows will be empty if there are no CFI instructions.
211223852d7SRamNalamothu   if (Cie->cfis().empty() && Fde->cfis().empty())
212223852d7SRamNalamothu     return UnwindTable();
213223852d7SRamNalamothu 
214223852d7SRamNalamothu   UnwindTable UT;
215223852d7SRamNalamothu   UnwindRow Row;
216223852d7SRamNalamothu   Row.setAddress(Fde->getInitialLocation());
217223852d7SRamNalamothu   UT.EndAddress = Fde->getInitialLocation() + Fde->getAddressRange();
218f8122d35SGreg Clayton   if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr))
219f8122d35SGreg Clayton     return std::move(CieError);
220f8122d35SGreg Clayton   // We need to save the initial locations of registers from the CIE parsing
221f8122d35SGreg Clayton   // in case we run into DW_CFA_restore or DW_CFA_restore_extended opcodes.
222f8122d35SGreg Clayton   const RegisterLocations InitialLocs = Row.getRegisterLocations();
223f8122d35SGreg Clayton   if (Error FdeError = UT.parseRows(Fde->cfis(), Row, &InitialLocs))
224f8122d35SGreg Clayton     return std::move(FdeError);
225223852d7SRamNalamothu   // May be all the CFI instructions were DW_CFA_nop amd Row becomes empty.
226223852d7SRamNalamothu   // Do not add that to the unwind table.
227223852d7SRamNalamothu   if (Row.getRegisterLocations().hasLocations() ||
228223852d7SRamNalamothu       Row.getCFAValue().getLocation() != UnwindLocation::Unspecified)
229f8122d35SGreg Clayton     UT.Rows.push_back(Row);
230f8122d35SGreg Clayton   return UT;
231f8122d35SGreg Clayton }
232f8122d35SGreg Clayton 
create(const CIE * Cie)233f8122d35SGreg Clayton Expected<UnwindTable> UnwindTable::create(const CIE *Cie) {
234223852d7SRamNalamothu   // Rows will be empty if there are no CFI instructions.
235223852d7SRamNalamothu   if (Cie->cfis().empty())
236223852d7SRamNalamothu     return UnwindTable();
237223852d7SRamNalamothu 
238f8122d35SGreg Clayton   UnwindTable UT;
239f8122d35SGreg Clayton   UnwindRow Row;
240f8122d35SGreg Clayton   if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr))
241f8122d35SGreg Clayton     return std::move(CieError);
242223852d7SRamNalamothu   // May be all the CFI instructions were DW_CFA_nop amd Row becomes empty.
243223852d7SRamNalamothu   // Do not add that to the unwind table.
244223852d7SRamNalamothu   if (Row.getRegisterLocations().hasLocations() ||
245223852d7SRamNalamothu       Row.getCFAValue().getLocation() != UnwindLocation::Unspecified)
246f8122d35SGreg Clayton     UT.Rows.push_back(Row);
247f8122d35SGreg Clayton   return UT;
248f8122d35SGreg Clayton }
249f8122d35SGreg Clayton 
25082af9438SZachary Turner // See DWARF standard v3, section 7.23
25182af9438SZachary Turner const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
25282af9438SZachary Turner const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
25382af9438SZachary Turner 
parse(DWARFDataExtractor Data,uint64_t * Offset,uint64_t EndOffset)254f26a70a5SIgor Kudrin Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset,
255f26a70a5SIgor Kudrin                         uint64_t EndOffset) {
2561e820e82SGeorgii Rymar   DataExtractor::Cursor C(*Offset);
2571e820e82SGeorgii Rymar   while (C && C.tell() < EndOffset) {
2581e820e82SGeorgii Rymar     uint8_t Opcode = Data.getRelocatedValue(C, 1);
259bee8cdcaSGeorgii Rymar     if (!C)
260bee8cdcaSGeorgii Rymar       break;
26182af9438SZachary Turner 
262bee8cdcaSGeorgii Rymar     // Some instructions have a primary opcode encoded in the top bits.
263bee8cdcaSGeorgii Rymar     if (uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) {
26482af9438SZachary Turner       // If it's a primary opcode, the first operand is encoded in the bottom
26582af9438SZachary Turner       // bits of the opcode itself.
26682af9438SZachary Turner       uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
26782af9438SZachary Turner       switch (Primary) {
26882af9438SZachary Turner       case DW_CFA_advance_loc:
26982af9438SZachary Turner       case DW_CFA_restore:
27082af9438SZachary Turner         addInstruction(Primary, Op1);
27182af9438SZachary Turner         break;
27282af9438SZachary Turner       case DW_CFA_offset:
2731e820e82SGeorgii Rymar         addInstruction(Primary, Op1, Data.getULEB128(C));
27482af9438SZachary Turner         break;
275bee8cdcaSGeorgii Rymar       default:
276bee8cdcaSGeorgii Rymar         llvm_unreachable("invalid primary CFI opcode");
27782af9438SZachary Turner       }
278bee8cdcaSGeorgii Rymar       continue;
279bee8cdcaSGeorgii Rymar     }
280bee8cdcaSGeorgii Rymar 
28182af9438SZachary Turner     // Extended opcode - its value is Opcode itself.
28282af9438SZachary Turner     switch (Opcode) {
28386fb7bf2SRafael Auler     default:
284cba595daSVictor Leschuk       return createStringError(errc::illegal_byte_sequence,
285bee8cdcaSGeorgii Rymar                                "invalid extended CFI opcode 0x%" PRIx8, Opcode);
28682af9438SZachary Turner     case DW_CFA_nop:
28782af9438SZachary Turner     case DW_CFA_remember_state:
28882af9438SZachary Turner     case DW_CFA_restore_state:
28982af9438SZachary Turner     case DW_CFA_GNU_window_save:
29082af9438SZachary Turner       // No operands
29182af9438SZachary Turner       addInstruction(Opcode);
29282af9438SZachary Turner       break;
29382af9438SZachary Turner     case DW_CFA_set_loc:
29482af9438SZachary Turner       // Operands: Address
2951e820e82SGeorgii Rymar       addInstruction(Opcode, Data.getRelocatedAddress(C));
29682af9438SZachary Turner       break;
29782af9438SZachary Turner     case DW_CFA_advance_loc1:
29882af9438SZachary Turner       // Operands: 1-byte delta
2991e820e82SGeorgii Rymar       addInstruction(Opcode, Data.getRelocatedValue(C, 1));
30082af9438SZachary Turner       break;
30182af9438SZachary Turner     case DW_CFA_advance_loc2:
30282af9438SZachary Turner       // Operands: 2-byte delta
3031e820e82SGeorgii Rymar       addInstruction(Opcode, Data.getRelocatedValue(C, 2));
30482af9438SZachary Turner       break;
30582af9438SZachary Turner     case DW_CFA_advance_loc4:
30682af9438SZachary Turner       // Operands: 4-byte delta
3071e820e82SGeorgii Rymar       addInstruction(Opcode, Data.getRelocatedValue(C, 4));
30882af9438SZachary Turner       break;
30982af9438SZachary Turner     case DW_CFA_restore_extended:
31082af9438SZachary Turner     case DW_CFA_undefined:
31182af9438SZachary Turner     case DW_CFA_same_value:
31282af9438SZachary Turner     case DW_CFA_def_cfa_register:
31382af9438SZachary Turner     case DW_CFA_def_cfa_offset:
31468b285f6SGeorge Rimar     case DW_CFA_GNU_args_size:
31582af9438SZachary Turner       // Operands: ULEB128
3161e820e82SGeorgii Rymar       addInstruction(Opcode, Data.getULEB128(C));
31782af9438SZachary Turner       break;
31882af9438SZachary Turner     case DW_CFA_def_cfa_offset_sf:
31982af9438SZachary Turner       // Operands: SLEB128
3201e820e82SGeorgii Rymar       addInstruction(Opcode, Data.getSLEB128(C));
32182af9438SZachary Turner       break;
322167e7afcSRamNalamothu     case DW_CFA_LLVM_def_aspace_cfa:
323167e7afcSRamNalamothu     case DW_CFA_LLVM_def_aspace_cfa_sf: {
324167e7afcSRamNalamothu       auto RegNum = Data.getULEB128(C);
325167e7afcSRamNalamothu       auto CfaOffset = Opcode == DW_CFA_LLVM_def_aspace_cfa
326167e7afcSRamNalamothu                            ? Data.getULEB128(C)
327167e7afcSRamNalamothu                            : Data.getSLEB128(C);
328167e7afcSRamNalamothu       auto AddressSpace = Data.getULEB128(C);
329167e7afcSRamNalamothu       addInstruction(Opcode, RegNum, CfaOffset, AddressSpace);
330167e7afcSRamNalamothu       break;
331167e7afcSRamNalamothu     }
33282af9438SZachary Turner     case DW_CFA_offset_extended:
33382af9438SZachary Turner     case DW_CFA_register:
33482af9438SZachary Turner     case DW_CFA_def_cfa:
3350e1605a3SIgor Laevsky     case DW_CFA_val_offset: {
33682af9438SZachary Turner       // Operands: ULEB128, ULEB128
3370e1605a3SIgor Laevsky       // Note: We can not embed getULEB128 directly into function
3380e1605a3SIgor Laevsky       // argument list. getULEB128 changes Offset and order of evaluation
3390e1605a3SIgor Laevsky       // for arguments is unspecified.
3401e820e82SGeorgii Rymar       uint64_t op1 = Data.getULEB128(C);
3411e820e82SGeorgii Rymar       uint64_t op2 = Data.getULEB128(C);
3420e1605a3SIgor Laevsky       addInstruction(Opcode, op1, op2);
34382af9438SZachary Turner       break;
3440e1605a3SIgor Laevsky     }
34582af9438SZachary Turner     case DW_CFA_offset_extended_sf:
34682af9438SZachary Turner     case DW_CFA_def_cfa_sf:
3470e1605a3SIgor Laevsky     case DW_CFA_val_offset_sf: {
34882af9438SZachary Turner       // Operands: ULEB128, SLEB128
3490e1605a3SIgor Laevsky       // Note: see comment for the previous case
3501e820e82SGeorgii Rymar       uint64_t op1 = Data.getULEB128(C);
3511e820e82SGeorgii Rymar       uint64_t op2 = (uint64_t)Data.getSLEB128(C);
3520e1605a3SIgor Laevsky       addInstruction(Opcode, op1, op2);
35382af9438SZachary Turner       break;
3540e1605a3SIgor Laevsky     }
35586fb7bf2SRafael Auler     case DW_CFA_def_cfa_expression: {
3561e820e82SGeorgii Rymar       uint64_t ExprLength = Data.getULEB128(C);
35786fb7bf2SRafael Auler       addInstruction(Opcode, 0);
3581e820e82SGeorgii Rymar       StringRef Expression = Data.getBytes(C, ExprLength);
3591e820e82SGeorgii Rymar 
3601e820e82SGeorgii Rymar       DataExtractor Extractor(Expression, Data.isLittleEndian(),
3611e820e82SGeorgii Rymar                               Data.getAddressSize());
362befbc99aSFangrui Song       // Note. We do not pass the DWARF format to DWARFExpression, because
363befbc99aSFangrui Song       // DW_OP_call_ref, the only operation which depends on the format, is
364befbc99aSFangrui Song       // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
3658f3d47c5SIgor Kudrin       Instructions.back().Expression =
3668f3d47c5SIgor Kudrin           DWARFExpression(Extractor, Data.getAddressSize());
367c0a758d8SJonas Devlieghere       break;
36886fb7bf2SRafael Auler     }
36982af9438SZachary Turner     case DW_CFA_expression:
370c0a758d8SJonas Devlieghere     case DW_CFA_val_expression: {
3711e820e82SGeorgii Rymar       uint64_t RegNum = Data.getULEB128(C);
37286fb7bf2SRafael Auler       addInstruction(Opcode, RegNum, 0);
3731e820e82SGeorgii Rymar 
3741e820e82SGeorgii Rymar       uint64_t BlockLength = Data.getULEB128(C);
3751e820e82SGeorgii Rymar       StringRef Expression = Data.getBytes(C, BlockLength);
3761e820e82SGeorgii Rymar       DataExtractor Extractor(Expression, Data.isLittleEndian(),
3771e820e82SGeorgii Rymar                               Data.getAddressSize());
378befbc99aSFangrui Song       // Note. We do not pass the DWARF format to DWARFExpression, because
379befbc99aSFangrui Song       // DW_OP_call_ref, the only operation which depends on the format, is
380befbc99aSFangrui Song       // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
3818f3d47c5SIgor Kudrin       Instructions.back().Expression =
3828f3d47c5SIgor Kudrin           DWARFExpression(Extractor, Data.getAddressSize());
383c0a758d8SJonas Devlieghere       break;
384c0a758d8SJonas Devlieghere     }
38582af9438SZachary Turner     }
38682af9438SZachary Turner   }
38786fb7bf2SRafael Auler 
3881e820e82SGeorgii Rymar   *Offset = C.tell();
3891e820e82SGeorgii Rymar   return C.takeError();
39082af9438SZachary Turner }
39182af9438SZachary Turner 
callFrameString(unsigned Opcode) const392f8122d35SGreg Clayton StringRef CFIProgram::callFrameString(unsigned Opcode) const {
393f8122d35SGreg Clayton   return dwarf::CallFrameString(Opcode, Arch);
394f8122d35SGreg Clayton }
39561a72d88SEugene Zelenko 
operandTypeString(CFIProgram::OperandType OT)396f8122d35SGreg Clayton const char *CFIProgram::operandTypeString(CFIProgram::OperandType OT) {
397f8122d35SGreg Clayton #define ENUM_TO_CSTR(e)                                                        \
398f8122d35SGreg Clayton   case e:                                                                      \
399f8122d35SGreg Clayton     return #e;
400f8122d35SGreg Clayton   switch (OT) {
401f8122d35SGreg Clayton     ENUM_TO_CSTR(OT_Unset);
402f8122d35SGreg Clayton     ENUM_TO_CSTR(OT_None);
403f8122d35SGreg Clayton     ENUM_TO_CSTR(OT_Address);
404f8122d35SGreg Clayton     ENUM_TO_CSTR(OT_Offset);
405f8122d35SGreg Clayton     ENUM_TO_CSTR(OT_FactoredCodeOffset);
406f8122d35SGreg Clayton     ENUM_TO_CSTR(OT_SignedFactDataOffset);
407f8122d35SGreg Clayton     ENUM_TO_CSTR(OT_UnsignedFactDataOffset);
408f8122d35SGreg Clayton     ENUM_TO_CSTR(OT_Register);
409167e7afcSRamNalamothu     ENUM_TO_CSTR(OT_AddressSpace);
410f8122d35SGreg Clayton     ENUM_TO_CSTR(OT_Expression);
411f8122d35SGreg Clayton   }
412f8122d35SGreg Clayton   return "<unknown CFIProgram::OperandType>";
413f8122d35SGreg Clayton }
414c0dd7243SFrederic Riss 
415f8122d35SGreg Clayton llvm::Expected<uint64_t>
getOperandAsUnsigned(const CFIProgram & CFIP,uint32_t OperandIdx) const416f8122d35SGreg Clayton CFIProgram::Instruction::getOperandAsUnsigned(const CFIProgram &CFIP,
417f8122d35SGreg Clayton                                               uint32_t OperandIdx) const {
418167e7afcSRamNalamothu   if (OperandIdx >= MaxOperands)
419f8122d35SGreg Clayton     return createStringError(errc::invalid_argument,
420f8122d35SGreg Clayton                              "operand index %" PRIu32 " is not valid",
421f8122d35SGreg Clayton                              OperandIdx);
422f8122d35SGreg Clayton   OperandType Type = CFIP.getOperandTypes()[Opcode][OperandIdx];
423f8122d35SGreg Clayton   uint64_t Operand = Ops[OperandIdx];
424f8122d35SGreg Clayton   switch (Type) {
425f8122d35SGreg Clayton   case OT_Unset:
426f8122d35SGreg Clayton   case OT_None:
427f8122d35SGreg Clayton   case OT_Expression:
428f8122d35SGreg Clayton     return createStringError(errc::invalid_argument,
429f8122d35SGreg Clayton                              "op[%" PRIu32 "] has type %s which has no value",
430f8122d35SGreg Clayton                              OperandIdx, CFIProgram::operandTypeString(Type));
431f8122d35SGreg Clayton 
432f8122d35SGreg Clayton   case OT_Offset:
433f8122d35SGreg Clayton   case OT_SignedFactDataOffset:
434f8122d35SGreg Clayton   case OT_UnsignedFactDataOffset:
435f8122d35SGreg Clayton     return createStringError(
436f8122d35SGreg Clayton         errc::invalid_argument,
437f8122d35SGreg Clayton         "op[%" PRIu32 "] has OperandType OT_Offset which produces a signed "
438f8122d35SGreg Clayton         "result, call getOperandAsSigned instead",
439f8122d35SGreg Clayton         OperandIdx);
440f8122d35SGreg Clayton 
441f8122d35SGreg Clayton   case OT_Address:
442f8122d35SGreg Clayton   case OT_Register:
443167e7afcSRamNalamothu   case OT_AddressSpace:
444f8122d35SGreg Clayton     return Operand;
445f8122d35SGreg Clayton 
446f8122d35SGreg Clayton   case OT_FactoredCodeOffset: {
447f8122d35SGreg Clayton     const uint64_t CodeAlignmentFactor = CFIP.codeAlign();
448f8122d35SGreg Clayton     if (CodeAlignmentFactor == 0)
449f8122d35SGreg Clayton       return createStringError(
450f8122d35SGreg Clayton           errc::invalid_argument,
451f8122d35SGreg Clayton           "op[%" PRIu32 "] has type OT_FactoredCodeOffset but code alignment "
452f8122d35SGreg Clayton           "is zero",
453f8122d35SGreg Clayton           OperandIdx);
454f8122d35SGreg Clayton     return Operand * CodeAlignmentFactor;
455f8122d35SGreg Clayton   }
456f8122d35SGreg Clayton   }
457e5f258cbSYang Fan   llvm_unreachable("invalid operand type");
458f8122d35SGreg Clayton }
459f8122d35SGreg Clayton 
460f8122d35SGreg Clayton llvm::Expected<int64_t>
getOperandAsSigned(const CFIProgram & CFIP,uint32_t OperandIdx) const461f8122d35SGreg Clayton CFIProgram::Instruction::getOperandAsSigned(const CFIProgram &CFIP,
462f8122d35SGreg Clayton                                             uint32_t OperandIdx) const {
463167e7afcSRamNalamothu   if (OperandIdx >= MaxOperands)
464f8122d35SGreg Clayton     return createStringError(errc::invalid_argument,
465f8122d35SGreg Clayton                              "operand index %" PRIu32 " is not valid",
466f8122d35SGreg Clayton                              OperandIdx);
467f8122d35SGreg Clayton   OperandType Type = CFIP.getOperandTypes()[Opcode][OperandIdx];
468f8122d35SGreg Clayton   uint64_t Operand = Ops[OperandIdx];
469f8122d35SGreg Clayton   switch (Type) {
470f8122d35SGreg Clayton   case OT_Unset:
471f8122d35SGreg Clayton   case OT_None:
472f8122d35SGreg Clayton   case OT_Expression:
473f8122d35SGreg Clayton     return createStringError(errc::invalid_argument,
474f8122d35SGreg Clayton                              "op[%" PRIu32 "] has type %s which has no value",
475f8122d35SGreg Clayton                              OperandIdx, CFIProgram::operandTypeString(Type));
476f8122d35SGreg Clayton 
477f8122d35SGreg Clayton   case OT_Address:
478f8122d35SGreg Clayton   case OT_Register:
479167e7afcSRamNalamothu   case OT_AddressSpace:
480f8122d35SGreg Clayton     return createStringError(
481f8122d35SGreg Clayton         errc::invalid_argument,
482f8122d35SGreg Clayton         "op[%" PRIu32 "] has OperandType %s which produces an unsigned result, "
483f8122d35SGreg Clayton         "call getOperandAsUnsigned instead",
484f8122d35SGreg Clayton         OperandIdx, CFIProgram::operandTypeString(Type));
485f8122d35SGreg Clayton 
486f8122d35SGreg Clayton   case OT_Offset:
487f8122d35SGreg Clayton     return (int64_t)Operand;
488f8122d35SGreg Clayton 
489f8122d35SGreg Clayton   case OT_FactoredCodeOffset:
490f8122d35SGreg Clayton   case OT_SignedFactDataOffset: {
491f8122d35SGreg Clayton     const int64_t DataAlignmentFactor = CFIP.dataAlign();
492f8122d35SGreg Clayton     if (DataAlignmentFactor == 0)
493f8122d35SGreg Clayton       return createStringError(errc::invalid_argument,
494f8122d35SGreg Clayton                                "op[%" PRIu32 "] has type %s but data "
495f8122d35SGreg Clayton                                "alignment is zero",
496f8122d35SGreg Clayton                                OperandIdx, CFIProgram::operandTypeString(Type));
497f8122d35SGreg Clayton     return int64_t(Operand) * DataAlignmentFactor;
498f8122d35SGreg Clayton   }
499f8122d35SGreg Clayton 
500f8122d35SGreg Clayton   case OT_UnsignedFactDataOffset: {
501f8122d35SGreg Clayton     const int64_t DataAlignmentFactor = CFIP.dataAlign();
502f8122d35SGreg Clayton     if (DataAlignmentFactor == 0)
503f8122d35SGreg Clayton       return createStringError(errc::invalid_argument,
504f8122d35SGreg Clayton                                "op[%" PRIu32
505f8122d35SGreg Clayton                                "] has type OT_UnsignedFactDataOffset but data "
506f8122d35SGreg Clayton                                "alignment is zero",
507f8122d35SGreg Clayton                                OperandIdx);
508f8122d35SGreg Clayton     return Operand * DataAlignmentFactor;
509f8122d35SGreg Clayton   }
510f8122d35SGreg Clayton   }
511e5f258cbSYang Fan   llvm_unreachable("invalid operand type");
512f8122d35SGreg Clayton }
513f8122d35SGreg Clayton 
parseRows(const CFIProgram & CFIP,UnwindRow & Row,const RegisterLocations * InitialLocs)514f8122d35SGreg Clayton Error UnwindTable::parseRows(const CFIProgram &CFIP, UnwindRow &Row,
515f8122d35SGreg Clayton                              const RegisterLocations *InitialLocs) {
516f8122d35SGreg Clayton   std::vector<RegisterLocations> RegisterStates;
517f8122d35SGreg Clayton   for (const CFIProgram::Instruction &Inst : CFIP) {
518f8122d35SGreg Clayton     switch (Inst.Opcode) {
519f8122d35SGreg Clayton     case dwarf::DW_CFA_set_loc: {
520f8122d35SGreg Clayton       // The DW_CFA_set_loc instruction takes a single operand that
521f8122d35SGreg Clayton       // represents a target address. The required action is to create a new
522f8122d35SGreg Clayton       // table row using the specified address as the location. All other
523f8122d35SGreg Clayton       // values in the new row are initially identical to the current row.
524f8122d35SGreg Clayton       // The new location value is always greater than the current one. If
525f8122d35SGreg Clayton       // the segment_size field of this FDE's CIE is non- zero, the initial
526f8122d35SGreg Clayton       // location is preceded by a segment selector of the given length
527f8122d35SGreg Clayton       llvm::Expected<uint64_t> NewAddress = Inst.getOperandAsUnsigned(CFIP, 0);
528f8122d35SGreg Clayton       if (!NewAddress)
529f8122d35SGreg Clayton         return NewAddress.takeError();
530f8122d35SGreg Clayton       if (*NewAddress <= Row.getAddress())
531f8122d35SGreg Clayton         return createStringError(
532f8122d35SGreg Clayton             errc::invalid_argument,
533f8122d35SGreg Clayton             "%s with adrress 0x%" PRIx64 " which must be greater than the "
534f8122d35SGreg Clayton             "current row address 0x%" PRIx64,
535f8122d35SGreg Clayton             CFIP.callFrameString(Inst.Opcode).str().c_str(), *NewAddress,
536f8122d35SGreg Clayton             Row.getAddress());
537f8122d35SGreg Clayton       Rows.push_back(Row);
538f8122d35SGreg Clayton       Row.setAddress(*NewAddress);
539f8122d35SGreg Clayton       break;
540f8122d35SGreg Clayton     }
541f8122d35SGreg Clayton 
542f8122d35SGreg Clayton     case dwarf::DW_CFA_advance_loc:
543f8122d35SGreg Clayton     case dwarf::DW_CFA_advance_loc1:
544f8122d35SGreg Clayton     case dwarf::DW_CFA_advance_loc2:
545f8122d35SGreg Clayton     case dwarf::DW_CFA_advance_loc4: {
546f8122d35SGreg Clayton       // The DW_CFA_advance instruction takes a single operand that
547f8122d35SGreg Clayton       // represents a constant delta. The required action is to create a new
548f8122d35SGreg Clayton       // table row with a location value that is computed by taking the
549f8122d35SGreg Clayton       // current entry’s location value and adding the value of delta *
550f8122d35SGreg Clayton       // code_alignment_factor. All other values in the new row are initially
551f8122d35SGreg Clayton       // identical to the current row.
552f8122d35SGreg Clayton       Rows.push_back(Row);
553f8122d35SGreg Clayton       llvm::Expected<uint64_t> Offset = Inst.getOperandAsUnsigned(CFIP, 0);
554f8122d35SGreg Clayton       if (!Offset)
555f8122d35SGreg Clayton         return Offset.takeError();
556f8122d35SGreg Clayton       Row.slideAddress(*Offset);
557f8122d35SGreg Clayton       break;
558f8122d35SGreg Clayton     }
559f8122d35SGreg Clayton 
560f8122d35SGreg Clayton     case dwarf::DW_CFA_restore:
561f8122d35SGreg Clayton     case dwarf::DW_CFA_restore_extended: {
562f8122d35SGreg Clayton       // The DW_CFA_restore instruction takes a single operand (encoded with
563f8122d35SGreg Clayton       // the opcode) that represents a register number. The required action
564f8122d35SGreg Clayton       // is to change the rule for the indicated register to the rule
565f8122d35SGreg Clayton       // assigned it by the initial_instructions in the CIE.
566f8122d35SGreg Clayton       if (InitialLocs == nullptr)
567f8122d35SGreg Clayton         return createStringError(
568f8122d35SGreg Clayton             errc::invalid_argument, "%s encountered while parsing a CIE",
569f8122d35SGreg Clayton             CFIP.callFrameString(Inst.Opcode).str().c_str());
570f8122d35SGreg Clayton       llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
571f8122d35SGreg Clayton       if (!RegNum)
572f8122d35SGreg Clayton         return RegNum.takeError();
573f8122d35SGreg Clayton       if (Optional<UnwindLocation> O =
574f8122d35SGreg Clayton               InitialLocs->getRegisterLocation(*RegNum))
575f8122d35SGreg Clayton         Row.getRegisterLocations().setRegisterLocation(*RegNum, *O);
576f8122d35SGreg Clayton       else
577f8122d35SGreg Clayton         Row.getRegisterLocations().removeRegisterLocation(*RegNum);
578f8122d35SGreg Clayton       break;
579f8122d35SGreg Clayton     }
580f8122d35SGreg Clayton 
581f8122d35SGreg Clayton     case dwarf::DW_CFA_offset:
582f8122d35SGreg Clayton     case dwarf::DW_CFA_offset_extended:
583f8122d35SGreg Clayton     case dwarf::DW_CFA_offset_extended_sf: {
584f8122d35SGreg Clayton       llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
585f8122d35SGreg Clayton       if (!RegNum)
586f8122d35SGreg Clayton         return RegNum.takeError();
587f8122d35SGreg Clayton       llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1);
588f8122d35SGreg Clayton       if (!Offset)
589f8122d35SGreg Clayton         return Offset.takeError();
590f8122d35SGreg Clayton       Row.getRegisterLocations().setRegisterLocation(
591f8122d35SGreg Clayton           *RegNum, UnwindLocation::createAtCFAPlusOffset(*Offset));
592f8122d35SGreg Clayton       break;
593f8122d35SGreg Clayton     }
594f8122d35SGreg Clayton 
595f8122d35SGreg Clayton     case dwarf::DW_CFA_nop:
596f8122d35SGreg Clayton       break;
597f8122d35SGreg Clayton 
598f8122d35SGreg Clayton     case dwarf::DW_CFA_remember_state:
599f8122d35SGreg Clayton       RegisterStates.push_back(Row.getRegisterLocations());
600f8122d35SGreg Clayton       break;
601f8122d35SGreg Clayton 
602f8122d35SGreg Clayton     case dwarf::DW_CFA_restore_state:
603f8122d35SGreg Clayton       if (RegisterStates.empty())
604f8122d35SGreg Clayton         return createStringError(errc::invalid_argument,
605f8122d35SGreg Clayton                                  "DW_CFA_restore_state without a matching "
606f8122d35SGreg Clayton                                  "previous DW_CFA_remember_state");
607f8122d35SGreg Clayton       Row.getRegisterLocations() = RegisterStates.back();
608f8122d35SGreg Clayton       RegisterStates.pop_back();
609f8122d35SGreg Clayton       break;
610f8122d35SGreg Clayton 
611f8122d35SGreg Clayton     case dwarf::DW_CFA_GNU_window_save:
612f8122d35SGreg Clayton       switch (CFIP.triple()) {
613f8122d35SGreg Clayton       case Triple::aarch64:
614f8122d35SGreg Clayton       case Triple::aarch64_be:
615f8122d35SGreg Clayton       case Triple::aarch64_32: {
616f8122d35SGreg Clayton         // DW_CFA_GNU_window_save is used for different things on different
617f8122d35SGreg Clayton         // architectures. For aarch64 it is known as
618f8122d35SGreg Clayton         // DW_CFA_AARCH64_negate_ra_state. The action is to toggle the
619f8122d35SGreg Clayton         // value of the return address state between 1 and 0. If there is
620f8122d35SGreg Clayton         // no rule for the AARCH64_DWARF_PAUTH_RA_STATE register, then it
621f8122d35SGreg Clayton         // should be initially set to 1.
622f8122d35SGreg Clayton         constexpr uint32_t AArch64DWARFPAuthRaState = 34;
623f8122d35SGreg Clayton         auto LRLoc = Row.getRegisterLocations().getRegisterLocation(
624f8122d35SGreg Clayton             AArch64DWARFPAuthRaState);
625f8122d35SGreg Clayton         if (LRLoc) {
626f8122d35SGreg Clayton           if (LRLoc->getLocation() == UnwindLocation::Constant) {
627f8122d35SGreg Clayton             // Toggle the constant value from 0 to 1 or 1 to 0.
628f8122d35SGreg Clayton             LRLoc->setConstant(LRLoc->getConstant() ^ 1);
629f8122d35SGreg Clayton           } else {
630f8122d35SGreg Clayton             return createStringError(
631f8122d35SGreg Clayton                 errc::invalid_argument,
632f8122d35SGreg Clayton                 "%s encountered when existing rule for this register is not "
633f8122d35SGreg Clayton                 "a constant",
634f8122d35SGreg Clayton                 CFIP.callFrameString(Inst.Opcode).str().c_str());
635f8122d35SGreg Clayton           }
636f8122d35SGreg Clayton         } else {
637f8122d35SGreg Clayton           Row.getRegisterLocations().setRegisterLocation(
638f8122d35SGreg Clayton               AArch64DWARFPAuthRaState, UnwindLocation::createIsConstant(1));
639f8122d35SGreg Clayton         }
640f8122d35SGreg Clayton         break;
641f8122d35SGreg Clayton       }
642f8122d35SGreg Clayton 
643f8122d35SGreg Clayton       case Triple::sparc:
644f8122d35SGreg Clayton       case Triple::sparcv9:
645f8122d35SGreg Clayton       case Triple::sparcel:
646f8122d35SGreg Clayton         for (uint32_t RegNum = 16; RegNum < 32; ++RegNum) {
647f8122d35SGreg Clayton           Row.getRegisterLocations().setRegisterLocation(
648f8122d35SGreg Clayton               RegNum, UnwindLocation::createAtCFAPlusOffset((RegNum - 16) * 8));
649f8122d35SGreg Clayton         }
650f8122d35SGreg Clayton         break;
651f8122d35SGreg Clayton 
652f8122d35SGreg Clayton       default: {
653f8122d35SGreg Clayton         return createStringError(
654f8122d35SGreg Clayton             errc::not_supported,
655f8122d35SGreg Clayton             "DW_CFA opcode %#x is not supported for architecture %s",
656f8122d35SGreg Clayton             Inst.Opcode, Triple::getArchTypeName(CFIP.triple()).str().c_str());
657f8122d35SGreg Clayton 
658f8122d35SGreg Clayton         break;
659f8122d35SGreg Clayton       }
660f8122d35SGreg Clayton       }
661f8122d35SGreg Clayton       break;
662f8122d35SGreg Clayton 
663f8122d35SGreg Clayton     case dwarf::DW_CFA_undefined: {
664f8122d35SGreg Clayton       llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
665f8122d35SGreg Clayton       if (!RegNum)
666f8122d35SGreg Clayton         return RegNum.takeError();
667f8122d35SGreg Clayton       Row.getRegisterLocations().setRegisterLocation(
668f8122d35SGreg Clayton           *RegNum, UnwindLocation::createUndefined());
669f8122d35SGreg Clayton       break;
670f8122d35SGreg Clayton     }
671f8122d35SGreg Clayton 
672f8122d35SGreg Clayton     case dwarf::DW_CFA_same_value: {
673f8122d35SGreg Clayton       llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
674f8122d35SGreg Clayton       if (!RegNum)
675f8122d35SGreg Clayton         return RegNum.takeError();
676f8122d35SGreg Clayton       Row.getRegisterLocations().setRegisterLocation(
677f8122d35SGreg Clayton           *RegNum, UnwindLocation::createSame());
678f8122d35SGreg Clayton       break;
679f8122d35SGreg Clayton     }
680f8122d35SGreg Clayton 
681f8122d35SGreg Clayton     case dwarf::DW_CFA_GNU_args_size:
682f8122d35SGreg Clayton       break;
683f8122d35SGreg Clayton 
684f8122d35SGreg Clayton     case dwarf::DW_CFA_register: {
685f8122d35SGreg Clayton       llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
686f8122d35SGreg Clayton       if (!RegNum)
687f8122d35SGreg Clayton         return RegNum.takeError();
688f8122d35SGreg Clayton       llvm::Expected<uint64_t> NewRegNum = Inst.getOperandAsUnsigned(CFIP, 1);
689f8122d35SGreg Clayton       if (!NewRegNum)
690f8122d35SGreg Clayton         return NewRegNum.takeError();
691f8122d35SGreg Clayton       Row.getRegisterLocations().setRegisterLocation(
692f8122d35SGreg Clayton           *RegNum, UnwindLocation::createIsRegisterPlusOffset(*NewRegNum, 0));
693f8122d35SGreg Clayton       break;
694f8122d35SGreg Clayton     }
695f8122d35SGreg Clayton 
696f8122d35SGreg Clayton     case dwarf::DW_CFA_val_offset:
697f8122d35SGreg Clayton     case dwarf::DW_CFA_val_offset_sf: {
698f8122d35SGreg Clayton       llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
699f8122d35SGreg Clayton       if (!RegNum)
700f8122d35SGreg Clayton         return RegNum.takeError();
701f8122d35SGreg Clayton       llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1);
702f8122d35SGreg Clayton       if (!Offset)
703f8122d35SGreg Clayton         return Offset.takeError();
704f8122d35SGreg Clayton       Row.getRegisterLocations().setRegisterLocation(
705f8122d35SGreg Clayton           *RegNum, UnwindLocation::createIsCFAPlusOffset(*Offset));
706f8122d35SGreg Clayton       break;
707f8122d35SGreg Clayton     }
708f8122d35SGreg Clayton 
709f8122d35SGreg Clayton     case dwarf::DW_CFA_expression: {
710f8122d35SGreg Clayton       llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
711f8122d35SGreg Clayton       if (!RegNum)
712f8122d35SGreg Clayton         return RegNum.takeError();
713f8122d35SGreg Clayton       Row.getRegisterLocations().setRegisterLocation(
714f8122d35SGreg Clayton           *RegNum, UnwindLocation::createAtDWARFExpression(*Inst.Expression));
715f8122d35SGreg Clayton       break;
716f8122d35SGreg Clayton     }
717f8122d35SGreg Clayton 
718f8122d35SGreg Clayton     case dwarf::DW_CFA_val_expression: {
719f8122d35SGreg Clayton       llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
720f8122d35SGreg Clayton       if (!RegNum)
721f8122d35SGreg Clayton         return RegNum.takeError();
722f8122d35SGreg Clayton       Row.getRegisterLocations().setRegisterLocation(
723f8122d35SGreg Clayton           *RegNum, UnwindLocation::createIsDWARFExpression(*Inst.Expression));
724f8122d35SGreg Clayton       break;
725f8122d35SGreg Clayton     }
726f8122d35SGreg Clayton 
727f8122d35SGreg Clayton     case dwarf::DW_CFA_def_cfa_register: {
728f8122d35SGreg Clayton       llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
729f8122d35SGreg Clayton       if (!RegNum)
730f8122d35SGreg Clayton         return RegNum.takeError();
731f8122d35SGreg Clayton       if (Row.getCFAValue().getLocation() != UnwindLocation::RegPlusOffset)
732f8122d35SGreg Clayton         Row.getCFAValue() =
733f8122d35SGreg Clayton             UnwindLocation::createIsRegisterPlusOffset(*RegNum, 0);
734f8122d35SGreg Clayton       else
735f8122d35SGreg Clayton         Row.getCFAValue().setRegister(*RegNum);
736f8122d35SGreg Clayton       break;
737f8122d35SGreg Clayton     }
738f8122d35SGreg Clayton 
739f8122d35SGreg Clayton     case dwarf::DW_CFA_def_cfa_offset:
740f8122d35SGreg Clayton     case dwarf::DW_CFA_def_cfa_offset_sf: {
741f8122d35SGreg Clayton       llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 0);
742f8122d35SGreg Clayton       if (!Offset)
743f8122d35SGreg Clayton         return Offset.takeError();
744f8122d35SGreg Clayton       if (Row.getCFAValue().getLocation() != UnwindLocation::RegPlusOffset) {
745f8122d35SGreg Clayton         return createStringError(
746f8122d35SGreg Clayton             errc::invalid_argument,
747f8122d35SGreg Clayton             "%s found when CFA rule was not RegPlusOffset",
748f8122d35SGreg Clayton             CFIP.callFrameString(Inst.Opcode).str().c_str());
749f8122d35SGreg Clayton       }
750f8122d35SGreg Clayton       Row.getCFAValue().setOffset(*Offset);
751f8122d35SGreg Clayton       break;
752f8122d35SGreg Clayton     }
753f8122d35SGreg Clayton 
754f8122d35SGreg Clayton     case dwarf::DW_CFA_def_cfa:
755f8122d35SGreg Clayton     case dwarf::DW_CFA_def_cfa_sf: {
756f8122d35SGreg Clayton       llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
757f8122d35SGreg Clayton       if (!RegNum)
758f8122d35SGreg Clayton         return RegNum.takeError();
759f8122d35SGreg Clayton       llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1);
760f8122d35SGreg Clayton       if (!Offset)
761f8122d35SGreg Clayton         return Offset.takeError();
762f8122d35SGreg Clayton       Row.getCFAValue() =
763f8122d35SGreg Clayton           UnwindLocation::createIsRegisterPlusOffset(*RegNum, *Offset);
764f8122d35SGreg Clayton       break;
765f8122d35SGreg Clayton     }
766f8122d35SGreg Clayton 
767167e7afcSRamNalamothu     case dwarf::DW_CFA_LLVM_def_aspace_cfa:
768167e7afcSRamNalamothu     case dwarf::DW_CFA_LLVM_def_aspace_cfa_sf: {
769167e7afcSRamNalamothu       llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);
770167e7afcSRamNalamothu       if (!RegNum)
771167e7afcSRamNalamothu         return RegNum.takeError();
772167e7afcSRamNalamothu       llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1);
773167e7afcSRamNalamothu       if (!Offset)
774167e7afcSRamNalamothu         return Offset.takeError();
775167e7afcSRamNalamothu       llvm::Expected<uint32_t> CFAAddrSpace =
776167e7afcSRamNalamothu           Inst.getOperandAsUnsigned(CFIP, 2);
777167e7afcSRamNalamothu       if (!CFAAddrSpace)
778167e7afcSRamNalamothu         return CFAAddrSpace.takeError();
779167e7afcSRamNalamothu       Row.getCFAValue() = UnwindLocation::createIsRegisterPlusOffset(
780167e7afcSRamNalamothu           *RegNum, *Offset, *CFAAddrSpace);
781167e7afcSRamNalamothu       break;
782167e7afcSRamNalamothu     }
783167e7afcSRamNalamothu 
784f8122d35SGreg Clayton     case dwarf::DW_CFA_def_cfa_expression:
785f8122d35SGreg Clayton       Row.getCFAValue() =
786f8122d35SGreg Clayton           UnwindLocation::createIsDWARFExpression(*Inst.Expression);
787f8122d35SGreg Clayton       break;
788f8122d35SGreg Clayton     }
789f8122d35SGreg Clayton   }
790f8122d35SGreg Clayton   return Error::success();
791f8122d35SGreg Clayton }
79282af9438SZachary Turner 
793167e7afcSRamNalamothu ArrayRef<CFIProgram::OperandType[CFIProgram::MaxOperands]>
getOperandTypes()794167e7afcSRamNalamothu CFIProgram::getOperandTypes() {
795167e7afcSRamNalamothu   static OperandType OpTypes[DW_CFA_restore + 1][MaxOperands];
79686fb7bf2SRafael Auler   static bool Initialized = false;
79786fb7bf2SRafael Auler   if (Initialized) {
798167e7afcSRamNalamothu     return ArrayRef<OperandType[MaxOperands]>(&OpTypes[0], DW_CFA_restore + 1);
79986fb7bf2SRafael Auler   }
80086fb7bf2SRafael Auler   Initialized = true;
801c0dd7243SFrederic Riss 
802167e7afcSRamNalamothu #define DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OPTYPE2)                             \
803c0dd7243SFrederic Riss   do {                                                                         \
804c0dd7243SFrederic Riss     OpTypes[OP][0] = OPTYPE0;                                                  \
805c0dd7243SFrederic Riss     OpTypes[OP][1] = OPTYPE1;                                                  \
806167e7afcSRamNalamothu     OpTypes[OP][2] = OPTYPE2;                                                  \
80761a72d88SEugene Zelenko   } while (false)
808167e7afcSRamNalamothu #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1)                                      \
809167e7afcSRamNalamothu   DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OT_None)
810c0dd7243SFrederic Riss #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None)
811c0dd7243SFrederic Riss #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None)
812c0dd7243SFrederic Riss 
813c0dd7243SFrederic Riss   DECLARE_OP1(DW_CFA_set_loc, OT_Address);
814c0dd7243SFrederic Riss   DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset);
815c0dd7243SFrederic Riss   DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset);
816c0dd7243SFrederic Riss   DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset);
817c0dd7243SFrederic Riss   DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset);
818c0dd7243SFrederic Riss   DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset);
819c0dd7243SFrederic Riss   DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset);
820c0dd7243SFrederic Riss   DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset);
821c0dd7243SFrederic Riss   DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register);
822167e7afcSRamNalamothu   DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa, OT_Register, OT_Offset,
823167e7afcSRamNalamothu               OT_AddressSpace);
824167e7afcSRamNalamothu   DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa_sf, OT_Register,
825167e7afcSRamNalamothu               OT_SignedFactDataOffset, OT_AddressSpace);
826c0dd7243SFrederic Riss   DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset);
827c0dd7243SFrederic Riss   DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset);
828c0dd7243SFrederic Riss   DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression);
829c0dd7243SFrederic Riss   DECLARE_OP1(DW_CFA_undefined, OT_Register);
830c0dd7243SFrederic Riss   DECLARE_OP1(DW_CFA_same_value, OT_Register);
831c0dd7243SFrederic Riss   DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset);
832c0dd7243SFrederic Riss   DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset);
833c0dd7243SFrederic Riss   DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset);
834c0dd7243SFrederic Riss   DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset);
835c0dd7243SFrederic Riss   DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset);
836c0dd7243SFrederic Riss   DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register);
837c0dd7243SFrederic Riss   DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression);
838c0dd7243SFrederic Riss   DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression);
839c0dd7243SFrederic Riss   DECLARE_OP1(DW_CFA_restore, OT_Register);
840c0dd7243SFrederic Riss   DECLARE_OP1(DW_CFA_restore_extended, OT_Register);
841c0dd7243SFrederic Riss   DECLARE_OP0(DW_CFA_remember_state);
842c0dd7243SFrederic Riss   DECLARE_OP0(DW_CFA_restore_state);
843c0dd7243SFrederic Riss   DECLARE_OP0(DW_CFA_GNU_window_save);
844c0dd7243SFrederic Riss   DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset);
845c0dd7243SFrederic Riss   DECLARE_OP0(DW_CFA_nop);
846c0dd7243SFrederic Riss 
847c0dd7243SFrederic Riss #undef DECLARE_OP0
848c0dd7243SFrederic Riss #undef DECLARE_OP1
849c0dd7243SFrederic Riss #undef DECLARE_OP2
85061a72d88SEugene Zelenko 
851167e7afcSRamNalamothu   return ArrayRef<OperandType[MaxOperands]>(&OpTypes[0], DW_CFA_restore + 1);
852c0dd7243SFrederic Riss }
853c0dd7243SFrederic Riss 
85486fb7bf2SRafael Auler /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
printOperand(raw_ostream & OS,DIDumpOptions DumpOpts,const MCRegisterInfo * MRI,bool IsEH,const Instruction & Instr,unsigned OperandIdx,uint64_t Operand) const8550ec5baa1SDavid Blaikie void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
8560ec5baa1SDavid Blaikie                               const MCRegisterInfo *MRI, bool IsEH,
8570ec5baa1SDavid Blaikie                               const Instruction &Instr, unsigned OperandIdx,
8580ec5baa1SDavid Blaikie                               uint64_t Operand) const {
859167e7afcSRamNalamothu   assert(OperandIdx < MaxOperands);
86086fb7bf2SRafael Auler   uint8_t Opcode = Instr.Opcode;
86186fb7bf2SRafael Auler   OperandType Type = getOperandTypes()[Opcode][OperandIdx];
862c0dd7243SFrederic Riss 
863c0dd7243SFrederic Riss   switch (Type) {
864149f6eaeSMehdi Amini   case OT_Unset: {
865c0dd7243SFrederic Riss     OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";
866f8122d35SGreg Clayton     auto OpcodeName = callFrameString(Opcode);
867149f6eaeSMehdi Amini     if (!OpcodeName.empty())
868c0dd7243SFrederic Riss       OS << " " << OpcodeName;
869c0dd7243SFrederic Riss     else
870c0dd7243SFrederic Riss       OS << format(" Opcode %x",  Opcode);
871c0dd7243SFrederic Riss     break;
872149f6eaeSMehdi Amini   }
873c0dd7243SFrederic Riss   case OT_None:
874c0dd7243SFrederic Riss     break;
875c0dd7243SFrederic Riss   case OT_Address:
876c0dd7243SFrederic Riss     OS << format(" %" PRIx64, Operand);
877c0dd7243SFrederic Riss     break;
878c0dd7243SFrederic Riss   case OT_Offset:
879c0dd7243SFrederic Riss     // The offsets are all encoded in a unsigned form, but in practice
880c0dd7243SFrederic Riss     // consumers use them signed. It's most certainly legacy due to
881c0dd7243SFrederic Riss     // the lack of signed variants in the first Dwarf standards.
882c0dd7243SFrederic Riss     OS << format(" %+" PRId64, int64_t(Operand));
883c0dd7243SFrederic Riss     break;
884c0dd7243SFrederic Riss   case OT_FactoredCodeOffset: // Always Unsigned
885c0dd7243SFrederic Riss     if (CodeAlignmentFactor)
886c0dd7243SFrederic Riss       OS << format(" %" PRId64, Operand * CodeAlignmentFactor);
887c0dd7243SFrederic Riss     else
888c0dd7243SFrederic Riss       OS << format(" %" PRId64 "*code_alignment_factor" , Operand);
889c0dd7243SFrederic Riss     break;
890c0dd7243SFrederic Riss   case OT_SignedFactDataOffset:
891c0dd7243SFrederic Riss     if (DataAlignmentFactor)
892c0dd7243SFrederic Riss       OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor);
893c0dd7243SFrederic Riss     else
894c0dd7243SFrederic Riss       OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand));
895c0dd7243SFrederic Riss     break;
896c0dd7243SFrederic Riss   case OT_UnsignedFactDataOffset:
897c0dd7243SFrederic Riss     if (DataAlignmentFactor)
898c0dd7243SFrederic Riss       OS << format(" %" PRId64, Operand * DataAlignmentFactor);
899c0dd7243SFrederic Riss     else
900c0dd7243SFrederic Riss       OS << format(" %" PRId64 "*data_alignment_factor" , Operand);
901c0dd7243SFrederic Riss     break;
902c0dd7243SFrederic Riss   case OT_Register:
903a4b842e2SGreg Clayton     OS << ' ';
904a4b842e2SGreg Clayton     printRegister(OS, MRI, IsEH, Operand);
905c0dd7243SFrederic Riss     break;
906167e7afcSRamNalamothu   case OT_AddressSpace:
907167e7afcSRamNalamothu     OS << format(" in addrspace%" PRId64, Operand);
908167e7afcSRamNalamothu     break;
909c0dd7243SFrederic Riss   case OT_Expression:
91086fb7bf2SRafael Auler     assert(Instr.Expression && "missing DWARFExpression object");
91186fb7bf2SRafael Auler     OS << " ";
9120ec5baa1SDavid Blaikie     Instr.Expression->print(OS, DumpOpts, MRI, nullptr, IsEH);
913c0dd7243SFrederic Riss     break;
914c0dd7243SFrederic Riss   }
915c0dd7243SFrederic Riss }
916c0dd7243SFrederic Riss 
dump(raw_ostream & OS,DIDumpOptions DumpOpts,const MCRegisterInfo * MRI,bool IsEH,unsigned IndentLevel) const9170ec5baa1SDavid Blaikie void CFIProgram::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
9180ec5baa1SDavid Blaikie                       const MCRegisterInfo *MRI, bool IsEH,
91986fb7bf2SRafael Auler                       unsigned IndentLevel) const {
920056ad058SFrederic Riss   for (const auto &Instr : Instructions) {
921056ad058SFrederic Riss     uint8_t Opcode = Instr.Opcode;
92286fb7bf2SRafael Auler     OS.indent(2 * IndentLevel);
923f8122d35SGreg Clayton     OS << callFrameString(Opcode) << ":";
924c0dd7243SFrederic Riss     for (unsigned i = 0; i < Instr.Ops.size(); ++i)
9250ec5baa1SDavid Blaikie       printOperand(OS, DumpOpts, MRI, IsEH, Instr, i, Instr.Ops[i]);
926c0dd7243SFrederic Riss     OS << '\n';
927056ad058SFrederic Riss   }
928056ad058SFrederic Riss }
92982af9438SZachary Turner 
9301a837569SIgor Kudrin // Returns the CIE identifier to be used by the requested format.
9311a837569SIgor Kudrin // CIE ids for .debug_frame sections are defined in Section 7.24 of DWARFv5.
9321a837569SIgor Kudrin // For CIE ID in .eh_frame sections see
9331a837569SIgor Kudrin // https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
getCIEId(bool IsDWARF64,bool IsEH)9341a837569SIgor Kudrin constexpr uint64_t getCIEId(bool IsDWARF64, bool IsEH) {
9351a837569SIgor Kudrin   if (IsEH)
9361a837569SIgor Kudrin     return 0;
9371a837569SIgor Kudrin   if (IsDWARF64)
9381a837569SIgor Kudrin     return DW64_CIE_ID;
9391a837569SIgor Kudrin   return DW_CIE_ID;
9401a837569SIgor Kudrin }
9411a837569SIgor Kudrin 
dump(raw_ostream & OS,DIDumpOptions DumpOpts,const MCRegisterInfo * MRI,bool IsEH) const9420ec5baa1SDavid Blaikie void CIE::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
9430ec5baa1SDavid Blaikie                const MCRegisterInfo *MRI, bool IsEH) const {
94484c64335SGeorgii Rymar   // A CIE with a zero length is a terminator entry in the .eh_frame section.
9452e365ca2SGeorgii Rymar   if (IsEH && Length == 0) {
9462e365ca2SGeorgii Rymar     OS << format("%08" PRIx64, Offset) << " ZERO terminator\n";
9472e365ca2SGeorgii Rymar     return;
9482e365ca2SGeorgii Rymar   }
9492e365ca2SGeorgii Rymar 
950cada5b88SIgor Kudrin   OS << format("%08" PRIx64, Offset)
951cada5b88SIgor Kudrin      << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length)
952cada5b88SIgor Kudrin      << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8,
953cada5b88SIgor Kudrin                getCIEId(IsDWARF64, IsEH))
9544933ab2cSIgor Kudrin      << " CIE\n"
9557a3e664dSRafael Auler      << "  Format:                " << FormatString(IsDWARF64) << "\n";
9567a3e664dSRafael Auler   if (IsEH && Version != 1)
9577a3e664dSRafael Auler     OS << "WARNING: unsupported CIE version\n";
9587a3e664dSRafael Auler   OS << format("  Version:               %d\n", Version)
9594933ab2cSIgor Kudrin      << "  Augmentation:          \"" << Augmentation << "\"\n";
96086fb7bf2SRafael Auler   if (Version >= 4) {
96186fb7bf2SRafael Auler     OS << format("  Address size:          %u\n", (uint32_t)AddressSize);
96286fb7bf2SRafael Auler     OS << format("  Segment desc size:     %u\n",
96386fb7bf2SRafael Auler                  (uint32_t)SegmentDescriptorSize);
96486fb7bf2SRafael Auler   }
96586fb7bf2SRafael Auler   OS << format("  Code alignment factor: %u\n", (uint32_t)CodeAlignmentFactor);
96686fb7bf2SRafael Auler   OS << format("  Data alignment factor: %d\n", (int32_t)DataAlignmentFactor);
96786fb7bf2SRafael Auler   OS << format("  Return address column: %d\n", (int32_t)ReturnAddressRegister);
96886fb7bf2SRafael Auler   if (Personality)
96995817d36SPetar Jovanovic     OS << format("  Personality Address: %016" PRIx64 "\n", *Personality);
97086fb7bf2SRafael Auler   if (!AugmentationData.empty()) {
97186fb7bf2SRafael Auler     OS << "  Augmentation data:    ";
97286fb7bf2SRafael Auler     for (uint8_t Byte : AugmentationData)
97386fb7bf2SRafael Auler       OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf);
97486fb7bf2SRafael Auler     OS << "\n";
97586fb7bf2SRafael Auler   }
97686fb7bf2SRafael Auler   OS << "\n";
9770ec5baa1SDavid Blaikie   CFIs.dump(OS, DumpOpts, MRI, IsEH);
97886fb7bf2SRafael Auler   OS << "\n";
979f8122d35SGreg Clayton 
980f8122d35SGreg Clayton   if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))
981f8122d35SGreg Clayton     RowsOrErr->dump(OS, MRI, IsEH, 1);
982f8122d35SGreg Clayton   else {
983f8122d35SGreg Clayton     DumpOpts.RecoverableErrorHandler(joinErrors(
984f8122d35SGreg Clayton         createStringError(errc::invalid_argument,
985f8122d35SGreg Clayton                           "decoding the CIE opcodes into rows failed"),
986f8122d35SGreg Clayton         RowsOrErr.takeError()));
987f8122d35SGreg Clayton   }
988f8122d35SGreg Clayton   OS << "\n";
98986fb7bf2SRafael Auler }
99086fb7bf2SRafael Auler 
dump(raw_ostream & OS,DIDumpOptions DumpOpts,const MCRegisterInfo * MRI,bool IsEH) const9910ec5baa1SDavid Blaikie void FDE::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
9920ec5baa1SDavid Blaikie                const MCRegisterInfo *MRI, bool IsEH) const {
993cada5b88SIgor Kudrin   OS << format("%08" PRIx64, Offset)
994cada5b88SIgor Kudrin      << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length)
995cada5b88SIgor Kudrin      << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8, CIEPointer)
996bd2df13eSIgor Kudrin      << " FDE cie=";
997bd2df13eSIgor Kudrin   if (LinkedCIE)
998cada5b88SIgor Kudrin     OS << format("%08" PRIx64, LinkedCIE->getOffset());
999bd2df13eSIgor Kudrin   else
1000bd2df13eSIgor Kudrin     OS << "<invalid offset>";
1001cada5b88SIgor Kudrin   OS << format(" pc=%08" PRIx64 "...%08" PRIx64 "\n", InitialLocation,
1002cada5b88SIgor Kudrin                InitialLocation + AddressRange);
10034933ab2cSIgor Kudrin   OS << "  Format:       " << FormatString(IsDWARF64) << "\n";
100486fb7bf2SRafael Auler   if (LSDAAddress)
100595817d36SPetar Jovanovic     OS << format("  LSDA Address: %016" PRIx64 "\n", *LSDAAddress);
10060ec5baa1SDavid Blaikie   CFIs.dump(OS, DumpOpts, MRI, IsEH);
100786fb7bf2SRafael Auler   OS << "\n";
1008f8122d35SGreg Clayton 
1009f8122d35SGreg Clayton   if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))
1010f8122d35SGreg Clayton     RowsOrErr->dump(OS, MRI, IsEH, 1);
1011f8122d35SGreg Clayton   else {
1012f8122d35SGreg Clayton     DumpOpts.RecoverableErrorHandler(joinErrors(
1013f8122d35SGreg Clayton         createStringError(errc::invalid_argument,
1014f8122d35SGreg Clayton                           "decoding the FDE opcodes into rows failed"),
1015f8122d35SGreg Clayton         RowsOrErr.takeError()));
1016f8122d35SGreg Clayton   }
1017f8122d35SGreg Clayton   OS << "\n";
101886fb7bf2SRafael Auler }
101986fb7bf2SRafael Auler 
DWARFDebugFrame(Triple::ArchType Arch,bool IsEH,uint64_t EHFrameAddress)1020f57d7d82SLuke Cheeseman DWARFDebugFrame::DWARFDebugFrame(Triple::ArchType Arch,
1021f57d7d82SLuke Cheeseman     bool IsEH, uint64_t EHFrameAddress)
1022f57d7d82SLuke Cheeseman     : Arch(Arch), IsEH(IsEH), EHFrameAddress(EHFrameAddress) {}
102382af9438SZachary Turner 
1024570e39a2SEugene Zelenko DWARFDebugFrame::~DWARFDebugFrame() = default;
102582af9438SZachary Turner 
dumpDataAux(DataExtractor Data,uint64_t Offset,int Length)102682af9438SZachary Turner static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
1027f26a70a5SIgor Kudrin                                               uint64_t Offset, int Length) {
102882af9438SZachary Turner   errs() << "DUMP: ";
102982af9438SZachary Turner   for (int i = 0; i < Length; ++i) {
103082af9438SZachary Turner     uint8_t c = Data.getU8(&Offset);
103182af9438SZachary Turner     errs().write_hex(c); errs() << " ";
103282af9438SZachary Turner   }
103382af9438SZachary Turner   errs() << "\n";
103482af9438SZachary Turner }
103582af9438SZachary Turner 
parse(DWARFDataExtractor Data)1036710d9d66SGeorgii Rymar Error DWARFDebugFrame::parse(DWARFDataExtractor Data) {
1037f26a70a5SIgor Kudrin   uint64_t Offset = 0;
1038f26a70a5SIgor Kudrin   DenseMap<uint64_t, CIE *> CIEs;
103982af9438SZachary Turner 
104082af9438SZachary Turner   while (Data.isValidOffset(Offset)) {
1041f26a70a5SIgor Kudrin     uint64_t StartOffset = Offset;
104282af9438SZachary Turner 
1043bddab928SPavel Labath     uint64_t Length;
1044bddab928SPavel Labath     DwarfFormat Format;
1045bddab928SPavel Labath     std::tie(Length, Format) = Data.getInitialLength(&Offset);
10462569787eSGeorgii Rymar     bool IsDWARF64 = Format == DWARF64;
10472569787eSGeorgii Rymar 
10482569787eSGeorgii Rymar     // If the Length is 0, then this CIE is a terminator. We add it because some
10492569787eSGeorgii Rymar     // dumper tools might need it to print something special for such entries
10502569787eSGeorgii Rymar     // (e.g. llvm-objdump --dwarf=frames prints "ZERO terminator").
10512569787eSGeorgii Rymar     if (Length == 0) {
10522569787eSGeorgii Rymar       auto Cie = std::make_unique<CIE>(
10532569787eSGeorgii Rymar           IsDWARF64, StartOffset, 0, 0, SmallString<8>(), 0, 0, 0, 0, 0,
10542569787eSGeorgii Rymar           SmallString<8>(), 0, 0, None, None, Arch);
10552569787eSGeorgii Rymar       CIEs[StartOffset] = Cie.get();
10562569787eSGeorgii Rymar       Entries.push_back(std::move(Cie));
10572569787eSGeorgii Rymar       break;
10582569787eSGeorgii Rymar     }
105982af9438SZachary Turner 
106082af9438SZachary Turner     // At this point, Offset points to the next field after Length.
106182af9438SZachary Turner     // Length is the structure size excluding itself. Compute an offset one
106282af9438SZachary Turner     // past the end of the structure (needed to know how many instructions to
106382af9438SZachary Turner     // read).
1064f26a70a5SIgor Kudrin     uint64_t StartStructureOffset = Offset;
1065f26a70a5SIgor Kudrin     uint64_t EndStructureOffset = Offset + Length;
106682af9438SZachary Turner 
106782af9438SZachary Turner     // The Id field's size depends on the DWARF format
10682569787eSGeorgii Rymar     Error Err = Error::success();
10692569787eSGeorgii Rymar     uint64_t Id = Data.getRelocatedValue((IsDWARF64 && !IsEH) ? 8 : 4, &Offset,
10702569787eSGeorgii Rymar                                          /*SectionIndex=*/nullptr, &Err);
10712569787eSGeorgii Rymar     if (Err)
10722569787eSGeorgii Rymar       return Err;
10732569787eSGeorgii Rymar 
10741a837569SIgor Kudrin     if (Id == getCIEId(IsDWARF64, IsEH)) {
107582af9438SZachary Turner       uint8_t Version = Data.getU8(&Offset);
107682af9438SZachary Turner       const char *Augmentation = Data.getCStr(&Offset);
107703a670c0SIgor Laevsky       StringRef AugmentationString(Augmentation ? Augmentation : "");
107803a670c0SIgor Laevsky       uint8_t AddressSize = Version < 4 ? Data.getAddressSize() :
107903a670c0SIgor Laevsky                                           Data.getU8(&Offset);
1080ea9483f8SKeith Walker       Data.setAddressSize(AddressSize);
1081ea9483f8SKeith Walker       uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset);
108282af9438SZachary Turner       uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
108382af9438SZachary Turner       int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
10847e981f33SGeorge Rimar       uint64_t ReturnAddressRegister =
10857e981f33SGeorge Rimar           Version == 1 ? Data.getU8(&Offset) : Data.getULEB128(&Offset);
108682af9438SZachary Turner 
108703a670c0SIgor Laevsky       // Parse the augmentation data for EH CIEs
1088ff291b58SIgor Laevsky       StringRef AugmentationData("");
1089fa762cc1SMaksim Panchenko       uint32_t FDEPointerEncoding = DW_EH_PE_absptr;
1090ff291b58SIgor Laevsky       uint32_t LSDAPointerEncoding = DW_EH_PE_omit;
10916aa8b349SRui Ueyama       Optional<uint64_t> Personality;
109286fb7bf2SRafael Auler       Optional<uint32_t> PersonalityEncoding;
109386fb7bf2SRafael Auler       if (IsEH) {
1094ff291b58SIgor Laevsky         Optional<uint64_t> AugmentationLength;
1095f26a70a5SIgor Kudrin         uint64_t StartAugmentationOffset;
1096f26a70a5SIgor Kudrin         uint64_t EndAugmentationOffset;
109703a670c0SIgor Laevsky 
109803a670c0SIgor Laevsky         // Walk the augmentation string to get all the augmentation data.
109903a670c0SIgor Laevsky         for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) {
110003a670c0SIgor Laevsky           switch (AugmentationString[i]) {
110103a670c0SIgor Laevsky           default:
1102710d9d66SGeorgii Rymar             return createStringError(
1103710d9d66SGeorgii Rymar                 errc::invalid_argument,
1104f6087525SFlorian Mayer                 "unknown augmentation character %c in entry at 0x%" PRIx64,
1105f6087525SFlorian Mayer                 AugmentationString[i], StartOffset);
110603a670c0SIgor Laevsky           case 'L':
110703a670c0SIgor Laevsky             LSDAPointerEncoding = Data.getU8(&Offset);
110803a670c0SIgor Laevsky             break;
110903a670c0SIgor Laevsky           case 'P': {
111003a670c0SIgor Laevsky             if (Personality)
1111710d9d66SGeorgii Rymar               return createStringError(
1112710d9d66SGeorgii Rymar                   errc::invalid_argument,
1113710d9d66SGeorgii Rymar                   "duplicate personality in entry at 0x%" PRIx64, StartOffset);
111403a670c0SIgor Laevsky             PersonalityEncoding = Data.getU8(&Offset);
111586fb7bf2SRafael Auler             Personality = Data.getEncodedPointer(
111686fb7bf2SRafael Auler                 &Offset, *PersonalityEncoding,
111786fb7bf2SRafael Auler                 EHFrameAddress ? EHFrameAddress + Offset : 0);
111803a670c0SIgor Laevsky             break;
111903a670c0SIgor Laevsky           }
112003a670c0SIgor Laevsky           case 'R':
112103a670c0SIgor Laevsky             FDEPointerEncoding = Data.getU8(&Offset);
112203a670c0SIgor Laevsky             break;
1123bd088560SFangrui Song           case 'S':
1124bd088560SFangrui Song             // Current frame is a signal trampoline.
1125bd088560SFangrui Song             break;
112603a670c0SIgor Laevsky           case 'z':
112703a670c0SIgor Laevsky             if (i)
1128710d9d66SGeorgii Rymar               return createStringError(
1129710d9d66SGeorgii Rymar                   errc::invalid_argument,
1130710d9d66SGeorgii Rymar                   "'z' must be the first character at 0x%" PRIx64, StartOffset);
113103a670c0SIgor Laevsky             // Parse the augmentation length first.  We only parse it if
113203a670c0SIgor Laevsky             // the string contains a 'z'.
113303a670c0SIgor Laevsky             AugmentationLength = Data.getULEB128(&Offset);
113403a670c0SIgor Laevsky             StartAugmentationOffset = Offset;
1135f26a70a5SIgor Kudrin             EndAugmentationOffset = Offset + *AugmentationLength;
113641a9e535SLuke Cheeseman             break;
113741a9e535SLuke Cheeseman           case 'B':
113841a9e535SLuke Cheeseman             // B-Key is used for signing functions associated with this
113941a9e535SLuke Cheeseman             // augmentation string
114041a9e535SLuke Cheeseman             break;
1141a2695c3fSFlorian Mayer             // This stack frame contains MTE tagged data, so needs to be
1142a2695c3fSFlorian Mayer             // untagged on unwind.
1143a2695c3fSFlorian Mayer           case 'G':
1144a2695c3fSFlorian Mayer             break;
114503a670c0SIgor Laevsky           }
114603a670c0SIgor Laevsky         }
114703a670c0SIgor Laevsky 
1148*e0e687a6SKazu Hirata         if (AugmentationLength) {
114903a670c0SIgor Laevsky           if (Offset != EndAugmentationOffset)
1150710d9d66SGeorgii Rymar             return createStringError(errc::invalid_argument,
1151710d9d66SGeorgii Rymar                                      "parsing augmentation data at 0x%" PRIx64
1152710d9d66SGeorgii Rymar                                      " failed",
1153710d9d66SGeorgii Rymar                                      StartOffset);
115403a670c0SIgor Laevsky           AugmentationData = Data.getData().slice(StartAugmentationOffset,
115503a670c0SIgor Laevsky                                                   EndAugmentationOffset);
115603a670c0SIgor Laevsky         }
1157ff291b58SIgor Laevsky       }
115803a670c0SIgor Laevsky 
11590eaee545SJonas Devlieghere       auto Cie = std::make_unique<CIE>(
1160cada5b88SIgor Kudrin           IsDWARF64, StartOffset, Length, Version, AugmentationString,
1161cada5b88SIgor Kudrin           AddressSize, SegmentDescriptorSize, CodeAlignmentFactor,
1162cada5b88SIgor Kudrin           DataAlignmentFactor, ReturnAddressRegister, AugmentationData,
1163cada5b88SIgor Kudrin           FDEPointerEncoding, LSDAPointerEncoding, Personality,
1164cada5b88SIgor Kudrin           PersonalityEncoding, Arch);
1165baf195f7SFrederic Riss       CIEs[StartOffset] = Cie.get();
1166baf195f7SFrederic Riss       Entries.emplace_back(std::move(Cie));
116782af9438SZachary Turner     } else {
116882af9438SZachary Turner       // FDE
116982af9438SZachary Turner       uint64_t CIEPointer = Id;
117003a670c0SIgor Laevsky       uint64_t InitialLocation = 0;
117103a670c0SIgor Laevsky       uint64_t AddressRange = 0;
117286fb7bf2SRafael Auler       Optional<uint64_t> LSDAAddress;
117303a670c0SIgor Laevsky       CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer];
117403a670c0SIgor Laevsky 
117503a670c0SIgor Laevsky       if (IsEH) {
117603a670c0SIgor Laevsky         // The address size is encoded in the CIE we reference.
117703a670c0SIgor Laevsky         if (!Cie)
1178710d9d66SGeorgii Rymar           return createStringError(errc::invalid_argument,
1179710d9d66SGeorgii Rymar                                    "parsing FDE data at 0x%" PRIx64
1180710d9d66SGeorgii Rymar                                    " failed due to missing CIE",
1181710d9d66SGeorgii Rymar                                    StartOffset);
11823ab0f53eSFangrui Song         if (auto Val =
11833ab0f53eSFangrui Song                 Data.getEncodedPointer(&Offset, Cie->getFDEPointerEncoding(),
11843ab0f53eSFangrui Song                                        EHFrameAddress + Offset)) {
118586fb7bf2SRafael Auler           InitialLocation = *Val;
118686fb7bf2SRafael Auler         }
118786fb7bf2SRafael Auler         if (auto Val = Data.getEncodedPointer(
118886fb7bf2SRafael Auler                 &Offset, Cie->getFDEPointerEncoding(), 0)) {
118986fb7bf2SRafael Auler           AddressRange = *Val;
119086fb7bf2SRafael Auler         }
119103a670c0SIgor Laevsky 
119203a670c0SIgor Laevsky         StringRef AugmentationString = Cie->getAugmentationString();
119303a670c0SIgor Laevsky         if (!AugmentationString.empty()) {
119403a670c0SIgor Laevsky           // Parse the augmentation length and data for this FDE.
119503a670c0SIgor Laevsky           uint64_t AugmentationLength = Data.getULEB128(&Offset);
119603a670c0SIgor Laevsky 
1197f26a70a5SIgor Kudrin           uint64_t EndAugmentationOffset = Offset + AugmentationLength;
119803a670c0SIgor Laevsky 
119903a670c0SIgor Laevsky           // Decode the LSDA if the CIE augmentation string said we should.
120086fb7bf2SRafael Auler           if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) {
120186fb7bf2SRafael Auler             LSDAAddress = Data.getEncodedPointer(
120286fb7bf2SRafael Auler                 &Offset, Cie->getLSDAPointerEncoding(),
120386fb7bf2SRafael Auler                 EHFrameAddress ? Offset + EHFrameAddress : 0);
120486fb7bf2SRafael Auler           }
120503a670c0SIgor Laevsky 
120603a670c0SIgor Laevsky           if (Offset != EndAugmentationOffset)
1207710d9d66SGeorgii Rymar             return createStringError(errc::invalid_argument,
1208710d9d66SGeorgii Rymar                                      "parsing augmentation data at 0x%" PRIx64
1209710d9d66SGeorgii Rymar                                      " failed",
1210710d9d66SGeorgii Rymar                                      StartOffset);
121103a670c0SIgor Laevsky         }
121203a670c0SIgor Laevsky       } else {
121318ccfaddSHsiangkai Wang         InitialLocation = Data.getRelocatedAddress(&Offset);
121418ccfaddSHsiangkai Wang         AddressRange = Data.getRelocatedAddress(&Offset);
121503a670c0SIgor Laevsky       }
121682af9438SZachary Turner 
1217cada5b88SIgor Kudrin       Entries.emplace_back(new FDE(IsDWARF64, StartOffset, Length, CIEPointer,
1218cada5b88SIgor Kudrin                                    InitialLocation, AddressRange, Cie,
1219cada5b88SIgor Kudrin                                    LSDAAddress, Arch));
122082af9438SZachary Turner     }
122182af9438SZachary Turner 
122286fb7bf2SRafael Auler     if (Error E =
1223710d9d66SGeorgii Rymar             Entries.back()->cfis().parse(Data, &Offset, EndStructureOffset))
1224710d9d66SGeorgii Rymar       return E;
122582af9438SZachary Turner 
122603a670c0SIgor Laevsky     if (Offset != EndStructureOffset)
1227710d9d66SGeorgii Rymar       return createStringError(
1228710d9d66SGeorgii Rymar           errc::invalid_argument,
1229710d9d66SGeorgii Rymar           "parsing entry instructions at 0x%" PRIx64 " failed", StartOffset);
123082af9438SZachary Turner   }
1231710d9d66SGeorgii Rymar 
1232710d9d66SGeorgii Rymar   return Error::success();
123382af9438SZachary Turner }
123482af9438SZachary Turner 
getEntryAtOffset(uint64_t Offset) const123562528e69SAdrian Prantl FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const {
123678ee2fbfSFangrui Song   auto It = partition_point(Entries, [=](const std::unique_ptr<FrameEntry> &E) {
123778ee2fbfSFangrui Song     return E->getOffset() < Offset;
1238dc8de603SFangrui Song   });
123962528e69SAdrian Prantl   if (It != Entries.end() && (*It)->getOffset() == Offset)
124062528e69SAdrian Prantl     return It->get();
124162528e69SAdrian Prantl   return nullptr;
124282af9438SZachary Turner }
124362528e69SAdrian Prantl 
dump(raw_ostream & OS,DIDumpOptions DumpOpts,const MCRegisterInfo * MRI,Optional<uint64_t> Offset) const12440ec5baa1SDavid Blaikie void DWARFDebugFrame::dump(raw_ostream &OS, DIDumpOptions DumpOpts,
12450ec5baa1SDavid Blaikie                            const MCRegisterInfo *MRI,
124686fb7bf2SRafael Auler                            Optional<uint64_t> Offset) const {
124762528e69SAdrian Prantl   if (Offset) {
124862528e69SAdrian Prantl     if (auto *Entry = getEntryAtOffset(*Offset))
12490ec5baa1SDavid Blaikie       Entry->dump(OS, DumpOpts, MRI, IsEH);
125062528e69SAdrian Prantl     return;
125162528e69SAdrian Prantl   }
125262528e69SAdrian Prantl 
125362528e69SAdrian Prantl   OS << "\n";
125462528e69SAdrian Prantl   for (const auto &Entry : Entries)
12550ec5baa1SDavid Blaikie     Entry->dump(OS, DumpOpts, MRI, IsEH);
125682af9438SZachary Turner }
1257