[lld] 0a9756f - [lld][WebAssemlby] Improve support for -L / -l and add testing
Sam Clegg via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 3 17:02:00 PDT 2022
Author: Sam Clegg
Date: 2022-10-03T16:53:30-07:00
New Revision: 0a9756fc15c57dc94146e65d251d7a3d941ae78a
URL: https://github.com/llvm/llvm-project/commit/0a9756fc15c57dc94146e65d251d7a3d941ae78a
DIFF: https://github.com/llvm/llvm-project/commit/0a9756fc15c57dc94146e65d251d7a3d941ae78a.diff
LOG: [lld][WebAssemlby] Improve support for -L / -l and add testing
- Add support -Bdynamic/-Bstatic and their aliases
- Add support for `--library` and `--library-path` long form args
- Add test based on test/ELF/libsearch.s
- In `-Bdynamic` mode search for `.so` files in preference to `.a`.
- Unlike ELF continue to default to static mode until `-pie` or
`-shared` are used.
Differential Revision: https://reviews.llvm.org/D135087
Added:
lld/test/wasm/Inputs/libsearch-dyn.s
lld/test/wasm/Inputs/libsearch-st.s
lld/test/wasm/Inputs/use-bar.s
lld/test/wasm/libsearch.s
Modified:
lld/wasm/Config.h
lld/wasm/Driver.cpp
lld/wasm/Options.td
Removed:
################################################################################
diff --git a/lld/test/wasm/Inputs/libsearch-dyn.s b/lld/test/wasm/Inputs/libsearch-dyn.s
new file mode 100644
index 000000000000..bb59580b830f
--- /dev/null
+++ b/lld/test/wasm/Inputs/libsearch-dyn.s
@@ -0,0 +1,8 @@
+.globl _bar,_dynamic
+
+.section .data,"",@
+_bar:
+.size _bar,4
+
+_dynamic:
+.size _dynamic,4
diff --git a/lld/test/wasm/Inputs/libsearch-st.s b/lld/test/wasm/Inputs/libsearch-st.s
new file mode 100644
index 000000000000..dc5d89b406af
--- /dev/null
+++ b/lld/test/wasm/Inputs/libsearch-st.s
@@ -0,0 +1,9 @@
+.globl _bar,_static
+
+.section .data,"",@
+_bar:
+.int32 42
+.size _bar,4
+
+_static:
+.size _static,4
diff --git a/lld/test/wasm/Inputs/use-bar.s b/lld/test/wasm/Inputs/use-bar.s
new file mode 100644
index 000000000000..4ba20a061466
--- /dev/null
+++ b/lld/test/wasm/Inputs/use-bar.s
@@ -0,0 +1,2 @@
+.section .bar,"",@
+ .quad _bar
diff --git a/lld/test/wasm/libsearch.s b/lld/test/wasm/libsearch.s
new file mode 100644
index 000000000000..23336510748c
--- /dev/null
+++ b/lld/test/wasm/libsearch.s
@@ -0,0 +1,99 @@
+// Based on lld/test/ELF/libsearch.s
+
+// RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown \
+// RUN: %p/Inputs/libsearch-dyn.s -o %tdyn.o
+// RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown \
+// RUN: %p/Inputs/libsearch-st.s -o %tst.o
+// RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown \
+// RUN: %p/Inputs/use-bar.s -o %tbar.o
+// RUN: mkdir -p %t.dir
+// RUN: wasm-ld -shared --experimental-pic %tdyn.o -o %t.dir/libls.so
+// RUN: cp -f %t.dir/libls.so %t.dir/libls2.so
+// RUN: rm -f %t.dir/libls.a
+// RUN: llvm-ar rcs %t.dir/libls.a %tst.o
+
+// Should fail if no library specified
+// RUN: not wasm-ld -l 2>&1 \
+// RUN: | FileCheck --check-prefix=NOLIBRARY %s
+// NOLIBRARY: -l: missing argument
+
+// Should link normally, because _bar is not used
+// RUN: wasm-ld -o %t3 %t.o
+// Should not link because of undefined symbol _bar
+// RUN: not wasm-ld --no-gc-sections -o /dev/null %t.o %tbar.o 2>&1 \
+// RUN: | FileCheck --check-prefix=UNDEFINED %s
+// UNDEFINED: wasm-ld: error: {{.*}}: undefined symbol: _bar
+
+// Should fail if cannot find specified library (without -L switch)
+// RUN: not wasm-ld -o /dev/null %t.o -lls 2>&1 \
+// RUN: | FileCheck --check-prefix=NOLIB %s
+// NOLIB: unable to find library -lls
+
+// Should use explicitly specified static library
+// Also ensure that we accept -L <arg>
+// RUN: wasm-ld --emit-relocs --no-gc-sections -o %t3 %t.o -L %t.dir -l:libls.a
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s
+// STATIC: Symbols [
+// STATIC: Name: _static
+
+// Should use explicitly specified dynamic library
+// RUN: wasm-ld -pie --experimental-pic --emit-relocs --no-gc-sections -o %t3 %t.o -L%t.dir -l:libls.so
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=DYNAMIC %s
+// DYNAMIC: Symbols [
+// DYNAMIC-NOT: Name: _static
+
+// Should prefer static to dynamic when linking regular executable.
+// RUN: wasm-ld --emit-relocs --no-gc-sections -o %t3 %t.o -L%t.dir -lls
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s
+
+// Should prefer dynamic when linking PIE.
+// RUN: wasm-ld -pie --experimental-pic --emit-relocs --no-gc-sections -o %t3 %t.o -L%t.dir -lls
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=DYNAMIC %s
+
+// Check for library search order
+// RUN: mkdir -p %t.dir2
+// RUN: cp %t.dir/libls.a %t.dir2
+// RUN: wasm-ld -pie --experimental-pic --emit-relocs --no-gc-sections -o %t3 %t.o -L%t.dir2 -L%t.dir -lls
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s
+
+// -L can be placed after -l
+// RUN: wasm-ld -o %t3 %t.o -lls -L%t.dir
+
+// Check long forms as well
+// RUN: wasm-ld --emit-relocs --no-gc-sections -o %t3 %t.o --library-path=%t.dir --library=ls
+// RUN: wasm-ld --emit-relocs --no-gc-sections -o %t3 %t.o --library-path %t.dir --library ls
+
+// Should not search for dynamic libraries if -Bstatic is specified
+// RUN: wasm-ld -pie --experimental-pic --emit-relocs --no-gc-sections -o %t3 %t.o -L%t.dir -Bstatic -lls
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s
+// RUN: not wasm-ld -pie --experimental-pic --emit-relocs --no-gc-sections -o /dev/null %t.o -L%t.dir -Bstatic -lls2 2>&1 \
+// RUN: | FileCheck --check-prefix=NOLIB2 %s
+// NOLIB2: unable to find library -lls2
+
+// -Bdynamic should restore default behaviour
+// RUN: wasm-ld -pie --experimental-pic --emit-relocs --no-gc-sections -o %t3 %t.o -L%t.dir -Bstatic -Bdynamic -lls
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=DYNAMIC %s
+
+// -Bstatic and -Bdynamic should affect only libraries which follow them
+// RUN: wasm-ld -pie --experimental-pic --emit-relocs --no-gc-sections -o %t3 %t.o -L%t.dir -lls -Bstatic -Bdynamic
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=DYNAMIC %s
+// RUN: wasm-ld -pie --experimental-pic --emit-relocs --no-gc-sections -o %t3 %t.o -L%t.dir -Bstatic -lls -Bdynamic
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s
+
+// Check aliases as well
+// RUN: wasm-ld -pie --experimental-pic --emit-relocs --no-gc-sections -o %t3 %t.o -L%t.dir -dn -lls
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s
+// RUN: wasm-ld -pie --experimental-pic --emit-relocs --no-gc-sections -o %t3 %t.o -L%t.dir -non_shared -lls
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s
+// RUN: wasm-ld -pie --experimental-pic --emit-relocs --no-gc-sections -o %t3 %t.o -L%t.dir -static -lls
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s
+// RUN: wasm-ld -pie --experimental-pic --emit-relocs --no-gc-sections -o %t3 %t.o -L%t.dir -Bstatic -dy -lls
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=DYNAMIC %s
+// RUN: wasm-ld -pie --experimental-pic --emit-relocs --no-gc-sections -o %t3 %t.o -L%t.dir -Bstatic -call_shared -lls
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=DYNAMIC %s
+
+.globl _start, _bar
+_start:
+ .functype _start () -> ()
+ end_function
diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h
index 2c79e4196338..fbc195e974f0 100644
--- a/lld/wasm/Config.h
+++ b/lld/wasm/Config.h
@@ -53,6 +53,7 @@ struct Configuration {
bool stripAll;
bool stripDebug;
bool stackFirst;
+ bool isStatic = false;
bool trace;
uint64_t globalBase;
uint64_t initialMemory;
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index 27943198c93f..e6b2239e7a15 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -279,27 +279,58 @@ void LinkerDriver::addFile(StringRef path) {
}
}
-// Add a given library by searching it from input search paths.
-void LinkerDriver::addLibrary(StringRef name) {
+static Optional<std::string> findFromSearchPaths(StringRef path) {
+ for (StringRef dir : config->searchPaths)
+ if (Optional<std::string> s = findFile(dir, path))
+ return s;
+ return None;
+}
+
+// This is for -l<basename>. We'll look for lib<basename>.a from
+// search paths.
+static Optional<std::string> searchLibraryBaseName(StringRef name) {
for (StringRef dir : config->searchPaths) {
- if (Optional<std::string> s = findFile(dir, "lib" + name + ".a")) {
- addFile(*s);
- return;
- }
+ // Currently we don't enable dyanmic linking at all unless -shared or -pie
+ // are used, so don't even look for .so files in that case..
+ if (config->isPic && !config->isStatic)
+ if (Optional<std::string> s = findFile(dir, "lib" + name + ".so"))
+ return s;
+ if (Optional<std::string> s = findFile(dir, "lib" + name + ".a"))
+ return s;
}
+ return None;
+}
- error("unable to find library -l" + name);
+// This is for -l<namespec>.
+static Optional<std::string> searchLibrary(StringRef name) {
+ if (name.startswith(":"))
+ return findFromSearchPaths(name.substr(1));
+ return searchLibraryBaseName(name);
+}
+
+// Add a given library by searching it from input search paths.
+void LinkerDriver::addLibrary(StringRef name) {
+ if (Optional<std::string> path = searchLibrary(name))
+ addFile(saver().save(*path));
+ else
+ error("unable to find library -l" + name, ErrorTag::LibNotFound, {name});
}
void LinkerDriver::createFiles(opt::InputArgList &args) {
for (auto *arg : args) {
switch (arg->getOption().getID()) {
- case OPT_l:
+ case OPT_library:
addLibrary(arg->getValue());
break;
case OPT_INPUT:
addFile(arg->getValue());
break;
+ case OPT_Bstatic:
+ config->isStatic = true;
+ break;
+ case OPT_Bdynamic:
+ config->isStatic = false;
+ break;
case OPT_whole_archive:
inWholeArchive = true;
break;
@@ -382,7 +413,7 @@ static void readConfigs(opt::InputArgList &args) {
config->printGcSections =
args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false);
config->saveTemps = args.hasArg(OPT_save_temps);
- config->searchPaths = args::getStrings(args, OPT_L);
+ config->searchPaths = args::getStrings(args, OPT_library_path);
config->shared = args.hasArg(OPT_shared);
config->stripAll = args.hasArg(OPT_strip_all);
config->stripDebug = args.hasArg(OPT_strip_debug);
@@ -898,12 +929,12 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
cl::ParseCommandLineOptions(v.size(), v.data());
readConfigs(args);
+ setConfigs();
createFiles(args);
if (errorCount())
return;
- setConfigs();
checkOptions(args);
if (errorCount())
return;
diff --git a/lld/wasm/Options.td b/lld/wasm/Options.td
index b0c4a811e85a..7a6192433ec8 100644
--- a/lld/wasm/Options.td
+++ b/lld/wasm/Options.td
@@ -38,6 +38,10 @@ multiclass B<string name, string help1, string help2> {
// The following flags are shared with the ELF linker
def Bsymbolic: F<"Bsymbolic">, HelpText<"Bind defined symbols locally">;
+def Bdynamic: F<"Bdynamic">, HelpText<"Link against shared libraries (default)">;
+
+def Bstatic: F<"Bstatic">, HelpText<"Do not link against shared libraries">;
+
defm color_diagnostics: B<"color-diagnostics",
"Alias for --color-diagnostics=always",
"Alias for --color-diagnostics=never">;
@@ -80,10 +84,10 @@ defm merge_data_segments: BB<"merge-data-segments",
def help: F<"help">, HelpText<"Print option help">;
-def l: JoinedOrSeparate<["-"], "l">, MetaVarName<"<libName>">,
+def library: JoinedOrSeparate<["-"], "l">, MetaVarName<"<libName>">,
HelpText<"Root name of library to use">;
-def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">,
+def library_path: JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">,
HelpText<"Add a directory to the library search path">;
def m: JoinedOrSeparate<["-"], "m">, HelpText<"Set target emulation">;
@@ -219,8 +223,17 @@ def features: CommaJoined<["--", "-"], "features=">,
// Aliases
def: JoinedOrSeparate<["-"], "e">, Alias<entry>;
def: J<"entry=">, Alias<entry>;
+def: F<"call_shared">, Alias<Bdynamic>, HelpText<"Alias for --Bdynamic">;
+def: F<"dy">, Alias<Bdynamic>, HelpText<"Alias for --Bdynamic">;
+def: F<"dn">, Alias<Bstatic>, HelpText<"Alias for --Bstatic">;
+def: F<"non_shared">, Alias<Bstatic>, HelpText<"Alias for --Bstatic">;
+def: F<"static">, Alias<Bstatic>, HelpText<"Alias for --Bstatic">;
def: Flag<["-"], "E">, Alias<export_dynamic>, HelpText<"Alias for --export-dynamic">;
def: Flag<["-"], "i">, Alias<initial_memory>;
+def: Separate<["--", "-"], "library">, Alias<library>;
+def: Joined<["--", "-"], "library=">, Alias<library>;
+def: Separate<["--", "-"], "library-path">, Alias<library_path>;
+def: Joined<["--", "-"], "library-path=">, Alias<library_path>;
def: Flag<["-"], "M">, Alias<print_map>, HelpText<"Alias for --print-map">;
def: Flag<["-"], "r">, Alias<relocatable>;
def: Flag<["-"], "s">, Alias<strip_all>, HelpText<"Alias for --strip-all">;
More information about the llvm-commits
mailing list