[ELF] Print file:line for 'undefined section' errors

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

llvm-svn: 288019
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index feafd37..07497f4 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -884,13 +884,15 @@
 }
 
 template <class ELFT>
-const OutputSectionBase *LinkerScript<ELFT>::getOutputSection(StringRef Name) {
+const OutputSectionBase *LinkerScript<ELFT>::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;
 }
 
@@ -1697,6 +1699,7 @@
     return readParenExpr();
 
   StringRef Tok = next();
+  std::string Location = currentLocation();
 
   if (Tok == "~") {
     Expr E = readPrimary();
@@ -1711,15 +1714,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")
@@ -1776,7 +1780,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")
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index d6dae4d..f2d49a8 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/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<OutputSectionBase *> *OutputSections;
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 33c2f90..fc0d233 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -172,6 +172,13 @@
     setError(Expect + " expected, but got " + Tok);
 }
 
+std::string ScriptParserBase::currentLocation() {
+  MemoryBufferRef MB = currentBuffer();
+  return (MB.getBufferIdentifier() + ":" +
+          Twine(getPos(MB.getBuffer(), Tokens[Pos - 1]).first))
+      .str();
+}
+
 // Returns true if string 'Bigger' contains string 'Shorter'.
 static bool containsString(StringRef Bigger, StringRef Shorter) {
   const char *BiggerEnd = Bigger.data() + Bigger.size();
diff --git a/lld/ELF/ScriptParser.h b/lld/ELF/ScriptParser.h
index 6c314a4..a0da48d 100644
--- a/lld/ELF/ScriptParser.h
+++ b/lld/ELF/ScriptParser.h
@@ -32,6 +32,7 @@
   void skip();
   bool consume(StringRef Tok);
   void expect(StringRef Expect);
+  std::string currentLocation();
 
   std::vector<MemoryBufferRef> MBs;
   std::vector<StringRef> Tokens;
diff --git a/lld/test/ELF/linkerscript/alignof.s b/lld/test/ELF/linkerscript/alignof.s
index f530abd..8880634 100644
--- a/lld/test/ELF/linkerscript/alignof.s
+++ b/lld/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
diff --git a/lld/test/ELF/linkerscript/loadaddr.s b/lld/test/ELF/linkerscript/loadaddr.s
index 870d694..33c5f21 100644
--- a/lld/test/ELF/linkerscript/loadaddr.s
+++ b/lld/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: