forked from OSchip/llvm-project
[ELF] - Linkerscript: implemented ASSERT() keyword.
ASSERT(exp, message) Ensure that exp is non-zero. If it is zero, then exit the linker with an error code, and print message. ASSERT is useful and was seen in few projects in the wild. Differential revision: https://reviews.llvm.org/D22912 llvm-svn: 277710
This commit is contained in:
parent
8100940b8b
commit
eefa758ee2
|
@ -55,6 +55,10 @@ bool InputSectionDescription::classof(const BaseCommand *C) {
|
|||
return C->Kind == InputSectionKind;
|
||||
}
|
||||
|
||||
bool AssertCommand::classof(const BaseCommand *C) {
|
||||
return C->Kind == AssertKind;
|
||||
}
|
||||
|
||||
template <class ELFT> static bool isDiscarded(InputSectionBase<ELFT> *S) {
|
||||
return !S || !S->Live;
|
||||
}
|
||||
|
@ -249,6 +253,11 @@ void LinkerScript<ELFT>::assignAddresses(
|
|||
continue;
|
||||
}
|
||||
|
||||
if (auto *Cmd = dyn_cast<AssertCommand>(Base.get())) {
|
||||
Cmd->Expression(Dot);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find all the sections with required name. There can be more than
|
||||
// one section with such name, if the alignment, flags or type
|
||||
// attribute differs.
|
||||
|
@ -487,6 +496,7 @@ private:
|
|||
SymbolAssignment *readProvide(bool Hidden);
|
||||
Expr readAlign();
|
||||
void readSort();
|
||||
Expr readAssert();
|
||||
|
||||
Expr readExpr();
|
||||
Expr readExpr1(Expr Lhs, int MinPrec);
|
||||
|
@ -693,6 +703,8 @@ void ScriptParser::readSections() {
|
|||
Cmd = readProvide(false);
|
||||
} else if (Tok == "PROVIDE_HIDDEN") {
|
||||
Cmd = readProvide(true);
|
||||
} else if (Tok == "ASSERT") {
|
||||
Cmd = new AssertCommand(readAssert());
|
||||
} else {
|
||||
Cmd = readOutputSectionDescription(Tok);
|
||||
}
|
||||
|
@ -796,6 +808,20 @@ void ScriptParser::readSort() {
|
|||
expect(")");
|
||||
}
|
||||
|
||||
Expr ScriptParser::readAssert() {
|
||||
expect("(");
|
||||
Expr E = readExpr();
|
||||
expect(",");
|
||||
StringRef Msg = next();
|
||||
expect(")");
|
||||
return [=](uint64_t Dot) {
|
||||
uint64_t V = E(Dot);
|
||||
if (!V)
|
||||
error(Msg);
|
||||
return V;
|
||||
};
|
||||
}
|
||||
|
||||
OutputSectionCommand *
|
||||
ScriptParser::readOutputSectionDescription(StringRef OutSec) {
|
||||
OutputSectionCommand *Cmd = new OutputSectionCommand(OutSec);
|
||||
|
@ -967,6 +993,8 @@ Expr ScriptParser::readPrimary() {
|
|||
|
||||
// Built-in functions are parsed here.
|
||||
// https://sourceware.org/binutils/docs/ld/Builtin-Functions.html.
|
||||
if (Tok == "ASSERT")
|
||||
return readAssert();
|
||||
if (Tok == "ALIGN") {
|
||||
expect("(");
|
||||
Expr E = readExpr();
|
||||
|
|
|
@ -41,7 +41,8 @@ template <class ELFT> class OutputSectionBase;
|
|||
enum SectionsCommandKind {
|
||||
AssignmentKind,
|
||||
OutputSectionKind,
|
||||
InputSectionKind
|
||||
InputSectionKind,
|
||||
AssertKind
|
||||
};
|
||||
|
||||
struct BaseCommand {
|
||||
|
@ -98,6 +99,12 @@ struct InputSectionDescription : BaseCommand {
|
|||
std::vector<StringRef> SectionPatterns;
|
||||
};
|
||||
|
||||
struct AssertCommand : BaseCommand {
|
||||
AssertCommand(Expr E) : BaseCommand(AssertKind), Expression(E) {}
|
||||
static bool classof(const BaseCommand *C);
|
||||
Expr Expression;
|
||||
};
|
||||
|
||||
struct PhdrsCommand {
|
||||
StringRef Name;
|
||||
unsigned Type;
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
|
||||
|
||||
# RUN: echo "SECTIONS { \
|
||||
# RUN: ASSERT(1, \"true\") \
|
||||
# RUN: }" > %t1.script
|
||||
# RUN: ld.lld -shared -o %t1 --script %t1.script %t1.o
|
||||
# RUN: llvm-readobj %t1 > /dev/null
|
||||
|
||||
# RUN: echo "SECTIONS { \
|
||||
# RUN: ASSERT(ASSERT(42, \"true\") == 42, \"true\") \
|
||||
# RUN: }" > %t2.script
|
||||
# RUN: ld.lld -shared -o %t2 --script %t2.script %t1.o
|
||||
# RUN: llvm-readobj %t2 > /dev/null
|
||||
|
||||
# RUN: echo "SECTIONS { \
|
||||
# RUN: ASSERT(0,\ "fail\") \
|
||||
# RUN: }" > %t3.script
|
||||
# RUN: not ld.lld -shared -o %t3 --script %t3.script %t1.o > %t.log 2>&1
|
||||
# RUN: FileCheck %s -check-prefix=FAIL < %t.log
|
||||
# FAIL: fail
|
||||
|
||||
# RUN: echo "SECTIONS { \
|
||||
# RUN: . = ASSERT(0x1000, \"true\"); \
|
||||
# RUN: }" > %t4.script
|
||||
# RUN: ld.lld -shared -o %t4 --script %t4.script %t1.o
|
||||
# RUN: llvm-readobj %t4 > /dev/null
|
Loading…
Reference in New Issue