forked from OSchip/llvm-project
[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
This commit is contained in:
parent
d67def8704
commit
0a9756fc15
|
@ -0,0 +1,8 @@
|
|||
.globl _bar,_dynamic
|
||||
|
||||
.section .data,"",@
|
||||
_bar:
|
||||
.size _bar,4
|
||||
|
||||
_dynamic:
|
||||
.size _dynamic,4
|
|
@ -0,0 +1,9 @@
|
|||
.globl _bar,_static
|
||||
|
||||
.section .data,"",@
|
||||
_bar:
|
||||
.int32 42
|
||||
.size _bar,4
|
||||
|
||||
_static:
|
||||
.size _static,4
|
|
@ -0,0 +1,2 @@
|
|||
.section .bar,"",@
|
||||
.quad _bar
|
|
@ -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
|
|
@ -53,6 +53,7 @@ struct Configuration {
|
|||
bool stripAll;
|
||||
bool stripDebug;
|
||||
bool stackFirst;
|
||||
bool isStatic = false;
|
||||
bool trace;
|
||||
uint64_t globalBase;
|
||||
uint64_t initialMemory;
|
||||
|
|
|
@ -279,27 +279,58 @@ void LinkerDriver::addFile(StringRef path) {
|
|||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
for (StringRef dir : config->searchPaths) {
|
||||
if (Optional<std::string> s = findFile(dir, "lib" + name + ".a")) {
|
||||
addFile(*s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
error("unable to find library -l" + 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;
|
||||
|
|
|
@ -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">;
|
||||
|
|
Loading…
Reference in New Issue