forked from OSchip/llvm-project
[ELF] - Linkerscript: improved error reporting.
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
This commit is contained in:
parent
154a4fd5dc
commit
41c7ab4a3d
|
|
@ -54,7 +54,7 @@ uint64_t ExprValue::getValue() const {
|
||||||
if (Sec) {
|
if (Sec) {
|
||||||
if (OutputSection *OS = Sec->getOutputSection())
|
if (OutputSection *OS = Sec->getOutputSection())
|
||||||
return alignTo(Sec->getOffset(Val) + OS->Addr, Alignment);
|
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");
|
" has no output section assigned");
|
||||||
}
|
}
|
||||||
return alignTo(Val, Alignment);
|
return alignTo(Val, Alignment);
|
||||||
|
|
@ -1231,12 +1231,12 @@ bool LinkerScript::hasLMA(OutputSection *Sec) {
|
||||||
|
|
||||||
ExprValue LinkerScript::getSymbolValue(const Twine &Loc, StringRef S) {
|
ExprValue LinkerScript::getSymbolValue(const Twine &Loc, StringRef S) {
|
||||||
if (S == ".")
|
if (S == ".")
|
||||||
return {CurOutSec, Dot - CurOutSec->Addr};
|
return {CurOutSec, Dot - CurOutSec->Addr, Loc};
|
||||||
if (SymbolBody *B = findSymbol(S)) {
|
if (SymbolBody *B = findSymbol(S)) {
|
||||||
if (auto *D = dyn_cast<DefinedRegular>(B))
|
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))
|
if (auto *C = dyn_cast<DefinedCommon>(B))
|
||||||
return {InX::Common, C->Offset};
|
return {InX::Common, C->Offset, Loc};
|
||||||
}
|
}
|
||||||
error(Loc + ": symbol not found: " + S);
|
error(Loc + ": symbol not found: " + S);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -42,15 +42,14 @@ struct ExprValue {
|
||||||
uint64_t Val;
|
uint64_t Val;
|
||||||
bool ForceAbsolute;
|
bool ForceAbsolute;
|
||||||
uint64_t Alignment = 1;
|
uint64_t Alignment = 1;
|
||||||
|
std::string Loc;
|
||||||
|
|
||||||
ExprValue(SectionBase *Sec, bool ForceAbsolute, uint64_t Val,
|
ExprValue(SectionBase *Sec, bool ForceAbsolute, uint64_t Val,
|
||||||
uint64_t Alignment)
|
const Twine &Loc)
|
||||||
: Sec(Sec), Val(Val), ForceAbsolute(ForceAbsolute), Alignment(Alignment) {
|
: Sec(Sec), Val(Val), ForceAbsolute(ForceAbsolute), Loc(Loc.str()) {}
|
||||||
}
|
ExprValue(SectionBase *Sec, uint64_t Val, const Twine &Loc)
|
||||||
ExprValue(SectionBase *Sec, bool ForceAbsolute, uint64_t Val)
|
: ExprValue(Sec, false, Val, Loc) {}
|
||||||
: Sec(Sec), Val(Val), ForceAbsolute(ForceAbsolute) {}
|
ExprValue(uint64_t Val) : ExprValue(nullptr, Val, "") {}
|
||||||
ExprValue(SectionBase *Sec, uint64_t Val) : ExprValue(Sec, false, Val) {}
|
|
||||||
ExprValue(uint64_t Val) : ExprValue(nullptr, Val) {}
|
|
||||||
bool isAbsolute() const { return ForceAbsolute || Sec == nullptr; }
|
bool isAbsolute() const { return ForceAbsolute || Sec == nullptr; }
|
||||||
uint64_t getValue() const;
|
uint64_t getValue() const;
|
||||||
uint64_t getSecAddr() const;
|
uint64_t getSecAddr() const;
|
||||||
|
|
|
||||||
|
|
@ -127,16 +127,16 @@ static void moveAbsRight(ExprValue &A, ExprValue &B) {
|
||||||
if (A.isAbsolute())
|
if (A.isAbsolute())
|
||||||
std::swap(A, B);
|
std::swap(A, B);
|
||||||
if (!B.isAbsolute())
|
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) {
|
static ExprValue add(ExprValue A, ExprValue B) {
|
||||||
moveAbsRight(A, 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) {
|
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) {
|
static ExprValue mul(ExprValue A, ExprValue B) {
|
||||||
|
|
@ -153,13 +153,13 @@ static ExprValue div(ExprValue A, ExprValue B) {
|
||||||
static ExprValue bitAnd(ExprValue A, ExprValue B) {
|
static ExprValue bitAnd(ExprValue A, ExprValue B) {
|
||||||
moveAbsRight(A, B);
|
moveAbsRight(A, B);
|
||||||
return {A.Sec, A.ForceAbsolute,
|
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) {
|
static ExprValue bitOr(ExprValue A, ExprValue B) {
|
||||||
moveAbsRight(A, B);
|
moveAbsRight(A, B);
|
||||||
return {A.Sec, A.ForceAbsolute,
|
return {A.Sec, A.ForceAbsolute,
|
||||||
(A.getValue() | B.getValue()) - A.getSecAddr()};
|
(A.getValue() | B.getValue()) - A.getSecAddr(), A.Loc};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptParser::readDynamicList() {
|
void ScriptParser::readDynamicList() {
|
||||||
|
|
@ -859,7 +859,9 @@ Expr ScriptParser::readPrimary() {
|
||||||
if (Tok == "ADDR") {
|
if (Tok == "ADDR") {
|
||||||
StringRef Name = readParenLiteral();
|
StringRef Name = readParenLiteral();
|
||||||
OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name);
|
OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name);
|
||||||
return [=]() -> ExprValue { return {checkSection(Cmd, Location), 0}; };
|
return [=]() -> ExprValue {
|
||||||
|
return {checkSection(Cmd, Location), 0, Location};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (Tok == "ALIGN") {
|
if (Tok == "ALIGN") {
|
||||||
expect("(");
|
expect("(");
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
# RUN: echo "SECTIONS { aaa = ABSOLUTE(foo - 1) + 1; .text : { *(.text*) } }" > %t2.script
|
# 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
|
# 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
|
.section .text
|
||||||
.globl foo
|
.globl foo
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,4 @@
|
||||||
# RUN: echo "SECTIONS { foo = ADDR(.text) + ADDR(.text); };" > %t.script
|
# 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
|
# 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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue