Index: COFF/Driver.cpp =================================================================== --- COFF/Driver.cpp +++ COFF/Driver.cpp @@ -91,6 +91,18 @@ return (S.substr(0, S.rfind('.')) + E).str(); } +// Returns true if S matches /Filename.?\.o$/. +static bool isCrtBeginEnd(StringRef S, StringRef Filename) { + if (!S.endswith(".o")) + return false; + S = S.drop_back(2); + if (S.endswith(Filename)) + return true; + return !S.empty() && S.drop_back().endswith(Filename); +} + +static bool isCrtend(StringRef S) { return isCrtBeginEnd(S, "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 @@ -1407,11 +1419,18 @@ return false; }; + std::vector DeferredObjects; + // Create a list of input files. Files can be given as arguments // for /defaultlib option. - for (auto *Arg : Args.filtered(OPT_INPUT, OPT_wholearchive_file)) - if (Optional Path = findFile(Arg->getValue())) - enqueuePath(*Path, IsWholeArchive(*Path)); + for (auto *Arg : Args.filtered(OPT_INPUT, OPT_wholearchive_file)) { + if (Optional Path = findFile(Arg->getValue())) { + if (Config->MinGW && isCrtend(*Path)) + DeferredObjects.push_back(*Path); + else + enqueuePath(*Path, IsWholeArchive(*Path)); + } + } for (auto *Arg : Args.filtered(OPT_defaultlib)) if (Optional Path = findLib(Arg->getValue())) @@ -1628,6 +1647,12 @@ if (errorCount()) return; + // Add deferred object files (crtend.o). These are expected to cope with + // being linked last, not adding any new undefined symbols that need further + // iterations. + for (StringRef Path : DeferredObjects) + enqueuePath(Path, /* WholeArchive */ false); + // Do LTO by compiling bitcode input files to a set of native COFF files then // link those files. Symtab->addCombinedLTOObjects(); Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ 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: test/COFF/Inputs/eh_frame_terminator-crtend.s =================================================================== --- /dev/null +++ test/COFF/Inputs/eh_frame_terminator-crtend.s @@ -0,0 +1,3 @@ + .section .eh_frame,"dr" +__FRAME_END__: + .byte 3 Index: test/COFF/Inputs/eh_frame_terminator-otherfunc.s =================================================================== --- /dev/null +++ test/COFF/Inputs/eh_frame_terminator-otherfunc.s @@ -0,0 +1,7 @@ + .text + .globl otherfunc +otherfunc: + ret + + .section .eh_frame,"dr" + .byte 2 Index: test/COFF/eh_frame_terminator.s =================================================================== --- /dev/null +++ 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