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