Don't declare all text sections at the start of the .s
authorRafael Espindola <rafael.espindola@gmail.com>
Fri, 20 Mar 2015 20:00:01 +0000 (20:00 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Fri, 20 Mar 2015 20:00:01 +0000 (20:00 +0000)
The code this patch removes was there to make sure the text sections went
before the dwarf sections. That is necessary because MachO uses offsets
relative to the start of the file, so adding a section can change relaxations.

The dwarf sections were being printed at the start just to produce symbols
pointing at the start of those sections.

The underlying issue was fixed in r231898. The dwarf sections are now printed
when they are about to be used, which is after we printed the text sections.

To make sure we don't regress, the patch makes the MachO streamer assert
if CodeGen puts anything unexpected after the DWARF sections.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@232842 91177308-0d34-0410-b5e6-96231b3b80d8

14 files changed:
include/llvm/MC/MCObjectStreamer.h
include/llvm/Support/TargetRegistry.h
lib/CodeGen/LLVMTargetMachine.cpp
lib/MC/MCMachOStreamer.cpp
lib/MC/MCObjectStreamer.cpp
lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp
lib/Target/ARM/ARMAsmPrinter.cpp
lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp
test/CodeGen/ARM/darwin-section-order.ll [deleted file]
test/CodeGen/ARM/none-macho.ll
test/DebugInfo/ARM/header.ll [new file with mode: 0644]
test/DebugInfo/ARM/sectionorder.ll [deleted file]
tools/dsymutil/DwarfLinker.cpp
tools/llvm-mc/llvm-mc.cpp

index 100029f3aae7d62158958aca3f01788d22c568d3..24200724c628bb1603d17fa85c0a694343cbc2ae 100644 (file)
@@ -85,6 +85,8 @@ protected:
   /// fragment is not a data fragment.
   MCDataFragment *getOrCreateDataFragment();
 
+  bool changeSectionImpl(const MCSection *Section, const MCExpr *Subsection);
+
 public:
   void visitUsedSymbol(const MCSymbol &Sym) override;
 
index bad1e5146b17e3bf98ebe1a2795f9c0824b290b7..26134e4eecb79f944cd436e3cf449884227a9197 100644 (file)
@@ -65,7 +65,8 @@ namespace llvm {
                                 bool RelaxAll);
   MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB,
                                   raw_ostream &OS, MCCodeEmitter *CE,
-                                  bool RelaxAll, bool LabelSections = false);
+                                  bool RelaxAll, bool DWARFMustBeAtTheEnd,
+                                  bool LabelSections = false);
 
   MCRelocationInfo *createMCRelocationInfo(StringRef TT, MCContext &Ctx);
 
@@ -138,11 +139,9 @@ namespace llvm {
                                              MCAsmBackend &TAB, raw_ostream &OS,
                                              MCCodeEmitter *Emitter,
                                              bool RelaxAll);
