Index: ELF/LinkerScript.h
===================================================================
--- ELF/LinkerScript.h
+++ ELF/LinkerScript.h
@@ -22,6 +22,7 @@
 class ScriptParser;
 template <class ELFT> class InputSectionBase;
 template <class ELFT> class OutputSectionBase;
+template <class ELFT> class SymbolTable;
 
 // This class represents each rule in SECTIONS command.
 class SectionRule {
@@ -42,14 +43,18 @@
 };
 
 // This enum represents what we can observe in SECTIONS tag of script:
-// ExprKind is a location counter change, like ". = . + 0x1000"
-// SectionKind is a description of output section, like ".data :..."
-enum SectionsCommandKind { ExprKind, SectionKind };
+// * ExprKind is a location counter change, like ". = . + 0x1000"
+// * SectionKind is a description of output section, like ".data :..."
+// * ContentKind is a content of output section, it helps to distinguish PROVIDE
+//   command before and after section content, first one should have address
+//   equal to address of output section, second points to location after that.
+// * ProvideKind is PROVIDE command.
+enum SectionsCommandKind { ExprKind, SectionKind, ContentKind, ProvideKind };
 
 struct SectionsCommand {
   SectionsCommandKind Kind;
   std::vector<StringRef> Expr;
-  StringRef SectionName;
+  StringRef Name;
 };
 
 // This is a runner of the linker script.
@@ -68,6 +73,9 @@
   template <class ELFT>
   void assignAddresses(std::vector<OutputSectionBase<ELFT> *> &S);
   int compareSections(StringRef A, StringRef B);
+  template <class ELFT>
+  void createSymbols(SymbolTable<ELFT> &Symtab,
+                     ArrayRef<OutputSectionBase<ELFT> *> Sections);
 
   bool DoLayout = false;
 
Index: ELF/LinkerScript.cpp
===================================================================
--- ELF/LinkerScript.cpp
+++ ELF/LinkerScript.cpp
@@ -172,7 +172,7 @@
 
 template <class ELFT>
 static OutputSectionBase<ELFT> *
-findSection(std::vector<OutputSectionBase<ELFT> *> &V, StringRef Name) {
+findSection(ArrayRef<OutputSectionBase<ELFT> *> V, StringRef Name) {
   for (OutputSectionBase<ELFT> *Sec : V)
     if (Sec->getName() == Name)
       return Sec;
@@ -192,8 +192,10 @@
   for (OutputSectionBase<ELFT> *Sec : Sections) {
     StringRef Name = Sec->getName();
     auto I = std::find(SectionOrder.begin(), SectionOrder.end(), Name);
-    if (I == SectionOrder.end())
+    if (I == SectionOrder.end()) {
       Commands.push_back({SectionKind, {}, Name});
+      Commands.push_back({ContentKind, {}, Name});
+    }
   }
 
   // Assign addresses as instructed by linker script SECTIONS sub-commands.
@@ -206,8 +208,10 @@
       VA = evaluate(Cmd.Expr, VA);
       continue;
     }
+    if (Cmd.Kind != ContentKind)
+      continue;
 
-    OutputSectionBase<ELFT> *Sec = findSection(Sections, Cmd.SectionName);
+    OutputSectionBase<ELFT> *Sec = findSection<ELFT>(Sections, Cmd.Name);
     if (!Sec)
       continue;
 
@@ -235,6 +239,40 @@
   return I->second;
 }
 
+template <class ELFT>
+void LinkerScript::createSymbols(SymbolTable<ELFT> &Symtab,
+                                 ArrayRef<OutputSectionBase<ELFT> *> Sections) {
+  typedef typename ELFT::uint uintX_t;
+  if (!Script->DoLayout)
+    return;
+
+  // Currently we support only PROVIDE keywords inside
+  // output sections descriptions that are used to mark
+  // begin and end of the section.
+  StringRef SecName;
+  uintX_t Val;
+  for (SectionsCommand &Cmd : Commands) {
+    if (Cmd.Kind == SectionKind) {
+      SecName = Cmd.Name;
+      Val = 0;
+    } else if (Cmd.Kind == ContentKind) {
+      Val = DefinedSynthetic<ELFT>::SectionEnd;
+    }
+
+    if (Cmd.Kind != ProvideKind)
+      continue;
+
+    OutputSectionBase<ELFT> *Sec = findSection(Sections, SecName);
+    if (!Sec)
+      continue;
+
+    StringRef SymName = Cmd.Name;
+    if (SymbolBody *S = Symtab.find(SymName))
+      if (S->isUndefined())
+        Symtab.addSynthetic(SymName, *Sec, Val);
+  }
+}
+
 // A compartor to sort output sections. Returns -1 or 1 if both
 // A and B are mentioned in linker scripts. Otherwise, returns 0
 // to use the default rule which is implemented in Writer.cpp.
@@ -300,6 +338,7 @@
   void readSections();
 
   void readLocationCounterValue();
+  void readProvide();
   void readOutputSectionDescription();
   void readSectionPatterns(StringRef OutSec, bool Keep);
 
@@ -464,6 +503,9 @@
   expect("{");
   while (!Error && !skip("}")) {
     StringRef Tok = peek();
+    if (Tok == "PROVIDE")
+      setError("PROVIDE outside section declaration not allowed");
+
     if (Tok == ".")
       readLocationCounterValue();
     else
@@ -473,6 +515,7 @@
 
 void ScriptParser::readSectionPatterns(StringRef OutSec, bool Keep) {
   expect("(");
+  Script->Commands.push_back({ContentKind, {}, OutSec});
   while (!Error && !skip(")"))
     Script->Sections.emplace_back(OutSec, next(), Keep);
 }
@@ -492,6 +535,27 @@
     error("error in location counter expression");
 }
 
