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