[lld] Keep full library path in DT_NEEDED.

Fixes PR32572.

When
    (a) a library has no soname
and (b) library is given on the command line with path (and not through -L/-l flags)
DT_NEEDED entry for such library keeps the path as given.

This behavior is consistent with gold and bfd, and is used in compiler-rt test suite.

This is a second attempt after r300007 got reverted. This time relro-omagic test is
changed in a way to avoid hardcoding the path to the test directory in the objdump'd
binary.

llvm-svn: 300011
This commit is contained in:
Evgeniy Stepanov 2017-04-12 00:13:48 +00:00
parent 13c8daf57a
commit a76349bffe
8 changed files with 54 additions and 13 deletions

View File

@ -153,7 +153,7 @@ LinkerDriver::getArchiveMembers(MemoryBufferRef MB) {
// Opens and parses a file. Path has to be resolved already. // Opens and parses a file. Path has to be resolved already.
// Newly created memory buffers are owned by this driver. // Newly created memory buffers are owned by this driver.
void LinkerDriver::addFile(StringRef Path) { void LinkerDriver::addFile(StringRef Path, bool WithLOption) {
using namespace sys::fs; using namespace sys::fs;
Optional<MemoryBufferRef> Buffer = readFile(Path); Optional<MemoryBufferRef> Buffer = readFile(Path);
@ -184,6 +184,11 @@ void LinkerDriver::addFile(StringRef Path) {
return; return;
} }
Files.push_back(createSharedFile(MBRef)); Files.push_back(createSharedFile(MBRef));
// If the library is found at an explicitly given path use the entire path
// as he default soname. Such libraries should not require RPATH or
// LD_LIBRARY_PATH to run.
Files.back()->DefaultSoName =
WithLOption ? sys::path::filename(Path) : Path;
return; return;
default: default:
if (InLib) if (InLib)
@ -196,7 +201,7 @@ void LinkerDriver::addFile(StringRef Path) {
// Add a given library by searching it from input search paths. // Add a given library by searching it from input search paths.
void LinkerDriver::addLibrary(StringRef Name) { void LinkerDriver::addLibrary(StringRef Name) {
if (Optional<std::string> Path = searchLibrary(Name)) if (Optional<std::string> Path = searchLibrary(Name))
addFile(*Path); addFile(*Path, /*WithLOption=*/true);
else else
error("unable to find library -l" + Name); error("unable to find library -l" + Name);
} }
@ -762,7 +767,7 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) {
addLibrary(Arg->getValue()); addLibrary(Arg->getValue());
break; break;
case OPT_INPUT: case OPT_INPUT:
addFile(Arg->getValue()); addFile(Arg->getValue(), /*WithLOption=*/false);
break; break;
case OPT_alias_script_T: case OPT_alias_script_T:
case OPT_script: case OPT_script:

View File

@ -27,7 +27,7 @@ extern class LinkerDriver *Driver;
class LinkerDriver { class LinkerDriver {
public: public:
void main(ArrayRef<const char *> Args, bool CanExitEarly); void main(ArrayRef<const char *> Args, bool CanExitEarly);
void addFile(StringRef Path); void addFile(StringRef Path, bool WithLOption);
void addLibrary(StringRef Name); void addLibrary(StringRef Name);
private: private:

View File

@ -661,7 +661,7 @@ template <class ELFT> void SharedFile<ELFT>::parseSoName() {
// DSOs are identified by soname, and they usually contain // DSOs are identified by soname, and they usually contain
// DT_SONAME tag in their header. But if they are missing, // DT_SONAME tag in their header. But if they are missing,
// filenames are used as default sonames. // filenames are used as default sonames.
SoName = sys::path::filename(this->getName()); SoName = this->DefaultSoName;
if (!DynamicSec) if (!DynamicSec)
return; return;

View File

@ -93,6 +93,10 @@ public:
uint16_t EMachine = llvm::ELF::EM_NONE; uint16_t EMachine = llvm::ELF::EM_NONE;
uint8_t OSABI = 0; uint8_t OSABI = 0;
// For SharedKind inputs, the string to use in DT_NEEDED when the library
// has no soname.
std::string DefaultSoName;
// Cache for toString(). Only toString() should use this member. // Cache for toString(). Only toString() should use this member.
mutable std::string ToStringCache; mutable std::string ToStringCache;

View File

@ -243,25 +243,26 @@ void ScriptParser::addFile(StringRef S) {
SmallString<128> PathData; SmallString<128> PathData;
StringRef Path = (Config->Sysroot + S).toStringRef(PathData); StringRef Path = (Config->Sysroot + S).toStringRef(PathData);
if (sys::fs::exists(Path)) { if (sys::fs::exists(Path)) {
Driver->addFile(Saver.save(Path)); Driver->addFile(Saver.save(Path), /*WithLOption=*/false);
return; return;
} }
} }
if (sys::path::is_absolute(S)) { if (sys::path::is_absolute(S)) {
Driver->addFile(S); Driver->addFile(S, /*WithLOption=*/false);
} else if (S.startswith("=")) { } else if (S.startswith("=")) {
if (Config->Sysroot.empty()) if (Config->Sysroot.empty())
Driver->addFile(S.substr(1)); Driver->addFile(S.substr(1), /*WithLOption=*/false);
else else
Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1))); Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1)),
/*WithLOption=*/false);
} else if (S.startswith("-l")) { } else if (S.startswith("-l")) {
Driver->addLibrary(S.substr(2)); Driver->addLibrary(S.substr(2));
} else if (sys::fs::exists(S)) { } else if (sys::fs::exists(S)) {
Driver->addFile(S); Driver->addFile(S, /*WithLOption=*/false);
} else { } else {
if (Optional<std::string> Path = findFromSearchPaths(S)) if (Optional<std::string> Path = findFromSearchPaths(S))
Driver->addFile(Saver.save(*Path)); Driver->addFile(Saver.save(*Path), /*WithLOption=*/true);
else else
setError("unable to find " + S); setError("unable to find " + S);
} }

