diff --git a/lld/test/wasm/gc-imports.s b/lld/test/wasm/gc-imports.s --- a/lld/test/wasm/gc-imports.s +++ b/lld/test/wasm/gc-imports.s @@ -42,6 +42,11 @@ # CHECK-NEXT: Name: _start # CHECK-NEXT: - Index: 2 # CHECK-NEXT: Name: use_undef_global +# CHECK-NEXT: - Type: CUSTOM +# CHECK-NEXT: Name: target_features +# CHECK-NEXT: Features: +# CHECK-NEXT: - Prefix: USED +# CHECK-NEXT: Name: mutable-globals # CHECK-NEXT: ... # RUN: wasm-ld --no-gc-sections --allow-undefined \ @@ -84,4 +89,9 @@ # NO-GC-NEXT: Name: _start # NO-GC-NEXT: - Index: 5 # NO-GC-NEXT: Name: use_undef_global +# NO-GC-NEXT: - Type: CUSTOM +# NO-GC-NEXT: Name: target_features +# NO-GC-NEXT: Features: +# NO-GC-NEXT: - Prefix: USED +# NO-GC-NEXT: Name: mutable-globals # NO-GC-NEXT: ... diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -445,6 +445,27 @@ std::any_of(file->segments.begin(), file->segments.end(), isTLS); } + // If no object files explictly used mutable globals we still might need + // to include it due to linker-generated globals such as those use in the + // PIC ABI for importing and exported symbol offsets. + if (!config->relocatable && used.count("mutable-globals") == 0) { + for (Symbol *sym : symtab->getSymbols()) { + if (auto *global = dyn_cast(sym)) { + if (global->getGlobalType()->Mutable) { + if (!sym->isLive()) + continue; + if (!sym->isUsedInRegularObj) + continue; + if (sym->isUndefined() && sym->isWeak() && !config->relocatable) + continue; + if (sym->isUndefined() || sym->isExported()) { + used.insert({"mutable-globals", ""}); + } + } + } + } + } + if (inferFeatures) for (const auto &key : used.keys()) allowed.insert(std::string(key));