[PATCH] D15423: [ELF] - Place RW sections that go after relro to another memory page.

Rafael EspĂ­ndola via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 23 07:02:46 PST 2015


Thanks!

I also refactored the code so that there is only one point where we do
page alignments.


On 23 December 2015 at 03:55, George Rimar <grimar at accesssoftek.com> wrote:
> grimar added a comment.
>
> In http://reviews.llvm.org/D15423#315938, @rafael wrote:
>
>> What do you think of the attached variation?
>
>
> Works for me. btw, updateRelro() in variation does not need Sec argument then.
>
>   template <class ELFT>
>   void Writer<ELFT>::updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr,
>                                  OutputSectionBase<ELFT> *Sec, uintX_t VA) {
>     if (!GnuRelroPhdr->p_type)
>       setPhdr(GnuRelroPhdr, PT_GNU_RELRO, PF_R, Cur->p_offset, Cur->p_vaddr,
>               VA - Cur->p_vaddr, 1 /*p_align*/);
>     GnuRelroPhdr->p_filesz = VA - Cur->p_vaddr;
>     GnuRelroPhdr->p_memsz = VA - Cur->p_vaddr;
>   }
>
>
> http://reviews.llvm.org/D15423
>
>
>
-------------- next part --------------
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index 2440f1a..e11affc 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -1,1188 +1,1194 @@
 //===- Writer.cpp ---------------------------------------------------------===//
 //
 //                             The LLVM Linker
 //
 // This file is distributed under the University of Illinois Open Source
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 
 #include "Writer.h"
 #include "Config.h"
 #include "OutputSections.h"
 #include "SymbolTable.h"
 #include "Target.h"
 
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/FileOutputBuffer.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/StringSaver.h"
 
 using namespace llvm;
 using namespace llvm::ELF;
 using namespace llvm::object;
 
 using namespace lld;
 using namespace lld::elf2;
 
 namespace {
 // The writer writes a SymbolTable result to a file.
 template <class ELFT> class Writer {
 public:
   typedef typename ELFFile<ELFT>::uintX_t uintX_t;
   typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
   typedef typename ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr;
   typedef typename ELFFile<ELFT>::Elf_Phdr Elf_Phdr;
   typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
   typedef typename ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
   typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela;
   Writer(SymbolTable<ELFT> &S) : Symtab(S) {}
   void run();
 
 private:
   void copyLocalSymbols();
   void createSections();
   template <bool isRela>
   void scanRelocs(InputSectionBase<ELFT> &C,
                   iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels);
   void scanRelocs(InputSection<ELFT> &C);
   void scanRelocs(InputSectionBase<ELFT> &S, const Elf_Shdr &RelSec);
-  void updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr,
-                   OutputSectionBase<ELFT> *Sec, uintX_t VA);
+  void updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr, uintX_t VA);
   void assignAddresses();
   void buildSectionMap();
   void openFile(StringRef OutputPath);
   void writeHeader();
   void writeSections();
   bool isDiscarded(InputSectionBase<ELFT> *IS) const;
   StringRef getOutputSectionName(StringRef S) const;
   bool needsInterpSection() const {
     return !Symtab.getSharedFiles().empty() && !Config->DynamicLinker.empty();
   }
   bool isOutputDynamic() const {
     return !Symtab.getSharedFiles().empty() || Config->Shared;
   }
   uintX_t getEntryAddr() const;
   int getPhdrsNum() const;
 
   OutputSection<ELFT> *getBSS();
   void addCommonSymbols(std::vector<DefinedCommon<ELFT> *> &Syms);
   void addSharedCopySymbols(std::vector<SharedSymbol<ELFT> *> &Syms);
 
   std::unique_ptr<llvm::FileOutputBuffer> Buffer;
 
   SpecificBumpPtrAllocator<OutputSection<ELFT>> SecAlloc;
   SpecificBumpPtrAllocator<MergeOutputSection<ELFT>> MSecAlloc;
   SpecificBumpPtrAllocator<EHOutputSection<ELFT>> EHSecAlloc;
   SpecificBumpPtrAllocator<MipsReginfoOutputSection<ELFT>> MReginfoSecAlloc;
   BumpPtrAllocator Alloc;
   std::vector<OutputSectionBase<ELFT> *> OutputSections;
   unsigned getNumSections() const { return OutputSections.size() + 1; }
 
   void addStartStopSymbols(OutputSectionBase<ELFT> *Sec);
   void setPhdr(Elf_Phdr *PH, uint32_t Type, uint32_t Flags, uintX_t FileOff,
                uintX_t VA, uintX_t Size, uintX_t Align);
   void copyPhdr(Elf_Phdr *PH, OutputSectionBase<ELFT> *From);
 
   bool HasRelro = false;
   SymbolTable<ELFT> &Symtab;
   std::vector<Elf_Phdr> Phdrs;
 
   uintX_t FileSize;
   uintX_t SectionHeaderOff;
 
   llvm::StringMap<llvm::StringRef> InputToOutputSection;
 };
 } // anonymous namespace
 
 template <class ELFT> static bool shouldUseRela() {
   ELFKind K = cast<ELFFileBase<ELFT>>(Config->FirstElf)->getELFKind();
   return K == ELF64LEKind || K == ELF64BEKind;
 }
 
 template <class ELFT> void lld::elf2::writeResult(SymbolTable<ELFT> *Symtab) {
   // Initialize output sections that are handled by Writer specially.
   // Don't reorder because the order of initialization matters.
   InterpSection<ELFT> Interp;
   Out<ELFT>::Interp = &Interp;
   StringTableSection<ELFT> ShStrTab(".shstrtab", false);
   Out<ELFT>::ShStrTab = &ShStrTab;
   StringTableSection<ELFT> StrTab(".strtab", false);
   if (!Config->StripAll)
     Out<ELFT>::StrTab = &StrTab;
   StringTableSection<ELFT> DynStrTab(".dynstr", true);
   Out<ELFT>::DynStrTab = &DynStrTab;
   GotSection<ELFT> Got;
   Out<ELFT>::Got = &Got;
   GotPltSection<ELFT> GotPlt;
   if (Target->supportsLazyRelocations())
     Out<ELFT>::GotPlt = &GotPlt;
   PltSection<ELFT> Plt;
   Out<ELFT>::Plt = &Plt;
   std::unique_ptr<SymbolTableSection<ELFT>> SymTab;
   if (!Config->StripAll) {
     SymTab.reset(new SymbolTableSection<ELFT>(*Symtab, *Out<ELFT>::StrTab));
     Out<ELFT>::SymTab = SymTab.get();
   }
   SymbolTableSection<ELFT> DynSymTab(*Symtab, *Out<ELFT>::DynStrTab);
   Out<ELFT>::DynSymTab = &DynSymTab;
   HashTableSection<ELFT> HashTab;
   if (Config->SysvHash)
     Out<ELFT>::HashTab = &HashTab;
   GnuHashTableSection<ELFT> GnuHashTab;
   if (Config->GnuHash)
     Out<ELFT>::GnuHashTab = &GnuHashTab;
   bool IsRela = shouldUseRela<ELFT>();
   RelocationSection<ELFT> RelaDyn(IsRela ? ".rela.dyn" : ".rel.dyn", IsRela);
   Out<ELFT>::RelaDyn = &RelaDyn;
   RelocationSection<ELFT> RelaPlt(IsRela ? ".rela.plt" : ".rel.plt", IsRela);
   if (Target->supportsLazyRelocations())
     Out<ELFT>::RelaPlt = &RelaPlt;
   DynamicSection<ELFT> Dynamic(*Symtab);
   Out<ELFT>::Dynamic = &Dynamic;
 
   Writer<ELFT>(*Symtab).run();
 }
 
 // The main function of the writer.
 template <class ELFT> void Writer<ELFT>::run() {
   buildSectionMap();
   if (!Config->DiscardAll)
     copyLocalSymbols();
   createSections();
   assignAddresses();
   openFile(Config->OutputFile);
   writeHeader();
   writeSections();
   error(Buffer->commit());
 }
 
 namespace {
 template <bool Is64Bits> struct SectionKey {
   typedef typename std::conditional<Is64Bits, uint64_t, uint32_t>::type uintX_t;
   StringRef Name;
   uint32_t Type;
   uintX_t Flags;
   uintX_t EntSize;
 };
 }
 namespace llvm {
 template <bool Is64Bits> struct DenseMapInfo<SectionKey<Is64Bits>> {
   static SectionKey<Is64Bits> getEmptyKey() {
     return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getEmptyKey(), 0, 0,
                                 0};
   }
   static SectionKey<Is64Bits> getTombstoneKey() {
     return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getTombstoneKey(), 0,
                                 0, 0};
   }
   static unsigned getHashValue(const SectionKey<Is64Bits> &Val) {
     return hash_combine(Val.Name, Val.Type, Val.Flags, Val.EntSize);
   }
   static bool isEqual(const SectionKey<Is64Bits> &LHS,
                       const SectionKey<Is64Bits> &RHS) {
     return DenseMapInfo<StringRef>::isEqual(LHS.Name, RHS.Name) &&
            LHS.Type == RHS.Type && LHS.Flags == RHS.Flags &&
            LHS.EntSize == RHS.EntSize;
   }
 };
 }
 
 // The reason we have to do this early scan is as follows
 // * To mmap the output file, we need to know the size
 // * For that, we need to know how many dynamic relocs we will have.
 // It might be possible to avoid this by outputting the file with write:
 // * Write the allocated output sections, computing addresses.
 // * Apply relocations, recording which ones require a dynamic reloc.
 // * Write the dynamic relocations.
 // * Write the rest of the file.
 template <class ELFT>
 template <bool isRela>
 void Writer<ELFT>::scanRelocs(
     InputSectionBase<ELFT> &C,
     iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels) {
   typedef Elf_Rel_Impl<ELFT, isRela> RelType;
   const ObjectFile<ELFT> &File = *C.getFile();
   for (const RelType &RI : Rels) {
     uint32_t SymIndex = RI.getSymbol(Config->Mips64EL);
     SymbolBody *Body = File.getSymbolBody(SymIndex);
     uint32_t Type = RI.getType(Config->Mips64EL);
 
     if (Target->isGotRelative(Type))
       HasGotOffRel = true;
 
     if (Target->isTlsLocalDynamicReloc(Type)) {
       if (Target->isTlsOptimized(Type, nullptr))
         continue;
       if (Out<ELFT>::Got->addCurrentModuleTlsIndex())
         Out<ELFT>::RelaDyn->addReloc({&C, &RI});
       continue;
     }
 
     // Set "used" bit for --as-needed.
     if (Body && Body->isUndefined() && !Body->isWeak())
       if (auto *S = dyn_cast<SharedSymbol<ELFT>>(Body->repl()))
         S->File->IsUsed = true;
 
     if (Body)
       Body = Body->repl();
 
     if (Body && Body->isTls() && Target->isTlsGlobalDynamicReloc(Type)) {
       bool Opt = Target->isTlsOptimized(Type, Body);
       if (!Opt && Out<ELFT>::Got->addDynTlsEntry(Body)) {
         Out<ELFT>::RelaDyn->addReloc({&C, &RI});
         Out<ELFT>::RelaDyn->addReloc({nullptr, nullptr});
         Body->setUsedInDynamicReloc();
         continue;
       }
       if (!canBePreempted(Body, true))
         continue;
     }
 
     if (Body && Body->isTls() && !Target->isTlsDynReloc(Type, *Body))
       continue;
 
     if (Target->relocNeedsDynRelative(Type)) {
       RelType *Rel = new (Alloc) RelType;
       Rel->setSymbolAndType(0, Target->getRelativeReloc(), Config->Mips64EL);
       Rel->r_offset = RI.r_offset;
       Out<ELFT>::RelaDyn->addReloc({&C, Rel});
     }
 
     bool NeedsGot = false;
     bool NeedsPlt = false;
     if (Body) {
       if (auto *E = dyn_cast<SharedSymbol<ELFT>>(Body)) {
         if (E->NeedsCopy)
           continue;
         if (Target->needsCopyRel(Type, *Body))
           E->NeedsCopy = true;
       }
       NeedsPlt = Target->relocNeedsPlt(Type, *Body);
       if (NeedsPlt) {
         if (Body->isInPlt())
           continue;
         Out<ELFT>::Plt->addEntry(Body);
       }
       NeedsGot = Target->relocNeedsGot(Type, *Body);
       if (NeedsGot) {
         if (NeedsPlt && Target->supportsLazyRelocations()) {
           Out<ELFT>::GotPlt->addEntry(Body);
         } else {
           if (Body->isInGot())
             continue;
           Out<ELFT>::Got->addEntry(Body);
         }
       }
     }
 
     // An STT_GNU_IFUNC symbol always uses a PLT entry, and all references
     // to the symbol go through the PLT. This is true even for a local
     // symbol, although local symbols normally do not require PLT entries.
     if (Body && isGnuIFunc<ELFT>(*Body)) {
       Body->setUsedInDynamicReloc();
       Out<ELFT>::RelaPlt->addReloc({&C, &RI});
       continue;
     }
 
     if (Config->EMachine == EM_MIPS && NeedsGot) {
       // MIPS ABI has special rules to process GOT entries
       // and doesn't require relocation entries for them.
       // See "Global Offset Table" in Chapter 5 in the following document
       // for detailed description:
       // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
       Body->setUsedInDynamicReloc();
       continue;
     }
     bool CBP = canBePreempted(Body, NeedsGot);
     if (!CBP && (!Config->Shared || Target->isRelRelative(Type)))
       continue;
     if (CBP)
       Body->setUsedInDynamicReloc();
     if (NeedsPlt && Target->supportsLazyRelocations())
       Out<ELFT>::RelaPlt->addReloc({&C, &RI});
     else
       Out<ELFT>::RelaDyn->addReloc({&C, &RI});
   }
 }
 
 template <class ELFT> void Writer<ELFT>::scanRelocs(InputSection<ELFT> &C) {
   if (!(C.getSectionHdr()->sh_flags & SHF_ALLOC))
     return;
 
   for (const Elf_Shdr *RelSec : C.RelocSections)
     scanRelocs(C, *RelSec);
 }
 
 template <class ELFT>
 void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &S,
                               const Elf_Shdr &RelSec) {
   ELFFile<ELFT> &EObj = S.getFile()->getObj();
   if (RelSec.sh_type == SHT_RELA)
     scanRelocs(S, EObj.relas(&RelSec));
   else
     scanRelocs(S, EObj.rels(&RelSec));
 }
 
 template <class ELFT>
 static void reportUndefined(const SymbolTable<ELFT> &S, const SymbolBody &Sym) {
   if (Config->Shared && !Config->NoUndefined)
     return;
 
   ELFFileBase<ELFT> *SymFile = findFile<ELFT>(S.getObjectFiles(), &Sym);
   std::string Message = "undefined symbol: " + Sym.getName().str();
   if (SymFile)
     Message += " in " + SymFile->getName().str();
   if (Config->NoInhibitExec)
     warning(Message);
   else
     error(Message);
 }
 
 // Local symbols are not in the linker's symbol table. This function scans
 // each object file's symbol table to copy local symbols to the output.
 template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
   for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
     for (const Elf_Sym &Sym : F->getLocalSymbols()) {
       ErrorOr<StringRef> SymNameOrErr = Sym.getName(F->getStringTable());
       error(SymNameOrErr);
       StringRef SymName = *SymNameOrErr;
       if (!shouldKeepInSymtab<ELFT>(*F, SymName, Sym))
         continue;
       if (Out<ELFT>::SymTab)
         Out<ELFT>::SymTab->addLocalSymbol(SymName);
     }
   }
 }
 
 // PPC64 has a number of special SHT_PROGBITS+SHF_ALLOC+SHF_WRITE sections that
 // we would like to make sure appear is a specific order to maximize their
 // coverage by a single signed 16-bit offset from the TOC base pointer.
 // Conversely, the special .tocbss section should be first among all SHT_NOBITS
 // sections. This will put it next to the loaded special PPC64 sections (and,
 // thus, within reach of the TOC base pointer).
 static int getPPC64SectionRank(StringRef SectionName) {
   return StringSwitch<int>(SectionName)
            .Case(".tocbss", 0)
            .Case(".branch_lt", 2)
            .Case(".toc", 3)
            .Case(".toc1", 4)
            .Case(".opd", 5)
            .Default(1);
 }
 
 template <class ELFT> static bool isRelroSection(OutputSectionBase<ELFT> *Sec) {
   typename OutputSectionBase<ELFT>::uintX_t Flags = Sec->getFlags();
   if (!(Flags & SHF_ALLOC) || !(Flags & SHF_WRITE))
     return false;
   if (Flags & SHF_TLS)
     return true;
   uint32_t Type = Sec->getType();
   if (Type == SHT_INIT_ARRAY || Type == SHT_FINI_ARRAY ||
       Type == SHT_PREINIT_ARRAY)
     return true;
   if (Sec == Out<ELFT>::GotPlt)
     return Config->ZNow;
   if (Sec == Out<ELFT>::Dynamic || Sec == Out<ELFT>::Got)
     return true;
   StringRef S = Sec->getName();
   return S == ".data.rel.ro" || S == ".ctors" || S == ".dtors" || S == ".jcr" ||
          S == ".eh_frame";
 }
 
 // Output section ordering is determined by this function.
 template <class ELFT>
 static bool compareOutputSections(OutputSectionBase<ELFT> *A,
                                   OutputSectionBase<ELFT> *B) {
   typedef typename ELFFile<ELFT>::uintX_t uintX_t;
 
   uintX_t AFlags = A->getFlags();
   uintX_t BFlags = B->getFlags();
 
   // Allocatable sections go first to reduce the total PT_LOAD size and
   // so debug info doesn't change addresses in actual code.
   bool AIsAlloc = AFlags & SHF_ALLOC;
   bool BIsAlloc = BFlags & SHF_ALLOC;
   if (AIsAlloc != BIsAlloc)
     return AIsAlloc;
 
   // We don't have any special requirements for the relative order of
   // two non allocatable sections.
   if (!AIsAlloc)
     return false;
 
   // We want the read only sections first so that they go in the PT_LOAD
   // covering the program headers at the start of the file.
   bool AIsWritable = AFlags & SHF_WRITE;
   bool BIsWritable = BFlags & SHF_WRITE;
   if (AIsWritable != BIsWritable)
     return BIsWritable;
 
   // For a corresponding reason, put non exec sections first (the program
   // header PT_LOAD is not executable).
   bool AIsExec = AFlags & SHF_EXECINSTR;
   bool BIsExec = BFlags & SHF_EXECINSTR;
   if (AIsExec != BIsExec)
     return BIsExec;
 
   // If we got here we know that both A and B are in the same PT_LOAD.
 
   // The TLS initialization block needs to be a single contiguous block in a R/W
   // PT_LOAD, so stick TLS sections directly before R/W sections. The TLS NOBITS
   // sections are placed here as they don't take up virtual address space in the
   // PT_LOAD.
   bool AIsTls = AFlags & SHF_TLS;
   bool BIsTls = BFlags & SHF_TLS;
   if (AIsTls != BIsTls)
     return AIsTls;
 
   // The next requirement we have is to put nobits sections last. The
   // reason is that the only thing the dynamic linker will see about
   // them is a p_memsz that is larger than p_filesz. Seeing that it
   // zeros the end of the PT_LOAD, so that has to correspond to the
   // nobits sections.
   bool AIsNoBits = A->getType() == SHT_NOBITS;
   bool BIsNoBits = B->getType() == SHT_NOBITS;
   if (AIsNoBits != BIsNoBits)
     return BIsNoBits;
 
   // We place RelRo section before plain r/w ones.
   bool AIsRelRo = isRelroSection(A);
   bool BIsRelRo = isRelroSection(B);
   if (AIsRelRo != BIsRelRo)
     return AIsRelRo;
 
   // Some architectures have additional ordering restrictions for sections
   // within the same PT_LOAD.
   if (Config->EMachine == EM_PPC64)
     return getPPC64SectionRank(A->getName()) <
            getPPC64SectionRank(B->getName());
 
   return false;
 }
 
 template <class ELFT> OutputSection<ELFT> *Writer<ELFT>::getBSS() {
   if (!Out<ELFT>::Bss) {
     Out<ELFT>::Bss = new (SecAlloc.Allocate())
         OutputSection<ELFT>(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
     OutputSections.push_back(Out<ELFT>::Bss);
   }
   return Out<ELFT>::Bss;
 }
 
 // Until this function is called, common symbols do not belong to any section.
 // This function adds them to end of BSS section.
 template <class ELFT>
 void Writer<ELFT>::addCommonSymbols(std::vector<DefinedCommon<ELFT> *> &Syms) {
   typedef typename ELFFile<ELFT>::uintX_t uintX_t;
   typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
 
   if (Syms.empty())
     return;
 
   // Sort the common symbols by alignment as an heuristic to pack them better.
   std::stable_sort(
     Syms.begin(), Syms.end(),
     [](const DefinedCommon<ELFT> *A, const DefinedCommon<ELFT> *B) {
       return A->MaxAlignment > B->MaxAlignment;
     });
 
   uintX_t Off = getBSS()->getSize();
   for (DefinedCommon<ELFT> *C : Syms) {
     const Elf_Sym &Sym = C->Sym;
     uintX_t Align = C->MaxAlignment;
     Off = RoundUpToAlignment(Off, Align);
     C->OffsetInBSS = Off;
     Off += Sym.st_size;
   }
 
   Out<ELFT>::Bss->setSize(Off);
 }
 
 template <class ELFT>
 void Writer<ELFT>::addSharedCopySymbols(
     std::vector<SharedSymbol<ELFT> *> &Syms) {
   typedef typename ELFFile<ELFT>::uintX_t uintX_t;
   typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
   typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
 
   if (Syms.empty())
     return;
 
   uintX_t Off = getBSS()->getSize();
   for (SharedSymbol<ELFT> *C : Syms) {
     const Elf_Sym &Sym = C->Sym;
     const Elf_Shdr *Sec = C->File->getSection(Sym);
     uintX_t SecAlign = Sec->sh_addralign;
     unsigned TrailingZeros =
         std::min(countTrailingZeros(SecAlign),
                  countTrailingZeros((uintX_t)Sym.st_value));
     uintX_t Align = 1 << TrailingZeros;
     Out<ELFT>::Bss->updateAlign(Align);
     Off = RoundUpToAlignment(Off, Align);
     C->OffsetInBSS = Off;
     Off += Sym.st_size;
   }
   Out<ELFT>::Bss->setSize(Off);
 }
 
 template <class ELFT>
 StringRef Writer<ELFT>::getOutputSectionName(StringRef S) const {
   auto It = InputToOutputSection.find(S);
   if (It != std::end(InputToOutputSection))
     return It->second;
 
   if (S.startswith(".text."))
     return ".text";
   if (S.startswith(".rodata."))
     return ".rodata";
   if (S.startswith(".data.rel.ro"))
     return ".data.rel.ro";
   if (S.startswith(".data."))
     return ".data";
   if (S.startswith(".bss."))
     return ".bss";
   return S;
 }
 
 template <class ELFT>
 void reportDiscarded(InputSectionBase<ELFT> *IS,
                      const std::unique_ptr<ObjectFile<ELFT>> &File) {
   if (!Config->PrintGcSections || !IS || IS->isLive())
     return;
   llvm::errs() << "removing unused section from '" << IS->getSectionName()
                << "' in file '" << File->getName() << "'\n";
 }
 
 template <class ELFT>
 bool Writer<ELFT>::isDiscarded(InputSectionBase<ELFT> *IS) const {
   if (!IS || !IS->isLive() || IS == &InputSection<ELFT>::Discarded)
     return true;
   return InputToOutputSection.lookup(IS->getSectionName()) == "/DISCARD/";
 }
 
 template <class ELFT>
 static bool compareSections(OutputSectionBase<ELFT> *A,
                             OutputSectionBase<ELFT> *B) {
   auto ItA = Config->OutputSections.find(A->getName());
   auto ItEnd = std::end(Config->OutputSections);
   if (ItA == ItEnd)
     return compareOutputSections(A, B);
   auto ItB = Config->OutputSections.find(B->getName());
   if (ItB == ItEnd)
     return compareOutputSections(A, B);
 
   return std::distance(ItA, ItB) > 0;
 }
 
 // A statically linked executable will have rel[a].plt section
 // to hold R_[*]_IRELATIVE relocations.
 // The multi-arch libc will use these symbols to locate
 // these relocations at program startup time.
 // If RelaPlt is empty then there is no reason to create this symbols.
 template <class ELFT>
 static void addIRelocMarkers(SymbolTable<ELFT> &Symtab, bool IsDynamic) {
   if (IsDynamic || !Out<ELFT>::RelaPlt || !Out<ELFT>::RelaPlt->hasRelocs())
     return;
   bool IsRela = shouldUseRela<ELFT>();
   auto AddMarker = [&](StringRef Name, typename Writer<ELFT>::Elf_Sym &Sym) {
     if (SymbolBody *B = Symtab.find(Name))
       if (B->isUndefined())
         Symtab.addAbsolute(Name, Sym);
   };
   AddMarker(IsRela ? "__rela_iplt_start" : "__rel_iplt_start",
             DefinedAbsolute<ELFT>::RelaIpltStart);
   AddMarker(IsRela ? "__rela_iplt_end" : "__rel_iplt_end",
             DefinedAbsolute<ELFT>::RelaIpltEnd);
 }
 
 // Create output section objects and add them to OutputSections.
 template <class ELFT> void Writer<ELFT>::createSections() {
   // .interp needs to be on the first page in the output file.
   if (needsInterpSection())
     OutputSections.push_back(Out<ELFT>::Interp);
 
   SmallDenseMap<SectionKey<ELFT::Is64Bits>, OutputSectionBase<ELFT> *> Map;
 
   std::vector<OutputSectionBase<ELFT> *> RegularSections;
 
   for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
     for (InputSectionBase<ELFT> *C : F->getSections()) {
       if (isDiscarded(C)) {
         reportDiscarded(C, F);
         continue;
       }
       const Elf_Shdr *H = C->getSectionHdr();
       uintX_t OutFlags = H->sh_flags & ~SHF_GROUP;
       // For SHF_MERGE we create different output sections for each sh_entsize.
       // This makes each output section simple and keeps a single level
       // mapping from input to output.
       typename InputSectionBase<ELFT>::Kind K = C->SectionKind;
       uintX_t EntSize = K != InputSectionBase<ELFT>::Merge ? 0 : H->sh_entsize;
       uint32_t OutType = H->sh_type;
       if (OutType == SHT_PROGBITS && C->getSectionName() == ".eh_frame" &&
           Config->EMachine == EM_X86_64)
         OutType = SHT_X86_64_UNWIND;
       SectionKey<ELFT::Is64Bits> Key{getOutputSectionName(C->getSectionName()),
                                      OutType, OutFlags, EntSize};
       OutputSectionBase<ELFT> *&Sec = Map[Key];
       if (!Sec) {
         switch (K) {
         case InputSectionBase<ELFT>::Regular:
           Sec = new (SecAlloc.Allocate())
               OutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
           break;
         case InputSectionBase<ELFT>::EHFrame:
           Sec = new (EHSecAlloc.Allocate())
               EHOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
           break;
         case InputSectionBase<ELFT>::Merge:
           Sec = new (MSecAlloc.Allocate())
               MergeOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
           break;
         case InputSectionBase<ELFT>::MipsReginfo:
           Sec = new (MReginfoSecAlloc.Allocate())
               MipsReginfoOutputSection<ELFT>();
           break;
         }
         OutputSections.push_back(Sec);
         RegularSections.push_back(Sec);
       }
       switch (K) {
       case InputSectionBase<ELFT>::Regular:
         static_cast<OutputSection<ELFT> *>(Sec)
             ->addSection(cast<InputSection<ELFT>>(C));
         break;
       case InputSectionBase<ELFT>::EHFrame:
         static_cast<EHOutputSection<ELFT> *>(Sec)
             ->addSection(cast<EHInputSection<ELFT>>(C));
         break;
       case InputSectionBase<ELFT>::Merge:
         static_cast<MergeOutputSection<ELFT> *>(Sec)
             ->addSection(cast<MergeInputSection<ELFT>>(C));
         break;
       case InputSectionBase<ELFT>::MipsReginfo:
         static_cast<MipsReginfoOutputSection<ELFT> *>(Sec)
             ->addSection(cast<MipsReginfoInputSection<ELFT>>(C));
         break;
       }
     }
   }
 
   Out<ELFT>::Bss = static_cast<OutputSection<ELFT> *>(
       Map[{".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE, 0}]);
 
   Out<ELFT>::Dynamic->PreInitArraySec = Map.lookup(
       {".preinit_array", SHT_PREINIT_ARRAY, SHF_WRITE | SHF_ALLOC, 0});
   Out<ELFT>::Dynamic->InitArraySec =
       Map.lookup({".init_array", SHT_INIT_ARRAY, SHF_WRITE | SHF_ALLOC, 0});
   Out<ELFT>::Dynamic->FiniArraySec =
       Map.lookup({".fini_array", SHT_FINI_ARRAY, SHF_WRITE | SHF_ALLOC, 0});
 
   auto AddStartEnd = [&](StringRef Start, StringRef End,
                          OutputSectionBase<ELFT> *OS) {
     if (OS) {
       Symtab.addSynthetic(Start, *OS, 0);
       Symtab.addSynthetic(End, *OS, OS->getSize());
     } else {
       Symtab.addIgnored(Start);
       Symtab.addIgnored(End);
     }
   };
 
   AddStartEnd("__preinit_array_start", "__preinit_array_end",
               Out<ELFT>::Dynamic->PreInitArraySec);
   AddStartEnd("__init_array_start", "__init_array_end",
               Out<ELFT>::Dynamic->InitArraySec);
   AddStartEnd("__fini_array_start", "__fini_array_end",
               Out<ELFT>::Dynamic->FiniArraySec);
 
   for (OutputSectionBase<ELFT> *Sec : RegularSections)
     addStartStopSymbols(Sec);
 
   // __tls_get_addr is defined by the dynamic linker for dynamic ELFs. For
   // static linking the linker is required to optimize away any references to
   // __tls_get_addr, so it's not defined anywhere. Create a hidden definition
   // to avoid the undefined symbol error.
   if (!isOutputDynamic())
     Symtab.addIgnored("__tls_get_addr");
 
   // If the "_end" symbol is referenced, it is expected to point to the address
   // right after the data segment. Usually, this symbol points to the end
   // of .bss section or to the end of .data section if .bss section is absent.
   // The order of the sections can be affected by linker script,
   // so it is hard to predict which section will be the last one.
   // So, if this symbol is referenced, we just add the placeholder here
   // and update its value later.
   if (Symtab.find("_end"))
     Symtab.addAbsolute("_end", DefinedAbsolute<ELFT>::End);
 
   // If there is an undefined symbol "end", we should initialize it
   // with the same value as "_end". In any other case it should stay intact,
   // because it is an allowable name for a user symbol.
   if (SymbolBody *B = Symtab.find("end"))
     if (B->isUndefined())
       Symtab.addAbsolute("end", DefinedAbsolute<ELFT>::End);
 
   // Scan relocations. This must be done after every symbol is declared so that
   // we can correctly decide if a dynamic relocation is needed.
   for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
     for (InputSectionBase<ELFT> *C : F->getSections()) {
       if (isDiscarded(C))
         continue;
       if (auto *S = dyn_cast<InputSection<ELFT>>(C))
         scanRelocs(*S);
       else if (auto *S = dyn_cast<EHInputSection<ELFT>>(C))
         if (S->RelocSection)
           scanRelocs(*S, *S->RelocSection);
     }
   }
 
   addIRelocMarkers<ELFT>(Symtab, isOutputDynamic());
 
   std::vector<DefinedCommon<ELFT> *> CommonSymbols;
   std::vector<SharedSymbol<ELFT> *> SharedCopySymbols;
   for (auto &P : Symtab.getSymbols()) {
     SymbolBody *Body = P.second->Body;
     if (auto *U = dyn_cast<Undefined>(Body))
       if (!U->isWeak() && !U->canKeepUndefined())
         reportUndefined<ELFT>(Symtab, *Body);
 
     if (auto *C = dyn_cast<DefinedCommon<ELFT>>(Body))
       CommonSymbols.push_back(C);
     if (auto *SC = dyn_cast<SharedSymbol<ELFT>>(Body))
       if (SC->NeedsCopy)
         SharedCopySymbols.push_back(SC);
 
     if (!includeInSymtab<ELFT>(*Body))
       continue;
     if (Out<ELFT>::SymTab)
       Out<ELFT>::SymTab->addSymbol(Body);
 
     if (isOutputDynamic() && includeInDynamicSymtab(*Body))
       Out<ELFT>::DynSymTab->addSymbol(Body);
   }
   addCommonSymbols(CommonSymbols);
   addSharedCopySymbols(SharedCopySymbols);
 
   // This order is not the same as the final output order
   // because we sort the sections using their attributes below.
   if (Out<ELFT>::SymTab)
     OutputSections.push_back(Out<ELFT>::SymTab);
   OutputSections.push_back(Out<ELFT>::ShStrTab);
   if (Out<ELFT>::StrTab)
     OutputSections.push_back(Out<ELFT>::StrTab);
   if (isOutputDynamic()) {
     OutputSections.push_back(Out<ELFT>::DynSymTab);
     if (Out<ELFT>::GnuHashTab)
       OutputSections.push_back(Out<ELFT>::GnuHashTab);
     if (Out<ELFT>::HashTab)
       OutputSections.push_back(Out<ELFT>::HashTab);
     OutputSections.push_back(Out<ELFT>::Dynamic);
     OutputSections.push_back(Out<ELFT>::DynStrTab);
     if (Out<ELFT>::RelaDyn->hasRelocs())
       OutputSections.push_back(Out<ELFT>::RelaDyn);
     // This is a MIPS specific section to hold a space within the data segment
     // of executable file which is pointed to by the DT_MIPS_RLD_MAP entry.
     // See "Dynamic section" in Chapter 5 in the following document:
     // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
     if (Config->EMachine == EM_MIPS && !Config->Shared) {
       Out<ELFT>::MipsRldMap = new (SecAlloc.Allocate())
           OutputSection<ELFT>(".rld_map", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
       Out<ELFT>::MipsRldMap->setSize(ELFT::Is64Bits ? 8 : 4);
       Out<ELFT>::MipsRldMap->updateAlign(ELFT::Is64Bits ? 8 : 4);
       OutputSections.push_back(Out<ELFT>::MipsRldMap);
     }
   }
 
   // We always need to add rel[a].plt to output if it has entries.
   // Even during static linking it can contain R_[*]_IRELATIVE relocations.
   if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
     OutputSections.push_back(Out<ELFT>::RelaPlt);
     Out<ELFT>::RelaPlt->Static = !isOutputDynamic();
   }
 
   bool needsGot = !Out<ELFT>::Got->empty();
   // We add the .got section to the result for dynamic MIPS target because
   // its address and properties are mentioned in the .dynamic section.
   if (Config->EMachine == EM_MIPS)
     needsGot |= isOutputDynamic();
   // If we have a relocation that is relative to GOT (such as GOTOFFREL),
   // we need to emit a GOT even if it's empty.
   if (HasGotOffRel)
     needsGot = true;
 
   if (needsGot)
     OutputSections.push_back(Out<ELFT>::Got);
   if (Out<ELFT>::GotPlt && !Out<ELFT>::GotPlt->empty())
     OutputSections.push_back(Out<ELFT>::GotPlt);
   if (!Out<ELFT>::Plt->empty())
     OutputSections.push_back(Out<ELFT>::Plt);
 
   std::stable_sort(OutputSections.begin(), OutputSections.end(),
                    compareSections<ELFT>);
 
   for (unsigned I = 0, N = OutputSections.size(); I < N; ++I) {
     OutputSections[I]->SectionIndex = I + 1;
     HasRelro |= (Config->ZRelro && isRelroSection(OutputSections[I]));
   }
 
   for (OutputSectionBase<ELFT> *Sec : OutputSections)
     Out<ELFT>::ShStrTab->add(Sec->getName());
 
   // Finalizers fix each section's size.
   // .dynamic section's finalizer may add strings to .dynstr,
   // so finalize that early.
   // Likewise, .dynsym is finalized early since that may fill up .gnu.hash.
   Out<ELFT>::Dynamic->finalize();
   if (isOutputDynamic())
     Out<ELFT>::DynSymTab->finalize();
 
   // Fill other section headers.
   for (OutputSectionBase<ELFT> *Sec : OutputSections)
     Sec->finalize();
 
   // If we have a .opd section (used under PPC64 for function descriptors),
   // store a pointer to it here so that we can use it later when processing
   // relocations.
   Out<ELFT>::Opd = Map.lookup({".opd", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, 0});
 }
 
 static bool isAlpha(char C) {
   return ('a' <= C && C <= 'z') || ('A' <= C && C <= 'Z') || C == '_';
 }
 
 static bool isAlnum(char C) { return isAlpha(C) || ('0' <= C && C <= '9'); }
 
 // Returns true if S is valid as a C language identifier.
 static bool isValidCIdentifier(StringRef S) {
   if (S.empty() || !isAlpha(S[0]))
     return false;
   return std::all_of(S.begin() + 1, S.end(), isAlnum);
 }
 
 // If a section name is valid as a C identifier (which is rare because of
 // the leading '.'), linkers are expected to define __start_<secname> and
 // __stop_<secname> symbols. They are at beginning and end of the section,
 // respectively. This is not requested by the ELF standard, but GNU ld and
 // gold provide the feature, and used by many programs.
 template <class ELFT>
 void Writer<ELFT>::addStartStopSymbols(OutputSectionBase<ELFT> *Sec) {
   StringRef S = Sec->getName();
   if (!isValidCIdentifier(S))
     return;
   StringSaver Saver(Alloc);
   StringRef Start = Saver.save("__start_" + S);
   StringRef Stop = Saver.save("__stop_" + S);
   if (Symtab.isUndefined(Start))
     Symtab.addSynthetic(Start, *Sec, 0);
   if (Symtab.isUndefined(Stop))
     Symtab.addSynthetic(Stop, *Sec, Sec->getSize());
 }
 
 template <class ELFT> static bool needsPhdr(OutputSectionBase<ELFT> *Sec) {
   return Sec->getFlags() & SHF_ALLOC;
 }
 
 static uint32_t toPhdrFlags(uint64_t Flags) {
   uint32_t Ret = PF_R;
   if (Flags & SHF_WRITE)
     Ret |= PF_W;
   if (Flags & SHF_EXECINSTR)
     Ret |= PF_X;
   return Ret;
 }
 
 template <class ELFT>
 void Writer<ELFT>::updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr,
-                               OutputSectionBase<ELFT> *Sec, uintX_t VA) {
-  if (!Config->ZRelro || !(Cur->p_flags & PF_W) || !isRelroSection(Sec))
-    return;
+                               uintX_t VA) {
   if (!GnuRelroPhdr->p_type)
     setPhdr(GnuRelroPhdr, PT_GNU_RELRO, PF_R, Cur->p_offset, Cur->p_vaddr,
             VA - Cur->p_vaddr, 1 /*p_align*/);
   GnuRelroPhdr->p_filesz = VA - Cur->p_vaddr;
   GnuRelroPhdr->p_memsz = VA - Cur->p_vaddr;
 }
 
 // Visits all sections to create PHDRs and to assign incremental,
 // non-overlapping addresses to output sections.
 template <class ELFT> void Writer<ELFT>::assignAddresses() {
   uintX_t VA = Target->getVAStart() + sizeof(Elf_Ehdr);
   uintX_t FileOff = sizeof(Elf_Ehdr);
 
   // Calculate and reserve the space for the program header first so that
   // the first section can start right after the program header.
   Phdrs.resize(getPhdrsNum());
   size_t PhdrSize = sizeof(Elf_Phdr) * Phdrs.size();
 
   // The first phdr entry is PT_PHDR which describes the program header itself.
   setPhdr(&Phdrs[0], PT_PHDR, PF_R, FileOff, VA, PhdrSize, /*Align=*/8);
   FileOff += PhdrSize;
   VA += PhdrSize;
 
   // PT_INTERP must be the second entry if exists.
   int PhdrIdx = 0;
   Elf_Phdr *Interp = nullptr;
   if (needsInterpSection())
     Interp = &Phdrs[++PhdrIdx];
 
   // Add the first PT_LOAD segment for regular output sections.
   setPhdr(&Phdrs[++PhdrIdx], PT_LOAD, PF_R, 0, Target->getVAStart(), FileOff,
           Target->getPageSize());
 
   Elf_Phdr GnuRelroPhdr = {};
   Elf_Phdr TlsPhdr{};
+  bool RelroAligned = false;
   uintX_t ThreadBSSOffset = 0;
   // Create phdrs as we assign VAs and file offsets to all output sections.
   for (OutputSectionBase<ELFT> *Sec : OutputSections) {
+    Elf_Phdr *PH = &Phdrs[PhdrIdx];
     if (needsPhdr<ELFT>(Sec)) {
       uintX_t Flags = toPhdrFlags(Sec->getFlags());
-      if (Phdrs[PhdrIdx].p_flags != Flags) {
-        // Flags changed. Create a new PT_LOAD.
+      bool InRelRo = Config->ZRelro && (Flags & PF_W) && isRelroSection(Sec);
+      bool FirstNonRelRo = GnuRelroPhdr.p_type && !InRelRo && !RelroAligned;
+      if (FirstNonRelRo || PH->p_flags != Flags) {
         VA = RoundUpToAlignment(VA, Target->getPageSize());
         FileOff = RoundUpToAlignment(FileOff, Target->getPageSize());
-        Elf_Phdr *PH = &Phdrs[++PhdrIdx];
+        if (FirstNonRelRo)
+          RelroAligned = true;
+      }
+
+      if (PH->p_flags != Flags) {
+        // Flags changed. Create a new PT_LOAD.
+        PH = &Phdrs[++PhdrIdx];
         setPhdr(PH, PT_LOAD, Flags, FileOff, VA, 0, Target->getPageSize());
       }
 
       if (Sec->getFlags() & SHF_TLS) {
         if (!TlsPhdr.p_vaddr)
           setPhdr(&TlsPhdr, PT_TLS, PF_R, FileOff, VA, 0, Sec->getAlign());
         if (Sec->getType() != SHT_NOBITS)
           VA = RoundUpToAlignment(VA, Sec->getAlign());
         uintX_t TVA = RoundUpToAlignment(VA + ThreadBSSOffset, Sec->getAlign());
         Sec->setVA(TVA);
         TlsPhdr.p_memsz += Sec->getSize();
         if (Sec->getType() == SHT_NOBITS) {
           ThreadBSSOffset = TVA - VA + Sec->getSize();
         } else {
           TlsPhdr.p_filesz += Sec->getSize();
           VA += Sec->getSize();
         }
         TlsPhdr.p_align = std::max<uintX_t>(TlsPhdr.p_align, Sec->getAlign());
       } else {
         VA = RoundUpToAlignment(VA, Sec->getAlign());
         Sec->setVA(VA);
         VA += Sec->getSize();
-        updateRelro(&Phdrs[PhdrIdx], &GnuRelroPhdr, Sec, VA);
+        if (InRelRo)
+          updateRelro(PH, &GnuRelroPhdr, VA);
       }
     }
 
     FileOff = RoundUpToAlignment(FileOff, Sec->getAlign());
     Sec->setFileOffset(FileOff);
     if (Sec->getType() != SHT_NOBITS)
       FileOff += Sec->getSize();
     if (needsPhdr<ELFT>(Sec)) {
-      Elf_Phdr *Cur = &Phdrs[PhdrIdx];
-      Cur->p_filesz = FileOff - Cur->p_offset;
-      Cur->p_memsz = VA - Cur->p_vaddr;
+      PH->p_filesz = FileOff - PH->p_offset;
+      PH->p_memsz = VA - PH->p_vaddr;
     }
   }
 
   if (TlsPhdr.p_vaddr) {
     // The TLS pointer goes after PT_TLS. At least glibc will align it,
     // so round up the size to make sure the offsets are correct.
     TlsPhdr.p_memsz = RoundUpToAlignment(TlsPhdr.p_memsz, TlsPhdr.p_align);
     Phdrs[++PhdrIdx] = TlsPhdr;
     Out<ELFT>::TlsPhdr = &Phdrs[PhdrIdx];
   }
 
   // Add an entry for .dynamic.
   if (isOutputDynamic()) {
     Elf_Phdr *PH = &Phdrs[++PhdrIdx];
     PH->p_type = PT_DYNAMIC;
     copyPhdr(PH, Out<ELFT>::Dynamic);
   }
 
   if (HasRelro) {
     Elf_Phdr *PH = &Phdrs[++PhdrIdx];
     *PH = GnuRelroPhdr;
   }
 
   // PT_GNU_STACK is a special section to tell the loader to make the
   // pages for the stack non-executable.
   if (!Config->ZExecStack) {
     Elf_Phdr *PH = &Phdrs[++PhdrIdx];
     PH->p_type = PT_GNU_STACK;
     PH->p_flags = PF_R | PF_W;
   }
 
   // Fix up PT_INTERP as we now know the address of .interp section.
   if (Interp) {
     Interp->p_type = PT_INTERP;
     copyPhdr(Interp, Out<ELFT>::Interp);
   }
 
   // Add space for section headers.
   SectionHeaderOff = RoundUpToAlignment(FileOff, ELFT::Is64Bits ? 8 : 4);
   FileSize = SectionHeaderOff + getNumSections() * sizeof(Elf_Shdr);
 
   // Update "_end" and "end" symbols so that they
   // point to the end of the data segment.
   DefinedAbsolute<ELFT>::End.st_value = VA;
 
   // Update __rel_iplt_start/__rel_iplt_end to wrap the
   // rela.plt section.
   if (Out<ELFT>::RelaPlt) {
     uintX_t Start = Out<ELFT>::RelaPlt->getVA();
     DefinedAbsolute<ELFT>::RelaIpltStart.st_value = Start;
     DefinedAbsolute<ELFT>::RelaIpltEnd.st_value =
         Start + Out<ELFT>::RelaPlt->getSize();
   }
 
   // Update MIPS _gp absolute symbol so that it points to the static data.
   if (Config->EMachine == EM_MIPS)
     DefinedAbsolute<ELFT>::MipsGp.st_value = getMipsGpAddr<ELFT>();
 }
 
 // Returns the number of PHDR entries.
 template <class ELFT> int Writer<ELFT>::getPhdrsNum() const {
   bool Tls = false;
   int I = 2; // 2 for PT_PHDR and first PT_LOAD
   if (needsInterpSection())
     ++I;
   if (isOutputDynamic())
     ++I;
   if (!Config->ZExecStack)
     ++I;
   uintX_t Last = PF_R;
   for (OutputSectionBase<ELFT> *Sec : OutputSections) {
     if (!needsPhdr<ELFT>(Sec))
       continue;
     if (Sec->getFlags() & SHF_TLS)
       Tls = true;
     uintX_t Flags = toPhdrFlags(Sec->getFlags());
     if (Last != Flags) {
       Last = Flags;
       ++I;
     }
   }
   if (Tls)
     ++I;
   if (HasRelro)
     ++I;
   return I;
 }
 
 static uint32_t getELFFlags() {
   if (Config->EMachine != EM_MIPS)
     return 0;
   // FIXME: In fact ELF flags depends on ELF flags of input object files
   // and selected emulation. For now just use hadr coded values.
   uint32_t V = EF_MIPS_ABI_O32 | EF_MIPS_CPIC | EF_MIPS_ARCH_32R2;
   if (Config->Shared)
     V |= EF_MIPS_PIC;
   return V;
 }
 
 template <class ELFT> void Writer<ELFT>::writeHeader() {
   uint8_t *Buf = Buffer->getBufferStart();
   memcpy(Buf, "\177ELF", 4);
 
   // Write the ELF header.
   auto *EHdr = reinterpret_cast<Elf_Ehdr *>(Buf);
   EHdr->e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
   EHdr->e_ident[EI_DATA] = ELFT::TargetEndianness == llvm::support::little
                                ? ELFDATA2LSB
                                : ELFDATA2MSB;
   EHdr->e_ident[EI_VERSION] = EV_CURRENT;
 
   auto &FirstObj = cast<ELFFileBase<ELFT>>(*Config->FirstElf);
   EHdr->e_ident[EI_OSABI] = FirstObj.getOSABI();
 
   EHdr->e_type = Config->Shared ? ET_DYN : ET_EXEC;
   EHdr->e_machine = FirstObj.getEMachine();
   EHdr->e_version = EV_CURRENT;
   EHdr->e_entry = getEntryAddr();
   EHdr->e_phoff = sizeof(Elf_Ehdr);
   EHdr->e_shoff = SectionHeaderOff;
   EHdr->e_flags = getELFFlags();
   EHdr->e_ehsize = sizeof(Elf_Ehdr);
   EHdr->e_phentsize = sizeof(Elf_Phdr);
   EHdr->e_phnum = Phdrs.size();
   EHdr->e_shentsize = sizeof(Elf_Shdr);
   EHdr->e_shnum = getNumSections();
   EHdr->e_shstrndx = Out<ELFT>::ShStrTab->SectionIndex;
 
   // Write the program header table.
   memcpy(Buf + EHdr->e_phoff, &Phdrs[0], Phdrs.size() * sizeof(Phdrs[0]));
 
   // Write the section header table. Note that the first table entry is null.
   auto SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff);
   for (OutputSectionBase<ELFT> *Sec : OutputSections)
     Sec->writeHeaderTo(++SHdrs);
 }
 
 template <class ELFT> void Writer<ELFT>::openFile(StringRef Path) {
   ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
       FileOutputBuffer::create(Path, FileSize, FileOutputBuffer::F_executable);
   error(BufferOrErr, Twine("failed to open ") + Path);
   Buffer = std::move(*BufferOrErr);
 }
 
 // Write section contents to a mmap'ed file.
 template <class ELFT> void Writer<ELFT>::writeSections() {
   uint8_t *Buf = Buffer->getBufferStart();
 
   // PPC64 needs to process relocations in the .opd section before processing
   // relocations in code-containing sections.
   if (OutputSectionBase<ELFT> *Sec = Out<ELFT>::Opd) {
     Out<ELFT>::OpdBuf = Buf + Sec->getFileOff();
     Sec->writeTo(Buf + Sec->getFileOff());
   }
 
   for (OutputSectionBase<ELFT> *Sec : OutputSections)
     if (Sec != Out<ELFT>::Opd)
       Sec->writeTo(Buf + Sec->getFileOff());
 }
 
 template <class ELFT>
 typename ELFFile<ELFT>::uintX_t Writer<ELFT>::getEntryAddr() const {
   if (Config->EntrySym) {
     if (SymbolBody *E = Config->EntrySym->repl())
       return getSymVA<ELFT>(*E);
     return 0;
   }
   if (Config->EntryAddr != uint64_t(-1))
     return Config->EntryAddr;
   return 0;
 }
 
 template <class ELFT>
 void Writer<ELFT>::setPhdr(Elf_Phdr *PH, uint32_t Type, uint32_t Flags,
                            uintX_t FileOff, uintX_t VA, uintX_t Size,
                            uintX_t Align) {
   PH->p_type = Type;
   PH->p_flags = Flags;
   PH->p_offset = FileOff;
   PH->p_vaddr = VA;
   PH->p_paddr = VA;
   PH->p_filesz = Size;
   PH->p_memsz = Size;
   PH->p_align = Align;
 }
 
 template <class ELFT>
 void Writer<ELFT>::copyPhdr(Elf_Phdr *PH, OutputSectionBase<ELFT> *From) {
   PH->p_flags = toPhdrFlags(From->getFlags());
   PH->p_offset = From->getFileOff();
   PH->p_vaddr = From->getVA();
   PH->p_paddr = From->getVA();
   PH->p_filesz = From->getSize();
   PH->p_memsz = From->getSize();
   PH->p_align = From->getAlign();
 }
 
 template <class ELFT> void Writer<ELFT>::buildSectionMap() {
   for (const std::pair<StringRef, std::vector<StringRef>> &OutSec :
        Config->OutputSections)
     for (StringRef Name : OutSec.second)
       InputToOutputSection[Name] = OutSec.first;
 }
 
 template void lld::elf2::writeResult<ELF32LE>(SymbolTable<ELF32LE> *Symtab);
 template void lld::elf2::writeResult<ELF32BE>(SymbolTable<ELF32BE> *Symtab);
 template void lld::elf2::writeResult<ELF64LE>(SymbolTable<ELF64LE> *Symtab);
 template void lld::elf2::writeResult<ELF64BE>(SymbolTable<ELF64BE> *Symtab);
diff --git a/test/ELF/aarch64-copy.s b/test/ELF/aarch64-copy.s
index 6fc8c5b..86d9720 100644
--- a/test/ELF/aarch64-copy.s
+++ b/test/ELF/aarch64-copy.s
@@ -1,93 +1,93 @@
 // REQUIRES: aarch64
 // RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %s -o %t.o
 // RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %p/Inputs/relocation-copy.s -o %t2.o
 // RUN: ld.lld -shared %t2.o -o %t2.so
 // RUN: ld.lld %t.o %t2.so -o %t3
 // RUN: llvm-readobj -s -r --expand-relocs -symbols %t3 | FileCheck %s
 // RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=CODE %s
 // RUN: llvm-objdump -s -section=.data %t3 | FileCheck -check-prefix=DATA %s
 
 .text
 .globl _start
 _start:
     adr x1, x
     adrp x2, y
     add x2, x2, :lo12:y
 .data
     .word z
 
 // CHECK:     Name: .bss
 // CHECK-NEXT:     Type: SHT_NOBITS
 // CHECK-NEXT:     Flags [
 // CHECK-NEXT:       SHF_ALLOC
 // CHECK-NEXT:       SHF_WRITE
 // CHECK-NEXT:     ]
-// CHECK-NEXT:     Address: 0x120B0
+// CHECK-NEXT:     Address: 0x13010
 // CHECK-NEXT:     Offset:
 // CHECK-NEXT:     Size: 24
 // CHECK-NEXT:     Link:
 // CHECK-NEXT:     Info:
 // CHECK-NEXT:     AddressAlignment: 16
 
 // CHECK: Relocations [
 // CHECK-NEXT:   Section ({{.*}}) .rela.dyn {
 // CHECK-NEXT:     Relocation {
-// CHECK-NEXT:       Offset: 0x120B0
+// CHECK-NEXT:       Offset: 0x13010
 // CHECK-NEXT:       Type: R_AARCH64_COPY
 // CHECK-NEXT:       Symbol: x
 // CHECK-NEXT:       Addend: 0x0
 // CHECK-NEXT:     }
 // CHECK-NEXT:     Relocation {
-// CHECK-NEXT:       Offset: 0x120C0
+// CHECK-NEXT:       Offset: 0x13020
 // CHECK-NEXT:       Type: R_AARCH64_COPY
 // CHECK-NEXT:       Symbol: y
 // CHECK-NEXT:       Addend: 0x0
 // CHECK-NEXT:     }
 // CHECK-NEXT:     Relocation {
-// CHECK-NEXT:       Offset: 0x120C4
+// CHECK-NEXT:       Offset: 0x13024
 // CHECK-NEXT:       Type: R_AARCH64_COPY
 // CHECK-NEXT:       Symbol: z
 // CHECK-NEXT:       Addend: 0x0
 // CHECK-NEXT:     }
 // CHECK-NEXT:   }
 // CHECK-NEXT: ]
 
 // CHECK: Symbols [
 // CHECK:     Name: x
-// CHECK-NEXT:     Value: 0x120B0
+// CHECK-NEXT:     Value: 0x13010
 // CHECK-NEXT:     Size: 4
 // CHECK-NEXT:     Binding: Global
 // CHECK-NEXT:     Type: Object
 // CHECK-NEXT:     Other:
 // CHECK-NEXT:     Section: .bss
 // CHECK:     Name: y
-// CHECK-NEXT:     Value: 0x120C0
+// CHECK-NEXT:     Value: 0x13020
 // CHECK-NEXT:     Size: 4
 // CHECK-NEXT:     Binding: Global
 // CHECK-NEXT:     Type: Object
 // CHECK-NEXT:     Other:
 // CHECK-NEXT:     Section: .bss
 // CHECK:     Name: z
-// CHECK-NEXT:     Value: 0x120C4
+// CHECK-NEXT:     Value: 0x13024
 // CHECK-NEXT:     Size: 4
 // CHECK-NEXT:     Binding: Global
 // CHECK-NEXT:     Type: Object
 // CHECK-NEXT:     Other:
 // CHECK-NEXT:     Section: .bss
 // CHECK: ]
 
 // CODE: Disassembly of section .text:
 // CODE-NEXT: _start:
-// S(x) = 0x120B0, A = 0, P = 0x11000
-// S + A - P = 0x10B0 = 4272
-// CODE-NEXT:  11000: {{.*}} adr  x1, #4272
-// S(y) = 0x120C0, A = 0, P = 0x11004
-// Page(S + A) - Page(P) = 0x12000 - 0x11000 = 0x1000 - 4096
-// CODE-NEXT:  11004: {{.*}} adrp x2, #4096
-// S(y) = 0x120C0, A = 0
-// (S + A) & 0xFFF = 0xC0 = 192
-// CODE-NEXT:  11008: {{.*}} add  x2, x2, #192
+// S(x) = 0x13010, A = 0, P = 0x11000
+// S + A - P = 0x10B0 = 8208
+// CODE-NEXT:  11000: {{.*}} adr  x1, #8208
+// S(y) = 0x13020, A = 0, P = 0x11004
+// Page(S + A) - Page(P) = 0x13000 - 0x11000 = 0x2000 = 8192
+// CODE-NEXT:  11004: {{.*}} adrp x2, #8192
+// S(y) = 0x13020, A = 0
+// (S + A) & 0xFFF = 0x20 = 32
+// CODE-NEXT:  11008: {{.*}} add  x2, x2, #32
 
 // DATA: Contents of section .data:
-// S(z) = 0x120c4
-// DATA-NEXT:  120a0 c4200100
+// S(z) = 0x13024
+// DATA-NEXT:  13000 24300100
diff --git a/test/ELF/dynamic-reloc-index.s b/test/ELF/dynamic-reloc-index.s
index 43d9dbb..2d38c01 100644
--- a/test/ELF/dynamic-reloc-index.s
+++ b/test/ELF/dynamic-reloc-index.s
@@ -1,21 +1,21 @@
 // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
 // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
 // RUN: ld.lld -shared %t2.o -o %t2.so
 // RUN: ld.lld %t.o %t2.so -o %t
 // RUN: llvm-readobj -r %t | FileCheck %s
 
 // We used to record the wrong symbol index for this test
 
 // CHECK:      Relocations [
 // CHECK-NEXT:   Section ({{.*}}) .rela.plt {
-// CHECK-NEXT:     0x120C8 R_X86_64_JUMP_SLOT bar 0x0
+// CHECK-NEXT:     0x13018 R_X86_64_JUMP_SLOT bar 0x0
 // CHECK-NEXT:   }
 // CHECK-NEXT: ]
 
         .global foobar
 foobar:
         .global zedx
 zedx:
         .global _start
 _start:
 .quad bar
diff --git a/test/ELF/dynamic-reloc.s b/test/ELF/dynamic-reloc.s
index 6de2fba..ab2a240 100644
--- a/test/ELF/dynamic-reloc.s
+++ b/test/ELF/dynamic-reloc.s
@@ -1,64 +1,64 @@
 // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
 // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
 // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/dynamic-reloc.s -o %t3.o
 // RUN: ld.lld -shared %t2.o -o %t2.so
 // RUN: ld.lld %t.o %t3.o %t2.so -o %t
 // RUN: llvm-readobj -dynamic-table -r --expand-relocs -s %t | FileCheck %s
 // REQUIRES: x86
 
 // CHECK:      Index: 1
 // CHECK-NEXT: Name: .dynsym
 
 // CHECK:      Name: .rela.plt
 // CHECK-NEXT: Type: SHT_RELA
 // CHECK-NEXT: Flags [
 // CHECK-NEXT:   SHF_ALLOC
 // CHECK-NEXT: ]
 // CHECK-NEXT: Address: [[RELAADDR:.*]]
 // CHECK-NEXT: Offset:
 // CHECK-NEXT: Size: [[RELASIZE:.*]]
 // CHECK-NEXT: Link: 1
 // CHECK-NEXT: Info: 0
 // CHECK-NEXT: AddressAlignment: 8
 // CHECK-NEXT: EntrySize: 24
 
 // CHECK:      Name: .text
 // CHECK-NEXT: Type: SHT_PROGBITS
 // CHECK-NEXT: Flags [
 // CHECK-NEXT:   SHF_ALLOC
 // CHECK-NEXT:   SHF_EXECINSTR
 // CHECK-NEXT: ]
 // CHECK-NEXT: Address: 0x11000
 
 // CHECK:      Relocations [
 // CHECK-NEXT:   Section ({{.*}}) .rela.plt {
 // CHECK-NEXT:     Relocation {
-// CHECK-NEXT:       Offset: 0x120C8
+// CHECK-NEXT:       Offset: 0x13018
 // CHECK-NEXT:       Type: R_X86_64_JUMP_SLOT
 // CHECK-NEXT:       Symbol: bar
 // CHECK-NEXT:       Addend: 0x0
 // CHECK-NEXT:     }
 // CHECK-NEXT:   }
 // CHECK-NEXT: ]
 
 // CHECK: DynamicSection [
 // CHECK-NEXT:  Tag                Type                 Name/Value
 // CHECK-NEXT:  0x0000000000000017 JMPREL
 // CHECK-NEXT:  0x0000000000000002 PLTRELSZ             24 (bytes)
 // CHECK-NEXT:  0x0000000000000003 PLTGOT
 // CHECK-NEXT:  0x0000000000000014 PLTREL               RELA
 // CHECK-NEXT:  0x0000000000000006 SYMTAB
 // CHECK-NEXT:  0x000000000000000B SYMENT               24 (bytes)
 // CHECK-NEXT:  0x0000000000000005 STRTAB
 // CHECK-NEXT:  0x000000000000000A STRSZ
 // CHECK-NEXT:  0x0000000000000004 HASH
 // CHECK-NEXT:  0x0000000000000001 NEEDED               SharedLibrary ({{.*}}2.so)
 // CHECK-NEXT:  0x0000000000000000 NULL                 0x0
 // CHECK-NEXT: ]
 
 .global _start
 _start:
 .quad bar + 0x42
 .weak foo
 .quad foo
 call main
diff --git a/test/ELF/mips-got-relocs.s b/test/ELF/mips-got-relocs.s
index f8b7be4..27180fb 100644
--- a/test/ELF/mips-got-relocs.s
+++ b/test/ELF/mips-got-relocs.s
@@ -1,99 +1,99 @@
 # Check R_MIPS_GOT16 relocation calculation.
 
 # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-be.o
 # RUN: ld.lld %t-be.o -o %t-be.exe
 # RUN: llvm-objdump -section-headers -t %t-be.exe | FileCheck -check-prefix=EXE_SYM %s
 # RUN: llvm-objdump -s -section=.got %t-be.exe | FileCheck -check-prefix=EXE_GOT_BE %s
 # RUN: llvm-objdump -d %t-be.exe | FileCheck -check-prefix=EXE_DIS_BE %s
 # RUN: llvm-readobj -relocations %t-be.exe | FileCheck -check-prefix=NORELOC %s
 # RUN: llvm-readobj -sections %t-be.exe | FileCheck -check-prefix=SHFLAGS %s
 
 # RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %t-el.o
 # RUN: ld.lld %t-el.o -o %t-el.exe
 # RUN: llvm-objdump -section-headers -t %t-el.exe | FileCheck -check-prefix=EXE_SYM %s
 # RUN: llvm-objdump -s -section=.got %t-el.exe | FileCheck -check-prefix=EXE_GOT_EL %s
 # RUN: llvm-objdump -d %t-el.exe | FileCheck -check-prefix=EXE_DIS_EL %s
 # RUN: llvm-readobj -relocations %t-el.exe | FileCheck -check-prefix=NORELOC %s
 # RUN: llvm-readobj -sections %t-el.exe | FileCheck -check-prefix=SHFLAGS %s
 
 # RUN: ld.lld -shared %t-be.o -o %t-be.so
 # RUN: llvm-objdump -section-headers -t %t-be.so | FileCheck -check-prefix=DSO_SYM %s
 # RUN: llvm-objdump -s -section=.got %t-be.so | FileCheck -check-prefix=DSO_GOT_BE %s
 # RUN: llvm-objdump -d %t-be.so | FileCheck -check-prefix=DSO_DIS_BE %s
 # RUN: llvm-readobj -relocations %t-be.so | FileCheck -check-prefix=NORELOC %s
 # RUN: llvm-readobj -sections %t-be.so | FileCheck -check-prefix=SHFLAGS %s
 
 # RUN: ld.lld -shared %t-el.o -o %t-el.so
 # RUN: llvm-objdump -section-headers -t %t-el.so | FileCheck -check-prefix=DSO_SYM %s
 # RUN: llvm-objdump -s -section=.got %t-el.so | FileCheck -check-prefix=DSO_GOT_EL %s
 # RUN: llvm-objdump -d %t-el.so | FileCheck -check-prefix=DSO_DIS_EL %s
 # RUN: llvm-readobj -relocations %t-el.so | FileCheck -check-prefix=NORELOC %s
 # RUN: llvm-readobj -sections %t-el.so | FileCheck -check-prefix=SHFLAGS %s
 
 # REQUIRES: mips
 
   .text
   .globl  __start
 __start:
   lui $2, %got(v1)
 
   .data
   .globl v1
   .type  v1, at object
   .size  v1,4
 v1:
   .word 0
 
 # EXE_SYM: Sections:
 # EXE_SYM: .got 0000000c 0000000000030000 DATA
 # EXE_SYM: SYMBOL TABLE:
 # EXE_SYM: 00037ff0         *ABS*		 00000000 _gp
 #          ^-- .got + GP offset (0x7ff0)
-# EXE_SYM: 00030010 g       .data		 00000004 v1
+# EXE_SYM: 00040000 g       .data		 00000004 v1
 
 # EXE_GOT_BE: Contents of section .got:
-# EXE_GOT_BE:  30000 00000000 80000000 00030010
-#                    ^        ^        ^-- v1 (0x30010)
+# EXE_GOT_BE:  30000 00000000 80000000 00040000
+#                    ^        ^        ^-- v1 (0x40000)
 #                    |        +-- Module pointer (0x80000000)
 #                    +-- Lazy resolver (0x0)
 
 # EXE_GOT_EL: Contents of section .got:
-# EXE_GOT_EL:  30000 00000000 00000080 10000300
-#                    ^        ^        ^-- v1 (0x30010)
+# EXE_GOT_EL:  30000 00000000 00000080 00000400
+#                    ^        ^        ^-- v1 (0x40000)
 #                    |        +-- Module pointer (0x80000000)
 #                    +-- Lazy resolver (0x0)
 
 # v1GotAddr (0x3000c) - _gp (0x37ff4) = -0x7fe8 => 0x8018 = 32792
 # EXE_DIS_BE:  20000:  3c 02 80 18  lui $2, 32792
 # EXE_DIS_EL:  20000:  18 80 02 3c  lui $2, 32792
 
 # DSO_SYM: Sections:
 # DSO_SYM: .got 0000000c 0000000000020000 DATA
 # DSO_SYM: SYMBOL TABLE:
 # DSO_SYM: 00027ff0         *ABS*		 00000000 _gp
 #          ^-- .got + GP offset (0x7ff0)
-# DSO_SYM: 00020010 g       .data		 00000004 v1
+# DSO_SYM: 00030000 g       .data		 00000004 v1
 
 # DSO_GOT_BE: Contents of section .got:
-# DSO_GOT_BE:  20000 00000000 80000000 00020010
-#                    ^        ^        ^-- v1 (0x20010)
+# DSO_GOT_BE:  20000 00000000 80000000 00030000
+#                    ^        ^        ^-- v1 (0x30000)
 #                    |        +-- Module pointer (0x80000000)
 #                    +-- Lazy resolver (0x0)
 
 # DSO_GOT_EL: Contents of section .got:
-# DSO_GOT_EL:  20000 00000000 00000080 10000200
-#                    ^        ^        ^-- v1 (0x20010)
+# DSO_GOT_EL:  20000 00000000 00000080 00000300
+#                    ^        ^        ^-- v1 (0x30000)
 #                    |        +-- Module pointer (0x80000000)
 #                    +-- Lazy resolver (0x0)
 
 # v1GotAddr (0x2000c) - _gp (0x27ff4) = -0x7fe8 => 0x8018 = 32792
 # DSO_DIS_BE:  10000:  3c 02 80 18  lui $2, 32792
 # DSO_DIS_EL:  10000:  18 80 02 3c  lui $2, 32792
 
 # NORELOC:      Relocations [
 # NORELOC-NEXT: ]
 
 # SHFLAGS:      Name: .got
 # SHFLAGS-NEXT: Type: SHT_PROGBITS
 # SHFLAGS-NEXT: Flags [ (0x10000003)
 #                        ^-- SHF_MIPS_GPREL | SHF_ALLOC | SHF_WRITE
diff --git a/test/ELF/plt-aarch64.s b/test/ELF/plt-aarch64.s
index 3c58dae..6ea732e 100644
--- a/test/ELF/plt-aarch64.s
+++ b/test/ELF/plt-aarch64.s
@@ -1,205 +1,205 @@
 // RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %s -o %t.o
 // RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %p/Inputs/shared.s -o %t2.o
 // RUN: ld.lld -shared %t2.o -o %t2.so
 // RUN: ld.lld -shared %t.o %t2.so -o %t.so
 // RUN: ld.lld %t.o %t2.so -o %t.exe
 // RUN: llvm-readobj -s -r %t.so | FileCheck --check-prefix=CHECKDSO %s
 // RUN: llvm-objdump -s -section=.got.plt %t.so | FileCheck --check-prefix=DUMPDSO %s
 // RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASMDSO %s
 // RUN: llvm-readobj -s -r %t.exe | FileCheck --check-prefix=CHECKEXE %s
 // RUN: llvm-objdump -s -section=.got.plt %t.exe | FileCheck --check-prefix=DUMPEXE %s
 // RUN: llvm-objdump -d %t.exe | FileCheck --check-prefix=DISASMEXE %s
 
 // REQUIRES: aarch64
 
 // CHECKDSO:     Name: .plt
 // CHECKDSO-NEXT:     Type: SHT_PROGBITS
 // CHECKDSO-NEXT:     Flags [
 // CHECKDSO-NEXT:       SHF_ALLOC
 // CHECKDSO-NEXT:       SHF_EXECINSTR
 // CHECKDSO-NEXT:     ]
 // CHECKDSO-NEXT:     Address: 0x1010
 // CHECKDSO-NEXT:     Offset:
 // CHECKDSO-NEXT:     Size: 80
 // CHECKDSO-NEXT:     Link:
 // CHECKDSO-NEXT:     Info:
 // CHECKDSO-NEXT:     AddressAlignment: 16
 
 // CHECKDSO:     Name: .got.plt
 // CHECKDSO-NEXT:     Type: SHT_PROGBITS
 // CHECKDSO-NEXT:     Flags [
 // CHECKDSO-NEXT:       SHF_ALLOC
 // CHECKDSO-NEXT:       SHF_WRITE
 // CHECKDSO-NEXT:     ]
-// CHECKDSO-NEXT:     Address: 0x20B0
+// CHECKDSO-NEXT:     Address: 0x3000
 // CHECKDSO-NEXT:     Offset:
 // CHECKDSO-NEXT:     Size: 48
 // CHECKDSO-NEXT:     Link:
 // CHECKDSO-NEXT:     Info:
 // CHECKDSO-NEXT:     AddressAlignment: 8
 
 // CHECKDSO: Relocations [
 // CHECKDSO-NEXT:   Section ({{.*}}) .rela.plt {
 
-// &(.got.plt[3]) = 0x20B0 + 3 * 8 = 0x20C8
-// CHECKDSO-NEXT:     0x20C8 R_AARCH64_JUMP_SLOT foo
+// &(.got.plt[3]) = 0x3000 + 3 * 8 = 0x3018
+// CHECKDSO-NEXT:     0x3018 R_AARCH64_JUMP_SLOT foo
 
-// &(.got.plt[4]) = 0x20B0 + 4 * 8 = 0x20D0
-// CHECKDSO-NEXT:     0x20D0 R_AARCH64_JUMP_SLOT bar
+// &(.got.plt[4]) = 0x3000 + 4 * 8 = 0x3020
+// CHECKDSO-NEXT:     0x3020 R_AARCH64_JUMP_SLOT bar
 
-// &(.got.plt[5]) = 0x20B0 + 5 * 8 = 0x20D8
-// CHECKDSO-NEXT:     0x20D8 R_AARCH64_JUMP_SLOT weak
+// &(.got.plt[5]) = 0x3000 + 5 * 8 = 0x3028
+// CHECKDSO-NEXT:     0x3028 R_AARCH64_JUMP_SLOT weak
 // CHECKDSO-NEXT:   }
 // CHECKDSO-NEXT: ]
 
 // DUMPDSO: Contents of section .got.plt:
 // .got.plt[0..2] = 0 (reserved)
 // .got.plt[3..5] = .plt = 0x1010
-// DUMPDSO-NEXT:  20b0 00000000 00000000 00000000 00000000  ................
-// DUMPDSO-NEXT:  20c0 00000000 00000000 10100000 00000000  ................
-// DUMPDSO-NEXT:  20d0 10100000 00000000 10100000 00000000  ................
+// DUMPDSO-NEXT:  3000 00000000 00000000 00000000 00000000  ................
+// DUMPDSO-NEXT:  3010 00000000 00000000 10100000 00000000  ................
+// DUMPDSO-NEXT:  3020 10100000 00000000 10100000 00000000  ................
 
 // DISASMDSO: _start:
 // 0x1030 - 0x1000 = 0x30 = 48
 // DISASMDSO-NEXT:     1000:	0c 00 00 14 	b	#48
 // 0x1040 - 0x1004 = 0x3c = 60
 // DISASMDSO-NEXT:     1004:	0f 00 00 14 	b	#60
 // 0x1050 - 0x1008 = 0x48 = 72
 // DISASMDSO-NEXT:     1008:	12 00 00 14 	b	#72
 
 // DISASMDSO: foo:
 // DISASMDSO-NEXT:     100c:	1f 20 03 d5 	nop
 
 // DISASMDSO: Disassembly of section .plt:
 // DISASMDSO-NEXT: .plt:
 // DISASMDSO-NEXT:     1010:	f0 7b bf a9 	stp	x16, x30, [sp, #-16]!
-// &(.got.plt[2]) = 0x20B0 + 2 * 8 = 0x20C0
-// Page(0x20C0) - Page(0x1014) = 0x2000 - 0x1000 = 0x1000 = 4096
-// DISASMDSO-NEXT:     1014:	10 00 00 b0 	adrp	x16, #4096
-// 0x20c0 & 0xFFF = 0xC0 = 192
-// DISASMDSO-NEXT:     1018:	11 62 40 f9 	ldr	x17, [x16, #192]
-// DISASMDSO-NEXT:     101c:	10 02 03 91 	add	x16, x16, #192
+// &(.got.plt[2]) = 0x3000 + 2 * 8 = 0x3010
+// Page(0x3010) - Page(0x1014) = 0x3000 - 0x1000 = 0x2000 = 8192
+// DISASMDSO-NEXT:     1014:	10 00 00 d0 	adrp	x16, #8192
+// 0x3010 & 0xFFF = 0x10 = 16
+// DISASMDSO-NEXT:     1018:	11 0a 40 f9 ldr x17, [x16, #16]
+// DISASMDSO-NEXT:     101c:	10 42 00 91 	add	x16, x16, #16
 // DISASMDSO-NEXT:     1020:	20 02 1f d6 	br	x17
 // DISASMDSO-NEXT:     1024:	1f 20 03 d5 	nop
 // DISASMDSO-NEXT:     1028:	1f 20 03 d5 	nop
 // DISASMDSO-NEXT:     102c:	1f 20 03 d5 	nop
 
 // foo at plt
-// Page(0x20C8) - Page(0x1030) = 0x2000 - 0x1000 = 0x1000 = 4096
-// DISASMDSO-NEXT:     1030:	10 00 00 b0 	adrp	x16, #4096
-// 0x20C8 & 0xFFF = 0xC8 = 200
-// DISASMDSO-NEXT:     1034:	11 66 40 f9 	ldr	x17, [x16, #200]
-// DISASMDSO-NEXT:     1038:	10 22 03 91 	add	x16, x16, #200
+// Page(0x3018) - Page(0x1030) = 0x3000 - 0x1000 = 0x2000 = 8192
+// DISASMDSO-NEXT:     1030:	10 00 00 d0 	adrp	x16, #8192
+// 0x3018 & 0xFFF = 0x18 = 24
+// DISASMDSO-NEXT:     1034:	11 0e 40 f9 	ldr	x17, [x16, #24]
+// DISASMDSO-NEXT:     1038:	10 62 00 91 	add	x16, x16, #24
 // DISASMDSO-NEXT:     103c:	20 02 1f d6 	br	x17
 
 // bar at plt
-// Page(0x20D0) - Page(0x1040) = 0x2000 - 0x1000 = 0x1000 = 4096
-// DISASMDSO-NEXT:     1040:	10 00 00 b0 	adrp	x16, #4096
-// 0x20D0 & 0xFFF = 0xD0 = 208
-// DISASMDSO-NEXT:     1044:	11 6a 40 f9 	ldr	x17, [x16, #208]
-// DISASMDSO-NEXT:     1048:	10 42 03 91 	add	x16, x16, #208
+// Page(0x3020) - Page(0x1040) = 0x3000 - 0x1000 = 0x2000 = 8192
+// DISASMDSO-NEXT:     1040:	10 00 00 d0 	adrp	x16, #8192
+// 0x3020 & 0xFFF = 0x20 = 32
+// DISASMDSO-NEXT:     1044:	11 12 40 f9 	ldr	x17, [x16, #32]
+// DISASMDSO-NEXT:     1048:	10 82 00 91 	add	x16, x16, #32
 // DISASMDSO-NEXT:     104c:	20 02 1f d6 	br	x17
 
 // weak at plt
-// Page(0x20D8) - Page(0x1050) = 0x2000 - 0x1000 = 0x1000 = 4096
-// DISASMDSO-NEXT:     1050:	10 00 00 b0 	adrp	x16, #4096
-// 0x20D8 & 0xFFF = 0xD8 = 216
-// DISASMDSO-NEXT:     1054:	11 6e 40 f9 	ldr	x17, [x16, #216]
-// DISASMDSO-NEXT:     1058:	10 62 03 91 	add	x16, x16, #216
+// Page(0x3028) - Page(0x1050) = 0x3000 - 0x1000 = 0x2000 = 8192
+// DISASMDSO-NEXT:     1050:	10 00 00 d0 	adrp	x16, #8192
+// 0x3028 & 0xFFF = 0x28 = 40
+// DISASMDSO-NEXT:     1054:	11 16 40 f9 	ldr	x17, [x16, #40]
+// DISASMDSO-NEXT:     1058:	10 a2 00 91 	add	x16, x16, #40
 // DISASMDSO-NEXT:     105c:	20 02 1f d6 	br	x17
 
 // CHECKEXE:     Name: .plt
 // CHECKEXE-NEXT:     Type: SHT_PROGBITS
 // CHECKEXE-NEXT:     Flags [
 // CHECKEXE-NEXT:       SHF_ALLOC
 // CHECKEXE-NEXT:       SHF_EXECINSTR
 // CHECKEXE-NEXT:     ]
 // CHECKEXE-NEXT:     Address: 0x11010
 // CHECKEXE-NEXT:     Offset:
 // CHECKEXE-NEXT:     Size: 64
 // CHECKEXE-NEXT:     Link:
 // CHECKEXE-NEXT:     Info:
 // CHECKEXE-NEXT:     AddressAlignment: 16
 
 // CHECKEXE:     Name: .got.plt
 // CHECKEXE-NEXT:     Type: SHT_PROGBITS
 // CHECKEXE-NEXT:     Flags [
 // CHECKEXE-NEXT:       SHF_ALLOC
 // CHECKEXE-NEXT:       SHF_WRITE
 // CHECKEXE-NEXT:     ]
-// CHECKEXE-NEXT:     Address: 0x120B0
+// CHECKEXE-NEXT:     Address: 0x13000
 // CHECKEXE-NEXT:     Offset:
 // CHECKEXE-NEXT:     Size: 40
 // CHECKEXE-NEXT:     Link:
 // CHECKEXE-NEXT:     Info:
 // CHECKEXE-NEXT:     AddressAlignment: 8
 
 // CHECKEXE: Relocations [
 // CHECKEXE-NEXT:   Section ({{.*}}) .rela.plt {
 
-// &(.got.plt[3]) = 0x120B0 + 3 * 8 = 0x120C8
-// CHECKEXE-NEXT:     0x120C8 R_AARCH64_JUMP_SLOT bar 0x0
+// &(.got.plt[3]) = 0x13000 + 3 * 8 = 0x13018
+// CHECKEXE-NEXT:     0x13018 R_AARCH64_JUMP_SLOT bar 0x0
 
-// &(.got.plt[4]) = 0x120B0 + 4 * 8 = 0x120D0
-// CHECKEXE-NEXT:     0x120D0 R_AARCH64_JUMP_SLOT weak 0x0
+// &(.got.plt[4]) = 0x13000 + 4 * 8 = 0x13020
+// CHECKEXE-NEXT:     0x13020 R_AARCH64_JUMP_SLOT weak 0x0
 // CHECKEXE-NEXT:   }
 // CHECKEXE-NEXT: ]
 
 // DUMPEXE: Contents of section .got.plt:
 // .got.plt[0..2] = 0 (reserved)
 // .got.plt[3..4] = .plt = 0x11010
-// DUMPEXE-NEXT:  120b0 00000000 00000000 00000000 00000000  ................
-// DUMPEXE-NEXT:  120c0 00000000 00000000 10100100 00000000  ................
-// DUMPEXE-NEXT:  120d0 10100100 00000000                    ........
+// DUMPEXE-NEXT:  13000 00000000 00000000 00000000 00000000  ................
+// DUMPEXE-NEXT:  13010 00000000 00000000 10100100 00000000  ................
+// DUMPEXE-NEXT:  13020 10100100 00000000                    ........
 
 // DISASMEXE: _start:
 // 0x1100c - 0x11000 = 0xc = 12
 // DISASMEXE-NEXT:    11000:	03 00 00 14 	b	#12
 // 0x11030 - 0x11004 = 0x2c = 44
 // DISASMEXE-NEXT:    11004:	0b 00 00 14 	b	#44
 // 0x11040 - 0x11008 = 0x38 = 56
 // DISASMEXE-NEXT:    11008:	0e 00 00 14 	b	#56
 
 // DISASMEXE: foo:
 // DISASMEXE-NEXT:    1100c:	1f 20 03 d5 	nop
 
 // DISASMEXE: Disassembly of section .plt:
 // DISASMEXE-NEXT: .plt:
 // DISASMEXE-NEXT:    11010:	f0 7b bf a9 	stp	x16, x30, [sp, #-16]!
 // &(.got.plt[2]) = 0x120B0 + 2 * 8 = 0x120C0
-// Page(0x120C0) - Page(0x11014) = 0x12000 - 0x11000 = 0x1000 = 4096
-// DISASMEXE-NEXT:    11014:	10 00 00 b0 	adrp	x16, #4096
+// Page(0x13010) - Page(0x11014) = 0x13000 - 0x11000 = 0x1000 = 8192
+// DISASMEXE-NEXT:    11014:	10 00 00 d0  	adrp	x16, #8192
 // 0x120c0 & 0xFFF = 0xC0 = 192
-// DISASMEXE-NEXT:    11018:	11 62 40 f9 	ldr	x17, [x16, #192]
-// DISASMEXE-NEXT:    1101c:	10 02 03 91 	add	x16, x16, #192
+// DISASMEXE-NEXT:    11018:	11 0a 40 f9 	ldr	x17, [x16, #16]
+// DISASMEXE-NEXT:    1101c:	10 42 00 91 	add	x16, x16, #16
 // DISASMEXE-NEXT:    11020:	20 02 1f d6 	br	x17
 // DISASMEXE-NEXT:    11024:	1f 20 03 d5 	nop
 // DISASMEXE-NEXT:    11028:	1f 20 03 d5 	nop
 // DISASMEXE-NEXT:    1102c:	1f 20 03 d5 	nop
 
 // bar at plt
-// Page(0x120C8) - Page(0x11030) = 0x12000 - 0x11000 = 0x1000 = 4096
-// DISASMEXE-NEXT:    11030:	10 00 00 b0 	adrp	x16, #4096
+// Page(0x13018) - Page(0x11030) = 0x12000 - 0x11000 = 0x1000 = 8192
+// DISASMEXE-NEXT:    11030:	10 00 00 d0 	adrp	x16, #8192
 // 0x120C8 & 0xFFF = 0xC8 = 200
-// DISASMEXE-NEXT:    11034:	11 66 40 f9 	ldr	x17, [x16, #200]
-// DISASMEXE-NEXT:    11038:	10 22 03 91 	add	x16, x16, #200
+// DISASMEXE-NEXT:    11034:	11 0e 40 f9 	ldr	x17, [x16, #24]
+// DISASMEXE-NEXT:    11038:	10 62 00 91 	add	x16, x16, #24
 // DISASMEXE-NEXT:    1103c:	20 02 1f d6 	br	x17
 
 // weak at plt
-// Page(0x120D0) - Page(0x11040) = 0x12000 - 0x11000 = 0x1000 = 4096
-// DISASMEXE-NEXT:    11040:	10 00 00 b0 	adrp	x16, #4096
+// Page(0x13020) - Page(0x11040) = 0x12000 - 0x11000 = 0x1000 = 8192
+// DISASMEXE-NEXT:    11040:	10 00 00 d0 	adrp	x16, #8192
 // 0x120D0 & 0xFFF = 0xD0 = 208
-// DISASMEXE-NEXT:    11044:	11 6a 40 f9 	ldr	x17, [x16, #208]
-// DISASMEXE-NEXT:    11048:	10 42 03 91 	add	x16, x16, #208
+// DISASMEXE-NEXT:    11044:	11 12 40 f9 	ldr	x17, [x16, #32]
+// DISASMEXE-NEXT:    11048:	10 82 00 91 	add	x16, x16, #32
 // DISASMEXE-NEXT:    1104c:	20 02 1f d6 	br	x17
 
 .global _start,foo,bar
 .weak weak
 _start:
   b foo
   b bar
   b weak
 
 .section .text2,"ax", at progbits
 foo:
   nop
diff --git a/test/ELF/plt-i686.s b/test/ELF/plt-i686.s
index 7f50967..4947e0e 100644
--- a/test/ELF/plt-i686.s
+++ b/test/ELF/plt-i686.s
@@ -1,158 +1,158 @@
 // RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
 // RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o
 // RUN: ld.lld -shared %t2.o -o %t2.so
 // RUN: ld.lld %t.o %t2.so -o %t
 // RUN: llvm-readobj -s -r %t | FileCheck --check-prefix=CHECK %s
 // RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
 // RUN: ld.lld -shared %t.o %t2.so -o %t
 // RUN: llvm-readobj -s -r %t | FileCheck --check-prefix=CHECKSHARED %s
 // RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASMSHARED %s
 
 // REQUIRES: x86
 
 // CHECK:      Name: .plt
 // CHECK-NEXT: Type: SHT_PROGBITS
 // CHECK-NEXT: Flags [
 // CHECK-NEXT:   SHF_ALLOC
 // CHECK-NEXT:   SHF_EXECINSTR
 // CHECK-NEXT: ]
 // CHECK-NEXT: Address: 0x11020
 // CHECK-NEXT: Offset:
 // CHECK-NEXT: Size: 48
 // CHECK-NEXT: Link: 0
 // CHECK-NEXT: Info: 0
 // CHECK-NEXT: AddressAlignment: 16
 
 // CHECK:      Name: .got.plt
 // CHECK-NEXT: Type: SHT_PROGBITS
 // CHECK-NEXT: Flags [
 // CHECK-NEXT:   SHF_ALLOC
 // CHECK-NEXT:   SHF_WRITE
 // CHECK-NEXT: ]
-// CHECK-NEXT: Address: 0x12058
-// CHECK-NEXT: Offset: 0x2058
+// CHECK-NEXT: Address: 0x13000
+// CHECK-NEXT: Offset: 0x3000
 // CHECK-NEXT: Size: 20
 // CHECK-NEXT: Link: 0
 // CHECK-NEXT: Info: 0
 // CHECK-NEXT: AddressAlignment: 4
 // CHECK-NEXT: EntrySize: 0
 
-// 0x12058 + got.plt.reserved(12) = 0x12064
-// 0x12058 + got.plt.reserved(12) + 4 = 0x12068
+// 0x13000 + got.plt.reserved(12) = 0x1300C
+// 0x13000 + got.plt.reserved(12) + 4 = 0x13010
 // CHECK:      Relocations [
 // CHECK-NEXT:   Section ({{.*}}) .rel.plt {
-// CHECK-NEXT:     0x12064 R_386_JUMP_SLOT bar 0x0
-// CHECK-NEXT:     0x12068 R_386_JUMP_SLOT zed 0x0
+// CHECK-NEXT:     0x1300C R_386_JUMP_SLOT bar 0x0
+// CHECK-NEXT:     0x13010 R_386_JUMP_SLOT zed 0x0
 // CHECK-NEXT:   }
 // CHECK-NEXT: ]
 
 // Unfortunately FileCheck can't do math, so we have to check for explicit
 // values:
 
 // 16 is the size of PLT[0]
 // (0x11010 + 16) - (0x11000 + 1) - 4 = 27
 // (0x11010 + 16) - (0x11005 + 1) - 4 = 22
 // (0x11020 + 16) - (0x1100a + 1) - 4 = 33
 
 // DISASM:       local:
 // DISASM-NEXT:  11000: {{.*}}
 // DISASM-NEXT:  11002: {{.*}}
 // DISASM:       _start:
 // 0x11013 + 5 - 24 = 0x11000
 // DISASM-NEXT: 11004: e9 27 00 00 00 jmp 39
 // DISASM-NEXT: 11009: e9 22 00 00 00 jmp 34
 // DISASM-NEXT: 1100e: e9 2d 00 00 00 jmp 45
 // DISASM-NEXT: 11013: e9 e8 ff ff ff jmp -24
 
 // 0x11010 - 0x1102b - 5 = -32
 // 0x11010 - 0x1103b - 5 = -48
-// 73820 = 0x1205C = .got.plt (0x12058) + 4
-// 73824 = 0x12060 = .got.plt (0x12058) + 8
-// 73828 = 0x12064 = .got.plt (0x12058) + got.plt.reserved(12)
-// 73832 = 0x12068 = .got.plt (0x12058) + got.plt.reserved(12) + 4
+// 77828 = 0x13004 = .got.plt (0x13000) + 4
+// 77832 = 0x13008 = .got.plt (0x13000) + 8
+// 77836 = 0x1300C = .got.plt (0x13000) + got.plt.reserved(12)
+// 77840 = 0x13010 = .got.plt (0x13000) + got.plt.reserved(12) + 4
 // DISASM:      Disassembly of section .plt:
 // DISASM-NEXT: .plt:
-// DISASM-NEXT:    11020: ff 35 5c 20 01 00 pushl 73820
-// DISASM-NEXT:    11026: ff 25 60 20 01 00 jmpl *73824
+// DISASM-NEXT:    11020: ff 35 04 30 01 00 pushl 77828
+// DISASM-NEXT:    11026: ff 25 08 30 01 00 jmpl *77832
 // DISASM-NEXT:    1102c: 90 nop
 // DISASM-NEXT:    1102d: 90 nop
 // DISASM-NEXT:    1102e: 90 nop
 // DISASM-NEXT:    1102f: 90 nop
-// DISASM-NEXT:    11030: ff 25 64 20 01 00 jmpl *73828
+// DISASM-NEXT:    11030: ff 25 0c 30 01 00 jmpl *77836
 // DISASM-NEXT:    11036: 68 00 00 00 00 pushl $0
 // DISASM-NEXT:    1103b: e9 e0 ff ff ff jmp -32 <.plt>
-// DISASM-NEXT:    11040: ff 25 68 20 01 00 jmpl *73832
+// DISASM-NEXT:    11040: ff 25 10 30 01 00 jmpl *77840
 // DISASM-NEXT:    11046: 68 08 00 00 00 pushl $8
 // DISASM-NEXT:    1104b: e9 d0 ff ff ff jmp -48 <.plt>
 
 // CHECKSHARED:        Name: .plt
 // CHECKSHARED-NEXT:   Type: SHT_PROGBITS
 // CHECKSHARED-NEXT:   Flags [
 // CHECKSHARED-NEXT:     SHF_ALLOC
 // CHECKSHARED-NEXT:     SHF_EXECINSTR
 // CHECKSHARED-NEXT:   ]
 // CHECKSHARED-NEXT:   Address: 0x1020
 // CHECKSHARED-NEXT:   Offset: 0x1020
 // CHECKSHARED-NEXT:   Size: 48
 // CHECKSHARED-NEXT:   Link: 0
 // CHECKSHARED-NEXT:   Info: 0
 // CHECKSHARED-NEXT:   AddressAlignment: 16
 // CHECKSHARED-NEXT:   EntrySize: 0
 // CHECKSHARED-NEXT:   }
 // CHECKSHARED:        Name: .got.plt
 // CHECKSHARED-NEXT:   Type: SHT_PROGBITS
 // CHECKSHARED-NEXT:   Flags [
 // CHECKSHARED-NEXT:     SHF_ALLOC
 // CHECKSHARED-NEXT:     SHF_WRITE
 // CHECKSHARED-NEXT:   ]
-// CHECKSHARED-NEXT:   Address: 0x2058
-// CHECKSHARED-NEXT:   Offset: 0x2058
+// CHECKSHARED-NEXT:   Address: 0x3000
+// CHECKSHARED-NEXT:   Offset: 0x3000
 // CHECKSHARED-NEXT:   Size: 20
 // CHECKSHARED-NEXT:   Link: 0
 // CHECKSHARED-NEXT:   Info: 0
 // CHECKSHARED-NEXT:   AddressAlignment: 4
 // CHECKSHARED-NEXT:   EntrySize: 0
 // CHECKSHARED-NEXT:   }
 
-// 0x2058 + got.plt.reserved(12) = 0x2064
-// 0x2058 + got.plt.reserved(12) + 4 = 0x2068
+// 0x3000 + got.plt.reserved(12) = 0x300C
+// 0x3000 + got.plt.reserved(12) + 4 = 0x3010
 // CHECKSHARED:        Relocations [
 // CHECKSHARED-NEXT:     Section ({{.*}}) .rel.plt {
-// CHECKSHARED-NEXT:       0x2064 R_386_JUMP_SLOT bar 0x0
-// CHECKSHARED-NEXT:       0x2068 R_386_JUMP_SLOT zed 0x0
+// CHECKSHARED-NEXT:       0x300C R_386_JUMP_SLOT bar 0x0
+// CHECKSHARED-NEXT:       0x3010 R_386_JUMP_SLOT zed 0x0
 // CHECKSHARED-NEXT:     }
 // CHECKSHARED-NEXT:   ]
 
 // DISASMSHARED:       local:
 // DISASMSHARED-NEXT:  1000: {{.*}}
 // DISASMSHARED-NEXT:  1002: {{.*}}
 // DISASMSHARED:       _start:
 // 0x1013 + 5 - 24 = 0x1000
 // DISASMSHARED-NEXT:  1004: e9 27 00 00 00 jmp 39
 // DISASMSHARED-NEXT:  1009: e9 22 00 00 00 jmp 34
 // DISASMSHARED-NEXT:  100e: e9 2d 00 00 00 jmp 45
 // DISASMSHARED-NEXT:  1013: e9 e8 ff ff ff jmp -24
 // DISASMSHARED-NEXT:  Disassembly of section .plt:
 // DISASMSHARED-NEXT:  .plt:
 // DISASMSHARED-NEXT:  1020: ff b3 04 00 00 00  pushl 4(%ebx)
 // DISASMSHARED-NEXT:  1026: ff a3 08 00 00 00  jmpl *8(%ebx)
 // DISASMSHARED-NEXT:  102c: 90 nop
 // DISASMSHARED-NEXT:  102d: 90 nop
 // DISASMSHARED-NEXT:  102e: 90 nop
 // DISASMSHARED-NEXT:  102f: 90 nop
 // DISASMSHARED-NEXT:  1030: ff a3 0c 00 00 00  jmpl *12(%ebx)
 // DISASMSHARED-NEXT:  1036: 68 00 00 00 00     pushl $0
 // DISASMSHARED-NEXT:  103b: e9 e0 ff ff ff     jmp -32 <.plt>
 // DISASMSHARED-NEXT:  1040: ff a3 10 00 00 00  jmpl *16(%ebx)
 // DISASMSHARED-NEXT:  1046: 68 08 00 00 00     pushl $8
 // DISASMSHARED-NEXT:  104b: e9 d0 ff ff ff     jmp -48 <.plt>
 
 local:
 .long 0
 
 .global _start
 _start:
   jmp bar at PLT
   jmp bar at PLT
   jmp zed at PLT
   jmp local at plt
diff --git a/test/ELF/plt.s b/test/ELF/plt.s
index 0159091..1183d32 100644
--- a/test/ELF/plt.s
+++ b/test/ELF/plt.s
@@ -1,119 +1,119 @@
 // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
 // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
 // RUN: ld.lld -shared %t2.o -o %t2.so
 // RUN: ld.lld -shared %t.o %t2.so -o %t
 // RUN: ld.lld %t.o %t2.so -o %t3
 // RUN: llvm-readobj -s -r %t | FileCheck %s
 // RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
 // RUN: llvm-readobj -s -r %t3 | FileCheck --check-prefix=CHECK2 %s
 // RUN: llvm-objdump -d %t3 | FileCheck --check-prefix=DISASM2 %s
 
 // REQUIRES: x86
 
 // CHECK:      Name: .plt
 // CHECK-NEXT: Type: SHT_PROGBITS
 // CHECK-NEXT: Flags [
 // CHECK-NEXT:   SHF_ALLOC
 // CHECK-NEXT:   SHF_EXECINSTR
 // CHECK-NEXT: ]
 // CHECK-NEXT: Address: 0x1020
 // CHECK-NEXT: Offset:
 // CHECK-NEXT: Size: 64
 // CHECK-NEXT: Link: 0
 // CHECK-NEXT: Info: 0
 // CHECK-NEXT: AddressAlignment: 16
 
 // CHECK:      Relocations [
 // CHECK-NEXT:   Section ({{.*}}) .rela.plt {
-// CHECK-NEXT:     0x20C8 R_X86_64_JUMP_SLOT bar 0x0
-// CHECK-NEXT:     0x20D0 R_X86_64_JUMP_SLOT zed 0x0
-// CHECK-NEXT:     0x20D8 R_X86_64_JUMP_SLOT _start 0x0
+// CHECK-NEXT:     0x3018 R_X86_64_JUMP_SLOT bar 0x0
+// CHECK-NEXT:     0x3020 R_X86_64_JUMP_SLOT zed 0x0
+// CHECK-NEXT:     0x3028 R_X86_64_JUMP_SLOT _start 0x0
 // CHECK-NEXT:   }
 // CHECK-NEXT: ]
 
 // CHECK2:      Name: .plt
 // CHECK2-NEXT: Type: SHT_PROGBITS
 // CHECK2-NEXT: Flags [
 // CHECK2-NEXT:   SHF_ALLOC
 // CHECK2-NEXT:   SHF_EXECINSTR
 // CHECK2-NEXT: ]
 // CHECK2-NEXT: Address: 0x11020
 // CHECK2-NEXT: Offset:
 // CHECK2-NEXT: Size: 48
 // CHECK2-NEXT: Link: 0
 // CHECK2-NEXT: Info: 0
 // CHECK2-NEXT: AddressAlignment: 16
 
 // CHECK2:      Relocations [
 // CHECK2-NEXT:   Section ({{.*}}) .rela.plt {
-// CHECK2-NEXT:     0x120C8 R_X86_64_JUMP_SLOT bar 0x0
-// CHECK2-NEXT:     0x120D0 R_X86_64_JUMP_SLOT zed 0x0
+// CHECK2-NEXT:     0x13018 R_X86_64_JUMP_SLOT bar 0x0
+// CHECK2-NEXT:     0x13020 R_X86_64_JUMP_SLOT zed 0x0
 // CHECK2-NEXT:   }
 // CHECK2-NEXT: ]
 
 // Unfortunately FileCheck can't do math, so we have to check for explicit
 // values:
 
 // 0x1030 - (0x1000 + 5) = 43
 // 0x1030 - (0x1005 + 5) = 38
 // 0x1040 - (0x100a + 5) = 49
 // 0x1048 - (0x100a + 5) = 60
 
 // DISASM:      _start:
 // DISASM-NEXT:   1000:  e9 {{.*}}       jmp  43
 // DISASM-NEXT:   1005:  e9 {{.*}}       jmp  38
 // DISASM-NEXT:   100a:  e9 {{.*}}       jmp  49
 // DISASM-NEXT:   100f:  e9 {{.*}}       jmp  60
 
-// 0x20C8 - 0x1036  = 4242
-// 0x20D0 - 0x1046  = 4234
-// 0x20D8 - 0x1056  = 4226
+// 0x3018 - 0x1036  = 8162
+// 0x3020 - 0x1046  = 4234
+// 0x3028 - 0x1056  = 4226
 
 // DISASM:      Disassembly of section .plt:
 // DISASM-NEXT: .plt:
-// DISASM-NEXT:   1020:  ff 35 92 10 00 00  pushq 4242(%rip)
-// DISASM-NEXT:   1026:  ff 25 94 10 00 00  jmpq *4244(%rip)
+// DISASM-NEXT:   1020:  ff 35 e2 1f 00 00  pushq 8162(%rip)
+// DISASM-NEXT:   1026:  ff 25 e4 1f 00 00  jmpq *8164(%rip)
 // DISASM-NEXT:   102c:  0f 1f 40 00        nopl (%rax)
-// DISASM-NEXT:   1030:  ff 25 92 10 00 00  jmpq *4242(%rip)
+// DISASM-NEXT:   1030:  ff 25 e2 1f 00 00  jmpq *8162(%rip)
 // DISASM-NEXT:   1036:  68 00 00 00 00     pushq $0
 // DISASM-NEXT:   103b:  e9 e0 ff ff ff     jmp -32 <.plt>
-// DISASM-NEXT:   1040:  ff 25 8a 10 00 00  jmpq *4234(%rip)
+// DISASM-NEXT:   1040:  ff 25 da 1f 00 00  jmpq *8154(%rip)
 // DISASM-NEXT:   1046:  68 01 00 00 00     pushq $1
 // DISASM-NEXT:   104b:  e9 d0 ff ff ff     jmp -48 <.plt>
-// DISASM-NEXT:   1050:  ff 25 82 10 00 00  jmpq *4226(%rip)
+// DISASM-NEXT:   1050:  ff 25 d2 1f 00 00  jmpq *8146(%rip)
 // DISASM-NEXT:   1056:  68 02 00 00 00     pushq $2
 // DISASM-NEXT:   105b:  e9 c0 ff ff ff     jmp -64 <.plt>
 
 // 0x11030 - (0x11000 + 1) - 4 = 43
 // 0x11030 - (0x11005 + 1) - 4 = 38
 // 0x11040 - (0x1100a + 1) - 4 = 49
 // 0x11000 - (0x1100f + 1) - 4 = -20
 
 // DISASM2:      _start:
 // DISASM2-NEXT:   11000:  e9 {{.*}}     jmp  43
 // DISASM2-NEXT:   11005:  e9 {{.*}}     jmp  38
 // DISASM2-NEXT:   1100a:  e9 {{.*}}     jmp  49
 // DISASM2-NEXT:   1100f:  e9 {{.*}}     jmp  -20
 
-// 0x120C8 - 0x11036  = 4242
-// 0x120D0 - 0x11046  = 4234
+// 0x13018 - 0x11036  = 4242
+// 0x13020 - 0x11046  = 4234
 
 // DISASM2:      Disassembly of section .plt:
 // DISASM2-NEXT: .plt:
-// DISASM2-NEXT:  11020:  ff 35 92 10 00 00   pushq 4242(%rip)
-// DISASM2-NEXT:  11026:  ff 25 94 10 00 00   jmpq *4244(%rip)
+// DISASM2-NEXT:  11020:  ff 35 e2 1f 00 00   pushq 8162(%rip)
+// DISASM2-NEXT:  11026:  ff 25 e4 1f 00 00   jmpq *8164(%rip)
 // DISASM2-NEXT:  1102c:  0f 1f 40 00         nopl  (%rax)
-// DISASM2-NEXT:  11030:  ff 25 92 10 00 00   jmpq *4242(%rip)
+// DISASM2-NEXT:  11030:  ff 25 e2 1f 00 00   jmpq *8162(%rip)
 // DISASM2-NEXT:  11036:  68 00 00 00 00      pushq $0
 // DISASM2-NEXT:  1103b:  e9 e0 ff ff ff      jmp -32 <.plt>
-// DISASM2-NEXT:  11040:  ff 25 8a 10 00 00   jmpq *4234(%rip)
+// DISASM2-NEXT:  11040:  ff 25 da 1f 00 00   jmpq *8154(%rip)
 // DISASM2-NEXT:  11046:  68 01 00 00 00      pushq $1
 // DISASM2-NEXT:  1104b:  e9 d0 ff ff ff      jmp -48 <.plt>
 // DISASM2-NEXT-NOT: 110C0
 
 .global _start
 _start:
   jmp bar at PLT
   jmp bar at PLT
   jmp zed at PLT
   jmp _start at plt
diff --git a/test/ELF/ppc64-shared-rel-toc.s b/test/ELF/ppc64-shared-rel-toc.s
index aa8654a..f5cd459 100644
--- a/test/ELF/ppc64-shared-rel-toc.s
+++ b/test/ELF/ppc64-shared-rel-toc.s
@@ -1,27 +1,27 @@
 // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
 // RUN: ld.lld -shared %t.o -o %t.so
 // RUN: llvm-readobj -t -r -dyn-symbols %t.so | FileCheck %s
 // REQUIRES: ppc
 
 // When we create the TOC reference in the shared library, make sure that the
 // R_PPC64_RELATIVE relocation uses the correct (non-zero) offset.
 
         .globl  foo
         .align  2
         .type   foo, at function
         .section        .opd,"aw", at progbits
 foo:                                    # @foo
         .align  3
         .quad   .Lfunc_begin0
         .quad   .TOC. at tocbase
         .quad   0
         .text
 .Lfunc_begin0:
         blr
 
-// CHECK: 0x20090 R_PPC64_RELATIVE - 0x10000
-// CHECK: 0x20098 R_PPC64_RELATIVE - 0x8000
+// CHECK: 0x30000 R_PPC64_RELATIVE - 0x10000
+// CHECK: 0x30008 R_PPC64_RELATIVE - 0x8000
 
 // CHECK: Name: foo
-// CHECK-NEXT: Value: 0x20090
+// CHECK-NEXT: Value: 0x30000
 
diff --git a/test/ELF/relocation-copy-i686.s b/test/ELF/relocation-copy-i686.s
index b537edf..d61f847 100644
--- a/test/ELF/relocation-copy-i686.s
+++ b/test/ELF/relocation-copy-i686.s
@@ -1,63 +1,63 @@
 // REQUIRES: x86
 // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
 // RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %p/Inputs/relocation-copy.s -o %t2.o
 // RUN: ld.lld -shared %t2.o -o %t.so
 // RUN: ld.lld -e main %t.o %t.so -o %t3
 // RUN: llvm-readobj -s -r --expand-relocs %t3 | FileCheck %s
 // RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=CODE %s
 
 .text
 .globl main
 .align 16, 0x90
 .type main, at function
 main:
 movl $5, x
 movl $7, y
 movl $9, z
 
 // CHECK:      Name: .bss
 // CHECK-NEXT:  Type: SHT_NOBITS
 // CHECK-NEXT:  Flags [
 // CHECK-NEXT:   SHF_ALLOC
 // CHECK-NEXT:   SHF_WRITE
 // CHECK-NEXT:  ]
-// CHECK-NEXT:  Address: 0x12050
-// CHECK-NEXT:  Offset: 0x2050
+// CHECK-NEXT:  Address: 0x13000
+// CHECK-NEXT:  Offset: 0x3000
 // CHECK-NEXT:  Size: 24
 // CHECK-NEXT:  Link: 0
 // CHECK-NEXT:  Info: 0
 // CHECK-NEXT:  AddressAlignment: 16
 // CHECK-NEXT:  EntrySize: 0
 
 // CHECK:      Relocations [
 // CHECK-NEXT:   Section ({{.*}}) .rel.dyn {
 // CHECK-NEXT:     Relocation {
 // CHECK-NEXT:       Offset:
 // CHECK-NEXT:       Type: R_386_COPY
 // CHECK-NEXT:       Symbol: x
 // CHECK-NEXT:       Addend: 0x0
 // CHECK-NEXT:     }
 // CHECK-NEXT:     Relocation {
 // CHECK-NEXT:       Offset:
 // CHECK-NEXT:       Type: R_386_COPY
 // CHECK-NEXT:       Symbol: y
 // CHECK-NEXT:       Addend: 0x0
 // CHECK-NEXT:     }
 // CHECK-NEXT:     Relocation {
 // CHECK-NEXT:       Offset:
 // CHECK-NEXT:       Type: R_386_COPY
 // CHECK-NEXT:       Symbol: z
 // CHECK-NEXT:       Addend: 0x0
 // CHECK-NEXT:     }
 // CHECK-NEXT:   }
 // CHECK-NEXT: ]
 
-// 73808 = 0x12050
+// 77824 = 0x13000
 // 16 is alignment here
-// 73824 = 0x12050 + 16
-// 73828 = 0x12050 + 16 + 4
+// 77840 = 0x13000 + 16
+// 77844 = 0x13000 + 16 + 4
 // CODE: Disassembly of section .text:
 // CODE-NEXT: main:
-// CODE-NEXT: 11000: c7 05 50 20 01 00 05 00 00 00 movl $5, 73808
-// CODE-NEXT: 1100a: c7 05 60 20 01 00 07 00 00 00 movl $7, 73824
-// CODE-NEXT: 11014: c7 05 64 20 01 00 09 00 00 00 movl $9, 73828
+// CODE-NEXT: 11000: c7 05 00 30 01 00 05 00 00 00 movl $5, 77824
+// CODE-NEXT: 1100a: c7 05 10 30 01 00 07 00 00 00 movl $7, 77840
+// CODE-NEXT: 11014: c7 05 14 30 01 00 09 00 00 00 movl $9, 77844
diff --git a/test/ELF/relocation-copy.s b/test/ELF/relocation-copy.s
index 17b3a64..85cbf67 100644
--- a/test/ELF/relocation-copy.s
+++ b/test/ELF/relocation-copy.s
@@ -1,63 +1,63 @@
 // REQUIRES: x86
 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/relocation-copy.s -o %t2.o
 // RUN: ld.lld -shared %t2.o -o %t.so
 // RUN: ld.lld -e main %t.o %t.so -o %t3
 // RUN: llvm-readobj -s -r --expand-relocs %t3 | FileCheck %s
 // RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=CODE %s
 
 .text
 .globl main
 .align 16, 0x90
 .type main, at function
 main:
 movl $5, x
 movl $7, y
 movl $9, z
 
 // CHECK:      Name: .bss
 // CHECK-NEXT:  Type: SHT_NOBITS (0x8)
 // CHECK-NEXT:  Flags [ (0x3)
 // CHECK-NEXT:   SHF_ALLOC (0x2)
 // CHECK-NEXT:   SHF_WRITE (0x1)
 // CHECK-NEXT:  ]
-// CHECK-NEXT:  Address: 0x120A0
-// CHECK-NEXT:  Offset: 0x20A0
+// CHECK-NEXT:  Address: 0x13000
+// CHECK-NEXT:  Offset: 0x3000
 // CHECK-NEXT:  Size: 24
 // CHECK-NEXT:  Link: 0
 // CHECK-NEXT:  Info: 0
 // CHECK-NEXT:  AddressAlignment: 16
 // CHECK-NEXT:  EntrySize: 0
 
 // CHECK:      Relocations [
 // CHECK-NEXT:   Section ({{.*}}) .rela.dyn {
 // CHECK-NEXT:     Relocation {
 // CHECK-NEXT:       Offset:
 // CHECK-NEXT:       Type: R_X86_64_COPY
 // CHECK-NEXT:       Symbol: x
 // CHECK-NEXT:       Addend: 0x0
 // CHECK-NEXT:     }
 // CHECK-NEXT:     Relocation {
 // CHECK-NEXT:       Offset:
 // CHECK-NEXT:       Type: R_X86_64_COPY
 // CHECK-NEXT:       Symbol: y
 // CHECK-NEXT:       Addend: 0x0
 // CHECK-NEXT:     }
 // CHECK-NEXT:     Relocation {
 // CHECK-NEXT:       Offset:
 // CHECK-NEXT:       Type: R_X86_64_COPY
 // CHECK-NEXT:       Symbol: z
 // CHECK-NEXT:       Addend: 0x0
 // CHECK-NEXT:     }
 // CHECK-NEXT:   }
 // CHECK-NEXT: ]
 
-// 73888 = 0x120A0
+// 77824 = 0x13000
 // 16 is alignment here
-// 73904 = 0x120A0 + 16
-// 73908 = 0x120A0 + 16 + 4
+// 77840 = 0x13000 + 16
+// 77844 = 0x13000 + 16 + 4
 // CODE: Disassembly of section .text:
 // CODE-NEXT: main:
-// CODE-NEXT: 11000: c7 04 25 a0 20 01 00 05 00 00 00 movl $5, 73888
-// CODE-NEXT: 1100b: c7 04 25 b0 20 01 00 07 00 00 00 movl $7, 73904
-// CODE-NEXT: 11016: c7 04 25 b4 20 01 00 09 00 00 00 movl $9, 73908
+// CODE-NEXT: 11000: c7 04 25 00 30 01 00 05 00 00 00 movl $5, 77824
+// CODE-NEXT: 1100b: c7 04 25 10 30 01 00 07 00 00 00 movl $7, 77840
+// CODE-NEXT: 11016: c7 04 25 14 30 01 00 09 00 00 00 movl $9, 77844
diff --git a/test/ELF/relocation.s b/test/ELF/relocation.s
index 9d4c03b..a6dd1d1 100644
--- a/test/ELF/relocation.s
+++ b/test/ELF/relocation.s
@@ -1,117 +1,117 @@
 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/shared.s -o %t2
 // RUN: ld.lld %t2 -o %t2.so -shared
 // RUN: ld.lld %t %t2.so -o %t3
 // RUN: llvm-readobj -s  %t3 | FileCheck --check-prefix=SEC %s
 // RUN: llvm-objdump -s -d %t3 | FileCheck %s
 // REQUIRES: x86
 
 // SEC:      Name: .plt
 // SEC-NEXT: Type: SHT_PROGBITS
 // SEC-NEXT: Flags [
 // SEC-NEXT:   SHF_ALLOC
 // SEC-NEXT:   SHF_EXECINSTR
 // SEC-NEXT: ]
 // SEC-NEXT: Address: 0x11030
 // SEC-NEXT: Offset: 0x1030
 // SEC-NEXT: Size: 32
 
 // SEC:         Name: .got
 // SEC-NEXT:   Type: SHT_PROGBITS
 // SEC-NEXT:   Flags [
 // SEC-NEXT:     SHF_ALLOC
 // SEC-NEXT:     SHF_WRITE
 // SEC-NEXT:   ]
 // SEC-NEXT:   Address: 0x120E0
 // SEC-NEXT:   Offset:
 // SEC-NEXT:   Size: 8
 // SEC-NEXT:   Link: 0
 // SEC-NEXT:   Info: 0
 // SEC-NEXT:   AddressAlignment: 8
 // SEC-NEXT:   EntrySize: 0
 // SEC-NEXT: }
 
 // SEC:        Name: .got.plt
 // SEC-NEXT:   Type: SHT_PROGBITS
 // SEC-NEXT:   Flags [
 // SEC-NEXT:     SHF_ALLOC
 // SEC-NEXT:     SHF_WRITE
 // SEC-NEXT:   ]
-// SEC-NEXT:   Address: 0x120E8
-// SEC-NEXT:   Offset: 0x20E8
+// SEC-NEXT:   Address: 0x13000
+// SEC-NEXT:   Offset: 0x3000
 // SEC-NEXT:   Size: 32
 // SEC-NEXT:   Link: 0
 // SEC-NEXT:   Info: 0
 // SEC-NEXT:   AddressAlignment: 8
 // SEC-NEXT:   EntrySize: 0
 // SEC-NEXT:   }
 
 .section       .text,"ax", at progbits,unique,1
 .global _start
 _start:
   call lulz
 
 .section       .text,"ax", at progbits,unique,2
 .zero 4
 .global lulz
 lulz:
   nop
 
 // CHECK: Disassembly of section .text:
 // CHECK-NEXT: _start:
 // CHECK-NEXT:   11000:  e8 04 00 00 00   callq 4
 // CHECK-NEXT:   11005:
 
 // CHECK:      lulz:
 // CHECK-NEXT:   11009:  90  nop
 
 
 .section       .text2,"ax", at progbits
 .global R_X86_64_32
 R_X86_64_32:
   movl $R_X86_64_32, %edx
 
 // FIXME: this would be far more self evident if llvm-objdump printed
 // constants in hex.
 // CHECK: Disassembly of section .text2:
 // CHECK-NEXT: R_X86_64_32:
 // CHECK-NEXT:  1100a: {{.*}} movl $69642, %edx
 
 .section .R_X86_64_32S,"ax", at progbits
 .global R_X86_64_32S
 R_X86_64_32S:
   movq lulz - 0x100000, %rdx
 
 // CHECK: Disassembly of section .R_X86_64_32S:
 // CHECK-NEXT: R_X86_64_32S:
 // CHECK-NEXT:  {{.*}}: {{.*}} movq -978935, %rdx
 
 .section .R_X86_64_PC32,"ax", at progbits
 .global R_X86_64_PC32
 R_X86_64_PC32:
  call bar
  movl $bar, %eax
 //16 is a size of PLT[0]
 // 0x11030 + 16 - (0x11017 + 5) = 20
 // CHECK:      Disassembly of section .R_X86_64_PC32:
 // CHECK-NEXT: R_X86_64_PC32:
 // CHECK-NEXT:  11017:   {{.*}}  callq  36
 // CHECK-NEXT:  1101c:   {{.*}}  movl $69696, %eax
 
 .section .R_X86_64_64,"a", at progbits
 .global R_X86_64_64
 R_X86_64_64:
  .quad R_X86_64_64
 
 // CHECK:      Contents of section .R_X86_64_64:
 // CHECK-NEXT:   101c8 c8010100 00000000
 
 .section .R_X86_64_GOTPCREL,"a", at progbits
 .global R_X86_64_GOTPCREL
 R_X86_64_GOTPCREL:
  .long zed at gotpcrel
 
 // 0x120E8 - 0x101D8 = 7952
 // 7952 = 0x101f0000 in little endian
 // CHECK:      Contents of section .R_X86_64_GOTPCREL
 // CHECK-NEXT:   101d0 101f0000
diff --git a/test/ELF/relro.s b/test/ELF/relro.s
index 43b0d34..7a225a2 100644
--- a/test/ELF/relro.s
+++ b/test/ELF/relro.s
@@ -1,243 +1,242 @@
 // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
 // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
 // RUN: ld.lld -shared %t2.o -o %t2.so
 // RUN: ld.lld %t.o %t2.so -z now -z relro -o %t
 // RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data %t | FileCheck --check-prefix=FULLRELRO %s
 // RUN: ld.lld %t.o %t2.so -z relro -o %t
 // RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data %t | FileCheck --check-prefix=PARTRELRO %s
 // RUN: ld.lld %t.o %t2.so -z norelro -o %t
 // RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data %t | FileCheck --check-prefix=NORELRO %s
 // REQUIRES: x86
 
 // FULLRELRO:        Section {
 // FULLRELRO:        Index: 9
 // FULLRELRO-NEXT:   Name: .got
 // FULLRELRO-NEXT:   Type: SHT_PROGBITS
 // FULLRELRO-NEXT:   Flags [
 // FULLRELRO-NEXT:     SHF_ALLOC
 // FULLRELRO-NEXT:     SHF_WRITE
 // FULLRELRO-NEXT:   ]
 // FULLRELRO-NEXT:   Address: 0x12100
 // FULLRELRO-NEXT:   Offset: 0x2100
 // FULLRELRO-NEXT:   Size: 8
 // FULLRELRO-NEXT:   Link: 0
 // FULLRELRO-NEXT:   Info: 0
 // FULLRELRO-NEXT:   AddressAlignment: 8
 // FULLRELRO-NEXT:   EntrySize: 0
 // FULLRELRO-NEXT:   SectionData (
 // FULLRELRO-NEXT:     0000: 00000000 00000000
 // FULLRELRO-NEXT:   )
 // FULLRELRO-NEXT: }
 // FULLRELRO-NEXT: Section {
 // FULLRELRO-NEXT:   Index: 10
 // FULLRELRO-NEXT:   Name: .got.plt
 // FULLRELRO-NEXT:   Type: SHT_PROGBITS
 // FULLRELRO-NEXT:   Flags [
 // FULLRELRO-NEXT:     SHF_ALLOC
 // FULLRELRO-NEXT:     SHF_WRITE
 // FULLRELRO-NEXT:   ]
 // FULLRELRO-NEXT:   Address: 0x12108
 // FULLRELRO-NEXT:   Offset: 0x2108
 // FULLRELRO-NEXT:   Size: 32
 // FULLRELRO-NEXT:   Link: 0
 // FULLRELRO-NEXT:   Info: 0
 // FULLRELRO-NEXT:   AddressAlignment: 8
 // FULLRELRO-NEXT:   EntrySize: 0
 // FULLRELRO-NEXT:   SectionData (
 // FULLRELRO-NEXT:     0000:
 // FULLRELRO-NEXT:     0010:
 // FULLRELRO-NEXT:   )
 // FULLRELRO-NEXT: }
 // FULLRELRO-NEXT: Section {
 // FULLRELRO-NEXT:   Index: 11
 // FULLRELRO-NEXT:   Name: .data
 // FULLRELRO-NEXT:   Type: SHT_PROGBITS
 // FULLRELRO-NEXT:   Flags [
 // FULLRELRO-NEXT:     SHF_ALLOC
 // FULLRELRO-NEXT:     SHF_WRITE
 // FULLRELRO-NEXT:   ]
-// FULLRELRO-NEXT:   Address: 0x12128
-// FULLRELRO-NEXT:   Offset: 0x2128
+// FULLRELRO-NEXT:   Address: 0x13000
+// FULLRELRO-NEXT:   Offset: 0x3000
 // FULLRELRO-NEXT:   Size: 12
 // FULLRELRO-NEXT:   Link: 0
 // FULLRELRO-NEXT:   Info: 0
 // FULLRELRO-NEXT:   AddressAlignment:
 // FULLRELRO-NEXT:   EntrySize: 0
 // FULLRELRO-NEXT:   SectionData (
 // FULLRELRO-NEXT:     0000:
 // FULLRELRO-NEXT:   )
 // FULLRELRO-NEXT: }
 // FULLRELRO-NEXT: Section {
 // FULLRELRO-NEXT:   Index: 12
 // FULLRELRO-NEXT:   Name: .foo
 // FULLRELRO-NEXT:   Type: SHT_PROGBITS
 // FULLRELRO-NEXT:   Flags [
 // FULLRELRO-NEXT:     SHF_ALLOC
 // FULLRELRO-NEXT:     SHF_WRITE
 // FULLRELRO-NEXT:   ]
-// FULLRELRO-NEXT:   Address: 0x12134
-// FULLRELRO-NEXT:   Offset: 0x2134
+// FULLRELRO-NEXT:   Address: 0x1300C
+// FULLRELRO-NEXT:   Offset: 0x300C
 // FULLRELRO-NEXT:   Size: 0
 // FULLRELRO-NEXT:   Link: 0
 // FULLRELRO-NEXT:   Info: 0
 // FULLRELRO-NEXT:   AddressAlignment:
 // FULLRELRO-NEXT:   EntrySize: 0
 // FULLRELRO-NEXT:   SectionData (
 // FULLRELRO-NEXT:   )
 // FULLRELRO-NEXT: }
 // 308 - sizeof(.data)(12) = 296
 // FULLRELRO:       ProgramHeaders [
 // FULLRELRO:       Type: PT_LOAD
 // FULLRELRO:       Offset: 0x2000
 // FULLRELRO-NEXT:  VirtualAddress: [[RWADDR:.*]]
 // FULLRELRO-NEXT:  PhysicalAddress:
-// FULLRELRO-NEXT:  FileSize: 308
-// FULLRELRO-NEXT:  MemSize: 308
+// FULLRELRO-NEXT:  FileSize: 4108
+// FULLRELRO-NEXT:  MemSize: 4108
 // FULLRELRO-NEXT:  Flags [
 // FULLRELRO-NEXT:    PF_R
 // FULLRELRO-NEXT:    PF_W
 // FULLRELRO-NEXT:  ]
 // FULLRELRO-NEXT:  Alignment: 4096
 // FULLRELRO-NEXT:}
 // FULLRELRO:       Type: PT_GNU_RELRO
 // FULLRELRO-NEXT:  Offset: 0x
 // FULLRELRO-NEXT:  VirtualAddress: [[RWADDR]]
 // FULLRELRO-NEXT:  PhysicalAddress:
 // FULLRELRO-NEXT:  FileSize: 296
 // FULLRELRO-NEXT:  MemSize: 296
 // FULLRELRO-NEXT:  Flags [
 // FULLRELRO-NEXT:    PF_R
 // FULLRELRO-NEXT:  ]
 // FULLRELRO-NEXT:  Alignment: 1
 // FULLRELRO-NEXT:}
 
 // PARTRELRO:       Section {
 // PARTRELRO:       Index: 9
 // PARTRELRO-NEXT:  Name: .got
 // PARTRELRO-NEXT:  Type: SHT_PROGBITS
 // PARTRELRO-NEXT:  Flags [
 // PARTRELRO-NEXT:    SHF_ALLOC
 // PARTRELRO-NEXT:    SHF_WRITE
 // PARTRELRO-NEXT:  ]
 // PARTRELRO-NEXT:  Address: 0x120E0
 // PARTRELRO-NEXT:  Offset: 0x20E0
 // PARTRELRO-NEXT:  Size: 8
 // PARTRELRO-NEXT:  Link: 0
 // PARTRELRO-NEXT:  Info: 0
 // PARTRELRO-NEXT:  AddressAlignment: 8
 // PARTRELRO-NEXT:  EntrySize: 0
 // PARTRELRO-NEXT:  SectionData (
 // PARTRELRO-NEXT:    0000:
 // PARTRELRO-NEXT:  )
 // PARTRELRO-NEXT:  }
 // PARTRELRO-NEXT:  Section {
 // PARTRELRO-NEXT:  Index: 10
 // PARTRELRO-NEXT:  Name: .data
 // PARTRELRO-NEXT:  Type: SHT_PROGBITS
 // PARTRELRO-NEXT:  Flags [
 // PARTRELRO-NEXT:    SHF_ALLOC
 // PARTRELRO-NEXT:    SHF_WRITE
 // PARTRELRO-NEXT:  ]
-// PARTRELRO-NEXT:  Address: 0x120E8
-// PARTRELRO-NEXT:  Offset: 0x20E8
+// PARTRELRO-NEXT:  Address: 0x13000
+// PARTRELRO-NEXT:  Offset: 0x3000
 // PARTRELRO-NEXT:  Size: 12
 // PARTRELRO-NEXT:  Link: 0
 // PARTRELRO-NEXT:  Info: 0
 // PARTRELRO-NEXT:  AddressAlignment: 1
 // PARTRELRO-NEXT:  EntrySize: 0
 // PARTRELRO-NEXT:  SectionData (
 // PARTRELRO-NEXT:    0000:
 // PARTRELRO-NEXT:  )
 // PARTRELRO-NEXT:  }
 // PARTRELRO-NEXT:  Section {
 // PARTRELRO-NEXT:    Index: 11
 // PARTRELRO-NEXT:    Name: .foo
 // PARTRELRO-NEXT:    Type: SHT_PROGBITS
 // PARTRELRO-NEXT:    Flags [
 // PARTRELRO-NEXT:      SHF_ALLOC
 // PARTRELRO-NEXT:      SHF_WRITE
 // PARTRELRO-NEXT:    ]
-// PARTRELRO-NEXT:    Address: 0x120F4
-// PARTRELRO-NEXT:    Offset: 0x20F4
+// PARTRELRO-NEXT:    Address: 0x1300C
+// PARTRELRO-NEXT:    Offset: 0x300C
 // PARTRELRO-NEXT:    Size: 0
 // PARTRELRO-NEXT:    Link: 0
 // PARTRELRO-NEXT:    Info: 0
 // PARTRELRO-NEXT:    AddressAlignment: 1
 // PARTRELRO-NEXT:    EntrySize: 0
 // PARTRELRO-NEXT:    SectionData (
 // PARTRELRO-NEXT:    )
 // PARTRELRO-NEXT:  }
 // PARTRELRO-NEXT:  Section {
 // PARTRELRO-NEXT:    Index: 12
 // PARTRELRO-NEXT:    Name: .got.plt
 // PARTRELRO-NEXT:    Type: SHT_PROGBITS
 // PARTRELRO-NEXT:    Flags [
 // PARTRELRO-NEXT:      SHF_ALLOC
 // PARTRELRO-NEXT:      SHF_WRITE
 // PARTRELRO-NEXT:    ]
-// PARTRELRO-NEXT:    Address: 0x120F8
-// PARTRELRO-NEXT:    Offset: 0x20F8
+// PARTRELRO-NEXT:    Address: 0x13010
+// PARTRELRO-NEXT:    Offset: 0x3010
 // PARTRELRO-NEXT:    Size: 32
 // PARTRELRO-NEXT:    Link: 0
 // PARTRELRO-NEXT:    Info: 0
 // PARTRELRO-NEXT:    AddressAlignment: 8
 // PARTRELRO-NEXT:    EntrySize: 0
 // PARTRELRO-NEXT:    SectionData (
 // PARTRELRO-NEXT:      0000:
 // PARTRELRO-NEXT:      0010:
 // PARTRELRO-NEXT:    )
 // PARTRELRO-NEXT:  }
 // PARTRELRO-NEXT:  Section {
 // PARTRELRO-NEXT:    Index: 13
 // PARTRELRO-NEXT:    Name: .bss
 // PARTRELRO-NEXT:    Type: SHT_NOBITS
 // PARTRELRO-NEXT:    Flags [
 // PARTRELRO-NEXT:      SHF_ALLOC
 // PARTRELRO-NEXT:      SHF_WRITE
 // PARTRELRO-NEXT:    ]
-// PARTRELRO-NEXT:    Address: 0x12118
-// PARTRELRO-NEXT:    Offset: 0x2118
+// PARTRELRO-NEXT:    Address: 0x13030
+// PARTRELRO-NEXT:    Offset: 0x3030
 // PARTRELRO-NEXT:    Size: 0
 // PARTRELRO-NEXT:    Link: 0
 // PARTRELRO-NEXT:    Info: 0
 // PARTRELRO-NEXT:    AddressAlignment: 1
 // PARTRELRO-NEXT:    EntrySize: 0
 // PARTRELRO-NEXT:  }
-// 232 + sizeof(.data)(12) + align(4) + sizeof(.got.plt)(32) = 280
 // PARTRELRO:       ProgramHeader {
 // PARTRELRO:       Type: PT_LOAD
 // PARTRELRO:       Offset: 0x2000
 // PARTRELRO-NEXT:  VirtualAddress: [[RWADDR:.*]]
 // PARTRELRO-NEXT:  PhysicalAddress:
-// PARTRELRO-NEXT:  FileSize: 280
-// PARTRELRO-NEXT:  MemSize: 280
+// PARTRELRO-NEXT:  FileSize: 4144
+// PARTRELRO-NEXT:  MemSize: 4144
 // PARTRELRO-NEXT:  Flags [
 // PARTRELRO-NEXT:    PF_R (0x4)
 // PARTRELRO-NEXT:    PF_W (0x2)
 // PARTRELRO-NEXT:  ]
 // PARTRELRO-NEXT:  Alignment: 4096
 // PARTRELRO:       Type: PT_GNU_RELRO
 // PARTRELRO-NEXT:  Offset: 0x2000
 // PARTRELRO-NEXT:  VirtualAddress: [[RWADDR]]
 // PARTRELRO-NEXT:  PhysicalAddress:
 // PARTRELRO-NEXT:  FileSize: 232
 // PARTRELRO-NEXT:  MemSize: 232
 // PARTRELRO-NEXT:  Flags [
 // PARTRELRO-NEXT:    PF_R
 // PARTRELRO-NEXT:  ]
 // PARTRELRO-NEXT:  Alignment: 1
 
 // NORELRO:     ProgramHeaders [
 // NORELRO-NOT: PT_GNU_RELRO
 
 .global _start
 _start:
   .long bar
   jmp *bar at GOTPCREL(%rip)
 
 .section .data,"aw"
 .quad 0
 
 .zero 4
 .section .foo,"aw"
 .section .bss,"", at nobits
diff --git a/test/ELF/tls-opt-gdie.s b/test/ELF/tls-opt-gdie.s
index 2b59ed7..a6c6868 100644
--- a/test/ELF/tls-opt-gdie.s
+++ b/test/ELF/tls-opt-gdie.s
@@ -1,55 +1,55 @@
 // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
 // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/tls-opt-gdie.s -o %tso.o
 // RUN: ld.lld -shared %tso.o -o %t.so
 // RUN: ld.lld %t.o %t.so -o %t1
 // RUN: llvm-readobj -s -r %t1 | FileCheck --check-prefix=RELOC %s
 // RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
 
 //RELOC:      Section {
 //RELOC:      Index: 9
 //RELOC-NEXT: Name: .got
 //RELOC-NEXT: Type: SHT_PROGBITS
 //RELOC-NEXT: Flags [
 //RELOC-NEXT:   SHF_ALLOC
 //RELOC-NEXT:   SHF_WRITE
 //RELOC-NEXT: ]
 //RELOC-NEXT: Address: 0x120E0
 //RELOC-NEXT: Offset: 0x20E0
 //RELOC-NEXT: Size: 16
 //RELOC-NEXT: Link: 0
 //RELOC-NEXT: Info: 0
 //RELOC-NEXT: AddressAlignment: 8
 //RELOC-NEXT: EntrySize: 0
 //RELOC-NEXT: }
 //RELOC:      Relocations [
 //RELOC-NEXT:   Section (4) .rela.dyn {
 //RELOC-NEXT:     0x120E0 R_X86_64_TPOFF64 tlsshared0 0x0
 //RELOC-NEXT:     0x120E8 R_X86_64_TPOFF64 tlsshared1 0x0
 //RELOC-NEXT:   }
 //RELOC-NEXT:   Section (5) .rela.plt {
-//RELOC-NEXT:     0x12108 R_X86_64_JUMP_SLOT __tls_get_addr 0x0
+//RELOC-NEXT:     0x13018 R_X86_64_JUMP_SLOT __tls_get_addr 0x0
 //RELOC-NEXT:   }
 //RELOC-NEXT: ]
 
 //0x11009 + (4304 + 7) = 0x120E0
 //0x11019 + (4296 + 7) = 0x120E8
 // DISASM:      Disassembly of section .text:
 // DISASM-NEXT: _start:
 // DISASM-NEXT: 11000: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax
 // DISASM-NEXT: 11009: 48 03 05 d0 10 00 00       addq 4304(%rip), %rax
 // DISASM-NEXT: 11010: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax
 // DISASM-NEXT: 11019: 48 03 05 c8 10 00 00       addq 4296(%rip), %rax
 
 .section .text
 .globl _start
 _start:
  .byte 0x66
  leaq tlsshared0 at tlsgd(%rip),%rdi
  .word 0x6666
  rex64
  call __tls_get_addr at plt
  .byte 0x66
  leaq tlsshared1 at tlsgd(%rip),%rdi
  .word 0x6666
  rex64
  call __tls_get_addr at plt


More information about the llvm-commits mailing list