Index: lld/trunk/COFF/Driver.cpp =================================================================== --- lld/trunk/COFF/Driver.cpp +++ lld/trunk/COFF/Driver.cpp @@ -91,6 +91,16 @@ 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 @@ 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) { Index: lld/trunk/docs/ReleaseNotes.rst =================================================================== --- lld/trunk/docs/ReleaseNotes.rst +++ lld/trunk/docs/ReleaseNotes.rst @@ -37,7 +37,9 @@ 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 ------------------ Index: lld/trunk/test/COFF/Inputs/eh_frame_terminator-crtend.s =================================================================== --- lld/trunk/test/COFF/Inputs/eh_frame_terminator-crtend.s +++ lld/trunk/test/COFF/Inputs/eh_frame_terminator-crtend.s @@ -0,0 +1,3 @@ + .section .eh_frame,"dr" +__FRAME_END__: + .byte 3 Index: lld/trunk/test/COFF/Inputs/eh_frame_terminator-otherfunc.s =================================================================== --- lld/trunk/test/COFF/Inputs/eh_frame_terminator-otherfunc.s +++ lld/trunk/test/COFF/Inputs/eh_frame_terminator-otherfunc.s @@ -0,0 +1,7 @@ + .text + .globl otherfunc +otherfunc: + ret + + .section .eh_frame,"dr" + .byte 2 Index: lld/trunk/test/COFF/eh_frame_terminator.s =================================================================== --- lld/trunk/test/COFF/eh_frame_terminator.s +++ lld/trunk/test/COFF/eh_frame_terminator.s @@ -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