aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/llvm/MC/MCAssembler.h12
-rw-r--r--lib/MC/MCAssembler.cpp31
-rw-r--r--test/MC/ELF/relax-crash.s11
3 files changed, 40 insertions, 14 deletions
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h
index 6a1f83e..a757a92 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 6558a1b..9dc67644 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<MCOrgFragment>(F).getSize();
- case MCFragment::FT_Dwarf: {
- const MCDwarfLineAddrFragment &OF = cast<MCDwarfLineAddrFragment>(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<MCDwarfLineAddrFragment>(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<MCOrgFragment>(it2));
break;
+ case MCFragment::FT_Dwarf:
+ WasRelaxed |= RelaxDwarfLineAddr(Writer, Layout,
+ *cast<MCDwarfLineAddrFragment>(it2));
+ break;
case MCFragment::FT_LEB:
WasRelaxed |= RelaxLEB(Writer, Layout, *cast<MCLEBFragment>(it2));
break;
diff --git a/test/MC/ELF/relax-crash.s b/test/MC/ELF/relax-crash.s
new file mode 100644
index 0000000..442825d
--- /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