Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
35266 views
//===- DWARFDebugFrame.h - Parsing of .debug_frame ------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"9#include "llvm/ADT/DenseMap.h"10#include "llvm/ADT/StringExtras.h"11#include "llvm/ADT/StringRef.h"12#include "llvm/BinaryFormat/Dwarf.h"13#include "llvm/DebugInfo/DIContext.h"14#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"15#include "llvm/Support/Compiler.h"16#include "llvm/Support/DataExtractor.h"17#include "llvm/Support/Errc.h"18#include "llvm/Support/ErrorHandling.h"19#include "llvm/Support/Format.h"20#include "llvm/Support/raw_ostream.h"21#include <algorithm>22#include <cassert>23#include <cinttypes>24#include <cstdint>25#include <optional>2627using namespace llvm;28using namespace dwarf;2930static void printRegister(raw_ostream &OS, DIDumpOptions DumpOpts,31unsigned RegNum) {32if (DumpOpts.GetNameForDWARFReg) {33auto RegName = DumpOpts.GetNameForDWARFReg(RegNum, DumpOpts.IsEH);34if (!RegName.empty()) {35OS << RegName;36return;37}38}39OS << "reg" << RegNum;40}4142UnwindLocation UnwindLocation::createUnspecified() { return {Unspecified}; }4344UnwindLocation UnwindLocation::createUndefined() { return {Undefined}; }4546UnwindLocation UnwindLocation::createSame() { return {Same}; }4748UnwindLocation UnwindLocation::createIsConstant(int32_t Value) {49return {Constant, InvalidRegisterNumber, Value, std::nullopt, false};50}5152UnwindLocation UnwindLocation::createIsCFAPlusOffset(int32_t Offset) {53return {CFAPlusOffset, InvalidRegisterNumber, Offset, std::nullopt, false};54}5556UnwindLocation UnwindLocation::createAtCFAPlusOffset(int32_t Offset) {57return {CFAPlusOffset, InvalidRegisterNumber, Offset, std::nullopt, true};58}5960UnwindLocation61UnwindLocation::createIsRegisterPlusOffset(uint32_t RegNum, int32_t Offset,62std::optional<uint32_t> AddrSpace) {63return {RegPlusOffset, RegNum, Offset, AddrSpace, false};64}6566UnwindLocation67UnwindLocation::createAtRegisterPlusOffset(uint32_t RegNum, int32_t Offset,68std::optional<uint32_t> AddrSpace) {69return {RegPlusOffset, RegNum, Offset, AddrSpace, true};70}7172UnwindLocation UnwindLocation::createIsDWARFExpression(DWARFExpression Expr) {73return {Expr, false};74}7576UnwindLocation UnwindLocation::createAtDWARFExpression(DWARFExpression Expr) {77return {Expr, true};78}7980void UnwindLocation::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {81if (Dereference)82OS << '[';83switch (Kind) {84case Unspecified:85OS << "unspecified";86break;87case Undefined:88OS << "undefined";89break;90case Same:91OS << "same";92break;93case CFAPlusOffset:94OS << "CFA";95if (Offset == 0)96break;97if (Offset > 0)98OS << "+";99OS << Offset;100break;101case RegPlusOffset:102printRegister(OS, DumpOpts, RegNum);103if (Offset == 0 && !AddrSpace)104break;105if (Offset >= 0)106OS << "+";107OS << Offset;108if (AddrSpace)109OS << " in addrspace" << *AddrSpace;110break;111case DWARFExpr: {112Expr->print(OS, DumpOpts, nullptr);113break;114}115case Constant:116OS << Offset;117break;118}119if (Dereference)120OS << ']';121}122123raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS,124const UnwindLocation &UL) {125auto DumpOpts = DIDumpOptions();126UL.dump(OS, DumpOpts);127return OS;128}129130bool UnwindLocation::operator==(const UnwindLocation &RHS) const {131if (Kind != RHS.Kind)132return false;133switch (Kind) {134case Unspecified:135case Undefined:136case Same:137return true;138case CFAPlusOffset:139return Offset == RHS.Offset && Dereference == RHS.Dereference;140case RegPlusOffset:141return RegNum == RHS.RegNum && Offset == RHS.Offset &&142Dereference == RHS.Dereference;143case DWARFExpr:144return *Expr == *RHS.Expr && Dereference == RHS.Dereference;145case Constant:146return Offset == RHS.Offset;147}148return false;149}150151void RegisterLocations::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {152bool First = true;153for (const auto &RegLocPair : Locations) {154if (First)155First = false;156else157OS << ", ";158printRegister(OS, DumpOpts, RegLocPair.first);159OS << '=';160RegLocPair.second.dump(OS, DumpOpts);161}162}163164raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS,165const RegisterLocations &RL) {166auto DumpOpts = DIDumpOptions();167RL.dump(OS, DumpOpts);168return OS;169}170171void UnwindRow::dump(raw_ostream &OS, DIDumpOptions DumpOpts,172unsigned IndentLevel) const {173OS.indent(2 * IndentLevel);174if (hasAddress())175OS << format("0x%" PRIx64 ": ", *Address);176OS << "CFA=";177CFAValue.dump(OS, DumpOpts);178if (RegLocs.hasLocations()) {179OS << ": ";180RegLocs.dump(OS, DumpOpts);181}182OS << "\n";183}184185raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindRow &Row) {186auto DumpOpts = DIDumpOptions();187Row.dump(OS, DumpOpts, 0);188return OS;189}190191void UnwindTable::dump(raw_ostream &OS, DIDumpOptions DumpOpts,192unsigned IndentLevel) const {193for (const UnwindRow &Row : Rows)194Row.dump(OS, DumpOpts, IndentLevel);195}196197raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindTable &Rows) {198auto DumpOpts = DIDumpOptions();199Rows.dump(OS, DumpOpts, 0);200return OS;201}202203Expected<UnwindTable> UnwindTable::create(const FDE *Fde) {204const CIE *Cie = Fde->getLinkedCIE();205if (Cie == nullptr)206return createStringError(errc::invalid_argument,207"unable to get CIE for FDE at offset 0x%" PRIx64,208Fde->getOffset());209210// Rows will be empty if there are no CFI instructions.211if (Cie->cfis().empty() && Fde->cfis().empty())212return UnwindTable();213214UnwindTable UT;215UnwindRow Row;216Row.setAddress(Fde->getInitialLocation());217UT.EndAddress = Fde->getInitialLocation() + Fde->getAddressRange();218if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr))219return std::move(CieError);220// We need to save the initial locations of registers from the CIE parsing221// in case we run into DW_CFA_restore or DW_CFA_restore_extended opcodes.222const RegisterLocations InitialLocs = Row.getRegisterLocations();223if (Error FdeError = UT.parseRows(Fde->cfis(), Row, &InitialLocs))224return std::move(FdeError);225// May be all the CFI instructions were DW_CFA_nop amd Row becomes empty.226// Do not add that to the unwind table.227if (Row.getRegisterLocations().hasLocations() ||228Row.getCFAValue().getLocation() != UnwindLocation::Unspecified)229UT.Rows.push_back(Row);230return UT;231}232233Expected<UnwindTable> UnwindTable::create(const CIE *Cie) {234// Rows will be empty if there are no CFI instructions.235if (Cie->cfis().empty())236return UnwindTable();237238UnwindTable UT;239UnwindRow Row;240if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr))241return std::move(CieError);242// May be all the CFI instructions were DW_CFA_nop amd Row becomes empty.243// Do not add that to the unwind table.244if (Row.getRegisterLocations().hasLocations() ||245Row.getCFAValue().getLocation() != UnwindLocation::Unspecified)246UT.Rows.push_back(Row);247return UT;248}249250// See DWARF standard v3, section 7.23251const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;252const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;253254Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset,255uint64_t EndOffset) {256DataExtractor::Cursor C(*Offset);257while (C && C.tell() < EndOffset) {258uint8_t Opcode = Data.getRelocatedValue(C, 1);259if (!C)260break;261262// Some instructions have a primary opcode encoded in the top bits.263if (uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) {264// If it's a primary opcode, the first operand is encoded in the bottom265// bits of the opcode itself.266uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;267switch (Primary) {268case DW_CFA_advance_loc:269case DW_CFA_restore:270addInstruction(Primary, Op1);271break;272case DW_CFA_offset:273addInstruction(Primary, Op1, Data.getULEB128(C));274break;275default:276llvm_unreachable("invalid primary CFI opcode");277}278continue;279}280281// Extended opcode - its value is Opcode itself.282switch (Opcode) {283default:284return createStringError(errc::illegal_byte_sequence,285"invalid extended CFI opcode 0x%" PRIx8, Opcode);286case DW_CFA_nop:287case DW_CFA_remember_state:288case DW_CFA_restore_state:289case DW_CFA_GNU_window_save:290// No operands291addInstruction(Opcode);292break;293case DW_CFA_set_loc:294// Operands: Address295addInstruction(Opcode, Data.getRelocatedAddress(C));296break;297case DW_CFA_advance_loc1:298// Operands: 1-byte delta299addInstruction(Opcode, Data.getRelocatedValue(C, 1));300break;301case DW_CFA_advance_loc2:302// Operands: 2-byte delta303addInstruction(Opcode, Data.getRelocatedValue(C, 2));304break;305case DW_CFA_advance_loc4:306// Operands: 4-byte delta307addInstruction(Opcode, Data.getRelocatedValue(C, 4));308break;309case DW_CFA_restore_extended:310case DW_CFA_undefined:311case DW_CFA_same_value:312case DW_CFA_def_cfa_register:313case DW_CFA_def_cfa_offset:314case DW_CFA_GNU_args_size:315// Operands: ULEB128316addInstruction(Opcode, Data.getULEB128(C));317break;318case DW_CFA_def_cfa_offset_sf:319// Operands: SLEB128320addInstruction(Opcode, Data.getSLEB128(C));321break;322case DW_CFA_LLVM_def_aspace_cfa:323case DW_CFA_LLVM_def_aspace_cfa_sf: {324auto RegNum = Data.getULEB128(C);325auto CfaOffset = Opcode == DW_CFA_LLVM_def_aspace_cfa326? Data.getULEB128(C)327: Data.getSLEB128(C);328auto AddressSpace = Data.getULEB128(C);329addInstruction(Opcode, RegNum, CfaOffset, AddressSpace);330break;331}332case DW_CFA_offset_extended:333case DW_CFA_register:334case DW_CFA_def_cfa:335case DW_CFA_val_offset: {336// Operands: ULEB128, ULEB128337// Note: We can not embed getULEB128 directly into function338// argument list. getULEB128 changes Offset and order of evaluation339// for arguments is unspecified.340uint64_t op1 = Data.getULEB128(C);341uint64_t op2 = Data.getULEB128(C);342addInstruction(Opcode, op1, op2);343break;344}345case DW_CFA_offset_extended_sf:346case DW_CFA_def_cfa_sf:347case DW_CFA_val_offset_sf: {348// Operands: ULEB128, SLEB128349// Note: see comment for the previous case350uint64_t op1 = Data.getULEB128(C);351uint64_t op2 = (uint64_t)Data.getSLEB128(C);352addInstruction(Opcode, op1, op2);353break;354}355case DW_CFA_def_cfa_expression: {356uint64_t ExprLength = Data.getULEB128(C);357addInstruction(Opcode, 0);358StringRef Expression = Data.getBytes(C, ExprLength);359360DataExtractor Extractor(Expression, Data.isLittleEndian(),361Data.getAddressSize());362// Note. We do not pass the DWARF format to DWARFExpression, because363// DW_OP_call_ref, the only operation which depends on the format, is364// prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.365Instructions.back().Expression =366DWARFExpression(Extractor, Data.getAddressSize());367break;368}369case DW_CFA_expression:370case DW_CFA_val_expression: {371uint64_t RegNum = Data.getULEB128(C);372addInstruction(Opcode, RegNum, 0);373374uint64_t BlockLength = Data.getULEB128(C);375StringRef Expression = Data.getBytes(C, BlockLength);376DataExtractor Extractor(Expression, Data.isLittleEndian(),377Data.getAddressSize());378// Note. We do not pass the DWARF format to DWARFExpression, because379// DW_OP_call_ref, the only operation which depends on the format, is380// prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.381Instructions.back().Expression =382DWARFExpression(Extractor, Data.getAddressSize());383break;384}385}386}387388*Offset = C.tell();389return C.takeError();390}391392StringRef CFIProgram::callFrameString(unsigned Opcode) const {393return dwarf::CallFrameString(Opcode, Arch);394}395396const char *CFIProgram::operandTypeString(CFIProgram::OperandType OT) {397#define ENUM_TO_CSTR(e) \398case e: \399return #e;400switch (OT) {401ENUM_TO_CSTR(OT_Unset);402ENUM_TO_CSTR(OT_None);403ENUM_TO_CSTR(OT_Address);404ENUM_TO_CSTR(OT_Offset);405ENUM_TO_CSTR(OT_FactoredCodeOffset);406ENUM_TO_CSTR(OT_SignedFactDataOffset);407ENUM_TO_CSTR(OT_UnsignedFactDataOffset);408ENUM_TO_CSTR(OT_Register);409ENUM_TO_CSTR(OT_AddressSpace);410ENUM_TO_CSTR(OT_Expression);411}412return "<unknown CFIProgram::OperandType>";413}414415llvm::Expected<uint64_t>416CFIProgram::Instruction::getOperandAsUnsigned(const CFIProgram &CFIP,417uint32_t OperandIdx) const {418if (OperandIdx >= MaxOperands)419return createStringError(errc::invalid_argument,420"operand index %" PRIu32 " is not valid",421OperandIdx);422OperandType Type = CFIP.getOperandTypes()[Opcode][OperandIdx];423uint64_t Operand = Ops[OperandIdx];424switch (Type) {425case OT_Unset:426case OT_None:427case OT_Expression:428return createStringError(errc::invalid_argument,429"op[%" PRIu32 "] has type %s which has no value",430OperandIdx, CFIProgram::operandTypeString(Type));431432case OT_Offset:433case OT_SignedFactDataOffset:434case OT_UnsignedFactDataOffset:435return createStringError(436errc::invalid_argument,437"op[%" PRIu32 "] has OperandType OT_Offset which produces a signed "438"result, call getOperandAsSigned instead",439OperandIdx);440441case OT_Address:442case OT_Register:443case OT_AddressSpace:444return Operand;445446case OT_FactoredCodeOffset: {447const uint64_t CodeAlignmentFactor = CFIP.codeAlign();448if (CodeAlignmentFactor == 0)449return createStringError(450errc::invalid_argument,451"op[%" PRIu32 "] has type OT_FactoredCodeOffset but code alignment "452"is zero",453OperandIdx);454return Operand * CodeAlignmentFactor;455}456}457llvm_unreachable("invalid operand type");458}459460llvm::Expected<int64_t>461CFIProgram::Instruction::getOperandAsSigned(const CFIProgram &CFIP,462uint32_t OperandIdx) const {463if (OperandIdx >= MaxOperands)464return createStringError(errc::invalid_argument,465"operand index %" PRIu32 " is not valid",466OperandIdx);467OperandType Type = CFIP.getOperandTypes()[Opcode][OperandIdx];468uint64_t Operand = Ops[OperandIdx];469switch (Type) {470case OT_Unset:471case OT_None:472case OT_Expression:473return createStringError(errc::invalid_argument,474"op[%" PRIu32 "] has type %s which has no value",475OperandIdx, CFIProgram::operandTypeString(Type));476477case OT_Address:478case OT_Register:479case OT_AddressSpace:480return createStringError(481errc::invalid_argument,482"op[%" PRIu32 "] has OperandType %s which produces an unsigned result, "483"call getOperandAsUnsigned instead",484OperandIdx, CFIProgram::operandTypeString(Type));485486case OT_Offset:487return (int64_t)Operand;488489case OT_FactoredCodeOffset:490case OT_SignedFactDataOffset: {491const int64_t DataAlignmentFactor = CFIP.dataAlign();492if (DataAlignmentFactor == 0)493return createStringError(errc::invalid_argument,494"op[%" PRIu32 "] has type %s but data "495"alignment is zero",496OperandIdx, CFIProgram::operandTypeString(Type));497return int64_t(Operand) * DataAlignmentFactor;498}499500case OT_UnsignedFactDataOffset: {501const int64_t DataAlignmentFactor = CFIP.dataAlign();502if (DataAlignmentFactor == 0)503return createStringError(errc::invalid_argument,504"op[%" PRIu32505"] has type OT_UnsignedFactDataOffset but data "506"alignment is zero",507OperandIdx);508return Operand * DataAlignmentFactor;509}510}511llvm_unreachable("invalid operand type");512}513514Error UnwindTable::parseRows(const CFIProgram &CFIP, UnwindRow &Row,515const RegisterLocations *InitialLocs) {516// State consists of CFA value and register locations.517std::vector<std::pair<UnwindLocation, RegisterLocations>> States;518for (const CFIProgram::Instruction &Inst : CFIP) {519switch (Inst.Opcode) {520case dwarf::DW_CFA_set_loc: {521// The DW_CFA_set_loc instruction takes a single operand that522// represents a target address. The required action is to create a new523// table row using the specified address as the location. All other524// values in the new row are initially identical to the current row.525// The new location value is always greater than the current one. If526// the segment_size field of this FDE's CIE is non- zero, the initial527// location is preceded by a segment selector of the given length528llvm::Expected<uint64_t> NewAddress = Inst.getOperandAsUnsigned(CFIP, 0);529if (!NewAddress)530return NewAddress.takeError();531if (*NewAddress <= Row.getAddress())532return createStringError(533errc::invalid_argument,534"%s with adrress 0x%" PRIx64 " which must be greater than the "535"current row address 0x%" PRIx64,536CFIP.callFrameString(Inst.Opcode).str().c_str(), *NewAddress,537Row.getAddress());538Rows.push_back(Row);539Row.setAddress(*NewAddress);540break;541}542543case dwarf::DW_CFA_advance_loc:544case dwarf::DW_CFA_advance_loc1:545case dwarf::DW_CFA_advance_loc2:546case dwarf::DW_CFA_advance_loc4: {547// The DW_CFA_advance instruction takes a single operand that548// represents a constant delta. The required action is to create a new549// table row with a location value that is computed by taking the550// current entry’s location value and adding the value of delta *551// code_alignment_factor. All other values in the new row are initially552// identical to the current row.553Rows.push_back(Row);554llvm::Expected<uint64_t> Offset = Inst.getOperandAsUnsigned(CFIP, 0);555if (!Offset)556return Offset.takeError();557Row.slideAddress(*Offset);558break;559}560561case dwarf::DW_CFA_restore:562case dwarf::DW_CFA_restore_extended: {563// The DW_CFA_restore instruction takes a single operand (encoded with564// the opcode) that represents a register number. The required action565// is to change the rule for the indicated register to the rule566// assigned it by the initial_instructions in the CIE.567if (InitialLocs == nullptr)568return createStringError(569errc::invalid_argument, "%s encountered while parsing a CIE",570CFIP.callFrameString(Inst.Opcode).str().c_str());571llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);572if (!RegNum)573return RegNum.takeError();574if (std::optional<UnwindLocation> O =575InitialLocs->getRegisterLocation(*RegNum))576Row.getRegisterLocations().setRegisterLocation(*RegNum, *O);577else578Row.getRegisterLocations().removeRegisterLocation(*RegNum);579break;580}581582case dwarf::DW_CFA_offset:583case dwarf::DW_CFA_offset_extended:584case dwarf::DW_CFA_offset_extended_sf: {585llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);586if (!RegNum)587return RegNum.takeError();588llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1);589if (!Offset)590return Offset.takeError();591Row.getRegisterLocations().setRegisterLocation(592*RegNum, UnwindLocation::createAtCFAPlusOffset(*Offset));593break;594}595596case dwarf::DW_CFA_nop:597break;598599case dwarf::DW_CFA_remember_state:600States.push_back(601std::make_pair(Row.getCFAValue(), Row.getRegisterLocations()));602break;603604case dwarf::DW_CFA_restore_state:605if (States.empty())606return createStringError(errc::invalid_argument,607"DW_CFA_restore_state without a matching "608"previous DW_CFA_remember_state");609Row.getCFAValue() = States.back().first;610Row.getRegisterLocations() = States.back().second;611States.pop_back();612break;613614case dwarf::DW_CFA_GNU_window_save:615switch (CFIP.triple()) {616case Triple::aarch64:617case Triple::aarch64_be:618case Triple::aarch64_32: {619// DW_CFA_GNU_window_save is used for different things on different620// architectures. For aarch64 it is known as621// DW_CFA_AARCH64_negate_ra_state. The action is to toggle the622// value of the return address state between 1 and 0. If there is623// no rule for the AARCH64_DWARF_PAUTH_RA_STATE register, then it624// should be initially set to 1.625constexpr uint32_t AArch64DWARFPAuthRaState = 34;626auto LRLoc = Row.getRegisterLocations().getRegisterLocation(627AArch64DWARFPAuthRaState);628if (LRLoc) {629if (LRLoc->getLocation() == UnwindLocation::Constant) {630// Toggle the constant value from 0 to 1 or 1 to 0.631LRLoc->setConstant(LRLoc->getConstant() ^ 1);632Row.getRegisterLocations().setRegisterLocation(633AArch64DWARFPAuthRaState, *LRLoc);634} else {635return createStringError(636errc::invalid_argument,637"%s encountered when existing rule for this register is not "638"a constant",639CFIP.callFrameString(Inst.Opcode).str().c_str());640}641} else {642Row.getRegisterLocations().setRegisterLocation(643AArch64DWARFPAuthRaState, UnwindLocation::createIsConstant(1));644}645break;646}647648case Triple::sparc:649case Triple::sparcv9:650case Triple::sparcel:651for (uint32_t RegNum = 16; RegNum < 32; ++RegNum) {652Row.getRegisterLocations().setRegisterLocation(653RegNum, UnwindLocation::createAtCFAPlusOffset((RegNum - 16) * 8));654}655break;656657default: {658return createStringError(659errc::not_supported,660"DW_CFA opcode %#x is not supported for architecture %s",661Inst.Opcode, Triple::getArchTypeName(CFIP.triple()).str().c_str());662663break;664}665}666break;667668case dwarf::DW_CFA_undefined: {669llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);670if (!RegNum)671return RegNum.takeError();672Row.getRegisterLocations().setRegisterLocation(673*RegNum, UnwindLocation::createUndefined());674break;675}676677case dwarf::DW_CFA_same_value: {678llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);679if (!RegNum)680return RegNum.takeError();681Row.getRegisterLocations().setRegisterLocation(682*RegNum, UnwindLocation::createSame());683break;684}685686case dwarf::DW_CFA_GNU_args_size:687break;688689case dwarf::DW_CFA_register: {690llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);691if (!RegNum)692return RegNum.takeError();693llvm::Expected<uint64_t> NewRegNum = Inst.getOperandAsUnsigned(CFIP, 1);694if (!NewRegNum)695return NewRegNum.takeError();696Row.getRegisterLocations().setRegisterLocation(697*RegNum, UnwindLocation::createIsRegisterPlusOffset(*NewRegNum, 0));698break;699}700701case dwarf::DW_CFA_val_offset:702case dwarf::DW_CFA_val_offset_sf: {703llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);704if (!RegNum)705return RegNum.takeError();706llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1);707if (!Offset)708return Offset.takeError();709Row.getRegisterLocations().setRegisterLocation(710*RegNum, UnwindLocation::createIsCFAPlusOffset(*Offset));711break;712}713714case dwarf::DW_CFA_expression: {715llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);716if (!RegNum)717return RegNum.takeError();718Row.getRegisterLocations().setRegisterLocation(719*RegNum, UnwindLocation::createAtDWARFExpression(*Inst.Expression));720break;721}722723case dwarf::DW_CFA_val_expression: {724llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);725if (!RegNum)726return RegNum.takeError();727Row.getRegisterLocations().setRegisterLocation(728*RegNum, UnwindLocation::createIsDWARFExpression(*Inst.Expression));729break;730}731732case dwarf::DW_CFA_def_cfa_register: {733llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);734if (!RegNum)735return RegNum.takeError();736if (Row.getCFAValue().getLocation() != UnwindLocation::RegPlusOffset)737Row.getCFAValue() =738UnwindLocation::createIsRegisterPlusOffset(*RegNum, 0);739else740Row.getCFAValue().setRegister(*RegNum);741break;742}743744case dwarf::DW_CFA_def_cfa_offset:745case dwarf::DW_CFA_def_cfa_offset_sf: {746llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 0);747if (!Offset)748return Offset.takeError();749if (Row.getCFAValue().getLocation() != UnwindLocation::RegPlusOffset) {750return createStringError(751errc::invalid_argument,752"%s found when CFA rule was not RegPlusOffset",753CFIP.callFrameString(Inst.Opcode).str().c_str());754}755Row.getCFAValue().setOffset(*Offset);756break;757}758759case dwarf::DW_CFA_def_cfa:760case dwarf::DW_CFA_def_cfa_sf: {761llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);762if (!RegNum)763return RegNum.takeError();764llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1);765if (!Offset)766return Offset.takeError();767Row.getCFAValue() =768UnwindLocation::createIsRegisterPlusOffset(*RegNum, *Offset);769break;770}771772case dwarf::DW_CFA_LLVM_def_aspace_cfa:773case dwarf::DW_CFA_LLVM_def_aspace_cfa_sf: {774llvm::Expected<uint64_t> RegNum = Inst.getOperandAsUnsigned(CFIP, 0);775if (!RegNum)776return RegNum.takeError();777llvm::Expected<int64_t> Offset = Inst.getOperandAsSigned(CFIP, 1);778if (!Offset)779return Offset.takeError();780llvm::Expected<uint32_t> CFAAddrSpace =781Inst.getOperandAsUnsigned(CFIP, 2);782if (!CFAAddrSpace)783return CFAAddrSpace.takeError();784Row.getCFAValue() = UnwindLocation::createIsRegisterPlusOffset(785*RegNum, *Offset, *CFAAddrSpace);786break;787}788789case dwarf::DW_CFA_def_cfa_expression:790Row.getCFAValue() =791UnwindLocation::createIsDWARFExpression(*Inst.Expression);792break;793}794}795return Error::success();796}797798ArrayRef<CFIProgram::OperandType[CFIProgram::MaxOperands]>799CFIProgram::getOperandTypes() {800static OperandType OpTypes[DW_CFA_restore + 1][MaxOperands];801static bool Initialized = false;802if (Initialized) {803return ArrayRef<OperandType[MaxOperands]>(&OpTypes[0], DW_CFA_restore + 1);804}805Initialized = true;806807#define DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OPTYPE2) \808do { \809OpTypes[OP][0] = OPTYPE0; \810OpTypes[OP][1] = OPTYPE1; \811OpTypes[OP][2] = OPTYPE2; \812} while (false)813#define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \814DECLARE_OP3(OP, OPTYPE0, OPTYPE1, OT_None)815#define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None)816#define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None)817818DECLARE_OP1(DW_CFA_set_loc, OT_Address);819DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset);820DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset);821DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset);822DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset);823DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset);824DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset);825DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset);826DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register);827DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa, OT_Register, OT_Offset,828OT_AddressSpace);829DECLARE_OP3(DW_CFA_LLVM_def_aspace_cfa_sf, OT_Register,830OT_SignedFactDataOffset, OT_AddressSpace);831DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset);832DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset);833DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression);834DECLARE_OP1(DW_CFA_undefined, OT_Register);835DECLARE_OP1(DW_CFA_same_value, OT_Register);836DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset);837DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset);838DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset);839DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset);840DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset);841DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register);842DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression);843DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression);844DECLARE_OP1(DW_CFA_restore, OT_Register);845DECLARE_OP1(DW_CFA_restore_extended, OT_Register);846DECLARE_OP0(DW_CFA_remember_state);847DECLARE_OP0(DW_CFA_restore_state);848DECLARE_OP0(DW_CFA_GNU_window_save);849DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset);850DECLARE_OP0(DW_CFA_nop);851852#undef DECLARE_OP0853#undef DECLARE_OP1854#undef DECLARE_OP2855856return ArrayRef<OperandType[MaxOperands]>(&OpTypes[0], DW_CFA_restore + 1);857}858859/// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.860void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,861const Instruction &Instr, unsigned OperandIdx,862uint64_t Operand,863std::optional<uint64_t> &Address) const {864assert(OperandIdx < MaxOperands);865uint8_t Opcode = Instr.Opcode;866OperandType Type = getOperandTypes()[Opcode][OperandIdx];867868switch (Type) {869case OT_Unset: {870OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";871auto OpcodeName = callFrameString(Opcode);872if (!OpcodeName.empty())873OS << " " << OpcodeName;874else875OS << format(" Opcode %x", Opcode);876break;877}878case OT_None:879break;880case OT_Address:881OS << format(" %" PRIx64, Operand);882Address = Operand;883break;884case OT_Offset:885// The offsets are all encoded in a unsigned form, but in practice886// consumers use them signed. It's most certainly legacy due to887// the lack of signed variants in the first Dwarf standards.888OS << format(" %+" PRId64, int64_t(Operand));889break;890case OT_FactoredCodeOffset: // Always Unsigned891if (CodeAlignmentFactor)892OS << format(" %" PRId64, Operand * CodeAlignmentFactor);893else894OS << format(" %" PRId64 "*code_alignment_factor", Operand);895if (Address && CodeAlignmentFactor) {896*Address += Operand * CodeAlignmentFactor;897OS << format(" to 0x%" PRIx64, *Address);898}899break;900case OT_SignedFactDataOffset:901if (DataAlignmentFactor)902OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor);903else904OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand));905break;906case OT_UnsignedFactDataOffset:907if (DataAlignmentFactor)908OS << format(" %" PRId64, Operand * DataAlignmentFactor);909else910OS << format(" %" PRId64 "*data_alignment_factor" , Operand);911break;912case OT_Register:913OS << ' ';914printRegister(OS, DumpOpts, Operand);915break;916case OT_AddressSpace:917OS << format(" in addrspace%" PRId64, Operand);918break;919case OT_Expression:920assert(Instr.Expression && "missing DWARFExpression object");921OS << " ";922Instr.Expression->print(OS, DumpOpts, nullptr);923break;924}925}926927void CFIProgram::dump(raw_ostream &OS, DIDumpOptions DumpOpts,928unsigned IndentLevel,929std::optional<uint64_t> Address) const {930for (const auto &Instr : Instructions) {931uint8_t Opcode = Instr.Opcode;932OS.indent(2 * IndentLevel);933OS << callFrameString(Opcode) << ":";934for (unsigned i = 0; i < Instr.Ops.size(); ++i)935printOperand(OS, DumpOpts, Instr, i, Instr.Ops[i], Address);936OS << '\n';937}938}939940// Returns the CIE identifier to be used by the requested format.941// CIE ids for .debug_frame sections are defined in Section 7.24 of DWARFv5.942// For CIE ID in .eh_frame sections see943// https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html944constexpr uint64_t getCIEId(bool IsDWARF64, bool IsEH) {945if (IsEH)946return 0;947if (IsDWARF64)948return DW64_CIE_ID;949return DW_CIE_ID;950}951952void CIE::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {953// A CIE with a zero length is a terminator entry in the .eh_frame section.954if (DumpOpts.IsEH && Length == 0) {955OS << format("%08" PRIx64, Offset) << " ZERO terminator\n";956return;957}958959OS << format("%08" PRIx64, Offset)960<< format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length)961<< format(" %0*" PRIx64, IsDWARF64 && !DumpOpts.IsEH ? 16 : 8,962getCIEId(IsDWARF64, DumpOpts.IsEH))963<< " CIE\n"964<< " Format: " << FormatString(IsDWARF64) << "\n";965if (DumpOpts.IsEH && Version != 1)966OS << "WARNING: unsupported CIE version\n";967OS << format(" Version: %d\n", Version)968<< " Augmentation: \"" << Augmentation << "\"\n";969if (Version >= 4) {970OS << format(" Address size: %u\n", (uint32_t)AddressSize);971OS << format(" Segment desc size: %u\n",972(uint32_t)SegmentDescriptorSize);973}974OS << format(" Code alignment factor: %u\n", (uint32_t)CodeAlignmentFactor);975OS << format(" Data alignment factor: %d\n", (int32_t)DataAlignmentFactor);976OS << format(" Return address column: %d\n", (int32_t)ReturnAddressRegister);977if (Personality)978OS << format(" Personality Address: %016" PRIx64 "\n", *Personality);979if (!AugmentationData.empty()) {980OS << " Augmentation data: ";981for (uint8_t Byte : AugmentationData)982OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf);983OS << "\n";984}985OS << "\n";986CFIs.dump(OS, DumpOpts, /*IndentLevel=*/1, /*InitialLocation=*/{});987OS << "\n";988989if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))990RowsOrErr->dump(OS, DumpOpts, 1);991else {992DumpOpts.RecoverableErrorHandler(joinErrors(993createStringError(errc::invalid_argument,994"decoding the CIE opcodes into rows failed"),995RowsOrErr.takeError()));996}997OS << "\n";998}9991000void FDE::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {1001OS << format("%08" PRIx64, Offset)1002<< format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length)1003<< format(" %0*" PRIx64, IsDWARF64 && !DumpOpts.IsEH ? 16 : 8, CIEPointer)1004<< " FDE cie=";1005if (LinkedCIE)1006OS << format("%08" PRIx64, LinkedCIE->getOffset());1007else1008OS << "<invalid offset>";1009OS << format(" pc=%08" PRIx64 "...%08" PRIx64 "\n", InitialLocation,1010InitialLocation + AddressRange);1011OS << " Format: " << FormatString(IsDWARF64) << "\n";1012if (LSDAAddress)1013OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress);1014CFIs.dump(OS, DumpOpts, /*IndentLevel=*/1, InitialLocation);1015OS << "\n";10161017if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))1018RowsOrErr->dump(OS, DumpOpts, 1);1019else {1020DumpOpts.RecoverableErrorHandler(joinErrors(1021createStringError(errc::invalid_argument,1022"decoding the FDE opcodes into rows failed"),1023RowsOrErr.takeError()));1024}1025OS << "\n";1026}10271028DWARFDebugFrame::DWARFDebugFrame(Triple::ArchType Arch,1029bool IsEH, uint64_t EHFrameAddress)1030: Arch(Arch), IsEH(IsEH), EHFrameAddress(EHFrameAddress) {}10311032DWARFDebugFrame::~DWARFDebugFrame() = default;10331034static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,1035uint64_t Offset, int Length) {1036errs() << "DUMP: ";1037for (int i = 0; i < Length; ++i) {1038uint8_t c = Data.getU8(&Offset);1039errs().write_hex(c); errs() << " ";1040}1041errs() << "\n";1042}10431044Error DWARFDebugFrame::parse(DWARFDataExtractor Data) {1045uint64_t Offset = 0;1046DenseMap<uint64_t, CIE *> CIEs;10471048while (Data.isValidOffset(Offset)) {1049uint64_t StartOffset = Offset;10501051uint64_t Length;1052DwarfFormat Format;1053std::tie(Length, Format) = Data.getInitialLength(&Offset);1054bool IsDWARF64 = Format == DWARF64;10551056// If the Length is 0, then this CIE is a terminator. We add it because some1057// dumper tools might need it to print something special for such entries1058// (e.g. llvm-objdump --dwarf=frames prints "ZERO terminator").1059if (Length == 0) {1060auto Cie = std::make_unique<CIE>(1061IsDWARF64, StartOffset, 0, 0, SmallString<8>(), 0, 0, 0, 0, 0,1062SmallString<8>(), 0, 0, std::nullopt, std::nullopt, Arch);1063CIEs[StartOffset] = Cie.get();1064Entries.push_back(std::move(Cie));1065break;1066}10671068// At this point, Offset points to the next field after Length.1069// Length is the structure size excluding itself. Compute an offset one1070// past the end of the structure (needed to know how many instructions to1071// read).1072uint64_t StartStructureOffset = Offset;1073uint64_t EndStructureOffset = Offset + Length;10741075// The Id field's size depends on the DWARF format1076Error Err = Error::success();1077uint64_t Id = Data.getRelocatedValue((IsDWARF64 && !IsEH) ? 8 : 4, &Offset,1078/*SectionIndex=*/nullptr, &Err);1079if (Err)1080return Err;10811082if (Id == getCIEId(IsDWARF64, IsEH)) {1083uint8_t Version = Data.getU8(&Offset);1084const char *Augmentation = Data.getCStr(&Offset);1085StringRef AugmentationString(Augmentation ? Augmentation : "");1086uint8_t AddressSize = Version < 4 ? Data.getAddressSize() :1087Data.getU8(&Offset);1088Data.setAddressSize(AddressSize);1089uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset);1090uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);1091int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);1092uint64_t ReturnAddressRegister =1093Version == 1 ? Data.getU8(&Offset) : Data.getULEB128(&Offset);10941095// Parse the augmentation data for EH CIEs1096StringRef AugmentationData("");1097uint32_t FDEPointerEncoding = DW_EH_PE_absptr;1098uint32_t LSDAPointerEncoding = DW_EH_PE_omit;1099std::optional<uint64_t> Personality;1100std::optional<uint32_t> PersonalityEncoding;1101if (IsEH) {1102std::optional<uint64_t> AugmentationLength;1103uint64_t StartAugmentationOffset;1104uint64_t EndAugmentationOffset;11051106// Walk the augmentation string to get all the augmentation data.1107for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) {1108switch (AugmentationString[i]) {1109default:1110return createStringError(1111errc::invalid_argument,1112"unknown augmentation character %c in entry at 0x%" PRIx64,1113AugmentationString[i], StartOffset);1114case 'L':1115LSDAPointerEncoding = Data.getU8(&Offset);1116break;1117case 'P': {1118if (Personality)1119return createStringError(1120errc::invalid_argument,1121"duplicate personality in entry at 0x%" PRIx64, StartOffset);1122PersonalityEncoding = Data.getU8(&Offset);1123Personality = Data.getEncodedPointer(1124&Offset, *PersonalityEncoding,1125EHFrameAddress ? EHFrameAddress + Offset : 0);1126break;1127}1128case 'R':1129FDEPointerEncoding = Data.getU8(&Offset);1130break;1131case 'S':1132// Current frame is a signal trampoline.1133break;1134case 'z':1135if (i)1136return createStringError(1137errc::invalid_argument,1138"'z' must be the first character at 0x%" PRIx64, StartOffset);1139// Parse the augmentation length first. We only parse it if1140// the string contains a 'z'.1141AugmentationLength = Data.getULEB128(&Offset);1142StartAugmentationOffset = Offset;1143EndAugmentationOffset = Offset + *AugmentationLength;1144break;1145case 'B':1146// B-Key is used for signing functions associated with this1147// augmentation string1148break;1149// This stack frame contains MTE tagged data, so needs to be1150// untagged on unwind.1151case 'G':1152break;1153}1154}11551156if (AugmentationLength) {1157if (Offset != EndAugmentationOffset)1158return createStringError(errc::invalid_argument,1159"parsing augmentation data at 0x%" PRIx641160" failed",1161StartOffset);1162AugmentationData = Data.getData().slice(StartAugmentationOffset,1163EndAugmentationOffset);1164}1165}11661167auto Cie = std::make_unique<CIE>(1168IsDWARF64, StartOffset, Length, Version, AugmentationString,1169AddressSize, SegmentDescriptorSize, CodeAlignmentFactor,1170DataAlignmentFactor, ReturnAddressRegister, AugmentationData,1171FDEPointerEncoding, LSDAPointerEncoding, Personality,1172PersonalityEncoding, Arch);1173CIEs[StartOffset] = Cie.get();1174Entries.emplace_back(std::move(Cie));1175} else {1176// FDE1177uint64_t CIEPointer = Id;1178uint64_t InitialLocation = 0;1179uint64_t AddressRange = 0;1180std::optional<uint64_t> LSDAAddress;1181CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer];11821183if (IsEH) {1184// The address size is encoded in the CIE we reference.1185if (!Cie)1186return createStringError(errc::invalid_argument,1187"parsing FDE data at 0x%" PRIx641188" failed due to missing CIE",1189StartOffset);1190if (auto Val =1191Data.getEncodedPointer(&Offset, Cie->getFDEPointerEncoding(),1192EHFrameAddress + Offset)) {1193InitialLocation = *Val;1194}1195if (auto Val = Data.getEncodedPointer(1196&Offset, Cie->getFDEPointerEncoding(), 0)) {1197AddressRange = *Val;1198}11991200StringRef AugmentationString = Cie->getAugmentationString();1201if (!AugmentationString.empty()) {1202// Parse the augmentation length and data for this FDE.1203uint64_t AugmentationLength = Data.getULEB128(&Offset);12041205uint64_t EndAugmentationOffset = Offset + AugmentationLength;12061207// Decode the LSDA if the CIE augmentation string said we should.1208if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) {1209LSDAAddress = Data.getEncodedPointer(1210&Offset, Cie->getLSDAPointerEncoding(),1211EHFrameAddress ? Offset + EHFrameAddress : 0);1212}12131214if (Offset != EndAugmentationOffset)1215return createStringError(errc::invalid_argument,1216"parsing augmentation data at 0x%" PRIx641217" failed",1218StartOffset);1219}1220} else {1221InitialLocation = Data.getRelocatedAddress(&Offset);1222AddressRange = Data.getRelocatedAddress(&Offset);1223}12241225Entries.emplace_back(new FDE(IsDWARF64, StartOffset, Length, CIEPointer,1226InitialLocation, AddressRange, Cie,1227LSDAAddress, Arch));1228}12291230if (Error E =1231Entries.back()->cfis().parse(Data, &Offset, EndStructureOffset))1232return E;12331234if (Offset != EndStructureOffset)1235return createStringError(1236errc::invalid_argument,1237"parsing entry instructions at 0x%" PRIx64 " failed", StartOffset);1238}12391240return Error::success();1241}12421243FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const {1244auto It = partition_point(Entries, [=](const std::unique_ptr<FrameEntry> &E) {1245return E->getOffset() < Offset;1246});1247if (It != Entries.end() && (*It)->getOffset() == Offset)1248return It->get();1249return nullptr;1250}12511252void DWARFDebugFrame::dump(raw_ostream &OS, DIDumpOptions DumpOpts,1253std::optional<uint64_t> Offset) const {1254DumpOpts.IsEH = IsEH;1255if (Offset) {1256if (auto *Entry = getEntryAtOffset(*Offset))1257Entry->dump(OS, DumpOpts);1258return;1259}12601261OS << "\n";1262for (const auto &Entry : Entries)1263Entry->dump(OS, DumpOpts);1264}126512661267