diff --git a/lld/test/wasm/driver.s b/lld/test/wasm/driver.s --- a/lld/test/wasm/driver.s +++ b/lld/test/wasm/driver.s @@ -40,3 +40,6 @@ ## stack-size without an = is also an error # RUN: not wasm-ld %t.o -z stack-size 2>&1 | FileCheck -check-prefix=ERR11 %s # ERR11: unknown -z value: stack-size + +# RUN: not wasm-ld %t.o --require-defined=foo -o /dev/null 2>&1 | FileCheck -check-prefix=REQUIRE-DEFINED %s +# REQUIRE-DEFINED: wasm-ld: error: required symbol `foo` not defined diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h --- a/lld/wasm/Config.h +++ b/lld/wasm/Config.h @@ -72,6 +72,7 @@ llvm::StringSet<> allowUndefinedSymbols; llvm::StringSet<> exportedSymbols; std::vector requiredExports; + std::vector requireDefined; std::vector searchPaths; llvm::CachePruningPolicy thinLTOCachePolicy; llvm::Optional> features; diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -902,6 +902,9 @@ for (auto *arg : args.filtered(OPT_export_if_defined)) config->exportedSymbols.insert(arg->getValue()); + for (auto *arg : args.filtered(OPT_require_defined)) + config->requireDefined.push_back(arg->getValue()); + for (auto *arg : args.filtered(OPT_export)) { config->exportedSymbols.insert(arg->getValue()); config->requiredExports.push_back(arg->getValue()); diff --git a/lld/wasm/Options.td b/lld/wasm/Options.td --- a/lld/wasm/Options.td +++ b/lld/wasm/Options.td @@ -35,6 +35,9 @@ def no_ # NAME: Flag<["--", "-"], "no-" # name>, HelpText; } +defm require_defined: Eq<"require-defined", + "Force symbol to be added to symbol table as an undefined one">; + // The following flags are shared with the ELF linker def Bsymbolic: F<"Bsymbolic">, HelpText<"Bind defined symbols locally">; diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -1585,6 +1585,13 @@ // Delay reporting error about explicit exports until after // addStartStopSymbols which can create optional symbols. + for (auto &name : config->requireDefined) { + Symbol *sym = symtab->find(name); + if (!sym || !sym->isDefined()) { + error(Twine("required symbol `") + name + "` not defined"); + } + } + for (auto &name : config->requiredExports) { Symbol *sym = symtab->find(name); if (!sym || !sym->isDefined()) {