From 187d8339dbc0530850e54a86edf36f1a865a5823 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 7 Nov 2010 02:07:12 +0000 Subject: [PATCH] Relax dwarf line fragments. This fixes a crash in the included testcase. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118365 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCAssembler.h | 12 +++++++++++- lib/MC/MCAssembler.cpp | 31 ++++++++++++++++++------------- test/MC/ELF/relax-crash.s | 11 +++++++++++ 3 files changed, 40 insertions(+), 14 deletions(-) create mode 100644 test/MC/ELF/relax-crash.s diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 6a1f83e1597..a757a922085 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -388,11 +388,14 @@ class MCDwarfLineAddrFragment : public MCFragment { /// make up the address delta between two .loc dwarf directives. const MCExpr *AddrDelta; + /// Size - The current size estimate. + uint64_t Size; + public: MCDwarfLineAddrFragment(int64_t _LineDelta, const MCExpr &_AddrDelta, MCSectionData *SD = 0) : MCFragment(FT_Dwarf, SD), - LineDelta(_LineDelta), AddrDelta(&_AddrDelta) {} + LineDelta(_LineDelta), AddrDelta(&_AddrDelta), Size(1) {} /// @name Accessors /// @{ @@ -401,6 +404,10 @@ public: const MCExpr &getAddrDelta() const { return *AddrDelta; } + uint64_t getSize() const { return Size; } + + void setSize(uint64_t Size_) { Size = Size_; } + /// @} static bool classof(const MCFragment *F) { @@ -727,6 +734,9 @@ private: bool RelaxLEB(const MCObjectWriter &Writer, MCAsmLayout &Layout, MCLEBFragment &IF); + bool RelaxDwarfLineAddr(const MCObjectWriter &Writer, MCAsmLayout &Layout, + MCDwarfLineAddrFragment &DF); + /// FinishLayout - Finalize a layout, including fragment lowering. void FinishLayout(MCAsmLayout &Layout); diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 6558a1b927b..9dc67644b7a 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -340,19 +340,8 @@ uint64_t MCAssembler::ComputeFragmentSize(MCAsmLayout &Layout, case MCFragment::FT_Org: return cast(F).getSize(); - case MCFragment::FT_Dwarf: { - const MCDwarfLineAddrFragment &OF = cast(F); - - // The AddrDelta is really unsigned and it can only increase. - int64_t AddrDelta; - - OF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, &Layout); - - int64_t LineDelta; - LineDelta = OF.getLineDelta(); - - return MCDwarfLineAddr::ComputeSize(LineDelta, AddrDelta); - } + case MCFragment::FT_Dwarf: + return cast(F).getSize(); } assert(0 && "invalid fragment kind"); @@ -861,6 +850,18 @@ bool MCAssembler::RelaxLEB(const MCObjectWriter &Writer, return OldSize != LF.getSize(); } +bool MCAssembler::RelaxDwarfLineAddr(const MCObjectWriter &Writer, + MCAsmLayout &Layout, + MCDwarfLineAddrFragment &DF) { + int64_t AddrDelta; + DF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, &Layout); + int64_t LineDelta; + LineDelta = DF.getLineDelta(); + uint64_t OldSize = DF.getSize(); + DF.setSize(MCDwarfLineAddr::ComputeSize(LineDelta, AddrDelta)); + return OldSize != DF.getSize(); +} + bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer, MCAsmLayout &Layout) { ++stats::RelaxationSteps; @@ -886,6 +887,10 @@ bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer, case MCFragment::FT_Org: WasRelaxed |= RelaxOrg(Writer, Layout, *cast(it2)); break; + case MCFragment::FT_Dwarf: + WasRelaxed |= RelaxDwarfLineAddr(Writer, Layout, + *cast(it2)); + break; case MCFragment::FT_LEB: WasRelaxed |= RelaxLEB(Writer, Layout, *cast(it2)); break; diff --git a/test/MC/ELF/relax-crash.s b/test/MC/ELF/relax-crash.s new file mode 100644 index 00000000000..442825db81a --- /dev/null +++ b/test/MC/ELF/relax-crash.s @@ -0,0 +1,11 @@ +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t + +// This is a test that we don't crash. We used to do so by going in a infinite +// recursion trying to compute the size of a MCDwarfLineAddrFragment. + + .section .debug_line,"",@progbits + .text + .file 1 "Disassembler.ii" + .section foo + .loc 1 1 0 + ret -- 2.34.1