brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.9 KiB · a4bdd1f Raw
186 lines · cpp
1//===----------------------------------------------------------------------===//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/DWARFUnwindTablePrinter.h"10#include "llvm/DebugInfo/DIContext.h"11#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"12#include "llvm/Support/ErrorHandling.h"13#include "llvm/Support/Format.h"14#include "llvm/Support/raw_ostream.h"15#include <cassert>16#include <cinttypes>17#include <cstdint>18 19using namespace llvm;20using namespace dwarf;21 22static void printRegister(raw_ostream &OS, DIDumpOptions DumpOpts,23                          unsigned RegNum) {24  if (DumpOpts.GetNameForDWARFReg) {25    auto RegName = DumpOpts.GetNameForDWARFReg(RegNum, DumpOpts.IsEH);26    if (!RegName.empty()) {27      OS << RegName;28      return;29    }30  }31  OS << "reg" << RegNum;32}33 34/// 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,49                                DIDumpOptions DumpOpts) {50  if (UL.getDereference())51    OS << '[';52  switch (UL.getLocation()) {53  case UnwindLocation::Unspecified:54    OS << "unspecified";55    break;56  case UnwindLocation::Undefined:57    OS << "undefined";58    break;59  case UnwindLocation::Same:60    OS << "same";61    break;62  case UnwindLocation::CFAPlusOffset:63    OS << "CFA";64    if (UL.getOffset() == 0)65      break;66    if (UL.getOffset() > 0)67      OS << "+";68    OS << UL.getOffset();69    break;70  case UnwindLocation::RegPlusOffset:71    printRegister(OS, DumpOpts, UL.getRegister());72    if (UL.getOffset() == 0 && !UL.hasAddressSpace())73      break;74    if (UL.getOffset() >= 0)75      OS << "+";76    OS << UL.getOffset();77    if (UL.hasAddressSpace())78      OS << " in addrspace" << UL.getAddressSpace();79    break;80  case UnwindLocation::DWARFExpr: {81    if (UL.getDWARFExpressionBytes()) {82      auto Expr = *UL.getDWARFExpressionBytes();83      printDwarfExpression(&Expr, OS, DumpOpts, nullptr);84    }85    break;86  }87  case UnwindLocation::Constant:88    OS << UL.getOffset();89    break;90  }91  if (UL.getDereference())92    OS << ']';93}94 95raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS,96                                     const UnwindLocation &UL) {97  auto DumpOpts = DIDumpOptions();98  printUnwindLocation(UL, OS, DumpOpts);99  return OS;100}101 102/// 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,117                                   DIDumpOptions DumpOpts) {118  bool First = true;119  for (uint32_t Reg : RL.getRegisters()) {120    auto Loc = *RL.getRegisterLocation(Reg);121    if (First)122      First = false;123    else124      OS << ", ";125    printRegister(OS, DumpOpts, Reg);126    OS << '=';127    printUnwindLocation(Loc, OS, DumpOpts);128  }129}130 131raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS,132                                     const RegisterLocations &RL) {133  auto DumpOpts = DIDumpOptions();134  printRegisterLocations(RL, OS, DumpOpts);135  return OS;136}137 138/// 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,155                           DIDumpOptions DumpOpts, unsigned IndentLevel) {156  OS.indent(2 * IndentLevel);157  if (Row.hasAddress())158    OS << format("0x%" PRIx64 ": ", Row.getAddress());159  OS << "CFA=";160  printUnwindLocation(Row.getCFAValue(), OS, DumpOpts);161  if (Row.getRegisterLocations().hasLocations()) {162    OS << ": ";163    printRegisterLocations(Row.getRegisterLocations(), OS, DumpOpts);164  }165  OS << "\n";166}167 168raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindRow &Row) {169  auto DumpOpts = DIDumpOptions();170  printUnwindRow(Row, OS, DumpOpts, 0);171  return OS;172}173 174void llvm::dwarf::printUnwindTable(const UnwindTable &Rows, raw_ostream &OS,175                                   DIDumpOptions DumpOpts,176                                   unsigned IndentLevel) {177  for (const UnwindRow &Row : Rows)178    printUnwindRow(Row, OS, DumpOpts, IndentLevel);179}180 181raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindTable &Rows) {182  auto DumpOpts = DIDumpOptions();183  printUnwindTable(Rows, OS, DumpOpts, 0);184  return OS;185}186