Index: ELF/Config.h
===================================================================
--- ELF/Config.h
+++ ELF/Config.h
@@ -101,6 +101,7 @@
   bool Demangle = true;
   bool DisableVerify;
   bool EhFrameHdr;
+  bool EmitRelocs;
   bool EnableNewDtags;
   bool ExportDynamic;
   bool FatalWarnings;
Index: ELF/Driver.cpp
===================================================================
--- ELF/Driver.cpp
+++ ELF/Driver.cpp
@@ -163,6 +163,10 @@
       error("attempted static link of dynamic object " + Path);
       return;
     }
+    if (Config->EmitRelocs) {
+      error("--emit-reloc does not allow link against dynamic object " + Path);
+      return;
+    }
     Files.push_back(createSharedFile(MBRef));
     return;
   default:
@@ -220,6 +224,9 @@
     if (Config->Pie)
       error("-r and -pie may not be used together");
   }
+
+  if (Config->EmitRelocs && Config->Pic)
+    error("-pie/-shared and --emit-relocs may not be used together");
 }
 
 static StringRef getString(opt::InputArgList &Args, unsigned Key,
@@ -482,6 +489,7 @@
   Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions);
   Config->Demangle = getArg(Args, OPT_demangle, OPT_no_demangle, true);
   Config->DisableVerify = Args.hasArg(OPT_disable_verify);
+  Config->EmitRelocs = Args.hasArg(OPT_emit_relocs);
   Config->EhFrameHdr = Args.hasArg(OPT_eh_frame_hdr);
   Config->EnableNewDtags = !Args.hasArg(OPT_disable_new_dtags);
   Config->ExportDynamic = Args.hasArg(OPT_export_dynamic);
Index: ELF/InputFiles.cpp
===================================================================
--- ELF/InputFiles.cpp
+++ ELF/InputFiles.cpp
@@ -399,6 +399,10 @@
     }
     assert(isUInt<31>(NumRelocations));
     Target->NumRelocations = NumRelocations;
+
+    if (Config->EmitRelocs)
+      return make<InputSection<ELFT>>(this, &Sec, Name);
+
     return nullptr;
   }
   }
Index: ELF/InputSection.cpp
===================================================================
--- ELF/InputSection.cpp
+++ ELF/InputSection.cpp
@@ -250,7 +250,8 @@
 
     if (Config->Rela)
       P->r_addend = getAddend<ELFT>(Rel);
-    P->r_offset = RelocatedSection->getOffset(Rel.r_offset);
+    P->r_offset = RelocatedSection->OutSec->Addr +
+                  RelocatedSection->getOffset(Rel.r_offset);
     P->setSymbolAndType(Body.DynsymIndex, Type, Config->Mips64EL);
   }
 }
@@ -533,7 +534,8 @@
     return;
   }
 
-  // If -r is given, then an InputSection may be a relocation section.
+  // If -r or --emit-relocs is given, then an InputSection
+  // may be a relocation section.
   if (this->Type == SHT_RELA) {
     copyRelocations(Buf + OutSecOff, this->template getDataAs<Elf_Rela>());
     return;
Index: ELF/Options.td
===================================================================
--- ELF/Options.td
+++ ELF/Options.td
@@ -65,6 +65,8 @@
 def eh_frame_hdr: F<"eh-frame-hdr">,
   HelpText<"Request creation of .eh_frame_hdr section and PT_GNU_EH_FRAME segment header">;
 
+def emit_relocs: F<"emit-relocs">, HelpText<"Generate relocations in output">;
+
 def enable_new_dtags: F<"enable-new-dtags">,
   HelpText<"Enable new dynamic tags">;
 
@@ -258,6 +260,7 @@
 def alias_discard_all_x: Flag<["-"], "x">, Alias<discard_all>;
 def alias_discard_locals_X: Flag<["-"], "X">, Alias<discard_locals>;
 def alias_dynamic_list: J<"dynamic-list=">, Alias<dynamic_list>;
+def alias_emit_relocs: Flag<["-"], "q">, Alias<emit_relocs>;
 def alias_entry_e: JoinedOrSeparate<["-"], "e">, Alias<entry>;
 def alias_entry_entry: J<"entry=">, Alias<entry>;
 def alias_error_limit: J<"error-limit=">, Alias<error_limit>;
Index: ELF/OutputSections.cpp
===================================================================
--- ELF/OutputSections.cpp
+++ ELF/OutputSections.cpp
@@ -116,7 +116,8 @@
   }
 
   uint32_t Type = this->Type;
-  if (!Config->Relocatable || (Type != SHT_RELA && Type != SHT_REL))
+  if ((!Config->Relocatable && !Config->EmitRelocs) ||
+      (Type != SHT_RELA && Type != SHT_REL))
     return;
 
   this->Link = In<ELFT>::SymTab->OutSec->SectionIndex;
Index: ELF/SyntheticSections.cpp
===================================================================
--- ELF/SyntheticSections.cpp
+++ ELF/SyntheticSections.cpp
@@ -1065,11 +1065,15 @@
   this->OutSec->Info = this->Info = NumLocals + 1;
   this->OutSec->Entsize = this->Entsize;
 
