Index: ELF/Config.h
===================================================================
--- ELF/Config.h
+++ ELF/Config.h
@@ -54,6 +54,7 @@
   bool AsNeeded = false;
   bool Bsymbolic;
   bool BsymbolicFunctions;
+  bool BuildId;
   bool Demangle = true;
   bool DiscardAll;
   bool DiscardLocals;
Index: ELF/Driver.cpp
===================================================================
--- ELF/Driver.cpp
+++ ELF/Driver.cpp
@@ -223,6 +223,7 @@
   Config->AllowMultipleDefinition = Args.hasArg(OPT_allow_multiple_definition);
   Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic);
   Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions);
+  Config->BuildId = Args.hasArg(OPT_build_id);
   Config->Demangle = !Args.hasArg(OPT_no_demangle);
   Config->DiscardAll = Args.hasArg(OPT_discard_all);
   Config->DiscardLocals = Args.hasArg(OPT_discard_locals);
Index: ELF/Options.td
===================================================================
--- ELF/Options.td
+++ ELF/Options.td
@@ -12,6 +12,9 @@
 def Bstatic: Flag<["-"], "Bstatic">,
   HelpText<"Do not link against shared libraries">;
 
+def build_id : Flag<["--", "-"], "build-id">,
+  HelpText<"Generate build ID note">;
+
 def L : JoinedOrSeparate<["-"], "L">, MetaVarName<"
">,
   HelpText<"Directory to search for libraries">;
 
@@ -172,7 +175,6 @@
 def start_group_paren: Flag<["-"], "(">;
 
 // Options listed below are silently ignored for now for compatibility.
-def build_id : Flag<["--"], "build-id">;
 def fatal_warnings : Flag<["--"], "fatal-warnings">;
 def no_add_needed : Flag<["--"], "no-add-needed">;
 def no_fatal_warnings : Flag<["--"], "no-fatal-warnings">;
Index: ELF/OutputSections.h
===================================================================
--- ELF/OutputSections.h
+++ ELF/OutputSections.h
@@ -511,12 +511,26 @@
   std::vector FdeList;
 };
 
+template 
+class BuildIdSection final : public OutputSectionBase {
+public:
+  BuildIdSection();
+  void writeTo(uint8_t *Buf) override;
+  void update(ArrayRef Buf);
+  void writeBuildId();
+
+private:
+  uint64_t Hash = 0xcbf29ce484222325; // FNV1 hash basis
+  uint8_t *HashBuf;
+};
+
 // All output sections that are hadnled by the linker specially are
 // globally accessible. Writer initializes them, so don't use them
 // until Writer is initialized.
 template  struct Out {
   typedef typename llvm::object::ELFFile::uintX_t uintX_t;
   typedef typename llvm::object::ELFFile::Elf_Phdr Elf_Phdr;
+  static BuildIdSection *BuildId;
   static DynamicSection *Dynamic;
   static EhFrameHeader *EhFrameHdr;
   static GnuHashTableSection *GnuHashTab;
@@ -541,6 +555,7 @@
   static OutputSectionBase *ProgramHeaders;
 };
 
+template  BuildIdSection *Out::BuildId;
 template  DynamicSection *Out::Dynamic;
 template  EhFrameHeader *Out::EhFrameHdr;
 template  GnuHashTableSection *Out::GnuHashTab;
Index: ELF/OutputSections.cpp
===================================================================
--- ELF/OutputSections.cpp
+++ ELF/OutputSections.cpp
@@ -1530,6 +1530,36 @@
 }
 
 template 
+BuildIdSection::BuildIdSection()
+    : OutputSectionBase(".note.gnu.build-id", SHT_NOTE, 0) {
+  // 16 bytes for the note section header and 8 bytes for FNV1 hash.
+  this->Header.sh_size = 24;
+}
+
+template  void BuildIdSection::writeTo(uint8_t *Buf) {
+  const endianness E = ELFT::TargetEndianness;
+  write32(Buf, 4);                // Name size
+  write32(Buf + 4, sizeof(Hash)); // Content size
+  write32(Buf + 8, 3);            // Type (NT_GNU_BUILD_ID = 3)
+  memcpy(Buf + 12, "GNU", 4);        // Name string
+  HashBuf = Buf + 16;
+}
+
+template  void BuildIdSection::update(ArrayRef Buf) {
+  // 64-bit FNV1 hash
+  const uint64_t Prime = 0x100000001b3;
+  for (uint8_t B : Buf) {
+    Hash *= Prime;
+    Hash ^= B;
+  }
+}
+
+template  void BuildIdSection::writeBuildId() {
+  const endianness E = ELFT::TargetEndianness;
+  write64(HashBuf, Hash);
+}
+
+template 
 MipsReginfoOutputSection::MipsReginfoOutputSection()
     : OutputSectionBase(".reginfo", SHT_MIPS_REGINFO, SHF_ALLOC) {
   this->Header.sh_addralign = 4;
@@ -1632,5 +1662,10 @@
 template class SymbolTableSection;
 template class SymbolTableSection;
 template class SymbolTableSection;
+
+template class BuildIdSection;
+template class BuildIdSection;
+template class BuildIdSection;
+template class BuildIdSection;
 }
 }
