1//===- DWARFCFIProgram.cpp - Parsing the cfi-portions of .debug_frame -----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h"
10#include "llvm/DebugInfo/DWARF/LowLevel/DWARFDataExtractorSimple.h"
11#include "llvm/Support/Compiler.h"
12#include "llvm/Support/DataExtractor.h"
13#include "llvm/Support/Errc.h"
14#include "llvm/Support/ErrorHandling.h"
15#include "llvm/Support/Format.h"
16#include "llvm/Support/raw_ostream.h"
17#include <cassert>
18#include <cinttypes>
19#include <cstdint>
20#include <optional>
21
22using namespace llvm;
23using namespace dwarf;
24
25StringRef CFIProgram::callFrameString(unsigned Opcode) const {
26 return dwarf::CallFrameString(Encoding: Opcode, Arch);
27}
28
29const char *CFIProgram::operandTypeString(CFIProgram::OperandType OT) {
30#define ENUM_TO_CSTR(e) \
31 case e: \
32 return #e;
33 switch (OT) {
34 ENUM_TO_CSTR(OT_Unset);
35 ENUM_TO_CSTR(OT_None);
36 ENUM_TO_CSTR(OT_Address);
37 ENUM_TO_CSTR(OT_Offset);
38 ENUM_TO_CSTR(OT_FactoredCodeOffset);
39 ENUM_TO_CSTR(OT_SignedFactDataOffset);
40 ENUM_TO_CSTR(OT_UnsignedFactDataOffset);
41 ENUM_TO_CSTR(OT_Register);
42 ENUM_TO_CSTR(OT_AddressSpace);
43 ENUM_TO_CSTR(OT_Expression);
44 }
45 return "<unknown CFIProgram::OperandType>";
46}
47
48llvm::Expected<uint64_t>
49CFIProgram::Instruction::getOperandAsUnsigned(const CFIProgram &CFIP,
50 uint32_t OperandIdx) const {
51 if (OperandIdx >= MaxOperands)
52 return createStringError(EC: errc::invalid_argument,
53 Fmt: "operand index %" PRIu32 " is not valid",
54 Vals: OperandIdx);
55 OperandType Type = CFIP.getOperandTypes()[Opcode][OperandIdx];
56 uint64_t Operand = Ops[OperandIdx];
57 switch (Type) {
58 case OT_Unset:
59 case OT_None:
60 case OT_Expression:
61 return createStringError(EC: errc::invalid_argument,
62 Fmt: "op[%" PRIu32 "] has type %s which has no value",
63 Vals: OperandIdx, Vals: CFIProgram::operandTypeString(OT: Type));
64
65 case OT_Offset:
66 case OT_SignedFactDataOffset:
67 case OT_UnsignedFactDataOffset:
68 return createStringError(
69 EC: errc::invalid_argument,
70 Fmt: "op[%" PRIu32 "] has OperandType OT_Offset which produces a signed "
71 "result, call getOperandAsSigned instead",
72 Vals: OperandIdx);
73
74 case OT_Address:
75 case OT_Register:
76 case OT_AddressSpace:
77 return Operand;
78
79 case OT_FactoredCodeOffset: {
80 const uint64_t CodeAlignmentFactor = CFIP.codeAlign();
81 if (CodeAlignmentFactor == 0)
82 return createStringError(
83 EC: errc::invalid_argument,
84 Fmt: "op[%" PRIu32 "] has type OT_FactoredCodeOffset but code alignment "
85 "is zero",
86 Vals: OperandIdx);
87 return Operand * CodeAlignmentFactor;
88 }
89 }
90 llvm_unreachable("invalid operand type");
91}
92
93llvm::Expected<int64_t>
94CFIProgram::Instruction::getOperandAsSigned(const CFIProgram &CFIP,
95 uint32_t OperandIdx) const {
96 if (OperandIdx >= MaxOperands)
97 return createStringError(EC: errc::invalid_argument,
98 Fmt: "operand index %" PRIu32 " is not valid",
99 Vals: OperandIdx);
100 OperandType Type = CFIP.getOperandTypes()[Opcode][OperandIdx];
101 uint64_t Operand = Ops[OperandIdx];
102 switch (Type) {
103 case OT_Unset:
104 case OT_None:
105 case OT_Expression:
106 return createStringError(EC: errc::invalid_argument,
107 Fmt: "op[%" PRIu32 "] has type %s which has no value",
108 Vals: OperandIdx, Vals: CFIProgram::operandTypeString(OT: Type));
109
110 case OT_Address:
111 case OT_Register:
112 case OT_AddressSpace:
113 return createStringError(
114 EC: errc::invalid_argument,
115 Fmt: "op[%" PRIu32 "] has OperandType %s which produces an unsigned result, "
116 "call getOperandAsUnsigned instead",
117 Vals: OperandIdx, Vals: CFIProgram::operandTypeString(OT: Type));
118
119 case OT_Offset:
120 return (int64_t)Operand;
121
122 case OT_FactoredCodeOffset:
123 case OT_SignedFactDataOffset: {
124 const int64_t DataAlignmentFactor = CFIP.dataAlign();
125 if (DataAlignmentFactor == 0)
126 return createStringError(EC: errc::invalid_argument,
127 Fmt: "op[%" PRIu32 "] has type %s but data "
128 "alignment is zero",
129 Vals: OperandIdx, Vals: CFIProgram::operandTypeString(OT: Type));
130 return int64_t(Operand) * DataAlignmentFactor;
131 }
132
133 case OT_UnsignedFactDataOffset: {
134 const int64_t DataAlignmentFactor = CFIP.dataAlign();
135 if (DataAlignmentFactor == 0)
136 return createStringError(EC: errc::invalid_argument,
137 Fmt: "op[%" PRIu32
138 "] has type OT_UnsignedFactDataOffset but data "
139 "alignment is zero",
140 Vals: OperandIdx);
141 return Operand * DataAlignmentFactor;
142 }
143 }
144 llvm_unreachable("invalid operand type");
145}
146
147ArrayRef<CFIProgram::OperandType[CFIProgram::MaxOperands]>
148CFIProgram::getOperandTypes() {
149 static OperandType OpTypes[DW_CFA_restore + 1][MaxOperands];
150 static bool Initialized = false;
151 if (Initialized) {
152 return ArrayRef<OperandType[MaxOperands]>(&OpTypes[0], DW_CFA_restore + 1);
153 }
154 Initialized = true;
155
156#define DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OPTYPE2) \
157 do { \
158 OpTypes[OP][0] = OPTYPE0; \
159 OpTypes[OP][1] = OPTYPE1; \
160 OpTypes[OP][2] = OPTYPE2; \
161 } while (false)
162#define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \
163 DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OT_None)
164#define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None)
165#define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None)
166
167 DECLARE_OP1(DW_CFA_set_loc, OT_Address);
168 DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset);
169 DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset);
170 DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset);
171 DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset);
172 DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset);
173 DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset);
174 DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset);
175 DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register);
176 DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa, OT_Register, OT_Offset,
177 OT_AddressSpace);
178 DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa_sf, OT_Register,
179 OT_SignedFactDataOffset, OT_AddressSpace);
180 DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset);
181 DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset);
182 DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression);
183 DECLARE_OP1(DW_CFA_undefined, OT_Register);
184 DECLARE_OP1(DW_CFA_same_value, OT_Register);
185 DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset);
186 DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset);
187 DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset);
188 DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset);
189 DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset);
190 DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register);
191 DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression);
192 DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression);
193 DECLARE_OP1(DW_CFA_restore, OT_Register);
194 DECLARE_OP1(DW_CFA_restore_extended, OT_Register);
195 DECLARE_OP0(DW_CFA_remember_state);
196 DECLARE_OP0(DW_CFA_restore_state);
197 DECLARE_OP0(DW_CFA_GNU_window_save);
198 DECLARE_OP0(DW_CFA_AARCH64_negate_ra_state_with_pc);
199 DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset);
200 DECLARE_OP0(DW_CFA_nop);
201
202#undef DECLARE_OP0
203#undef DECLARE_OP1
204#undef DECLARE_OP2
205
206 return ArrayRef<OperandType[MaxOperands]>(&OpTypes[0], DW_CFA_restore + 1);
207}
208