Index: include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h +++ include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h @@ -41,7 +41,7 @@ SmallVector Entries; /// Dump this list on OS. void dump(raw_ostream &OS, bool IsLittleEndian, unsigned AddressSize, - const MCRegisterInfo *MRI, uint64_t BaseAddress, + const MCRegisterInfo *MRI, DWARFUnit *U, uint64_t BaseAddress, unsigned Indent) const; }; Index: include/llvm/DebugInfo/DWARF/DWARFExpression.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFExpression.h +++ include/llvm/DebugInfo/DWARF/DWARFExpression.h @@ -41,7 +41,8 @@ SizeAddr = 5, SizeRefAddr = 6, SizeBlock = 7, ///< Preceding operand contains block size - SignBit = 0x8, + BaseTypeRef = 8, + SignBit = 0x80, SignedSize1 = SignBit | Size1, SignedSize2 = SignBit | Size2, SignedSize4 = SignBit | Size4, @@ -54,7 +55,8 @@ DwarfNA, ///< Serves as a marker for unused entries Dwarf2 = 2, Dwarf3, - Dwarf4 + Dwarf4, + Dwarf5 }; /// Description of the encoding of one expression Op. @@ -86,8 +88,9 @@ bool extract(DataExtractor Data, uint16_t Version, uint8_t AddressSize, uint32_t Offset); bool isError() { return Error; } - bool print(raw_ostream &OS, const DWARFExpression *U, - const MCRegisterInfo *RegInfo, bool isEH); + bool print(raw_ostream &OS, const DWARFExpression *Expr, + const MCRegisterInfo *RegInfo, DWARFUnit *U, bool isEH); + bool verify(DWARFUnit *U); }; /// An iterator to go through the expression operations. @@ -130,9 +133,11 @@ iterator begin() const { return iterator(this, 0); } iterator end() const { return iterator(this, Data.getData().size()); } - void print(raw_ostream &OS, const MCRegisterInfo *RegInfo, + void print(raw_ostream &OS, const MCRegisterInfo *RegInfo, DWARFUnit *U, bool IsEH = false) const; + bool verify(DWARFUnit *U); + private: DataExtractor Data; uint16_t Version; Index: lib/DebugInfo/DWARF/DWARFDebugFrame.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -266,7 +266,7 @@ case OT_Expression: assert(Instr.Expression && "missing DWARFExpression object"); OS << " "; - Instr.Expression->print(OS, MRI, IsEH); + Instr.Expression->print(OS, MRI, nullptr, IsEH); break; } } Index: lib/DebugInfo/DWARF/DWARFDebugLoc.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -30,15 +30,16 @@ // non-LLVM tools. static void dumpExpression(raw_ostream &OS, ArrayRef Data, bool IsLittleEndian, unsigned AddressSize, - const MCRegisterInfo *MRI) { + const MCRegisterInfo *MRI, DWARFUnit *U) { DWARFDataExtractor Extractor(StringRef(Data.data(), Data.size()), IsLittleEndian, AddressSize); - DWARFExpression(Extractor, dwarf::DWARF_VERSION, AddressSize).print(OS, MRI); + DWARFExpression(Extractor, dwarf::DWARF_VERSION, AddressSize).print(OS, MRI, U); } void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, bool IsLittleEndian, unsigned AddressSize, const MCRegisterInfo *MRI, + DWARFUnit *U, uint64_t BaseAddress, unsigned Indent) const { for (const Entry &E : Entries) { @@ -50,7 +51,7 @@ BaseAddress + E.End); OS << ": "; - dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI); + dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI, U); } } @@ -68,7 +69,7 @@ Optional Offset) const { auto DumpLocationList = [&](const LocationList &L) { OS << format("0x%8.8x: ", L.Offset); - L.dump(OS, IsLittleEndian, AddressSize, MRI, 0, 12); + L.dump(OS, IsLittleEndian, AddressSize, MRI, nullptr, 0, 12); OS << "\n\n"; }; @@ -253,7 +254,7 @@ llvm_unreachable("unreachable locations list kind"); } - dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI); + dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI, nullptr); } } Index: lib/DebugInfo/DWARF/DWARFDie.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDie.cpp +++ lib/DebugInfo/DWARF/DWARFDie.cpp @@ -86,7 +86,7 @@ DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), Ctx.isLittleEndian(), 0); DWARFExpression(Data, U->getVersion(), U->getAddressByteSize()) - .print(OS, MRI); + .print(OS, MRI, U); return; } @@ -102,8 +102,8 @@ uint64_t BaseAddr = 0; if (Optional BA = U->getBaseAddress()) BaseAddr = BA->Address; - LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, BaseAddr, - Indent); + LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, U, + BaseAddr, Indent); } else OS << "error extracting location list."; return; Index: lib/DebugInfo/DWARF/DWARFExpression.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFExpression.cpp +++ lib/DebugInfo/DWARF/DWARFExpression.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #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" @@ -96,6 +97,9 @@ 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_convert] = Desc(Op::Dwarf5, Op::BaseTypeRef); + return Descriptions; } @@ -170,6 +174,9 @@ 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) @@ -221,6 +228,7 @@ bool DWARFExpression::Operation::print(raw_ostream &OS, const DWARFExpression *Expr, const MCRegisterInfo *RegInfo, + DWARFUnit *U, bool isEH) { if (Error) { OS << ""; @@ -244,7 +252,17 @@ 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(" ", + 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)); @@ -259,9 +277,9 @@ } void DWARFExpression::print(raw_ostream &OS, const MCRegisterInfo *RegInfo, - bool IsEH) const { + DWARFUnit *U, bool IsEH) const { 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)); @@ -272,4 +290,32 @@ } } +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 Index: lib/DebugInfo/DWARF/DWARFVerifier.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -502,7 +502,7 @@ bool Error = llvm::any_of(Expression, [](DWARFExpression::Operation &Op) { return Op.isError(); }); - if (Error) + if (Error || !Expression.verify(U)) ReportError("DIE contains invalid DWARF expression:"); }; if (Optional> Expr = AttrValue.Value.getAsBlock()) { Index: test/tools/llvm-dwarfdump/X86/debug_expr_convert.s =================================================================== --- /dev/null +++ test/tools/llvm-dwarfdump/X86/debug_expr_convert.s @@ -0,0 +1,124 @@ +# RUN: llvm-mc %s -filetype obj -triple x86_64-pc-linux -o %t.o +# RUN: llvm-dwarfdump %t.o | FileCheck %s +# RUN: not llvm-dwarfdump -verify %t.o + +# CHECK: DW_AT_location (DW_OP_addr 0x{{[0-9a-f]+}}, DW_OP_convert , DW_OP_convert (0x{{[0-9a-f]+}}) "DW_ATE_signed_32") + + .text + .file "dbg.g.c" + .file 1 "/tmp/dbg.g.c" + .type global,@object # @global + .data + .globl global + .p2align 2 +global: + .long 255 # 0xff + .size global, 4 + + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 9.0.0 (trunk 354265) (llvm/trunk 354264)" # string offset=0 +.Linfo_string1: + .asciz "dbg.g.c" # string offset=55 +.Linfo_string2: + .asciz "/tmp" # string offset=63 +.Linfo_string3: + .asciz "global" # string offset=68 +.Linfo_string4: + .asciz "int" # string offset=75 +.Linfo_string5: + .asciz "DW_ATE_signed_32" # string offset=79 +.Linfo_string6: + .asciz "DW_ATE_signed_8" # string offset=96 + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x48 DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 12 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + .byte 2 # Abbrev [2] 0x1e:0x7 DW_TAG_base_type + .long .Linfo_string6 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 2 # Abbrev [2] 0x25:0x7 DW_TAG_base_type + .long .Linfo_string5 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 3 # Abbrev [3] 0x2c:0x1f DW_TAG_variable + .long .Linfo_string3 # DW_AT_name + .long 75 # DW_AT_type + # DW_AT_external + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 19 # DW_AT_location + .byte 3 + .quad global + .byte 168 + .asciz "\235\200\200" ### This offset is off by one to test the invalid base_type ref printout + .byte 168 + .asciz "\245\200\200" + .byte 2 # Abbrev [2] 0x4b:0x7 DW_TAG_base_type + .long .Linfo_string4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_macinfo,"",@progbits + .byte 0 # End Of Macro List Mark + + .ident "clang version 9.0.0 (trunk 354265) (llvm/trunk 354264)" + .section ".note.GNU-stack","",@progbits + .section .debug_line,"",@progbits +.Lline_table_start0: