Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp
213799 views
//===- DWARFCFIPrinter.cpp - Print the cfi-portions 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/DWARFCFIPrinter.h"9#include "llvm/DebugInfo/DIContext.h"10#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"11#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"12#include "llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h"13#include "llvm/Support/Compiler.h"14#include "llvm/Support/DataExtractor.h"15#include "llvm/Support/Errc.h"16#include "llvm/Support/ErrorHandling.h"17#include "llvm/Support/Format.h"18#include "llvm/Support/raw_ostream.h"19#include <cassert>20#include <cinttypes>21#include <cstdint>22#include <optional>2324using namespace llvm;25using namespace dwarf;2627static void printRegister(raw_ostream &OS, const DIDumpOptions &DumpOpts,28unsigned RegNum) {29if (DumpOpts.GetNameForDWARFReg) {30auto RegName = DumpOpts.GetNameForDWARFReg(RegNum, DumpOpts.IsEH);31if (!RegName.empty()) {32OS << RegName;33return;34}35}36OS << "reg" << RegNum;37}3839/// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.40static void printOperand(raw_ostream &OS, const DIDumpOptions &DumpOpts,41const CFIProgram &P,42const CFIProgram::Instruction &Instr,43unsigned OperandIdx, uint64_t Operand,44std::optional<uint64_t> &Address) {45assert(OperandIdx < CFIProgram::MaxOperands);46uint8_t Opcode = Instr.Opcode;47CFIProgram::OperandType Type = P.getOperandTypes()[Opcode][OperandIdx];4849switch (Type) {50case CFIProgram::OT_Unset: {51OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";52auto OpcodeName = P.callFrameString(Opcode);53if (!OpcodeName.empty())54OS << " " << OpcodeName;55else56OS << format(" Opcode %x", Opcode);57break;58}59case CFIProgram::OT_None:60break;61case CFIProgram::OT_Address:62OS << format(" %" PRIx64, Operand);63Address = Operand;64break;65case CFIProgram::OT_Offset:66// The offsets are all encoded in a unsigned form, but in practice67// consumers use them signed. It's most certainly legacy due to68// the lack of signed variants in the first Dwarf standards.69OS << format(" %+" PRId64, int64_t(Operand));70break;71case CFIProgram::OT_FactoredCodeOffset: // Always Unsigned72if (P.codeAlign())73OS << format(" %" PRId64, Operand * P.codeAlign());74else75OS << format(" %" PRId64 "*code_alignment_factor", Operand);76if (Address && P.codeAlign()) {77*Address += Operand * P.codeAlign();78OS << format(" to 0x%" PRIx64, *Address);79}80break;81case CFIProgram::OT_SignedFactDataOffset:82if (P.dataAlign())83OS << format(" %" PRId64, int64_t(Operand) * P.dataAlign());84else85OS << format(" %" PRId64 "*data_alignment_factor", int64_t(Operand));86break;87case CFIProgram::OT_UnsignedFactDataOffset:88if (P.dataAlign())89OS << format(" %" PRId64, Operand * P.dataAlign());90else91OS << format(" %" PRId64 "*data_alignment_factor", Operand);92break;93case CFIProgram::OT_Register:94OS << ' ';95printRegister(OS, DumpOpts, Operand);96break;97case CFIProgram::OT_AddressSpace:98OS << format(" in addrspace%" PRId64, Operand);99break;100case CFIProgram::OT_Expression:101assert(Instr.Expression && "missing DWARFExpression object");102OS << " ";103printDwarfExpression(&Instr.Expression.value(), OS, DumpOpts, nullptr);104break;105}106}107108void llvm::dwarf::printCFIProgram(const CFIProgram &P, raw_ostream &OS,109const DIDumpOptions &DumpOpts,110unsigned IndentLevel,111std::optional<uint64_t> Address) {112for (const auto &Instr : P) {113uint8_t Opcode = Instr.Opcode;114OS.indent(2 * IndentLevel);115OS << P.callFrameString(Opcode) << ":";116for (size_t i = 0; i < Instr.Ops.size(); ++i)117printOperand(OS, DumpOpts, P, Instr, i, Instr.Ops[i], Address);118OS << '\n';119}120}121122123