119 lines · cpp
1//===- DWARFCFIPrinter.cpp - Print 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/DWARFCFIPrinter.h"10#include "llvm/DebugInfo/DIContext.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/ErrorHandling.h"15#include "llvm/Support/Format.h"16#include "llvm/Support/raw_ostream.h"17#include <cassert>18#include <cinttypes>19#include <cstdint>20#include <optional>21 22using namespace llvm;23using namespace dwarf;24 25static void printRegister(raw_ostream &OS, const DIDumpOptions &DumpOpts,26 unsigned RegNum) {27 if (DumpOpts.GetNameForDWARFReg) {28 auto RegName = DumpOpts.GetNameForDWARFReg(RegNum, DumpOpts.IsEH);29 if (!RegName.empty()) {30 OS << RegName;31 return;32 }33 }34 OS << "reg" << RegNum;35}36 37/// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.38static void printOperand(raw_ostream &OS, const DIDumpOptions &DumpOpts,39 const CFIProgram &P,40 const CFIProgram::Instruction &Instr,41 unsigned OperandIdx, uint64_t Operand,42 std::optional<uint64_t> &Address) {43 assert(OperandIdx < CFIProgram::MaxOperands);44 uint8_t Opcode = Instr.Opcode;45 CFIProgram::OperandType Type = P.getOperandTypes()[Opcode][OperandIdx];46 47 switch (Type) {48 case CFIProgram::OT_Unset: {49 OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";50 auto OpcodeName = P.callFrameString(Opcode);51 if (!OpcodeName.empty())52 OS << " " << OpcodeName;53 else54 OS << format(" Opcode %x", Opcode);55 break;56 }57 case CFIProgram::OT_None:58 break;59 case CFIProgram::OT_Address:60 OS << format(" %" PRIx64, Operand);61 Address = Operand;62 break;63 case CFIProgram::OT_Offset:64 // The offsets are all encoded in a unsigned form, but in practice65 // consumers use them signed. It's most certainly legacy due to66 // the lack of signed variants in the first Dwarf standards.67 OS << format(" %+" PRId64, int64_t(Operand));68 break;69 case CFIProgram::OT_FactoredCodeOffset: // Always Unsigned70 if (P.codeAlign())71 OS << format(" %" PRId64, Operand * P.codeAlign());72 else73 OS << format(" %" PRId64 "*code_alignment_factor", Operand);74 if (Address && P.codeAlign()) {75 *Address += Operand * P.codeAlign();76 OS << format(" to 0x%" PRIx64, *Address);77 }78 break;79 case CFIProgram::OT_SignedFactDataOffset:80 if (P.dataAlign())81 OS << format(" %" PRId64, int64_t(Operand) * P.dataAlign());82 else83 OS << format(" %" PRId64 "*data_alignment_factor", int64_t(Operand));84 break;85 case CFIProgram::OT_UnsignedFactDataOffset:86 if (P.dataAlign())87 OS << format(" %" PRId64, Operand * P.dataAlign());88 else89 OS << format(" %" PRId64 "*data_alignment_factor", Operand);90 break;91 case CFIProgram::OT_Register:92 OS << ' ';93 printRegister(OS, DumpOpts, Operand);94 break;95 case CFIProgram::OT_AddressSpace:96 OS << format(" in addrspace%" PRId64, Operand);97 break;98 case CFIProgram::OT_Expression:99 assert(Instr.Expression && "missing DWARFExpression object");100 OS << " ";101 printDwarfExpression(&Instr.Expression.value(), OS, DumpOpts, nullptr);102 break;103 }104}105 106void llvm::dwarf::printCFIProgram(const CFIProgram &P, raw_ostream &OS,107 const DIDumpOptions &DumpOpts,108 unsigned IndentLevel,109 std::optional<uint64_t> Address) {110 for (const auto &Instr : P) {111 uint8_t Opcode = Instr.Opcode;112 OS.indent(2 * IndentLevel);113 OS << P.callFrameString(Opcode) << ":";114 for (size_t i = 0; i < Instr.Ops.size(); ++i)115 printOperand(OS, DumpOpts, P, Instr, i, Instr.Ops[i], Address);116 OS << '\n';117 }118}119