<div dir="ltr">I believe that the resulting object files with this patch contains some linker-synthesized symbols such as __init_array_start or __start_<section-name>. Is this expected?</div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Feb 25, 2016 at 12:23 AM, George Rimar via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: grimar<br>
Date: Thu Feb 25 02:23:37 2016<br>
New Revision: 261838<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=261838&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=261838&view=rev</a><br>
Log:<br>
[ELF2] - Basic implementation of -r/--relocatable<br>
<br>
-r, -relocatable - Generate relocatable output<br>
<br>
Currently does not have support for files containing<br>
relocation sections with entries that refer to local<br>
symbols (like rel[a].eh_frame which refer to sections<br>
and not to symbols)<br>
<br>
Differential revision: <a href="http://reviews.llvm.org/D14382" rel="noreferrer" target="_blank">http://reviews.llvm.org/D14382</a><br>
<br>
Added:<br>
    lld/trunk/test/ELF/Inputs/relocatable.s<br>
    lld/trunk/test/ELF/Inputs/relocatable2.s<br>
Modified:<br>
    lld/trunk/ELF/Config.h<br>
    lld/trunk/ELF/Driver.cpp<br>
    lld/trunk/ELF/InputFiles.cpp<br>
    lld/trunk/ELF/InputSection.cpp<br>
    lld/trunk/ELF/InputSection.h<br>
    lld/trunk/ELF/Options.td<br>
    lld/trunk/ELF/OutputSections.cpp<br>
    lld/trunk/ELF/OutputSections.h<br>
    lld/trunk/ELF/Writer.cpp<br>
    lld/trunk/test/ELF/relocatable.s<br>
    lld/trunk/test/ELF/strip-all.s<br>
