From d30a78b3fede801cf6b7054851d4daa041103948 Mon Sep 17 00:00:00 2001 From: George Rimar Date: Wed, 25 Apr 2018 11:16:31 +0000 Subject: [PATCH] [ELF] - Eliminate the AssertCommand. Currently, LLD supports ASSERT as a separate command. We support two forms now. Assign expression-form: . = ASSERT(0x100) (old GNU ld required it and some scripts in the wild are still using something like . = ASSERT((_end - _text <= (512 * 1024 * 1024)), "kernel image bigger than KERNEL_IMAGE_SIZE"); Nowadays above is not a mandatory form and command-like form is commonly used: ASSERT(, "text); The return value of the ASSERT is Dot. That was implemented in D30171. It looks like (2) is just a short version of (1) then. GNU ld does *not* list ASSERT as a SECTIONS command: https://sourceware.org/binutils/docs/ld/SECTIONS.html#SECTIONS Given above we probably can change ASSERT to be an assignment to Dot. That makes the rest of the code much simpler. Patch do that. Differential revision: https://reviews.llvm.org/D45434 llvm-svn: 330814 --- lld/ELF/LinkerScript.cpp | 12 --------- lld/ELF/LinkerScript.h | 10 -------- lld/ELF/ScriptParser.cpp | 50 +++++++++++++++----------------------- lld/test/ELF/linkerscript/assert.s | 7 +++--- 4 files changed, 24 insertions(+), 55 deletions(-) diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 7d372ac..d99d382 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -801,12 +801,6 @@ void LinkerScript::assignOffsets(OutputSection *Sec) { continue; } - // Handle ASSERT(). - if (auto *Cmd = dyn_cast(Base)) { - Cmd->Expression(); - continue; - } - // Handle a single input section description command. // It calculates and assigns the offsets for each section and also // updates the output section size. @@ -1053,12 +1047,6 @@ void LinkerScript::assignAddresses() { Cmd->Size = Dot - Cmd->Addr; continue; } - - if (auto *Cmd = dyn_cast(Base)) { - Cmd->Expression(); - continue; - } - assignOffsets(cast(Base)); } Ctx = nullptr; diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 4dd9586..3b790dd 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -75,7 +75,6 @@ enum SectionsCommandKind { AssignmentKind, // . = expr or = expr OutputSectionKind, InputSectionKind, - AssertKind, // ASSERT(expr) ByteKind // BYTE(expr), SHORT(expr), LONG(expr) or QUAD(expr) }; @@ -177,15 +176,6 @@ struct InputSectionDescription : BaseCommand { std::vector> ThunkSections; }; -// Represents an ASSERT(). -struct AssertCommand : BaseCommand { - AssertCommand(Expr E) : BaseCommand(AssertKind), Expression(E) {} - - static bool classof(const BaseCommand *C) { return C->Kind == AssertKind; } - - Expr Expression; -}; - // Represents BYTE(), SHORT(), LONG(), or QUAD(). struct ByteCommand : BaseCommand { ByteCommand(Expr E, unsigned Size, std::string CommandString) diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp index 5ed5b49..707e104 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -75,7 +75,7 @@ private: void readVersion(); void readVersionScriptCommand(); - SymbolAssignment *readAssignment(StringRef Name); + SymbolAssignment *readSymbolAssignment(StringRef Name); ByteCommand *readByteCommand(StringRef Tok); uint32_t readFill(); uint32_t parseFill(StringRef Tok); @@ -89,10 +89,9 @@ private: unsigned readPhdrType(); SortSectionPolicy readSortKind(); SymbolAssignment *readProvideHidden(bool Provide, bool Hidden); - SymbolAssignment *readProvideOrAssignment(StringRef Tok); + SymbolAssignment *readAssignment(StringRef Tok); void readSort(); - AssertCommand *readAssert(); - Expr readAssertExpr(); + Expr readAssert(); Expr readConstant(); Expr getPageSize(); @@ -228,9 +227,7 @@ void ScriptParser::readLinkerScript() { if (Tok == ";") continue; - if (Tok == "ASSERT") { - Script->SectionCommands.push_back(readAssert()); - } else if (Tok == "ENTRY") { + if (Tok == "ENTRY") { readEntry(); } else if (Tok == "EXTERN") { readExtern(); @@ -258,7 +255,7 @@ void ScriptParser::readLinkerScript() { readSections(); } else if (Tok == "VERSION") { readVersion(); - } else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok)) { + } else if (SymbolAssignment *Cmd = readAssignment(Tok)) { Script->SectionCommands.push_back(Cmd); } else { setError("unknown directive: " + Tok); @@ -451,14 +448,10 @@ void ScriptParser::readSections() { std::vector V; while (!errorCount() && !consume("}")) { StringRef Tok = next(); - BaseCommand *Cmd = readProvideOrAssignment(Tok); - if (!Cmd) { - if (Tok == "ASSERT") - Cmd = readAssert(); - else - Cmd = readOutputSectionDescription(Tok); - } - V.push_back(Cmd); + if (BaseCommand *Cmd = readAssignment(Tok)) + V.push_back(Cmd); + else + V.push_back(readOutputSectionDescription(Tok)); } if (!atEOF() && consume("INSERT")) { @@ -608,11 +601,7 @@ void ScriptParser::readSort() { expect(")"); } -AssertCommand *ScriptParser::readAssert() { - return make(readAssertExpr()); -} - -Expr ScriptParser::readAssertExpr() { +Expr ScriptParser::readAssert() { expect("("); Expr E = readExpr(); expect(","); @@ -713,13 +702,10 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) { StringRef Tok = next(); if (Tok == ";") { // Empty commands are allowed. Do nothing here. - } else if (SymbolAssignment *Assign = readProvideOrAssignment(Tok)) { + } else if (SymbolAssignment *Assign = readAssignment(Tok)) { Cmd->SectionCommands.push_back(Assign); } else if (ByteCommand *Data = readByteCommand(Tok)) { Cmd->SectionCommands.push_back(Data); - } else if (Tok == "ASSERT") { - Cmd->SectionCommands.push_back(readAssert()); - expect(";"); } else if (Tok == "CONSTRUCTORS") { // CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors // by name. This is for very old file formats such as ECOFF/XCOFF. @@ -780,18 +766,22 @@ uint32_t ScriptParser::parseFill(StringRef Tok) { SymbolAssignment *ScriptParser::readProvideHidden(bool Provide, bool Hidden) { expect("("); - SymbolAssignment *Cmd = readAssignment(next()); + SymbolAssignment *Cmd = readSymbolAssignment(next()); Cmd->Provide = Provide; Cmd->Hidden = Hidden; expect(")"); return Cmd; } -SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok) { +SymbolAssignment *ScriptParser::readAssignment(StringRef Tok) { + // Assert expression returns Dot, so this is equal to ".=." + if (Tok == "ASSERT") + return make(".", readAssert(), getCurrentLocation()); + size_t OldPos = Pos; SymbolAssignment *Cmd = nullptr; if (peek() == "=" || peek() == "+=") - Cmd = readAssignment(Tok); + Cmd = readSymbolAssignment(Tok); else if (Tok == "PROVIDE") Cmd = readProvideHidden(true, false); else if (Tok == "HIDDEN") @@ -808,7 +798,7 @@ SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok) { return Cmd; } -SymbolAssignment *ScriptParser::readAssignment(StringRef Name) { +SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef Name) { StringRef Op = next(); assert(Op == "=" || Op == "+="); Expr E = readExpr(); @@ -1057,7 +1047,7 @@ Expr ScriptParser::readPrimary() { }; } if (Tok == "ASSERT") - return readAssertExpr(); + return readAssert(); if (Tok == "CONSTANT") return readConstant(); if (Tok == "DATA_SEGMENT_ALIGN") { diff --git a/lld/test/ELF/linkerscript/assert.s b/lld/test/ELF/linkerscript/assert.s index 73cc940..100631a 100644 --- a/lld/test/ELF/linkerscript/assert.s +++ b/lld/test/ELF/linkerscript/assert.s @@ -30,10 +30,11 @@ # RUN: ld.lld -shared -o %t6 --script %t6.script %t1.o # RUN: llvm-readobj %t6 > /dev/null +## Unlike the GNU ld, we accept the ASSERT without the semicolon. +## It is consistent with how ASSERT can be written outside of the +## output section declaration. # RUN: echo "SECTIONS { .foo : { ASSERT(1, \"true\") } }" > %t7.script -# RUN: not ld.lld -shared -o %t7 --script %t7.script %t1.o > %t.log 2>&1 -# RUN: FileCheck %s -check-prefix=CHECK-SEMI < %t.log -# CHECK-SEMI: error: {{.*}}.script:1: ; expected, but got } +# RUN: ld.lld -shared -o %t7 --script %t7.script %t1.o .section .foo, "a" .quad 0 -- 2.7.4