Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnwindTablePrinter.cpp
213799 views
//===----------------------------------------------------------------------===//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/DWARFUnwindTablePrinter.h"9#include "llvm/DebugInfo/DIContext.h"10#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"11#include "llvm/Support/ErrorHandling.h"12#include "llvm/Support/Format.h"13#include "llvm/Support/raw_ostream.h"14#include <cassert>15#include <cinttypes>16#include <cstdint>17#include <optional>1819using namespace llvm;20using namespace dwarf;2122static void printRegister(raw_ostream &OS, DIDumpOptions DumpOpts,23unsigned RegNum) {24if (DumpOpts.GetNameForDWARFReg) {25auto RegName = DumpOpts.GetNameForDWARFReg(RegNum, DumpOpts.IsEH);26if (!RegName.empty()) {27OS << RegName;28return;29}30}31OS << "reg" << RegNum;32}3334/// Print an unwind location expression as text and use the register information35/// if some is provided.36///37/// \param R the unwind location to print.38///39/// \param OS the stream to use for output.40///41/// \param MRI register information that helps emit register names insteead42/// of raw register numbers.43///44/// \param IsEH true if the DWARF Call Frame Information is from .eh_frame45/// instead of from .debug_frame. This is needed for register number46/// conversion because some register numbers differ between the two sections47/// for certain architectures like x86.48static void printUnwindLocation(const UnwindLocation &UL, raw_ostream &OS,49DIDumpOptions DumpOpts) {50if (UL.getDereference())51OS << '[';52switch (UL.getLocation()) {53case UnwindLocation::Unspecified:54OS << "unspecified";55break;56case UnwindLocation::Undefined:57OS << "undefined";58break;59case UnwindLocation::Same:60OS << "same";61break;62case UnwindLocation::CFAPlusOffset:63OS << "CFA";64if (UL.getOffset() == 0)65break;66if (UL.getOffset() > 0)67OS << "+";68OS << UL.getOffset();69break;70case UnwindLocation::RegPlusOffset:71printRegister(OS, DumpOpts, UL.getRegister());72if (UL.getOffset() == 0 && !UL.hasAddressSpace())73break;74if (UL.getOffset() >= 0)75OS << "+";76OS << UL.getOffset();77if (UL.hasAddressSpace())78OS << " in addrspace" << UL.getAddressSpace();79break;80case UnwindLocation::DWARFExpr: {81if (UL.getDWARFExpressionBytes()) {82auto Expr = *UL.getDWARFExpressionBytes();83printDwarfExpression(&Expr, OS, DumpOpts, nullptr);84}85break;86}87case UnwindLocation::Constant:88OS << UL.getOffset();89break;90}91if (UL.getDereference())92OS << ']';93}9495raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS,96const UnwindLocation &UL) {97auto DumpOpts = DIDumpOptions();98printUnwindLocation(UL, OS, DumpOpts);99return OS;100}101102/// Print all registers + locations that are currently defined in a register103/// locations.104///105/// \param RL the register locations to print.106///107/// \param OS the stream to use for output.108///109/// \param MRI register information that helps emit register names insteead110/// of raw register numbers.111///112/// \param IsEH true if the DWARF Call Frame Information is from .eh_frame113/// instead of from .debug_frame. This is needed for register number114/// conversion because some register numbers differ between the two sections115/// for certain architectures like x86.116static void printRegisterLocations(const RegisterLocations &RL, raw_ostream &OS,117DIDumpOptions DumpOpts) {118bool First = true;119for (uint32_t Reg : RL.getRegisters()) {120auto Loc = *RL.getRegisterLocation(Reg);121if (First)122First = false;123else124OS << ", ";125printRegister(OS, DumpOpts, Reg);126OS << '=';127printUnwindLocation(Loc, OS, DumpOpts);128}129}130131raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS,132const RegisterLocations &RL) {133auto DumpOpts = DIDumpOptions();134printRegisterLocations(RL, OS, DumpOpts);135return OS;136}137138/// Print an UnwindRow to the stream.139///140/// \param Row the UnwindRow to print.141///142/// \param OS the stream to use for output.143///144/// \param MRI register information that helps emit register names insteead145/// of raw register numbers.146///147/// \param IsEH true if the DWARF Call Frame Information is from .eh_frame148/// instead of from .debug_frame. This is needed for register number149/// conversion because some register numbers differ between the two sections150/// for certain architectures like x86.151///152/// \param IndentLevel specify the indent level as an integer. The UnwindRow153/// will be output to the stream preceded by 2 * IndentLevel number of spaces.154static void printUnwindRow(const UnwindRow &Row, raw_ostream &OS,155DIDumpOptions DumpOpts, unsigned IndentLevel) {156OS.indent(2 * IndentLevel);157if (Row.hasAddress())158OS << format("0x%" PRIx64 ": ", Row.getAddress());159OS << "CFA=";160printUnwindLocation(Row.getCFAValue(), OS, DumpOpts);161if (Row.getRegisterLocations().hasLocations()) {162OS << ": ";163printRegisterLocations(Row.getRegisterLocations(), OS, DumpOpts);164}165OS << "\n";166}167168raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindRow &Row) {169auto DumpOpts = DIDumpOptions();170printUnwindRow(Row, OS, DumpOpts, 0);171return OS;172}173174void llvm::dwarf::printUnwindTable(const UnwindTable &Rows, raw_ostream &OS,175DIDumpOptions DumpOpts,176unsigned IndentLevel) {177for (const UnwindRow &Row : Rows)178printUnwindRow(Row, OS, DumpOpts, IndentLevel);179}180181raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindTable &Rows) {182auto DumpOpts = DIDumpOptions();183printUnwindTable(Rows, OS, DumpOpts, 0);184return OS;185}186187188