204 lines · cpp
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-exception6//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(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(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 89llvm::Expected<int64_t>90CFIProgram::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[%" PRIu32134 "] 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 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_OP0199#undef DECLARE_OP1200#undef DECLARE_OP2201 202 return ArrayRef<OperandType[MaxOperands]>(&OpTypes[0], DW_CFA_restore + 1);203}204