mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-19 09:26:59 +00:00
[ELF] Implement parsing -l
prefixed items in the GROUP
linker script command.
There are two forms of `-l` prefixed expression: * -l<libname> * -l:<filename> In the first case a linker should construct a full library name `lib + libname + .[so|a]` and search this library as usual. In the second case a linker should use the `<filename>` as is and search this file through library search directories. The patch reviewed by Shankar Easwaran. llvm-svn: 213077
This commit is contained in:
parent
bc94c94be4
commit
64c0ac2b35
@ -34,6 +34,7 @@ public:
|
||||
unknown,
|
||||
eof,
|
||||
identifier,
|
||||
libname,
|
||||
comma,
|
||||
l_paren,
|
||||
r_paren,
|
||||
@ -145,10 +146,11 @@ private:
|
||||
struct Path {
|
||||
StringRef _path;
|
||||
bool _asNeeded;
|
||||
bool _isDashlPrefix;
|
||||
|
||||
Path() : _asNeeded(false) {}
|
||||
explicit Path(StringRef path, bool asNeeded = false)
|
||||
: _path(path), _asNeeded(asNeeded) {}
|
||||
Path() : _asNeeded(false), _isDashlPrefix(false) {}
|
||||
explicit Path(StringRef path, bool asNeeded = false, bool isLib = false)
|
||||
: _path(path), _asNeeded(asNeeded), _isDashlPrefix(isLib) {}
|
||||
};
|
||||
|
||||
class Group : public Command {
|
||||
@ -169,6 +171,8 @@ public:
|
||||
first = false;
|
||||
if (path._asNeeded)
|
||||
os << "AS_NEEDED(";
|
||||
if (path._isDashlPrefix)
|
||||
os << "-l";
|
||||
os << path._path;
|
||||
if (path._asNeeded)
|
||||
os << ")";
|
||||
|
@ -96,6 +96,7 @@ std::error_code ELFGNULdScript::parse(const LinkingContext &ctx,
|
||||
for (const script::Path &path : group->getPaths()) {
|
||||
// TODO : Propagate Set WholeArchive/dashlPrefix
|
||||
attributes.setAsNeeded(path._asNeeded);
|
||||
attributes.setDashlPrefix(path._isDashlPrefix);
|
||||
auto inputNode = new ELFFileNode(
|
||||
_elfLinkingContext, _elfLinkingContext.allocateString(path._path),
|
||||
attributes);
|
||||
|
@ -163,18 +163,23 @@ static void buildSearchPath(SmallString<128> &path, StringRef dir,
|
||||
}
|
||||
|
||||
ErrorOr<StringRef> ELFLinkingContext::searchLibrary(StringRef libName) const {
|
||||
bool hasColonPrefix = libName[0] == ':';
|
||||
Twine soName =
|
||||
hasColonPrefix ? libName.drop_front() : Twine("lib", libName) + ".so";
|
||||
Twine archiveName =
|
||||
hasColonPrefix ? libName.drop_front() : Twine("lib", libName) + ".a";
|
||||
SmallString<128> path;
|
||||
for (StringRef dir : _inputSearchPaths) {
|
||||
// Search for dynamic library
|
||||
if (!_isStaticExecutable) {
|
||||
buildSearchPath(path, dir, _sysrootPath);
|
||||
llvm::sys::path::append(path, Twine("lib") + libName + ".so");
|
||||
llvm::sys::path::append(path, soName);
|
||||
if (llvm::sys::fs::exists(path.str()))
|
||||
return StringRef(*new (_allocator) std::string(path.str()));
|
||||
}
|
||||
// Search for static libraries too
|
||||
buildSearchPath(path, dir, _sysrootPath);
|
||||
llvm::sys::path::append(path, Twine("lib") + libName + ".a");
|
||||
llvm::sys::path::append(path, archiveName);
|
||||
if (llvm::sys::fs::exists(path.str()))
|
||||
return StringRef(*new (_allocator) std::string(path.str()));
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ void Token::dump(raw_ostream &os) const {
|
||||
break;
|
||||
CASE(eof)
|
||||
CASE(identifier)
|
||||
CASE(libname)
|
||||
CASE(kw_as_needed)
|
||||
CASE(kw_entry)
|
||||
CASE(kw_group)
|
||||
@ -118,6 +119,24 @@ void Lexer::lex(Token &tok) {
|
||||
_buffer = _buffer.drop_front(quotedStringEnd + 1);
|
||||
return;
|
||||
}
|
||||
// -l<lib name>
|
||||
if (_buffer.startswith("-l")) {
|
||||
_buffer = _buffer.drop_front(2);
|
||||
StringRef::size_type start = 0;
|
||||
if (_buffer[start] == ':')
|
||||
++start;
|
||||
if (!canStartName(_buffer[start]))
|
||||
// Create 'unknown' token.
|
||||
break;
|
||||
auto libNameEnd =
|
||||
std::find_if(_buffer.begin() + start + 1, _buffer.end(),
|
||||
[=](char c) { return !canContinueName(c); });
|
||||
StringRef::size_type libNameLen =
|
||||
std::distance(_buffer.begin(), libNameEnd);
|
||||
tok = Token(_buffer.substr(0, libNameLen), Token::libname);
|
||||
_buffer = _buffer.drop_front(libNameLen);
|
||||
return;
|
||||
}
|
||||
/// keyword or identifer.
|
||||
if (!canStartName(_buffer[0]))
|
||||
break;
|
||||
@ -295,12 +314,17 @@ Group *Parser::parseGroup() {
|
||||
|
||||
std::vector<Path> paths;
|
||||
|
||||
while (_tok._kind == Token::identifier || _tok._kind == Token::kw_as_needed) {
|
||||
while (_tok._kind == Token::identifier || _tok._kind == Token::libname ||
|
||||
_tok._kind == Token::kw_as_needed) {
|
||||
switch (_tok._kind) {
|
||||
case Token::identifier:
|
||||
paths.push_back(Path(_tok._range));
|
||||
consumeToken();
|
||||
break;
|
||||
case Token::libname:
|
||||
paths.push_back(Path(_tok._range, false, true));
|
||||
consumeToken();
|
||||
break;
|
||||
case Token::kw_as_needed:
|
||||
if (!parseAsNeeded(paths))
|
||||
return nullptr;
|
||||
@ -325,9 +349,19 @@ bool Parser::parseAsNeeded(std::vector<Path> &paths) {
|
||||
if (!expectAndConsume(Token::l_paren, "expected ("))
|
||||
return false;
|
||||
|
||||
while (_tok._kind == Token::identifier) {
|
||||
paths.push_back(Path(_tok._range, true));
|
||||
consumeToken();
|
||||
while (_tok._kind == Token::identifier || _tok._kind == Token::libname) {
|
||||
switch (_tok._kind) {
|
||||
case Token::identifier:
|
||||
paths.push_back(Path(_tok._range, true, false));
|
||||
consumeToken();
|
||||
break;
|
||||
case Token::libname:
|
||||
paths.push_back(Path(_tok._range, true, true));
|
||||
consumeToken();
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Invalid token.");
|
||||
}
|
||||
}
|
||||
|
||||
if (!expectAndConsume(Token::r_paren, "expected )"))
|
||||
|
11
lld/test/LinkerScript/libname-err-1.test
Normal file
11
lld/test/LinkerScript/libname-err-1.test
Normal file
@ -0,0 +1,11 @@
|
||||
/* RUN: linker-script-test %s 2>&1 | FileCheck %s
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH(i386:x86_64)
|
||||
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
|
||||
GROUP( -l### )
|
||||
ENTRY(init)
|
||||
|
||||
/*
|
||||
CHECK: test/LinkerScript/libname-err-1.test:6:10: error: expected )
|
||||
*/
|
11
lld/test/LinkerScript/libname-err-2.test
Normal file
11
lld/test/LinkerScript/libname-err-2.test
Normal file
@ -0,0 +1,11 @@
|
||||
/* RUN: linker-script-test %s 2>&1 | FileCheck %s
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH(i386:x86_64)
|
||||
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
|
||||
GROUP( -l )
|
||||
ENTRY(init)
|
||||
|
||||
/*
|
||||
CHECK: test/LinkerScript/libname-err-2.test:6:10: error: expected )
|
||||
*/
|
@ -3,7 +3,7 @@
|
||||
|
||||
OUTPUT_ARCH(i386:x86_64)
|
||||
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
|
||||
GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED ( /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ) )
|
||||
GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED ( /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ) -lm -l:libgcc.a )
|
||||
ENTRY(init)
|
||||
|
||||
/*
|
||||
@ -27,6 +27,8 @@ CHECK: kw_as_needed: AS_NEEDED
|
||||
CHECK: l_paren: (
|
||||
CHECK: identifier: /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
|
||||
CHECK: r_paren: )
|
||||
CHECK: libname: m
|
||||
CHECK: libname: :libgcc.a
|
||||
CHECK: r_paren: )
|
||||
CHECK: kw_entry: ENTRY
|
||||
CHECK: l_paren: (
|
||||
@ -34,6 +36,6 @@ CHECK: identifier: init
|
||||
CHECK: r_paren: )
|
||||
CHECK: eof:
|
||||
CHECK: OUTPUT_FORMAT(elf64-x86-64,elf64-x86-64,elf64-x86-64)
|
||||
CHECK: GROUP(/lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED(/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2))
|
||||
CHECK: GROUP(/lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED(/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2) -lm -l:libgcc.a)
|
||||
CHECK: ENTRY(init)
|
||||
*/
|
||||
|
1
lld/test/elf/Inputs/group-cmd-search-3.ls
Normal file
1
lld/test/elf/Inputs/group-cmd-search-3.ls
Normal file
@ -0,0 +1 @@
|
||||
GROUP ( -l:shared.so-x86-64 -lfnarchive )
|
@ -100,6 +100,19 @@ RUN: -L%p/Inputs %p/Inputs/use-shared.x86-64 \
|
||||
RUN: %p/Inputs/group-cmd-search-2.ls -o %t6
|
||||
*/
|
||||
|
||||
/*
|
||||
This link should finish successfully. The group-cmd-search-3.ls
|
||||
script contains GROUP command with two elements. The first one
|
||||
has a -l:<path> form and should be found by iterating through
|
||||
lib dirs and searching the 'path' name exactly. The second element
|
||||
has a -l<lib name> form and should be found by constructing a full
|
||||
library name lib<lib name>.a and iterating through lib dirs.
|
||||
|
||||
RUN: lld -flavor gnu -target x86_64 -shared \
|
||||
RUN: -L%p/Inputs %p/Inputs/use-shared.x86-64 \
|
||||
RUN: %p/Inputs/group-cmd-search-3.ls -o %t8
|
||||
*/
|
||||
|
||||
/*
|
||||
This link should fail with unknown input file format error.
|
||||
The linker script from this file contains GROUP with an absolute
|
||||
|
Loading…
x
Reference in New Issue
Block a user