[lld] r358394 - [COFF] Link crtend.o as the last object file

Martin Storsjo via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 15 03:57:45 PDT 2019


Author: mstorsjo
Date: Mon Apr 15 03:57:44 2019
New Revision: 358394

URL: http://llvm.org/viewvc/llvm-project?rev=358394&view=rev
Log:
[COFF] Link crtend.o as the last object file

When faced with command line options such as "crtbegin.o appmain.o
-lsomelib crtend.o", GNU ld pulls in all necessary object files from
somelib before proceeding to crtend.o.

LLD operates differently, only loading object files from any
referenced static libraries after processing all input object files.

This uses a similar hack as in the ELF linker. Here, it moves crtend.o
to the end of the vector of object files. This makes sure that
terminator chunks for sections such as .eh_frame gets ordered last,
fixing DWARF exception handling for libgcc and gcc's crtend.o.

Differential Revision: https://reviews.llvm.org/D60628

Added:
    lld/trunk/test/COFF/Inputs/eh_frame_terminator-crtend.s
    lld/trunk/test/COFF/Inputs/eh_frame_terminator-otherfunc.s
    lld/trunk/test/COFF/eh_frame_terminator.s
Modified:
    lld/trunk/COFF/Driver.cpp
    lld/trunk/docs/ReleaseNotes.rst

Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=358394&r1=358393&r2=358394&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Mon Apr 15 03:57:44 2019
@@ -91,6 +91,16 @@ static std::string getOutputPath(StringR
   return (S.substr(0, S.rfind('.')) + E).str();
 }
 
+// Returns true if S matches /crtend.?\.o$/.
+static bool isCrtend(StringRef S) {
+  if (!S.endswith(".o"))
+    return false;
+  S = S.drop_back(2);
+  if (S.endswith("crtend"))
+    return true;
+  return !S.empty() && S.drop_back().endswith("crtend");
+}
+
 // ErrorOr is not default constructible, so it cannot be used as the type
 // parameter of a future.
 // FIXME: We could open the file in createFutureForFile and avoid needing to
@@ -1665,11 +1675,28 @@ void LinkerDriver::link(ArrayRef<const c
       return;
   }
 
-  // In MinGW, all symbols are automatically exported if no symbols
-  // are chosen to be exported.
-  if (Config->MinGW)
+  if (Config->MinGW) {
+    // In MinGW, all symbols are automatically exported if no symbols
+    // are chosen to be exported.
     maybeExportMinGWSymbols(Args);
 
+    // Make sure the crtend.o object is the last object file. This object
+    // file can contain terminating section chunks that need to be placed
+    // last. GNU ld processes files and static libraries explicitly in the
+    // order provided on the command line, while lld will pull in needed
+    // files from static libraries only after the last object file on the
+    // command line.
+    for (auto I = ObjFile::Instances.begin(), E = ObjFile::Instances.end();
+         I != E; I++) {
+      ObjFile *File = *I;
+      if (isCrtend(File->getName())) {
+        ObjFile::Instances.erase(I);
+        ObjFile::Instances.push_back(File);
+        break;
+      }
+    }
+  }
+
   // Windows specific -- when we are creating a .dll file, we also
   // need to create a .lib file.
   if (!Config->Exports.empty() || Config->DLL) {

Modified: lld/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/docs/ReleaseNotes.rst?rev=358394&r1=358393&r2=358394&view=diff
==============================================================================
--- lld/trunk/docs/ReleaseNotes.rst (original)
+++ lld/trunk/docs/ReleaseNotes.rst Mon Apr 15 03:57:44 2019
@@ -37,7 +37,9 @@ COFF Improvements
 MinGW Improvements
 ------------------
 
-* ...
+* lld now correctly links crtend.o as the last object file, handling
+  terminators for the sections such as .eh_frame properly, fixing
+  DWARF exception handling with libgcc and gcc's crtend.o.
 
 MachO Improvements
 ------------------

Added: lld/trunk/test/COFF/Inputs/eh_frame_terminator-crtend.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/Inputs/eh_frame_terminator-crtend.s?rev=358394&view=auto
==============================================================================
--- lld/trunk/test/COFF/Inputs/eh_frame_terminator-crtend.s (added)
+++ lld/trunk/test/COFF/Inputs/eh_frame_terminator-crtend.s Mon Apr 15 03:57:44 2019
@@ -0,0 +1,3 @@
+    .section .eh_frame,"dr"
+__FRAME_END__:
+    .byte 3

Added: lld/trunk/test/COFF/Inputs/eh_frame_terminator-otherfunc.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/Inputs/eh_frame_terminator-otherfunc.s?rev=358394&view=auto
==============================================================================
--- lld/trunk/test/COFF/Inputs/eh_frame_terminator-otherfunc.s (added)
+++ lld/trunk/test/COFF/Inputs/eh_frame_terminator-otherfunc.s Mon Apr 15 03:57:44 2019
@@ -0,0 +1,7 @@
+    .text
+    .globl otherfunc
+otherfunc:
+    ret
+
+    .section .eh_frame,"dr"
+    .byte 2

Added: lld/trunk/test/COFF/eh_frame_terminator.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/eh_frame_terminator.s?rev=358394&view=auto
==============================================================================
--- lld/trunk/test/COFF/eh_frame_terminator.s (added)
+++ lld/trunk/test/COFF/eh_frame_terminator.s Mon Apr 15 03:57:44 2019
@@ -0,0 +1,26 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-windows-gnu %s -o %t.main.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-windows-gnu \
+// RUN:   %p/Inputs/eh_frame_terminator-otherfunc.s -o %t.otherfunc.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-windows-gnu \
+// RUN:   %p/Inputs/eh_frame_terminator-crtend.s -o %t.crtend.o
+// RUN: rm -f %t.otherfunc.lib
+// RUN: llvm-ar rcs %t.otherfunc.lib %t.otherfunc.o
+// RUN: lld-link -lldmingw %t.main.o %t.otherfunc.lib %t.crtend.o -out:%t.exe
+// RUN: llvm-objdump -s %t.exe | FileCheck %s
+
+    .text
+    .globl main
+main:
+    call otherfunc
+    ret
+
+    .globl mainCRTStartup
+mainCRTStartup:
+    call main
+
+    .section .eh_frame,"dr"
+    .byte 1
+
+// CHECK: Contents of section .eh_fram:
+// CHECK-NEXT: 140003000 010203




More information about the llvm-commits mailing list