View File

@ -16,7 +16,7 @@
# CHECK-NEXT: Other: 0 # CHECK-NEXT: Other: 0
# CHECK-NEXT: Section: Undefined # CHECK-NEXT: Section: Undefined
# CHECK: NEEDED SharedLibrary (as-needed-no-reloc{{.*}}2.so) # CHECK: NEEDED SharedLibrary ({{.*}}as-needed-no-reloc{{.*}}2.so)
.globl _start .globl _start
_start: _start:

31
lld/test/ELF/no-soname.s Normal file
View File

@ -0,0 +1,31 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
// RUN: mkdir -p %T/no-soname
// RUN: ld.lld %t.o -shared -o %T/no-soname/libfoo.so
// RUN: ld.lld %t.o %T/no-soname/libfoo.so -o %t
// RUN: llvm-readobj --dynamic-table %t | FileCheck %s
// CHECK: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}/no-soname/libfoo.so)
// CHECK-NOT: NEEDED
// RUN: ld.lld %t.o %T/no-soname/../no-soname/libfoo.so -o %t
// RUN: llvm-readobj --dynamic-table %t | FileCheck %s --check-prefix=CHECK2
// CHECK2: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}/no-soname/../no-soname/libfoo.so)
// CHECK2-NOT: NEEDED
// RUN: ld.lld %t.o -L%T/no-soname/../no-soname -lfoo -o %t
// RUN: llvm-readobj --dynamic-table %t | FileCheck %s --check-prefix=CHECK3
// CHECK3: 0x0000000000000001 NEEDED SharedLibrary (libfoo.so)
// CHECK3-NOT: NEEDED
// RUN: ld.lld %t.o -shared -soname libbar.so -o %T/no-soname/libbar.so
// RUN: ld.lld %t.o %T/no-soname/libbar.so -o %t
// RUN: llvm-readobj --dynamic-table %t | FileCheck %s --check-prefix=CHECK4
// CHECK4: 0x0000000000000001 NEEDED SharedLibrary (libbar.so)
// CHECK4-NOT: NEEDED
.global _start
_start:

View File

@ -1,6 +1,6 @@
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
# RUN: ld.lld -shared %t2.o -o %t2.so # RUN: ld.lld -shared %t2.o -o %t2.so -soname relro-omagic.s.tmp2.so
# RUN: ld.lld -N %t.o %t2.so -o %t # RUN: ld.lld -N %t.o %t2.so -o %t
# RUN: llvm-objdump -section-headers %t | FileCheck --check-prefix=NORELRO %s # RUN: llvm-objdump -section-headers %t | FileCheck --check-prefix=NORELRO %s
# RUN: llvm-readobj --program-headers %t | FileCheck --check-prefix=NOPHDRS %s # RUN: llvm-readobj --program-headers %t | FileCheck --check-prefix=NOPHDRS %s