mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-03-05 08:58:13 +00:00
[ELF] Support PROVIDE and PROVIDE_HIDDEN inside SECTIONS
llvm-svn: 276398
This commit is contained in:
parent
2db00ce4b6
commit
a31c91b150
@ -338,7 +338,7 @@ void LinkerScript<ELFT>::dispatchAssignment(SymbolAssignment *Cmd) {
|
||||
uint64_t Val = evalExpr(Cmd->Expr, Dot);
|
||||
if (Cmd->Name == ".") {
|
||||
Dot = Val;
|
||||
} else {
|
||||
} else if (!Cmd->Ignore) {
|
||||
auto *D = cast<DefinedRegular<ELFT>>(Symtab<ELFT>::X->find(Cmd->Name));
|
||||
D->Value = Val;
|
||||
}
|
||||
@ -528,10 +528,19 @@ int LinkerScript<ELFT>::compareSections(StringRef A, StringRef B) {
|
||||
}
|
||||
|
||||
template <class ELFT> void LinkerScript<ELFT>::addScriptedSymbols() {
|
||||
for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands)
|
||||
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base.get()))
|
||||
if (Cmd->Name != "." && Symtab<ELFT>::X->find(Cmd->Name) == nullptr)
|
||||
Symtab<ELFT>::X->addAbsolute(Cmd->Name, STV_DEFAULT);
|
||||
for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
|
||||
auto *Cmd = dyn_cast<SymbolAssignment>(Base.get());
|
||||
if (!Cmd || Cmd->Name == ".")
|
||||
continue;
|
||||
|
||||
if (Symtab<ELFT>::X->find(Cmd->Name) == nullptr)
|
||||
Symtab<ELFT>::X->addAbsolute(Cmd->Name,
|
||||
Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT);
|
||||
else
|
||||
// Symbol already exists in symbol table. If it is provided
|
||||
// then we can't override its value.
|
||||
Cmd->Ignore = Cmd->Provide;
|
||||
}
|
||||
}
|
||||
|
||||
template <class ELFT> bool LinkerScript<ELFT>::hasPhdrsCommands() {
|
||||
@ -592,7 +601,8 @@ private:
|
||||
void readOutputSectionDescription(StringRef OutSec);
|
||||
std::vector<StringRef> readOutputSectionPhdrs();
|
||||
unsigned readPhdrType();
|
||||
void readSymbolAssignment(StringRef Name);
|
||||
void readProvide(bool Hidden);
|
||||
SymbolAssignment *readSymbolAssignment(StringRef Name);
|
||||
std::vector<StringRef> readSectionsCommandExpr();
|
||||
|
||||
const static StringMap<Handler> Cmd;
|
||||
@ -789,7 +799,11 @@ void ScriptParser::readSections() {
|
||||
continue;
|
||||
}
|
||||
next();
|
||||
if (peek() == "=")
|
||||
if (Tok == "PROVIDE")
|
||||
readProvide(false);
|
||||
else if (Tok == "PROVIDE_HIDDEN")
|
||||
readProvide(true);
|
||||
else if (peek() == "=")
|
||||
readSymbolAssignment(Tok);
|
||||
else
|
||||
readOutputSectionDescription(Tok);
|
||||
@ -855,19 +869,42 @@ void ScriptParser::readOutputSectionDescription(StringRef OutSec) {
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptParser::readSymbolAssignment(StringRef Name) {
|
||||
expect("=");
|
||||
std::vector<StringRef> Expr = readSectionsCommandExpr();
|
||||
if (Expr.empty())
|
||||
error("error in symbol assignment expression");
|
||||
else
|
||||
Opt.Commands.push_back(llvm::make_unique<SymbolAssignment>(Name, Expr));
|
||||
void ScriptParser::readProvide(bool Hidden) {
|
||||
expect("(");
|
||||
if (SymbolAssignment *Assignment = readSymbolAssignment(next())) {
|
||||
Assignment->Provide = true;
|
||||
Assignment->Hidden = Hidden;
|
||||
}
|
||||
expect(")");
|
||||
expect(";");
|
||||
}
|
||||
|
||||
SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef Name) {
|
||||
expect("=");
|
||||
std::vector<StringRef> Expr = readSectionsCommandExpr();
|
||||
if (Expr.empty()) {
|
||||
error("error in symbol assignment expression");
|
||||
} else {
|
||||
Opt.Commands.push_back(llvm::make_unique<SymbolAssignment>(Name, Expr));
|
||||
return static_cast<SymbolAssignment *>(Opt.Commands.back().get());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This function reads balanced expression until semicolon is seen.
|
||||
std::vector<StringRef> ScriptParser::readSectionsCommandExpr() {
|
||||
int Braces = 0;
|
||||
std::vector<StringRef> Expr;
|
||||
while (!Error) {
|
||||
StringRef Tok = next();
|
||||
StringRef Tok = peek();
|
||||
|
||||
if (Tok == "(")
|
||||
Braces++;
|
||||
else if (Tok == ")")
|
||||
if (--Braces < 0)
|
||||
break;
|
||||
|
||||
next();
|
||||
if (Tok == ";")
|
||||
break;
|
||||
Expr.push_back(Tok);
|
||||
|
@ -51,6 +51,10 @@ struct SymbolAssignment : BaseCommand {
|
||||
static bool classof(const BaseCommand *C);
|
||||
StringRef Name;
|
||||
std::vector<StringRef> Expr;
|
||||
bool Provide = false;
|
||||
// Hidden and Ignore can be true, only if Provide is true
|
||||
bool Hidden = false;
|
||||
bool Ignore = false;
|
||||
};
|
||||
|
||||
// Linker scripts allow additional constraints to be put on ouput sections.
|
||||
|
@ -319,7 +319,7 @@
|
||||
# RUN: }" > %t.script
|
||||
# RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \
|
||||
# RUN: FileCheck --check-prefix=BRACKETERR2 %s
|
||||
# BRACKETERR2: stray token: )
|
||||
# BRACKETERR2: expected, but got *
|
||||
|
||||
## Empty expression.
|
||||
# RUN: echo "SECTIONS { \
|
||||
|
@ -1,11 +1,43 @@
|
||||
# REQUIRES: x86
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
|
||||
|
||||
# Simple symbol assignment. Should raise conflict in case we
|
||||
# have duplicates in any input section, but currently simply
|
||||
# replaces the value.
|
||||
# RUN: echo "SECTIONS {.text : {*(.text.*)} text_end = .;}" > %t.script
|
||||
# RUN: ld.lld -o %t1 --script %t.script %t
|
||||
# RUN: llvm-objdump -t %t1 | FileCheck %s
|
||||
# CHECK: 0000000000000121 *ABS* 00000000 text_end
|
||||
# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=SIMPLE %s
|
||||
# SIMPLE: 0000000000000121 *ABS* 00000000 text_end
|
||||
|
||||
# Provide new symbol. The value should be 1, like set in PROVIDE()
|
||||
# RUN: echo "SECTIONS { PROVIDE(newsym = 1);}" > %t.script
|
||||
# RUN: ld.lld -o %t1 --script %t.script %t
|
||||
# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=PROVIDE1 %s
|
||||
# PROVIDE1: 0000000000000001 *ABS* 00000000 newsym
|
||||
|
||||
# Provide new symbol (hidden). The value should be 1
|
||||
# RUN: echo "SECTIONS { PROVIDE_HIDDEN(newsym = 1);}" > %t.script
|
||||
# RUN: ld.lld -o %t1 --script %t.script %t
|
||||
# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=HIDDEN1 %s
|
||||
# HIDDEN1: 0000000000000001 *ABS* 00000000 .hidden newsym
|
||||
|
||||
# Provide existing symbol. The value should be 0, even though we
|
||||
# have value of 1 in PROVIDE()
|
||||
# RUN: echo "SECTIONS { PROVIDE(somesym = 1);}" > %t.script
|
||||
# RUN: ld.lld -o %t1 --script %t.script %t
|
||||
# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=PROVIDE2 %s
|
||||
# PROVIDE2: 0000000000000000 *ABS* 00000000 somesym
|
||||
|
||||
# Provide existing symbol. The value should be 0, even though we
|
||||
# have value of 1 in PROVIDE(). Visibility should not change
|
||||
# RUN: echo "SECTIONS { PROVIDE(somesym = 1);}" > %t.script
|
||||
# RUN: ld.lld -o %t1 --script %t.script %t
|
||||
# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=HIDDEN2 %s
|
||||
# HIDDEN2: 0000000000000000 *ABS* 00000000 somesym
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
nop
|
||||
|
||||
.global somesym
|
||||
somesym = 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user