<br>
Modified: lld/trunk/ELF/Config.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=261838&r1=261837&r2=261838&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=261838&r1=261837&r2=261838&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Config.h (original)<br>
+++ lld/trunk/ELF/Config.h Thu Feb 25 02:23:37 2016<br>
@@ -67,6 +67,7 @@ struct Configuration {<br>
   bool NoInhibitExec;<br>
   bool NoUndefined;<br>
   bool PrintGcSections;<br>
+  bool Relocatable;<br>
   bool Shared;<br>
   bool Static = false;<br>
   bool StripAll;<br>
<br>
Modified: lld/trunk/ELF/Driver.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=261838&r1=261837&r2=261838&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=261838&r1=261837&r2=261838&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Driver.cpp (original)<br>
+++ lld/trunk/ELF/Driver.cpp Thu Feb 25 02:23:37 2016<br>
@@ -111,6 +111,10 @@ void LinkerDriver::addFile(StringRef Pat<br>
     Files.push_back(make_unique<ArchiveFile>(MBRef));<br>
     return;<br>
   case file_magic::elf_shared_object:<br>
+    if (Config->Relocatable) {<br>
+      error("Attempted static link of dynamic object " + Path);<br>
+      return;<br>
+    }<br>
     Files.push_back(createSharedFile(MBRef));<br>
     return;<br>
   default:<br>
@@ -130,12 +134,6 @@ void LinkerDriver::addLibrary(StringRef<br>
 // Some command line options or some combinations of them are not allowed.<br>
 // This function checks for such errors.<br>
 static void checkOptions(opt::InputArgList &Args) {<br>
-  // Traditional linkers can generate re-linkable object files instead<br>
-  // of executables or DSOs. We don't support that since the feature<br>
-  // does not seem to provide more value than the static archiver.<br>
-  if (Args.hasArg(OPT_relocatable))<br>
-    error("-r option is not supported. Use 'ar' command instead.");<br>
-<br>
   // The MIPS ABI as of 2016 does not support the GNU-style symbol lookup<br>
   // table which is a relatively new feature.<br>
   if (Config->EMachine == EM_MIPS && Config->GnuHash)<br>
@@ -143,6 +141,9 @@ static void checkOptions(opt::InputArgLi<br>
<br>
   if (Config->EMachine == EM_AMDGPU && !Config->Entry.empty())<br>
     error("-e option is not valid for AMDGPU.");<br>
+<br>
+  if (Config->Relocatable && Config->Shared)<br>
+    error("-r and -shared may not be used together");<br>
 }<br>
<br>
 static StringRef<br>
@@ -219,6 +220,7 @@ void LinkerDriver::readConfigs(opt::Inpu<br>
   Config->NoInhibitExec = Args.hasArg(OPT_noinhibit_exec);<br>
   Config->NoUndefined = Args.hasArg(OPT_no_undefined);<br>
   Config->PrintGcSections = Args.hasArg(OPT_print_gc_sections);<br>
+  Config->Relocatable = Args.hasArg(OPT_relocatable);<br>
   Config->Shared = Args.hasArg(OPT_shared);<br>
   Config->StripAll = Args.hasArg(OPT_strip_all);<br>
   Config->Verbose = Args.hasArg(OPT_verbose);<br>
@@ -237,6 +239,9 @@ void LinkerDriver::readConfigs(opt::Inpu<br>
   Config->ZOrigin = hasZOption(Args, "origin");<br>
   Config->ZRelro = !hasZOption(Args, "norelro");<br>
<br>
+  if (Config->Relocatable)<br>
+    Config->StripAll = false;<br>
+<br>
   if (auto *Arg = Args.getLastArg(OPT_O)) {<br>
     StringRef Val = Arg->getValue();<br>
     if (Val.getAsInteger(10, Config->Optimize))<br>
@@ -303,7 +308,7 @@ template <class ELFT> void LinkerDriver:<br>
   std::unique_ptr<TargetInfo> TI(createTarget());<br>
   Target = TI.get();<br>
<br>
-  if (!Config->Shared) {<br>
+  if (!Config->Shared && !Config->Relocatable) {<br>
     // Add entry symbol.<br>
     //<br>
     // There is no entry symbol for AMDGPU binaries, so skip adding one to avoid<br>
<br>
Modified: lld/trunk/ELF/InputFiles.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=261838&r1=261837&r2=261838&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=261838&r1=261837&r2=261838&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/InputFiles.cpp (original)<br>
+++ lld/trunk/ELF/InputFiles.cpp Thu Feb 25 02:23:37 2016<br>
@@ -226,7 +226,10 @@ void elf2::ObjectFile<ELFT>::initializeS<br>
         continue;<br>
       if (!RelocatedSection)<br>
         fatal("Unsupported relocation reference");<br>
-      if (auto *S = dyn_cast<InputSection<ELFT>>(RelocatedSection)) {<br>
+      if (Config->Relocatable) {<br>
+        // For -r, relocation sections are handled as regular input sections.<br>
+        Sections[I] = new (Alloc) InputSection<ELFT>(this, &Sec);<br>
+      } else if (auto *S = dyn_cast<InputSection<ELFT>>(RelocatedSection)) {<br>
         S->RelocSections.push_back(&Sec);<br>
       } else if (auto *S = dyn_cast<EHInputSection<ELFT>>(RelocatedSection)) {<br>
         if (S->RelocSection)<br>
<br>
Modified: lld/trunk/ELF/InputSection.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=261838&r1=261837&r2=261838&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=261838&r1=261837&r2=261838&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/InputSection.cpp (original)<br>
+++ lld/trunk/ELF/InputSection.cpp Thu Feb 25 02:23:37 2016<br>
@@ -105,6 +105,43 @@ bool InputSection<ELFT>::classof(const I<br>
 }<br>
<br>
 template <class ELFT><br>
+InputSectionBase<ELFT> *InputSection<ELFT>::getRelocatedSection() {<br>
+  assert(this->Header->sh_type == SHT_RELA || this->Header->sh_type == SHT_REL);<br>
+  ArrayRef<InputSectionBase<ELFT> *> Sections = this->File->getSections();<br>
+  return Sections[this->Header->sh_info];<br>
+}<br>
+<br>
+// This is used for -r. We can't use memcpy to copy relocations because we need<br>
+// to update symbol table offset and section index for each relocation. So we<br>
+// copy relocations one by one.<br>
+template <class ELFT><br>
+template <bool isRela><br>
+void InputSection<ELFT>::copyRelocations(uint8_t *Buf,<br>
+                                         RelIteratorRange<isRela> Rels) {<br>
+  typedef Elf_Rel_Impl<ELFT, isRela> RelType;<br>
+  InputSectionBase<ELFT> *RelocatedSection = getRelocatedSection();<br>
+<br>
+  for (const RelType &Rel : Rels) {<br>
+    uint32_t SymIndex = Rel.getSymbol(Config->Mips64EL);<br>
+    uint32_t Type = Rel.getType(Config->Mips64EL);<br>
+    const Elf_Shdr *SymTab = this->File->getSymbolTable();<br>
+<br>
+    RelType *P = reinterpret_cast<RelType *>(Buf);<br>
+    Buf += sizeof(RelType);<br>
+<br>
+    // Relocation for local symbol here means that it is probably<br>
+    // rel[a].eh_frame section which has references to<br>
+    // sections in r_info field. Also needs fix for addend.<br>
+    if (SymIndex < SymTab->sh_info)<br>
+      fatal("Relocation against local symbols is not supported yet");<br>
+<br>
+    SymbolBody *Body = this->File->getSymbolBody(SymIndex)->repl();<br>
+    P->r_offset = RelocatedSection->getOffset(Rel.r_offset);<br>
+    P->setSymbolAndType(Body->DynsymIndex, Type, Config->Mips64EL);<br>
+  }<br>
+}<br>
+<br>
+template <class ELFT><br>
 template <bool isRela><br>
 uint8_t *<br>
 InputSectionBase<ELFT>::findMipsPairedReloc(uint8_t *Buf, uint32_t SymIndex,<br>
@@ -256,9 +293,21 @@ template <class ELFT> void InputSection<<br>
     return;<br>
   // Copy section contents from source object file to output file.<br>
   ArrayRef<uint8_t> Data = this->getSectionData();<br>
+  ELFFile<ELFT> &EObj = this->File->getObj();<br>
+<br>
+  // That happens with -r. In that case we need fix the relocation position and<br>
+  // target. No relocations are applied.<br>
+  if (this->Header->sh_type == SHT_RELA) {<br>
+    this->copyRelocations(Buf + OutSecOff, EObj.relas(this->Header));<br>
+    return;<br>
+  }<br>
+  if (this->Header->sh_type == SHT_REL) {<br>
+    this->copyRelocations(Buf + OutSecOff, EObj.rels(this->Header));<br>
+    return;<br>
+  }<br>
+<br>
   memcpy(Buf + OutSecOff, Data.data(), Data.size());<br>
<br>
-  ELFFile<ELFT> &EObj = this->File->getObj();<br>
   uint8_t *BufEnd = Buf + OutSecOff + Data.size();<br>
   // Iterate over all relocation sections that apply to this section.<br>
   for (const Elf_Shdr *RelSec : this->RelocSections) {<br>
<br>
Modified: lld/trunk/ELF/InputSection.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=261838&r1=261837&r2=261838&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=261838&r1=261837&r2=261838&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/InputSection.h (original)<br>
+++ lld/trunk/ELF/InputSection.h Thu Feb 25 02:23:37 2016<br>
@@ -158,6 +158,16 @@ public:<br>
   uint64_t OutSecOff = 0;<br>
<br>
   static bool classof(const InputSectionBase<ELFT> *S);<br>
+<br>
+  InputSectionBase<ELFT> *getRelocatedSection();<br>
+<br>
+private:<br>
+  template <bool isRela><br>
+  using RelIteratorRange =<br>
+      llvm::iterator_range<const llvm::object::Elf_Rel_Impl<ELFT, isRela> *>;<br>
+<br>
+  template <bool isRela><br>
+  void copyRelocations(uint8_t *Buf, RelIteratorRange<isRela> Rels);<br>
 };<br>
<br>
 // MIPS .reginfo section provides information on the registers used by the code<br>
<br>
Modified: lld/trunk/ELF/Options.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=261838&r1=261837&r2=261838&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=261838&r1=261837&r2=261838&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Options.td (original)<br>
+++ lld/trunk/ELF/Options.td Thu Feb 25 02:23:37 2016<br>
@@ -94,7 +94,8 @@ def print_gc_sections: Flag<["--"], "pri<br>
 def rpath : Separate<["-"], "rpath">,<br>
   HelpText<"Add a DT_RUNPATH to the output">;<br>
<br>
-def relocatable : Flag<["--"], "relocatable">;<br>
+def relocatable : Flag<["--"], "relocatable">,<br>
+  HelpText<"Create relocatable object file">;<br>
<br>
 def script : Separate<["--"], "script">, HelpText<"Read linker script">;<br>
<br>
<br>
Modified: lld/trunk/ELF/OutputSections.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=261838&r1=261837&r2=261838&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=261838&r1=261837&r2=261838&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/OutputSections.cpp (original)<br>
+++ lld/trunk/ELF/OutputSections.cpp Thu Feb 25 02:23:37 2016<br>
@@ -728,9 +728,24 @@ template <class ELFT> void EhFrameHeader<br>
 }<br>
<br>
 template <class ELFT><br>
-OutputSection<ELFT>::OutputSection(StringRef Name, uint32_t Type,<br>
-                                   uintX_t Flags)<br>
-    : OutputSectionBase<ELFT>(Name, Type, Flags) {}<br>
+OutputSection<ELFT>::OutputSection(StringRef Name, uint32_t Type, uintX_t Flags)<br>
+    : OutputSectionBase<ELFT>(Name, Type, Flags) {<br>
+  if (Type == SHT_RELA)<br>
+    this->Header.sh_entsize = sizeof(Elf_Rela);<br>
+  else if (Type == SHT_REL)<br>
+    this->Header.sh_entsize = sizeof(Elf_Rel);<br>
+}<br>
+<br>
+template <class ELFT> void OutputSection<ELFT>::finalize() {<br>
+  uint32_t Type = this->Header.sh_type;<br>
+  if (Type != SHT_RELA && Type != SHT_REL)<br>
+    return;<br>
+  this->Header.sh_link = Out<ELFT>::SymTab->SectionIndex;<br>
+  // sh_info for SHT_REL[A] sections should contain the section header index of<br>
+  // the section to which the relocation applies.<br>
+  InputSectionBase<ELFT> *S = Sections[0]->getRelocatedSection();<br>
+  this->Header.sh_info = S->OutSec->SectionIndex;<br>
+}<br>
<br>
 template <class ELFT><br>
 void OutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {<br>
@@ -1368,6 +1383,13 @@ template <class ELFT> void SymbolTableSe<br>
   this->Header.sh_link = StrTabSec.SectionIndex;<br>
   this->Header.sh_info = NumLocals + 1;<br>
<br>
+  if (Config->Relocatable) {<br>
+    size_t I = NumLocals;<br>
+    for (const std::pair<SymbolBody *, size_t> &P : Symbols)<br>
+      P.first->DynsymIndex = ++I;<br>
+    return;<br>
+  }<br>
+<br>
   if (!StrTabSec.isDynamic()) {<br>
     std::stable_sort(Symbols.begin(), Symbols.end(),<br>
                      [](const std::pair<SymbolBody *, unsigned> &L,<br>
<br>
Modified: lld/trunk/ELF/OutputSections.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=261838&r1=261837&r2=261838&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=261838&r1=261837&r2=261838&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/OutputSections.h (original)<br>
+++ lld/trunk/ELF/OutputSections.h Thu Feb 25 02:23:37 2016<br>
@@ -287,6 +287,7 @@ public:<br>
   void sortInitFini();<br>
   void sortCtorsDtors();<br>
   void writeTo(uint8_t *Buf) override;<br>
+  void finalize() override;<br>
<br>
 private:<br>
   void reassignOffsets();<br>
<br>
Modified: lld/trunk/ELF/Writer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=261838&r1=261837&r2=261838&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=261838&r1=261837&r2=261838&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Writer.cpp (original)<br>
+++ lld/trunk/ELF/Writer.cpp Thu Feb 25 02:23:37 2016<br>
@@ -69,6 +69,7 @@ private:<br>
   void scanRelocs(InputSectionBase<ELFT> &S, const Elf_Shdr &RelSec);<br>
   void createPhdrs();<br>
   void assignAddresses();<br>
+  void assignAddressesRelocatable();<br>
   void fixAbsoluteSymbols();<br>
   bool openFile();<br>
   void writeHeader();<br>
@@ -93,13 +94,15 @@ private:<br>
   std::vector<std::unique_ptr<OutputSectionBase<ELFT>>> OwningSections;<br>
<br>
   // We create a section for the ELF header and one for the program headers.<br>
-  const unsigned NumDummySections = 2;<br>
   ArrayRef<OutputSectionBase<ELFT> *> getSections() const {<br>
-    return makeArrayRef(OutputSections).slice(NumDummySections);<br>
+    return makeArrayRef(OutputSections).slice(dummySectionsNum());<br>
   }<br>
   unsigned getNumSections() const {<br>
-    return OutputSections.size() + 1 - NumDummySections;<br>
+    return OutputSections.size() + 1 - dummySectionsNum();<br>
   }<br>
+  // Usually there are 2 dummies sections: ELF header and program header.<br>
+  // Relocatable output does not require program headers to be created.<br>
+  unsigned dummySectionsNum() const { return Config->Relocatable ? 1 : 2; }<br>
<br>
   void addRelIpltSymbols();<br>
   void addStartEndSymbols();<br>
@@ -193,8 +196,12 @@ template <class ELFT> void Writer<ELFT>:<br>
   addReservedSymbols();<br>
   if (!createSections())<br>
     return;<br>
-  createPhdrs();<br>
-  assignAddresses();<br>
+  if (!Config->Relocatable) {<br>
+    createPhdrs();<br>
+    assignAddresses();<br>
+  } else {<br>
+    assignAddressesRelocatable();<br>
+  }<br>
   fixAbsoluteSymbols();<br>
   if (!openFile())<br>
     return;<br>
@@ -495,7 +502,7 @@ void Writer<ELFT>::scanRelocs(InputSecti<br>
<br>
 template <class ELFT><br>
 static void reportUndefined(SymbolTable<ELFT> &Symtab, SymbolBody *Sym) {<br>
-  if (Config->Shared && !Config->NoUndefined)<br>
+  if ((Config->Relocatable || Config->Shared) && !Config->NoUndefined)<br>
     return;<br>
<br>
   std::string Msg = "undefined symbol: " + Sym->getName().str();<br>
@@ -928,7 +935,8 @@ template <class ELFT> static void sortCt<br>
 // Create output section objects and add them to OutputSections.<br>
 template <class ELFT> bool Writer<ELFT>::createSections() {<br>
   OutputSections.push_back(Out<ELFT>::ElfHeader);<br>
-  OutputSections.push_back(Out<ELFT>::ProgramHeaders);<br>
+  if (!Config->Relocatable)<br>
+    OutputSections.push_back(Out<ELFT>::ProgramHeaders);<br>
<br>
   // Add .interp first because some loaders want to see that section<br>
   // on the first page of the executable file when loaded into memory.<br>
@@ -1040,8 +1048,8 @@ template <class ELFT> bool Writer<ELFT>:<br>
   std::stable_sort(OutputSections.begin(), OutputSections.end(),<br>
                    compareSections<ELFT>);<br>
<br>
-  for (unsigned I = NumDummySections, N = OutputSections.size(); I < N; ++I)<br>
-    OutputSections[I]->SectionIndex = I + 1 - NumDummySections;<br>
+  for (unsigned I = dummySectionsNum(), N = OutputSections.size(); I < N; ++I)<br>
+    OutputSections[I]->SectionIndex = I + 1 - dummySectionsNum();<br>
<br>
   for (OutputSectionBase<ELFT> *Sec : getSections())<br>
     Sec->setSHName(Out<ELFT>::ShStrTab->addString(Sec->getName()));<br>
@@ -1304,6 +1312,21 @@ template <class ELFT> void Writer<ELFT>:<br>
     AddHdr(PT_GNU_STACK, PF_R | PF_W);<br>
 }<br>
<br>
+// Used for relocatable output (-r). In this case we create only ELF file<br>
+// header, do not create program headers. Also assign of section addresses<br>
+// is very straightforward: we just put all sections sequentually to the file.<br>
+template <class ELFT> void Writer<ELFT>::assignAddressesRelocatable() {<br>
+  Out<ELFT>::ElfHeader->setSize(sizeof(Elf_Ehdr));<br>
+  uintX_t FileOff = 0;<br>
+  for (OutputSectionBase<ELFT> *Sec : OutputSections) {<br>
+    FileOff = alignTo(FileOff, Sec->getAlign());<br>
+    Sec->setFileOffset(FileOff);<br>
+    FileOff += Sec->getSize();<br>
+  }<br>
+  SectionHeaderOff = alignTo(FileOff, sizeof(uintX_t));<br>
+  FileSize = SectionHeaderOff + getNumSections() * sizeof(Elf_Shdr);<br>
+}<br>
+<br>
 // Visits all headers in PhdrTable and assigns the adresses to<br>
 // the output sections. Also creates common and special headers.<br>
 template <class ELFT> void Writer<ELFT>::assignAddresses() {<br>
@@ -1445,20 +1468,29 @@ template <class ELFT> void Writer<ELFT>:<br>
   auto &FirstObj = cast<ELFFileBase<ELFT>>(*Config->FirstElf);<br>
   EHdr->e_ident[EI_OSABI] = FirstObj.getOSABI();<br>
<br>
-  EHdr->e_type = Config->Shared ? ET_DYN : ET_EXEC;<br>
+  if (Config->Shared)<br>
+    EHdr->e_type = ET_DYN;<br>
+  else if (Config->Relocatable)<br>
+    EHdr->e_type = ET_REL;<br>
+  else<br>
+    EHdr->e_type = ET_EXEC;<br>
+<br>
   EHdr->e_machine = FirstObj.getEMachine();<br>
   EHdr->e_version = EV_CURRENT;<br>
   EHdr->e_entry = getEntryAddr<ELFT>();<br>
-  EHdr->e_phoff = sizeof(Elf_Ehdr);<br>
   EHdr->e_shoff = SectionHeaderOff;<br>
   EHdr->e_flags = getELFFlags();<br>
   EHdr->e_ehsize = sizeof(Elf_Ehdr);<br>
-  EHdr->e_phentsize = sizeof(Elf_Phdr);<br>
   EHdr->e_phnum = Phdrs.size();<br>
   EHdr->e_shentsize = sizeof(Elf_Shdr);<br>
   EHdr->e_shnum = getNumSections();<br>
   EHdr->e_shstrndx = Out<ELFT>::ShStrTab->SectionIndex;<br>
<br>
+  if (!Config->Relocatable) {<br>
+    EHdr->e_phoff = sizeof(Elf_Ehdr);<br>
+    EHdr->e_phentsize = sizeof(Elf_Phdr);<br>
+  }<br>
+<br>
   // Write the program header table.<br>
   auto *HBuf = reinterpret_cast<Elf_Phdr *>(Buf + EHdr->e_phoff);<br>
   for (Phdr &P : Phdrs)<br>
<br>
Added: lld/trunk/test/ELF/Inputs/relocatable.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/relocatable.s?rev=261838&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/relocatable.s?rev=261838&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/test/ELF/Inputs/relocatable.s (added)<br>
+++ lld/trunk/test/ELF/Inputs/relocatable.s Thu Feb 25 02:23:37 2016<br>
@@ -0,0 +1,22 @@<br>
+.text<br>
+.type xx,@object<br>
+.bss<br>
+.globl xx<br>
+.align 4<br>
+xx:<br>
+.long 0<br>
+.size xx, 4<br>
+.type yy,@object<br>
+.globl yy<br>
+.align 4<br>
+yy:<br>
+.long 0<br>
+.size yy, 4<br>
+<br>
+.text<br>
+.globl foo<br>
+.align 16, 0x90<br>
+.type foo,@function<br>
+foo:<br>
+movl $1, xx<br>
+movl $2, yy<br>
<br>
Added: lld/trunk/test/ELF/Inputs/relocatable2.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/relocatable2.s?rev=261838&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/relocatable2.s?rev=261838&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/test/ELF/Inputs/relocatable2.s (added)<br>
+++ lld/trunk/test/ELF/Inputs/relocatable2.s Thu Feb 25 02:23:37 2016<br>
@@ -0,0 +1,22 @@<br>
+.text<br>
+.type xxx,@object<br>
+.bss<br>
+.globl xxx<br>
+.align 4<br>
+xxx:<br>
+.long 0<br>
+.size xxx, 4<br>
+.type yyy,@object<br>
+.globl yyy<br>
+.align 4<br>
+yyy:<br>
+.long 0<br>
+.size yyy, 4<br>
+<br>
+.text<br>
+.globl bar<br>
+.align 16, 0x90<br>
+.type bar,@function<br>
+bar:<br>
+movl $8, xxx<br>
+movl $9, yyy<br>
<br>
Modified: lld/trunk/test/ELF/relocatable.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/relocatable.s?rev=261838&r1=261837&r2=261838&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/relocatable.s?rev=261838&r1=261837&r2=261838&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/test/ELF/relocatable.s (original)<br>
+++ lld/trunk/test/ELF/relocatable.s Thu Feb 25 02:23:37 2016<br>
@@ -1,9 +1,129 @@<br>
 # REQUIRES: x86<br>
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o<br>
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/relocatable.s -o %t2.o<br>
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/relocatable2.s -o %t3.o<br>
+# RUN: ld.lld -r %t1.o %t2.o %t3.o -o %t<br>
+# RUN: llvm-readobj -file-headers -sections -program-headers -symbols -r %t | FileCheck %s<br>
+# RUN: llvm-objdump -s -d %t | FileCheck -check-prefix=CHECKTEXT %s<br>
<br>
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t<br>
-# RUN: not ld.lld -r %t -o %t2 2>&1 | FileCheck %s<br>
+## Test --relocatable alias<br>
+# RUN: ld.lld --relocatable %t1.o %t2.o %t3.o -o %t<br>
+# RUN: llvm-readobj -file-headers -sections -program-headers -symbols -r %t | FileCheck %s<br>
+# RUN: llvm-objdump -s -d %t | FileCheck -check-prefix=CHECKTEXT %s<br>
<br>
-# CHECK: -r option is not supported. Use 'ar' command instead.<br>
+## Verify that we can use our relocation output as input to produce executable<br>
+# RUN: ld.lld -e main %t -o %texec<br>
+# RUN: llvm-readobj -file-headers %texec | FileCheck -check-prefix=CHECKEXE %s<br>
<br>
-.globl _start;<br>
-_start:<br>
+## Attempt to link DSO with -r<br>
+# RUN: ld.lld -shared %t1.o -o %t.so<br>
+# RUN: not ld.lld -r %t.so %t2.o -o %tfail 2>&1 | FileCheck -check-prefix=ERR %s<br>
+# ERR: Attempted static link of dynamic object<br>
+<br>
+## Attempt to use -r and shared together<br>
+# RUN: not ld.lld -r -shared %t2.o -o %tfail 2>&1 | FileCheck -check-prefix=ERR2 %s<br>
+# ERR2: -r and -shared may not be used together<br>
+<br>
+# CHECK:       ElfHeader {<br>
+# CHECK-NEXT:  Ident {<br>
+# CHECK-NEXT:    Magic: (7F 45 4C 46)<br>
+# CHECK-NEXT:    Class: 64-bit<br>
+# CHECK-NEXT:    DataEncoding: LittleEndian<br>
+# CHECK-NEXT:    FileVersion: 1<br>
+# CHECK-NEXT:    OS/ABI: SystemV<br>
+# CHECK-NEXT:    ABIVersion: 0<br>
+# CHECK-NEXT:    Unused: (00 00 00 00 00 00 00)<br>
+# CHECK-NEXT:  }<br>
+# CHECK-NEXT:  Type: Relocatable<br>
+# CHECK-NEXT:  Machine: EM_X86_64<br>
+# CHECK-NEXT:  Version: 1<br>
+# CHECK-NEXT:  Entry: 0x0<br>
+# CHECK-NEXT:  ProgramHeaderOffset: 0x0<br>
+# CHECK-NEXT:  SectionHeaderOffset: 0x2D8<br>
+# CHECK-NEXT:  Flags [<br>
+# CHECK-NEXT:  ]<br>
+# CHECK-NEXT:  HeaderSize: 64<br>
+# CHECK-NEXT:  ProgramHeaderEntrySize: 0<br>
+# CHECK-NEXT:  ProgramHeaderCount: 0<br>
+# CHECK-NEXT:  SectionHeaderEntrySize: 64<br>
+# CHECK-NEXT:  SectionHeaderCount: 7<br>
+# CHECK-NEXT:  StringTableSectionIndex: 5<br>
+# CHECK-NEXT:  }<br>
+<br>
+# CHECK:       Relocations [<br>
+# CHECK-NEXT:  Section (3) .rela.text {<br>
+# CHECK-NEXT:    0x3 R_X86_64_32S x 0x0<br>
+# CHECK-NEXT:    0xE R_X86_64_32S y 0x0<br>
+# CHECK-NEXT:    0x23 R_X86_64_32S xx 0x0<br>
+# CHECK-NEXT:    0x2E R_X86_64_32S yy 0x0<br>
+# CHECK-NEXT:    0x43 R_X86_64_32S xxx 0x0<br>
+# CHECK-NEXT:    0x4E R_X86_64_32S yyy 0x0<br>
+# CHECK-NEXT:  }<br>
+<br>
+# CHECKTEXT:      Disassembly of section .text:<br>
+# CHECKTEXT-NEXT: main:<br>
+# CHECKTEXT-NEXT: 0: c7 04 25 00 00 00 00 05 00 00 00 movl $5, 0<br>
+# CHECKTEXT-NEXT: b: c7 04 25 00 00 00 00 07 00 00 00 movl $7, 0<br>
+# CHECKTEXT:      foo:<br>
+# CHECKTEXT-NEXT: 20: c7 04 25 00 00 00 00 01 00 00 00 movl $1, 0<br>
+# CHECKTEXT-NEXT: 2b: c7 04 25 00 00 00 00 02 00 00 00 movl $2, 0<br>
+# CHECKTEXT:      bar:<br>
+# CHECKTEXT-NEXT: 40: c7 04 25 00 00 00 00 08 00 00 00 movl $8, 0<br>
+# CHECKTEXT-NEXT: 4b: c7 04 25 00 00 00 00 09 00 00 00 movl $9, 0<br>
+<br>
+# CHECKEXE:       Format: ELF64-x86-64<br>
+# CHECKEXE-NEXT:  Arch: x86_64<br>
+# CHECKEXE-NEXT:  AddressSize: 64bit<br>
+# CHECKEXE-NEXT:  LoadName:<br>
+# CHECKEXE-NEXT:  ElfHeader {<br>
+# CHECKEXE-NEXT:    Ident {<br>
+# CHECKEXE-NEXT:      Magic: (7F 45 4C 46)<br>
+# CHECKEXE-NEXT:      Class: 64-bit<br>
+# CHECKEXE-NEXT:      DataEncoding: LittleEndian<br>
+# CHECKEXE-NEXT:      FileVersion: 1<br>
+# CHECKEXE-NEXT:      OS/ABI: SystemV (0x0)<br>
+# CHECKEXE-NEXT:      ABIVersion: 0<br>
+# CHECKEXE-NEXT:      Unused: (00 00 00 00 00 00 00)<br>
+# CHECKEXE-NEXT:    }<br>
+# CHECKEXE-NEXT:    Type: Executable<br>
+# CHECKEXE-NEXT:    Machine: EM_X86_64<br>
+# CHECKEXE-NEXT:    Version: 1<br>
+# CHECKEXE-NEXT:    Entry: 0x11000<br>
+# CHECKEXE-NEXT:    ProgramHeaderOffset: 0x40<br>
+# CHECKEXE-NEXT:    SectionHeaderOffset: 0x11E8<br>
+# CHECKEXE-NEXT:    Flags [<br>
+# CHECKEXE-NEXT:    ]<br>
+# CHECKEXE-NEXT:    HeaderSize: 64<br>
+# CHECKEXE-NEXT:    ProgramHeaderEntrySize: 56<br>
+# CHECKEXE-NEXT:    ProgramHeaderCount: 5<br>
+# CHECKEXE-NEXT:    SectionHeaderEntrySize: 64<br>
+# CHECKEXE-NEXT:    SectionHeaderCount: 6<br>
+# CHECKEXE-NEXT:    StringTableSectionIndex: 4<br>
+# CHECKEXE-NEXT:  }<br>
+<br>
+.text<br>
+.type x,@object<br>
+.bss<br>
+.globl x<br>
+.align 4<br>
+x:<br>
+.long 0<br>
+.size x, 4<br>
+.type y,@object<br>
+.globl y<br>
+.align 4<br>
+y:<br>
+.long 0<br>
+.size y, 4<br>
+<br>
+.text<br>
+.globl main<br>
+.align 16, 0x90<br>
+.type main,@function<br>
+main:<br>
+movl $5, x<br>
+movl $7, y<br>
+<br>
+blah:<br>
+goo:<br>
+abs = 42<br>
<br>
Modified: lld/trunk/test/ELF/strip-all.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/strip-all.s?rev=261838&r1=261837&r2=261838&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/strip-all.s?rev=261838&r1=261837&r2=261838&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/test/ELF/strip-all.s (original)<br>
+++ lld/trunk/test/ELF/strip-all.s Thu Feb 25 02:23:37 2016<br>
@@ -13,6 +13,10 @@<br>
 #AFTER:     .shstrtab<br>
 #AFTER-NOT: .strtab<br>
<br>
+# Ignore --strip-all if -r is specified<br>
+#RUN: ld.lld %t.o --strip-all -r -o %t1<br>
+#RUN: llvm-objdump -section-headers %t1 | FileCheck %s -check-prefix BEFORE<br>
+<br>
 # Test alias -s<br>
 #RUN: ld.lld %t.o -s -o %t1<br>
 #RUN: llvm-objdump -section-headers %t1 | FileCheck %s -check-prefix AFTER<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>