-  if (Config->Relocatable) {
+  // When -r or --emit-relocs is specified, we use DynsymIndex
+  // to store symbol index in .symtab section. It is safe because
+  // .dynsym is not exist in that cases.
+  if (Config->Relocatable || Config->EmitRelocs) {
     size_t I = NumLocals;
     for (const SymbolTableEntry &S : Symbols)
       S.Symbol->DynsymIndex = ++I;
-    return;
+    if (Config->Relocatable)
+      return;
   }
 
   if (!StrTabSec.isDynamic()) {
Index: ELF/Writer.cpp
===================================================================
--- ELF/Writer.cpp
+++ ELF/Writer.cpp
@@ -385,9 +385,9 @@
   if (B.isFile())
     return false;
 
-  // We keep sections in symtab for relocatable output.
+  // We keep sections in symtab for relocatable output and --emit-reloc.
   if (B.isSection())
-    return Config->Relocatable;
+    return Config->Relocatable || Config->EmitRelocs;
 
   // If sym references a section in a discarded group, don't keep it.
   if (Sec == &InputSection<ELFT>::Discarded)
@@ -456,7 +456,7 @@
       if (!shouldKeepInSymtab<ELFT>(Sec, B->getName(), *B))
         continue;
       ++In<ELFT>::SymTab->NumLocals;
-      if (Config->Relocatable)
+      if (Config->Relocatable || Config->EmitRelocs)
         B->DynsymIndex = In<ELFT>::SymTab->NumLocals;
       F->KeptLocalSyms.push_back(std::make_pair(
           DR, In<ELFT>::SymTab->StrTabSec.addString(B->getName())));
Index: test/ELF/Inputs/emit-relocs.s
===================================================================
--- test/ELF/Inputs/emit-relocs.s
+++ test/ELF/Inputs/emit-relocs.s
@@ -0,0 +1,10 @@
+.section .text
+.globl fn2
+.type fn2,@function
+fn2:
+ nop
+
+foo:
+  movl $foo, %edx
+  callq fn2@PLT
+  nop
Index: test/ELF/emit-relocs.s
===================================================================
--- test/ELF/emit-relocs.s
+++ test/ELF/emit-relocs.s
@@ -0,0 +1,98 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/emit-relocs.s -o %t2.o
+# RUN: ld.lld --emit-relocs %t1.o %t2.o -o %t
+# RUN: llvm-readobj -t -r %t | FileCheck %s
+
+## Check single dash form.
+# RUN: ld.lld -emit-relocs %t1.o %t2.o -o %t1
+# RUN: llvm-readobj -t -r %t1 | FileCheck %s
+
+## Check alias.
+# RUN: ld.lld -q %t1.o %t2.o -o %t2
+# RUN: llvm-readobj -t -r %t2 | FileCheck %s
+
+# CHECK:      Relocations [
+# CHECK-NEXT:   Section ({{.*}}) .rela.text {
+# CHECK-NEXT:     0x201002 R_X86_64_32 .text 0x1
+# CHECK-NEXT:     0x201007 R_X86_64_PLT32 fn 0xFFFFFFFFFFFFFFFC
+# CHECK-NEXT:     0x20100E R_X86_64_32 .text 0x1
+# CHECK-NEXT:     0x201013 R_X86_64_PLT32 fn2 0xFFFFFFFFFFFFFFFC
+# CHECK-NEXT:   }
+# CHECK-NEXT: ]
+# CHECK-NEXT: Symbols [
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Name:
+# CHECK-NEXT:     Value: 0x0
+# CHECK-NEXT:     Size: 0
+# CHECK-NEXT:     Binding: Local
+# CHECK-NEXT:     Type: None
+# CHECK-NEXT:     Other: 0
+# CHECK-NEXT:     Section: Undefined
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Name: bar
+# CHECK-NEXT:     Value: 0x201001
+# CHECK-NEXT:     Size: 0
+# CHECK-NEXT:     Binding: Local
+# CHECK-NEXT:     Type: None
+# CHECK-NEXT:     Other: 0
+# CHECK-NEXT:     Section: .text
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Name:
+# CHECK-NEXT:     Value: 0x201000
+# CHECK-NEXT:     Size: 0
+# CHECK-NEXT:     Binding: Local
+# CHECK-NEXT:     Type: Section
+# CHECK-NEXT:     Other: 0
+# CHECK-NEXT:     Section: .text
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Name: foo
+# CHECK-NEXT:     Value: 0x20100D
+# CHECK-NEXT:     Size: 0
+# CHECK-NEXT:     Binding: Local
+# CHECK-NEXT:     Type: None
+# CHECK-NEXT:     Other: 0
+# CHECK-NEXT:     Section: .text
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Name:
+# CHECK-NEXT:     Value: 0x20100C
+# CHECK-NEXT:     Size: 0
+# CHECK-NEXT:     Binding: Local
+# CHECK-NEXT:     Type: Section
+# CHECK-NEXT:     Other: 0
+# CHECK-NEXT:     Section: .text
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Name: fn
+# CHECK-NEXT:     Value: 0x201000
+# CHECK-NEXT:     Size: 0
+# CHECK-NEXT:     Binding: Global
+# CHECK-NEXT:     Type: Function
+# CHECK-NEXT:     Other: 0
+# CHECK-NEXT:     Section: .text
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Name: fn2
+# CHECK-NEXT:     Value: 0x20100C
+# CHECK-NEXT:     Size: 0
+# CHECK-NEXT:     Binding: Global
+# CHECK-NEXT:     Type: Function
+# CHECK-NEXT:     Other: 0
+# CHECK-NEXT:     Section: .text
+# CHECK-NEXT:   }
+# CHECK-NEXT: ]
+
+.section .text
+.globl fn
+.type fn,@function
+fn:
+ nop
+
+bar:
+  movl $bar, %edx
+  callq fn@PLT
+  nop