+void ScriptParser::readProvide() {
+  expect("(");
+  Script->Commands.push_back({ProvideKind, {}, ""});
+  SectionsCommand &Cmd = Script->Commands.back();
+  Cmd.Name = next();
+
+  expect("=");
+  while (!Error) {
+    StringRef Tok = next();
+    if (Tok == ")")
+      break;
+    Cmd.Expr.push_back(Tok);
+  }
+  expect(";");
+
+  if (Cmd.Expr.empty())
+    error("empty provide expression");
+  else if (Cmd.Expr[0] != "." || Cmd.Expr.size() > 1)
+    error("PROVIDE does not support expressions");
+}
+
 void ScriptParser::readOutputSectionDescription() {
   StringRef OutSec = next();
   Script->SectionOrder.push_back(OutSec);
@@ -500,7 +564,9 @@
   expect("{");
   while (!Error && !skip("}")) {
     StringRef Tok = next();
-    if (Tok == "*") {
+    if (Tok == "PROVIDE") {
+      readProvide();
+    } else if (Tok == "*") {
       readSectionPatterns(OutSec, false);
     } else if (Tok == "KEEP") {
       expect("(");
@@ -561,3 +627,16 @@
 LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF64LE> *> &);
 template void
 LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF64BE> *> &);
+
+template void
+LinkerScript::createSymbols(SymbolTable<ELF32LE> &,
+                            ArrayRef<OutputSectionBase<ELF32LE> *> Sections);
+template void
+LinkerScript::createSymbols(SymbolTable<ELF32BE> &,
+                            ArrayRef<OutputSectionBase<ELF32BE> *> Sections);
+template void
+LinkerScript::createSymbols(SymbolTable<ELF64LE> &,
+                            ArrayRef<OutputSectionBase<ELF64LE> *> Sections);
+template void
+LinkerScript::createSymbols(SymbolTable<ELF64BE> &,
+                            ArrayRef<OutputSectionBase<ELF64BE> *> Sections);
Index: ELF/Writer.cpp
===================================================================
--- ELF/Writer.cpp
+++ ELF/Writer.cpp
@@ -1215,6 +1215,8 @@
   // Define __rel[a]_iplt_{start,end} symbols if needed.
   addRelIpltSymbols();
 
+  Script->createSymbols<ELFT>(Symtab, OutputSections);
+
   if (Out<ELFT>::EhFrameHdr->Sec)
     Out<ELFT>::EhFrameHdr->Sec->finalize();
 
Index: test/ELF/linkerscript-provide.s
===================================================================
--- test/ELF/linkerscript-provide.s
+++ test/ELF/linkerscript-provide.s
@@ -0,0 +1,96 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+## We do not support PROVIDE keyword outside
+## of output section declarations.
+# RUN: echo "SECTIONS \
+# RUN: { \
+# RUN:    PROVIDE (beginText = .); \
+# RUN:    .text : \
+# RUN:    { \
+# RUN:      *(.text) \
+# RUN:    } \
+# RUN: }" > %t.script
+# RUN: not ld.lld -o %t2 --script %t.script %t 2>&1 | FileCheck -check-prefix=ERR1 %s
+# ERR1: PROVIDE outside section declaration not allowed
+
+## We do not support PROVIDE keyword that
+## contains anything except assign of location counter.
+# RUN: echo "SECTIONS \
+# RUN: { \
+# RUN:    .text : \
+# RUN:    { \
+# RUN:      PROVIDE (beginText = . + 0x0); \
+# RUN:      *(.text) \
+# RUN:    } \
+# RUN: }" > %t.script
+# RUN: not ld.lld -o %t2 --script %t.script %t 2>&1 | FileCheck -check-prefix=ERR2 %s
+# ERR2: PROVIDE does not support expressions
+
+## Empty expression is a error.
+# RUN: echo "SECTIONS \
+# RUN: { \
+# RUN:    .text : \
+# RUN:    { \
+# RUN:      PROVIDE (beginText = ); \
+# RUN:      *(.text) \
+# RUN:    } \
+# RUN: }" > %t.script
+# RUN: not ld.lld -o %t2 --script %t.script %t 2>&1 | FileCheck -check-prefix=ERR3 %s
+# ERR3: empty provide expression
+
+## Check case with PROVIDE inside section description.
+# RUN: echo "SECTIONS \
+# RUN: { \
+# RUN:    .text : \
+# RUN:    { \
+# RUN:      PROVIDE (beginText = .); \
+# RUN:      *(.text) \
+# RUN:      PROVIDE (endText = .); \
+# RUN:    } \
+# RUN: }" > %t.script
+# RUN: ld.lld -o %t2 --script %t.script %t
+# RUN: llvm-readobj -sections -symbols %t2 | FileCheck %s
+# CHECK:       Sections [
+# CHECK:         Section {
+# CHECK:           Name: .text
+# CHECK-NEXT:      Type: SHT_PROGBITS
+# CHECK-NEXT:      Flags [
+# CHECK-NEXT:        SHF_ALLOC
+# CHECK-NEXT:        SHF_EXECINSTR
+# CHECK-NEXT:      ]
+# CHECK-NEXT:      Address: 0x[[ADDR:.*]]
+# CHECK-NEXT:      Offset:
+# CHECK-NEXT:      Size: 10
+# CHECK-NEXT:      Link: 0
+# CHECK-NEXT:      Info: 0
+# CHECK-NEXT:      AddressAlignment: 4
+# CHECK-NEXT:      EntrySize: 0
+# CHECK-NEXT:    }
+# CHECK:       Symbol {
+# CHECK:          Name: beginText
+# CHECK-NEXT:     Value: 0x[[ADDR]]
+# CHECK-NEXT:     Size: 0
+# CHECK-NEXT:     Binding: Local
+# CHECK-NEXT:     Type: None
+# CHECK-NEXT:     Other [
+# CHECK-NEXT:       STV_HIDDEN
+# CHECK-NEXT:     ]
+# CHECK-NEXT:     Section: .text
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Name: endText
+# CHECK-NEXT:     Value: 0x12A
+# CHECK-NEXT:     Size: 0
+# CHECK-NEXT:     Binding: Local
+# CHECK-NEXT:     Type: None
+# CHECK-NEXT:     Other [
+# CHECK-NEXT:       STV_HIDDEN
+# CHECK-NEXT:     ]
+# CHECK-NEXT:     Section: .text
+# CHECK-NEXT:   }
+
+.globl _start
+_start:
+  call beginText
+  call endText