Index: ELF/Writer.cpp
===================================================================
--- ELF/Writer.cpp
+++ ELF/Writer.cpp
@@ -75,6 +75,7 @@
   bool openFile();
   void writeHeader();
   void writeSections();
+  void writeBuildId();
   bool isDiscarded(InputSectionBase *IS) const;
   StringRef getOutputSectionName(InputSectionBase *S) const;
   bool needsInterpSection() const {
@@ -143,6 +144,7 @@
   ProgramHeaders.updateAlign(sizeof(uintX_t));
 
   // Instantiate optional output sections if they are needed.
+  std::unique_ptr> BuildId;
   std::unique_ptr> GnuHashTab;
   std::unique_ptr> GotPlt;
   std::unique_ptr> HashTab;
@@ -151,6 +153,8 @@
   std::unique_ptr> SymTabSec;
   std::unique_ptr> MipsRldMap;
 
+  if (Config->BuildId)
+    BuildId.reset(new BuildIdSection);
   if (Config->GnuHash)
     GnuHashTab.reset(new GnuHashTableSection);
   if (Config->SysvHash)
@@ -175,6 +179,7 @@
     MipsRldMap->updateAlign(sizeof(uintX_t));
   }
 
+  Out::BuildId = BuildId.get();
   Out::DynStrTab = &DynStrTab;
   Out::DynSymTab = &DynSymTab;
   Out::Dynamic = &Dynamic;
@@ -219,6 +224,7 @@
     return;
   writeHeader();
   writeSections();
+  writeBuildId();
   if (HasError)
     return;
   check(Buffer->commit());
@@ -1113,6 +1119,7 @@
 
   // This order is not the same as the final output order
   // because we sort the sections using their attributes below.
+  Add(Out::BuildId);
   Add(Out::SymTab);
   Add(Out::ShStrTab);
   Add(Out::StrTab);
@@ -1531,6 +1538,29 @@
       Sec->writeTo(Buf + Sec->getFileOff());
 }
 
+template  void Writer::writeBuildId() {
+  BuildIdSection *S = Out::BuildId;
+  if (!S)
+    return;
+
+  // Compute a hash of all sections except .debug_* sections.
+  // We skip debug sections because they tend to be very large
+  // and their contents are very likely to be the same as long as
+  // other sections are the same.
+  uint8_t *Start = Buffer->getBufferStart();
+  uint8_t *Last = Start;
+  for (OutputSectionBase *Sec : OutputSections) {
+    uint8_t *End = Start + Sec->getFileOff();
+    if (!Sec->getName().startswith(".debug_"))
+      S->update({Last, End});
+    Last = End;
+  }
+  S->update({Last, Start + FileSize});
+
+  // Fill the hash value field in the .note.gnu.build-id section.
+  S->writeBuildId();
+}
+
 template void elf::writeResult(SymbolTable *Symtab);
 template void elf::writeResult(SymbolTable *Symtab);
 template void elf::writeResult(SymbolTable *Symtab);
Index: test/ELF/build-id.s
===================================================================
--- /dev/null
+++ test/ELF/build-id.s
@@ -0,0 +1,16 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld --build-id %t -o %t2
+# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=BUILDID %s
+# RUN: ld.lld %t -o %t2
+# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=NO-BUILDID %s
+
+.globl _start;
+_start:
+  nop
+
+# BUILDID:      Contents of section .note.gnu.build-id:
+# BUILDID-NEXT: 0000 04000000 08000000 03000000 474e5500  ............GNU.
+
+# NO-BUILDID-NOT: Contents of section .note.gnu.build-id: