Index: llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h @@ -12,6 +12,8 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/Optional.h" +#include "llvm/BinaryFormat/Dwarf.h" #include "llvm/Support/DataExtractor.h" namespace llvm { @@ -88,7 +90,8 @@ uint64_t getRawOperand(unsigned Idx) { return Operands[Idx]; } uint64_t getOperandEndOffset(unsigned Idx) { return OperandEndOffsets[Idx]; } uint64_t getEndOffset() { return EndOffset; } - bool extract(DataExtractor Data, uint8_t AddressSize, uint64_t Offset); + bool extract(DataExtractor Data, uint8_t AddressSize, uint64_t Offset, + Optional Format); bool isError() { return Error; } bool print(raw_ostream &OS, const DWARFExpression *Expr, const MCRegisterInfo *RegInfo, DWARFUnit *U, bool isEH); @@ -107,7 +110,7 @@ : Expr(Expr), Offset(Offset) { Op.Error = Offset >= Expr->Data.getData().size() || - !Op.extract(Expr->Data, Expr->AddressSize, Offset); + !Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format); } public: @@ -115,7 +118,7 @@ Offset = Op.isError() ? Expr->Data.getData().size() : Op.EndOffset; Op.Error = Offset >= Expr->Data.getData().size() || - !Op.extract(Expr->Data, Expr->AddressSize, Offset); + !Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format); return Op; } @@ -127,8 +130,9 @@ friend bool operator==(const iterator &, const iterator &); }; - DWARFExpression(DataExtractor Data, uint8_t AddressSize) - : Data(Data), AddressSize(AddressSize) { + DWARFExpression(DataExtractor Data, uint8_t AddressSize, + Optional Format = None) + : Data(Data), AddressSize(AddressSize), Format(Format) { assert(AddressSize == 8 || AddressSize == 4 || AddressSize == 2); } @@ -143,6 +147,7 @@ private: DataExtractor Data; uint8_t AddressSize; + Optional Format; }; inline bool operator==(const DWARFExpression::iterator &LHS, Index: llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -2337,7 +2337,7 @@ DWARFDataExtractor Data(StringRef(DebugLocs.getBytes(Entry).data(), DebugLocs.getBytes(Entry).size()), Asm->getDataLayout().isLittleEndian(), PtrSize); - DWARFExpression Expr(Data, PtrSize); + DWARFExpression Expr(Data, PtrSize, Asm->OutContext.getDwarfFormat()); using Encoding = DWARFExpression::Operation::Encoding; uint64_t Offset = 0; Index: llvm/lib/DWARFLinker/DWARFLinker.cpp =================================================================== --- llvm/lib/DWARFLinker/DWARFLinker.cpp +++ llvm/lib/DWARFLinker/DWARFLinker.cpp @@ -991,7 +991,8 @@ DWARFUnit &OrigUnit = Unit.getOrigUnit(); DataExtractor Data(StringRef((const char *)Bytes.data(), Bytes.size()), IsLittleEndian, OrigUnit.getAddressByteSize()); - DWARFExpression Expr(Data, OrigUnit.getAddressByteSize()); + DWARFExpression Expr(Data, OrigUnit.getAddressByteSize(), + OrigUnit.getFormParams().Format); cloneExpression(Data, Expr, File, Unit, Buffer); Bytes = Buffer; } @@ -2114,7 +2115,8 @@ DataExtractor Data(Bytes, IsLittleEndian, OrigUnit.getAddressByteSize()); cloneExpression(Data, - DWARFExpression(Data, OrigUnit.getAddressByteSize()), + DWARFExpression(Data, OrigUnit.getAddressByteSize(), + OrigUnit.getFormParams().Format), File, *CurrentUnit, Buffer); }; Emitter->emitLocationsForUnit(*CurrentUnit, DwarfContext, ProcessExpr); Index: llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -130,6 +130,9 @@ DataExtractor Extractor( Data.getData().slice(*Offset, *Offset + ExprLength), Data.isLittleEndian(), Data.getAddressSize()); + // Note. We do not pass the DWARF format to DWARFExpression, because + // DW_OP_call_ref, the only operation which depends on the format, is + // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5. Instructions.back().Expression = DWARFExpression(Extractor, Data.getAddressSize()); *Offset += ExprLength; @@ -143,6 +146,9 @@ DataExtractor Extractor( Data.getData().slice(*Offset, *Offset + BlockLength), Data.isLittleEndian(), Data.getAddressSize()); + // Note. We do not pass the DWARF format to DWARFExpression, because + // DW_OP_call_ref, the only operation which depends on the format, is + // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5. Instructions.back().Expression = DWARFExpression(Extractor, Data.getAddressSize()); *Offset += BlockLength; Index: llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -110,6 +110,10 @@ bool IsLittleEndian, unsigned AddressSize, const MCRegisterInfo *MRI, DWARFUnit *U) { DWARFDataExtractor Extractor(Data, IsLittleEndian, AddressSize); + // Note. We do not pass any format to DWARFExpression, even if the + // corresponding unit is known. For now, there is only one operation, + // DW_OP_call_ref, which depends on the format; it is rarely used, and it is + // unexpected in the location table. DWARFExpression(Extractor, AddressSize).print(OS, MRI, U); } Index: llvm/lib/DebugInfo/DWARF/DWARFDie.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -79,7 +79,8 @@ ArrayRef Expr = *FormValue.getAsBlock(); DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), Ctx.isLittleEndian(), 0); - DWARFExpression(Data, U->getAddressByteSize()).print(OS, MRI, U); + DWARFExpression(Data, U->getAddressByteSize(), U->getFormParams().Format) + .print(OS, MRI, U); return; } Index: llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp @@ -8,7 +8,6 @@ #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" #include @@ -119,7 +118,8 @@ } bool DWARFExpression::Operation::extract(DataExtractor Data, - uint8_t AddressSize, uint64_t Offset) { + uint8_t AddressSize, uint64_t Offset, + Optional Format) { Opcode = Data.getU8(&Offset); Desc = getOpDesc(Opcode); @@ -158,8 +158,10 @@ Operands[Operand] = Data.getUnsigned(&Offset, AddressSize); break; case Operation::SizeRefAddr: - // TODO: Add support for 64-bit DWARF format. - Operands[Operand] = Data.getU32(&Offset); + if (!Format) + return false; + Operands[Operand] = + Data.getUnsigned(&Offset, dwarf::getDwarfOffsetByteSize(*Format)); break; case Operation::SizeLEB: if (Signed) Index: llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -486,7 +486,8 @@ DWARFUnit *U = Die.getDwarfUnit(); for (const auto &Entry : *Loc) { DataExtractor Data(toStringRef(Entry.Expr), DCtx.isLittleEndian(), 0); - DWARFExpression Expression(Data, U->getAddressByteSize()); + DWARFExpression Expression(Data, U->getAddressByteSize(), + U->getFormParams().Format); bool Error = any_of(Expression, [](DWARFExpression::Operation &Op) { return Op.isError(); }); @@ -1294,7 +1295,8 @@ for (const auto &Entry : *Loc) { DataExtractor Data(toStringRef(Entry.Expr), DCtx.isLittleEndian(), U->getAddressByteSize()); - DWARFExpression Expression(Data, U->getAddressByteSize()); + DWARFExpression Expression(Data, U->getAddressByteSize(), + U->getFormParams().Format); bool IsInteresting = any_of(Expression, [](DWARFExpression::Operation &Op) { return !Op.isError() && (Op.getCode() == DW_OP_addr || Op.getCode() == DW_OP_form_tls_address || Index: llvm/test/DebugInfo/X86/DW_OP_call_ref_dwarf64.s =================================================================== --- /dev/null +++ llvm/test/DebugInfo/X86/DW_OP_call_ref_dwarf64.s @@ -0,0 +1,42 @@ +# RUN: llvm-mc -triple x86_64 %s -filetype=obj -o %t.o +# RUN: llvm-dwarfdump -debug-info %t.o | FileCheck %s +# RUN: llvm-dwarfdump -verify %t.o | FileCheck %s --check-prefix=VERIFY + +# CHECK: DW_TAG_variable +# CHECK-NEXT: DW_AT_location (DW_OP_call_ref 0x1100223344) + +# VERIFY-NOT: error: DIE contains invalid DWARF expression: +# VERIFY: No errors. + + .section .debug_abbrev,"",@progbits + .uleb128 1 # Abbreviation Code + .uleb128 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .uleb128 5 # Abbreviation Code + .uleb128 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .uleb128 2 # DW_AT_location + .uleb128 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + + .section .debug_info,"",@progbits + .long 0xffffffff # DWARF64 mark + .quad .Lcu_end-.Lcu_start # Length of Unit +.Lcu_start: + .short 5 # DWARF version number + .byte 1 # DW_UT_compile + .byte 8 # Address Size + .quad .debug_abbrev # Offset Into Abbrev. Section + .uleb128 1 # Abbrev [1] DW_TAG_compile_unit + .uleb128 5 # Abbrev [5] DW_TAG_variable + .byte .Lloc_end-.Lloc_begin # DW_AT_location +.Lloc_begin: + .byte 154 # DW_OP_call_ref + .quad 0x1100223344 # Offset +.Lloc_end: + .byte 0 # End Of Children Mark +.Lcu_end: Index: llvm/test/DebugInfo/X86/DW_OP_call_ref_unexpected.s =================================================================== --- /dev/null +++ llvm/test/DebugInfo/X86/DW_OP_call_ref_unexpected.s @@ -0,0 +1,29 @@ +# RUN: llvm-mc -triple x86_64 %s -filetype=obj -o - | \ +# RUN: llvm-dwarfdump -debug-loc - | \ +# RUN: FileCheck %s + +# This checks that we do not try to interpret DW_OP_call_ref if it is +# encountered in the location table. + +# CHECK: .debug_loc contents: +# CHECK-NEXT: 0x00000000: +# CHECK-NEXT: (0x0000000000000000, 0x0000000000000015): 9a ff 00 00 00 + + .section .debug_loc, "", @progbits + .quad 0 # Beginning address offset + .quad 0x15 # Ending address offset + .short .LDescrEnd-.LDescrBegin # Location description length +.LDescrBegin: + .byte 0x9a # DW_OP_call_ref + .long 0xff +.LDescrEnd: + .quad 0, 0 # EOL entry + +# A dummy CU to provide the parser of .debug_loc with the address size. + .section .debug_info,"",@progbits + .long .LCUEnd-.LCUBegin # Length of Unit +.LCUBegin: + .short 4 # DWARF version number + .long 0 # Offset Into Abbrev. Section + .byte 8 # Address Size +.LCUEnd: Index: llvm/tools/llvm-dwarfdump/Statistics.cpp =================================================================== --- llvm/tools/llvm-dwarfdump/Statistics.cpp +++ llvm/tools/llvm-dwarfdump/Statistics.cpp @@ -248,7 +248,8 @@ DWARFUnit *U = Die.getDwarfUnit(); DataExtractor Data(toStringRef(D), Die.getDwarfUnit()->getContext().isLittleEndian(), 0); - DWARFExpression Expression(Data, U->getAddressByteSize()); + DWARFExpression Expression(Data, U->getAddressByteSize(), + U->getFormParams().Format); // Consider the expression containing the DW_OP_entry_value as // an entry value. return llvm::any_of(Expression, [](DWARFExpression::Operation &Op) {