-    typedef MCStreamer *(*MachOStreamerCtorTy)(MCContext &Ctx,
-                                               MCAsmBackend &TAB,
-                                               raw_ostream &OS,
-                                               MCCodeEmitter *Emitter,
-                                               bool RelaxAll);
+    typedef MCStreamer *(*MachOStreamerCtorTy)(
+        MCContext &Ctx, MCAsmBackend &TAB, raw_ostream &OS,
+        MCCodeEmitter *Emitter, bool RelaxAll, bool DWARFMustBeAtTheEnd);
     typedef MCStreamer *(*COFFStreamerCtorTy)(MCContext &Ctx, MCAsmBackend &TAB,
                                               raw_ostream &OS,
                                               MCCodeEmitter *Emitter,
@@ -444,7 +443,8 @@ namespace llvm {
                                        MCAsmBackend &TAB, raw_ostream &OS,
                                        MCCodeEmitter *Emitter,
                                        const MCSubtargetInfo &STI,
-                                       bool RelaxAll) const {
+                                       bool RelaxAll,
+                                       bool DWARFMustBeAtTheEnd) const {
       MCStreamer *S;
       switch (T.getObjectFormat()) {
       default:
@@ -455,9 +455,11 @@ namespace llvm {
         break;
       case Triple::MachO:
         if (MachOStreamerCtorFn)
-          S = MachOStreamerCtorFn(Ctx, TAB, OS, Emitter, RelaxAll);
+          S = MachOStreamerCtorFn(Ctx, TAB, OS, Emitter, RelaxAll,
+                                  DWARFMustBeAtTheEnd);
         else
-          S = createMachOStreamer(Ctx, TAB, OS, Emitter, RelaxAll);
+          S = createMachOStreamer(Ctx, TAB, OS, Emitter, RelaxAll,
+                                  DWARFMustBeAtTheEnd);
         break;
       case Triple::ELF:
         if (ELFStreamerCtorFn)
index f463f70d3e611e2865840375e569cccc1204fbde..0fb0c46ddb14acdc8c3f606b20f5904dfea478f9 100644 (file)
@@ -202,7 +202,8 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
 
     Triple T(getTargetTriple());
     AsmStreamer.reset(getTarget().createMCObjectStreamer(
-        T, *Context, *MAB, Out, MCE, STI, Options.MCOptions.MCRelaxAll));
+        T, *Context, *MAB, Out, MCE, STI, Options.MCOptions.MCRelaxAll,
+        /*DWARFMustBeAtTheEnd*/ true));
     break;
   }
   case CGFT_Null:
@@ -253,7 +254,8 @@ bool LLVMTargetMachine::addPassesToEmitMC(PassManagerBase &PM,
   Triple T(getTargetTriple());
   const MCSubtargetInfo &STI = *getMCSubtargetInfo();
   std::unique_ptr<MCStreamer> AsmStreamer(getTarget().createMCObjectStreamer(
-      T, *Ctx, *MAB, Out, MCE, STI, Options.MCOptions.MCRelaxAll));
+      T, *Ctx, *MAB, Out, MCE, STI, Options.MCOptions.MCRelaxAll,
+      /*DWARFMustBeAtTheEnd*/ true));
 
   // Create the AsmPrinter, which takes ownership of AsmStreamer if successful.
   FunctionPass *Printer =
index 6246ed01ab7b663866ad68a6cdba9cb0dd066e1c..d5c7101d0d554da05fca859546c323b67d6a3fdc 100644 (file)
@@ -40,6 +40,9 @@ private:
   /// need for local relocations. False by default.
   bool LabelSections;
 
+  bool DWARFMustBeAtTheEnd;
+  bool CreatedADWARFSection;
+
   /// HasSectionLabel - map of which sections have already had a non-local
   /// label emitted to them. Used so we don't emit extraneous linker local
   /// labels in the middle of the section.
@@ -52,9 +55,9 @@ private:
 
 public:
   MCMachOStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS,
-                  MCCodeEmitter *Emitter, bool label)
-      : MCObjectStreamer(Context, MAB, OS, Emitter),
-        LabelSections(label) {}
+                  MCCodeEmitter *Emitter, bool DWARFMustBeAtTheEnd, bool label)
+      : MCObjectStreamer(Context, MAB, OS, Emitter), LabelSections(label),
+        DWARFMustBeAtTheEnd(DWARFMustBeAtTheEnd), CreatedADWARFSection(false) {}
 
   /// state management
   void reset() override {
@@ -120,10 +123,43 @@ public:
 
 } // end anonymous namespace.
 
