Skip to content

Commit

Permalink
[ELF] - Linkerscript: improved error reporting.
Browse files Browse the repository at this point in the history
When linking linux kernel LLD currently reports next errors:

ld: error: unable to evaluate expression: input section .head.text has no output section assigned
ld: error: At least one side of the expression must be absolute
ld: error: At least one side of the expression must be absolute

That does not provide file/line information and overall looks unclear. 
Patch adds location information to ExprValue and that allows
to provide more clear error messages.

Differential revision: https://reviews.llvm.org/D33943

llvm-svn: 304881
  • Loading branch information
George Rimar committed Jun 7, 2017
1 parent 154a4fd commit 41c7ab4
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 19 deletions.
8 changes: 4 additions & 4 deletions lld/ELF/LinkerScript.cpp
Expand Up @@ -54,7 +54,7 @@ uint64_t ExprValue::getValue() const {
if (Sec) {
if (OutputSection *OS = Sec->getOutputSection())
return alignTo(Sec->getOffset(Val) + OS->Addr, Alignment);
error("unable to evaluate expression: input section " + Sec->Name +
error(Loc + ": unable to evaluate expression: input section " + Sec->Name +
" has no output section assigned");
}
return alignTo(Val, Alignment);
Expand Down Expand Up @@ -1231,12 +1231,12 @@ bool LinkerScript::hasLMA(OutputSection *Sec) {

ExprValue LinkerScript::getSymbolValue(const Twine &Loc, StringRef S) {
if (S == ".")
return {CurOutSec, Dot - CurOutSec->Addr};
return {CurOutSec, Dot - CurOutSec->Addr, Loc};
if (SymbolBody *B = findSymbol(S)) {
if (auto *D = dyn_cast<DefinedRegular>(B))
return {D->Section, D->Value};
return {D->Section, D->Value, Loc};
if (auto *C = dyn_cast<DefinedCommon>(B))
return {InX::Common, C->Offset};
return {InX::Common, C->Offset, Loc};
}
error(Loc + ": symbol not found: " + S);
return 0;
Expand Down
13 changes: 6 additions & 7 deletions lld/ELF/LinkerScript.h
Expand Up @@ -42,15 +42,14 @@ struct ExprValue {
uint64_t Val;
bool ForceAbsolute;
uint64_t Alignment = 1;
std::string Loc;

ExprValue(SectionBase *Sec, bool ForceAbsolute, uint64_t Val,
uint64_t Alignment)
: Sec(Sec), Val(Val), ForceAbsolute(ForceAbsolute), Alignment(Alignment) {
}
ExprValue(SectionBase *Sec, bool ForceAbsolute, uint64_t Val)
: Sec(Sec), Val(Val), ForceAbsolute(ForceAbsolute) {}
ExprValue(SectionBase *Sec, uint64_t Val) : ExprValue(Sec, false, Val) {}
ExprValue(uint64_t Val) : ExprValue(nullptr, Val) {}
const Twine &Loc)
: Sec(Sec), Val(Val), ForceAbsolute(ForceAbsolute), Loc(Loc.str()) {}
ExprValue(SectionBase *Sec, uint64_t Val, const Twine &Loc)
: ExprValue(Sec, false, Val, Loc) {}
ExprValue(uint64_t Val) : ExprValue(nullptr, Val, "") {}
bool isAbsolute() const { return ForceAbsolute || Sec == nullptr; }
uint64_t getValue() const;
uint64_t getSecAddr() const;
Expand Down
14 changes: 8 additions & 6 deletions lld/ELF/ScriptParser.cpp
Expand Up @@ -127,16 +127,16 @@ static void moveAbsRight(ExprValue &A, ExprValue &B) {
if (A.isAbsolute())
std::swap(A, B);
if (!B.isAbsolute())
error("At least one side of the expression must be absolute");
error(A.Loc + ": at least one side of the expression must be absolute");
}

static ExprValue add(ExprValue A, ExprValue B) {
moveAbsRight(A, B);
return {A.Sec, A.ForceAbsolute, A.Val + B.getValue()};
return {A.Sec, A.ForceAbsolute, A.Val + B.getValue(), A.Loc};
}

static ExprValue sub(ExprValue A, ExprValue B) {
return {A.Sec, A.Val - B.getValue()};
return {A.Sec, A.Val - B.getValue(), A.Loc};
}

static ExprValue mul(ExprValue A, ExprValue B) {
Expand All @@ -153,13 +153,13 @@ static ExprValue div(ExprValue A, ExprValue B) {
static ExprValue bitAnd(ExprValue A, ExprValue B) {
moveAbsRight(A, B);
return {A.Sec, A.ForceAbsolute,
(A.getValue() & B.getValue()) - A.getSecAddr()};
(A.getValue() & B.getValue()) - A.getSecAddr(), A.Loc};
}

static ExprValue bitOr(ExprValue A, ExprValue B) {
moveAbsRight(A, B);
return {A.Sec, A.ForceAbsolute,
(A.getValue() | B.getValue()) - A.getSecAddr()};
(A.getValue() | B.getValue()) - A.getSecAddr(), A.Loc};
}

void ScriptParser::readDynamicList() {
Expand Down Expand Up @@ -859,7 +859,9 @@ Expr ScriptParser::readPrimary() {
if (Tok == "ADDR") {
StringRef Name = readParenLiteral();
OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name);
return [=]() -> ExprValue { return {checkSection(Cmd, Location), 0}; };
return [=]() -> ExprValue {
return {checkSection(Cmd, Location), 0, Location};
};
}
if (Tok == "ALIGN") {
expect("(");
Expand Down
2 changes: 1 addition & 1 deletion lld/test/ELF/linkerscript/early-assign-symbol.s
Expand Up @@ -7,7 +7,7 @@
# RUN: echo "SECTIONS { aaa = ABSOLUTE(foo - 1) + 1; .text : { *(.text*) } }" > %t2.script
# RUN: not ld.lld -o %t --script %t2.script %t.o 2>&1 | FileCheck %s

# CHECK: error: unable to evaluate expression: input section .text has no output section assigned
# CHECK: error: {{.*}}.script:1: unable to evaluate expression: input section .text has no output section assigned

.section .text
.globl foo
Expand Down
2 changes: 1 addition & 1 deletion lld/test/ELF/linkerscript/expr-invalid-sec.s
Expand Up @@ -3,4 +3,4 @@
# RUN: echo "SECTIONS { foo = ADDR(.text) + ADDR(.text); };" > %t.script
# RUN: not ld.lld -o %t.so --script %t.script %t.o -shared 2>&1 | FileCheck %s

# CHECK: At least one side of the expression must be absolute
# CHECK: error: {{.*}}.script:1: at least one side of the expression must be absolute

0 comments on commit 41c7ab4

Please sign in to comment.