[LLD] [COFF] Fix including the personality function for DWARF EH when linking with...
authorMartin Storsjö <martin@martin.st>
Sun, 9 May 2021 20:27:35 +0000 (23:27 +0300)
committerMartin Storsjö <martin@martin.st>
Wed, 12 May 2021 19:23:01 +0000 (22:23 +0300)
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
lld/test/COFF/gc-dwarf-eh.s [new file with mode: 0644]

index e2374b5..029148c 100644 (file)
@@ -2226,8 +2226,25 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> 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<Defined>(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 (file)
index 0000000..757aa67
--- /dev/null
@@ -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