xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
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 
18 using namespace llvm;
19 using namespace dwarf;
20 
21 StringRef CFIProgram::callFrameString(unsigned Opcode) const {
22   return dwarf::CallFrameString(Opcode, Arch);
23 }
24 
25 const 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 
44 llvm::Expected<uint64_t>
45 CFIProgram::Instruction::getOperandAsUnsigned(const CFIProgram &CFIP,
46                                               uint32_t OperandIdx) const {
47   if (OperandIdx >= MaxOperands)
48     return createStringError(errc::invalid_argument,
49                              "operand index %" PRIu32 " is not valid",
50                              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(errc::invalid_argument,
58                              "op[%" PRIu32 "] has type %s which has no value",
59                              OperandIdx, CFIProgram::operandTypeString(Type));
60 
61   case OT_Offset:
62   case OT_SignedFactDataOffset:
63   case OT_UnsignedFactDataOffset:
64     return createStringError(
65         errc::invalid_argument,
66         "op[%" PRIu32 "] has OperandType OT_Offset which produces a signed "
67         "result, call getOperandAsSigned instead",
68         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           errc::invalid_argument,
80           "op[%" PRIu32 "] has type OT_FactoredCodeOffset but code alignment "
81           "is zero",
82           OperandIdx);
83     return Operand * CodeAlignmentFactor;
84   }
85   }
86   llvm_unreachable("invalid operand type");
87 }
88 
89 llvm::Expected<int64_t>
90 CFIProgram::Instruction::getOperandAsSigned(const CFIProgram &CFIP,
91                                             uint32_t OperandIdx) const {
92   if (OperandIdx >= MaxOperands)
93     return createStringError(errc::invalid_argument,
94                              "operand index %" PRIu32 " is not valid",
95                              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(errc::invalid_argument,
103                              "op[%" PRIu32 "] has type %s which has no value",
104                              OperandIdx, CFIProgram::operandTypeString(Type));
105 
106   case OT_Address:
107   case OT_Register:
108   case OT_AddressSpace:
109     return createStringError(
110         errc::invalid_argument,
111         "op[%" PRIu32 "] has OperandType %s which produces an unsigned result, "
112         "call getOperandAsUnsigned instead",
113         OperandIdx, CFIProgram::operandTypeString(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(errc::invalid_argument,
123                                "op[%" PRIu32 "] has type %s but data "
124                                "alignment is zero",
125                                OperandIdx, CFIProgram::operandTypeString(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(errc::invalid_argument,
133                                "op[%" PRIu32
134                                "] has type OT_UnsignedFactDataOffset but data "
135                                "alignment is zero",
136                                OperandIdx);
137     return Operand * DataAlignmentFactor;
138   }
139   }
140   llvm_unreachable("invalid operand type");
141 }
142 
143 ArrayRef<CFIProgram::OperandType[CFIProgram::MaxOperands]>
144 CFIProgram::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