[llvm] befbc99 - Reland D79501 "[DebugInfo] Fix handling DW_OP_call_ref in DWARF64 units."
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Fri May 8 09:36:20 PDT 2020
Author: Fangrui Song
Date: 2020-05-08T09:35:54-07:00
New Revision: befbc99a7f092df5868b5ff0c6e46f41236cb1af
URL: https://github.com/llvm/llvm-project/commit/befbc99a7f092df5868b5ff0c6e46f41236cb1af
DIFF: https://github.com/llvm/llvm-project/commit/befbc99a7f092df5868b5ff0c6e46f41236cb1af.diff
LOG: Reland D79501 "[DebugInfo] Fix handling DW_OP_call_ref in DWARF64 units."
With a fix to uninitialized EndOffset.
DW_OP_call_ref is the only operation that has an operand which depends
on the DWARF format. The patch fixes handling that operation in DWARF64
units.
Differential Revision: https://reviews.llvm.org/D79501
Added:
llvm/test/DebugInfo/X86/DW_OP_call_ref_dwarf64.s
llvm/test/DebugInfo/X86/DW_OP_call_ref_unexpected.s
Modified:
llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h
llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
llvm/lib/DWARFLinker/DWARFLinker.cpp
llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp
llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
llvm/tools/llvm-dwarfdump/Statistics.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h
index 4bbff49606ab..28929306ca92 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h
+++ b/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 @@ class DWARFExpression {
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<dwarf::DwarfFormat> Format);
bool isError() { return Error; }
bool print(raw_ostream &OS, const DWARFExpression *Expr,
const MCRegisterInfo *RegInfo, DWARFUnit *U, bool isEH);
@@ -107,7 +110,7 @@ class DWARFExpression {
: 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 @@ class DWARFExpression {
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 @@ class DWARFExpression {
friend bool operator==(const iterator &, const iterator &);
};
- DWARFExpression(DataExtractor Data, uint8_t AddressSize)
- : Data(Data), AddressSize(AddressSize) {
+ DWARFExpression(DataExtractor Data, uint8_t AddressSize,
+ Optional<dwarf::DwarfFormat> Format = None)
+ : Data(Data), AddressSize(AddressSize), Format(Format) {
assert(AddressSize == 8 || AddressSize == 4 || AddressSize == 2);
}
@@ -143,6 +147,7 @@ class DWARFExpression {
private:
DataExtractor Data;
uint8_t AddressSize;
+ Optional<dwarf::DwarfFormat> Format;
};
inline bool operator==(const DWARFExpression::iterator &LHS,
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index cf1e269e80ad..25b973ec836c 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -2337,7 +2337,7 @@ void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,
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;
diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp
index 1d7ef350f63d..fff3763aea41 100644
--- a/llvm/lib/DWARFLinker/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp
@@ -1008,7 +1008,8 @@ unsigned DWARFLinker::DIECloner::cloneBlockAttribute(
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;
}
@@ -2134,7 +2135,8 @@ uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(
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);
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
index 7c1280dd1944..5b38b29227ab 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
@@ -130,6 +130,9 @@ Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset,
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 @@ Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset,
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;
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
index 17f0b7f5c32a..f38126364401 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
@@ -110,6 +110,10 @@ static void dumpExpression(raw_ostream &OS, ArrayRef<uint8_t> Data,
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
+ // is unexpected in location tables.
DWARFExpression(Extractor, AddressSize).print(OS, MRI, U);
}
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index f93f32917c33..81a6b5dcd5e7 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -79,7 +79,8 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue,
ArrayRef<uint8_t> 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;
}
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp b/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp
index 379b88c49c73..605236bc1833 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp
+++ b/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 <cassert>
@@ -119,7 +118,8 @@ static DWARFExpression::Operation::Description getOpDesc(unsigned OpCode) {
}
bool DWARFExpression::Operation::extract(DataExtractor Data,
- uint8_t AddressSize, uint64_t Offset) {
+ uint8_t AddressSize, uint64_t Offset,
+ Optional<DwarfFormat> Format) {
Opcode = Data.getU8(&Offset);
Desc = getOpDesc(Opcode);
@@ -135,6 +135,7 @@ bool DWARFExpression::Operation::extract(DataExtractor Data,
if (Size == Operation::SizeNA)
break;
+ EndOffset = Offset;
switch (Size & ~Operation::SignBit) {
case Operation::Size1:
Operands[Operand] = Data.getU8(&Offset);
@@ -158,8 +159,10 @@ bool DWARFExpression::Operation::extract(DataExtractor Data,
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)
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
index c7d3974fd79a..4f128788b102 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -486,7 +486,8 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
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 @@ static bool isVariableIndexable(const DWARFDie &Die, DWARFContext &DCtx) {
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 ||
diff --git a/llvm/test/DebugInfo/X86/DW_OP_call_ref_dwarf64.s b/llvm/test/DebugInfo/X86/DW_OP_call_ref_dwarf64.s
new file mode 100644
index 000000000000..5031e141956d
--- /dev/null
+++ b/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,"", at 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,"", at 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:
diff --git a/llvm/test/DebugInfo/X86/DW_OP_call_ref_unexpected.s b/llvm/test/DebugInfo/X86/DW_OP_call_ref_unexpected.s
new file mode 100644
index 000000000000..036e044270b6
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/DW_OP_call_ref_unexpected.s
@@ -0,0 +1,28 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
+# RUN: llvm-dwarfdump -debug-loc %t.o | FileCheck %s
+
+# This checks that we do not try to interpret DW_OP_call_ref if it is
+# encountered in a location table.
+
+# CHECK: .debug_loc contents:
+# CHECK-NEXT: 0x00000000:
+# CHECK-NEXT: (0x0000000000000000, 0x0000000000000015): <decoding error>
+
+ .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,"", at progbits
+ .long .LCUEnd-.LCUBegin # Length of Unit
+.LCUBegin:
+ .short 4 # DWARF version number
+ .long 0 # Offset Into Abbrev. Section
+ .byte 8 # Address Size
+.LCUEnd:
diff --git a/llvm/tools/llvm-dwarfdump/Statistics.cpp b/llvm/tools/llvm-dwarfdump/Statistics.cpp
index f1f37c9ec6ea..18b4c40c4d75 100644
--- a/llvm/tools/llvm-dwarfdump/Statistics.cpp
+++ b/llvm/tools/llvm-dwarfdump/Statistics.cpp
@@ -248,7 +248,8 @@ static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
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) {
More information about the llvm-commits
mailing list