[LLD] [COFF] Fix handling of comdat .drectve sections (#68116)
authorMartin Storsjö <martin@martin.st>
Wed, 4 Oct 2023 07:54:50 +0000 (10:54 +0300)
committerTobias Hieta <tobias@hieta.se>
Tue, 10 Oct 2023 06:43:27 +0000 (08:43 +0200)
This can happen when manually emitting strings into .drectve sections
with `__attribute__((section(".drectve")))`, which is a way to emulate
`#pragma comment(linker, "...")` for mingw compilers, without requiring
building with -fms-extensions.

Normally, this doesn't generate any comdat, but if compiled with
-fsanitize=address, this section does get turned into a comdat section.

This fixes #67261. This issue can be seen as a regression; a change in
the "lli" tool in 17.x triggers this case, if compiled with ASAN
enabled, triggering this unsupported corner case in LLD. With this
change, LLD can handle it.

(cherry picked from commit 503bc5f66111f7e4fc79972bb9bfec8bb5606bab)

lld/COFF/InputFiles.cpp
lld/test/COFF/comdat-drectve.s [new file with mode: 0644]

index 541837a..a7a08fb 100644 (file)
@@ -661,6 +661,8 @@ std::optional<Symbol *> ObjFile::createDefined(
     if (prevailing) {
       SectionChunk *c = readSection(sectionNumber, def, getName());
       sparseChunks[sectionNumber] = c;
+      if (!c)
+        return nullptr;
       c->sym = cast<DefinedRegular>(leader);
       c->selection = selection;
       cast<DefinedRegular>(leader)->data = &c->repl;
diff --git a/lld/test/COFF/comdat-drectve.s b/lld/test/COFF/comdat-drectve.s
new file mode 100644 (file)
index 0000000..6f96a87
--- /dev/null
@@ -0,0 +1,31 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj
+
+# RUN: lld-link %t.obj -out:%t.exe -debug:symtab -subsystem:console
+# RUN: llvm-readobj --coff-exports %t.exe | FileCheck %s
+
+# CHECK: Name: exportedFunc
+
+## This assembly snippet has been reduced from what Clang generates from
+## this C snippet, with -fsanitize=address. Normally, the .drectve
+## section would be a regular section - but when compiled with
+## -fsanitize=address, it becomes a comdat section.
+##
+# void exportedFunc(void) {}
+# void mainCRTStartup(void) {}
+# static __attribute__((section(".drectve"), used)) const char export_chkstk[] =
+#     "-export:exportedFunc";
+
+       .text
+       .globl  exportedFunc
+exportedFunc:
+       retq
+
+       .globl  mainCRTStartup
+mainCRTStartup:
+       retq
+
+       .section        .drectve,"dr",one_only,export_chkstk
+export_chkstk:
+       .asciz  "-export:exportedFunc"