+static bool canGoAfterDWARF(const MCSectionMachO &MSec) {
+  // These sections are created by the assembler itself after the end of
+  // the .s file.
+  StringRef SegName = MSec.getSegmentName();
+  StringRef SecName = MSec.getSectionName();
+
+  if (SegName == "__LD" && SecName == "__compact_unwind")
+    return true;
+
+  if (SegName == "__IMPORT") {
+    if (SecName == "__jump_table")
+      return true;
+
+    if (SecName == "__pointers")
+      return true;
+  }
+
+  if (SegName == "__TEXT" && SecName == "__eh_frame")
+    return true;
+
+  if (SegName == "__DATA" && SecName == "__nl_symbol_ptr")
+    return true;
+
+  return false;
+}
+
 void MCMachOStreamer::ChangeSection(const MCSection *Section,
                                     const MCExpr *Subsection) {
   // Change the section normally.
-  MCObjectStreamer::ChangeSection(Section, Subsection);
+  bool Created = MCObjectStreamer::changeSectionImpl(Section, Subsection);
+  const MCSectionMachO &MSec = *cast<MCSectionMachO>(Section);
+  StringRef SegName = MSec.getSegmentName();
+  if (SegName == "__DWARF")
+    CreatedADWARFSection = true;
+  else if (Created && DWARFMustBeAtTheEnd && !canGoAfterDWARF(MSec))
+    assert(!CreatedADWARFSection && "Creating regular section after DWARF");
+
   // Output a linker-local symbol so we don't need section-relative local
   // relocations. The linker hates us when we do that.
   if (LabelSections && !HasSectionLabel[Section]) {
@@ -456,9 +492,10 @@ void MCMachOStreamer::FinishImpl() {
 
 MCStreamer *llvm::createMachOStreamer(MCContext &Context, MCAsmBackend &MAB,
                                       raw_ostream &OS, MCCodeEmitter *CE,
-                                      bool RelaxAll,
+                                      bool RelaxAll, bool DWARFMustBeAtTheEnd,
                                       bool LabelSections) {
-  MCMachOStreamer *S = new MCMachOStreamer(Context, MAB, OS, CE, LabelSections);
+  MCMachOStreamer *S = new MCMachOStreamer(Context, MAB, OS, CE,
+                                           DWARFMustBeAtTheEnd, LabelSections);
   if (RelaxAll)
     S->getAssembler().setRelaxAll(true);
   return S;
index 5b6b6b5facfca70417a861acf1812ae92b0bd24b..6aa2de36db6fbfb23b4a38079967fb8eded07ed0 100644 (file)
@@ -182,10 +182,16 @@ void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias,
 
 void MCObjectStreamer::ChangeSection(const MCSection *Section,
                                      const MCExpr *Subsection) {
+  changeSectionImpl(Section, Subsection);
+}
+
+bool MCObjectStreamer::changeSectionImpl(const MCSection *Section,
+                                         const MCExpr *Subsection) {
   assert(Section && "Cannot switch to a null section!");
   flushPendingLabels(nullptr);
 
-  CurSectionData = &getAssembler().getOrCreateSectionData(*Section);
+  bool Created;
+  CurSectionData = &getAssembler().getOrCreateSectionData(*Section, &Created);
 
   int64_t IntSubsection = 0;
   if (Subsection &&
@@ -195,6 +201,7 @@ void MCObjectStreamer::ChangeSection(const MCSection *Section,
     report_fatal_error("Subsection number out of range");
   CurInsertionPoint =
     CurSectionData->getSubsectionInsertionPoint(unsigned(IntSubsection));
+  return Created;
 }
 
 void MCObjectStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
index 1a72b79a291bea40da99e4618c8a27851bb83d8c..38b399d5da4119b197c793838c7060e67448a972 100644 (file)
@@ -131,8 +131,10 @@ static MCStreamer *createELFStreamer(const Triple &T, MCContext &Ctx,
 
 static MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB,
                                        raw_ostream &OS, MCCodeEmitter *Emitter,
-                                       bool RelaxAll) {
+                                       bool RelaxAll,
+                                       bool DWARFMustBeAtTheEnd) {
   return createMachOStreamer(Ctx, TAB, OS, Emitter, RelaxAll,
+                             DWARFMustBeAtTheEnd,
                              /*LabelSections*/ true);
 }
 
index e3c9dcbf72b1b5323cfb9c2f7c3ac81c1dd99e90..971e10df8b968696708bd0a78bcad95be9a0d3fa 100644 (file)
@@ -435,65 +435,6 @@ void ARMAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
 
 void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) {
   Triple TT(TM.getTargetTriple());
-  if (TT.isOSBinFormatMachO()) {
-    Reloc::Model RelocM = TM.getRelocationModel();
-    if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) {
-      // Declare all the text sections up front (before the DWARF sections
-      // emitted by AsmPrinter::doInitialization) so the assembler will keep
-      // them together at the beginning of the object file.  This helps
-      // avoid out-of-range branches that are due a fundamental limitation of
-      // the way symbol offsets are encoded with the current Darwin ARM
-      // relocations.
-      const TargetLoweringObjectFileMachO &TLOFMacho =
-        static_cast<const TargetLoweringObjectFileMachO &>(
-          getObjFileLowering());
-
-      // Collect the set of sections our functions will go into.
-      SetVector<const MCSection *, SmallVector<const MCSection *, 8>,
-        SmallPtrSet<const MCSection *, 8> > TextSections;
-      // Default text section comes first.
-      TextSections.insert(TLOFMacho.getTextSection());
-      // Now any user defined text sections from function attributes.
-      for (Module::iterator F = M.begin(), e = M.end(); F != e; ++F)
-        if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage())
-          TextSections.insert(TLOFMacho.SectionForGlobal(F, *Mang, TM));
-      // Now the coalescable sections.
-      TextSections.insert(TLOFMacho.getTextCoalSection());
-      TextSections.insert(TLOFMacho.getConstTextCoalSection());
-
-      // Emit the sections in the .s file header to fix the order.
-      for (unsigned i = 0, e = TextSections.size(); i != e; ++i)
-        OutStreamer.SwitchSection(TextSections[i]);
-
-      if (RelocM == Reloc::DynamicNoPIC) {
-        const MCSection *sect =
-          OutContext.getMachOSection("__TEXT", "__symbol_stub4",
-                                     MachO::S_SYMBOL_STUBS,
-                                     12, SectionKind::getText());
-        OutStreamer.SwitchSection(sect);
-      } else {
-        const MCSection *sect =
-          OutContext.getMachOSection("__TEXT", "__picsymbolstub4",
-                                     MachO::S_SYMBOL_STUBS,
-                                     16, SectionKind::getText());
-        OutStreamer.SwitchSection(sect);
-      }
-      const MCSection *StaticInitSect =
-        OutContext.getMachOSection("__TEXT", "__StaticInit",
-                                   MachO::S_REGULAR |
-                                   MachO::S_ATTR_PURE_INSTRUCTIONS,
-                                   SectionKind::getText());
-      OutStreamer.SwitchSection(StaticInitSect);
-    }
-
-    // Compiling with debug info should not affect the code
-    // generation.  Ensure the cstring section comes before the
-    // optional __DWARF secion. Otherwise, PC-relative loads would
-    // have to use different instruction sequences at "-g" in order to
-    // reach global data in the same object file.
-    OutStreamer.SwitchSection(getObjFileLowering().getCStringSection());
-  }
-
   // Use unified assembler syntax.
   OutStreamer.EmitAssemblerFlag(MCAF_SyntaxUnified);
 
index 9f75491911cd6d4784b9b79c835c04a62a29bf43..82dac5c435755d898899e89d51e256693c865b0a 100644 (file)
@@ -307,9 +307,9 @@ static MCStreamer *createELFStreamer(const Triple &T, MCContext &Ctx,
 
 static MCStreamer *createARMMachOStreamer(MCContext &Ctx, MCAsmBackend &MAB,
                                           raw_ostream &OS,
-                                          MCCodeEmitter *Emitter,
-                                          bool RelaxAll) {
-  return createMachOStreamer(Ctx, MAB, OS, Emitter, false);
+                                          MCCodeEmitter *Emitter, bool RelaxAll,
+                                          bool DWARFMustBeAtTheEnd) {
+  return createMachOStreamer(Ctx, MAB, OS, Emitter, false, DWARFMustBeAtTheEnd);
 }
 
 static MCInstPrinter *createARMMCInstPrinter(const Target &T,
diff --git a/test/CodeGen/ARM/darwin-section-order.ll b/test/CodeGen/ARM/darwin-section-order.ll
deleted file mode 100644 (file)
index 701028c..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-; RUN: llc < %s -mtriple=armv7-apple-darwin | FileCheck %s
-
-; CHECK: .section      __TEXT,__text,regular,pure_instructions
-; CHECK: .section      __TEXT,myprecious
-; CHECK: .section      __TEXT,__textcoal_nt,coalesced,pure_instructions
-; CHECK: .section      __TEXT,__const_coal,coalesced
-; CHECK: .section      __TEXT,__picsymbolstub4,symbol_stubs,none,16
-; CHECK: .section      __TEXT,__StaticInit,regular,pure_instructions
-
-
-define void @normal() nounwind readnone {
-; CHECK: .section      __TEXT,__text,regular,pure_instructions
-; CHECK: _normal:
-  ret void
-}
-
-define void @special() nounwind readnone section "__TEXT,myprecious" {
-; CHECK: .section      __TEXT,myprecious
-; CHECK: _special:
-  ret void
-}
index 23555b3d22c8e30cd0720a7a731a69ce7fed48ce..733ba4ba2d2c9c44d435c42bc9c30994e1adbfb4 100644 (file)
@@ -2,11 +2,6 @@
 ; RUN: llc -mtriple=thumbv7m-none-macho -O0 %s -o - -relocation-model=pic -disable-fp-elim | FileCheck %s
 ; RUN: llc -mtriple=thumbv7m-none-macho -filetype=obj %s -o /dev/null
 
-  ; Bare-metal should probably "declare" segments just like normal MachO
-; CHECK: __picsymbolstub4
-; CHECK: __StaticInit
-; CHECK: __text
-
 @var = external global i32
 
 define i32 @test_litpool() minsize {
diff --git a/test/DebugInfo/ARM/header.ll b/test/DebugInfo/ARM/header.ll
new file mode 100644 (file)
index 0000000..d9dd611
--- /dev/null
@@ -0,0 +1,30 @@
+; RUN: llc -mtriple armv7-apple-darwin < %s  | FileCheck %s
+
+; Test that we don't pollute the start of the file with debug sections.
+; This is particularly important on ARM MachO as a change in section order can
+; cause a change the relaxation of the instructions used.
+
+; CHECK:      .section        __TEXT,__text,regular,pure_instructions
+; CHECK-NEXT: .syntax unified
+; CHECK-NEXT: .globl  _f
+; CHECK-NEXT: .align  2
+; CHECK-NEXT: _f:                    @ @f
+
+; CHECK:  .section        __DWARF,__debug_str,regular,debug
+
+define void @f() {
+  ret void, !dbg !9
+}
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!7, !8}
+
+!0 = !MDCompileUnit(language: DW_LANG_C99, file: !1, producer: "foo", isOptimized: true, runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !2, subprograms: !3, globals: !2, imports: !2)
+!1 = !MDFile(filename: "/foo/test.c", directory: "/foo")
+!2 = !{}
+!3 = !{!4}
+!4 = !MDSubprogram(name: "f", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, function: void ()* @f, variables: !2)
+!5 = !MDSubroutineType(types: !6)
+!6 = !{null}
+!7 = !{i32 2, !"Dwarf Version", i32 4}
+!8 = !{i32 2, !"Debug Info Version", i32 3}
+!9 = !MDLocation(line: 1, column: 15, scope: !4)
diff --git a/test/DebugInfo/ARM/sectionorder.ll b/test/DebugInfo/ARM/sectionorder.ll
deleted file mode 100644 (file)
index e6e067a..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-; RUN: llc  -filetype=asm %s -o - | FileCheck %s
-
-; Verifies that the DWARF* sections come _after_ the __TEXT sections.
-; rdar://problem/15623193
-
-; CHECK: .section      __TEXT,__text,
-; CHECK-NOT: __DWARF,__debug
-; CHECK: .section      __TEXT,__cstring,cstring_literals
-target triple = "thumbv7-apple-ios"
-
-!llvm.module.flags = !{!3, !4}
-!llvm.dbg.cu = !{!0}
-
-!0 = !MDCompileUnit(language: DW_LANG_C99, producer: "LLVM", isOptimized: true, file: !5, enums: !1, retainedTypes: !1, subprograms: !1, globals: !1)
-!1 = !{}
-!3 = !{i32 2, !"Dwarf Version", i32 2}
-!4 = !{i32 1, !"Debug Info Version", i32 3}
-!5 = !MDFile(filename: "test.c", directory: "/Volumes/Data/radar/15623193")
index 4326be45137f0bc7b93731e238634a22fa6b501a..c9c05cd54acabc1e0782cb2724e8cd899d9f288f 100644 (file)
@@ -511,7 +511,8 @@ bool DwarfStreamer::init(Triple TheTriple, StringRef OutputFilename) {
     return error(Twine(OutputFilename) + ": " + EC.message(), Context);
 
   MS = TheTarget->createMCObjectStreamer(TheTriple, *MC, *MAB, *OutFile, MCE,
-                                         *MSTI, false);
+                                         *MSTI, false,
+                                         /*DWARFMustBeAtTheEnd*/ false);
   if (!MS)
     return error("no object streamer for target " + TripleName, Context);
 
index eb0df78c48d0943fe99ef361021e537151b4d5be..4f9b6fc99e3186bd1e6ae7439da7f5964612302a 100644 (file)
@@ -472,7 +472,8 @@ int main(int argc, char **argv) {
     MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
     MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU);
     Str.reset(TheTarget->createMCObjectStreamer(TheTriple, Ctx, *MAB, FOS, CE,
-                                                *STI, RelaxAll));
+                                                *STI, RelaxAll,
+                                                /*DWARFMustBeAtTheEnd*/ false));
     if (NoExecStack)
       Str->InitSections(true);
   }