Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -194,7 +194,8 @@ virtual bool isDefined(StringRef S) = 0; virtual bool isAbsolute(StringRef S) = 0; virtual const OutputSectionBase *getSymbolSection(StringRef S) = 0; - virtual const OutputSectionBase *getOutputSection(StringRef S) = 0; + virtual const OutputSectionBase *getOutputSection(const Twine &Loc, + StringRef S) = 0; virtual uint64_t getOutputSectionSize(StringRef S) = 0; }; @@ -245,7 +246,8 @@ bool isDefined(StringRef S) override; bool isAbsolute(StringRef S) override; const OutputSectionBase *getSymbolSection(StringRef S) override; - const OutputSectionBase *getOutputSection(StringRef S) override; + const OutputSectionBase *getOutputSection(const Twine &Loc, + StringRef S) override; uint64_t getOutputSectionSize(StringRef S) override; std::vector *OutputSections; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -854,13 +854,15 @@ } template -const OutputSectionBase *LinkerScript::getOutputSection(StringRef Name) { +const OutputSectionBase *LinkerScript::getOutputSection(const Twine &Loc, + StringRef Name) { static OutputSectionBase FakeSec("", 0, 0); for (OutputSectionBase *Sec : *OutputSections) if (Sec->getName() == Name) return Sec; - error("undefined section " + Name); + + error(Loc + ": undefined section " + Name); return &FakeSec; } @@ -1666,6 +1668,7 @@ return readParenExpr(); StringRef Tok = next(); + std::string Location = currentLocation(); if (Tok == "~") { Expr E = readPrimary(); @@ -1680,15 +1683,16 @@ // https://sourceware.org/binutils/docs/ld/Builtin-Functions.html. if (Tok == "ADDR") { StringRef Name = readParenLiteral(); - return { - [=](uint64_t Dot) { return ScriptBase->getOutputSection(Name)->Addr; }, - [=] { return false; }, - [=] { return ScriptBase->getOutputSection(Name); }}; + return {[=](uint64_t Dot) { + return ScriptBase->getOutputSection(Location, Name)->Addr; + }, + [=] { return false; }, + [=] { return ScriptBase->getOutputSection(Location, Name); }}; } if (Tok == "LOADADDR") { StringRef Name = readParenLiteral(); return [=](uint64_t Dot) { - return ScriptBase->getOutputSection(Name)->getLMA(); + return ScriptBase->getOutputSection(Location, Name)->getLMA(); }; } if (Tok == "ASSERT") @@ -1745,7 +1749,7 @@ if (Tok == "ALIGNOF") { StringRef Name = readParenLiteral(); return [=](uint64_t Dot) { - return ScriptBase->getOutputSection(Name)->Addralign; + return ScriptBase->getOutputSection(Location, Name)->Addralign; }; } if (Tok == "SIZEOF_HEADERS") Index: ELF/ScriptParser.h =================================================================== --- ELF/ScriptParser.h +++ ELF/ScriptParser.h @@ -32,6 +32,7 @@ void skip(); bool consume(StringRef Tok); void expect(StringRef Expect); + std::string currentLocation(); std::vector MBs; std::vector Tokens; Index: ELF/ScriptParser.cpp =================================================================== --- ELF/ScriptParser.cpp +++ ELF/ScriptParser.cpp @@ -41,25 +41,32 @@ ScriptParserBase::ScriptParserBase(MemoryBufferRef MB) { tokenize(MB); } +static std::pair +getLocation(MemoryBufferRef MB, StringRef Token, std::string &LocStr) { + LocStr = MB.getBufferIdentifier(); + std::pair ErrPos = {0, 0}; + if (!Token.empty()) { + ErrPos = getPos(MB.getBuffer(), Token); + LocStr += ":"; + LocStr += std::to_string(ErrPos.first); + } + return ErrPos; +} + // We don't want to record cascading errors. Keep only the first one. void ScriptParserBase::setError(const Twine &Msg) { if (Error) return; - std::pair ErrPos; MemoryBufferRef MB = currentBuffer(); - std::string Location = MB.getBufferIdentifier(); - if (Pos) { - ErrPos = getPos(MB.getBuffer(), Tokens[Pos - 1]); - Location += ":"; - Location += std::to_string(ErrPos.first); - } + std::string Location; + auto ErrPos = getLocation(MB, Pos ? Tokens[Pos - 1] : StringRef(), Location); + error(Location + ": " + Msg); if (Pos) { error(Location + ": " + getLine(MB.getBuffer(), Tokens[Pos - 1])); error(Location + ": " + std::string(ErrPos.second, ' ') + "^"); } - Error = true; } @@ -180,6 +187,12 @@ return Bigger.data() <= Shorter.data() && BiggerEnd >= ShorterEnd; } +std::string ScriptParserBase::currentLocation() { + std::string Location; + getLocation(currentBuffer(), Tokens[Pos - 1], Location); + return Location; +} + MemoryBufferRef ScriptParserBase::currentBuffer() { // Find input buffer containing the current token. assert(!MBs.empty()); Index: test/ELF/linkerscript/alignof.s =================================================================== --- test/ELF/linkerscript/alignof.s +++ test/ELF/linkerscript/alignof.s @@ -23,7 +23,7 @@ # RUN: }" > %t.script # RUN: not ld.lld -o %t1 --script %t.script %t 2>&1 \ # RUN: | FileCheck -check-prefix=ERR %s -# ERR: undefined section .foo +# ERR: {{.*}}.script:1: undefined section .foo .global _start _start: nop Index: test/ELF/linkerscript/loadaddr.s =================================================================== --- test/ELF/linkerscript/loadaddr.s +++ test/ELF/linkerscript/loadaddr.s @@ -23,7 +23,7 @@ # CHECK-NEXT: 0000000000003000 *ABS* 00000000 ccc_lma # CHECK-NEXT: 0000000000004000 *ABS* 00000000 ddd_lma # CHECK-NEXT: 0000000000004008 *ABS* 00000000 txt_lma -# ERROR: undefined section .zzz +# ERROR: {{.*}}.script:1: undefined section .zzz .global _start _start: