[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
Tue Dec 22 20:42:32 PST 2015


I think this can be better expressed my moving the "is in relro" check
out of the method.

What do you think of the attached variation?

Cheers,
Rafael


On 21 December 2015 at 07:18, George Rimar <grimar at accesssoftek.com> wrote:
> grimar added inline comments.
>
> ================
> Comment at: ELF/Writer.cpp:855
> @@ -852,2 +854,3 @@
>  template <class ELFT>
> -void Writer<ELFT>::updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr,
> +bool Writer<ELFT>::isRelroEnded(Elf_Phdr *Cur, Elf_Phdr *RelroPhdr,
> +                                OutputSectionBase<ELFT> *Sec) {
> ----------------
> ruiu wrote:
>> Can you rename this isFirstNonRelroSection? I think it conveys the meaning better.
> Method unfortunately does not return is that is first non relro section or not.
> "unfortunately" because it seems not to be possible to know here without additional flags outside.
> Please see my comment for  "bool RelroAligned = false;" below.
> I renamed it to isPostRelroSection.
>
> ================
> Comment at: ELF/Writer.cpp:859
> @@ +858,3 @@
> +    return false;
> +  return RelroPhdr->p_type;
> +}
> ----------------
> ruiu wrote:
>> Please add that as a comment.
>>
>>   // p_type is zero if we have not created RELRO PHDR yet.
> Done.
>
> ================
> Comment at: ELF/Writer.cpp:901
> @@ -891,1 +900,3 @@
> +  Elf_Phdr RelroPhdr = {};
> +  bool RelroAligned = false;
>    Elf_Phdr TlsPhdr{};
> ----------------
> ruiu wrote:
>> Do you need this boolean variable? Because of the p_type check, I think isRelroEnded returns true only once.
> It will return true for each section after relro. Thats why I need that flag.
> Lets look again on conditions:
>
> ```
> if (!Config->ZRelro || ((Cur->p_flags & PF_W) && isRelroSection(Sec)))
>   return false;
> return RelroPhdr->p_type;
>
> ```
> If current section is not relro or not in writable segment it will return p_type, which is here can be:
> 1) zero - if we did not start proccessing the relro yet. So this flag was never set.
> 2) non zero - if we had relro and finished with it.
>
> So because of second I need to know if current section is the **first** section after relro or not, that is for what flag is there,
>
>
> http://reviews.llvm.org/D15423
>
>
>
-------------- next part --------------
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index 2440f1a..a7355e2 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -1,1188 +1,1196 @@
 //===- 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 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;
   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) {
+      if (PH->p_flags != Flags) {
         // Flags changed. Create a new PT_LOAD.
         VA = RoundUpToAlignment(VA, Target->getPageSize());
         FileOff = RoundUpToAlignment(FileOff, Target->getPageSize());
-        Elf_Phdr *PH = &Phdrs[++PhdrIdx];
+        PH = &Phdrs[++PhdrIdx];
         setPhdr(PH, PT_LOAD, Flags, FileOff, VA, 0, Target->getPageSize());
       }
 
+      bool InRelRo =
+          Config->ZRelro && (PH->p_flags & PF_W) && isRelroSection(Sec);
+      if (GnuRelroPhdr.p_type && !InRelRo && !RelroAligned) {
+        VA = RoundUpToAlignment(VA, Target->getPageSize());
+        FileOff = RoundUpToAlignment(FileOff, Target->getPageSize());
+        RelroAligned = true;
+      }
+
       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, Sec, 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