From 7e0768329ca347e37c7bdb0da16b51cb3e7b7d8b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Martin=20Storsj=C3=B6?= Date: Sun, 9 May 2021 23:27:35 +0300 Subject: [PATCH] [LLD] [COFF] Fix including the personality function for DWARF EH when linking with --gc-sections Since c579a5b1d92a9bc2046d00ee2d427832e0f5ddec we don't traverse .eh_frame when doing GC. But the exception handling personality function needs to be included, and is only referenced from within .eh_frame. Differential Revision: https://reviews.llvm.org/D102138 --- lld/COFF/Driver.cpp | 19 ++++++++++++++++++- lld/test/COFF/gc-dwarf-eh.s | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 lld/test/COFF/gc-dwarf-eh.s diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index e2374b5..029148c 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -2226,8 +2226,25 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { config->printSymbolOrder = arg->getValue(); // Identify unreferenced COMDAT sections. - if (config->doGC) + if (config->doGC) { + if (config->mingw) { + // markLive doesn't traverse .eh_frame, but the personality function is + // only reached that way. The proper solution would be to parse and + // traverse the .eh_frame section, like the ELF linker does. + // For now, just manually try to retain the known possible personality + // functions. This doesn't bring in more object files, but only marks + // functions that already have been included to be retained. + for (const char *n : {"__gxx_personality_v0", "__gcc_personality_v0"}) { + Defined *d = dyn_cast_or_null(symtab->findUnderscore(n)); + if (d && !d->isGCRoot) { + d->isGCRoot = true; + config->gcroot.push_back(d); + } + } + } + markLive(symtab->getChunks()); + } // Needs to happen after the last call to addFile(). convertResources(); diff --git a/lld/test/COFF/gc-dwarf-eh.s b/lld/test/COFF/gc-dwarf-eh.s new file mode 100644 index 0000000..757aa67 --- /dev/null +++ b/lld/test/COFF/gc-dwarf-eh.s @@ -0,0 +1,36 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -triple=i686-windows-gnu %s -filetype=obj -o %t.obj +# RUN: lld-link -lldmingw -lldmap:%t.map -out:%t.exe -opt:ref -entry:main %t.obj -verbose 2>&1 | FileCheck %s +# RUN: FileCheck %s --check-prefix=MAP --input-file=%t.map + +# CHECK: Discarded _unused + +# MAP: In Symbol +# MAP: gc-dwarf-eh.s.tmp.obj:(.text) +# MAP: {{ ___gxx_personality_v0$}} + + .def _main; .scl 2; .type 32; .endef + .section .text,"xr",one_only,_main + .globl _main + .cfi_startproc + .cfi_personality 0, ___gxx_personality_v0 +_main: + xorl %eax, %eax + ret + .cfi_endproc + + .def ___gxx_personality_v0; .scl 2; .type 32; .endef + .section .text,"xr",one_only,___gxx_personality_v0 + .globl ___gxx_personality_v0 +___gxx_personality_v0: + ret + + .def _unused; .scl 2; .type 32; .endef + .section .text,"xr",one_only,_unused + .globl _unused + .cfi_startproc + .cfi_personality 0, ___gxx_personality_v0 +_unused: + ret + .cfi_endproc -- 2.7.4