diff options
Diffstat (limited to 'contrib/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp')
-rw-r--r-- | contrib/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp | 93 |
1 files changed, 81 insertions, 12 deletions
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp index 2df4456053fb..470d4b5364b4 100644 --- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp @@ -1,13 +1,13 @@ //===-- DWARFExpression.cpp -----------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/Support/Format.h" @@ -97,6 +97,11 @@ static DescVector getDescriptions() { Descriptions[DW_OP_addrx] = Desc(Op::Dwarf4, Op::SizeLEB); Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB); Descriptions[DW_OP_GNU_const_index] = Desc(Op::Dwarf4, Op::SizeLEB); + Descriptions[DW_OP_GNU_entry_value] = Desc(Op::Dwarf4, Op::SizeLEB); + + Descriptions[DW_OP_convert] = Desc(Op::Dwarf5, Op::BaseTypeRef); + Descriptions[DW_OP_entry_value] = Desc(Op::Dwarf5, Op::SizeLEB); + return Descriptions; } @@ -152,17 +157,21 @@ bool DWARFExpression::Operation::extract(DataExtractor Data, uint16_t Version, case Operation::SizeAddr: if (AddressSize == 8) { Operands[Operand] = Data.getU64(&Offset); - } else { - assert(AddressSize == 4); + } else if (AddressSize == 4) { Operands[Operand] = Data.getU32(&Offset); + } else { + assert(AddressSize == 2); + Operands[Operand] = Data.getU16(&Offset); } break; case Operation::SizeRefAddr: if (getRefAddrSize(AddressSize, Version) == 8) { Operands[Operand] = Data.getU64(&Offset); - } else { - assert(getRefAddrSize(AddressSize, Version) == 4); + } else if (getRefAddrSize(AddressSize, Version) == 4) { Operands[Operand] = Data.getU32(&Offset); + } else { + assert(getRefAddrSize(AddressSize, Version) == 2); + Operands[Operand] = Data.getU16(&Offset); } break; case Operation::SizeLEB: @@ -171,6 +180,9 @@ bool DWARFExpression::Operation::extract(DataExtractor Data, uint16_t Version, else Operands[Operand] = Data.getULEB128(&Offset); break; + case Operation::BaseTypeRef: + Operands[Operand] = Data.getULEB128(&Offset); + break; case Operation::SizeBlock: // We need a size, so this cannot be the first operand if (Operand == 0) @@ -182,6 +194,8 @@ bool DWARFExpression::Operation::extract(DataExtractor Data, uint16_t Version, default: llvm_unreachable("Unknown DWARFExpression Op size"); } + + OperandEndOffsets[Operand] = Offset; } EndOffset = Offset; @@ -222,6 +236,7 @@ static bool prettyPrintRegisterOp(raw_ostream &OS, uint8_t Opcode, bool DWARFExpression::Operation::print(raw_ostream &OS, const DWARFExpression *Expr, const MCRegisterInfo *RegInfo, + DWARFUnit *U, bool isEH) { if (Error) { OS << "<decoding error>"; @@ -245,14 +260,25 @@ bool DWARFExpression::Operation::print(raw_ostream &OS, if (Size == Operation::SizeNA) break; - if (Size == Operation::SizeBlock) { + if (Size == Operation::BaseTypeRef && U) { + auto Die = U->getDIEForOffset(U->getOffset() + Operands[Operand]); + if (Die && Die.getTag() == dwarf::DW_TAG_base_type) { + OS << format(" (0x%08x)", U->getOffset() + Operands[Operand]); + if (auto Name = Die.find(dwarf::DW_AT_name)) + OS << " \"" << Name->getAsCString() << "\""; + } else { + OS << format(" <invalid base_type ref: 0x%" PRIx64 ">", + Operands[Operand]); + } + } else if (Size == Operation::SizeBlock) { uint32_t Offset = Operands[Operand]; for (unsigned i = 0; i < Operands[Operand - 1]; ++i) OS << format(" 0x%02x", Expr->Data.getU8(&Offset)); } else { if (Signed) OS << format(" %+" PRId64, (int64_t)Operands[Operand]); - else + else if (Opcode != DW_OP_entry_value && + Opcode != DW_OP_GNU_entry_value) OS << format(" 0x%" PRIx64, Operands[Operand]); } } @@ -260,17 +286,60 @@ bool DWARFExpression::Operation::print(raw_ostream &OS, } void DWARFExpression::print(raw_ostream &OS, const MCRegisterInfo *RegInfo, - bool IsEH) const { + DWARFUnit *U, bool IsEH) const { + uint32_t EntryValExprSize = 0; for (auto &Op : *this) { - if (!Op.print(OS, this, RegInfo, IsEH)) { + if (!Op.print(OS, this, RegInfo, U, IsEH)) { uint32_t FailOffset = Op.getEndOffset(); while (FailOffset < Data.getData().size()) OS << format(" %02x", Data.getU8(&FailOffset)); return; } + + if (Op.getCode() == DW_OP_entry_value || + Op.getCode() == DW_OP_GNU_entry_value) { + OS << "("; + EntryValExprSize = Op.getRawOperand(0); + continue; + } + + if (EntryValExprSize) { + EntryValExprSize--; + if (EntryValExprSize == 0) + OS << ")"; + } + if (Op.getEndOffset() < Data.getData().size()) OS << ", "; } } +bool DWARFExpression::Operation::verify(DWARFUnit *U) { + + for (unsigned Operand = 0; Operand < 2; ++Operand) { + unsigned Size = Desc.Op[Operand]; + + if (Size == Operation::SizeNA) + break; + + if (Size == Operation::BaseTypeRef) { + auto Die = U->getDIEForOffset(U->getOffset() + Operands[Operand]); + if (!Die || Die.getTag() != dwarf::DW_TAG_base_type) { + Error = true; + return false; + } + } + } + + return true; +} + +bool DWARFExpression::verify(DWARFUnit *U) { + for (auto &Op : *this) + if (!Op.verify(U)) + return false; + + return true; +} + } // namespace llvm |