Relax dwarf line fragments. This fixes a crash in the included testcase.
authorRafael Espindola <rafael.espindola@gmail.com>
Sun, 7 Nov 2010 02:07:12 +0000 (02:07 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Sun, 7 Nov 2010 02:07:12 +0000 (02:07 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118365 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCAssembler.h
lib/MC/MCAssembler.cpp
test/MC/ELF/relax-crash.s [new file with mode: 0644]

index 6a1f83e15978a0c290e73367d7e06ac3d4dd187f..a757a922085d08701134ca515a0603692b8949a2 100644 (file)
@@ -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);
 
index 6558a1b927b6ac5e5e4b9cb99045fb084275db50..9dc67644b7a1647b80d767b8a5fa889f8ac98f16 100644 (file)
@@ -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 (file)
index 0000000..442825d
--- /dev/null
@@ -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