[lld] wasm-ld: Preserve segment linking flags in --relocatable output (PR #210747)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 20 08:57:16 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lld

Author: Max Desiatov (MaxDesiatov)

<details>
<summary>Changes</summary>

`OutputSegment::addInputSegment` copied each input chunk's alignment but never its flags, so a relocatable link serialized `flags=0` for every data segment and dropped `RETAIN` and `STRINGS`. Losing `RETAIN` let the final default `--gc-sections` link discard runtime-registered sections such as Swift's `swift5_*` metadata, corrupting the program. This unions each input segment's flags into the output segment's `linkingFlags` and adds a `lld/test/wasm` test covering `RETAIN`, `STRINGS`, and flag accumulation across coalesced segments.

Resolves https://github.com/swiftlang/swift-package-manager/issues/10314.

---
Full diff: https://github.com/llvm/llvm-project/pull/210747.diff


2 Files Affected:

- (added) lld/test/wasm/relocatable-segment-flags.s (+39) 
- (modified) lld/wasm/OutputSegment.cpp (+4) 


``````````diff
diff --git a/lld/test/wasm/relocatable-segment-flags.s b/lld/test/wasm/relocatable-segment-flags.s
new file mode 100644
index 0000000000000..afed7b5ee18cb
--- /dev/null
+++ b/lld/test/wasm/relocatable-segment-flags.s
@@ -0,0 +1,39 @@
+# RUN: rm -rf %t && split-file %s %t
+# RUN: llvm-mc -filetype=obj --triple=wasm32-unknown-unknown -o %t/main.o %t/main.s
+# RUN: llvm-mc -filetype=obj --triple=wasm32-unknown-unknown -o %t/extra.o %t/extra.s
+# RUN: wasm-ld --relocatable -o %t/reloc.o %t/main.o %t/extra.o
+# RUN: obj2yaml %t/reloc.o | FileCheck %s
+
+# --relocatable must preserve per-segment linking flags (RETAIN, STRINGS). The plain
+# "retained" chunk in extra.s coalesces with the retained one in main.o, so RETAIN must
+# survive the flag union rather than be overwritten by the flag-less chunk.
+
+#--- main.s
+  .globl  _start
+_start:
+  .functype _start () -> ()
+  end_function
+
+  .section retained,"R",@
+  .asciz  "keep"
+
+  .section .rodata.str,"S",@
+  .asciz  "merge"
+
+  .section plain,"",@
+  .asciz  "drop"
+
+#--- extra.s
+  .section retained,"",@
+  .asciz  "more"
+
+# CHECK:      SegmentInfo:
+# CHECK:          Name:            .rodata.str
+# CHECK-NEXT:     Alignment:       0
+# CHECK-NEXT:     Flags:           [ STRINGS ]
+# CHECK:          Name:            retained
+# CHECK-NEXT:     Alignment:       0
+# CHECK-NEXT:     Flags:           [ RETAIN ]
+# CHECK:          Name:            plain
+# CHECK-NEXT:     Alignment:       0
+# CHECK-NEXT:     Flags:           [ ]
diff --git a/lld/wasm/OutputSegment.cpp b/lld/wasm/OutputSegment.cpp
index ea052e89dbb55..10fef48c90690 100644
--- a/lld/wasm/OutputSegment.cpp
+++ b/lld/wasm/OutputSegment.cpp
@@ -19,6 +19,10 @@ namespace lld::wasm {
 
 void OutputSegment::addInputSegment(InputChunk *inSeg) {
   alignment = std::max(alignment, inSeg->alignment);
+  // Carry input flags (RETAIN, STRINGS) into the relocatable SegmentInfo output;
+  // otherwise a relocatable link drops them and the downstream link loses RETAIN
+  // (segment GC'd) and STRINGS (string merge disabled).
+  linkingFlags |= inSeg->flags;
   inputSegments.push_back(inSeg);
   size = llvm::alignTo(size, 1ULL << inSeg->alignment);
   LLVM_DEBUG(dbgs() << "addInputSegment: " << inSeg->name << " oname=" << name

``````````

</details>


https://github.com/llvm/llvm-project/pull/210747


More information about the llvm-commits mailing list