merge lld-16.0.6
authorrobert <robert@openbsd.org>
Sat, 11 Nov 2023 18:22:09 +0000 (18:22 +0000)
committerrobert <robert@openbsd.org>
Sat, 11 Nov 2023 18:22:09 +0000 (18:22 +0000)
113 files changed:
gnu/llvm/lld/CMakeLists.txt
gnu/llvm/lld/ELF/Arch/AArch64.cpp
gnu/llvm/lld/ELF/Arch/PPC.cpp
gnu/llvm/lld/ELF/Arch/PPC64.cpp
gnu/llvm/lld/ELF/Arch/RISCV.cpp
gnu/llvm/lld/ELF/Arch/X86_64.cpp
gnu/llvm/lld/ELF/Config.h
gnu/llvm/lld/ELF/Driver.cpp
gnu/llvm/lld/ELF/DriverUtils.cpp
gnu/llvm/lld/ELF/InputFiles.cpp
gnu/llvm/lld/ELF/InputFiles.h
gnu/llvm/lld/ELF/InputSection.cpp
gnu/llvm/lld/ELF/LinkerScript.cpp
gnu/llvm/lld/ELF/Options.td
gnu/llvm/lld/ELF/Relocations.cpp
gnu/llvm/lld/ELF/ScriptParser.cpp
gnu/llvm/lld/ELF/SymbolTable.cpp
gnu/llvm/lld/ELF/Symbols.cpp
gnu/llvm/lld/ELF/Symbols.h
gnu/llvm/lld/ELF/SyntheticSections.cpp
gnu/llvm/lld/ELF/SyntheticSections.h
gnu/llvm/lld/ELF/Writer.cpp
gnu/llvm/lld/ELF/Writer.h
gnu/llvm/lld/docs/AtomLLD.rst [deleted file]
gnu/llvm/lld/docs/Driver.rst [deleted file]
gnu/llvm/lld/docs/Readers.rst [deleted file]
gnu/llvm/lld/docs/design.rst [deleted file]
gnu/llvm/lld/docs/development.rst [deleted file]
gnu/llvm/lld/docs/getting_started.rst [deleted file]
gnu/llvm/lld/docs/ld.lld.1
gnu/llvm/lld/docs/open_projects.rst [deleted file]
gnu/llvm/lld/docs/sphinx_intro.rst [deleted file]
gnu/llvm/lld/include/lld/Core/AbsoluteAtom.h [deleted file]
gnu/llvm/lld/include/lld/Core/ArchiveLibraryFile.h [deleted file]
gnu/llvm/lld/include/lld/Core/Atom.h [deleted file]
gnu/llvm/lld/include/lld/Core/DefinedAtom.h [deleted file]
gnu/llvm/lld/include/lld/Core/Error.h [deleted file]
gnu/llvm/lld/include/lld/Core/File.h [deleted file]
gnu/llvm/lld/include/lld/Core/Instrumentation.h [deleted file]
gnu/llvm/lld/include/lld/Core/LinkingContext.h [deleted file]
gnu/llvm/lld/include/lld/Core/Node.h [deleted file]
gnu/llvm/lld/include/lld/Core/Pass.h [deleted file]
gnu/llvm/lld/include/lld/Core/PassManager.h [deleted file]
gnu/llvm/lld/include/lld/Core/Reader.h [deleted file]
gnu/llvm/lld/include/lld/Core/Reference.h [deleted file]
gnu/llvm/lld/include/lld/Core/Resolver.h [deleted file]
gnu/llvm/lld/include/lld/Core/SharedLibraryAtom.h [deleted file]
gnu/llvm/lld/include/lld/Core/SharedLibraryFile.h [deleted file]
gnu/llvm/lld/include/lld/Core/Simple.h [deleted file]
gnu/llvm/lld/include/lld/Core/SymbolTable.h [deleted file]
gnu/llvm/lld/include/lld/Core/UndefinedAtom.h [deleted file]
gnu/llvm/lld/include/lld/Core/Writer.h [deleted file]
gnu/llvm/lld/include/lld/ReaderWriter/MachOLinkingContext.h [deleted file]
gnu/llvm/lld/include/lld/ReaderWriter/YamlContext.h [deleted file]
gnu/llvm/lld/lib/CMakeLists.txt [deleted file]
gnu/llvm/lld/lib/Core/CMakeLists.txt [deleted file]
gnu/llvm/lld/lib/Core/DefinedAtom.cpp [deleted file]
gnu/llvm/lld/lib/Core/Error.cpp [deleted file]
gnu/llvm/lld/lib/Core/File.cpp [deleted file]
gnu/llvm/lld/lib/Core/LinkingContext.cpp [deleted file]
gnu/llvm/lld/lib/Core/Reader.cpp [deleted file]
gnu/llvm/lld/lib/Core/Resolver.cpp [deleted file]
gnu/llvm/lld/lib/Core/SymbolTable.cpp [deleted file]
gnu/llvm/lld/lib/Core/Writer.cpp [deleted file]
gnu/llvm/lld/lib/Driver/CMakeLists.txt [deleted file]
gnu/llvm/lld/lib/Driver/DarwinLdDriver.cpp [deleted file]
gnu/llvm/lld/lib/Driver/DarwinLdOptions.td [deleted file]
gnu/llvm/lld/lib/ReaderWriter/CMakeLists.txt [deleted file]
gnu/llvm/lld/lib/ReaderWriter/FileArchive.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/ArchHandler.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/ArchHandler.h [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/Atoms.h [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/CMakeLists.txt [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/DebugInfo.h [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/ExecutableAtoms.h [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/File.h [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/FlatNamespaceFile.h [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/GOTPass.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/LayoutPass.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/LayoutPass.h [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/MachOPasses.h [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/ObjCPass.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/SectCreateFile.h [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/ShimPass.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/StubsPass.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/TLVPass.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/MachO/WriterMachO.cpp [deleted file]
gnu/llvm/lld/lib/ReaderWriter/YAML/CMakeLists.txt [deleted file]
gnu/llvm/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp [deleted file]
gnu/llvm/lld/tools/lld/CMakeLists.txt
gnu/llvm/lld/tools/lld/lld.cpp
gnu/llvm/lld/unittests/CMakeLists.txt [deleted file]
gnu/llvm/lld/unittests/DriverTests/CMakeLists.txt [deleted file]
gnu/llvm/lld/unittests/DriverTests/DarwinLdDriverTest.cpp [deleted file]
gnu/llvm/lld/unittests/MachOTests/CMakeLists.txt [deleted file]
gnu/llvm/lld/unittests/MachOTests/MachONormalizedFileBinaryReaderTests.cpp [deleted file]
gnu/llvm/lld/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp [deleted file]
gnu/llvm/lld/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp [deleted file]
gnu/llvm/lld/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp [deleted file]
gnu/llvm/lld/unittests/MachOTests/empty_obj_x86_armv7.txt [deleted file]

index 3d62256..b680e40 100644 (file)
@@ -161,6 +161,34 @@ list(INSERT CMAKE_MODULE_PATH 0
 
 include(AddLLD)
 
+option(LLD_ENABLE_WASM
+       "Enable support for WASM."
+       OFF)
+if (LLD_ENABLE_WASM)
+  add_definitions("-DLLD_ENABLE_WASM=1")
+endif()
+
+option(LLD_ENABLE_MACHO
+       "Enable support for MachO."
+       OFF)
+if (LLD_ENABLE_MACHO)
+  add_definitions("-DLLD_ENABLE_MACHO=1")
+endif()
+
+option(LLD_ENABLE_MINGW
+       "Enable support for MINGW."
+       OFF)
+if (LLD_ENABLE_MINGW)
+  add_definitions("-DLLD_ENABLE_MINGW=1")
+endif()
+
+option(LLD_ENABLE_COFF
+       "Enable support for COFF."
+       OFF)
+if (LLD_ENABLE_COFF)
+  add_definitions("-DLLD_ENABLE_COFF=1")
+endif()
+
 option(LLD_USE_VTUNE
        "Enable VTune user task tracking."
        OFF)
@@ -210,7 +238,9 @@ endif()
 add_subdirectory(docs)
 add_subdirectory(COFF)
 add_subdirectory(ELF)
-add_subdirectory(MachO)
+if (LLD_ENABLE_MACHO)
+  add_subdirectory(MachO)
+endif()
 add_subdirectory(MinGW)
 add_subdirectory(wasm)
 
index 7021aa0..1ed1227 100644 (file)
@@ -6,12 +6,12 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "OutputSections.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
 #include "Target.h"
-#include "Thunks.h"
 #include "lld/Common/ErrorHandler.h"
-#include "llvm/Object/ELF.h"
+#include "llvm/BinaryFormat/ELF.h"
 #include "llvm/Support/Endian.h"
 
 using namespace llvm;
@@ -36,6 +36,7 @@ public:
   RelType getDynRel(RelType type) const override;
   int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;
   void writeGotPlt(uint8_t *buf, const Symbol &s) const override;
+  void writeIgotPlt(uint8_t *buf, const Symbol &s) const override;
   void writePltHeader(uint8_t *buf) const override;
   void writePlt(uint8_t *buf, const Symbol &sym,
                 uint64_t pltEntryAddr) const override;
@@ -48,12 +49,22 @@ public:
   void relocate(uint8_t *loc, const Relocation &rel,
                 uint64_t val) const override;
   RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override;
-  void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
-                      uint64_t val) const override;
-  void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
-                      uint64_t val) const override;
-  void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
-                      uint64_t val) const override;
+  void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override;
+
+private:
+  void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
+  void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
+  void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
+};
+
+struct AArch64Relaxer {
+  bool safeToRelaxAdrpLdr = false;
+
+  AArch64Relaxer(ArrayRef<Relocation> relocs);
+  bool tryRelaxAdrpAdd(const Relocation &adrpRel, const Relocation &addRel,
+                       uint64_t secAddr, uint8_t *buf) const;
+  bool tryRelaxAdrpLdr(const Relocation &adrpRel, const Relocation &ldrRel,
+                       uint64_t secAddr, uint8_t *buf) const;
 };
 } // namespace
 
@@ -62,7 +73,6 @@ AArch64::AArch64() {
   relativeRel = R_AARCH64_RELATIVE;
   iRelativeRel = R_AARCH64_IRELATIVE;
   gotRel = R_AARCH64_GLOB_DAT;
-  noneRel = R_AARCH64_NONE;
   pltRel = R_AARCH64_JUMP_SLOT;
   symbolicRel = R_AARCH64_ABS64;
   tlsDescRel = R_AARCH64_TLSDESC;
@@ -71,7 +81,6 @@ AArch64::AArch64() {
   pltEntrySize = 16;
   ipltEntrySize = 16;
   defaultMaxPageSize = 65536;
-  gotBaseSymInGotPlt = false;
 
   // Align to the 2 MiB page size (known as a superpage or huge page).
   // FreeBSD automatically promotes 2 MiB-aligned allocations.
@@ -199,6 +208,18 @@ int64_t AArch64::getImplicitAddend(const uint8_t *buf, RelType type) const {
   switch (type) {
   case R_AARCH64_TLSDESC:
     return read64(buf + 8);
+  case R_AARCH64_NONE:
+  case R_AARCH64_GLOB_DAT:
+  case R_AARCH64_JUMP_SLOT:
+    return 0;
+  case R_AARCH64_PREL32:
+    return SignExtend64<32>(read32(buf));
+  case R_AARCH64_ABS64:
+  case R_AARCH64_PREL64:
+  case R_AARCH64_RELATIVE:
+  case R_AARCH64_IRELATIVE:
+  case R_AARCH64_TLS_TPREL64:
+    return read64(buf);
   default:
     internalLinkerError(getErrorLocation(buf),
                         "cannot read addend for relocation " + toString(type));
@@ -210,12 +231,17 @@ void AArch64::writeGotPlt(uint8_t *buf, const Symbol &) const {
   write64(buf, in.plt->getVA());
 }
 
+void AArch64::writeIgotPlt(uint8_t *buf, const Symbol &s) const {
+  if (config->writeAddends)
+    write64(buf, s.getVA());
+}
+
 void AArch64::writePltHeader(uint8_t *buf) const {
   const uint8_t pltData[] = {
       0xf0, 0x7b, 0xbf, 0xa9, // stp    x16, x30, [sp,#-16]!
-      0x10, 0x00, 0x00, 0x90, // adrp   x16, Page(&(.plt.got[2]))
-      0x11, 0x02, 0x40, 0xf9, // ldr    x17, [x16, Offset(&(.plt.got[2]))]
-      0x10, 0x02, 0x00, 0x91, // add    x16, x16, Offset(&(.plt.got[2]))
+      0x10, 0x00, 0x00, 0x90, // adrp   x16, Page(&(.got.plt[2]))
+      0x11, 0x02, 0x40, 0xf9, // ldr    x17, [x16, Offset(&(.got.plt[2]))]
+      0x10, 0x02, 0x00, 0x91, // add    x16, x16, Offset(&(.got.plt[2]))
       0x20, 0x02, 0x1f, 0xd6, // br     x17
       0x1f, 0x20, 0x03, 0xd5, // nop
       0x1f, 0x20, 0x03, 0xd5, // nop
@@ -234,9 +260,9 @@ void AArch64::writePltHeader(uint8_t *buf) const {
 void AArch64::writePlt(uint8_t *buf, const Symbol &sym,
                        uint64_t pltEntryAddr) const {
   const uint8_t inst[] = {
-      0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[n]))
-      0x11, 0x02, 0x40, 0xf9, // ldr  x17, [x16, Offset(&(.plt.got[n]))]
-      0x10, 0x02, 0x00, 0x91, // add  x16, x16, Offset(&(.plt.got[n]))
+      0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.got.plt[n]))
+      0x11, 0x02, 0x40, 0xf9, // ldr  x17, [x16, Offset(&(.got.plt[n]))]
+      0x10, 0x02, 0x00, 0x91, // add  x16, x16, Offset(&(.got.plt[n]))
       0x20, 0x02, 0x1f, 0xd6  // br   x17
   };
   memcpy(buf, inst, sizeof(inst));
@@ -251,9 +277,11 @@ void AArch64::writePlt(uint8_t *buf, const Symbol &sym,
 bool AArch64::needsThunk(RelExpr expr, RelType type, const InputFile *file,
                          uint64_t branchAddr, const Symbol &s,
                          int64_t a) const {
-  // If s is an undefined weak symbol and does not have a PLT entry then it
-  // will be resolved as a branch to the next instruction.
-  if (s.isUndefWeak() && !s.isInPlt())
+  // If s is an undefined weak symbol and does not have a PLT entry then it will
+  // be resolved as a branch to the next instruction. If it is hidden, its
+  // binding has been converted to local, so we just check isUndefined() here. A
+  // undefined non-weak symbol will have been errored.
+  if (s.isUndefined() && !s.isInPlt())
     return false;
   // ELF for the ARM 64-bit architecture, section Call and Jump relocations
   // only permits range extension thunks for R_AARCH64_CALL26 and
@@ -358,7 +386,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
   case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
   case R_AARCH64_TLSDESC_ADR_PAGE21:
     checkInt(loc, val, 33, rel);
-    LLVM_FALLTHROUGH;
+    [[fallthrough]];
   case R_AARCH64_ADR_PREL_PG_HI21_NC:
     write32AArch64Addr(loc, val >> 12);
     break;
@@ -375,7 +403,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
     // transformation by placing a R_AARCH64_JUMP26 relocation at the offset of
     // the instruction we want to patch.
     write32le(loc, 0x14000000);
-    LLVM_FALLTHROUGH;
+    [[fallthrough]];
   case R_AARCH64_CALL26:
     checkInt(loc, val, 28, rel);
     or32le(loc, (val & 0x0FFFFFFC) >> 2);
@@ -419,19 +447,19 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
     break;
   case R_AARCH64_MOVW_UABS_G0:
     checkUInt(loc, val, 16, rel);
-    LLVM_FALLTHROUGH;
+    [[fallthrough]];
   case R_AARCH64_MOVW_UABS_G0_NC:
     or32le(loc, (val & 0xFFFF) << 5);
     break;
   case R_AARCH64_MOVW_UABS_G1:
     checkUInt(loc, val, 32, rel);
-    LLVM_FALLTHROUGH;
+    [[fallthrough]];
   case R_AARCH64_MOVW_UABS_G1_NC:
     or32le(loc, (val & 0xFFFF0000) >> 11);
     break;
   case R_AARCH64_MOVW_UABS_G2:
     checkUInt(loc, val, 48, rel);
-    LLVM_FALLTHROUGH;
+    [[fallthrough]];
   case R_AARCH64_MOVW_UABS_G2_NC:
     or32le(loc, (val & 0xFFFF00000000) >> 27);
     break;
@@ -442,7 +470,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
   case R_AARCH64_MOVW_SABS_G0:
   case R_AARCH64_TLSLE_MOVW_TPREL_G0:
     checkInt(loc, val, 17, rel);
-    LLVM_FALLTHROUGH;
+    [[fallthrough]];
   case R_AARCH64_MOVW_PREL_G0_NC:
   case R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
     writeSMovWImm(loc, val);
@@ -451,7 +479,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
   case R_AARCH64_MOVW_SABS_G1:
   case R_AARCH64_TLSLE_MOVW_TPREL_G1:
     checkInt(loc, val, 33, rel);
-    LLVM_FALLTHROUGH;
+    [[fallthrough]];
   case R_AARCH64_MOVW_PREL_G1_NC:
   case R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
     writeSMovWImm(loc, val >> 16);
@@ -460,7 +488,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
   case R_AARCH64_MOVW_SABS_G2:
   case R_AARCH64_TLSLE_MOVW_TPREL_G2:
     checkInt(loc, val, 49, rel);
-    LLVM_FALLTHROUGH;
+    [[fallthrough]];
   case R_AARCH64_MOVW_PREL_G2_NC:
     writeSMovWImm(loc, val >> 32);
     break;
@@ -570,6 +598,194 @@ void AArch64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
   llvm_unreachable("invalid relocation for TLS IE to LE relaxation");
 }
 
+AArch64Relaxer::AArch64Relaxer(ArrayRef<Relocation> relocs) {
+  if (!config->relax)
+    return;
+  // Check if R_AARCH64_ADR_GOT_PAGE and R_AARCH64_LD64_GOT_LO12_NC
+  // always appear in pairs.
+  size_t i = 0;
+  const size_t size = relocs.size();
+  for (; i != size; ++i) {
+    if (relocs[i].type == R_AARCH64_ADR_GOT_PAGE) {
+      if (i + 1 < size && relocs[i + 1].type == R_AARCH64_LD64_GOT_LO12_NC) {
+        ++i;
+        continue;
+      }
+      break;
+    } else if (relocs[i].type == R_AARCH64_LD64_GOT_LO12_NC) {
+      break;
+    }
+  }
+  safeToRelaxAdrpLdr = i == size;
+}
+
+bool AArch64Relaxer::tryRelaxAdrpAdd(const Relocation &adrpRel,
+                                     const Relocation &addRel, uint64_t secAddr,
+                                     uint8_t *buf) const {
+  // When the address of sym is within the range of ADR then
+  // we may relax
+  // ADRP xn, sym
+  // ADD  xn, xn, :lo12: sym
+  // to
+  // NOP
+  // ADR xn, sym
+  if (!config->relax || adrpRel.type != R_AARCH64_ADR_PREL_PG_HI21 ||
+      addRel.type != R_AARCH64_ADD_ABS_LO12_NC)
+    return false;
+  // Check if the relocations apply to consecutive instructions.
+  if (adrpRel.offset + 4 != addRel.offset)
+    return false;
+  if (adrpRel.sym != addRel.sym)
+    return false;
+  if (adrpRel.addend != 0 || addRel.addend != 0)
+    return false;
+
+  uint32_t adrpInstr = read32le(buf + adrpRel.offset);
+  uint32_t addInstr = read32le(buf + addRel.offset);
+  // Check if the first instruction is ADRP and the second instruction is ADD.
+  if ((adrpInstr & 0x9f000000) != 0x90000000 ||
+      (addInstr & 0xffc00000) != 0x91000000)
+    return false;
+  uint32_t adrpDestReg = adrpInstr & 0x1f;
+  uint32_t addDestReg = addInstr & 0x1f;
+  uint32_t addSrcReg = (addInstr >> 5) & 0x1f;
+  if (adrpDestReg != addDestReg || adrpDestReg != addSrcReg)
+    return false;
+
+  Symbol &sym = *adrpRel.sym;
+  // Check if the address difference is within 1MiB range.
+  int64_t val = sym.getVA() - (secAddr + addRel.offset);
+  if (val < -1024 * 1024 || val >= 1024 * 1024)
+    return false;
+
+  Relocation adrRel = {R_ABS, R_AARCH64_ADR_PREL_LO21, addRel.offset,
+                       /*addend=*/0, &sym};
+  // nop
+  write32le(buf + adrpRel.offset, 0xd503201f);
+  // adr x_<dest_reg>
+  write32le(buf + adrRel.offset, 0x10000000 | adrpDestReg);
+  target->relocate(buf + adrRel.offset, adrRel, val);
+  return true;
+}
+
+bool AArch64Relaxer::tryRelaxAdrpLdr(const Relocation &adrpRel,
+                                     const Relocation &ldrRel, uint64_t secAddr,
+                                     uint8_t *buf) const {
+  if (!safeToRelaxAdrpLdr)
+    return false;
+
+  // When the definition of sym is not preemptible then we may
+  // be able to relax
+  // ADRP xn, :got: sym
+  // LDR xn, [ xn :got_lo12: sym]
+  // to
+  // ADRP xn, sym
+  // ADD xn, xn, :lo_12: sym
+
+  if (adrpRel.type != R_AARCH64_ADR_GOT_PAGE ||
+      ldrRel.type != R_AARCH64_LD64_GOT_LO12_NC)
+    return false;
+  // Check if the relocations apply to consecutive instructions.
+  if (adrpRel.offset + 4 != ldrRel.offset)
+    return false;
+  // Check if the relocations reference the same symbol and
+  // skip undefined, preemptible and STT_GNU_IFUNC symbols.
+  if (!adrpRel.sym || adrpRel.sym != ldrRel.sym || !adrpRel.sym->isDefined() ||
+      adrpRel.sym->isPreemptible || adrpRel.sym->isGnuIFunc())
+    return false;
+  // Check if the addends of the both relocations are zero.
+  if (adrpRel.addend != 0 || ldrRel.addend != 0)
+    return false;
+  uint32_t adrpInstr = read32le(buf + adrpRel.offset);
+  uint32_t ldrInstr = read32le(buf + ldrRel.offset);
+  // Check if the first instruction is ADRP and the second instruction is LDR.
+  if ((adrpInstr & 0x9f000000) != 0x90000000 ||
+      (ldrInstr & 0x3b000000) != 0x39000000)
+    return false;
+  // Check the value of the sf bit.
+  if (!(ldrInstr >> 31))
+    return false;
+  uint32_t adrpDestReg = adrpInstr & 0x1f;
+  uint32_t ldrDestReg = ldrInstr & 0x1f;
+  uint32_t ldrSrcReg = (ldrInstr >> 5) & 0x1f;
+  // Check if ADPR and LDR use the same register.
+  if (adrpDestReg != ldrDestReg || adrpDestReg != ldrSrcReg)
+    return false;
+
+  Symbol &sym = *adrpRel.sym;
+  // GOT references to absolute symbols can't be relaxed to use ADRP/ADD in
+  // position-independent code because these instructions produce a relative
+  // address.
+  if (config->isPic && !cast<Defined>(sym).section)
+    return false;
+  // Check if the address difference is within 4GB range.
+  int64_t val =
+      getAArch64Page(sym.getVA()) - getAArch64Page(secAddr + adrpRel.offset);
+  if (val != llvm::SignExtend64(val, 33))
+    return false;
+
+  Relocation adrpSymRel = {R_AARCH64_PAGE_PC, R_AARCH64_ADR_PREL_PG_HI21,
+                           adrpRel.offset, /*addend=*/0, &sym};
+  Relocation addRel = {R_ABS, R_AARCH64_ADD_ABS_LO12_NC, ldrRel.offset,
+                       /*addend=*/0, &sym};
+
+  // adrp x_<dest_reg>
+  write32le(buf + adrpSymRel.offset, 0x90000000 | adrpDestReg);
+  // add x_<dest reg>, x_<dest reg>
+  write32le(buf + addRel.offset, 0x91000000 | adrpDestReg | (adrpDestReg << 5));
+
+  target->relocate(buf + adrpSymRel.offset, adrpSymRel,
+                   SignExtend64(getAArch64Page(sym.getVA()) -
+                                    getAArch64Page(secAddr + adrpSymRel.offset),
+                                64));
+  target->relocate(buf + addRel.offset, addRel, SignExtend64(sym.getVA(), 64));
+  tryRelaxAdrpAdd(adrpSymRel, addRel, secAddr, buf);
+  return true;
+}
+
+void AArch64::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
+  uint64_t secAddr = sec.getOutputSection()->addr;
+  if (auto *s = dyn_cast<InputSection>(&sec))
+    secAddr += s->outSecOff;
+  AArch64Relaxer relaxer(sec.relocs());
+  for (size_t i = 0, size = sec.relocs().size(); i != size; ++i) {
+    const Relocation &rel = sec.relocs()[i];
+    uint8_t *loc = buf + rel.offset;
+    const uint64_t val =
+        sec.getRelocTargetVA(sec.file, rel.type, rel.addend,
+                             secAddr + rel.offset, *rel.sym, rel.expr);
+    switch (rel.expr) {
+    case R_AARCH64_GOT_PAGE_PC:
+      if (i + 1 < size &&
+          relaxer.tryRelaxAdrpLdr(rel, sec.relocs()[i + 1], secAddr, buf)) {
+        ++i;
+        continue;
+      }
+      break;
+    case R_AARCH64_PAGE_PC:
+      if (i + 1 < size &&
+          relaxer.tryRelaxAdrpAdd(rel, sec.relocs()[i + 1], secAddr, buf)) {
+        ++i;
+        continue;
+      }
+      break;
+    case R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC:
+    case R_RELAX_TLS_GD_TO_IE_ABS:
+      relaxTlsGdToIe(loc, rel, val);
+      continue;
+    case R_RELAX_TLS_GD_TO_LE:
+      relaxTlsGdToLe(loc, rel, val);
+      continue;
+    case R_RELAX_TLS_IE_TO_LE:
+      relaxTlsIeToLe(loc, rel, val);
+      continue;
+    default:
+      break;
+    }
+    relocate(loc, rel, val);
+  }
+}
+
 // AArch64 may use security features in variant PLT sequences. These are:
 // Pointer Authentication (PAC), introduced in armv8.3-a and Branch Target
 // Indicator (BTI) introduced in armv8.5-a. The additional instructions used
@@ -614,8 +830,7 @@ public:
                 uint64_t pltEntryAddr) const override;
 
 private:
-  bool btiHeader; // bti instruction needed in PLT Header
-  bool btiEntry;  // bti instruction needed in PLT Entry
+  bool btiHeader; // bti instruction needed in PLT Header and Entry
   bool pacEntry;  // autia1716 instruction needed in PLT Entry
 };
 } // namespace
@@ -630,15 +845,14 @@ AArch64BtiPac::AArch64BtiPac() {
   // address of the PLT entry can be taken by the program, which permits an
   // indirect jump to the PLT entry. This can happen when the address
   // of the PLT entry for a function is canonicalised due to the address of
-  // the function in an executable being taken by a shared library.
-  // FIXME: There is a potential optimization to omit the BTI if we detect
-  // that the address of the PLT entry isn't taken.
+  // the function in an executable being taken by a shared library, or
+  // non-preemptible ifunc referenced by non-GOT-generating, non-PLT-generating
+  // relocations.
   // The PAC PLT entries require dynamic loader support and this isn't known
   // from properties in the objects, so we use the command line flag.
-  btiEntry = btiHeader && !config->shared;
   pacEntry = config->zPacPlt;
 
-  if (btiEntry || pacEntry) {
+  if (btiHeader || pacEntry) {
     pltEntrySize = 24;
     ipltEntrySize = 24;
   }
@@ -648,9 +862,9 @@ void AArch64BtiPac::writePltHeader(uint8_t *buf) const {
   const uint8_t btiData[] = { 0x5f, 0x24, 0x03, 0xd5 }; // bti c
   const uint8_t pltData[] = {
       0xf0, 0x7b, 0xbf, 0xa9, // stp    x16, x30, [sp,#-16]!
-      0x10, 0x00, 0x00, 0x90, // adrp   x16, Page(&(.plt.got[2]))
-      0x11, 0x02, 0x40, 0xf9, // ldr    x17, [x16, Offset(&(.plt.got[2]))]
-      0x10, 0x02, 0x00, 0x91, // add    x16, x16, Offset(&(.plt.got[2]))
+      0x10, 0x00, 0x00, 0x90, // adrp   x16, Page(&(.got.plt[2]))
+      0x11, 0x02, 0x40, 0xf9, // ldr    x17, [x16, Offset(&(.got.plt[2]))]
+      0x10, 0x02, 0x00, 0x91, // add    x16, x16, Offset(&(.got.plt[2]))
       0x20, 0x02, 0x1f, 0xd6, // br     x17
       0x1f, 0x20, 0x03, 0xd5, // nop
       0x1f, 0x20, 0x03, 0xd5  // nop
@@ -684,9 +898,9 @@ void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym,
   // [btiData] addrInst (pacBr | stdBr) [nopData]
   const uint8_t btiData[] = { 0x5f, 0x24, 0x03, 0xd5 }; // bti c
   const uint8_t addrInst[] = {
-      0x10, 0x00, 0x00, 0x90,  // adrp x16, Page(&(.plt.got[n]))
-      0x11, 0x02, 0x40, 0xf9,  // ldr  x17, [x16, Offset(&(.plt.got[n]))]
-      0x10, 0x02, 0x00, 0x91   // add  x16, x16, Offset(&(.plt.got[n]))
+      0x10, 0x00, 0x00, 0x90,  // adrp x16, Page(&(.got.plt[n]))
+      0x11, 0x02, 0x40, 0xf9,  // ldr  x17, [x16, Offset(&(.got.plt[n]))]
+      0x10, 0x02, 0x00, 0x91   // add  x16, x16, Offset(&(.got.plt[n]))
   };
   const uint8_t pacBr[] = {
       0x9f, 0x21, 0x03, 0xd5,  // autia1716
@@ -698,7 +912,12 @@ void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym,
   };
   const uint8_t nopData[] = { 0x1f, 0x20, 0x03, 0xd5 }; // nop
 
-  if (btiEntry) {
+  // NEEDS_COPY indicates a non-ifunc canonical PLT entry whose address may
+  // escape to shared objects. isInIplt indicates a non-preemptible ifunc. Its
+  // address may escape if referenced by a direct relocation. The condition is
+  // conservative.
+  bool hasBti = btiHeader && (sym.hasFlag(NEEDS_COPY) || sym.isInIplt);
+  if (hasBti) {
     memcpy(buf, btiData, sizeof(btiData));
     buf += sizeof(btiData);
     pltEntryAddr += sizeof(btiData);
@@ -715,7 +934,7 @@ void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym,
     memcpy(buf + sizeof(addrInst), pacBr, sizeof(pacBr));
   else
     memcpy(buf + sizeof(addrInst), stdBr, sizeof(stdBr));
-  if (!btiEntry)
+  if (!hasBti)
     // We didn't add the BTI c instruction so round out size with NOP.
     memcpy(buf + sizeof(addrInst) + sizeof(stdBr), nopData, sizeof(nopData));
 }
@@ -725,8 +944,8 @@ static TargetInfo *getTargetInfo() {
   static AArch64BtiPac t;
   return &t;
 #else
-  if (config->andFeatures & (GNU_PROPERTY_AARCH64_FEATURE_1_BTI |
-                             GNU_PROPERTY_AARCH64_FEATURE_1_PAC)) {
+  if ((config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) ||
+      config->zPacPlt) {
     static AArch64BtiPac t;
     return &t;
   }
index aaecef6..87942c1 100644 (file)
@@ -20,6 +20,9 @@ using namespace llvm::ELF;
 using namespace lld;
 using namespace lld::elf;
 
+// Undefine the macro predefined by GCC powerpc32.
+#undef PPC
+
 namespace {
 class PPC final : public TargetInfo {
 public:
@@ -27,6 +30,7 @@ public:
   RelExpr getRelExpr(RelType type, const Symbol &s,
                      const uint8_t *loc) const override;
   RelType getDynRel(RelType type) const override;
+  int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;
   void writeGotHeader(uint8_t *buf) const override;
   void writePltHeader(uint8_t *buf) const override {
     llvm_unreachable("should call writePPC32GlinkSection() instead");
@@ -47,14 +51,13 @@ public:
                 uint64_t val) const override;
   RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override;
   int getTlsGdRelaxSkip(RelType type) const override;
-  void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
-                      uint64_t val) const override;
-  void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
-                      uint64_t val) const override;
-  void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
-                      uint64_t val) const override;
-  void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
-                      uint64_t val) const override;
+  void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override;
+
+private:
+  void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
+  void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
+  void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
+  void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
 };
 } // namespace
 
@@ -74,7 +77,7 @@ void elf::writePPC32GlinkSection(uint8_t *buf, size_t numEntries) {
   // non-GOT-non-PLT relocations referencing external functions for -fpie/-fPIE.
   uint32_t glink = in.plt->getVA(); // VA of .glink
   if (!config->isPic) {
-    for (const Symbol *sym : cast<PPC32GlinkSection>(in.plt)->canonical_plts) {
+    for (const Symbol *sym : cast<PPC32GlinkSection>(*in.plt).canonical_plts) {
       writePPC32PltCallStub(buf, sym->getGotPltVA(), nullptr, 0);
       buf += 16;
       glink += 16;
@@ -151,12 +154,10 @@ void elf::writePPC32GlinkSection(uint8_t *buf, size_t numEntries) {
 PPC::PPC() {
   copyRel = R_PPC_COPY;
   gotRel = R_PPC_GLOB_DAT;
-  noneRel = R_PPC_NONE;
   pltRel = R_PPC_JMP_SLOT;
   relativeRel = R_PPC_RELATIVE;
   iRelativeRel = R_PPC_IRELATIVE;
   symbolicRel = R_PPC_ADDR32;
-  gotBaseSymInGotPlt = false;
   gotHeaderEntriesNum = 3;
   gotPltHeaderEntriesNum = 0;
   pltHeaderSize = 0;
@@ -191,7 +192,7 @@ void PPC::writeGotHeader(uint8_t *buf) const {
 
 void PPC::writeGotPlt(uint8_t *buf, const Symbol &s) const {
   // Address of the symbol resolver stub in .glink .
-  write32(buf, in.plt->getVA() + in.plt->headerSize + 4 * s.pltIndex);
+  write32(buf, in.plt->getVA() + in.plt->headerSize + 4 * s.getPltIdx());
 }
 
 bool PPC::needsThunk(RelExpr expr, RelType type, const InputFile *file,
@@ -274,6 +275,20 @@ RelType PPC::getDynRel(RelType type) const {
   return R_PPC_NONE;
 }
 
+int64_t PPC::getImplicitAddend(const uint8_t *buf, RelType type) const {
+  switch (type) {
+  case R_PPC_NONE:
+    return 0;
+  case R_PPC_ADDR32:
+  case R_PPC_REL32:
+    return SignExtend64<32>(read32(buf));
+  default:
+    internalLinkerError(getErrorLocation(buf),
+                        "cannot read addend for relocation " + toString(type));
+    return 0;
+  }
+}
+
 static std::pair<RelType, uint64_t> fromDTPREL(RelType type, uint64_t val) {
   uint64_t dtpBiasedVal = val - 0x8000;
   switch (type) {
@@ -467,6 +482,36 @@ void PPC::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
   }
 }
 
+void PPC::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
+  uint64_t secAddr = sec.getOutputSection()->addr;
+  if (auto *s = dyn_cast<InputSection>(&sec))
+    secAddr += s->outSecOff;
+  for (const Relocation &rel : sec.relocs()) {
+    uint8_t *loc = buf + rel.offset;
+    const uint64_t val = SignExtend64(
+        sec.getRelocTargetVA(sec.file, rel.type, rel.addend,
+                             secAddr + rel.offset, *rel.sym, rel.expr),
+        32);
+    switch (rel.expr) {
+    case R_RELAX_TLS_GD_TO_IE_GOT_OFF:
+      relaxTlsGdToIe(loc, rel, val);
+      break;
+    case R_RELAX_TLS_GD_TO_LE:
+      relaxTlsGdToLe(loc, rel, val);
+      break;
+    case R_RELAX_TLS_LD_TO_LE_ABS:
+      relaxTlsLdToLe(loc, rel, val);
+      break;
+    case R_RELAX_TLS_IE_TO_LE:
+      relaxTlsIeToLe(loc, rel, val);
+      break;
+    default:
+      relocate(loc, rel, val);
+      break;
+    }
+  }
+}
+
 TargetInfo *elf::getPPCTargetInfo() {
   static PPC target;
   return &target;
index dae2ac1..511a99c 100644 (file)
@@ -6,13 +6,14 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "InputFiles.h"
+#include "OutputSections.h"
 #include "SymbolTable.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
 #include "Target.h"
 #include "Thunks.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
 #include "llvm/Support/Endian.h"
 
 using namespace llvm;
@@ -148,6 +149,46 @@ enum class LegacyToPrefixMask : uint64_t {
       0x8000000003e00000, // S/T (6-10) - The [S/T]X bit moves from 28 to 5.
 };
 
+namespace {
+class PPC64 final : public TargetInfo {
+public:
+  PPC64();
+  int getTlsGdRelaxSkip(RelType type) const override;
+  uint32_t calcEFlags() const override;
+  RelExpr getRelExpr(RelType type, const Symbol &s,
+                     const uint8_t *loc) const override;
+  RelType getDynRel(RelType type) const override;
+  int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;
+  void writePltHeader(uint8_t *buf) const override;
+  void writePlt(uint8_t *buf, const Symbol &sym,
+                uint64_t pltEntryAddr) const override;
+  void writeIplt(uint8_t *buf, const Symbol &sym,
+                 uint64_t pltEntryAddr) const override;
+  void relocate(uint8_t *loc, const Relocation &rel,
+                uint64_t val) const override;
+  void writeGotHeader(uint8_t *buf) const override;
+  bool needsThunk(RelExpr expr, RelType type, const InputFile *file,
+                  uint64_t branchAddr, const Symbol &s,
+                  int64_t a) const override;
+  uint32_t getThunkSectionSpacing() const override;
+  bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override;
+  RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override;
+  RelExpr adjustGotPcExpr(RelType type, int64_t addend,
+                          const uint8_t *loc) const override;
+  void relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) const;
+  void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override;
+
+  bool adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
+                                        uint8_t stOther) const override;
+
+private:
+  void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
+  void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
+  void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
+  void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const;
+};
+} // namespace
+
 uint64_t elf::getPPC64TocBase() {
   // The TOC consists of sections .got, .toc, .tocbss, .plt in that order. The
   // TOC starts where the first of these sections starts. We always create a
@@ -187,11 +228,6 @@ unsigned elf::getPPC64GlobalEntryToLocalEntryOffset(uint8_t stOther) {
   return 0;
 }
 
-bool elf::isPPC64SmallCodeModelTocReloc(RelType type) {
-  // The only small code model relocations that access the .toc section.
-  return type == R_PPC64_TOC16 || type == R_PPC64_TOC16_DS;
-}
-
 void elf::writePrefixedInstruction(uint8_t *loc, uint64_t insn) {
   insn = config->isLE ? insn << 32 | insn >> 32 : insn;
   write64(loc, insn);
@@ -199,11 +235,11 @@ void elf::writePrefixedInstruction(uint8_t *loc, uint64_t insn) {
 
 static bool addOptional(StringRef name, uint64_t value,
                         std::vector<Defined *> &defined) {
-  Symbol *sym = symtab->find(name);
+  Symbol *sym = symtab.find(name);
   if (!sym || sym->isDefined())
     return false;
-  sym->resolve(Defined{/*file=*/nullptr, saver.save(name), STB_GLOBAL,
-                       STV_HIDDEN, STT_FUNC, value,
+  sym->resolve(Defined{/*file=*/nullptr, StringRef(), STB_GLOBAL, STV_HIDDEN,
+                       STT_FUNC, value,
                        /*size=*/0, /*section=*/nullptr});
   defined.push_back(cast<Defined>(sym));
   return true;
@@ -235,10 +271,10 @@ static void writeSequence(MutableArrayRef<uint32_t> buf, const char *prefix,
   // instructions and write [first,end).
   auto *sec = make<InputSection>(
       nullptr, SHF_ALLOC, SHT_PROGBITS, 4,
-      makeArrayRef(reinterpret_cast<uint8_t *>(buf.data() + first),
-                   4 * (buf.size() - first)),
+      ArrayRef(reinterpret_cast<uint8_t *>(buf.data() + first),
+               4 * (buf.size() - first)),
       ".text");
-  inputSections.push_back(sec);
+  ctx.inputSections.push_back(sec);
   for (Defined *sym : defined) {
     sym->section = sec;
     sym->value -= 4 * first;
@@ -279,9 +315,6 @@ void elf::addPPC64SaveRestore() {
 template <typename ELFT>
 static std::pair<Defined *, int64_t>
 getRelaTocSymAndAddend(InputSectionBase *tocSec, uint64_t offset) {
-  if (tocSec->numRelocations == 0)
-    return {};
-
   // .rela.toc contains exclusively R_PPC64_ADDR64 relocations sorted by
   // r_offset: 0, 8, 16, etc. For a given Offset, Offset / 8 gives us the
   // relocation index in most cases.
@@ -291,7 +324,10 @@ getRelaTocSymAndAddend(InputSectionBase *tocSec, uint64_t offset) {
   // points to a relocation with larger r_offset. Do a linear probe then.
   // Constants are extremely uncommon in .toc and the extra number of array
   // accesses can be seen as a small constant.
-  ArrayRef<typename ELFT::Rela> relas = tocSec->template relas<ELFT>();
+  ArrayRef<typename ELFT::Rela> relas =
+      tocSec->template relsOrRelas<ELFT>().relas;
+  if (relas.empty())
+    return {};
   uint64_t index = std::min<uint64_t>(offset / 8, relas.size() - 1);
   for (;;) {
     if (relas[index].r_offset == offset) {
@@ -325,7 +361,8 @@ getRelaTocSymAndAddend(InputSectionBase *tocSec, uint64_t offset) {
 //   ld/lwa 3, 0(3)           # load the value from the address
 //
 // Returns true if the relaxation is performed.
-bool elf::tryRelaxPPC64TocIndirection(const Relocation &rel, uint8_t *bufLoc) {
+static bool tryRelaxPPC64TocIndirection(const Relocation &rel,
+                                        uint8_t *bufLoc) {
   assert(config->tocOptimize);
   if (rel.addend < 0)
     return false;
@@ -356,51 +393,11 @@ bool elf::tryRelaxPPC64TocIndirection(const Relocation &rel, uint8_t *bufLoc) {
     return false;
 
   // Add PPC64TocOffset that will be subtracted by PPC64::relocate().
-  target->relaxGot(bufLoc, rel, tocRelative + ppc64TocOffset);
+  static_cast<const PPC64 &>(*target).relaxGot(bufLoc, rel,
+                                               tocRelative + ppc64TocOffset);
   return true;
 }
 
-namespace {
-class PPC64 final : public TargetInfo {
-public:
-  PPC64();
-  int getTlsGdRelaxSkip(RelType type) const override;
-  uint32_t calcEFlags() const override;
-  RelExpr getRelExpr(RelType type, const Symbol &s,
-                     const uint8_t *loc) const override;
-  RelType getDynRel(RelType type) const override;
-  void writePltHeader(uint8_t *buf) const override;
-  void writePlt(uint8_t *buf, const Symbol &sym,
-                uint64_t pltEntryAddr) const override;
-  void writeIplt(uint8_t *buf, const Symbol &sym,
-                 uint64_t pltEntryAddr) const override;
-  void relocate(uint8_t *loc, const Relocation &rel,
-                uint64_t val) const override;
-  void writeGotHeader(uint8_t *buf) const override;
-  bool needsThunk(RelExpr expr, RelType type, const InputFile *file,
-                  uint64_t branchAddr, const Symbol &s,
-                  int64_t a) const override;
-  uint32_t getThunkSectionSpacing() const override;
-  bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override;
-  RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override;
-  RelExpr adjustGotPcExpr(RelType type, int64_t addend,
-                          const uint8_t *loc) const override;
-  void relaxGot(uint8_t *loc, const Relocation &rel,
-                uint64_t val) const override;
-  void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
-                      uint64_t val) const override;
-  void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
-                      uint64_t val) const override;
-  void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
-                      uint64_t val) const override;
-  void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
-                      uint64_t val) const override;
-
-  bool adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
-                                        uint8_t stOther) const override;
-};
-} // namespace
-
 // Relocation masks following the #lo(value), #hi(value), #ha(value),
 // #higher(value), #highera(value), #highest(value), and #highesta(value)
 // macros defined in section 4.5.1. Relocation Types of the PPC-elf64abi
@@ -568,7 +565,6 @@ static uint64_t readPrefixedInstruction(const uint8_t *loc) {
 PPC64::PPC64() {
   copyRel = R_PPC64_COPY;
   gotRel = R_PPC64_GLOB_DAT;
-  noneRel = R_PPC64_NONE;
   pltRel = R_PPC64_JMP_SLOT;
   relativeRel = R_PPC64_RELATIVE;
   iRelativeRel = R_PPC64_IRELATIVE;
@@ -580,7 +576,6 @@ PPC64::PPC64() {
 #endif
   pltEntrySize = 4;
   ipltEntrySize = 16; // PPC64PltCallStub::size
-  gotBaseSymInGotPlt = false;
   gotHeaderEntriesNum = 1;
   gotPltHeaderEntriesNum = 2;
   needsThunks = true;
@@ -624,7 +619,7 @@ int PPC64::getTlsGdRelaxSkip(RelType type) const {
 }
 
 static uint32_t getEFlags(InputFile *file) {
-  if (config->ekind == ELF64BEKind)
+  if (file->ekind == ELF64BEKind)
     return cast<ObjFile<ELF64BE>>(file)->getObj().getHeader().e_flags;
   return cast<ObjFile<ELF64LE>>(file)->getObj().getHeader().e_flags;
 }
@@ -632,7 +627,7 @@ static uint32_t getEFlags(InputFile *file) {
 // This file implements v2 ABI. This function makes sure that all
 // object files have v2 or an unspecified version as an ABI version.
 uint32_t PPC64::calcEFlags() const {
-  for (InputFile *f : objectFiles) {
+  for (InputFile *f : ctx.objectFiles) {
     uint32_t flag = getEFlags(f);
     if (flag == 1)
       error(toString(f) + ": ABI version 1 is not supported");
@@ -1071,6 +1066,29 @@ RelType PPC64::getDynRel(RelType type) const {
   return R_PPC64_NONE;
 }
 
+int64_t PPC64::getImplicitAddend(const uint8_t *buf, RelType type) const {
+  switch (type) {
+  case R_PPC64_NONE:
+  case R_PPC64_GLOB_DAT:
+  case R_PPC64_JMP_SLOT:
+    return 0;
+  case R_PPC64_REL32:
+    return SignExtend64<32>(read32(buf));
+  case R_PPC64_ADDR64:
+  case R_PPC64_REL64:
+  case R_PPC64_RELATIVE:
+  case R_PPC64_IRELATIVE:
+  case R_PPC64_DTPMOD64:
+  case R_PPC64_DTPREL64:
+  case R_PPC64_TPREL64:
+    return read64(buf);
+  default:
+    internalLinkerError(getErrorLocation(buf),
+                        "cannot read addend for relocation " + toString(type));
+    return 0;
+  }
+}
+
 void PPC64::writeGotHeader(uint8_t *buf) const {
   write64(buf, getPPC64TocBase());
 }
@@ -1112,7 +1130,7 @@ void PPC64::writePltHeader(uint8_t *buf) const {
 
 void PPC64::writePlt(uint8_t *buf, const Symbol &sym,
                      uint64_t /*pltEntryAddr*/) const {
-  int32_t offset = pltHeaderSize + sym.pltIndex * pltEntrySize;
+  int32_t offset = pltHeaderSize + sym.getPltIdx() * pltEntrySize;
   // bl __glink_PLTresolve
   write32(buf, 0x48000000 | ((-offset) & 0x03FFFFFc));
 }
@@ -1348,7 +1366,7 @@ void PPC64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     // of the TLS block. Therefore, in the case of R_PPC64_DTPREL34 we first
     // need to subtract that value then fallthrough to the general case.
     val -= dynamicThreadPointerOffset;
-    LLVM_FALLTHROUGH;
+    [[fallthrough]];
   case R_PPC64_PCREL34:
   case R_PPC64_GOT_PCREL34:
   case R_PPC64_GOT_TLSGD_PCREL34:
@@ -1392,9 +1410,10 @@ bool PPC64::needsThunk(RelExpr expr, RelType type, const InputFile *file,
   if (type == R_PPC64_REL24_NOTOC && (s.stOther >> 5) > 1)
     return true;
 
-  // If a symbol is a weak undefined and we are compiling an executable
-  // it doesn't need a range-extending thunk since it can't be called.
-  if (s.isUndefWeak() && !config->shared)
+  // An undefined weak symbol not in a PLT does not need a thunk. If it is
+  // hidden, its binding has been converted to local, so we just check
+  // isUndefined() here. A undefined non-weak symbol has been errored.
+  if (s.isUndefined())
     return false;
 
   // If the offset exceeds the range of the branch type then it will need
@@ -1510,6 +1529,87 @@ void PPC64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
   }
 }
 
+void PPC64::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
+  uint64_t secAddr = sec.getOutputSection()->addr;
+  if (auto *s = dyn_cast<InputSection>(&sec))
+    secAddr += s->outSecOff;
+  uint64_t lastPPCRelaxedRelocOff = -1;
+  for (const Relocation &rel : sec.relocs()) {
+    uint8_t *loc = buf + rel.offset;
+    const uint64_t val =
+        sec.getRelocTargetVA(sec.file, rel.type, rel.addend,
+                             secAddr + rel.offset, *rel.sym, rel.expr);
+    switch (rel.expr) {
+    case R_PPC64_RELAX_GOT_PC: {
+      // The R_PPC64_PCREL_OPT relocation must appear immediately after
+      // R_PPC64_GOT_PCREL34 in the relocations table at the same offset.
+      // We can only relax R_PPC64_PCREL_OPT if we have also relaxed
+      // the associated R_PPC64_GOT_PCREL34 since only the latter has an
+      // associated symbol. So save the offset when relaxing R_PPC64_GOT_PCREL34
+      // and only relax the other if the saved offset matches.
+      if (rel.type == R_PPC64_GOT_PCREL34)
+        lastPPCRelaxedRelocOff = rel.offset;
+      if (rel.type == R_PPC64_PCREL_OPT && rel.offset != lastPPCRelaxedRelocOff)
+        break;
+      relaxGot(loc, rel, val);
+      break;
+    }
+    case R_PPC64_RELAX_TOC:
+      // rel.sym refers to the STT_SECTION symbol associated to the .toc input
+      // section. If an R_PPC64_TOC16_LO (.toc + addend) references the TOC
+      // entry, there may be R_PPC64_TOC16_HA not paired with
+      // R_PPC64_TOC16_LO_DS. Don't relax. This loses some relaxation
+      // opportunities but is safe.
+      if (ppc64noTocRelax.count({rel.sym, rel.addend}) ||
+          !tryRelaxPPC64TocIndirection(rel, loc))
+        relocate(loc, rel, val);
+      break;
+    case R_PPC64_CALL:
+      // If this is a call to __tls_get_addr, it may be part of a TLS
+      // sequence that has been relaxed and turned into a nop. In this
+      // case, we don't want to handle it as a call.
+      if (read32(loc) == 0x60000000) // nop
+        break;
+
+      // Patch a nop (0x60000000) to a ld.
+      if (rel.sym->needsTocRestore) {
+        // gcc/gfortran 5.4, 6.3 and earlier versions do not add nop for
+        // recursive calls even if the function is preemptible. This is not
+        // wrong in the common case where the function is not preempted at
+        // runtime. Just ignore.
+        if ((rel.offset + 8 > sec.content().size() ||
+             read32(loc + 4) != 0x60000000) &&
+            rel.sym->file != sec.file) {
+          // Use substr(6) to remove the "__plt_" prefix.
+          errorOrWarn(getErrorLocation(loc) + "call to " +
+                      lld::toString(*rel.sym).substr(6) +
+                      " lacks nop, can't restore toc");
+          break;
+        }
+        write32(loc + 4, 0xe8410018); // ld %r2, 24(%r1)
+      }
+      relocate(loc, rel, val);
+      break;
+    case R_RELAX_TLS_GD_TO_IE:
+    case R_RELAX_TLS_GD_TO_IE_GOT_OFF:
+      relaxTlsGdToIe(loc, rel, val);
+      break;
+    case R_RELAX_TLS_GD_TO_LE:
+      relaxTlsGdToLe(loc, rel, val);
+      break;
+    case R_RELAX_TLS_LD_TO_LE_ABS:
+      relaxTlsLdToLe(loc, rel, val);
+      break;
+    case R_RELAX_TLS_IE_TO_LE:
+      relaxTlsIeToLe(loc, rel, val);
+      break;
+    default:
+      relocate(loc, rel, val);
+      break;
+    }
+  }
+}
+
 // The prologue for a split-stack function is expected to look roughly
 // like this:
 //    .Lglobal_entry_point:
index baf0173..87887b3 100644 (file)
@@ -7,9 +7,16 @@
 //===----------------------------------------------------------------------===//
 
 #include "InputFiles.h"
+#include "OutputSections.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
 #include "Target.h"
+#include "llvm/Support/ELFAttributes.h"
+#include "llvm/Support/LEB128.h"
+#include "llvm/Support/RISCVAttributeParser.h"
+#include "llvm/Support/RISCVAttributes.h"
+#include "llvm/Support/RISCVISAInfo.h"
+#include "llvm/Support/TimeProfiler.h"
 
 using namespace llvm;
 using namespace llvm::object;
@@ -36,6 +43,7 @@ public:
                      const uint8_t *loc) const override;
   void relocate(uint8_t *loc, const Relocation &rel,
                 uint64_t val) const override;
+  bool relaxOnce(int pass) const override;
 };
 
 } // end anonymous namespace
@@ -54,6 +62,7 @@ enum Op {
 
 enum Reg {
   X_RA = 1,
+  X_TP = 4,
   X_T0 = 5,
   X_T1 = 6,
   X_T2 = 7,
@@ -73,9 +82,21 @@ static uint32_t utype(uint32_t op, uint32_t rd, uint32_t imm) {
   return op | (rd << 7) | (imm << 12);
 }
 
+// Extract bits v[begin:end], where range is inclusive, and begin must be < 63.
+static uint32_t extractBits(uint64_t v, uint32_t begin, uint32_t end) {
+  return (v & ((1ULL << (begin + 1)) - 1)) >> end;
+}
+
+static uint32_t setLO12_I(uint32_t insn, uint32_t imm) {
+  return (insn & 0xfffff) | (imm << 20);
+}
+static uint32_t setLO12_S(uint32_t insn, uint32_t imm) {
+  return (insn & 0x1fff07f) | (extractBits(imm, 11, 5) << 25) |
+         (extractBits(imm, 4, 0) << 7);
+}
+
 RISCV::RISCV() {
   copyRel = R_RISCV_COPY;
-  noneRel = R_RISCV_NONE;
   pltRel = R_RISCV_JUMP_SLOT;
   relativeRel = R_RISCV_RELATIVE;
   iRelativeRel = R_RISCV_IRELATIVE;
@@ -93,7 +114,6 @@ RISCV::RISCV() {
   gotRel = symbolicRel;
 
   // .got[0] = _DYNAMIC
-  gotBaseSymInGotPlt = false;
   gotHeaderEntriesNum = 1;
 
   // .got.plt[0] = _dl_runtime_resolve, .got.plt[1] = link_map
@@ -113,19 +133,21 @@ static uint32_t getEFlags(InputFile *f) {
 uint32_t RISCV::calcEFlags() const {
   // If there are only binary input files (from -b binary), use a
   // value of 0 for the ELF header flags.
-  if (objectFiles.empty())
+  if (ctx.objectFiles.empty())
     return 0;
 
-  uint32_t target = getEFlags(objectFiles.front());
+  uint32_t target = getEFlags(ctx.objectFiles.front());
 
-  for (InputFile *f : objectFiles) {
+  for (InputFile *f : ctx.objectFiles) {
     uint32_t eflags = getEFlags(f);
     if (eflags & EF_RISCV_RVC)
       target |= EF_RISCV_RVC;
 
     if ((eflags & EF_RISCV_FLOAT_ABI) != (target & EF_RISCV_FLOAT_ABI))
-      warn(toString(f) +
-            ": linking object files with different floating-point ABI");
+      error(
+          toString(f) +
+          ": cannot link object files with different floating-point ABI from " +
+          toString(ctx.objectFiles[0]));
 
     if ((eflags & EF_RISCV_RVE) != (target & EF_RISCV_RVE))
       error(toString(f) +
@@ -144,8 +166,12 @@ int64_t RISCV::getImplicitAddend(const uint8_t *buf, RelType type) const {
   case R_RISCV_32:
   case R_RISCV_TLS_DTPMOD32:
   case R_RISCV_TLS_DTPREL32:
+  case R_RISCV_TLS_TPREL32:
     return SignExtend64<32>(read32le(buf));
   case R_RISCV_64:
+  case R_RISCV_TLS_DTPMOD64:
+  case R_RISCV_TLS_DTPREL64:
+  case R_RISCV_TLS_TPREL64:
     return read64le(buf);
   case R_RISCV_RELATIVE:
   case R_RISCV_IRELATIVE:
@@ -263,22 +289,16 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
   case R_RISCV_TLS_GD_HI20:
     return R_TLSGD_PC;
   case R_RISCV_TLS_GOT_HI20:
-    config->hasStaticTlsModel = true;
     return R_GOT_PC;
   case R_RISCV_TPREL_HI20:
   case R_RISCV_TPREL_LO12_I:
   case R_RISCV_TPREL_LO12_S:
     return R_TPREL;
-  case R_RISCV_RELAX:
-  case R_RISCV_TPREL_ADD:
-    return R_NONE;
   case R_RISCV_ALIGN:
-    // Not just a hint; always padded to the worst-case number of NOPs, so may
-    // not currently be aligned, and without linker relaxation support we can't
-    // delete NOPs to realign.
-    errorOrWarn(getErrorLocation(loc) + "relocation R_RISCV_ALIGN requires "
-                "unimplemented linker relaxation; recompile with -mno-relax");
-    return R_NONE;
+    return R_RELAX_HINT;
+  case R_RISCV_TPREL_ADD:
+  case R_RISCV_RELAX:
+    return config->relax ? R_RELAX_HINT : R_NONE;
   default:
     error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
           ") against symbol " + toString(s));
@@ -286,11 +306,6 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
   }
 }
 
-// Extract bits V[Begin:End], where range is inclusive, and Begin must be < 63.
-static uint32_t extractBits(uint64_t v, uint32_t begin, uint32_t end) {
-  return (v & ((1ULL << (begin + 1)) - 1)) >> end;
-}
-
 void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   const unsigned bits = config->wordsize * 8;
 
@@ -303,7 +318,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     return;
 
   case R_RISCV_RVC_BRANCH: {
-    checkInt(loc, static_cast<int64_t>(val) >> 1, 8, rel);
+    checkInt(loc, val, 9, rel);
     checkAlignment(loc, val, 2, rel);
     uint16_t insn = read16le(loc) & 0xE383;
     uint16_t imm8 = extractBits(val, 8, 8) << 12;
@@ -318,7 +333,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   }
 
   case R_RISCV_RVC_JUMP: {
-    checkInt(loc, static_cast<int64_t>(val) >> 1, 11, rel);
+    checkInt(loc, val, 12, rel);
     checkAlignment(loc, val, 2, rel);
     uint16_t insn = read16le(loc) & 0xE003;
     uint16_t imm11 = extractBits(val, 11, 11) << 12;
@@ -349,7 +364,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   }
 
   case R_RISCV_JAL: {
-    checkInt(loc, static_cast<int64_t>(val) >> 1, 20, rel);
+    checkInt(loc, val, 21, rel);
     checkAlignment(loc, val, 2, rel);
 
     uint32_t insn = read32le(loc) & 0xFFF;
@@ -364,7 +379,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   }
 
   case R_RISCV_BRANCH: {
-    checkInt(loc, static_cast<int64_t>(val) >> 1, 12, rel);
+    checkInt(loc, val, 13, rel);
     checkAlignment(loc, val, 2, rel);
 
     uint32_t insn = read32le(loc) & 0x1FFF07F;
@@ -407,7 +422,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   case R_RISCV_LO12_I: {
     uint64_t hi = (val + 0x800) >> 12;
     uint64_t lo = val - (hi << 12);
-    write32le(loc, (read32le(loc) & 0xFFFFF) | ((lo & 0xFFF) << 20));
+    write32le(loc, setLO12_I(read32le(loc), lo & 0xfff));
     return;
   }
 
@@ -416,9 +431,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   case R_RISCV_LO12_S: {
     uint64_t hi = (val + 0x800) >> 12;
     uint64_t lo = val - (hi << 12);
-    uint32_t imm11_5 = extractBits(lo, 11, 5) << 25;
-    uint32_t imm4_0 = extractBits(lo, 4, 0) << 7;
-    write32le(loc, (read32le(loc) & 0x1FFF07F) | imm11_5 | imm4_0);
+    write32le(loc, setLO12_S(read32le(loc), lo));
     return;
   }
 
@@ -478,6 +491,531 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   }
 }
 
+namespace {
+struct SymbolAnchor {
+  uint64_t offset;
+  Defined *d;
+  bool end; // true for the anchor of st_value+st_size
+};
+} // namespace
+
+struct elf::RISCVRelaxAux {
+  // This records symbol start and end offsets which will be adjusted according
+  // to the nearest relocDeltas element.
+  SmallVector<SymbolAnchor, 0> anchors;
+  // For relocations[i], the actual offset is r_offset - (i ? relocDeltas[i-1] :
+  // 0).
+  std::unique_ptr<uint32_t[]> relocDeltas;
+  // For relocations[i], the actual type is relocTypes[i].
+  std::unique_ptr<RelType[]> relocTypes;
+  SmallVector<uint32_t, 0> writes;
+};
+
+static void initSymbolAnchors() {
+  SmallVector<InputSection *, 0> storage;
+  for (OutputSection *osec : outputSections) {
+    if (!(osec->flags & SHF_EXECINSTR))
+      continue;
+    for (InputSection *sec : getInputSections(*osec, storage)) {
+      sec->relaxAux = make<RISCVRelaxAux>();
+      if (sec->relocs().size()) {
+        sec->relaxAux->relocDeltas =
+            std::make_unique<uint32_t[]>(sec->relocs().size());
+        sec->relaxAux->relocTypes =
+            std::make_unique<RelType[]>(sec->relocs().size());
+      }
+    }
+  }
+  // Store anchors (st_value and st_value+st_size) for symbols relative to text
+  // sections.
+  for (InputFile *file : ctx.objectFiles)
+    for (Symbol *sym : file->getSymbols()) {
+      auto *d = dyn_cast<Defined>(sym);
+      if (!d || d->file != file)
+        continue;
+      if (auto *sec = dyn_cast_or_null<InputSection>(d->section))
+        if (sec->flags & SHF_EXECINSTR && sec->relaxAux) {
+          // If sec is discarded, relaxAux will be nullptr.
+          sec->relaxAux->anchors.push_back({d->value, d, false});
+          sec->relaxAux->anchors.push_back({d->value + d->size, d, true});
+        }
+    }
+  // Sort anchors by offset so that we can find the closest relocation
+  // efficiently. For a zero size symbol, ensure that its start anchor precedes
+  // its end anchor. For two symbols with anchors at the same offset, their
+  // order does not matter.
+  for (OutputSection *osec : outputSections) {
+    if (!(osec->flags & SHF_EXECINSTR))
+      continue;
+    for (InputSection *sec : getInputSections(*osec, storage)) {
+      llvm::sort(sec->relaxAux->anchors, [](auto &a, auto &b) {
+        return std::make_pair(a.offset, a.end) <
+               std::make_pair(b.offset, b.end);
+      });
+    }
+  }
+}
+
+// Relax R_RISCV_CALL/R_RISCV_CALL_PLT auipc+jalr to c.j, c.jal, or jal.
+static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
+                      Relocation &r, uint32_t &remove) {
+  const bool rvc = config->eflags & EF_RISCV_RVC;
+  const Symbol &sym = *r.sym;
+  const uint64_t insnPair = read64le(sec.content().data() + r.offset);
+  const uint32_t rd = extractBits(insnPair, 32 + 11, 32 + 7);
+  const uint64_t dest =
+      (r.expr == R_PLT_PC ? sym.getPltVA() : sym.getVA()) + r.addend;
+  const int64_t displace = dest - loc;
+
+  if (rvc && isInt<12>(displace) && rd == 0) {
+    sec.relaxAux->relocTypes[i] = R_RISCV_RVC_JUMP;
+    sec.relaxAux->writes.push_back(0xa001); // c.j
+    remove = 6;
+  } else if (rvc && isInt<12>(displace) && rd == X_RA &&
+             !config->is64) { // RV32C only
+    sec.relaxAux->relocTypes[i] = R_RISCV_RVC_JUMP;
+    sec.relaxAux->writes.push_back(0x2001); // c.jal
+    remove = 6;
+  } else if (isInt<21>(displace)) {
+    sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
+    sec.relaxAux->writes.push_back(0x6f | rd << 7); // jal
+    remove = 4;
+  }
+}
+
+// Relax local-exec TLS when hi20 is zero.
+static void relaxTlsLe(const InputSection &sec, size_t i, uint64_t loc,
+                       Relocation &r, uint32_t &remove) {
+  uint64_t val = r.sym->getVA(r.addend);
+  if (hi20(val) != 0)
+    return;
+  uint32_t insn = read32le(sec.content().data() + r.offset);
+  switch (r.type) {
+  case R_RISCV_TPREL_HI20:
+  case R_RISCV_TPREL_ADD:
+    // Remove lui rd, %tprel_hi(x) and add rd, rd, tp, %tprel_add(x).
+    sec.relaxAux->relocTypes[i] = R_RISCV_RELAX;
+    remove = 4;
+    break;
+  case R_RISCV_TPREL_LO12_I:
+    // addi rd, rd, %tprel_lo(x) => addi rd, tp, st_value(x)
+    sec.relaxAux->relocTypes[i] = R_RISCV_32;
+    insn = (insn & ~(31 << 15)) | (X_TP << 15);
+    sec.relaxAux->writes.push_back(setLO12_I(insn, val));
+    break;
+  case R_RISCV_TPREL_LO12_S:
+    // sw rs, %tprel_lo(x)(rd) => sw rs, st_value(x)(rd)
+    sec.relaxAux->relocTypes[i] = R_RISCV_32;
+    insn = (insn & ~(31 << 15)) | (X_TP << 15);
+    sec.relaxAux->writes.push_back(setLO12_S(insn, val));
+    break;
+  }
+}
+
+static bool relax(InputSection &sec) {
+  const uint64_t secAddr = sec.getVA();
+  auto &aux = *sec.relaxAux;
+  bool changed = false;
+
+  // Get st_value delta for symbols relative to this section from the previous
+  // iteration.
+  DenseMap<const Defined *, uint64_t> valueDelta;
+  ArrayRef<SymbolAnchor> sa = ArrayRef(aux.anchors);
+  uint32_t delta = 0;
+  for (auto [i, r] : llvm::enumerate(sec.relocs())) {
+    for (; sa.size() && sa[0].offset <= r.offset; sa = sa.slice(1))
+      if (!sa[0].end)
+        valueDelta[sa[0].d] = delta;
+    delta = aux.relocDeltas[i];
+  }
+  for (const SymbolAnchor &sa : sa)
+    if (!sa.end)
+      valueDelta[sa.d] = delta;
+  sa = ArrayRef(aux.anchors);
+  delta = 0;
+
+  std::fill_n(aux.relocTypes.get(), sec.relocs().size(), R_RISCV_NONE);
+  aux.writes.clear();
+  for (auto [i, r] : llvm::enumerate(sec.relocs())) {
+    const uint64_t loc = secAddr + r.offset - delta;
+    uint32_t &cur = aux.relocDeltas[i], remove = 0;
+    switch (r.type) {
+    case R_RISCV_ALIGN: {
+      const uint64_t nextLoc = loc + r.addend;
+      const uint64_t align = PowerOf2Ceil(r.addend + 2);
+      // All bytes beyond the alignment boundary should be removed.
+      remove = nextLoc - ((loc + align - 1) & -align);
+      assert(static_cast<int32_t>(remove) >= 0 &&
+             "R_RISCV_ALIGN needs expanding the content");
+      break;
+    }
+    case R_RISCV_CALL:
+    case R_RISCV_CALL_PLT:
+      if (i + 1 != sec.relocs().size() &&
+          sec.relocs()[i + 1].type == R_RISCV_RELAX)
+        relaxCall(sec, i, loc, r, remove);
+      break;
+    case R_RISCV_TPREL_HI20:
+    case R_RISCV_TPREL_ADD:
+    case R_RISCV_TPREL_LO12_I:
+    case R_RISCV_TPREL_LO12_S:
+      if (i + 1 != sec.relocs().size() &&
+          sec.relocs()[i + 1].type == R_RISCV_RELAX)
+        relaxTlsLe(sec, i, loc, r, remove);
+      break;
+    }
+
+    // For all anchors whose offsets are <= r.offset, they are preceded by
+    // the previous relocation whose `relocDeltas` value equals `delta`.
+    // Decrease their st_value and update their st_size.
+    for (; sa.size() && sa[0].offset <= r.offset; sa = sa.slice(1)) {
+      if (sa[0].end)
+        sa[0].d->size = sa[0].offset - delta - sa[0].d->value;
+      else
+        sa[0].d->value -= delta - valueDelta.find(sa[0].d)->second;
+    }
+    delta += remove;
+    if (delta != cur) {
+      cur = delta;
+      changed = true;
+    }
+  }
+
+  for (const SymbolAnchor &a : sa) {
+    if (a.end)
+      a.d->size = a.offset - delta - a.d->value;
+    else
+      a.d->value -= delta - valueDelta.find(a.d)->second;
+  }
+  // Inform assignAddresses that the size has changed.
+  if (!isUInt<16>(delta))
+    fatal("section size decrease is too large");
+  sec.bytesDropped = delta;
+  return changed;
+}
+
+// When relaxing just R_RISCV_ALIGN, relocDeltas is usually changed only once in
+// the absence of a linker script. For call and load/store R_RISCV_RELAX, code
+// shrinkage may reduce displacement and make more relocations eligible for
+// relaxation. Code shrinkage may increase displacement to a call/load/store
+// target at a higher fixed address, invalidating an earlier relaxation. Any
+// change in section sizes can have cascading effect and require another
+// relaxation pass.
+bool RISCV::relaxOnce(int pass) const {
+  llvm::TimeTraceScope timeScope("RISC-V relaxOnce");
+  if (config->relocatable)
+    return false;
+
+  if (pass == 0)
+    initSymbolAnchors();
+
+  SmallVector<InputSection *, 0> storage;
+  bool changed = false;
+  for (OutputSection *osec : outputSections) {
+    if (!(osec->flags & SHF_EXECINSTR))
+      continue;
+    for (InputSection *sec : getInputSections(*osec, storage))
+      changed |= relax(*sec);
+  }
+  return changed;
+}
+
+void elf::riscvFinalizeRelax(int passes) {
+  llvm::TimeTraceScope timeScope("Finalize RISC-V relaxation");
+  log("relaxation passes: " + Twine(passes));
+  SmallVector<InputSection *, 0> storage;
+  for (OutputSection *osec : outputSections) {
+    if (!(osec->flags & SHF_EXECINSTR))
+      continue;
+    for (InputSection *sec : getInputSections(*osec, storage)) {
+      RISCVRelaxAux &aux = *sec->relaxAux;
+      if (!aux.relocDeltas)
+        continue;
+
+      MutableArrayRef<Relocation> rels = sec->relocs();
+      ArrayRef<uint8_t> old = sec->content();
+      size_t newSize = old.size() - aux.relocDeltas[rels.size() - 1];
+      size_t writesIdx = 0;
+      uint8_t *p = context().bAlloc.Allocate<uint8_t>(newSize);
+      uint64_t offset = 0;
+      int64_t delta = 0;
+      sec->content_ = p;
+      sec->size = newSize;
+      sec->bytesDropped = 0;
+
+      // Update section content: remove NOPs for R_RISCV_ALIGN and rewrite
+      // instructions for relaxed relocations.
+      for (size_t i = 0, e = rels.size(); i != e; ++i) {
+        uint32_t remove = aux.relocDeltas[i] - delta;
+        delta = aux.relocDeltas[i];
+        if (remove == 0 && aux.relocTypes[i] == R_RISCV_NONE)
+          continue;
+
+        // Copy from last location to the current relocated location.
+        const Relocation &r = rels[i];
+        uint64_t size = r.offset - offset;
+        memcpy(p, old.data() + offset, size);
+        p += size;
+
+        // For R_RISCV_ALIGN, we will place `offset` in a location (among NOPs)
+        // to satisfy the alignment requirement. If both `remove` and r.addend
+        // are multiples of 4, it is as if we have skipped some NOPs. Otherwise
+        // we are in the middle of a 4-byte NOP, and we need to rewrite the NOP
+        // sequence.
+        int64_t skip = 0;
+        if (r.type == R_RISCV_ALIGN) {
+          if (remove % 4 || r.addend % 4) {
+            skip = r.addend - remove;
+            int64_t j = 0;
+            for (; j + 4 <= skip; j += 4)
+              write32le(p + j, 0x00000013); // nop
+            if (j != skip) {
+              assert(j + 2 == skip);
+              write16le(p + j, 0x0001); // c.nop
+            }
+          }
+        } else if (RelType newType = aux.relocTypes[i]) {
+          switch (newType) {
+          case R_RISCV_RELAX:
+            // Used by relaxTlsLe to indicate the relocation is ignored.
+            break;
+          case R_RISCV_RVC_JUMP:
+            skip = 2;
+            write16le(p, aux.writes[writesIdx++]);
+            break;
+          case R_RISCV_JAL:
+            skip = 4;
+            write32le(p, aux.writes[writesIdx++]);
+            break;
+          case R_RISCV_32:
+            // Used by relaxTlsLe to write a uint32_t then suppress the handling
+            // in relocateAlloc.
+            skip = 4;
+            write32le(p, aux.writes[writesIdx++]);
+            aux.relocTypes[i] = R_RISCV_NONE;
+            break;
+          default:
+            llvm_unreachable("unsupported type");
+          }
+        }
+
+        p += skip;
+        offset = r.offset + skip + remove;
+      }
+      memcpy(p, old.data() + offset, old.size() - offset);
+
+      // Subtract the previous relocDeltas value from the relocation offset.
+      // For a pair of R_RISCV_CALL/R_RISCV_RELAX with the same offset, decrease
+      // their r_offset by the same delta.
+      delta = 0;
+      for (size_t i = 0, e = rels.size(); i != e;) {
+        uint64_t cur = rels[i].offset;
+        do {
+          rels[i].offset -= delta;
+          if (aux.relocTypes[i] != R_RISCV_NONE)
+            rels[i].type = aux.relocTypes[i];
+        } while (++i != e && rels[i].offset == cur);
+        delta = aux.relocDeltas[i - 1];
+      }
+    }
+  }
+}
+
+namespace {
+// Representation of the merged .riscv.attributes input sections. The psABI
+// specifies merge policy for attributes. E.g. if we link an object without an
+// extension with an object with the extension, the output Tag_RISCV_arch shall
+// contain the extension. Some tools like objdump parse .riscv.attributes and
+// disabling some instructions if the first Tag_RISCV_arch does not contain an
+// extension.
+class RISCVAttributesSection final : public SyntheticSection {
+public:
+  RISCVAttributesSection()
+      : SyntheticSection(0, SHT_RISCV_ATTRIBUTES, 1, ".riscv.attributes") {}
+
+  size_t getSize() const override { return size; }
+  void writeTo(uint8_t *buf) override;
+
+  static constexpr StringRef vendor = "riscv";
+  DenseMap<unsigned, unsigned> intAttr;
+  DenseMap<unsigned, StringRef> strAttr;
+  size_t size = 0;
+};
+} // namespace
+
+static void mergeArch(RISCVISAInfo::OrderedExtensionMap &mergedExts,
+                      unsigned &mergedXlen, const InputSectionBase *sec,
+                      StringRef s) {
+  auto maybeInfo = RISCVISAInfo::parseNormalizedArchString(s);
+  if (!maybeInfo) {
+    errorOrWarn(toString(sec) + ": " + s + ": " +
+                llvm::toString(maybeInfo.takeError()));
+    return;
+  }
+
+  // Merge extensions.
+  RISCVISAInfo &info = **maybeInfo;
+  if (mergedExts.empty()) {
+    mergedExts = info.getExtensions();
+    mergedXlen = info.getXLen();
+  } else {
+    for (const auto &ext : info.getExtensions()) {
+      if (auto it = mergedExts.find(ext.first); it != mergedExts.end()) {
+        if (std::tie(it->second.MajorVersion, it->second.MinorVersion) >=
+            std::tie(ext.second.MajorVersion, ext.second.MinorVersion))
+          continue;
+      }
+      mergedExts[ext.first] = ext.second;
+    }
+  }
+}
+
+static RISCVAttributesSection *
+mergeAttributesSection(const SmallVector<InputSectionBase *, 0> &sections) {
+  RISCVISAInfo::OrderedExtensionMap exts;
+  const InputSectionBase *firstStackAlign = nullptr;
+  unsigned firstStackAlignValue = 0, xlen = 0;
+  bool hasArch = false;
+
+  in.riscvAttributes = std::make_unique<RISCVAttributesSection>();
+  auto &merged = static_cast<RISCVAttributesSection &>(*in.riscvAttributes);
+
+  // Collect all tags values from attributes section.
+  const auto &attributesTags = RISCVAttrs::getRISCVAttributeTags();
+  for (const InputSectionBase *sec : sections) {
+    RISCVAttributeParser parser;
+    if (Error e = parser.parse(sec->content(), support::little))
+      warn(toString(sec) + ": " + llvm::toString(std::move(e)));
+    for (const auto &tag : attributesTags) {
+      switch (RISCVAttrs::AttrType(tag.attr)) {
+        // Integer attributes.
+      case RISCVAttrs::STACK_ALIGN:
+        if (auto i = parser.getAttributeValue(tag.attr)) {
+          auto r = merged.intAttr.try_emplace(tag.attr, *i);
+          if (r.second) {
+            firstStackAlign = sec;
+            firstStackAlignValue = *i;
+          } else if (r.first->second != *i) {
+            errorOrWarn(toString(sec) + " has stack_align=" + Twine(*i) +
+                        " but " + toString(firstStackAlign) +
+                        " has stack_align=" + Twine(firstStackAlignValue));
+          }
+        }
+        continue;
+      case RISCVAttrs::UNALIGNED_ACCESS:
+        if (auto i = parser.getAttributeValue(tag.attr))
+          merged.intAttr[tag.attr] |= *i;
+        continue;
+
+        // String attributes.
+      case RISCVAttrs::ARCH:
+        if (auto s = parser.getAttributeString(tag.attr)) {
+          hasArch = true;
+          mergeArch(exts, xlen, sec, *s);
+        }
+        continue;
+
+        // Attributes which use the default handling.
+      case RISCVAttrs::PRIV_SPEC:
+      case RISCVAttrs::PRIV_SPEC_MINOR:
+      case RISCVAttrs::PRIV_SPEC_REVISION:
+        break;
+      }
+
+      // Fallback for deprecated priv_spec* and other unknown attributes: retain
+      // the attribute if all input sections agree on the value. GNU ld uses 0
+      // and empty strings as default values which are not dumped to the output.
+      // TODO Adjust after resolution to
+      // https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/352
+      if (tag.attr % 2 == 0) {
+        if (auto i = parser.getAttributeValue(tag.attr)) {
+          auto r = merged.intAttr.try_emplace(tag.attr, *i);
+          if (!r.second && r.first->second != *i)
+            r.first->second = 0;
+        }
+      } else if (auto s = parser.getAttributeString(tag.attr)) {
+        auto r = merged.strAttr.try_emplace(tag.attr, *s);
+        if (!r.second && r.first->second != *s)
+          r.first->second = {};
+      }
+    }
+  }
+
+  if (hasArch) {
+    if (auto result = RISCVISAInfo::postProcessAndChecking(
+            std::make_unique<RISCVISAInfo>(xlen, exts))) {
+      merged.strAttr.try_emplace(RISCVAttrs::ARCH,
+                                 saver().save((*result)->toString()));
+    } else {
+      errorOrWarn(llvm::toString(result.takeError()));
+    }
+  }
+
+  // The total size of headers: format-version [ <section-length> "vendor-name"
+  // [ <file-tag> <size>.
+  size_t size = 5 + merged.vendor.size() + 1 + 5;
+  for (auto &attr : merged.intAttr)
+    if (attr.second != 0)
+      size += getULEB128Size(attr.first) + getULEB128Size(attr.second);
+  for (auto &attr : merged.strAttr)
+    if (!attr.second.empty())
+      size += getULEB128Size(attr.first) + attr.second.size() + 1;
+  merged.size = size;
+  return &merged;
+}
+
+void RISCVAttributesSection::writeTo(uint8_t *buf) {
+  const size_t size = getSize();
+  uint8_t *const end = buf + size;
+  *buf = ELFAttrs::Format_Version;
+  write32(buf + 1, size - 1);
+  buf += 5;
+
+  memcpy(buf, vendor.data(), vendor.size());
+  buf += vendor.size() + 1;
+
+  *buf = ELFAttrs::File;
+  write32(buf + 1, end - buf);
+  buf += 5;
+
+  for (auto &attr : intAttr) {
+    if (attr.second == 0)
+      continue;
+    buf += encodeULEB128(attr.first, buf);
+    buf += encodeULEB128(attr.second, buf);
+  }
+  for (auto &attr : strAttr) {
+    if (attr.second.empty())
+      continue;
+    buf += encodeULEB128(attr.first, buf);
+    memcpy(buf, attr.second.data(), attr.second.size());
+    buf += attr.second.size() + 1;
+  }
+}
+
+void elf::mergeRISCVAttributesSections() {
+  // Find the first input SHT_RISCV_ATTRIBUTES; return if not found.
+  size_t place =
+      llvm::find_if(ctx.inputSections,
+                    [](auto *s) { return s->type == SHT_RISCV_ATTRIBUTES; }) -
+      ctx.inputSections.begin();
+  if (place == ctx.inputSections.size())
+    return;
+
+  // Extract all SHT_RISCV_ATTRIBUTES sections into `sections`.
+  SmallVector<InputSectionBase *, 0> sections;
+  llvm::erase_if(ctx.inputSections, [&](InputSectionBase *s) {
+    if (s->type != SHT_RISCV_ATTRIBUTES)
+      return false;
+    sections.push_back(s);
+    return true;
+  });
+
+  // Add the merged section.
+  ctx.inputSections.insert(ctx.inputSections.begin() + place,
+                           mergeAttributesSection(sections));
+}
+
 TargetInfo *elf::getRISCVTargetInfo() {
   static RISCV target;
   return &target;
index 0ecdfe5..a44c2fe 100644 (file)
@@ -6,13 +6,12 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "InputFiles.h"
 #include "OutputSections.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
 #include "Target.h"
 #include "lld/Common/ErrorHandler.h"
-#include "llvm/Object/ELF.h"
+#include "llvm/BinaryFormat/ELF.h"
 #include "llvm/Support/Endian.h"
 
 using namespace llvm;
@@ -41,19 +40,9 @@ public:
   int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;
   void applyJumpInstrMod(uint8_t *loc, JumpModType type,
                          unsigned size) const override;
-
   RelExpr adjustGotPcExpr(RelType type, int64_t addend,
                           const uint8_t *loc) const override;
-  void relaxGot(uint8_t *loc, const Relocation &rel,
-                uint64_t val) const override;
-  void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
-                      uint64_t val) const override;
-  void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
-                      uint64_t val) const override;
-  void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
-                      uint64_t val) const override;
-  void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
-                      uint64_t val) const override;
+  void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override;
   bool adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
                                         uint8_t stOther) const override;
   bool deleteFallThruJmpInsn(InputSection &is, InputFile *file,
@@ -78,7 +67,6 @@ static const std::vector<std::vector<uint8_t>> nopInstructions = {
 X86_64::X86_64() {
   copyRel = R_X86_64_COPY;
   gotRel = R_X86_64_GLOB_DAT;
-  noneRel = R_X86_64_NONE;
   pltRel = R_X86_64_JUMP_SLOT;
   relativeRel = R_X86_64_RELATIVE;
   iRelativeRel = R_X86_64_IRELATIVE;
@@ -87,6 +75,7 @@ X86_64::X86_64() {
   tlsGotRel = R_X86_64_TPOFF64;
   tlsModuleIndexRel = R_X86_64_DTPMOD64;
   tlsOffsetRel = R_X86_64_DTPOFF64;
+  gotBaseSymInGotPlt = true;
   gotEntrySize = 8;
   pltHeaderSize = 16;
   pltEntrySize = 16;
@@ -99,7 +88,11 @@ X86_64::X86_64() {
   defaultImageBase = 0x200000;
 }
 
-int X86_64::getTlsGdRelaxSkip(RelType type) const { return 2; }
+int X86_64::getTlsGdRelaxSkip(RelType type) const {
+  // TLSDESC relocations are processed separately. See relaxTlsGdToLe below.
+  return type == R_X86_64_GOTPC32_TLSDESC || type == R_X86_64_TLSDESC_CALL ? 1
+                                                                           : 2;
+}
 
 // Opcodes for the different X86_64 jmp instructions.
 enum JmpInsnOpcode : uint32_t {
@@ -158,9 +151,9 @@ static JmpInsnOpcode getJmpInsnType(const uint8_t *first,
 // Returns the maximum size of the vector if no such relocation is found.
 static unsigned getRelocationWithOffset(const InputSection &is,
                                         uint64_t offset) {
-  unsigned size = is.relocations.size();
+  unsigned size = is.relocs().size();
   for (unsigned i = size - 1; i + 1 > 0; --i) {
-    if (is.relocations[i].offset == offset && is.relocations[i].expr != R_NONE)
+    if (is.relocs()[i].offset == offset && is.relocs()[i].expr != R_NONE)
       return i;
   }
   return size;
@@ -254,13 +247,13 @@ bool X86_64::deleteFallThruJmpInsn(InputSection &is, InputFile *file,
   // If this jmp insn can be removed, it is the last insn and the
   // relocation is 4 bytes before the end.
   unsigned rIndex = getRelocationWithOffset(is, is.getSize() - 4);
-  if (rIndex == is.relocations.size())
+  if (rIndex == is.relocs().size())
     return false;
 
-  Relocation &r = is.relocations[rIndex];
+  Relocation &r = is.relocs()[rIndex];
 
   // Check if the relocation corresponds to a direct jmp.
-  const uint8_t *secContents = is.data().data();
+  const uint8_t *secContents = is.content().data();
   // If it is not a direct jmp instruction, there is nothing to do here.
   if (*(secContents + r.offset - 1) != 0xe9)
     return false;
@@ -276,16 +269,16 @@ bool X86_64::deleteFallThruJmpInsn(InputSection &is, InputFile *file,
 
   // Now, check if flip and delete is possible.
   const unsigned sizeOfJmpCCInsn = 6;
-  // To flip, there must be atleast one JmpCC and one direct jmp.
+  // To flip, there must be at least one JmpCC and one direct jmp.
   if (is.getSize() < sizeOfDirectJmpInsn + sizeOfJmpCCInsn)
-    return 0;
+    return false;
 
   unsigned rbIndex =
       getRelocationWithOffset(is, (is.getSize() - sizeOfDirectJmpInsn - 4));
-  if (rbIndex == is.relocations.size())
-    return 0;
+  if (rbIndex == is.relocs().size())
+    return false;
 
-  Relocation &rB = is.relocations[rbIndex];
+  Relocation &rB = is.relocs()[rbIndex];
 
   const uint8_t *jmpInsnB = secContents + rB.offset - 1;
   JmpInsnOpcode jmpOpcodeB = getJmpInsnType(jmpInsnB - 1, jmpInsnB);
@@ -300,7 +293,8 @@ bool X86_64::deleteFallThruJmpInsn(InputSection &is, InputFile *file,
   JmpInsnOpcode jInvert = invertJmpOpcode(jmpOpcodeB);
   if (jInvert == J_UNKNOWN)
     return false;
-  is.jumpInstrMods.push_back({jInvert, (rB.offset - 1), 4});
+  is.jumpInstrMod = make<JumpInstrMod>();
+  *is.jumpInstrMod = {rB.offset - 1, jInvert, 4};
   // Move R's values to rB except the offset.
   rB = {r.expr, r.type, rB.offset, r.addend, r.sym};
   // Cancel R
@@ -313,9 +307,6 @@ bool X86_64::deleteFallThruJmpInsn(InputSection &is, InputFile *file,
 
 RelExpr X86_64::getRelExpr(RelType type, const Symbol &s,
                            const uint8_t *loc) const {
-  if (type == R_X86_64_GOTTPOFF)
-    config->hasStaticTlsModel = true;
-
   switch (type) {
   case R_X86_64_8:
   case R_X86_64_16:
@@ -356,6 +347,8 @@ RelExpr X86_64::getRelExpr(RelType type, const Symbol &s,
     return R_GOT_PC;
   case R_X86_64_GOTOFF64:
     return R_GOTPLTREL;
+  case R_X86_64_PLTOFF64:
+    return R_PLT_GOTPLT;
   case R_X86_64_GOTPC32:
   case R_X86_64_GOTPC64:
     return R_GOTPLTONLY_PC;
@@ -410,7 +403,7 @@ void X86_64::writePlt(uint8_t *buf, const Symbol &sym,
   memcpy(buf, inst, sizeof(inst));
 
   write32le(buf + 2, sym.getGotPltVA() - pltEntryAddr - 6);
-  write32le(buf + 7, sym.pltIndex);
+  write32le(buf + 7, sym.getPltIdx());
   write32le(buf + 12, in.plt->getVA() - pltEntryAddr - 16);
 }
 
@@ -421,8 +414,7 @@ RelType X86_64::getDynRel(RelType type) const {
   return R_X86_64_NONE;
 }
 
-void X86_64::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
-                            uint64_t val) const {
+static void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) {
   if (rel.type == R_X86_64_TLSGD) {
     // Convert
     //   .byte 0x66
@@ -441,29 +433,28 @@ void X86_64::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
     // The original code used a pc relative relocation and so we have to
     // compensate for the -4 in had in the addend.
     write32le(loc + 8, val + 4);
-  } else {
-    // Convert
-    //   lea x@tlsgd(%rip), %rax
-    //   call *(%rax)
-    // to the following two instructions.
-    assert(rel.type == R_X86_64_GOTPC32_TLSDESC);
-    if (memcmp(loc - 3, "\x48\x8d\x05", 3)) {
-      error(getErrorLocation(loc - 3) + "R_X86_64_GOTPC32_TLSDESC must be used "
-                                        "in callq *x@tlsdesc(%rip), %rax");
+  } else if (rel.type == R_X86_64_GOTPC32_TLSDESC) {
+    // Convert leaq x@tlsdesc(%rip), %REG to movq $x@tpoff, %REG.
+    if ((loc[-3] & 0xfb) != 0x48 || loc[-2] != 0x8d ||
+        (loc[-1] & 0xc7) != 0x05) {
+      errorOrWarn(getErrorLocation(loc - 3) +
+                  "R_X86_64_GOTPC32_TLSDESC must be used "
+                  "in leaq x@tlsdesc(%rip), %REG");
       return;
     }
-    // movq $x@tpoff(%rip),%rax
+    loc[-3] = 0x48 | ((loc[-3] >> 2) & 1);
     loc[-2] = 0xc7;
-    loc[-1] = 0xc0;
+    loc[-1] = 0xc0 | ((loc[-1] >> 3) & 7);
     write32le(loc, val + 4);
-    // xchg ax,ax
-    loc[4] = 0x66;
-    loc[5] = 0x90;
+  } else {
+    // Convert call *x@tlsdesc(%REG) to xchg ax, ax.
+    assert(rel.type == R_X86_64_TLSDESC_CALL);
+    loc[0] = 0x66;
+    loc[1] = 0x90;
   }
 }
 
-void X86_64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
-                            uint64_t val) const {
+static void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, uint64_t val) {
   if (rel.type == R_X86_64_TLSGD) {
     // Convert
     //   .byte 0x66
@@ -482,30 +473,29 @@ void X86_64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
     // Both code sequences are PC relatives, but since we are moving the
     // constant forward by 8 bytes we have to subtract the value by 8.
     write32le(loc + 8, val - 8);
-  } else {
-    // Convert
-    //   lea x@tlsgd(%rip), %rax
-    //   call *(%rax)
-    // to the following two instructions.
+  } else if (rel.type == R_X86_64_GOTPC32_TLSDESC) {
+    // Convert leaq x@tlsdesc(%rip), %REG to movq x@gottpoff(%rip), %REG.
     assert(rel.type == R_X86_64_GOTPC32_TLSDESC);
-    if (memcmp(loc - 3, "\x48\x8d\x05", 3)) {
-      error(getErrorLocation(loc - 3) + "R_X86_64_GOTPC32_TLSDESC must be used "
-                                        "in callq *x@tlsdesc(%rip), %rax");
+    if ((loc[-3] & 0xfb) != 0x48 || loc[-2] != 0x8d ||
+        (loc[-1] & 0xc7) != 0x05) {
+      errorOrWarn(getErrorLocation(loc - 3) +
+                  "R_X86_64_GOTPC32_TLSDESC must be used "
+                  "in leaq x@tlsdesc(%rip), %REG");
       return;
     }
-    // movq x@gottpoff(%rip),%rax
     loc[-2] = 0x8b;
     write32le(loc, val);
-    // xchg ax,ax
-    loc[4] = 0x66;
-    loc[5] = 0x90;
+  } else {
+    // Convert call *x@tlsdesc(%rax) to xchg ax, ax.
+    assert(rel.type == R_X86_64_TLSDESC_CALL);
+    loc[0] = 0x66;
+    loc[1] = 0x90;
   }
 }
 
 // In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to
 // R_X86_64_TPOFF32 so that it does not use GOT.
-void X86_64::relaxTlsIeToLe(uint8_t *loc, const Relocation &,
-                            uint64_t val) const {
+static void relaxTlsIeToLe(uint8_t *loc, const Relocation &, uint64_t val) {
   uint8_t *inst = loc - 3;
   uint8_t reg = loc[-1] >> 3;
   uint8_t *regSlot = loc - 1;
@@ -546,17 +536,7 @@ void X86_64::relaxTlsIeToLe(uint8_t *loc, const Relocation &,
   write32le(loc, val + 4);
 }
 
-void X86_64::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
-                            uint64_t val) const {
-  if (rel.type == R_X86_64_DTPOFF64) {
-    write64le(loc, val);
-    return;
-  }
-  if (rel.type == R_X86_64_DTPOFF32) {
-    write32le(loc, val);
-    return;
-  }
-
+static void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) {
   const uint8_t inst[] = {
       0x66, 0x66,                                           // .word 0x6666
       0x66,                                                 // .byte 0x66
@@ -718,9 +698,12 @@ int64_t X86_64::getImplicitAddend(const uint8_t *buf, RelType type) const {
   case R_X86_64_GOT64:
   case R_X86_64_GOTOFF64:
   case R_X86_64_GOTPC64:
+  case R_X86_64_PLTOFF64:
   case R_X86_64_IRELATIVE:
   case R_X86_64_RELATIVE:
     return read64le(buf);
+  case R_X86_64_TLSDESC:
+    return read64le(buf + 8);
   case R_X86_64_JUMP_SLOT:
   case R_X86_64_NONE:
     // These relocations are defined as not having an implicit addend.
@@ -732,6 +715,8 @@ int64_t X86_64::getImplicitAddend(const uint8_t *buf, RelType type) const {
   }
 }
 
+static void relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val);
+
 void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   switch (rel.type) {
   case R_X86_64_8:
@@ -755,18 +740,11 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     write32le(loc, val);
     break;
   case R_X86_64_32S:
-  case R_X86_64_TPOFF32:
   case R_X86_64_GOT32:
   case R_X86_64_GOTPC32:
-  case R_X86_64_GOTPC32_TLSDESC:
   case R_X86_64_GOTPCREL:
-  case R_X86_64_GOTPCRELX:
-  case R_X86_64_REX_GOTPCRELX:
   case R_X86_64_PC32:
-  case R_X86_64_GOTTPOFF:
   case R_X86_64_PLT32:
-  case R_X86_64_TLSGD:
-  case R_X86_64_TLSLD:
   case R_X86_64_DTPOFF32:
   case R_X86_64_SIZE32:
     checkInt(loc, val, 32, rel);
@@ -779,8 +757,55 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   case R_X86_64_GOT64:
   case R_X86_64_GOTOFF64:
   case R_X86_64_GOTPC64:
+  case R_X86_64_PLTOFF64:
     write64le(loc, val);
     break;
+  case R_X86_64_GOTPCRELX:
+  case R_X86_64_REX_GOTPCRELX:
+    if (rel.expr != R_GOT_PC) {
+      relaxGot(loc, rel, val);
+    } else {
+      checkInt(loc, val, 32, rel);
+      write32le(loc, val);
+    }
+    break;
+  case R_X86_64_GOTPC32_TLSDESC:
+  case R_X86_64_TLSDESC_CALL:
+  case R_X86_64_TLSGD:
+    if (rel.expr == R_RELAX_TLS_GD_TO_LE) {
+      relaxTlsGdToLe(loc, rel, val);
+    } else if (rel.expr == R_RELAX_TLS_GD_TO_IE) {
+      relaxTlsGdToIe(loc, rel, val);
+    } else {
+      checkInt(loc, val, 32, rel);
+      write32le(loc, val);
+    }
+    break;
+  case R_X86_64_TLSLD:
+    if (rel.expr == R_RELAX_TLS_LD_TO_LE) {
+      relaxTlsLdToLe(loc, rel, val);
+    } else {
+      checkInt(loc, val, 32, rel);
+      write32le(loc, val);
+    }
+    break;
+  case R_X86_64_GOTTPOFF:
+    if (rel.expr == R_RELAX_TLS_IE_TO_LE) {
+      relaxTlsIeToLe(loc, rel, val);
+    } else {
+      checkInt(loc, val, 32, rel);
+      write32le(loc, val);
+    }
+    break;
+  case R_X86_64_TPOFF32:
+    checkInt(loc, val, 32, rel);
+    write32le(loc, val);
+    break;
+
+  case R_X86_64_TLSDESC:
+    // The addend is stored in the second 64-bit word.
+    write64le(loc + 8, val);
+    break;
   default:
     llvm_unreachable("unknown relocation");
   }
@@ -792,8 +817,8 @@ RelExpr X86_64::adjustGotPcExpr(RelType type, int64_t addend,
   // with addend != -4. Such an instruction does not load the full GOT entry, so
   // we cannot relax the relocation. E.g. movl x@GOTPCREL+4(%rip), %rax
   // (addend=0) loads the high 32 bits of the GOT entry.
-  if ((type != R_X86_64_GOTPCRELX && type != R_X86_64_REX_GOTPCRELX) ||
-      addend != -4)
+  if (!config->relax || addend != -4 ||
+      (type != R_X86_64_GOTPCRELX && type != R_X86_64_REX_GOTPCRELX))
     return R_GOT_PC;
   const uint8_t op = loc[-2];
   const uint8_t modRm = loc[-1];
@@ -886,7 +911,7 @@ static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op,
   write32le(loc, val);
 }
 
-void X86_64::relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) const {
+static void relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) {
   checkInt(loc, val, 32, rel);
   const uint8_t op = loc[-2];
   const uint8_t modRm = loc[-1];
@@ -932,7 +957,7 @@ void X86_64::relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) const {
 bool X86_64::adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
                                               uint8_t stOther) const {
   if (!config->is64) {
-    error("Target doesn't support split stacks.");
+    error("target doesn't support split stacks");
     return false;
   }
 
@@ -960,6 +985,25 @@ bool X86_64::adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
   return false;
 }
 
+void X86_64::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
+  uint64_t secAddr = sec.getOutputSection()->addr;
+  if (auto *s = dyn_cast<InputSection>(&sec))
+    secAddr += s->outSecOff;
+  for (const Relocation &rel : sec.relocs()) {
+    if (rel.expr == R_NONE) // See deleteFallThruJmpInsn
+      continue;
+    uint8_t *loc = buf + rel.offset;
+    const uint64_t val =
+        sec.getRelocTargetVA(sec.file, rel.type, rel.addend,
+                             secAddr + rel.offset, *rel.sym, rel.expr);
+    relocate(loc, rel, val);
+  }
+  if (sec.jumpInstrMod) {
+    applyJumpInstrMod(buf + sec.jumpInstrMod->offset,
+                      sec.jumpInstrMod->original, sec.jumpInstrMod->size);
+  }
+}
+
 // If Intel Indirect Branch Tracking is enabled, we have to emit special PLT
 // entries containing endbr64 instructions. A PLT entry will be split into two
 // parts, one in .plt.sec (writePlt), and the other in .plt (writeIBTPlt).
@@ -980,7 +1024,7 @@ IntelIBT::IntelIBT() { pltHeaderSize = 0; }
 
 void IntelIBT::writeGotPlt(uint8_t *buf, const Symbol &s) const {
   uint64_t va =
-      in.ibtPlt->getVA() + IBTPltHeaderSize + s.pltIndex * pltEntrySize;
+      in.ibtPlt->getVA() + IBTPltHeaderSize + s.getPltIdx() * pltEntrySize;
   write64le(buf, va);
 }
 
@@ -1093,7 +1137,7 @@ void Retpoline::writePlt(uint8_t *buf, const Symbol &sym,
   write32le(buf + 7, sym.getGotPltVA() - pltEntryAddr - 11);
   write32le(buf + 12, -off - 16 + 32);
   write32le(buf + 17, -off - 21 + 18);
-  write32le(buf + 22, sym.pltIndex);
+  write32le(buf + 22, sym.getPltIdx());
   write32le(buf + 27, -off - 31);
 }
 
index 73d4c8b..64734b5 100644 (file)
 
 #include "lld/Common/ErrorHandler.h"
 #include "llvm/ADT/CachedHashString.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/BinaryFormat/ELF.h"
+#include "llvm/Option/ArgList.h"
 #include "llvm/Support/CachePruning.h"
 #include "llvm/Support/CodeGen.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Compression.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/GlobPattern.h"
 #include "llvm/Support/PrettyStackTrace.h"
 #include <atomic>
+#include <memory>
+#include <optional>
 #include <vector>
 
-namespace lld {
-namespace elf {
+namespace lld::elf {
 
 class InputFile;
+class BinaryFile;
+class BitcodeFile;
+class ELFFileBase;
+class SharedFile;
 class InputSectionBase;
+class EhInputSection;
+class Symbol;
+class BitcodeCompiler;
 
-enum ELFKind {
+enum ELFKind : uint8_t {
   ELFNoneKind,
   ELF32LEKind,
   ELF32BEKind,
@@ -86,15 +98,40 @@ struct SymbolVersion {
 struct VersionDefinition {
   llvm::StringRef name;
   uint16_t id;
-  std::vector<SymbolVersion> nonLocalPatterns;
-  std::vector<SymbolVersion> localPatterns;
+  SmallVector<SymbolVersion, 0> nonLocalPatterns;
+  SmallVector<SymbolVersion, 0> localPatterns;
+};
+
+class LinkerDriver {
+public:
+  void linkerMain(ArrayRef<const char *> args);
+  void addFile(StringRef path, bool withLOption);
+  void addLibrary(StringRef name);
+
+private:
+  void createFiles(llvm::opt::InputArgList &args);
+  void inferMachineType();
+  void link(llvm::opt::InputArgList &args);
+  template <class ELFT> void compileBitcodeFiles(bool skipLinkedOutput);
+
+  // True if we are in --whole-archive and --no-whole-archive.
+  bool inWholeArchive = false;
+
+  // True if we are in --start-lib and --end-lib.
+  bool inLib = false;
+
+  std::unique_ptr<BitcodeCompiler> lto;
+  std::vector<InputFile *> files;
+
+public:
+  SmallVector<std::pair<StringRef, unsigned>, 0> archiveFiles;
 };
 
 // This struct contains the global configuration for the linker.
 // Most fields are direct mapping from the command line options
 // and such fields have the same name as the corresponding options.
-// Most fields are initialized by the driver.
-struct Configuration {
+// Most fields are initialized by the ctx.driver.
+struct Config {
   uint8_t osabi = 0;
   uint32_t andFeatures = 0;
   llvm::CachePruningPolicy thinLTOCachePolicy;
@@ -117,9 +154,10 @@ struct Configuration {
   llvm::StringRef mapFile;
   llvm::StringRef outputFile;
   llvm::StringRef optRemarksFilename;
-  llvm::Optional<uint64_t> optRemarksHotnessThreshold = 0;
+  std::optional<uint64_t> optRemarksHotnessThreshold = 0;
   llvm::StringRef optRemarksPasses;
   llvm::StringRef optRemarksFormat;
+  llvm::StringRef optStatsFilename;
   llvm::StringRef progName;
   llvm::StringRef printArchiveStats;
   llvm::StringRef printSymbolOrder;
@@ -127,24 +165,29 @@ struct Configuration {
   llvm::StringRef sysroot;
   llvm::StringRef thinLTOCacheDir;
   llvm::StringRef thinLTOIndexOnlyArg;
+  llvm::StringRef whyExtract;
+  StringRef zBtiReport = "none";
+  StringRef zCetReport = "none";
   llvm::StringRef ltoBasicBlockSections;
   std::pair<llvm::StringRef, llvm::StringRef> thinLTOObjectSuffixReplace;
   std::pair<llvm::StringRef, llvm::StringRef> thinLTOPrefixReplace;
   std::string rpath;
-  std::vector<VersionDefinition> versionDefinitions;
-  std::vector<llvm::StringRef> auxiliaryList;
-  std::vector<llvm::StringRef> filterList;
-  std::vector<llvm::StringRef> searchPaths;
-  std::vector<llvm::StringRef> symbolOrderingFile;
-  std::vector<llvm::StringRef> thinLTOModulesToCompile;
-  std::vector<llvm::StringRef> undefined;
-  std::vector<SymbolVersion> dynamicList;
-  std::vector<uint8_t> buildIdVector;
+  llvm::SmallVector<VersionDefinition, 0> versionDefinitions;
+  llvm::SmallVector<llvm::StringRef, 0> auxiliaryList;
+  llvm::SmallVector<llvm::StringRef, 0> filterList;
+  llvm::SmallVector<llvm::StringRef, 0> passPlugins;
+  llvm::SmallVector<llvm::StringRef, 0> searchPaths;
+  llvm::SmallVector<llvm::StringRef, 0> symbolOrderingFile;
+  llvm::SmallVector<llvm::StringRef, 0> thinLTOModulesToCompile;
+  llvm::SmallVector<llvm::StringRef, 0> undefined;
+  llvm::SmallVector<SymbolVersion, 0> dynamicList;
+  llvm::SmallVector<uint8_t, 0> buildIdVector;
+  llvm::SmallVector<llvm::StringRef, 0> mllvmOpts;
   llvm::MapVector<std::pair<const InputSectionBase *, const InputSectionBase *>,
                   uint64_t>
       callGraphProfile;
   bool allowMultipleDefinition;
-  bool androidPackDynRelocs;
+  bool androidPackDynRelocs = false;
   bool armHasBlx = false;
   bool armHasMovtMovw = false;
   bool armJ1J2BranchEncoding = false;
@@ -153,10 +196,10 @@ struct Configuration {
   bool callGraphProfileSort;
   bool checkSections;
   bool checkDynamicRelocs;
-  bool compressDebugSections;
+  llvm::DebugCompressionType compressDebugSections;
   bool cref;
-  std::vector<std::pair<llvm::GlobPattern, uint64_t>> deadRelocInNonAlloc;
-  bool defineCommon;
+  llvm::SmallVector<std::pair<llvm::GlobPattern, uint64_t>, 0>
+      deadRelocInNonAlloc;
   bool demangle = true;
   bool dependentLibraries;
   bool disableVerify;
@@ -178,10 +221,9 @@ struct Configuration {
   bool ignoreDataAddressEquality;
   bool ignoreFunctionAddressEquality;
   bool ltoCSProfileGenerate;
+  bool ltoPGOWarnMismatch;
   bool ltoDebugPassManager;
   bool ltoEmitAsm;
-  bool ltoNewPassManager;
-  bool ltoPseudoProbeForProfiling;
   bool ltoUniqueBasicBlockSectionNames;
   bool ltoWholeProgramVisibility;
   bool mergeArmExidx;
@@ -193,6 +235,7 @@ struct Configuration {
   bool nostdlib;
   bool oFormatBinary;
   bool omagic;
+  bool opaquePointers;
   bool optEB = false;
   bool optEL = false;
   bool optimizeBBJumps;
@@ -201,10 +244,12 @@ struct Configuration {
   bool pie;
   bool printGcSections;
   bool printIcfSections;
+  bool relax;
   bool relocatable;
-  bool relrPackDynRelocs;
-  bool saveTemps;
-  std::vector<std::pair<llvm::GlobPattern, uint32_t>> shuffleSections;
+  bool relrGlibc = false;
+  bool relrPackDynRelocs = false;
+  llvm::DenseSet<llvm::StringRef> saveTempsArgs;
+  llvm::SmallVector<std::pair<llvm::GlobPattern, uint32_t>, 0> shuffleSections;
   bool singleRoRx;
   bool shared;
   bool symbolic;
@@ -213,6 +258,7 @@ struct Configuration {
   bool target1Rel;
   bool trace;
   bool thinLTOEmitImportsFiles;
+  bool thinLTOEmitIndexFiles;
   bool thinLTOIndexOnly;
   bool timeTraceEnabled;
   bool tocOptimize;
@@ -221,7 +267,7 @@ struct Configuration {
   bool unique;
   bool useAndroidRelrTags = false;
   bool warnBackrefs;
-  std::vector<llvm::GlobPattern> warnBackrefsExclude;
+  llvm::SmallVector<llvm::GlobPattern, 0> warnBackrefsExclude;
   bool warnCommon;
   bool warnMissingEntry;
   bool warnSymbolOrdering;
@@ -260,13 +306,13 @@ struct Configuration {
   UnresolvedPolicy unresolvedSymbols;
   UnresolvedPolicy unresolvedSymbolsInShlib;
   Target2Policy target2;
-  bool Power10Stub;
+  bool power10Stubs;
   ARMVFPArgKind armVFPArgs = ARMVFPArgKind::Default;
   BuildIdKind buildId = BuildIdKind::None;
   SeparateSegmentKind zSeparate;
   ELFKind ekind = ELFNoneKind;
   uint16_t emachine = llvm::ELF::EM_NONE;
-  llvm::Optional<uint64_t> imageBase;
+  std::optional<uint64_t> imageBase;
   // commonPageSize and maxPageSize are influenced by nmagic or omagic
   // so may be set to 1 if either of those options is given.
   uint64_t commonPageSize;
@@ -282,6 +328,7 @@ struct Configuration {
   StringRef thinLTOJobs;
   unsigned timeTraceGranularity;
   int32_t splitStackAdjustSize;
+  StringRef packageMetadata;
 
   // The following config options do not directly correspond to any
   // particular command line options.
@@ -313,19 +360,10 @@ struct Configuration {
   // if that's true.)
   bool isMips64EL;
 
-  // True if we need to set the DF_STATIC_TLS flag to an output file,
-  // which works as a hint to the dynamic loader that the file contains
-  // code compiled with the static TLS model. The thread-local variable
-  // compiled with the static TLS model is faster but less flexible, and
-  // it may not be loaded using dlopen().
-  //
-  // We set this flag to true when we see a relocation for the static TLS
-  // model. Once this becomes true, it will never become false.
-  //
-  // Since the flag is updated by multi-threaded code, we use std::atomic.
-  // (Writing to a variable is not considered thread-safe even if the
-  // variable is boolean and we always set the same value from all threads.)
-  std::atomic<bool> hasStaticTlsModel{false};
+  // True if we need to set the DF_STATIC_TLS flag to an output file, which
+  // works as a hint to the dynamic loader that the shared object contains code
+  // compiled with the initial-exec TLS model.
+  bool hasTlsIe = false;
 
   // Holds set of ELF header flags for the target.
   uint32_t eflags = 0;
@@ -351,30 +389,83 @@ struct Configuration {
 
   // 4 for ELF32, 8 for ELF64.
   int wordsize;
+
+  // Mode of MTE to write to the ELF note. Should be one of NT_MEMTAG_ASYNC (for
+  // async), NT_MEMTAG_SYNC (for sync), or NT_MEMTAG_LEVEL_NONE (for none). If
+  // async or sync is enabled, write the ELF note specifying the default MTE
+  // mode.
+  int androidMemtagMode;
+  // Signal to the dynamic loader to enable heap MTE.
+  bool androidMemtagHeap;
+  // Signal to the dynamic loader that this binary expects stack MTE. Generally,
+  // this means to map the primary and thread stacks as PROT_MTE. Note: This is
+  // not supported on Android 11 & 12.
+  bool androidMemtagStack;
+
+  unsigned threadCount;
+};
+struct ConfigWrapper {
+  Config c;
+  Config *operator->() { return &c; }
+};
+
+LLVM_LIBRARY_VISIBILITY extern ConfigWrapper config;
+
+struct DuplicateSymbol {
+  const Symbol *sym;
+  const InputFile *file;
+  InputSectionBase *section;
+  uint64_t value;
+};
+
+struct Ctx {
+  LinkerDriver driver;
+  SmallVector<std::unique_ptr<MemoryBuffer>> memoryBuffers;
+  SmallVector<ELFFileBase *, 0> objectFiles;
+  SmallVector<SharedFile *, 0> sharedFiles;
+  SmallVector<BinaryFile *, 0> binaryFiles;
+  SmallVector<BitcodeFile *, 0> bitcodeFiles;
+  SmallVector<BitcodeFile *, 0> lazyBitcodeFiles;
+  SmallVector<InputSectionBase *, 0> inputSections;
+  SmallVector<EhInputSection *, 0> ehInputSections;
+  // Duplicate symbol candidates.
+  SmallVector<DuplicateSymbol, 0> duplicates;
+  // Symbols in a non-prevailing COMDAT group which should be changed to an
+  // Undefined.
+  SmallVector<std::pair<Symbol *, unsigned>, 0> nonPrevailingSyms;
+  // A tuple of (reference, extractedFile, sym). Used by --why-extract=.
+  SmallVector<std::tuple<std::string, const InputFile *, const Symbol &>, 0>
+      whyExtractRecords;
+  // A mapping from a symbol to an InputFile referencing it backward. Used by
+  // --warn-backrefs.
+  llvm::DenseMap<const Symbol *,
+                 std::pair<const InputFile *, const InputFile *>>
+      backwardReferences;
+  // True if SHT_LLVM_SYMPART is used.
+  std::atomic<bool> hasSympart{false};
+  // True if there are TLS IE relocations. Set DF_STATIC_TLS if -shared.
+  std::atomic<bool> hasTlsIe{false};
+  // True if we need to reserve two .got entries for local-dynamic TLS model.
+  std::atomic<bool> needsTlsLd{false};
+
+  void reset();
 };
 
-// The only instance of Configuration struct.
-extern Configuration *config;
+LLVM_LIBRARY_VISIBILITY extern Ctx ctx;
 
 // The first two elements of versionDefinitions represent VER_NDX_LOCAL and
 // VER_NDX_GLOBAL. This helper returns other elements.
 static inline ArrayRef<VersionDefinition> namedVersionDefs() {
-  return llvm::makeArrayRef(config->versionDefinitions).slice(2);
+  return llvm::ArrayRef(config->versionDefinitions).slice(2);
 }
 
-static inline void errorOrWarn(const Twine &msg) {
-  if (!config->noinhibitExec)
-    error(msg);
-  else
-    warn(msg);
-}
+void errorOrWarn(const Twine &msg);
 
 static inline void internalLinkerError(StringRef loc, const Twine &msg) {
   errorOrWarn(loc + "internal linker error: " + msg + "\n" +
               llvm::getBugReportMsg());
 }
 
-} // namespace elf
-} // namespace lld
+} // namespace lld::elf
 
 #endif
index ee98672..3eca6aa 100644 (file)
@@ -15,7 +15,7 @@
 // linker path or library paths) for each host OS.
 //
 // I don't think implicit default values are useful because they are
-// usually explicitly specified by the compiler driver. They can even
+// usually explicitly specified by the compiler ctx.driver. They can even
 // be harmful when you are doing cross-linking. Therefore, in LLD, we
 // simply trust the compiler driver to pass all required options and
 // don't try to make effort on our side.
@@ -27,6 +27,7 @@
 #include "ICF.h"
 #include "InputFiles.h"
 #include "InputSection.h"
+#include "LTO.h"
 #include "LinkerScript.h"
 #include "MarkLive.h"
 #include "OutputSections.h"
@@ -37,6 +38,7 @@
 #include "Target.h"
 #include "Writer.h"
 #include "lld/Common/Args.h"
+#include "lld/Common/CommonLinkerContext.h"
 #include "lld/Common/Driver.h"
 #include "lld/Common/ErrorHandler.h"
 #include "lld/Common/Filesystem.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/LTO/LTO.h"
+#include "llvm/Object/Archive.h"
 #include "llvm/Remarks/HotnessThresholdParser.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Compression.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/GlobPattern.h"
 #include "llvm/Support/LEB128.h"
 #include "llvm/Support/Parallel.h"
@@ -71,66 +75,76 @@ using namespace llvm::support;
 using namespace lld;
 using namespace lld::elf;
 
-Configuration *elf::config;
-LinkerDriver *elf::driver;
+ConfigWrapper elf::config;
+Ctx elf::ctx;
 
 static void setConfigs(opt::InputArgList &args);
 static void readConfigs(opt::InputArgList &args);
 
-bool elf::link(ArrayRef<const char *> args, bool canExitEarly,
-               raw_ostream &stdoutOS, raw_ostream &stderrOS) {
-  lld::stdoutOS = &stdoutOS;
-  lld::stderrOS = &stderrOS;
-
-  errorHandler().cleanupCallback = []() {
-    freeArena();
+void elf::errorOrWarn(const Twine &msg) {
+  if (config->noinhibitExec)
+    warn(msg);
+  else
+    error(msg);
+}
+
+void Ctx::reset() {
+  driver = LinkerDriver();
+  memoryBuffers.clear();
+  objectFiles.clear();
+  sharedFiles.clear();
+  binaryFiles.clear();
+  bitcodeFiles.clear();
+  lazyBitcodeFiles.clear();
+  inputSections.clear();
+  ehInputSections.clear();
+  duplicates.clear();
+  nonPrevailingSyms.clear();
+  whyExtractRecords.clear();
+  backwardReferences.clear();
+  hasSympart.store(false, std::memory_order_relaxed);
+  needsTlsLd.store(false, std::memory_order_relaxed);
+}
+
+bool elf::link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
+               llvm::raw_ostream &stderrOS, bool exitEarly,
+               bool disableOutput) {
+  // This driver-specific context will be freed later by lldMain().
+  auto *ctx = new CommonLinkerContext;
+
+  ctx->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput);
+  ctx->e.cleanupCallback = []() {
+    elf::ctx.reset();
+    symtab = SymbolTable();
 
-    inputSections.clear();
     outputSections.clear();
-    archiveFiles.clear();
-    binaryFiles.clear();
-    bitcodeFiles.clear();
-    lazyObjFiles.clear();
-    objectFiles.clear();
-    sharedFiles.clear();
-    backwardReferences.clear();
+    symAux.clear();
 
     tar = nullptr;
-    memset(&in, 0, sizeof(in));
+    in.reset();
 
-    partitions = {Partition()};
+    partitions.clear();
+    partitions.emplace_back();
 
     SharedFile::vernauxNum = 0;
   };
+  ctx->e.logName = args::getFilenameWithoutExe(args[0]);
+  ctx->e.errorLimitExceededMsg = "too many errors emitted, stopping now (use "
+                                 "--error-limit=0 to see all errors)";
 
-  errorHandler().logName = args::getFilenameWithoutExe(args[0]);
-  errorHandler().errorLimitExceededMsg =
-      "too many errors emitted, stopping now (use "
-      "-error-limit=0 to see all errors)";
-  errorHandler().exitEarly = canExitEarly;
-  stderrOS.enable_colors(stderrOS.has_colors());
+  config = ConfigWrapper();
+  script = std::make_unique<LinkerScript>();
 
-  config = make<Configuration>();
-  driver = make<LinkerDriver>();
-  script = make<LinkerScript>();
-  symtab = make<SymbolTable>();
+  symAux.emplace_back();
 
-  partitions = {Partition()};
+  partitions.clear();
+  partitions.emplace_back();
 
   config->progName = args[0];
 
-  driver->linkerMain(args);
-
-  // Exit immediately if we don't need to return to the caller.
-  // This saves time because the overhead of calling destructors
-  // for all globally-allocated objects is not negligible.
-  if (canExitEarly)
-    exitLld(errorCount() ? 1 : 0);
+  elf::ctx.driver.linkerMain(args);
 
-  bool ret = errorCount() == 0;
-  if (!canExitEarly)
-    errorHandler().reset();
-  return ret;
+  return errorCount() == 0;
 }
 
 // Parses a linker -m option.
@@ -163,12 +177,15 @@ static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef emul) {
           .Case("elf_iamcu", {ELF32LEKind, EM_IAMCU})
           .Case("elf64_sparc", {ELF64BEKind, EM_SPARCV9})
           .Case("msp430elf", {ELF32LEKind, EM_MSP430})
+          .Case("elf64_amdgpu", {ELF64LEKind, EM_AMDGPU})
           .Default({ELFNoneKind, EM_NONE});
 
   if (ret.first == ELFNoneKind)
     error("unknown emulation: " + emul);
   if (ret.second == EM_MSP430)
     osabi = ELFOSABI_STANDALONE;
+  else if (ret.second == EM_AMDGPU)
+    osabi = ELFOSABI_AMDGPU_HSA;
   return std::make_tuple(ret.first, ret.second, osabi);
 }
 
@@ -197,18 +214,22 @@ std::vector<std::pair<MemoryBufferRef, uint64_t>> static getArchiveMembers(
           toString(std::move(err)));
 
   // Take ownership of memory buffers created for members of thin archives.
-  for (std::unique_ptr<MemoryBuffer> &mb : file->takeThinBuffers())
-    make<std::unique_ptr<MemoryBuffer>>(std::move(mb));
+  std::vector<std::unique_ptr<MemoryBuffer>> mbs = file->takeThinBuffers();
+  std::move(mbs.begin(), mbs.end(), std::back_inserter(ctx.memoryBuffers));
 
   return v;
 }
 
+static bool isBitcode(MemoryBufferRef mb) {
+  return identify_magic(mb.getBuffer()) == llvm::file_magic::bitcode;
+}
+
 // Opens a file and create a file object. Path has to be resolved already.
 void LinkerDriver::addFile(StringRef path, bool withLOption) {
   using namespace sys::fs;
 
-  Optional<MemoryBufferRef> buffer = readFile(path);
-  if (!buffer.hasValue())
+  std::optional<MemoryBufferRef> buffer = readFile(path);
+  if (!buffer)
     return;
   MemoryBufferRef mbref = *buffer;
 
@@ -222,65 +243,70 @@ void LinkerDriver::addFile(StringRef path, bool withLOption) {
     readLinkerScript(mbref);
     return;
   case file_magic::archive: {
-    // Handle -whole-archive.
+    auto members = getArchiveMembers(mbref);
     if (inWholeArchive) {
-      for (const auto &p : getArchiveMembers(mbref))
-        files.push_back(createObjectFile(p.first, path, p.second));
+      for (const std::pair<MemoryBufferRef, uint64_t> &p : members) {
+        if (isBitcode(p.first))
+          files.push_back(make<BitcodeFile>(p.first, path, p.second, false));
+        else
+          files.push_back(createObjFile(p.first, path));
+      }
       return;
     }
 
-    std::unique_ptr<Archive> file =
-        CHECK(Archive::create(mbref), path + ": failed to parse archive");
-
-    // If an archive file has no symbol table, it is likely that a user
-    // is attempting LTO and using a default ar command that doesn't
-    // understand the LLVM bitcode file. It is a pretty common error, so
-    // we'll handle it as if it had a symbol table.
-    if (!file->isEmpty() && !file->hasSymbolTable()) {
-      // Check if all members are bitcode files. If not, ignore, which is the
-      // default action without the LTO hack described above.
-      for (const std::pair<MemoryBufferRef, uint64_t> &p :
-           getArchiveMembers(mbref))
-        if (identify_magic(p.first.getBuffer()) != file_magic::bitcode) {
-          error(path + ": archive has no index; run ranlib to add one");
-          return;
-        }
-
-      for (const std::pair<MemoryBufferRef, uint64_t> &p :
-           getArchiveMembers(mbref))
-        files.push_back(make<LazyObjFile>(p.first, path, p.second));
-      return;
+    archiveFiles.emplace_back(path, members.size());
+
+    // Handle archives and --start-lib/--end-lib using the same code path. This
+    // scans all the ELF relocatable object files and bitcode files in the
+    // archive rather than just the index file, with the benefit that the
+    // symbols are only loaded once. For many projects archives see high
+    // utilization rates and it is a net performance win. --start-lib scans
+    // symbols in the same order that llvm-ar adds them to the index, so in the
+    // common case the semantics are identical. If the archive symbol table was
+    // created in a different order, or is incomplete, this strategy has
+    // different semantics. Such output differences are considered user error.
+    //
+    // All files within the archive get the same group ID to allow mutual
+    // references for --warn-backrefs.
+    bool saved = InputFile::isInGroup;
+    InputFile::isInGroup = true;
+    for (const std::pair<MemoryBufferRef, uint64_t> &p : members) {
+      auto magic = identify_magic(p.first.getBuffer());
+      if (magic == file_magic::elf_relocatable)
+        files.push_back(createObjFile(p.first, path, true));
+      else if (magic == file_magic::bitcode)
+        files.push_back(make<BitcodeFile>(p.first, path, p.second, true));
+      else
+        warn(path + ": archive member '" + p.first.getBufferIdentifier() +
+             "' is neither ET_REL nor LLVM bitcode");
     }
-
-    // Handle the regular case.
-    files.push_back(make<ArchiveFile>(std::move(file)));
+    InputFile::isInGroup = saved;
+    if (!saved)
+      ++InputFile::nextGroupId;
     return;
   }
-  case file_magic::elf_shared_object:
+  case file_magic::elf_shared_object: {
     if (config->isStatic || config->relocatable) {
       error("attempted static link of dynamic object " + path);
       return;
     }
 
-    // DSOs usually have DT_SONAME tags in their ELF headers, and the
-    // sonames are used to identify DSOs. But if they are missing,
-    // they are identified by filenames. We don't know whether the new
-    // file has a DT_SONAME or not because we haven't parsed it yet.
-    // Here, we set the default soname for the file because we might
-    // need it later.
-    //
-    // If a file was specified by -lfoo, the directory part is not
-    // significant, as a user did not specify it. This behavior is
-    // compatible with GNU.
-    files.push_back(
-        make<SharedFile>(mbref, withLOption ? path::filename(path) : path));
+    // Shared objects are identified by soname. soname is (if specified)
+    // DT_SONAME and falls back to filename. If a file was specified by -lfoo,
+    // the directory part is ignored. Note that path may be a temporary and
+    // cannot be stored into SharedFile::soName.
+    path = mbref.getBufferIdentifier();
+    auto *f =
+        make<SharedFile>(mbref, withLOption ? path::filename(path) : path);
+    f->init();
+    files.push_back(f);
     return;
+  }
   case file_magic::bitcode:
+    files.push_back(make<BitcodeFile>(mbref, "", 0, inLib));
+    break;
   case file_magic::elf_relocatable:
-    if (inLib)
-      files.push_back(make<LazyObjFile>(mbref, "", 0));
-    else
-      files.push_back(createObjectFile(mbref));
+    files.push_back(createObjFile(mbref, "", inLib));
     break;
   default:
     error(path + ": unknown file type");
@@ -289,8 +315,8 @@ void LinkerDriver::addFile(StringRef path, bool withLOption) {
 
 // Add a given library by searching it from input search paths.
 void LinkerDriver::addLibrary(StringRef name) {
-  if (Optional<std::string> path = searchLibrary(name))
-    addFile(*path, /*withLOption=*/true);
+  if (std::optional<std::string> path = searchLibrary(name))
+    addFile(saver().save(*path), /*withLOption=*/true);
   else
     error("unable to find library -l" + name, ErrorTag::LibNotFound, {name});
 }
@@ -335,9 +361,6 @@ static void checkOptions() {
   if (!config->shared && !config->auxiliaryList.empty())
     error("-f may not be used without -shared");
 
-  if (!config->relocatable && !config->defineCommon)
-    error("-no-define-common not supported in non relocatable output");
-
   if (config->strip == StripPolicy::All && config->emitRelocs)
     error("--strip-all and --emit-relocs may not be used together");
 
@@ -373,7 +396,7 @@ static void checkOptions() {
     }
 
     if (config->singleRoRx && !script->hasSectionsCommand)
-      error("-execute-only and -no-rosegment cannot be used together");
+      error("--execute-only and --no-rosegment cannot be used together");
   }
 
   if (config->zRetpolineplt && config->zForceIbt)
@@ -384,7 +407,13 @@ static void checkOptions() {
       error("-z pac-plt only supported on AArch64");
     if (config->zForceBti)
       error("-z force-bti only supported on AArch64");
+    if (config->zBtiReport != "none")
+      error("-z bti-report only supported on AArch64");
   }
+
+  if (config->emachine != EM_386 && config->emachine != EM_X86_64 &&
+      config->zCetReport != "none")
+    error("-z cet-report only supported on X86 and X86_64");
 }
 
 static const char *getReproduceOption(opt::InputArgList &args) {
@@ -455,42 +484,84 @@ static uint8_t getZStartStopVisibility(opt::InputArgList &args) {
   return STV_PROTECTED;
 }
 
+constexpr const char *knownZFlags[] = {
+    "combreloc",
+    "copyreloc",
+    "defs",
+    "execstack",
+    "force-bti",
+    "force-ibt",
+    "global",
+    "hazardplt",
+    "ifunc-noplt",
+    "initfirst",
+    "interpose",
+    "keep-text-section-prefix",
+    "lazy",
+    "muldefs",
+    "nobtcfi",
+    "nocombreloc",
+    "nocopyreloc",
+    "nodefaultlib",
+    "nodelete",
+    "nodlopen",
+    "noexecstack",
+    "nognustack",
+    "nokeep-text-section-prefix",
+    "nopack-relative-relocs",
+    "norelro",
+    "noretpolineplt",
+    "noseparate-code",
+    "nostart-stop-gc",
+    "notext",
+    "now",
+    "origin",
+    "pac-plt",
+    "pack-relative-relocs",
+    "rel",
+    "rela",
+    "relro",
+    "retpolineplt",
+    "rodynamic",
+    "separate-code",
+    "separate-loadable-segments",
+    "shstk",
+    "start-stop-gc",
+    "text",
+    "undefs",
+    "wxneeded",
+};
+
 static bool isKnownZFlag(StringRef s) {
-  return s == "combreloc" || s == "copyreloc" || s == "defs" ||
-         s == "execstack" || s == "force-bti" || s == "force-ibt" ||
-         s == "global" || s == "hazardplt" || s == "ifunc-noplt" ||
-         s == "initfirst" || s == "interpose" ||
-         s == "keep-text-section-prefix" || s == "lazy" || s == "muldefs" ||
-         s == "separate-code" || s == "separate-loadable-segments" ||
-         s == "start-stop-gc" || s == "nobtcfi" ||
-         s == "nocombreloc" || s == "nocopyreloc" ||
-         s == "nodefaultlib" || s == "nodelete" || s == "nodlopen" ||
-         s == "noexecstack" || s == "nognustack" ||
-         s == "nokeep-text-section-prefix" || s == "norelro" ||
-         s == "noretpolineplt" ||
-         s == "noseparate-code" || s == "nostart-stop-gc" || s == "notext" ||
-         s == "now" || s == "origin" || s == "pac-plt" || s == "rel" ||
-         s == "rela" || s == "relro" || s == "retpolineplt" ||
-         s == "rodynamic" || s == "shstk" || s == "text" || s == "undefs" ||
-         s == "wxneeded" || s.startswith("common-page-size=") ||
+  return llvm::is_contained(knownZFlags, s) ||
+         s.startswith("common-page-size=") || s.startswith("bti-report=") ||
+         s.startswith("cet-report=") ||
          s.startswith("dead-reloc-in-nonalloc=") ||
          s.startswith("max-page-size=") || s.startswith("stack-size=") ||
          s.startswith("start-stop-visibility=");
 }
 
-// Report an error for an unknown -z option.
+// Report a warning for an unknown -z option.
 static void checkZOptions(opt::InputArgList &args) {
   for (auto *arg : args.filtered(OPT_z))
     if (!isKnownZFlag(arg->getValue()))
-      error("unknown -z value: " + StringRef(arg->getValue()));
+      warn("unknown -z value: " + StringRef(arg->getValue()));
 }
 
+constexpr const char *saveTempsValues[] = {
+    "resolution", "preopt",     "promote", "internalize",  "import",
+    "opt",        "precodegen", "prelink", "combinedindex"};
+
 void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   ELFOptTable parser;
   opt::InputArgList args = parser.parse(argsArr.slice(1));
 
-  // Interpret this flag early because error() depends on them.
+  // Interpret these flags early because error()/warn() depend on them.
   errorHandler().errorLimit = args::getInteger(args, OPT_error_limit, 20);
+  errorHandler().fatalWarnings =
+      args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false) &&
+      !args.hasArg(OPT_no_warnings);
+  errorHandler().suppressWarnings = args.hasArg(OPT_no_warnings);
   checkZOptions(args);
 
   // Handle -help
@@ -502,10 +573,9 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   // Handle -v or -version.
   //
   // A note about "compatible with GNU linkers" message: this is a hack for
-  // scripts generated by GNU Libtool 2.4.6 (released in February 2014 and
-  // still the newest version in March 2017) or earlier to recognize LLD as
-  // a GNU compatible linker. As long as an output for the -v option
-  // contains "GNU" or "with BFD", they recognize us as GNU-compatible.
+  // scripts generated by GNU Libtool up to 2021-10 to recognize LLD as
+  // a GNU compatible linker. See
+  // <https://lists.gnu.org/archive/html/libtool/2017-01/msg00007.html>.
   //
   // This is somewhat ugly hack, but in reality, we had no choice other
   // than doing this. Considering the very long release cycle of Libtool,
@@ -561,44 +631,18 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
     if (errorCount())
       return;
 
-    // The Target instance handles target-specific stuff, such as applying
-    // relocations or writing a PLT section. It also contains target-dependent
-    // values such as a default image base address.
-    target = getTarget();
-
-    switch (config->ekind) {
-    case ELF32LEKind:
-      link<ELF32LE>(args);
-      break;
-    case ELF32BEKind:
-      link<ELF32BE>(args);
-      break;
-    case ELF64LEKind:
-      link<ELF64LE>(args);
-      break;
-    case ELF64BEKind:
-      link<ELF64BE>(args);
-      break;
-    default:
-      llvm_unreachable("unknown Config->EKind");
-    }
+    link(args);
   }
 
   if (config->timeTraceEnabled) {
-    if (auto E = timeTraceProfilerWrite(args.getLastArgValue(OPT_time_trace_file_eq).str(),
-                                        config->outputFile)) {
-      handleAllErrors(std::move(E), [&](const StringError &SE) {
-        error(SE.getMessage());
-      });
-      return;
-    }
-
+    checkError(timeTraceProfilerWrite(
+        args.getLastArgValue(OPT_time_trace_eq).str(), config->outputFile));
     timeTraceProfilerCleanup();
   }
 }
 
 static std::string getRpath(opt::InputArgList &args) {
-  std::vector<StringRef> v = args::getStrings(args, OPT_rpath);
+  SmallVector<StringRef, 0> v = args::getStrings(args, OPT_rpath);
   return llvm::join(v.begin(), v.end(), ":");
 }
 
@@ -609,7 +653,7 @@ static void setUnresolvedSymbolPolicy(opt::InputArgList &args) {
                                               OPT_warn_unresolved_symbols, true)
                                      ? UnresolvedPolicy::ReportError
                                      : UnresolvedPolicy::Warn;
-  // -shared implies -unresolved-symbols=ignore-all because missing
+  // -shared implies --unresolved-symbols=ignore-all because missing
   // symbols are likely to be resolved at runtime.
   bool diagRegular = !config->shared, diagShlib = !config->shared;
 
@@ -703,6 +747,28 @@ static StringRef getDynamicLinker(opt::InputArgList &args) {
   return arg->getValue();
 }
 
+static int getMemtagMode(opt::InputArgList &args) {
+  StringRef memtagModeArg = args.getLastArgValue(OPT_android_memtag_mode);
+  if (!config->androidMemtagHeap && !config->androidMemtagStack) {
+    if (!memtagModeArg.empty())
+      error("when using --android-memtag-mode, at least one of "
+            "--android-memtag-heap or "
+            "--android-memtag-stack is required");
+    return ELF::NT_MEMTAG_LEVEL_NONE;
+  }
+
+  if (memtagModeArg == "sync" || memtagModeArg.empty())
+    return ELF::NT_MEMTAG_LEVEL_SYNC;
+  if (memtagModeArg == "async")
+    return ELF::NT_MEMTAG_LEVEL_ASYNC;
+  if (memtagModeArg == "none")
+    return ELF::NT_MEMTAG_LEVEL_NONE;
+
+  error("unknown --android-memtag-mode value: \"" + memtagModeArg +
+        "\", should be one of {async, sync, none}");
+  return ELF::NT_MEMTAG_LEVEL_NONE;
+}
+
 static ICFLevel getICF(opt::InputArgList &args) {
   auto *arg = args.getLastArg(OPT_icf_none, OPT_icf_safe, OPT_icf_all);
   if (!arg || arg->getOption().getID() == OPT_icf_none)
@@ -774,32 +840,15 @@ static OrphanHandlingPolicy getOrphanHandling(opt::InputArgList &args) {
   return OrphanHandlingPolicy::Place;
 }
 
-// Parses --power10-stubs= flags, to disable or enable Power 10
-// instructions in stubs.
-static bool getP10StubOpt(opt::InputArgList &args) {
-
-  if (args.getLastArgValue(OPT_power10_stubs_eq)== "no")
-    return false;
-
-  if (!args.hasArg(OPT_power10_stubs_eq) &&
-      args.hasArg(OPT_no_power10_stubs))
-    return false;
-
-  return true;
-}
-
 // Parse --build-id or --build-id=<style>. We handle "tree" as a
 // synonym for "sha1" because all our hash functions including
-// -build-id=sha1 are actually tree hashes for performance reasons.
-static std::pair<BuildIdKind, std::vector<uint8_t>>
+// --build-id=sha1 are actually tree hashes for performance reasons.
+static std::pair<BuildIdKind, SmallVector<uint8_t, 0>>
 getBuildId(opt::InputArgList &args) {
-  auto *arg = args.getLastArg(OPT_build_id, OPT_build_id_eq);
+  auto *arg = args.getLastArg(OPT_build_id);
   if (!arg)
     return {BuildIdKind::None, {}};
 
-  if (arg->getOption().getID() == OPT_build_id)
-    return {BuildIdKind::Fast, {}};
-
   StringRef s = arg->getValue();
   if (s == "fast")
     return {BuildIdKind::Fast, {}};
@@ -827,14 +876,14 @@ static std::pair<bool, bool> getPackDynRelocs(opt::InputArgList &args) {
     return {true, true};
 
   if (s != "none")
-    error("unknown -pack-dyn-relocs format: " + s);
+    error("unknown --pack-dyn-relocs format: " + s);
   return {false, false};
 }
 
 static void readCallGraph(MemoryBufferRef mb) {
   // Build a map from symbol name to section
   DenseMap<StringRef, Symbol *> map;
-  for (InputFile *file : objectFiles)
+  for (ELFFileBase *file : ctx.objectFiles)
     for (Symbol *sym : file->getSymbols())
       map[sym->getName()] = sym;
 
@@ -875,14 +924,13 @@ static bool
 processCallGraphRelocations(SmallVector<uint32_t, 32> &symbolIndices,
                             ArrayRef<typename ELFT::CGProfile> &cgProfile,
                             ObjFile<ELFT> *inputObj) {
-  symbolIndices.clear();
-  const ELFFile<ELFT> &obj = inputObj->getObj();
-  ArrayRef<Elf_Shdr_Impl<ELFT>> objSections =
-      CHECK(obj.sections(), "could not retrieve object sections");
-
   if (inputObj->cgProfileSectionIndex == SHN_UNDEF)
     return false;
 
+  ArrayRef<Elf_Shdr_Impl<ELFT>> objSections =
+      inputObj->template getELFShdrs<ELFT>();
+  symbolIndices.clear();
+  const ELFFile<ELFT> &obj = inputObj->getObj();
   cgProfile =
       check(obj.template getSectionContentsAsArray<typename ELFT::CGProfile>(
           objSections[inputObj->cgProfileSectionIndex]));
@@ -914,7 +962,7 @@ processCallGraphRelocations(SmallVector<uint32_t, 32> &symbolIndices,
 template <class ELFT> static void readCallGraphsFromObjectFiles() {
   SmallVector<uint32_t, 32> symbolIndices;
   ArrayRef<typename ELFT::CGProfile> cgProfile;
-  for (auto file : objectFiles) {
+  for (auto file : ctx.objectFiles) {
     auto *obj = cast<ObjFile<ELFT>>(file);
     if (!processCallGraphRelocations(symbolIndices, cgProfile, obj))
       continue;
@@ -939,15 +987,21 @@ template <class ELFT> static void readCallGraphsFromObjectFiles() {
   }
 }
 
-static bool getCompressDebugSections(opt::InputArgList &args) {
+static DebugCompressionType getCompressDebugSections(opt::InputArgList &args) {
   StringRef s = args.getLastArgValue(OPT_compress_debug_sections, "none");
-  if (s == "none")
-    return false;
-  if (s != "zlib")
+  if (s == "zlib") {
+    if (!compression::zlib::isAvailable())
+      error("--compress-debug-sections: zlib is not available");
+    return DebugCompressionType::Zlib;
+  }
+  if (s == "zstd") {
+    if (!compression::zstd::isAvailable())
+      error("--compress-debug-sections: zstd is not available");
+    return DebugCompressionType::Zstd;
+  }
+  if (s != "none")
     error("unknown --compress-debug-sections value: " + s);
-  if (!zlib::isAvailable())
-    error("--compress-debug-sections: zlib is not available");
-  return true;
+  return DebugCompressionType::None;
 }
 
 static StringRef getAliasSpelling(opt::Arg *arg) {
@@ -970,8 +1024,8 @@ static std::pair<StringRef, StringRef> getOldNewOptions(opt::InputArgList &args,
 }
 
 // Parse the symbol ordering file and warn for any duplicate entries.
-static std::vector<StringRef> getSymbolOrderingFile(MemoryBufferRef mb) {
-  SetVector<StringRef> names;
+static SmallVector<StringRef, 0> getSymbolOrderingFile(MemoryBufferRef mb) {
+  SetVector<StringRef, SmallVector<StringRef, 0>> names;
   for (StringRef s : args::getLines(mb))
     if (!names.insert(s) && config->warnSymbolOrdering)
       warn(mb.getBufferIdentifier() + ": duplicate ordered symbol: " + s);
@@ -1006,11 +1060,14 @@ static void parseClangOption(StringRef opt, const Twine &msg) {
   error(msg + ": " + StringRef(err).trim());
 }
 
+// Checks the parameter of the bti-report and cet-report options.
+static bool isValidReportString(StringRef arg) {
+  return arg == "none" || arg == "warning" || arg == "error";
+}
+
 // Initializes Config members by the command line options.
 static void readConfigs(opt::InputArgList &args) {
   errorHandler().verbose = args.hasArg(OPT_verbose);
-  errorHandler().fatalWarnings =
-      args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false);
   errorHandler().vsDiagnostics =
       args.hasArg(OPT_visual_studio_diagnostics_format, false);
 
@@ -1018,6 +1075,11 @@ static void readConfigs(opt::InputArgList &args) {
       args.hasFlag(OPT_allow_multiple_definition,
                    OPT_no_allow_multiple_definition, false) ||
       hasZOption(args, "muldefs");
+  config->androidMemtagHeap =
+      args.hasFlag(OPT_android_memtag_heap, OPT_no_android_memtag_heap, false);
+  config->androidMemtagStack = args.hasFlag(OPT_android_memtag_stack,
+                                            OPT_no_android_memtag_stack, false);
+  config->androidMemtagMode = getMemtagMode(args);
   config->auxiliaryList = args::getStrings(args, OPT_auxiliary);
   if (opt::Arg *arg =
           args.getLastArg(OPT_Bno_symbolic, OPT_Bsymbolic_non_weak_functions,
@@ -1034,8 +1096,6 @@ static void readConfigs(opt::InputArgList &args) {
   config->chroot = args.getLastArgValue(OPT_chroot);
   config->compressDebugSections = getCompressDebugSections(args);
   config->cref = args.hasArg(OPT_cref);
-  config->defineCommon = args.hasFlag(OPT_define_common, OPT_no_define_common,
-                                      !args.hasArg(OPT_relocatable));
   config->optimizeBBJumps =
       args.hasFlag(OPT_optimize_bb_jumps, OPT_no_optimize_bb_jumps, false);
   config->demangle = args.hasFlag(OPT_demangle, OPT_no_demangle, true);
@@ -1059,7 +1119,8 @@ static void readConfigs(opt::InputArgList &args) {
       args.getLastArgValue(OPT_error_handling_script);
 
   config->exportDynamic =
-      args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false);
+      args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false) ||
+      args.hasArg(OPT_shared);
   config->filterList = args::getStrings(args, OPT_filter);
   config->fini = args.getLastArgValue(OPT_fini, "_fini");
   config->fixCortexA53Errata843419 = args.hasArg(OPT_fix_cortex_a53_843419) &&
@@ -1067,7 +1128,7 @@ static void readConfigs(opt::InputArgList &args) {
   config->fixCortexA8 =
       args.hasArg(OPT_fix_cortex_a8) && !args.hasArg(OPT_relocatable);
   config->fortranCommon =
-      args.hasFlag(OPT_fortran_common, OPT_no_fortran_common, true);
+      args.hasFlag(OPT_fortran_common, OPT_no_fortran_common, false);
   config->gcSections = args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false);
   config->gnuUnique = args.hasFlag(OPT_gnu_unique, OPT_no_gnu_unique, true);
   config->gdbIndex = args.hasFlag(OPT_gdb_index, OPT_no_gdb_index, false);
@@ -1075,17 +1136,15 @@ static void readConfigs(opt::InputArgList &args) {
   config->ignoreDataAddressEquality =
       args.hasArg(OPT_ignore_data_address_equality);
   config->ignoreFunctionAddressEquality =
-      args.hasFlag(OPT_ignore_function_address_equality,
-      OPT_no_ignore_function_address_equality, true);
+      args.hasArg(OPT_ignore_function_address_equality);
   config->init = args.getLastArgValue(OPT_init, "_init");
   config->ltoAAPipeline = args.getLastArgValue(OPT_lto_aa_pipeline);
   config->ltoCSProfileGenerate = args.hasArg(OPT_lto_cs_profile_generate);
   config->ltoCSProfileFile = args.getLastArgValue(OPT_lto_cs_profile_file);
+  config->ltoPGOWarnMismatch = args.hasFlag(OPT_lto_pgo_warn_mismatch,
+                                            OPT_no_lto_pgo_warn_mismatch, true);
   config->ltoDebugPassManager = args.hasArg(OPT_lto_debug_pass_manager);
   config->ltoEmitAsm = args.hasArg(OPT_lto_emit_asm);
-  config->ltoNewPassManager =
-      args.hasFlag(OPT_no_lto_legacy_pass_manager, OPT_lto_legacy_pass_manager,
-                   LLVM_ENABLE_NEW_PASS_MANAGER);
   config->ltoNewPmPasses = args.getLastArgValue(OPT_lto_newpm_passes);
   config->ltoWholeProgramVisibility =
       args.hasFlag(OPT_lto_whole_program_visibility,
@@ -1093,8 +1152,6 @@ static void readConfigs(opt::InputArgList &args) {
   config->ltoo = args::getInteger(args, OPT_lto_O, 2);
   config->ltoObjPath = args.getLastArgValue(OPT_lto_obj_path_eq);
   config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1);
-  config->ltoPseudoProbeForProfiling =
-      args.hasArg(OPT_lto_pseudo_probe_for_profiling);
   config->ltoSampleProfile = args.getLastArgValue(OPT_lto_sample_profile);
   config->ltoBasicBlockSections =
       args.getLastArgValue(OPT_lto_basic_block_sections);
@@ -1112,7 +1169,10 @@ static void readConfigs(opt::InputArgList &args) {
   config->nostdlib = args.hasArg(OPT_nostdlib);
   config->oFormatBinary = isOutputFormatBinary(args);
   config->omagic = args.hasFlag(OPT_omagic, OPT_no_omagic, false);
+  config->opaquePointers = args.hasFlag(
+      OPT_plugin_opt_opaque_pointers, OPT_plugin_opt_no_opaque_pointers, true);
   config->optRemarksFilename = args.getLastArgValue(OPT_opt_remarks_filename);
+  config->optStatsFilename = args.getLastArgValue(OPT_plugin_opt_stats_file);
 
   // Parse remarks hotness threshold. Valid value is either integer or 'auto'.
   if (auto *arg = args.getLastArg(OPT_opt_remarks_hotness_threshold)) {
@@ -1130,6 +1190,7 @@ static void readConfigs(opt::InputArgList &args) {
   config->optimize = args::getInteger(args, OPT_O, 1);
   config->orphanHandling = getOrphanHandling(args);
   config->outputFile = args.getLastArgValue(OPT_o);
+  config->packageMetadata = args.getLastArgValue(OPT_package_metadata);
 #ifdef __OpenBSD__
   config->pie = args.hasFlag(OPT_pie, OPT_no_pie,
       !args.hasArg(OPT_shared) && !args.hasArg(OPT_relocatable));
@@ -1143,9 +1204,24 @@ static void readConfigs(opt::InputArgList &args) {
   config->printArchiveStats = args.getLastArgValue(OPT_print_archive_stats);
   config->printSymbolOrder =
       args.getLastArgValue(OPT_print_symbol_order);
+  config->relax = args.hasFlag(OPT_relax, OPT_no_relax, true);
   config->rpath = getRpath(args);
   config->relocatable = args.hasArg(OPT_relocatable);
-  config->saveTemps = args.hasArg(OPT_save_temps);
+
+  if (args.hasArg(OPT_save_temps)) {
+    // --save-temps implies saving all temps.
+    for (const char *s : saveTempsValues)
+      config->saveTempsArgs.insert(s);
+  } else {
+    for (auto *arg : args.filtered(OPT_save_temps_eq)) {
+      StringRef s = arg->getValue();
+      if (llvm::is_contained(saveTempsValues, s))
+        config->saveTempsArgs.insert(s);
+      else
+        error("unknown --save-temps value: " + s);
+    }
+  }
+
   config->searchPaths = args::getStrings(args, OPT_library_path);
   config->sectionStartMap = getSectionStartMap(args);
   config->shared = args.hasArg(OPT_shared);
@@ -1162,6 +1238,9 @@ static void readConfigs(opt::InputArgList &args) {
       parseCachePruningPolicy(args.getLastArgValue(OPT_thinlto_cache_policy)),
       "--thinlto-cache-policy: invalid cache policy");
   config->thinLTOEmitImportsFiles = args.hasArg(OPT_thinlto_emit_imports_files);
+  config->thinLTOEmitIndexFiles = args.hasArg(OPT_thinlto_emit_index_files) ||
+                                  args.hasArg(OPT_thinlto_index_only) ||
+                                  args.hasArg(OPT_thinlto_index_only_eq);
   config->thinLTOIndexOnly = args.hasArg(OPT_thinlto_index_only) ||
                              args.hasArg(OPT_thinlto_index_only_eq);
   config->thinLTOIndexOnlyArg = args.getLastArgValue(OPT_thinlto_index_only_eq);
@@ -1169,15 +1248,23 @@ static void readConfigs(opt::InputArgList &args) {
       getOldNewOptions(args, OPT_thinlto_object_suffix_replace_eq);
   config->thinLTOPrefixReplace =
       getOldNewOptions(args, OPT_thinlto_prefix_replace_eq);
+  if (config->thinLTOEmitIndexFiles && !config->thinLTOIndexOnly) {
+    if (args.hasArg(OPT_thinlto_object_suffix_replace_eq))
+      error("--thinlto-object-suffix-replace is not supported with "
+            "--thinlto-emit-index-files");
+    else if (args.hasArg(OPT_thinlto_prefix_replace_eq))
+      error("--thinlto-prefix-replace is not supported with "
+            "--thinlto-emit-index-files");
+  }
   config->thinLTOModulesToCompile =
       args::getStrings(args, OPT_thinlto_single_module_eq);
-  config->timeTraceEnabled = args.hasArg(OPT_time_trace);
+  config->timeTraceEnabled = args.hasArg(OPT_time_trace_eq);
   config->timeTraceGranularity =
       args::getInteger(args, OPT_time_trace_granularity, 500);
   config->trace = args.hasArg(OPT_trace);
   config->undefined = args::getStrings(args, OPT_undefined);
   config->undefinedVersion =
-      args.hasFlag(OPT_undefined_version, OPT_no_undefined_version, true);
+      args.hasFlag(OPT_undefined_version, OPT_no_undefined_version, false);
   config->unique = args.hasArg(OPT_unique);
   config->useAndroidRelrTags = args.hasFlag(
       OPT_use_android_relr_tags, OPT_no_use_android_relr_tags, false);
@@ -1186,6 +1273,7 @@ static void readConfigs(opt::InputArgList &args) {
   config->warnCommon = args.hasFlag(OPT_warn_common, OPT_no_warn_common, false);
   config->warnSymbolOrdering =
       args.hasFlag(OPT_warn_symbol_ordering, OPT_no_warn_symbol_ordering, true);
+  config->whyExtract = args.getLastArgValue(OPT_why_extract);
   config->zCombreloc = getZFlag(args, "combreloc", "nocombreloc", true);
   config->zCopyreloc = getZFlag(args, "copyreloc", "nocopyreloc", true);
   config->zForceBti = hasZOption(args, "force-bti");
@@ -1221,7 +1309,7 @@ static void readConfigs(opt::InputArgList &args) {
   config->zText = getZFlag(args, "text", "notext", true);
   config->zWxneeded = hasZOption(args, "wxneeded");
   setUnresolvedSymbolPolicy(args);
-  config->Power10Stub = getP10StubOpt(args);
+  config->power10Stubs = args.getLastArgValue(OPT_power10_stubs_eq) != "no";
 
   if (opt::Arg *arg = args.getLastArg(OPT_eb, OPT_el)) {
     if (arg->getOption().matches(OPT_eb))
@@ -1248,6 +1336,23 @@ static void readConfigs(opt::InputArgList &args) {
       error(errPrefix + toString(pat.takeError()));
   }
 
+  auto reports = {std::make_pair("bti-report", &config->zBtiReport),
+                  std::make_pair("cet-report", &config->zCetReport)};
+  for (opt::Arg *arg : args.filtered(OPT_z)) {
+    std::pair<StringRef, StringRef> option =
+        StringRef(arg->getValue()).split('=');
+    for (auto reportArg : reports) {
+      if (option.first != reportArg.first)
+        continue;
+      if (!isValidReportString(option.second)) {
+        error(Twine("-z ") + reportArg.first + "= parameter " + option.second +
+              " is not recognized");
+        continue;
+      }
+      *reportArg.second = option.second;
+    }
+  }
+
   for (opt::Arg *arg : args.filtered(OPT_z)) {
     std::pair<StringRef, StringRef> option =
         StringRef(arg->getValue()).split('=');
@@ -1273,23 +1378,30 @@ static void readConfigs(opt::InputArgList &args) {
 
   // Parse LTO options.
   if (auto *arg = args.getLastArg(OPT_plugin_opt_mcpu_eq))
-    parseClangOption(saver.save("-mcpu=" + StringRef(arg->getValue())),
+    parseClangOption(saver().save("-mcpu=" + StringRef(arg->getValue())),
                      arg->getSpelling());
 
   for (opt::Arg *arg : args.filtered(OPT_plugin_opt_eq_minus))
     parseClangOption(std::string("-") + arg->getValue(), arg->getSpelling());
 
   // GCC collect2 passes -plugin-opt=path/to/lto-wrapper with an absolute or
-  // relative path. Just ignore. If not ended with "lto-wrapper", consider it an
+  // relative path. Just ignore. If not ended with "lto-wrapper" (or
+  // "lto-wrapper.exe" for GCC cross-compiled for Windows), consider it an
   // unsupported LLVMgold.so option and error.
-  for (opt::Arg *arg : args.filtered(OPT_plugin_opt_eq))
-    if (!StringRef(arg->getValue()).endswith("lto-wrapper"))
+  for (opt::Arg *arg : args.filtered(OPT_plugin_opt_eq)) {
+    StringRef v(arg->getValue());
+    if (!v.endswith("lto-wrapper") && !v.endswith("lto-wrapper.exe"))
       error(arg->getSpelling() + ": unknown plugin option '" + arg->getValue() +
             "'");
+  }
+
+  config->passPlugins = args::getStrings(args, OPT_load_pass_plugins);
 
   // Parse -mllvm options.
-  for (auto *arg : args.filtered(OPT_mllvm))
+  for (const auto *arg : args.filtered(OPT_mllvm)) {
     parseClangOption(arg->getValue(), arg->getSpelling());
+    config->mllvmOpts.emplace_back(arg->getValue());
+  }
 
   // --threads= takes a positive integer and provides the default value for
   // --thinlto-jobs=.
@@ -1302,8 +1414,9 @@ static void readConfigs(opt::InputArgList &args) {
     parallel::strategy = hardware_concurrency(threads);
     config->thinLTOJobs = v;
   }
-  if (auto *arg = args.getLastArg(OPT_thinlto_jobs))
+  if (auto *arg = args.getLastArg(OPT_thinlto_jobs_eq))
     config->thinLTOJobs = arg->getValue();
+  config->threadCount = parallel::strategy.compute_thread_count();
 
   if (config->ltoo > 3)
     error("invalid optimization level for LTO: " + Twine(config->ltoo));
@@ -1333,7 +1446,7 @@ static void readConfigs(opt::InputArgList &args) {
     config->emulation = s;
   }
 
-  // Parse -hash-style={sysv,gnu,both}.
+  // Parse --hash-style={sysv,gnu,both}.
   if (auto *arg = args.getLastArg(OPT_hash_style)) {
     StringRef s = arg->getValue();
     if (s == "sysv")
@@ -1343,7 +1456,7 @@ static void readConfigs(opt::InputArgList &args) {
     else if (s == "both")
       config->sysvHash = config->gnuHash = true;
     else
-      error("unknown -hash-style: " + s);
+      error("unknown --hash-style: " + s);
   }
 
   if (args.hasArg(OPT_print_map))
@@ -1357,14 +1470,19 @@ static void readConfigs(opt::InputArgList &args) {
 
   std::tie(config->buildId, config->buildIdVector) = getBuildId(args);
 
-  std::tie(config->androidPackDynRelocs, config->relrPackDynRelocs) =
-      getPackDynRelocs(args);
+  if (getZFlag(args, "pack-relative-relocs", "nopack-relative-relocs", false)) {
+    config->relrGlibc = true;
+    config->relrPackDynRelocs = true;
+  } else {
+    std::tie(config->androidPackDynRelocs, config->relrPackDynRelocs) =
+        getPackDynRelocs(args);
+  }
 
   if (auto *arg = args.getLastArg(OPT_symbol_ordering_file)){
     if (args.hasArg(OPT_call_graph_ordering_file))
       error("--symbol-ordering-file and --call-graph-order-file "
             "may not be used together");
-    if (Optional<MemoryBufferRef> buffer = readFile(arg->getValue())){
+    if (std::optional<MemoryBufferRef> buffer = readFile(arg->getValue())) {
       config->symbolOrderingFile = getSymbolOrderingFile(*buffer);
       // Also need to disable CallGraphProfileSort to prevent
       // LLD order symbols with CGProfile
@@ -1383,7 +1501,7 @@ static void readConfigs(opt::InputArgList &args) {
   if (auto *arg = args.getLastArg(OPT_retain_symbols_file)) {
     config->versionDefinitions[VER_NDX_LOCAL].nonLocalPatterns.push_back(
         {"*", /*isExternCpp=*/false, /*hasWildcard=*/true});
-    if (Optional<MemoryBufferRef> buffer = readFile(arg->getValue()))
+    if (std::optional<MemoryBufferRef> buffer = readFile(arg->getValue()))
       for (StringRef s : args::getLines(*buffer))
         config->versionDefinitions[VER_NDX_GLOBAL].nonLocalPatterns.push_back(
             {s, /*isExternCpp=*/false, /*hasWildcard=*/false});
@@ -1397,26 +1515,29 @@ static void readConfigs(opt::InputArgList &args) {
       error(arg->getSpelling() + ": " + toString(pat.takeError()));
   }
 
-  // When producing an executable, --dynamic-list specifies non-local defined
-  // symbols which are required to be exported. When producing a shared object,
-  // symbols not specified by --dynamic-list are non-preemptible.
-  config->symbolic =
-      config->bsymbolic == BsymbolicKind::All || args.hasArg(OPT_dynamic_list);
-  for (auto *arg : args.filtered(OPT_dynamic_list))
-    if (Optional<MemoryBufferRef> buffer = readFile(arg->getValue()))
-      readDynamicList(*buffer);
-
-  // --export-dynamic-symbol specifies additional --dynamic-list symbols if any
-  // other option expresses a symbolic intention: -no-pie, -pie, -Bsymbolic,
+  // For -no-pie and -pie, --export-dynamic-symbol specifies defined symbols
+  // which should be exported. For -shared, references to matched non-local
+  // STV_DEFAULT symbols are not bound to definitions within the shared object,
+  // even if other options express a symbolic intention: -Bsymbolic,
   // -Bsymbolic-functions (if STT_FUNC), --dynamic-list.
   for (auto *arg : args.filtered(OPT_export_dynamic_symbol))
     config->dynamicList.push_back(
         {arg->getValue(), /*isExternCpp=*/false,
          /*hasWildcard=*/hasWildcard(arg->getValue())});
 
+  // --export-dynamic-symbol-list specifies a list of --export-dynamic-symbol
+  // patterns. --dynamic-list is --export-dynamic-symbol-list plus -Bsymbolic
+  // like semantics.
+  config->symbolic =
+      config->bsymbolic == BsymbolicKind::All || args.hasArg(OPT_dynamic_list);
+  for (auto *arg :
+       args.filtered(OPT_dynamic_list, OPT_export_dynamic_symbol_list))
+    if (std::optional<MemoryBufferRef> buffer = readFile(arg->getValue()))
+      readDynamicList(*buffer);
+
   for (auto *arg : args.filtered(OPT_version_script))
-    if (Optional<std::string> path = searchScript(arg->getValue())) {
-      if (Optional<MemoryBufferRef> buffer = readFile(*path))
+    if (std::optional<std::string> path = searchScript(arg->getValue())) {
+      if (std::optional<MemoryBufferRef> buffer = readFile(*path))
         readVersionScript(*buffer);
     } else {
       error(Twine("cannot find version script ") + arg->getValue());
@@ -1469,7 +1590,8 @@ static void setConfigs(opt::InputArgList &args) {
   // enable the debug checks for all targets, but currently not all targets
   // have support for reading Elf_Rel addends, so we only enable for a subset.
 #ifndef NDEBUG
-  bool checkDynamicRelocsDefault = m == EM_ARM || m == EM_386 || m == EM_MIPS ||
+  bool checkDynamicRelocsDefault = m == EM_AARCH64 || m == EM_ARM ||
+                                   m == EM_386 || m == EM_MIPS ||
                                    m == EM_X86_64 || m == EM_RISCV;
 #else
   bool checkDynamicRelocsDefault = false;
@@ -1500,13 +1622,12 @@ static void setConfigs(opt::InputArgList &args) {
       args.hasFlag(OPT_execute_only, OPT_no_execute_only, config->executeOnly);
 }
 
-// Returns a value of "-format" option.
 static bool isFormatBinary(StringRef s) {
   if (s == "binary")
     return true;
   if (s == "elf" || s == "default")
     return false;
-  error("unknown -format value: " + s +
+  error("unknown --format value: " + s +
         " (supported formats: elf, default, binary)");
   return false;
 }
@@ -1518,27 +1639,30 @@ void LinkerDriver::createFiles(opt::InputArgList &args) {
 
   // Iterate over argv to process input files and positional arguments.
   InputFile::isInGroup = false;
+  bool hasInput = false;
   for (auto *arg : args) {
     switch (arg->getOption().getID()) {
     case OPT_library:
       addLibrary(arg->getValue());
+      hasInput = true;
       break;
     case OPT_INPUT:
       addFile(arg->getValue(), /*withLOption=*/false);
+      hasInput = true;
       break;
     case OPT_defsym: {
       StringRef from;
       StringRef to;
       std::tie(from, to) = StringRef(arg->getValue()).split('=');
       if (from.empty() || to.empty())
-        error("-defsym: syntax error: " + StringRef(arg->getValue()));
+        error("--defsym: syntax error: " + StringRef(arg->getValue()));
       else
-        readDefsym(from, MemoryBufferRef(to, "-defsym"));
+        readDefsym(from, MemoryBufferRef(to, "--defsym"));
       break;
     }
     case OPT_script:
-      if (Optional<std::string> path = searchScript(arg->getValue())) {
-        if (Optional<MemoryBufferRef> mb = readFile(*path))
+      if (std::optional<std::string> path = searchScript(arg->getValue())) {
+        if (std::optional<MemoryBufferRef> mb = readFile(*path))
           readLinkerScript(*mb);
         break;
       }
@@ -1568,8 +1692,8 @@ void LinkerDriver::createFiles(opt::InputArgList &args) {
       inWholeArchive = false;
       break;
     case OPT_just_symbols:
-      if (Optional<MemoryBufferRef> mb = readFile(arg->getValue())) {
-        files.push_back(createObjectFile(*mb));
+      if (std::optional<MemoryBufferRef> mb = readFile(arg->getValue())) {
+        files.push_back(createObjFile(*mb));
         files.back()->justSymbols = true;
       }
       break;
@@ -1613,7 +1737,7 @@ void LinkerDriver::createFiles(opt::InputArgList &args) {
     }
   }
 
-  if (files.empty() && errorCount() == 0)
+  if (files.empty() && !hasInput && errorCount() == 0)
     error("no input files");
 }
 
@@ -1639,8 +1763,10 @@ void LinkerDriver::inferMachineType() {
 static uint64_t getMaxPageSize(opt::InputArgList &args) {
   uint64_t val = args::getZOptionValue(args, OPT_z, "max-page-size",
                                        target->defaultMaxPageSize);
-  if (!isPowerOf2_64(val))
+  if (!isPowerOf2_64(val)) {
     error("max-page-size: value isn't a power of 2");
+    return target->defaultMaxPageSize;
+  }
   if (config->nmagic || config->omagic) {
     if (val != target->defaultMaxPageSize)
       warn("-z max-page-size set, but paging disabled by omagic or nmagic");
@@ -1654,8 +1780,10 @@ static uint64_t getMaxPageSize(opt::InputArgList &args) {
 static uint64_t getCommonPageSize(opt::InputArgList &args) {
   uint64_t val = args::getZOptionValue(args, OPT_z, "common-page-size",
                                        target->defaultCommonPageSize);
-  if (!isPowerOf2_64(val))
+  if (!isPowerOf2_64(val)) {
     error("common-page-size: value isn't a power of 2");
+    return target->defaultCommonPageSize;
+  }
   if (config->nmagic || config->omagic) {
     if (val != target->defaultCommonPageSize)
       warn("-z common-page-size set, but paging disabled by omagic or nmagic");
@@ -1677,22 +1805,22 @@ static uint64_t getRealMaxPageSize(opt::InputArgList &args) {
   return val;
 }
 
-// Parses -image-base option.
-static Optional<uint64_t> getImageBase(opt::InputArgList &args) {
+// Parses --image-base option.
+static std::optional<uint64_t> getImageBase(opt::InputArgList &args) {
   // Because we are using "Config->maxPageSize" here, this function has to be
   // called after the variable is initialized.
   auto *arg = args.getLastArg(OPT_image_base);
   if (!arg)
-    return None;
+    return std::nullopt;
 
   StringRef s = arg->getValue();
   uint64_t v;
   if (!to_integer(s, v)) {
-    error("-image-base: number expected, but got " + s);
+    error("--image-base: number expected, but got " + s);
     return 0;
   }
   if ((v % config->maxPageSize) != 0)
-    warn("-image-base: address isn't multiple of page size: " + s);
+    warn("--image-base: address isn't multiple of page size: " + s);
   return v;
 }
 
@@ -1714,8 +1842,8 @@ static DenseSet<StringRef> getExcludeLibs(opt::InputArgList &args) {
   return ret;
 }
 
-// Handles the -exclude-libs option. If a static library file is specified
-// by the -exclude-libs option, all public symbols from the archive become
+// Handles the --exclude-libs option. If a static library file is specified
+// by the --exclude-libs option, all public symbols from the archive become
 // private unless otherwise specified by version scripts or something.
 // A special library name "ALL" means all archive files.
 //
@@ -1725,28 +1853,35 @@ static void excludeLibs(opt::InputArgList &args) {
   bool all = libs.count("ALL");
 
   auto visit = [&](InputFile *file) {
-    if (!file->archiveName.empty())
-      if (all || libs.count(path::filename(file->archiveName)))
-        for (Symbol *sym : file->getSymbols())
-          if (!sym->isUndefined() && !sym->isLocal() && sym->file == file)
-            sym->versionId = VER_NDX_LOCAL;
+    if (file->archiveName.empty() ||
+        !(all || libs.count(path::filename(file->archiveName))))
+      return;
+    ArrayRef<Symbol *> symbols = file->getSymbols();
+    if (isa<ELFFileBase>(file))
+      symbols = cast<ELFFileBase>(file)->getGlobalSymbols();
+    for (Symbol *sym : symbols)
+      if (!sym->isUndefined() && sym->file == file)
+        sym->versionId = VER_NDX_LOCAL;
   };
 
-  for (InputFile *file : objectFiles)
+  for (ELFFileBase *file : ctx.objectFiles)
     visit(file);
 
-  for (BitcodeFile *file : bitcodeFiles)
+  for (BitcodeFile *file : ctx.bitcodeFiles)
     visit(file);
 }
 
 // Force Sym to be entered in the output.
-static void handleUndefined(Symbol *sym) {
+static void handleUndefined(Symbol *sym, const char *option) {
   // Since a symbol may not be used inside the program, LTO may
   // eliminate it. Mark the symbol as "used" to prevent it.
   sym->isUsedInRegularObj = true;
 
-  if (sym->isLazy())
-    sym->fetch();
+  if (!sym->isLazy())
+    return;
+  sym->extract();
+  if (!config->whyExtract.empty())
+    ctx.whyExtractRecords.emplace_back(option, sym->file, *sym);
 }
 
 // As an extension to GNU linkers, lld supports a variant of `-u`
@@ -1759,32 +1894,95 @@ static void handleUndefinedGlob(StringRef arg) {
     return;
   }
 
-  std::vector<Symbol *> syms;
-  for (Symbol *sym : symtab->symbols()) {
-    // Calling Sym->fetch() from here is not safe because it may
-    // add new symbols to the symbol table, invalidating the
-    // current iterator. So we just keep a note.
-    if (pat->match(sym->getName()))
+  // Calling sym->extract() in the loop is not safe because it may add new
+  // symbols to the symbol table, invalidating the current iterator.
+  SmallVector<Symbol *, 0> syms;
+  for (Symbol *sym : symtab.getSymbols())
+    if (!sym->isPlaceholder() && pat->match(sym->getName()))
       syms.push_back(sym);
-  }
 
   for (Symbol *sym : syms)
-    handleUndefined(sym);
+    handleUndefined(sym, "--undefined-glob");
 }
 
 static void handleLibcall(StringRef name) {
-  Symbol *sym = symtab->find(name);
+  Symbol *sym = symtab.find(name);
   if (!sym || !sym->isLazy())
     return;
 
   MemoryBufferRef mb;
-  if (auto *lo = dyn_cast<LazyObject>(sym))
-    mb = lo->file->mb;
-  else
-    mb = cast<LazyArchive>(sym)->getMemberBuffer();
+  mb = cast<LazyObject>(sym)->file->mb;
 
   if (isBitcode(mb))
-    sym->fetch();
+    sym->extract();
+}
+
+static void writeArchiveStats() {
+  if (config->printArchiveStats.empty())
+    return;
+
+  std::error_code ec;
+  raw_fd_ostream os(config->printArchiveStats, ec, sys::fs::OF_None);
+  if (ec) {
+    error("--print-archive-stats=: cannot open " + config->printArchiveStats +
+          ": " + ec.message());
+    return;
+  }
+
+  os << "members\textracted\tarchive\n";
+
+  SmallVector<StringRef, 0> archives;
+  DenseMap<CachedHashStringRef, unsigned> all, extracted;
+  for (ELFFileBase *file : ctx.objectFiles)
+    if (file->archiveName.size())
+      ++extracted[CachedHashStringRef(file->archiveName)];
+  for (BitcodeFile *file : ctx.bitcodeFiles)
+    if (file->archiveName.size())
+      ++extracted[CachedHashStringRef(file->archiveName)];
+  for (std::pair<StringRef, unsigned> f : ctx.driver.archiveFiles) {
+    unsigned &v = extracted[CachedHashString(f.first)];
+    os << f.second << '\t' << v << '\t' << f.first << '\n';
+    // If the archive occurs multiple times, other instances have a count of 0.
+    v = 0;
+  }
+}
+
+static void writeWhyExtract() {
+  if (config->whyExtract.empty())
+    return;
+
+  std::error_code ec;
+  raw_fd_ostream os(config->whyExtract, ec, sys::fs::OF_None);
+  if (ec) {
+    error("cannot open --why-extract= file " + config->whyExtract + ": " +
+          ec.message());
+    return;
+  }
+
+  os << "reference\textracted\tsymbol\n";
+  for (auto &entry : ctx.whyExtractRecords) {
+    os << std::get<0>(entry) << '\t' << toString(std::get<1>(entry)) << '\t'
+       << toString(std::get<2>(entry)) << '\n';
+  }
+}
+
+static void reportBackrefs() {
+  for (auto &ref : ctx.backwardReferences) {
+    const Symbol &sym = *ref.first;
+    std::string to = toString(ref.second.second);
+    // Some libraries have known problems and can cause noise. Filter them out
+    // with --warn-backrefs-exclude=. The value may look like (for --start-lib)
+    // *.o or (archive member) *.a(*.o).
+    bool exclude = false;
+    for (const llvm::GlobPattern &pat : config->warnBackrefsExclude)
+      if (pat.match(to)) {
+        exclude = true;
+        break;
+      }
+    if (!exclude)
+      warn("backward reference detected: " + sym.getName() + " in " +
+           toString(ref.second.first) + " refers to " + to);
+  }
 }
 
 // Handle --dependency-file=<path>. If that option is given, lld creates a
@@ -1862,34 +2060,39 @@ static void writeDependencyFile() {
 // symbols of type CommonSymbol.
 static void replaceCommonSymbols() {
   llvm::TimeTraceScope timeScope("Replace common symbols");
-  for (Symbol *sym : symtab->symbols()) {
-    auto *s = dyn_cast<CommonSymbol>(sym);
-    if (!s)
+  for (ELFFileBase *file : ctx.objectFiles) {
+    if (!file->hasCommonSyms)
       continue;
+    for (Symbol *sym : file->getGlobalSymbols()) {
+      auto *s = dyn_cast<CommonSymbol>(sym);
+      if (!s)
+        continue;
 
-    auto *bss = make<BssSection>("COMMON", s->size, s->alignment);
-    bss->file = s->file;
-    bss->markDead();
-    inputSections.push_back(bss);
-    s->replace(Defined{s->file, s->getName(), s->binding, s->stOther, s->type,
-                       /*value=*/0, s->size, bss});
+      auto *bss = make<BssSection>("COMMON", s->size, s->alignment);
+      bss->file = s->file;
+      ctx.inputSections.push_back(bss);
+      Defined(s->file, StringRef(), s->binding, s->stOther, s->type,
+              /*value=*/0, s->size, bss)
+          .overwrite(*s);
+    }
   }
 }
 
-// If all references to a DSO happen to be weak, the DSO is not added
-// to DT_NEEDED. If that happens, we need to eliminate shared symbols
-// created from the DSO. Otherwise, they become dangling references
-// that point to a non-existent DSO.
-static void demoteSharedSymbols() {
-  llvm::TimeTraceScope timeScope("Demote shared symbols");
-  for (Symbol *sym : symtab->symbols()) {
+// If all references to a DSO happen to be weak, the DSO is not added to
+// DT_NEEDED. If that happens, replace ShardSymbol with Undefined to avoid
+// dangling references to an unneeded DSO. Use a weak binding to avoid
+// --no-allow-shlib-undefined diagnostics. Similarly, demote lazy symbols.
+static void demoteSharedAndLazySymbols() {
+  llvm::TimeTraceScope timeScope("Demote shared and lazy symbols");
+  for (Symbol *sym : symtab.getSymbols()) {
     auto *s = dyn_cast<SharedSymbol>(sym);
-    if (!s || s->getFile().isNeeded)
+    if (!(s && !cast<SharedFile>(s->file)->isNeeded) && !sym->isLazy())
       continue;
 
-    bool used = s->used;
-    s->replace(Undefined{nullptr, s->getName(), STB_WEAK, s->stOther, s->type});
-    s->used = used;
+    uint8_t binding = sym->isLazy() ? sym->binding : uint8_t(STB_WEAK);
+    Undefined(nullptr, sym->getName(), binding, sym->stOther, sym->type)
+        .overwrite(*sym);
+    sym->versionId = VER_NDX_GLOBAL;
   }
 }
 
@@ -1911,7 +2114,7 @@ template <class ELFT>
 static void findKeepUniqueSections(opt::InputArgList &args) {
   for (auto *arg : args.filtered(OPT_keep_unique)) {
     StringRef name = arg->getValue();
-    auto *d = dyn_cast_or_null<Defined>(symtab->find(name));
+    auto *d = dyn_cast_or_null<Defined>(symtab.find(name));
     if (!d || !d->section) {
       warn("could not find symbol " + name + " to keep unique");
       continue;
@@ -1926,13 +2129,13 @@ static void findKeepUniqueSections(opt::InputArgList &args) {
 
   // Symbols in the dynsym could be address-significant in other executables
   // or DSOs, so we conservatively mark them as address-significant.
-  for (Symbol *sym : symtab->symbols())
+  for (Symbol *sym : symtab.getSymbols())
     if (sym->includeInDynsym())
       markAddrsig(sym);
 
   // Visit the address-significance table in each object file and mark each
   // referenced symbol as address-significant.
-  for (InputFile *f : objectFiles) {
+  for (InputFile *f : ctx.objectFiles) {
     auto *obj = cast<ObjFile<ELFT>>(f);
     ArrayRef<Symbol *> syms = obj->getSymbols();
     if (obj->addrsigSec) {
@@ -1964,14 +2167,15 @@ template <typename ELFT>
 static void readSymbolPartitionSection(InputSectionBase *s) {
   // Read the relocation that refers to the partition's entry point symbol.
   Symbol *sym;
-  if (s->areRelocsRela)
-    sym = &s->getFile<ELFT>()->getRelocTargetSym(s->template relas<ELFT>()[0]);
+  const RelsOrRelas<ELFT> rels = s->template relsOrRelas<ELFT>();
+  if (rels.areRelocsRel())
+    sym = &s->getFile<ELFT>()->getRelocTargetSym(rels.rels[0]);
   else
-    sym = &s->getFile<ELFT>()->getRelocTargetSym(s->template rels<ELFT>()[0]);
+    sym = &s->getFile<ELFT>()->getRelocTargetSym(rels.relas[0]);
   if (!isa<Defined>(sym) || !sym->includeInDynsym())
     return;
 
-  StringRef partName = reinterpret_cast<const char *>(s->data().data());
+  StringRef partName = reinterpret_cast<const char *>(s->content().data());
   for (Partition &part : partitions) {
     if (part.name == partName) {
       sym->partition = part.getNumber();
@@ -2006,16 +2210,31 @@ static void readSymbolPartitionSection(InputSectionBase *s) {
   sym->partition = newPart.getNumber();
 }
 
-static Symbol *addUndefined(StringRef name) {
-  return symtab->addSymbol(
-      Undefined{nullptr, name, STB_GLOBAL, STV_DEFAULT, 0});
-}
-
 static Symbol *addUnusedUndefined(StringRef name,
                                   uint8_t binding = STB_GLOBAL) {
-  Undefined sym{nullptr, name, binding, STV_DEFAULT, 0};
-  sym.isUsedInRegularObj = false;
-  return symtab->addSymbol(sym);
+  return symtab.addSymbol(Undefined{nullptr, name, binding, STV_DEFAULT, 0});
+}
+
+static void markBuffersAsDontNeed(bool skipLinkedOutput) {
+  // With --thinlto-index-only, all buffers are nearly unused from now on
+  // (except symbol/section names used by infrequent passes). Mark input file
+  // buffers as MADV_DONTNEED so that these pages can be reused by the expensive
+  // thin link, saving memory.
+  if (skipLinkedOutput) {
+    for (MemoryBuffer &mb : llvm::make_pointee_range(ctx.memoryBuffers))
+      mb.dontNeedIfMmap();
+    return;
+  }
+
+  // Otherwise, just mark MemoryBuffers backing BitcodeFiles.
+  DenseSet<const char *> bufs;
+  for (BitcodeFile *file : ctx.bitcodeFiles)
+    bufs.insert(file->mb.getBufferStart());
+  for (BitcodeFile *file : ctx.lazyBitcodeFiles)
+    bufs.insert(file->mb.getBufferStart());
+  for (MemoryBuffer &mb : llvm::make_pointee_range(ctx.memoryBuffers))
+    if (bufs.count(mb.getBufferStart()))
+      mb.dontNeedIfMmap();
 }
 
 // This function is where all the optimizations of link-time
@@ -2025,13 +2244,17 @@ static Symbol *addUnusedUndefined(StringRef name,
 // using LLVM functions and replaces bitcode symbols with the results.
 // Because all bitcode files that the program consists of are passed to
 // the compiler at once, it can do a whole-program optimization.
-template <class ELFT> void LinkerDriver::compileBitcodeFiles() {
+template <class ELFT>
+void LinkerDriver::compileBitcodeFiles(bool skipLinkedOutput) {
   llvm::TimeTraceScope timeScope("LTO");
   // Compile bitcode files and replace bitcode symbols.
   lto.reset(new BitcodeCompiler);
-  for (BitcodeFile *file : bitcodeFiles)
+  for (BitcodeFile *file : ctx.bitcodeFiles)
     lto->add(*file);
 
+  if (!ctx.bitcodeFiles.empty())
+    markBuffersAsDontNeed(skipLinkedOutput);
+
   for (InputFile *file : lto->compile()) {
     auto *obj = cast<ObjFile<ELFT>>(file);
     obj->parse(/*ignoreComdats=*/true);
@@ -2039,26 +2262,27 @@ template <class ELFT> void LinkerDriver::compileBitcodeFiles() {
     // Parse '@' in symbol names for non-relocatable output.
     if (!config->relocatable)
       for (Symbol *sym : obj->getGlobalSymbols())
-        sym->parseSymbolVersion();
-    objectFiles.push_back(file);
+        if (sym->hasVersionSuffix)
+          sym->parseSymbolVersion();
+    ctx.objectFiles.push_back(obj);
   }
 }
 
 // The --wrap option is a feature to rename symbols so that you can write
-// wrappers for existing functions. If you pass `-wrap=foo`, all
+// wrappers for existing functions. If you pass `--wrap=foo`, all
 // occurrences of symbol `foo` are resolved to `__wrap_foo` (so, you are
 // expected to write `__wrap_foo` function as a wrapper). The original
 // symbol becomes accessible as `__real_foo`, so you can call that from your
 // wrapper.
 //
-// This data structure is instantiated for each -wrap option.
+// This data structure is instantiated for each --wrap option.
 struct WrappedSymbol {
   Symbol *sym;
   Symbol *real;
   Symbol *wrap;
 };
 
-// Handles -wrap option.
+// Handles --wrap option.
 //
 // This function instantiates wrapper symbols. At this point, they seem
 // like they are not being used at all, so we explicitly set some flags so
@@ -2072,35 +2296,93 @@ static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) {
     if (!seen.insert(name).second)
       continue;
 
-    Symbol *sym = symtab->find(name);
+    Symbol *sym = symtab.find(name);
     if (!sym)
       continue;
 
-    Symbol *real = addUnusedUndefined(saver.save("__real_" + name));
     Symbol *wrap =
-        addUnusedUndefined(saver.save("__wrap_" + name), sym->binding);
+        addUnusedUndefined(saver().save("__wrap_" + name), sym->binding);
+
+    // If __real_ is referenced, pull in the symbol if it is lazy. Do this after
+    // processing __wrap_ as that may have referenced __real_.
+    StringRef realName = saver().save("__real_" + name);
+    if (symtab.find(realName))
+      addUnusedUndefined(name, sym->binding);
+
+    Symbol *real = addUnusedUndefined(realName);
     v.push_back({sym, real, wrap});
 
     // We want to tell LTO not to inline symbols to be overwritten
     // because LTO doesn't know the final symbol contents after renaming.
-    real->canInline = false;
-    sym->canInline = false;
-
-    // Tell LTO not to eliminate these symbols.
-    sym->isUsedInRegularObj = true;
-    // If sym is referenced in any object file, bitcode file or shared object,
-    // retain wrap which is the redirection target of sym. If the object file
-    // defining sym has sym references, we cannot easily distinguish the case
-    // from cases where sym is not referenced. Retain wrap because we choose to
-    // wrap sym references regardless of whether sym is defined
+    real->scriptDefined = true;
+    sym->scriptDefined = true;
+
+    // If a symbol is referenced in any object file, bitcode file or shared
+    // object, mark its redirection target (foo for __real_foo and __wrap_foo
+    // for foo) as referenced after redirection, which will be used to tell LTO
+    // to not eliminate the redirection target. If the object file defining the
+    // symbol also references it, we cannot easily distinguish the case from
+    // cases where the symbol is not referenced. Retain the redirection target
+    // in this case because we choose to wrap symbol references regardless of
+    // whether the symbol is defined
     // (https://sourceware.org/bugzilla/show_bug.cgi?id=26358).
+    if (real->referenced || real->isDefined())
+      sym->referencedAfterWrap = true;
     if (sym->referenced || sym->isDefined())
-      wrap->isUsedInRegularObj = true;
+      wrap->referencedAfterWrap = true;
   }
   return v;
 }
 
-// Do renaming for -wrap and foo@v1 by updating pointers to symbols.
+static void combineVersionedSymbol(Symbol &sym,
+                                   DenseMap<Symbol *, Symbol *> &map) {
+  const char *suffix1 = sym.getVersionSuffix();
+  if (suffix1[0] != '@' || suffix1[1] == '@')
+    return;
+
+  // Check the existing symbol foo. We have two special cases to handle:
+  //
+  // * There is a definition of foo@v1 and foo@@v1.
+  // * There is a definition of foo@v1 and foo.
+  Defined *sym2 = dyn_cast_or_null<Defined>(symtab.find(sym.getName()));
+  if (!sym2)
+    return;
+  const char *suffix2 = sym2->getVersionSuffix();
+  if (suffix2[0] == '@' && suffix2[1] == '@' &&
+      strcmp(suffix1 + 1, suffix2 + 2) == 0) {
+    // foo@v1 and foo@@v1 should be merged, so redirect foo@v1 to foo@@v1.
+    map.try_emplace(&sym, sym2);
+    // If both foo@v1 and foo@@v1 are defined and non-weak, report a
+    // duplicate definition error.
+    if (sym.isDefined()) {
+      sym2->checkDuplicate(cast<Defined>(sym));
+      sym2->resolve(cast<Defined>(sym));
+    } else if (sym.isUndefined()) {
+      sym2->resolve(cast<Undefined>(sym));
+    } else {
+      sym2->resolve(cast<SharedSymbol>(sym));
+    }
+    // Eliminate foo@v1 from the symbol table.
+    sym.symbolKind = Symbol::PlaceholderKind;
+    sym.isUsedInRegularObj = false;
+  } else if (auto *sym1 = dyn_cast<Defined>(&sym)) {
+    if (sym2->versionId > VER_NDX_GLOBAL
+            ? config->versionDefinitions[sym2->versionId].name == suffix1 + 1
+            : sym1->section == sym2->section && sym1->value == sym2->value) {
+      // Due to an assembler design flaw, if foo is defined, .symver foo,
+      // foo@v1 defines both foo and foo@v1. Unless foo is bound to a
+      // different version, GNU ld makes foo@v1 canonical and eliminates
+      // foo. Emulate its behavior, otherwise we would have foo or foo@@v1
+      // beside foo@v1. foo@v1 and foo combining does not apply if they are
+      // not defined in the same place.
+      map.try_emplace(sym2, &sym);
+      sym2->symbolKind = Symbol::PlaceholderKind;
+      sym2->isUsedInRegularObj = false;
+    }
+  }
+}
+
+// Do renaming for --wrap and foo@v1 by updating pointers to symbols.
 //
 // When this function is executed, only InputFiles and symbol table
 // contain pointers to symbol objects. We visit them to replace pointers,
@@ -2112,63 +2394,41 @@ static void redirectSymbols(ArrayRef<WrappedSymbol> wrapped) {
     map[w.sym] = w.wrap;
     map[w.real] = w.sym;
   }
-  for (Symbol *sym : symtab->symbols()) {
-    // Enumerate symbols with a non-default version (foo@v1).
-    StringRef name = sym->getName();
-    const char *suffix1 = sym->getVersionSuffix();
-    if (suffix1[0] != '@' || suffix1[1] == '@')
-      continue;
 
-    // Check the existing symbol foo. We have two special cases to handle:
-    //
-    // * There is a definition of foo@v1 and foo@@v1.
-    // * There is a definition of foo@v1 and foo.
-    Defined *sym2 = dyn_cast_or_null<Defined>(symtab->find(name));
-    if (!sym2)
-      continue;
-    const char *suffix2 = sym2->getVersionSuffix();
-    if (suffix2[0] == '@' && suffix2[1] == '@' &&
-        strcmp(suffix1 + 1, suffix2 + 2) == 0) {
-      // foo@v1 and foo@@v1 should be merged, so redirect foo@v1 to foo@@v1.
-      map.try_emplace(sym, sym2);
-      // If both foo@v1 and foo@@v1 are defined and non-weak, report a duplicate
-      // definition error.
-      sym2->resolve(*sym);
-      // Eliminate foo@v1 from the symbol table.
-      sym->symbolKind = Symbol::PlaceholderKind;
-    } else if (auto *sym1 = dyn_cast<Defined>(sym)) {
-      if (sym2->versionId > VER_NDX_GLOBAL
-              ? config->versionDefinitions[sym2->versionId].name == suffix1 + 1
-              : sym1->section == sym2->section && sym1->value == sym2->value) {
-        // Due to an assembler design flaw, if foo is defined, .symver foo,
-        // foo@v1 defines both foo and foo@v1. Unless foo is bound to a
-        // different version, GNU ld makes foo@v1 canonical and elimiates foo.
-        // Emulate its behavior, otherwise we would have foo or foo@@v1 beside
-        // foo@v1. foo@v1 and foo combining does not apply if they are not
-        // defined in the same place.
-        map.try_emplace(sym2, sym);
-        sym2->symbolKind = Symbol::PlaceholderKind;
-      }
-    }
-  }
+  // If there are version definitions (versionDefinitions.size() > 2), enumerate
+  // symbols with a non-default version (foo@v1) and check whether it should be
+  // combined with foo or foo@@v1.
+  if (config->versionDefinitions.size() > 2)
+    for (Symbol *sym : symtab.getSymbols())
+      if (sym->hasVersionSuffix)
+        combineVersionedSymbol(*sym, map);
 
   if (map.empty())
     return;
 
   // Update pointers in input files.
-  parallelForEach(objectFiles, [&](InputFile *file) {
-    MutableArrayRef<Symbol *> syms = file->getMutableSymbols();
-    for (size_t i = 0, e = syms.size(); i != e; ++i)
-      if (Symbol *s = map.lookup(syms[i]))
-        syms[i] = s;
+  parallelForEach(ctx.objectFiles, [&](ELFFileBase *file) {
+    for (Symbol *&sym : file->getMutableGlobalSymbols())
+      if (Symbol *s = map.lookup(sym))
+        sym = s;
   });
 
   // Update pointers in the symbol table.
   for (const WrappedSymbol &w : wrapped)
-    symtab->wrap(w.sym, w.real, w.wrap);
+    symtab.wrap(w.sym, w.real, w.wrap);
+}
+
+static void checkAndReportMissingFeature(StringRef config, uint32_t features,
+                                         uint32_t mask, const Twine &report) {
+  if (!(features & mask)) {
+    if (config == "error")
+      error(report);
+    else if (config == "warning")
+      warn(report);
+  }
 }
 
-// To enable CET (x86's hardware-assited control flow enforcement), each
+// To enable CET (x86's hardware-assisted control flow enforcement), each
 // source file must be compiled with -fcf-protection. Object files compiled
 // with the flag contain feature flags indicating that they are compatible
 // with CET. We enable the feature only when all object files are compatible
@@ -2176,22 +2436,40 @@ static void redirectSymbols(ArrayRef<WrappedSymbol> wrapped) {
 //
 // This is also the case with AARCH64's BTI and PAC which use the similar
 // GNU_PROPERTY_AARCH64_FEATURE_1_AND mechanism.
-template <class ELFT> static uint32_t getAndFeatures() {
+static uint32_t getAndFeatures() {
   if (config->emachine != EM_386 && config->emachine != EM_X86_64 &&
       config->emachine != EM_AARCH64)
     return 0;
 
   uint32_t ret = -1;
-  for (InputFile *f : objectFiles) {
-    uint32_t features = cast<ObjFile<ELFT>>(f)->andFeatures;
+  for (ELFFileBase *f : ctx.objectFiles) {
+    uint32_t features = f->andFeatures;
+
+    checkAndReportMissingFeature(
+        config->zBtiReport, features, GNU_PROPERTY_AARCH64_FEATURE_1_BTI,
+        toString(f) + ": -z bti-report: file does not have "
+                      "GNU_PROPERTY_AARCH64_FEATURE_1_BTI property");
+
+    checkAndReportMissingFeature(
+        config->zCetReport, features, GNU_PROPERTY_X86_FEATURE_1_IBT,
+        toString(f) + ": -z cet-report: file does not have "
+                      "GNU_PROPERTY_X86_FEATURE_1_IBT property");
+
+    checkAndReportMissingFeature(
+        config->zCetReport, features, GNU_PROPERTY_X86_FEATURE_1_SHSTK,
+        toString(f) + ": -z cet-report: file does not have "
+                      "GNU_PROPERTY_X86_FEATURE_1_SHSTK property");
+
     if (config->zForceBti && !(features & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)) {
-      warn(toString(f) + ": -z force-bti: file does not have "
-                         "GNU_PROPERTY_AARCH64_FEATURE_1_BTI property");
       features |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
+      if (config->zBtiReport == "none")
+        warn(toString(f) + ": -z force-bti: file does not have "
+                           "GNU_PROPERTY_AARCH64_FEATURE_1_BTI property");
     } else if (config->zForceIbt &&
                !(features & GNU_PROPERTY_X86_FEATURE_1_IBT)) {
-      warn(toString(f) + ": -z force-ibt: file does not have "
-                         "GNU_PROPERTY_X86_FEATURE_1_IBT property");
+      if (config->zCetReport == "none")
+        warn(toString(f) + ": -z force-ibt: file does not have "
+                           "GNU_PROPERTY_X86_FEATURE_1_IBT property");
       features |= GNU_PROPERTY_X86_FEATURE_1_IBT;
     }
     if (config->zPacPlt && !(features & GNU_PROPERTY_AARCH64_FEATURE_1_PAC)) {
@@ -2209,11 +2487,49 @@ template <class ELFT> static uint32_t getAndFeatures() {
   return ret;
 }
 
+static void initSectionsAndLocalSyms(ELFFileBase *file, bool ignoreComdats) {
+  switch (file->ekind) {
+  case ELF32LEKind:
+    cast<ObjFile<ELF32LE>>(file)->initSectionsAndLocalSyms(ignoreComdats);
+    break;
+  case ELF32BEKind:
+    cast<ObjFile<ELF32BE>>(file)->initSectionsAndLocalSyms(ignoreComdats);
+    break;
+  case ELF64LEKind:
+    cast<ObjFile<ELF64LE>>(file)->initSectionsAndLocalSyms(ignoreComdats);
+    break;
+  case ELF64BEKind:
+    cast<ObjFile<ELF64BE>>(file)->initSectionsAndLocalSyms(ignoreComdats);
+    break;
+  default:
+    llvm_unreachable("");
+  }
+}
+
+static void postParseObjectFile(ELFFileBase *file) {
+  switch (file->ekind) {
+  case ELF32LEKind:
+    cast<ObjFile<ELF32LE>>(file)->postParse();
+    break;
+  case ELF32BEKind:
+    cast<ObjFile<ELF32BE>>(file)->postParse();
+    break;
+  case ELF64LEKind:
+    cast<ObjFile<ELF64LE>>(file)->postParse();
+    break;
+  case ELF64BEKind:
+    cast<ObjFile<ELF64BE>>(file)->postParse();
+    break;
+  default:
+    llvm_unreachable("");
+  }
+}
+
 // Do actual linking. Note that when this function is called,
 // all linker scripts have already been parsed.
-template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
+void LinkerDriver::link(opt::InputArgList &args) {
   llvm::TimeTraceScope timeScope("Link", StringRef("LinkerDriver::Link"));
-  // If a -hash-style option was not given, set to a default value,
+  // If a --hash-style option was not given, set to a default value,
   // which varies depending on the target.
   if (!args.hasArg(OPT_hash_style)) {
     if (config->emachine == EM_MIPS)
@@ -2236,6 +2552,9 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
             e.message());
     if (auto e = tryCreateFile(config->mapFile))
       error("cannot open map file " + config->mapFile + ": " + e.message());
+    if (auto e = tryCreateFile(config->whyExtract))
+      error("cannot open --why-extract= file " + config->whyExtract + ": " +
+            e.message());
   }
   if (errorCount())
     return;
@@ -2250,10 +2569,10 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
 
   // Handle --trace-symbol.
   for (auto *arg : args.filtered(OPT_trace_symbol))
-    symtab->insert(arg->getValue())->traced = true;
+    symtab.insert(arg->getValue())->traced = true;
 
   // Handle -u/--undefined before input files. If both a.a and b.so define foo,
-  // -u foo a.a b.so will fetch a.a.
+  // -u foo a.a b.so will extract a.a.
   for (StringRef name : config->undefined)
     addUnusedUndefined(name)->referenced = true;
 
@@ -2276,30 +2595,33 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
   // We also need one if any shared libraries are used and for pie executables
   // (probably because the dynamic linker needs it).
   config->hasDynSymTab =
-      !sharedFiles.empty() || config->isPic || config->exportDynamic;
+      !ctx.sharedFiles.empty() || config->isPic || config->exportDynamic;
 
   // Some symbols (such as __ehdr_start) are defined lazily only when there
   // are undefined symbols for them, so we add these to trigger that logic.
-  for (StringRef name : script->referencedSymbols)
-    addUndefined(name);
+  for (StringRef name : script->referencedSymbols) {
+    Symbol *sym = addUnusedUndefined(name);
+    sym->isUsedInRegularObj = true;
+    sym->referenced = true;
+  }
 
   // Prevent LTO from removing any definition referenced by -u.
   for (StringRef name : config->undefined)
-    if (Defined *sym = dyn_cast_or_null<Defined>(symtab->find(name)))
+    if (Defined *sym = dyn_cast_or_null<Defined>(symtab.find(name)))
       sym->isUsedInRegularObj = true;
 
   // If an entry symbol is in a static archive, pull out that file now.
-  if (Symbol *sym = symtab->find(config->entry))
-    handleUndefined(sym);
+  if (Symbol *sym = symtab.find(config->entry))
+    handleUndefined(sym, "--entry");
 
   // Handle the `--undefined-glob <pattern>` options.
   for (StringRef pat : args::getStrings(args, OPT_undefined_glob))
     handleUndefinedGlob(pat);
 
   // Mark -init and -fini symbols so that the LTO doesn't eliminate them.
-  if (Symbol *sym = dyn_cast_or_null<Defined>(symtab->find(config->init)))
+  if (Symbol *sym = dyn_cast_or_null<Defined>(symtab.find(config->init)))
     sym->isUsedInRegularObj = true;
-  if (Symbol *sym = dyn_cast_or_null<Defined>(symtab->find(config->fini)))
+  if (Symbol *sym = dyn_cast_or_null<Defined>(symtab.find(config->fini)))
     sym->isUsedInRegularObj = true;
 
   // If any of our inputs are bitcode files, the LTO code generator may create
@@ -2319,10 +2641,33 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
   // to, i.e. if the symbol's definition is in bitcode. Any other required
   // libcall symbols will be added to the link after LTO when we add the LTO
   // object file to the link.
-  if (!bitcodeFiles.empty())
+  if (!ctx.bitcodeFiles.empty())
     for (auto *s : lto::LTO::getRuntimeLibcallSymbols())
       handleLibcall(s);
 
+  // Archive members defining __wrap symbols may be extracted.
+  std::vector<WrappedSymbol> wrapped = addWrappedSymbols(args);
+
+  // No more lazy bitcode can be extracted at this point. Do post parse work
+  // like checking duplicate symbols.
+  parallelForEach(ctx.objectFiles, [](ELFFileBase *file) {
+    initSectionsAndLocalSyms(file, /*ignoreComdats=*/false);
+  });
+  parallelForEach(ctx.objectFiles, postParseObjectFile);
+  parallelForEach(ctx.bitcodeFiles,
+                  [](BitcodeFile *file) { file->postParse(); });
+  for (auto &it : ctx.nonPrevailingSyms) {
+    Symbol &sym = *it.first;
+    Undefined(sym.file, sym.getName(), sym.binding, sym.stOther, sym.type,
+              it.second)
+        .overwrite(sym);
+    cast<Undefined>(sym).nonPrevailing = true;
+  }
+  ctx.nonPrevailingSyms.clear();
+  for (const DuplicateSymbol &d : ctx.duplicates)
+    reportDuplicate(*d.sym, d.file, d.section, d.value);
+  ctx.duplicates.clear();
+
   // Return if there were name resolution errors.
   if (errorCount())
     return;
@@ -2343,10 +2688,6 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
   // Create elfHeader early. We need a dummy section in
   // addReservedSymbols to mark the created symbols as not absolute.
   Out::elfHeader = make<OutputSection>("", 0, SHF_ALLOC);
-  Out::elfHeader->size = sizeof(typename ELFT::Ehdr);
-
-  // Create wrapped symbols for -wrap option.
-  std::vector<WrappedSymbol> wrapped = addWrappedSymbols(args);
 
   // We need to create some reserved symbols such as _end. Create them.
   if (!config->relocatable)
@@ -2359,78 +2700,106 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
   // name "foo@ver1") rather do harm, so we don't call this if -r is given.
   if (!config->relocatable) {
     llvm::TimeTraceScope timeScope("Process symbol versions");
-    symtab->scanVersionScript();
+    symtab.scanVersionScript();
   }
 
+  // Skip the normal linked output if some LTO options are specified.
+  //
+  // For --thinlto-index-only, index file creation is performed in
+  // compileBitcodeFiles, so we are done afterwards. --plugin-opt=emit-llvm and
+  // --plugin-opt=emit-asm create output files in bitcode or assembly code,
+  // respectively. When only certain thinLTO modules are specified for
+  // compilation, the intermediate object file are the expected output.
+  const bool skipLinkedOutput = config->thinLTOIndexOnly || config->emitLLVM ||
+                                config->ltoEmitAsm ||
+                                !config->thinLTOModulesToCompile.empty();
+
   // Do link-time optimization if given files are LLVM bitcode files.
   // This compiles bitcode files into real object files.
   //
   // With this the symbol table should be complete. After this, no new names
   // except a few linker-synthesized ones will be added to the symbol table.
-  compileBitcodeFiles<ELFT>();
+  const size_t numObjsBeforeLTO = ctx.objectFiles.size();
+  invokeELFT(compileBitcodeFiles, skipLinkedOutput);
 
-  // Handle --exclude-libs again because lto.tmp may reference additional
-  // libcalls symbols defined in an excluded archive. This may override
-  // versionId set by scanVersionScript().
-  if (args.hasArg(OPT_exclude_libs))
-    excludeLibs(args);
-
-  // Symbol resolution finished. Report backward reference problems.
+  // Symbol resolution finished. Report backward reference problems,
+  // --print-archive-stats=, and --why-extract=.
   reportBackrefs();
+  writeArchiveStats();
+  writeWhyExtract();
   if (errorCount())
     return;
 
-  // If -thinlto-index-only is given, we should create only "index
-  // files" and not object files. Index file creation is already done
-  // in addCombinedLTOObject, so we are done if that's the case.
-  // Likewise, --plugin-opt=emit-llvm and --plugin-opt=emit-asm are the
-  // options to create output files in bitcode or assembly code
-  // respectively. No object files are generated.
-  // Also bail out here when only certain thinLTO modules are specified for
-  // compilation. The intermediate object file are the expected output.
-  if (config->thinLTOIndexOnly || config->emitLLVM || config->ltoEmitAsm ||
-      !config->thinLTOModulesToCompile.empty())
+  // Bail out if normal linked output is skipped due to LTO.
+  if (skipLinkedOutput)
     return;
 
-  // Apply symbol renames for -wrap and combine foo@v1 and foo@@v1.
+  // compileBitcodeFiles may have produced lto.tmp object files. After this, no
+  // more file will be added.
+  auto newObjectFiles = ArrayRef(ctx.objectFiles).slice(numObjsBeforeLTO);
+  parallelForEach(newObjectFiles, [](ELFFileBase *file) {
+    initSectionsAndLocalSyms(file, /*ignoreComdats=*/true);
+  });
+  parallelForEach(newObjectFiles, postParseObjectFile);
+  for (const DuplicateSymbol &d : ctx.duplicates)
+    reportDuplicate(*d.sym, d.file, d.section, d.value);
+
+  // Handle --exclude-libs again because lto.tmp may reference additional
+  // libcalls symbols defined in an excluded archive. This may override
+  // versionId set by scanVersionScript().
+  if (args.hasArg(OPT_exclude_libs))
+    excludeLibs(args);
+
+  // Apply symbol renames for --wrap and combine foo@v1 and foo@@v1.
   redirectSymbols(wrapped);
 
+  // Replace common symbols with regular symbols.
+  replaceCommonSymbols();
+
   {
     llvm::TimeTraceScope timeScope("Aggregate sections");
     // Now that we have a complete list of input files.
     // Beyond this point, no new files are added.
     // Aggregate all input sections into one place.
-    for (InputFile *f : objectFiles)
-      for (InputSectionBase *s : f->getSections())
-        if (s && s != &InputSection::discarded)
-          inputSections.push_back(s);
-    for (BinaryFile *f : binaryFiles)
+    for (InputFile *f : ctx.objectFiles) {
+      for (InputSectionBase *s : f->getSections()) {
+        if (!s || s == &InputSection::discarded)
+          continue;
+        if (LLVM_UNLIKELY(isa<EhInputSection>(s)))
+          ctx.ehInputSections.push_back(cast<EhInputSection>(s));
+        else
+          ctx.inputSections.push_back(s);
+      }
+    }
+    for (BinaryFile *f : ctx.binaryFiles)
       for (InputSectionBase *s : f->getSections())
-        inputSections.push_back(cast<InputSection>(s));
+        ctx.inputSections.push_back(cast<InputSection>(s));
   }
 
   {
     llvm::TimeTraceScope timeScope("Strip sections");
-    llvm::erase_if(inputSections, [](InputSectionBase *s) {
-      if (s->type == SHT_LLVM_SYMPART) {
-        readSymbolPartitionSection<ELFT>(s);
+    if (ctx.hasSympart.load(std::memory_order_relaxed)) {
+      llvm::erase_if(ctx.inputSections, [](InputSectionBase *s) {
+        if (s->type != SHT_LLVM_SYMPART)
+          return false;
+        invokeELFT(readSymbolPartitionSection, s);
         return true;
-      }
+      });
+    }
+    // We do not want to emit debug sections if --strip-all
+    // or --strip-debug are given.
+    if (config->strip != StripPolicy::None) {
+      llvm::erase_if(ctx.inputSections, [](InputSectionBase *s) {
+        if (isDebugSection(*s))
+          return true;
+        if (auto *isec = dyn_cast<InputSection>(s))
+          if (InputSectionBase *rel = isec->getRelocatedSection())
+            if (isDebugSection(*rel))
+              return true;
 
-      // We do not want to emit debug sections if --strip-all
-      // or -strip-debug are given.
-      if (config->strip == StripPolicy::None)
         return false;
-
-      if (isDebugSection(*s))
-        return true;
-      if (auto *isec = dyn_cast<InputSection>(s))
-        if (InputSectionBase *rel = isec->getRelocatedSection())
-          if (isDebugSection(*rel))
-            return true;
-
-      return false;
-    });
+      });
+    }
   }
 
   // Since we now have a complete set of input files, we can create
@@ -2444,7 +2813,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
 
   // Read .note.gnu.property sections from input object files which
   // contain a hint to tweak linker's and loader's behaviors.
-  config->andFeatures = getAndFeatures<ELFT>();
+  config->andFeatures = getAndFeatures();
 
   // The Target instance handles target-specific stuff, such as applying
   // relocations or writing a PLT section. It also contains target-dependent
@@ -2471,28 +2840,16 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
 
   config->imageBase = getImageBase(args);
 
-  if (config->emachine == EM_ARM) {
-    // FIXME: These warnings can be removed when lld only uses these features
-    // when the input objects have been compiled with an architecture that
-    // supports them.
-    if (config->armHasBlx == false)
-      warn("lld uses blx instruction, no object with architecture supporting "
-           "feature detected");
-  }
-
   // This adds a .comment section containing a version string.
   if (!config->relocatable)
-    inputSections.push_back(createCommentSection());
-
-  // Replace common symbols with regular symbols.
-  replaceCommonSymbols();
+    ctx.inputSections.push_back(createCommentSection());
 
   // Split SHF_MERGE and .eh_frame sections into pieces in preparation for garbage collection.
-  splitSections<ELFT>();
+  invokeELFT(splitSections);
 
   // Garbage collection and removal of shared symbols from unused shared objects.
-  markLive<ELFT>();
-  demoteSharedSymbols();
+  invokeELFT(markLive);
+  demoteSharedAndLazySymbols();
 
   // Make copies of any input sections that need to be copied into each
   // partition.
@@ -2500,7 +2857,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
 
   // Create synthesized sections such as .got and .plt. This is called before
   // processSectionCommands() so that they can be placed by SECTIONS commands.
-  createSyntheticSections<ELFT>();
+  invokeELFT(createSyntheticSections);
 
   // Some input sections that are used for exception handling need to be moved
   // into synthetic sections. Do that now so that they aren't assigned to
@@ -2508,6 +2865,10 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
   if (!config->relocatable)
     combineEhSections();
 
+  // Merge .riscv.attributes sections.
+  if (config->emachine == EM_RISCV)
+    mergeRISCVAttributesSections();
+
   {
     llvm::TimeTraceScope timeScope("Assign sections");
 
@@ -2528,29 +2889,26 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
     // merging MergeInputSections into a single MergeSyntheticSection. From this
     // point onwards InputSectionDescription::sections should be used instead of
     // sectionBases.
-    for (BaseCommand *base : script->sectionCommands)
-      if (auto *sec = dyn_cast<OutputSection>(base))
-        sec->finalizeInputSections();
-    llvm::erase_if(inputSections, [](InputSectionBase *s) {
-      return isa<MergeInputSection>(s);
-    });
+    for (SectionCommand *cmd : script->sectionCommands)
+      if (auto *osd = dyn_cast<OutputDesc>(cmd))
+        osd->osec.finalizeInputSections();
   }
 
   // Two input sections with different output sections should not be folded.
   // ICF runs after processSectionCommands() so that we know the output sections.
   if (config->icf != ICFLevel::None) {
-    findKeepUniqueSections<ELFT>(args);
-    doIcf<ELFT>();
+    invokeELFT(findKeepUniqueSections, args);
+    invokeELFT(doIcf);
   }
 
   // Read the callgraph now that we know what was gced or icfed
   if (config->callGraphProfileSort) {
     if (auto *arg = args.getLastArg(OPT_call_graph_ordering_file))
-      if (Optional<MemoryBufferRef> buffer = readFile(arg->getValue()))
+      if (std::optional<MemoryBufferRef> buffer = readFile(arg->getValue()))
         readCallGraph(*buffer);
-    readCallGraphsFromObjectFiles<ELFT>();
+    invokeELFT(readCallGraphsFromObjectFiles);
   }
 
   // Write the result to the file.
-  writeResult<ELFT>();
+  invokeELFT(writeResult);
 }
index 2fee853..266cd9e 100644 (file)
@@ -6,27 +6,24 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file contains utility functions for the driver. Because there
+// This file contains utility functions for the ctx.driver. Because there
 // are so many small functions, we created this separate file to make
 // Driver.cpp less cluttered.
 //
 //===----------------------------------------------------------------------===//
 
+#include "Config.h"
 #include "Driver.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
 #include "lld/Common/Reproduce.h"
-#include "lld/Common/Version.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Support/Path.h"
-#include "llvm/Support/Process.h"
 #include "llvm/Support/TimeProfiler.h"
+#include <optional>
 
 using namespace llvm;
 using namespace llvm::sys;
@@ -37,12 +34,15 @@ using namespace lld::elf;
 // Create OptTable
 
 // Create prefix string literals used in Options.td
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE)                                                    \
+  static constexpr StringLiteral NAME##_init[] = VALUE;                        \
+  static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
+                                                std::size(NAME##_init) - 1);
 #include "Options.inc"
 #undef PREFIX
 
 // Create table mapping all options defined in Options.td
-static const opt::OptTable::Info optInfo[] = {
+static constexpr opt::OptTable::Info optInfo[] = {
 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12)      \
   {X1, X2, X10,         X11,         OPT_##ID, opt::Option::KIND##Class,       \
    X9, X8, OPT_##GROUP, OPT_##ALIAS, X7,       X12},
@@ -50,28 +50,21 @@ static const opt::OptTable::Info optInfo[] = {
 #undef OPTION
 };
 
-ELFOptTable::ELFOptTable() : OptTable(optInfo) {}
+ELFOptTable::ELFOptTable() : GenericOptTable(optInfo) {}
 
-// Set color diagnostics according to -color-diagnostics={auto,always,never}
-// or -no-color-diagnostics flags.
+// Set color diagnostics according to --color-diagnostics={auto,always,never}
+// or --no-color-diagnostics flags.
 static void handleColorDiagnostics(opt::InputArgList &args) {
-  auto *arg = args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq,
-                              OPT_no_color_diagnostics);
+  auto *arg = args.getLastArg(OPT_color_diagnostics);
   if (!arg)
     return;
-  if (arg->getOption().getID() == OPT_color_diagnostics) {
+  StringRef s = arg->getValue();
+  if (s == "always")
     lld::errs().enable_colors(true);
-  } else if (arg->getOption().getID() == OPT_no_color_diagnostics) {
+  else if (s == "never")
     lld::errs().enable_colors(false);
-  } else {
-    StringRef s = arg->getValue();
-    if (s == "always")
-      lld::errs().enable_colors(true);
-    else if (s == "never")
-      lld::errs().enable_colors(false);
-    else if (s != "auto")
-      error("unknown option: --color-diagnostics=" + s);
-  }
+  else if (s != "auto")
+    error("unknown option: --color-diagnostics=" + s);
 }
 
 static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &args) {
@@ -102,7 +95,7 @@ static void concatLTOPluginOptions(SmallVectorImpl<const char *> &args) {
   for (size_t i = 0, e = args.size(); i != e; ++i) {
     StringRef s = args[i];
     if ((s == "-plugin-opt" || s == "--plugin-opt") && i + 1 != e) {
-      v.push_back(saver.save(s + "=" + args[i + 1]).data());
+      v.push_back(saver().save(s + "=" + args[i + 1]).data());
       ++i;
     } else {
       v.push_back(args[i]);
@@ -125,7 +118,7 @@ opt::InputArgList ELFOptTable::parse(ArrayRef<const char *> argv) {
 
   // Expand response files (arguments in the form of @<filename>)
   // and then parse the argument again.
-  cl::ExpandResponseFiles(saver, getQuotingStyle(args), vec);
+  cl::ExpandResponseFiles(saver(), getQuotingStyle(args), vec);
   concatLTOPluginOptions(vec);
   args = this->ParseArgs(vec, missingIndex, missingCount);
 
@@ -150,11 +143,10 @@ void elf::printHelp() {
       "lld", false /*ShowHidden*/, true /*ShowAllAliases*/);
   lld::outs() << "\n";
 
-  // Scripts generated by Libtool versions up to at least 2.4.6 (the most
-  // recent version as of March 2017) expect /: supported targets:.* elf/
-  // in a message for the -help option. If it doesn't match, the scripts
-  // assume that the linker doesn't support very basic features such as
-  // shared libraries. Therefore, we need to print out at least "elf".
+  // Scripts generated by Libtool versions up to 2021-10 expect /: supported
+  // targets:.* elf/ in a message for the --help option. If it doesn't match,
+  // the scripts assume that the linker doesn't support very basic features
+  // such as shared libraries. Therefore, we need to print out at least "elf".
   lld::outs() << config->progName << ": supported targets: elf\n";
 }
 
@@ -180,17 +172,24 @@ std::string elf::createResponseFile(const opt::InputArgList &args) {
       os << quote(rewritePath(arg->getValue())) << "\n";
       break;
     case OPT_o:
-      // If -o path contains directories, "lld @response.txt" will likely
-      // fail because the archive we are creating doesn't contain empty
+    case OPT_Map:
+    case OPT_print_archive_stats:
+    case OPT_why_extract:
+      // If an output path contains directories, "lld @response.txt" will
+      // likely fail because the archive we are creating doesn't contain empty
       // directories for the output path (-o doesn't create directories).
       // Strip directories to prevent the issue.
-      os << "-o " << quote(path::filename(arg->getValue())) << "\n";
+      os << arg->getSpelling();
+      if (arg->getOption().getRenderStyle() == opt::Option::RenderSeparateStyle)
+        os << ' ';
+      os << quote(path::filename(arg->getValue())) << '\n';
       break;
     case OPT_lto_sample_profile:
       os << arg->getSpelling() << quote(rewritePath(arg->getValue())) << "\n";
       break;
     case OPT_call_graph_ordering_file:
     case OPT_dynamic_list:
+    case OPT_export_dynamic_symbol_list:
     case OPT_just_symbols:
     case OPT_library_path:
     case OPT_retain_symbols_file:
@@ -211,7 +210,8 @@ std::string elf::createResponseFile(const opt::InputArgList &args) {
 
 // Find a file by concatenating given paths. If a resulting path
 // starts with "=", the character is replaced with a --sysroot value.
-static Optional<std::string> findFile(StringRef path1, const Twine &path2) {
+static std::optional<std::string> findFile(StringRef path1,
+                                           const Twine &path2) {
   SmallString<128> s;
   if (path1.startswith("="))
     path::append(s, config->sysroot, path1.substr(1), path2);
@@ -220,19 +220,19 @@ static Optional<std::string> findFile(StringRef path1, const Twine &path2) {
 
   if (fs::exists(s))
     return std::string(s);
-  return None;
+  return std::nullopt;
 }
 
-Optional<std::string> elf::findFromSearchPaths(StringRef path) {
+std::optional<std::string> elf::findFromSearchPaths(StringRef path) {
   for (StringRef dir : config->searchPaths)
-    if (Optional<std::string> s = findFile(dir, path))
+    if (std::optional<std::string> s = findFile(dir, path))
       return s;
-  return None;
+  return std::nullopt;
 }
 
 namespace {
 // Must be in sync with findMajMinShlib in clang/lib/Driver/Driver.cpp.
-llvm::Optional<std::string> findMajMinShlib(StringRef dir, const Twine& libNameSo) {
+  std::optional<std::string> findMajMinShlib(StringRef dir, const Twine& libNameSo) {
   // Handle OpenBSD-style maj/min shlib scheme
   llvm::SmallString<128> Scratch;
   const StringRef LibName = (libNameSo + ".").toStringRef(Scratch);
@@ -258,28 +258,28 @@ llvm::Optional<std::string> findMajMinShlib(StringRef dir, const Twine& libNameS
   }
   if (MaxMaj >= 0)
     return findFile(dir, LibName + Twine(MaxMaj) + "." + Twine(MaxMin));
-  return None;
+  return std::nullopt;
 }
 }  // namespace
 
 // This is for -l<basename>. We'll look for lib<basename>.so or lib<basename>.a from
 // search paths.
-Optional<std::string> elf::searchLibraryBaseName(StringRef name) {
+std::optional<std::string> elf::searchLibraryBaseName(StringRef name) {
   for (StringRef dir : config->searchPaths) {
     if (!config->isStatic) {
-      if (Optional<std::string> s = findFile(dir, "lib" + name + ".so"))
+      if (std::optional<std::string> s = findFile(dir, "lib" + name + ".so"))
         return s;
-      if (Optional<std::string> s = findMajMinShlib(dir, "lib" + name + ".so"))
+      if (std::optional<std::string> s = findMajMinShlib(dir, "lib" + name + ".so"))
         return s;
     }
-    if (Optional<std::string> s = findFile(dir, "lib" + name + ".a"))
+    if (std::optional<std::string> s = findFile(dir, "lib" + name + ".a"))
       return s;
   }
-  return None;
+  return std::nullopt;
 }
 
 // This is for -l<namespec>.
-Optional<std::string> elf::searchLibrary(StringRef name) {
+std::optional<std::string> elf::searchLibrary(StringRef name) {
   llvm::TimeTraceScope timeScope("Locate library", name);
   if (name.startswith(":"))
     return findFromSearchPaths(name.substr(1));
@@ -289,7 +289,7 @@ Optional<std::string> elf::searchLibrary(StringRef name) {
 // If a linker/version script doesn't exist in the current directory, we also
 // look for the script in the '-L' search paths. This matches the behaviour of
 // '-T', --version-script=, and linker script INPUT() command in ld.bfd.
-Optional<std::string> elf::searchScript(StringRef name) {
+std::optional<std::string> elf::searchScript(StringRef name) {
   if (fs::exists(name))
     return name.str();
   return findFromSearchPaths(name);
index 7565240..05fc619 100644 (file)
@@ -7,25 +7,25 @@
 //===----------------------------------------------------------------------===//
 
 #include "InputFiles.h"
+#include "Config.h"
+#include "DWARF.h"
 #include "Driver.h"
 #include "InputSection.h"
 #include "LinkerScript.h"
 #include "SymbolTable.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
+#include "Target.h"
+#include "lld/Common/CommonLinkerContext.h"
 #include "lld/Common/DWARF.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
+#include "llvm/ADT/CachedHashString.h"
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/CodeGen/Analysis.h"
-#include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/Module.h"
 #include "llvm/LTO/LTO.h"
-#include "llvm/MC/StringTableBuilder.h"
-#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/IRObjectFile.h"
 #include "llvm/Support/ARMAttributeParser.h"
 #include "llvm/Support/ARMBuildAttributes.h"
 #include "llvm/Support/Endian.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/RISCVAttributeParser.h"
 #include "llvm/Support/TarWriter.h"
@@ -43,29 +43,26 @@ using namespace lld::elf;
 bool InputFile::isInGroup;
 uint32_t InputFile::nextGroupId;
 
-std::vector<ArchiveFile *> elf::archiveFiles;
-std::vector<BinaryFile *> elf::binaryFiles;
-std::vector<BitcodeFile *> elf::bitcodeFiles;
-std::vector<LazyObjFile *> elf::lazyObjFiles;
-std::vector<InputFile *> elf::objectFiles;
-std::vector<SharedFile *> elf::sharedFiles;
-
 std::unique_ptr<TarWriter> elf::tar;
 
 DenseMap<StringRef, StringRef> elf::gnuWarnings;
 
 // Returns "<internal>", "foo.a(bar.o)" or "baz.o".
 std::string lld::toString(const InputFile *f) {
+  static std::mutex mu;
   if (!f)
     return "<internal>";
 
-  if (f->toStringCache.empty()) {
-    if (f->archiveName.empty())
-      f->toStringCache = std::string(f->getName());
-    else
-      f->toStringCache = (f->archiveName + "(" + f->getName() + ")").str();
+  {
+    std::lock_guard<std::mutex> lock(mu);
+    if (f->toStringCache.empty()) {
+      if (f->archiveName.empty())
+        f->toStringCache = f->getName();
+      else
+        (f->archiveName + "(" + f->getName() + ")").toVector(f->toStringCache);
+    }
   }
-  return f->toStringCache;
+  return std::string(f->toStringCache);
 }
 
 // .gnu.warning.SYMBOL are treated as warning symbols for the given symbol
@@ -74,7 +71,7 @@ void lld::parseGNUWarning(StringRef name, ArrayRef<char> data, size_t size) {
     StringRef wsym = name.substr(13);
     StringRef s(data.begin());
     StringRef wng(s.substr(0, size));
-    symtab->insert(wsym)->gwarn = true;
+    symtab.insert(wsym)->gwarn = true;
     gnuWarnings.insert({wsym, wng});
   }
 }
@@ -109,6 +106,92 @@ static ELFKind getELFKind(MemoryBufferRef mb, StringRef archiveName) {
   return (endian == ELFDATA2LSB) ? ELF64LEKind : ELF64BEKind;
 }
 
+// For ARM only, to set the EF_ARM_ABI_FLOAT_SOFT or EF_ARM_ABI_FLOAT_HARD
+// flag in the ELF Header we need to look at Tag_ABI_VFP_args to find out how
+// the input objects have been compiled.
+static void updateARMVFPArgs(const ARMAttributeParser &attributes,
+                             const InputFile *f) {
+  std::optional<unsigned> attr =
+      attributes.getAttributeValue(ARMBuildAttrs::ABI_VFP_args);
+  if (!attr)
+    // If an ABI tag isn't present then it is implicitly given the value of 0
+    // which maps to ARMBuildAttrs::BaseAAPCS. However many assembler files,
+    // including some in glibc that don't use FP args (and should have value 3)
+    // don't have the attribute so we do not consider an implicit value of 0
+    // as a clash.
+    return;
+
+  unsigned vfpArgs = *attr;
+  ARMVFPArgKind arg;
+  switch (vfpArgs) {
+  case ARMBuildAttrs::BaseAAPCS:
+    arg = ARMVFPArgKind::Base;
+    break;
+  case ARMBuildAttrs::HardFPAAPCS:
+    arg = ARMVFPArgKind::VFP;
+    break;
+  case ARMBuildAttrs::ToolChainFPPCS:
+    // Tool chain specific convention that conforms to neither AAPCS variant.
+    arg = ARMVFPArgKind::ToolChain;
+    break;
+  case ARMBuildAttrs::CompatibleFPAAPCS:
+    // Object compatible with all conventions.
+    return;
+  default:
+    error(toString(f) + ": unknown Tag_ABI_VFP_args value: " + Twine(vfpArgs));
+    return;
+  }
+  // Follow ld.bfd and error if there is a mix of calling conventions.
+  if (config->armVFPArgs != arg && config->armVFPArgs != ARMVFPArgKind::Default)
+    error(toString(f) + ": incompatible Tag_ABI_VFP_args");
+  else
+    config->armVFPArgs = arg;
+}
+
+// The ARM support in lld makes some use of instructions that are not available
+// on all ARM architectures. Namely:
+// - Use of BLX instruction for interworking between ARM and Thumb state.
+// - Use of the extended Thumb branch encoding in relocation.
+// - Use of the MOVT/MOVW instructions in Thumb Thunks.
+// The ARM Attributes section contains information about the architecture chosen
+// at compile time. We follow the convention that if at least one input object
+// is compiled with an architecture that supports these features then lld is
+// permitted to use them.
+static void updateSupportedARMFeatures(const ARMAttributeParser &attributes) {
+  std::optional<unsigned> attr =
+      attributes.getAttributeValue(ARMBuildAttrs::CPU_arch);
+  if (!attr)
+    return;
+  auto arch = *attr;
+  switch (arch) {
+  case ARMBuildAttrs::Pre_v4:
+  case ARMBuildAttrs::v4:
+  case ARMBuildAttrs::v4T:
+    // Architectures prior to v5 do not support BLX instruction
+    break;
+  case ARMBuildAttrs::v5T:
+  case ARMBuildAttrs::v5TE:
+  case ARMBuildAttrs::v5TEJ:
+  case ARMBuildAttrs::v6:
+  case ARMBuildAttrs::v6KZ:
+  case ARMBuildAttrs::v6K:
+    config->armHasBlx = true;
+    // Architectures used in pre-Cortex processors do not support
+    // The J1 = 1 J2 = 1 Thumb branch range extension, with the exception
+    // of Architecture v6T2 (arm1156t2-s and arm1156t2f-s) that do.
+    break;
+  default:
+    // All other Architectures have BLX and extended branch encoding
+    config->armHasBlx = true;
+    config->armJ1J2BranchEncoding = true;
+    if (arch != ARMBuildAttrs::v6_M && arch != ARMBuildAttrs::v6S_M)
+      // All Architectures used in Cortex processors with the exception
+      // of v6-M and v6S-M have the MOVT and MOVW instructions.
+      config->armHasMovtMovw = true;
+    break;
+  }
+}
+
 InputFile::InputFile(Kind k, MemoryBufferRef m)
     : mb(m), groupId(nextGroupId), fileKind(k) {
   // All files within the same --{start,end}-group get the same group ID.
@@ -117,13 +200,13 @@ InputFile::InputFile(Kind k, MemoryBufferRef m)
     ++nextGroupId;
 }
 
-Optional<MemoryBufferRef> elf::readFile(StringRef path) {
+std::optional<MemoryBufferRef> elf::readFile(StringRef path) {
   llvm::TimeTraceScope timeScope("Load input files", path);
 
   // The --chroot option changes our virtual root directory.
   // This is useful when you are dealing with files created by --reproduce.
   if (!config->chroot.empty() && path.startswith("/"))
-    path = saver.save(config->chroot + path);
+    path = saver().save(config->chroot + path);
 
   log(path);
   config->dependencyFiles.insert(llvm::CachedHashString(path));
@@ -132,12 +215,11 @@ Optional<MemoryBufferRef> elf::readFile(StringRef path) {
                                        /*RequiresNullTerminator=*/false);
   if (auto ec = mbOrErr.getError()) {
     error("cannot open " + path + ": " + ec.message());
-    return None;
+    return std::nullopt;
   }
 
-  std::unique_ptr<MemoryBuffer> &mb = *mbOrErr;
-  MemoryBufferRef mbref = mb->getMemBufferRef();
-  make<std::unique_ptr<MemoryBuffer>>(std::move(mb)); // take MB ownership
+  MemoryBufferRef mbref = (*mbOrErr)->getMemBufferRef();
+  ctx.memoryBuffers.push_back(std::move(*mbOrErr)); // take MB ownership
 
   if (tar)
     tar->append(relativeToRoot(path), mbref.getBuffer());
@@ -165,18 +247,17 @@ static bool isCompatible(InputFile *file) {
     return false;
   }
 
-  InputFile *existing;
-  if (!objectFiles.empty())
-    existing = objectFiles[0];
-  else if (!sharedFiles.empty())
-    existing = sharedFiles[0];
-  else if (!bitcodeFiles.empty())
-    existing = bitcodeFiles[0];
-  else
-    llvm_unreachable("Must have -m, OUTPUT_FORMAT or existing input file to "
-                     "determine target emulation");
-
-  error(toString(file) + " is incompatible with " + toString(existing));
+  InputFile *existing = nullptr;
+  if (!ctx.objectFiles.empty())
+    existing = ctx.objectFiles[0];
+  else if (!ctx.sharedFiles.empty())
+    existing = ctx.sharedFiles[0];
+  else if (!ctx.bitcodeFiles.empty())
+    existing = ctx.bitcodeFiles[0];
+  std::string with;
+  if (existing)
+    with = " with " + toString(existing);
+  error(toString(file) + " is incompatible" + with);
   return false;
 }
 
@@ -186,22 +267,19 @@ template <class ELFT> static void doParseFile(InputFile *file) {
 
   // Binary file
   if (auto *f = dyn_cast<BinaryFile>(file)) {
-    binaryFiles.push_back(f);
-    f->parse();
-    return;
-  }
-
-  // .a file
-  if (auto *f = dyn_cast<ArchiveFile>(file)) {
-    archiveFiles.push_back(f);
+    ctx.binaryFiles.push_back(f);
     f->parse();
     return;
   }
 
   // Lazy object file
-  if (auto *f = dyn_cast<LazyObjFile>(file)) {
-    lazyObjFiles.push_back(f);
-    f->parse<ELFT>();
+  if (file->lazy) {
+    if (auto *f = dyn_cast<BitcodeFile>(file)) {
+      ctx.lazyBitcodeFiles.push_back(f);
+      f->parseLazy();
+    } else {
+      cast<ObjFile<ELFT>>(file)->parseLazy();
+    }
     return;
   }
 
@@ -216,35 +294,18 @@ template <class ELFT> static void doParseFile(InputFile *file) {
 
   // LLVM bitcode file
   if (auto *f = dyn_cast<BitcodeFile>(file)) {
-    bitcodeFiles.push_back(f);
-    f->parse<ELFT>();
+    ctx.bitcodeFiles.push_back(f);
+    f->parse();
     return;
   }
 
   // Regular object file
-  objectFiles.push_back(file);
+  ctx.objectFiles.push_back(cast<ELFFileBase>(file));
   cast<ObjFile<ELFT>>(file)->parse();
 }
 
 // Add symbols in File to the symbol table.
-void elf::parseFile(InputFile *file) {
-  switch (config->ekind) {
-  case ELF32LEKind:
-    doParseFile<ELF32LE>(file);
-    return;
-  case ELF32BEKind:
-    doParseFile<ELF32BE>(file);
-    return;
-  case ELF64LEKind:
-    doParseFile<ELF64LE>(file);
-    return;
-  case ELF64BEKind:
-    doParseFile<ELF64BE>(file);
-    return;
-  default:
-    llvm_unreachable("unknown ELFT");
-  }
-}
+void elf::parseFile(InputFile *file) { invokeELFT(doParseFile, file); }
 
 // Concatenates arguments to construct a string representing an error location.
 static std::string createFileLineMsg(StringRef path, unsigned line) {
@@ -259,12 +320,12 @@ template <class ELFT>
 static std::string getSrcMsgAux(ObjFile<ELFT> &file, const Symbol &sym,
                                 InputSectionBase &sec, uint64_t offset) {
   // In DWARF, functions and variables are stored to different places.
-  // First, lookup a function for a given offset.
-  if (Optional<DILineInfo> info = file.getDILineInfo(&sec, offset))
+  // First, look up a function for a given offset.
+  if (std::optional<DILineInfo> info = file.getDILineInfo(&sec, offset))
     return createFileLineMsg(info->FileName, info->Line);
 
-  // If it failed, lookup again as a variable.
-  if (Optional<std::pair<std::string, unsigned>> fileLine =
+  // If it failed, look up again as a variable.
+  if (std::optional<std::pair<std::string, unsigned>> fileLine =
           file.getVariableLoc(sym.getName()))
     return createFileLineMsg(fileLine->first, fileLine->second);
 
@@ -276,7 +337,7 @@ std::string InputFile::getSrcMsg(const Symbol &sym, InputSectionBase &sec,
                                  uint64_t offset) {
   if (kind() != ObjKind)
     return "";
-  switch (config->ekind) {
+  switch (ekind) {
   default:
     llvm_unreachable("Invalid kind");
   case ELF32LEKind:
@@ -300,6 +361,65 @@ StringRef InputFile::getNameForScript() const {
   return nameForScriptCache;
 }
 
+// An ELF object file may contain a `.deplibs` section. If it exists, the
+// section contains a list of library specifiers such as `m` for libm. This
+// function resolves a given name by finding the first matching library checking
+// the various ways that a library can be specified to LLD. This ELF extension
+// is a form of autolinking and is called `dependent libraries`. It is currently
+// unique to LLVM and lld.
+static void addDependentLibrary(StringRef specifier, const InputFile *f) {
+  if (!config->dependentLibraries)
+    return;
+  if (std::optional<std::string> s = searchLibraryBaseName(specifier))
+    ctx.driver.addFile(saver().save(*s), /*withLOption=*/true);
+  else if (std::optional<std::string> s = findFromSearchPaths(specifier))
+    ctx.driver.addFile(saver().save(*s), /*withLOption=*/true);
+  else if (fs::exists(specifier))
+    ctx.driver.addFile(specifier, /*withLOption=*/false);
+  else
+    error(toString(f) +
+          ": unable to find library from dependent library specifier: " +
+          specifier);
+}
+
+// Record the membership of a section group so that in the garbage collection
+// pass, section group members are kept or discarded as a unit.
+template <class ELFT>
+static void handleSectionGroup(ArrayRef<InputSectionBase *> sections,
+                               ArrayRef<typename ELFT::Word> entries) {
+  bool hasAlloc = false;
+  for (uint32_t index : entries.slice(1)) {
+    if (index >= sections.size())
+      return;
+    if (InputSectionBase *s = sections[index])
+      if (s != &InputSection::discarded && s->flags & SHF_ALLOC)
+        hasAlloc = true;
+  }
+
+  // If any member has the SHF_ALLOC flag, the whole group is subject to garbage
+  // collection. See the comment in markLive(). This rule retains .debug_types
+  // and .rela.debug_types.
+  if (!hasAlloc)
+    return;
+
+  // Connect the members in a circular doubly-linked list via
+  // nextInSectionGroup.
+  InputSectionBase *head;
+  InputSectionBase *prev = nullptr;
+  for (uint32_t index : entries.slice(1)) {
+    InputSectionBase *s = sections[index];
+    if (!s || s == &InputSection::discarded)
+      continue;
+    if (prev)
+      prev->nextInSectionGroup = s;
+    else
+      head = s;
+    prev = s;
+  }
+  if (prev)
+    prev->nextInSectionGroup = head;
+}
+
 template <class ELFT> DWARFCache *ObjFile<ELFT>::getDwarf() {
   llvm::call_once(initDwarf, [this]() {
     dwarf = std::make_unique<DWARFCache>(std::make_unique<DWARFContext>(
@@ -316,7 +436,7 @@ template <class ELFT> DWARFCache *ObjFile<ELFT>::getDwarf() {
 // Returns the pair of file name and line number describing location of data
 // object (variable, array, etc) definition.
 template <class ELFT>
-Optional<std::pair<std::string, unsigned>>
+std::optional<std::pair<std::string, unsigned>>
 ObjFile<ELFT>::getVariableLoc(StringRef name) {
   return getDwarf()->getVariableLoc(name);
 }
@@ -324,8 +444,8 @@ ObjFile<ELFT>::getVariableLoc(StringRef name) {
 // Returns source line information for a given offset
 // using DWARF debug info.
 template <class ELFT>
-Optional<DILineInfo> ObjFile<ELFT>::getDILineInfo(InputSectionBase *s,
-                                                  uint64_t offset) {
+std::optional<DILineInfo> ObjFile<ELFT>::getDILineInfo(InputSectionBase *s,
+                                                       uint64_t offset) {
   // Detect SectionIndex for specified section.
   uint64_t sectionIndex = object::SectionedAddress::UndefSection;
   ArrayRef<InputSectionBase *> sections = s->file->getSections();
@@ -339,36 +459,39 @@ Optional<DILineInfo> ObjFile<ELFT>::getDILineInfo(InputSectionBase *s,
   return getDwarf()->getDILineInfo(offset, sectionIndex);
 }
 
-ELFFileBase::ELFFileBase(Kind k, MemoryBufferRef mb) : InputFile(k, mb) {
-  ekind = getELFKind(mb, "");
+ELFFileBase::ELFFileBase(Kind k, ELFKind ekind, MemoryBufferRef mb)
+    : InputFile(k, mb) {
+  this->ekind = ekind;
+}
+
+template <typename Elf_Shdr>
+static const Elf_Shdr *findSection(ArrayRef<Elf_Shdr> sections, uint32_t type) {
+  for (const Elf_Shdr &sec : sections)
+    if (sec.sh_type == type)
+      return &sec;
+  return nullptr;
+}
 
+void ELFFileBase::init() {
   switch (ekind) {
   case ELF32LEKind:
-    init<ELF32LE>();
+    init<ELF32LE>(fileKind);
     break;
   case ELF32BEKind:
-    init<ELF32BE>();
+    init<ELF32BE>(fileKind);
     break;
   case ELF64LEKind:
-    init<ELF64LE>();
+    init<ELF64LE>(fileKind);
     break;
   case ELF64BEKind:
-    init<ELF64BE>();
+    init<ELF64BE>(fileKind);
     break;
   default:
     llvm_unreachable("getELFKind");
   }
 }
 
-template <typename Elf_Shdr>
-static const Elf_Shdr *findSection(ArrayRef<Elf_Shdr> sections, uint32_t type) {
-  for (const Elf_Shdr &sec : sections)
-    if (sec.sh_type == type)
-      return &sec;
-  return nullptr;
-}
-
-template <class ELFT> void ELFFileBase::init() {
+template <class ELFT> void ELFFileBase::init(InputFile::Kind k) {
   using Elf_Shdr = typename ELFT::Shdr;
   using Elf_Sym = typename ELFT::Sym;
 
@@ -379,12 +502,12 @@ template <class ELFT> void ELFFileBase::init() {
   abiVersion = obj.getHeader().e_ident[llvm::ELF::EI_ABIVERSION];
 
   ArrayRef<Elf_Shdr> sections = CHECK(obj.sections(), this);
+  elfShdrs = sections.data();
+  numELFShdrs = sections.size();
 
   // Find a symbol table.
-  bool isDSO =
-      (identify_magic(mb.getBuffer()) == file_magic::elf_shared_object);
   const Elf_Shdr *symtabSec =
-      findSection(sections, isDSO ? SHT_DYNSYM : SHT_SYMTAB);
+      findSection(sections, k == SharedKind ? SHT_DYNSYM : SHT_SYMTAB);
 
   if (!symtabSec)
     return;
@@ -397,7 +520,7 @@ template <class ELFT> void ELFFileBase::init() {
     fatal(toString(this) + ": invalid sh_info in symbol table");
 
   elfSyms = reinterpret_cast<const void *>(eSyms.data());
-  numELFSyms = eSyms.size();
+  numELFSyms = uint32_t(eSyms.size());
   stringTable = CHECK(obj.getStringTableForSymtab(*symtabSec, sections), this);
 }
 
@@ -408,25 +531,103 @@ uint32_t ObjFile<ELFT>::getSectionIndex(const Elf_Sym &sym) const {
       this);
 }
 
-template <class ELFT> ArrayRef<Symbol *> ObjFile<ELFT>::getLocalSymbols() {
-  if (this->symbols.empty())
-    return {};
-  return makeArrayRef(this->symbols).slice(1, this->firstGlobal - 1);
-}
-
-template <class ELFT> ArrayRef<Symbol *> ObjFile<ELFT>::getGlobalSymbols() {
-  return makeArrayRef(this->symbols).slice(this->firstGlobal);
-}
-
 template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) {
+  object::ELFFile<ELFT> obj = this->getObj();
   // Read a section table. justSymbols is usually false.
-  if (this->justSymbols)
+  if (this->justSymbols) {
     initializeJustSymbols();
-  else
-    initializeSections(ignoreComdats);
+    initializeSymbols(obj);
+    return;
+  }
+
+  // Handle dependent libraries and selection of section groups as these are not
+  // done in parallel.
+  ArrayRef<Elf_Shdr> objSections = getELFShdrs<ELFT>();
+  StringRef shstrtab = CHECK(obj.getSectionStringTable(objSections), this);
+  uint64_t size = objSections.size();
+  sections.resize(size);
+  for (size_t i = 0; i != size; ++i) {
+    const Elf_Shdr &sec = objSections[i];
+    if (sec.sh_type == SHT_LLVM_DEPENDENT_LIBRARIES && !config->relocatable) {
+      StringRef name = check(obj.getSectionName(sec, shstrtab));
+      ArrayRef<char> data = CHECK(
+          this->getObj().template getSectionContentsAsArray<char>(sec), this);
+      if (!data.empty() && data.back() != '\0') {
+        error(
+            toString(this) +
+            ": corrupted dependent libraries section (unterminated string): " +
+            name);
+      } else {
+        for (const char *d = data.begin(), *e = data.end(); d < e;) {
+          StringRef s(d);
+          addDependentLibrary(s, this);
+          d += s.size() + 1;
+        }
+      }
+      this->sections[i] = &InputSection::discarded;
+      continue;
+    }
+
+    if (sec.sh_type == SHT_ARM_ATTRIBUTES && config->emachine == EM_ARM) {
+      ARMAttributeParser attributes;
+      ArrayRef<uint8_t> contents =
+          check(this->getObj().getSectionContents(sec));
+      StringRef name = check(obj.getSectionName(sec, shstrtab));
+      this->sections[i] = &InputSection::discarded;
+      if (Error e =
+              attributes.parse(contents, ekind == ELF32LEKind ? support::little
+                                                              : support::big)) {
+        InputSection isec(*this, sec, name);
+        warn(toString(&isec) + ": " + llvm::toString(std::move(e)));
+      } else {
+        updateSupportedARMFeatures(attributes);
+        updateARMVFPArgs(attributes, this);
+
+        // FIXME: Retain the first attribute section we see. The eglibc ARM
+        // dynamic loaders require the presence of an attribute section for
+        // dlopen to work. In a full implementation we would merge all attribute
+        // sections.
+        if (in.attributes == nullptr) {
+          in.attributes = std::make_unique<InputSection>(*this, sec, name);
+          this->sections[i] = in.attributes.get();
+        }
+      }
+    }
+
+    if (sec.sh_type != SHT_GROUP)
+      continue;
+    StringRef signature = getShtGroupSignature(objSections, sec);
+    ArrayRef<Elf_Word> entries =
+        CHECK(obj.template getSectionContentsAsArray<Elf_Word>(sec), this);
+    if (entries.empty())
+      fatal(toString(this) + ": empty SHT_GROUP");
+
+    Elf_Word flag = entries[0];
+    if (flag && flag != GRP_COMDAT)
+      fatal(toString(this) + ": unsupported SHT_GROUP format");
+
+    bool keepGroup =
+        (flag & GRP_COMDAT) == 0 || ignoreComdats ||
+        symtab.comdatGroups.try_emplace(CachedHashStringRef(signature), this)
+            .second;
+    if (keepGroup) {
+      if (config->relocatable)
+        this->sections[i] = createInputSection(
+            i, sec, check(obj.getSectionName(sec, shstrtab)));
+      continue;
+    }
+
+    // Otherwise, discard group members.
+    for (uint32_t secIndex : entries.slice(1)) {
+      if (secIndex >= size)
+        fatal(toString(this) +
+              ": invalid section index in group: " + Twine(secIndex));
+      this->sections[secIndex] = &InputSection::discarded;
+    }
+  }
 
   // Read a symbol table.
-  initializeSymbols();
+  initializeSymbols(obj);
 }
 
 // Sections with SHT_GROUP and comdat bits define comdat section groups.
@@ -439,25 +640,11 @@ StringRef ObjFile<ELFT>::getShtGroupSignature(ArrayRef<Elf_Shdr> sections,
   if (sec.sh_info >= symbols.size())
     fatal(toString(this) + ": invalid symbol index");
   const typename ELFT::Sym &sym = symbols[sec.sh_info];
-  StringRef signature = CHECK(sym.getName(this->stringTable), this);
-
-  // As a special case, if a symbol is a section symbol and has no name,
-  // we use a section name as a signature.
-  //
-  // Such SHT_GROUP sections are invalid from the perspective of the ELF
-  // standard, but GNU gold 1.14 (the newest version as of July 2017) or
-  // older produce such sections as outputs for the -r option, so we need
-  // a bug-compatibility.
-  if (signature.empty() && sym.getType() == STT_SECTION)
-    return getSectionName(sec);
-  return signature;
+  return CHECK(sym.getName(this->stringTable), this);
 }
 
 template <class ELFT>
 bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &sec, StringRef name) {
-  if (!(sec.sh_flags & SHF_MERGE))
-    return false;
-
   // On a regular link we don't merge sections if -O0 (default is -O1). This
   // sometimes makes the linker significantly faster, although the output will
   // be bigger.
@@ -510,93 +697,27 @@ bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &sec, StringRef name) {
 // When the option is given, we link "just symbols". The section table is
 // initialized with null pointers.
 template <class ELFT> void ObjFile<ELFT>::initializeJustSymbols() {
-  ArrayRef<Elf_Shdr> sections = CHECK(this->getObj().sections(), this);
-  this->sections.resize(sections.size());
-}
-
-// An ELF object file may contain a `.deplibs` section. If it exists, the
-// section contains a list of library specifiers such as `m` for libm. This
-// function resolves a given name by finding the first matching library checking
-// the various ways that a library can be specified to LLD. This ELF extension
-// is a form of autolinking and is called `dependent libraries`. It is currently
-// unique to LLVM and lld.
-static void addDependentLibrary(StringRef specifier, const InputFile *f) {
-  if (!config->dependentLibraries)
-    return;
-  if (fs::exists(specifier))
-    driver->addFile(specifier, /*withLOption=*/false);
-  else if (Optional<std::string> s = findFromSearchPaths(specifier))
-    driver->addFile(*s, /*withLOption=*/true);
-  else if (Optional<std::string> s = searchLibraryBaseName(specifier))
-    driver->addFile(*s, /*withLOption=*/true);
-  else
-    error(toString(f) +
-          ": unable to find library from dependent library specifier: " +
-          specifier);
+  sections.resize(numELFShdrs);
 }
 
-// Record the membership of a section group so that in the garbage collection
-// pass, section group members are kept or discarded as a unit.
 template <class ELFT>
-static void handleSectionGroup(ArrayRef<InputSectionBase *> sections,
-                               ArrayRef<typename ELFT::Word> entries) {
-  bool hasAlloc = false;
-  for (uint32_t index : entries.slice(1)) {
-    if (index >= sections.size())
-      return;
-    if (InputSectionBase *s = sections[index])
-      if (s != &InputSection::discarded && s->flags & SHF_ALLOC)
-        hasAlloc = true;
-  }
-
-  // If any member has the SHF_ALLOC flag, the whole group is subject to garbage
-  // collection. See the comment in markLive(). This rule retains .debug_types
-  // and .rela.debug_types.
-  if (!hasAlloc)
-    return;
-
-  // Connect the members in a circular doubly-linked list via
-  // nextInSectionGroup.
-  InputSectionBase *head;
-  InputSectionBase *prev = nullptr;
-  for (uint32_t index : entries.slice(1)) {
-    InputSectionBase *s = sections[index];
-    if (!s || s == &InputSection::discarded)
-      continue;
-    if (prev)
-      prev->nextInSectionGroup = s;
-    else
-      head = s;
-    prev = s;
-  }
-  if (prev)
-    prev->nextInSectionGroup = head;
-}
-
-template <class ELFT>
-void ObjFile<ELFT>::initializeSections(bool ignoreComdats) {
-  const ELFFile<ELFT> &obj = this->getObj();
-
-  ArrayRef<Elf_Shdr> objSections = CHECK(obj.sections(), this);
+void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
+                                       const llvm::object::ELFFile<ELFT> &obj) {
+  ArrayRef<Elf_Shdr> objSections = getELFShdrs<ELFT>();
+  StringRef shstrtab = CHECK(obj.getSectionStringTable(objSections), this);
   uint64_t size = objSections.size();
-  this->sections.resize(size);
-  this->sectionStringTable =
-      CHECK(obj.getSectionStringTable(objSections), this);
-
-  std::vector<ArrayRef<Elf_Word>> selectedGroups;
-
-  for (size_t i = 0, e = objSections.size(); i < e; ++i) {
+  SmallVector<ArrayRef<Elf_Word>, 0> selectedGroups;
+  for (size_t i = 0; i != size; ++i) {
     if (this->sections[i] == &InputSection::discarded)
       continue;
     const Elf_Shdr &sec = objSections[i];
 
-    if (sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE)
-      cgProfileSectionIndex = i;
-
     // SHF_EXCLUDE'ed sections are discarded by the linker. However,
     // if -r is given, we'll let the final link discard such sections.
     // This is compatible with GNU.
     if ((sec.sh_flags & SHF_EXCLUDE) && !config->relocatable) {
+      if (sec.sh_type == SHT_LLVM_CALL_GRAPH_PROFILE)
+        cgProfileSectionIndex = i;
       if (sec.sh_type == SHT_LLVM_ADDRSIG) {
         // We ignore the address-significance table if we know that the object
         // file was created by objcopy or ld -r. This is because these tools
@@ -618,37 +739,16 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats) {
 
     switch (sec.sh_type) {
     case SHT_GROUP: {
-      // De-duplicate section groups by their signatures.
-      StringRef signature = getShtGroupSignature(objSections, sec);
-      this->sections[i] = &InputSection::discarded;
-
+      if (!config->relocatable)
+        sections[i] = &InputSection::discarded;
+      StringRef signature =
+          cantFail(this->getELFSyms<ELFT>()[sec.sh_info].getName(stringTable));
       ArrayRef<Elf_Word> entries =
-          CHECK(obj.template getSectionContentsAsArray<Elf_Word>(sec), this);
-      if (entries.empty())
-        fatal(toString(this) + ": empty SHT_GROUP");
-
-      Elf_Word flag = entries[0];
-      if (flag && flag != GRP_COMDAT)
-        fatal(toString(this) + ": unsupported SHT_GROUP format");
-
-      bool keepGroup =
-          (flag & GRP_COMDAT) == 0 || ignoreComdats ||
-          symtab->comdatGroups.try_emplace(CachedHashStringRef(signature), this)
-              .second;
-      if (keepGroup) {
-        if (config->relocatable)
-          this->sections[i] = createInputSection(sec);
+          cantFail(obj.template getSectionContentsAsArray<Elf_Word>(sec));
+      if ((entries[0] & GRP_COMDAT) == 0 || ignoreComdats ||
+          symtab.comdatGroups.find(CachedHashStringRef(signature))->second ==
+              this)
         selectedGroups.push_back(entries);
-        continue;
-      }
-
-      // Otherwise, discard group members.
-      for (uint32_t secIndex : entries.slice(1)) {
-        if (secIndex >= size)
-          fatal(toString(this) +
-                ": invalid section index in group: " + Twine(secIndex));
-        this->sections[secIndex] = &InputSection::discarded;
-      }
       break;
     }
     case SHT_SYMTAB_SHNDX:
@@ -661,15 +761,19 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats) {
     case SHT_NULL:
       break;
     case SHT_PROGBITS: {
-      this->sections[i] = createInputSection(sec);
-      StringRef name = CHECK(obj.getSectionName(sec, this->sectionStringTable), this);
+      this->sections[i] = createInputSection(i, sec, check(obj.getSectionName(sec, shstrtab)));
+      StringRef name = check(obj.getSectionName(sec, shstrtab));
       ArrayRef<char> data =
           CHECK(obj.template getSectionContentsAsArray<char>(sec), this);
       parseGNUWarning(name, data, sec.sh_size);
       }
       break;
+    case SHT_LLVM_SYMPART:
+      ctx.hasSympart.store(true, std::memory_order_relaxed);
+      [[fallthrough]];
     default:
-      this->sections[i] = createInputSection(sec);
+      this->sections[i] =
+          createInputSection(i, sec, check(obj.getSectionName(sec, shstrtab)));
     }
   }
 
@@ -680,123 +784,78 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats) {
   //    such cases, the relocation section would attempt to reference a target
   //    section that has not yet been created. For simplicity, delay creation of
   //    relocation sections until now.
-  for (size_t i = 0, e = objSections.size(); i < e; ++i) {
+  for (size_t i = 0; i != size; ++i) {
     if (this->sections[i] == &InputSection::discarded)
       continue;
     const Elf_Shdr &sec = objSections[i];
 
-    if (sec.sh_type == SHT_REL || sec.sh_type == SHT_RELA)
-      this->sections[i] = createInputSection(sec);
-
-    // A SHF_LINK_ORDER section with sh_link=0 is handled as if it did not have
-    // the flag.
-    if (!(sec.sh_flags & SHF_LINK_ORDER) || !sec.sh_link)
-      continue;
-
-    InputSectionBase *linkSec = nullptr;
-    if (sec.sh_link < this->sections.size())
-      linkSec = this->sections[sec.sh_link];
-    if (!linkSec)
-      fatal(toString(this) + ": invalid sh_link index: " + Twine(sec.sh_link));
+    if (sec.sh_type == SHT_REL || sec.sh_type == SHT_RELA) {
+      // Find a relocation target section and associate this section with that.
+      // Target may have been discarded if it is in a different section group
+      // and the group is discarded, even though it's a violation of the spec.
+      // We handle that situation gracefully by discarding dangling relocation
+      // sections.
+      const uint32_t info = sec.sh_info;
+      InputSectionBase *s = getRelocTarget(i, sec, info);
+      if (!s)
+        continue;
 
-    // A SHF_LINK_ORDER section is discarded if its linked-to section is
-    // discarded.
-    InputSection *isec = cast<InputSection>(this->sections[i]);
-    linkSec->dependentSections.push_back(isec);
-    if (!isa<InputSection>(linkSec))
-      error("a section " + isec->name +
-            " with SHF_LINK_ORDER should not refer a non-regular section: " +
-            toString(linkSec));
-  }
+      // ELF spec allows mergeable sections with relocations, but they are rare,
+      // and it is in practice hard to merge such sections by contents, because
+      // applying relocations at end of linking changes section contents. So, we
+      // simply handle such sections as non-mergeable ones. Degrading like this
+      // is acceptable because section merging is optional.
+      if (auto *ms = dyn_cast<MergeInputSection>(s)) {
+        s = makeThreadLocal<InputSection>(
+            ms->file, ms->flags, ms->type, ms->addralign,
+            ms->contentMaybeDecompress(), ms->name);
+        sections[info] = s;
+      }
 
-  for (ArrayRef<Elf_Word> entries : selectedGroups)
-    handleSectionGroup<ELFT>(this->sections, entries);
-}
+      if (s->relSecIdx != 0)
+        error(
+            toString(s) +
+            ": multiple relocation sections to one section are not supported");
+      s->relSecIdx = i;
+
+      // Relocation sections are usually removed from the output, so return
+      // `nullptr` for the normal case. However, if -r or --emit-relocs is
+      // specified, we need to copy them to the output. (Some post link analysis
+      // tools specify --emit-relocs to obtain the information.)
+      if (config->copyRelocs) {
+        auto *isec = makeThreadLocal<InputSection>(
+            *this, sec, check(obj.getSectionName(sec, shstrtab)));
+        // If the relocated section is discarded (due to /DISCARD/ or
+        // --gc-sections), the relocation section should be discarded as well.
+        s->dependentSections.push_back(isec);
+        sections[i] = isec;
+      }
+      continue;
+    }
 
-// For ARM only, to set the EF_ARM_ABI_FLOAT_SOFT or EF_ARM_ABI_FLOAT_HARD
-// flag in the ELF Header we need to look at Tag_ABI_VFP_args to find out how
-// the input objects have been compiled.
-static void updateARMVFPArgs(const ARMAttributeParser &attributes,
-                             const InputFile *f) {
-  Optional<unsigned> attr =
-      attributes.getAttributeValue(ARMBuildAttrs::ABI_VFP_args);
-  if (!attr.hasValue())
-    // If an ABI tag isn't present then it is implicitly given the value of 0
-    // which maps to ARMBuildAttrs::BaseAAPCS. However many assembler files,
-    // including some in glibc that don't use FP args (and should have value 3)
-    // don't have the attribute so we do not consider an implicit value of 0
-    // as a clash.
-    return;
+    // A SHF_LINK_ORDER section with sh_link=0 is handled as if it did not have
+    // the flag.
+    if (!sec.sh_link || !(sec.sh_flags & SHF_LINK_ORDER))
+      continue;
 
-  unsigned vfpArgs = attr.getValue();
-  ARMVFPArgKind arg;
-  switch (vfpArgs) {
-  case ARMBuildAttrs::BaseAAPCS:
-    arg = ARMVFPArgKind::Base;
-    break;
-  case ARMBuildAttrs::HardFPAAPCS:
-    arg = ARMVFPArgKind::VFP;
-    break;
-  case ARMBuildAttrs::ToolChainFPPCS:
-    // Tool chain specific convention that conforms to neither AAPCS variant.
-    arg = ARMVFPArgKind::ToolChain;
-    break;
-  case ARMBuildAttrs::CompatibleFPAAPCS:
-    // Object compatible with all conventions.
-    return;
-  default:
-    error(toString(f) + ": unknown Tag_ABI_VFP_args value: " + Twine(vfpArgs));
-    return;
-  }
-  // Follow ld.bfd and error if there is a mix of calling conventions.
-  if (config->armVFPArgs != arg && config->armVFPArgs != ARMVFPArgKind::Default)
-    error(toString(f) + ": incompatible Tag_ABI_VFP_args");
-  else
-    config->armVFPArgs = arg;
-}
+    InputSectionBase *linkSec = nullptr;
+    if (sec.sh_link < size)
+      linkSec = this->sections[sec.sh_link];
+    if (!linkSec)
+      fatal(toString(this) + ": invalid sh_link index: " + Twine(sec.sh_link));
 
-// The ARM support in lld makes some use of instructions that are not available
-// on all ARM architectures. Namely:
-// - Use of BLX instruction for interworking between ARM and Thumb state.
-// - Use of the extended Thumb branch encoding in relocation.
-// - Use of the MOVT/MOVW instructions in Thumb Thunks.
-// The ARM Attributes section contains information about the architecture chosen
-// at compile time. We follow the convention that if at least one input object
-// is compiled with an architecture that supports these features then lld is
-// permitted to use them.
-static void updateSupportedARMFeatures(const ARMAttributeParser &attributes) {
-  Optional<unsigned> attr =
-      attributes.getAttributeValue(ARMBuildAttrs::CPU_arch);
-  if (!attr.hasValue())
-    return;
-  auto arch = attr.getValue();
-  switch (arch) {
-  case ARMBuildAttrs::Pre_v4:
-  case ARMBuildAttrs::v4:
-  case ARMBuildAttrs::v4T:
-    // Architectures prior to v5 do not support BLX instruction
-    break;
-  case ARMBuildAttrs::v5T:
-  case ARMBuildAttrs::v5TE:
-  case ARMBuildAttrs::v5TEJ:
-  case ARMBuildAttrs::v6:
-  case ARMBuildAttrs::v6KZ:
-  case ARMBuildAttrs::v6K:
-    config->armHasBlx = true;
-    // Architectures used in pre-Cortex processors do not support
-    // The J1 = 1 J2 = 1 Thumb branch range extension, with the exception
-    // of Architecture v6T2 (arm1156t2-s and arm1156t2f-s) that do.
-    break;
-  default:
-    // All other Architectures have BLX and extended branch encoding
-    config->armHasBlx = true;
-    config->armJ1J2BranchEncoding = true;
-    if (arch != ARMBuildAttrs::v6_M && arch != ARMBuildAttrs::v6S_M)
-      // All Architectures used in Cortex processors with the exception
-      // of v6-M and v6S-M have the MOVT and MOVW instructions.
-      config->armHasMovtMovw = true;
-    break;
+    // A SHF_LINK_ORDER section is discarded if its linked-to section is
+    // discarded.
+    InputSection *isec = cast<InputSection>(this->sections[i]);
+    linkSec->dependentSections.push_back(isec);
+    if (!isa<InputSection>(linkSec))
+      error("a section " + isec->name +
+            " with SHF_LINK_ORDER should not refer a non-regular section: " +
+            toString(linkSec));
   }
+
+  for (ArrayRef<Elf_Word> entries : selectedGroups)
+    handleSectionGroup<ELFT>(this->sections, entries);
 }
 
 // If a source file is compiled with x86 hardware-assisted call flow control
@@ -816,10 +875,10 @@ template <class ELFT> static uint32_t readAndFeatures(const InputSection &sec) {
   using Elf_Note = typename ELFT::Note;
 
   uint32_t featuresSet = 0;
-  ArrayRef<uint8_t> data = sec.data();
+  ArrayRef<uint8_t> data = sec.content();
   auto reportFatal = [&](const uint8_t *place, const char *msg) {
     fatal(toString(sec.file) + ":(" + sec.name + "+0x" +
-          Twine::utohexstr(place - sec.data().data()) + "): " + msg);
+          Twine::utohexstr(place - sec.content().data()) + "): " + msg);
   };
   while (!data.empty()) {
     // Read one NOTE record.
@@ -870,403 +929,273 @@ template <class ELFT> static uint32_t readAndFeatures(const InputSection &sec) {
 }
 
 template <class ELFT>
-InputSectionBase *ObjFile<ELFT>::getRelocTarget(const Elf_Shdr &sec) {
-  uint32_t idx = sec.sh_info;
-  if (idx >= this->sections.size())
-    fatal(toString(this) + ": invalid relocated section index: " + Twine(idx));
-  InputSectionBase *target = this->sections[idx];
-
-  // Strictly speaking, a relocation section must be included in the
-  // group of the section it relocates. However, LLVM 3.3 and earlier
-  // would fail to do so, so we gracefully handle that case.
-  if (target == &InputSection::discarded)
-    return nullptr;
-
-  if (!target)
-    fatal(toString(this) + ": unsupported relocation reference");
-  return target;
-}
+InputSectionBase *ObjFile<ELFT>::getRelocTarget(uint32_t idx,
+                                                const Elf_Shdr &sec,
+                                                uint32_t info) {
+  if (info < this->sections.size()) {
+    InputSectionBase *target = this->sections[info];
+
+    // Strictly speaking, a relocation section must be included in the
+    // group of the section it relocates. However, LLVM 3.3 and earlier
+    // would fail to do so, so we gracefully handle that case.
+    if (target == &InputSection::discarded)
+      return nullptr;
+
+    if (target != nullptr)
+      return target;
+  }
 
-// Create a regular InputSection class that has the same contents
-// as a given section.
-static InputSection *toRegularSection(MergeInputSection *sec) {
-  return make<InputSection>(sec->file, sec->flags, sec->type, sec->alignment,
-                            sec->data(), sec->name);
+  error(toString(this) + Twine(": relocation section (index ") + Twine(idx) +
+        ") has invalid sh_info (" + Twine(info) + ")");
+  return nullptr;
 }
 
+// The function may be called concurrently for different input files. For
+// allocation, prefer makeThreadLocal which does not require holding a lock.
 template <class ELFT>
-InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &sec) {
-  StringRef name = getSectionName(sec);
-
-  if (config->emachine == EM_ARM && sec.sh_type == SHT_ARM_ATTRIBUTES) {
-    ARMAttributeParser attributes;
-    ArrayRef<uint8_t> contents = check(this->getObj().getSectionContents(sec));
-    if (Error e = attributes.parse(contents, config->ekind == ELF32LEKind
-                                                 ? support::little
-                                                 : support::big)) {
-      auto *isec = make<InputSection>(*this, sec, name);
-      warn(toString(isec) + ": " + llvm::toString(std::move(e)));
-    } else {
-      updateSupportedARMFeatures(attributes);
-      updateARMVFPArgs(attributes, this);
+InputSectionBase *ObjFile<ELFT>::createInputSection(uint32_t idx,
+                                                    const Elf_Shdr &sec,
+                                                    StringRef name) {
+  if (name.startswith(".n")) {
+    // The GNU linker uses .note.GNU-stack section as a marker indicating
+    // that the code in the object file does not expect that the stack is
+    // executable (in terms of NX bit). If all input files have the marker,
+    // the GNU linker adds a PT_GNU_STACK segment to tells the loader to
+    // make the stack non-executable. Most object files have this section as
+    // of 2017.
+    //
+    // But making the stack non-executable is a norm today for security
+    // reasons. Failure to do so may result in a serious security issue.
+    // Therefore, we make LLD always add PT_GNU_STACK unless it is
+    // explicitly told to do otherwise (by -z execstack). Because the stack
+    // executable-ness is controlled solely by command line options,
+    // .note.GNU-stack sections are simply ignored.
+    if (name == ".note.GNU-stack")
+      return &InputSection::discarded;
 
-      // FIXME: Retain the first attribute section we see. The eglibc ARM
-      // dynamic loaders require the presence of an attribute section for dlopen
-      // to work. In a full implementation we would merge all attribute
-      // sections.
-      if (in.attributes == nullptr) {
-        in.attributes = make<InputSection>(*this, sec, name);
-        return in.attributes;
-      }
+    // Object files that use processor features such as Intel Control-Flow
+    // Enforcement (CET) or AArch64 Branch Target Identification BTI, use a
+    // .note.gnu.property section containing a bitfield of feature bits like the
+    // GNU_PROPERTY_X86_FEATURE_1_IBT flag. Read a bitmap containing the flag.
+    //
+    // Since we merge bitmaps from multiple object files to create a new
+    // .note.gnu.property containing a single AND'ed bitmap, we discard an input
+    // file's .note.gnu.property section.
+    if (name == ".note.gnu.property") {
+      this->andFeatures = readAndFeatures<ELFT>(InputSection(*this, sec, name));
       return &InputSection::discarded;
     }
-  }
 
-  if (config->emachine == EM_RISCV && sec.sh_type == SHT_RISCV_ATTRIBUTES) {
-    RISCVAttributeParser attributes;
-    ArrayRef<uint8_t> contents = check(this->getObj().getSectionContents(sec));
-    if (Error e = attributes.parse(contents, support::little)) {
-      auto *isec = make<InputSection>(*this, sec, name);
-      warn(toString(isec) + ": " + llvm::toString(std::move(e)));
-    } else {
-      // FIXME: Validate arch tag contains C if and only if EF_RISCV_RVC is
-      // present.
-
-      // FIXME: Retain the first attribute section we see. Tools such as
-      // llvm-objdump make use of the attribute section to determine which
-      // standard extensions to enable. In a full implementation we would merge
-      // all attribute sections.
-      if (in.attributes == nullptr) {
-        in.attributes = make<InputSection>(*this, sec, name);
-        return in.attributes;
+    // Split stacks is a feature to support a discontiguous stack,
+    // commonly used in the programming language Go. For the details,
+    // see https://gcc.gnu.org/wiki/SplitStacks. An object file compiled
+    // for split stack will include a .note.GNU-split-stack section.
+    if (name == ".note.GNU-split-stack") {
+      if (config->relocatable) {
+        error(
+            "cannot mix split-stack and non-split-stack in a relocatable link");
+        return &InputSection::discarded;
       }
+      this->splitStack = true;
       return &InputSection::discarded;
     }
-  }
 
-  switch (sec.sh_type) {
-  case SHT_LLVM_DEPENDENT_LIBRARIES: {
-    if (config->relocatable)
-      break;
-    ArrayRef<char> data =
-        CHECK(this->getObj().template getSectionContentsAsArray<char>(sec), this);
-    if (!data.empty() && data.back() != '\0') {
-      error(toString(this) +
-            ": corrupted dependent libraries section (unterminated string): " +
-            name);
+    // An object file compiled for split stack, but where some of the
+    // functions were compiled with the no_split_stack_attribute will
+    // include a .note.GNU-no-split-stack section.
+    if (name == ".note.GNU-no-split-stack") {
+      this->someNoSplitStack = true;
       return &InputSection::discarded;
     }
-    for (const char *d = data.begin(), *e = data.end(); d < e;) {
-      StringRef s(d);
-      addDependentLibrary(s, this);
-      d += s.size() + 1;
-    }
-    return &InputSection::discarded;
-  }
-  case SHT_RELA:
-  case SHT_REL: {
-    // Find a relocation target section and associate this section with that.
-    // Target may have been discarded if it is in a different section group
-    // and the group is discarded, even though it's a violation of the
-    // spec. We handle that situation gracefully by discarding dangling
-    // relocation sections.
-    InputSectionBase *target = getRelocTarget(sec);
-    if (!target)
-      return nullptr;
-
-    // ELF spec allows mergeable sections with relocations, but they are
-    // rare, and it is in practice hard to merge such sections by contents,
-    // because applying relocations at end of linking changes section
-    // contents. So, we simply handle such sections as non-mergeable ones.
-    // Degrading like this is acceptable because section merging is optional.
-    if (auto *ms = dyn_cast<MergeInputSection>(target)) {
-      target = toRegularSection(ms);
-      this->sections[sec.sh_info] = target;
-    }
-
-    if (target->firstRelocation)
-      fatal(toString(this) +
-            ": multiple relocation sections to one section are not supported");
-
-    if (sec.sh_type == SHT_RELA) {
-      ArrayRef<Elf_Rela> rels = CHECK(getObj().relas(sec), this);
-      target->firstRelocation = rels.begin();
-      target->numRelocations = rels.size();
-      target->areRelocsRela = true;
-    } else {
-      ArrayRef<Elf_Rel> rels = CHECK(getObj().rels(sec), this);
-      target->firstRelocation = rels.begin();
-      target->numRelocations = rels.size();
-      target->areRelocsRela = false;
-    }
-    assert(isUInt<31>(target->numRelocations));
-
-    // Relocation sections are usually removed from the output, so return
-    // `nullptr` for the normal case. However, if -r or --emit-relocs is
-    // specified, we need to copy them to the output. (Some post link analysis
-    // tools specify --emit-relocs to obtain the information.)
-    if (!config->relocatable && !config->emitRelocs)
-      return nullptr;
-    InputSection *relocSec = make<InputSection>(*this, sec, name);
-    // If the relocated section is discarded (due to /DISCARD/ or
-    // --gc-sections), the relocation section should be discarded as well.
-    target->dependentSections.push_back(relocSec);
-    return relocSec;
-  }
-  }
-
-  // The GNU linker uses .note.GNU-stack section as a marker indicating
-  // that the code in the object file does not expect that the stack is
-  // executable (in terms of NX bit). If all input files have the marker,
-  // the GNU linker adds a PT_GNU_STACK segment to tells the loader to
-  // make the stack non-executable. Most object files have this section as
-  // of 2017.
-  //
-  // But making the stack non-executable is a norm today for security
-  // reasons. Failure to do so may result in a serious security issue.
-  // Therefore, we make LLD always add PT_GNU_STACK unless it is
-  // explicitly told to do otherwise (by -z execstack). Because the stack
-  // executable-ness is controlled solely by command line options,
-  // .note.GNU-stack sections are simply ignored.
-  if (name == ".note.GNU-stack")
-    return &InputSection::discarded;
-
-  // Object files that use processor features such as Intel Control-Flow
-  // Enforcement (CET) or AArch64 Branch Target Identification BTI, use a
-  // .note.gnu.property section containing a bitfield of feature bits like the
-  // GNU_PROPERTY_X86_FEATURE_1_IBT flag. Read a bitmap containing the flag.
-  //
-  // Since we merge bitmaps from multiple object files to create a new
-  // .note.gnu.property containing a single AND'ed bitmap, we discard an input
-  // file's .note.gnu.property section.
-  if (name == ".note.gnu.property") {
-    this->andFeatures = readAndFeatures<ELFT>(InputSection(*this, sec, name));
-    return &InputSection::discarded;
-  }
 
-  // Split stacks is a feature to support a discontiguous stack,
-  // commonly used in the programming language Go. For the details,
-  // see https://gcc.gnu.org/wiki/SplitStacks. An object file compiled
-  // for split stack will include a .note.GNU-split-stack section.
-  if (name == ".note.GNU-split-stack") {
-    if (config->relocatable) {
-      error("cannot mix split-stack and non-split-stack in a relocatable link");
+    // Strip existing .note.gnu.build-id sections so that the output won't have
+    // more than one build-id. This is not usually a problem because input
+    // object files normally don't have .build-id sections, but you can create
+    // such files by "ld.{bfd,gold,lld} -r --build-id", and we want to guard
+    // against it.
+    if (name == ".note.gnu.build-id")
       return &InputSection::discarded;
-    }
-    this->splitStack = true;
-    return &InputSection::discarded;
-  }
-
-  // An object file cmpiled for split stack, but where some of the
-  // functions were compiled with the no_split_stack_attribute will
-  // include a .note.GNU-no-split-stack section.
-  if (name == ".note.GNU-no-split-stack") {
-    this->someNoSplitStack = true;
-    return &InputSection::discarded;
   }
 
-  // The linkonce feature is a sort of proto-comdat. Some glibc i386 object
-  // files contain definitions of symbol "__x86.get_pc_thunk.bx" in linkonce
-  // sections. Drop those sections to avoid duplicate symbol errors.
-  // FIXME: This is glibc PR20543, we should remove this hack once that has been
-  // fixed for a while.
-  if (name == ".gnu.linkonce.t.__x86.get_pc_thunk.bx" ||
-      name == ".gnu.linkonce.t.__i686.get_pc_thunk.bx")
-    return &InputSection::discarded;
-
-  // If we are creating a new .build-id section, strip existing .build-id
-  // sections so that the output won't have more than one .build-id.
-  // This is not usually a problem because input object files normally don't
-  // have .build-id sections, but you can create such files by
-  // "ld.{bfd,gold,lld} -r --build-id", and we want to guard against it.
-  if (name == ".note.gnu.build-id" && config->buildId != BuildIdKind::None)
-    return &InputSection::discarded;
-
   // The linker merges EH (exception handling) frames and creates a
   // .eh_frame_hdr section for runtime. So we handle them with a special
   // class. For relocatable outputs, they are just passed through.
   if (name == ".eh_frame" && !config->relocatable)
-    return make<EhInputSection>(*this, sec, name);
-
-  if (shouldMerge(sec, name))
-    return make<MergeInputSection>(*this, sec, name);
-  return make<InputSection>(*this, sec, name);
-}
+    return makeThreadLocal<EhInputSection>(*this, sec, name);
 
-template <class ELFT>
-StringRef ObjFile<ELFT>::getSectionName(const Elf_Shdr &sec) {
-  return CHECK(getObj().getSectionName(sec, sectionStringTable), this);
+  if ((sec.sh_flags & SHF_MERGE) && shouldMerge(sec, name))
+    return makeThreadLocal<MergeInputSection>(*this, sec, name);
+  return makeThreadLocal<InputSection>(*this, sec, name);
 }
 
 // Initialize this->Symbols. this->Symbols is a parallel array as
 // its corresponding ELF symbol table.
-template <class ELFT> void ObjFile<ELFT>::initializeSymbols() {
+template <class ELFT>
+void ObjFile<ELFT>::initializeSymbols(const object::ELFFile<ELFT> &obj) {
   ArrayRef<Elf_Sym> eSyms = this->getELFSyms<ELFT>();
-  this->symbols.resize(eSyms.size());
-
-  // Fill in InputFile::symbols. Some entries have been initialized
-  // because of LazyObjFile.
-  for (size_t i = 0, end = eSyms.size(); i != end; ++i) {
-    if (this->symbols[i])
-      continue;
-    const Elf_Sym &eSym = eSyms[i];
-    uint32_t secIdx = getSectionIndex(eSym);
-    if (secIdx >= this->sections.size())
-      fatal(toString(this) + ": invalid section index: " + Twine(secIdx));
-    if (eSym.getBinding() != STB_LOCAL) {
-      if (i < firstGlobal)
-        error(toString(this) + ": non-local symbol (" + Twine(i) +
-              ") found at index < .symtab's sh_info (" + Twine(firstGlobal) +
-              ")");
-      this->symbols[i] =
-          symtab->insert(CHECK(eSyms[i].getName(this->stringTable), this));
-      continue;
-    }
-
-    // Handle local symbols. Local symbols are not added to the symbol
-    // table because they are not visible from other object files. We
-    // allocate symbol instances and add their pointers to symbols.
-    if (i >= firstGlobal)
-      errorOrWarn(toString(this) + ": STB_LOCAL symbol (" + Twine(i) +
-                  ") found at index >= .symtab's sh_info (" +
-                  Twine(firstGlobal) + ")");
-
-    InputSectionBase *sec = this->sections[secIdx];
-    uint8_t type = eSym.getType();
-    if (type == STT_FILE)
-      sourceFile = CHECK(eSym.getName(this->stringTable), this);
-    if (this->stringTable.size() <= eSym.st_name)
-      fatal(toString(this) + ": invalid symbol name offset");
-    StringRefZ name = this->stringTable.data() + eSym.st_name;
-
-    if (eSym.st_shndx == SHN_UNDEF)
-      this->symbols[i] =
-          make<Undefined>(this, name, STB_LOCAL, eSym.st_other, type);
-    else if (sec == &InputSection::discarded)
-      this->symbols[i] =
-          make<Undefined>(this, name, STB_LOCAL, eSym.st_other, type,
-                          /*discardedSecIdx=*/secIdx);
-    else
-      this->symbols[i] = make<Defined>(this, name, STB_LOCAL, eSym.st_other,
-                                       type, eSym.st_value, eSym.st_size, sec);
+  if (numSymbols == 0) {
+    numSymbols = eSyms.size();
+    symbols = std::make_unique<Symbol *[]>(numSymbols);
   }
 
-  // Symbol resolution of non-local symbols.
+  // Some entries have been filled by LazyObjFile.
+  for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i)
+    if (!symbols[i])
+      symbols[i] = symtab.insert(CHECK(eSyms[i].getName(stringTable), this));
+
+  // Perform symbol resolution on non-local symbols.
   SmallVector<unsigned, 32> undefineds;
   for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i) {
     const Elf_Sym &eSym = eSyms[i];
-    uint8_t binding = eSym.getBinding();
-    if (binding == STB_LOCAL)
-      continue; // Errored above.
+    uint32_t secIdx = eSym.st_shndx;
+    if (secIdx == SHN_UNDEF) {
+      undefineds.push_back(i);
+      continue;
+    }
 
-    uint32_t secIdx = getSectionIndex(eSym);
-    InputSectionBase *sec = this->sections[secIdx];
+    uint8_t binding = eSym.getBinding();
     uint8_t stOther = eSym.st_other;
     uint8_t type = eSym.getType();
     uint64_t value = eSym.st_value;
     uint64_t size = eSym.st_size;
-    StringRefZ name = this->stringTable.data() + eSym.st_name;
-
-    // Handle global undefined symbols.
-    if (eSym.st_shndx == SHN_UNDEF) {
-      undefineds.push_back(i);
-      continue;
-    }
 
-    // Handle global common symbols.
-    if (eSym.st_shndx == SHN_COMMON) {
+    Symbol *sym = symbols[i];
+    sym->isUsedInRegularObj = true;
+    if (LLVM_UNLIKELY(eSym.st_shndx == SHN_COMMON)) {
       if (value == 0 || value >= UINT32_MAX)
-        fatal(toString(this) + ": common symbol '" + StringRef(name.data) +
+        fatal(toString(this) + ": common symbol '" + sym->getName() +
               "' has invalid alignment: " + Twine(value));
-      this->symbols[i]->resolve(
-          CommonSymbol{this, name, binding, stOther, type, value, size});
+      hasCommonSyms = true;
+      sym->resolve(
+          CommonSymbol{this, StringRef(), binding, stOther, type, value, size});
       continue;
     }
 
-    // If a defined symbol is in a discarded section, handle it as if it
-    // were an undefined symbol. Such symbol doesn't comply with the
-    // standard, but in practice, a .eh_frame often directly refer
-    // COMDAT member sections, and if a comdat group is discarded, some
-    // defined symbol in a .eh_frame becomes dangling symbols.
-    if (sec == &InputSection::discarded) {
-      Undefined und{this, name, binding, stOther, type, secIdx};
-      Symbol *sym = this->symbols[i];
-      // !ArchiveFile::parsed or LazyObjFile::fetched means that the file
-      // containing this object has not finished processing, i.e. this symbol is
-      // a result of a lazy symbol fetch. We should demote the lazy symbol to an
-      // Undefined so that any relocations outside of the group to it will
-      // trigger a discarded section error.
-      if ((sym->symbolKind == Symbol::LazyArchiveKind &&
-           !cast<ArchiveFile>(sym->file)->parsed) ||
-          (sym->symbolKind == Symbol::LazyObjectKind &&
-           cast<LazyObjFile>(sym->file)->fetched))
-        sym->replace(und);
-      else
-        sym->resolve(und);
-      continue;
-    }
-
-    // Handle global defined symbols.
-    if (binding == STB_GLOBAL || binding == STB_WEAK ||
-        binding == STB_GNU_UNIQUE) {
-      this->symbols[i]->resolve(
-          Defined{this, name, binding, stOther, type, value, size, sec});
-      continue;
-    }
-
-    fatal(toString(this) + ": unexpected binding: " + Twine((int)binding));
+    // Handle global defined symbols. Defined::section will be set in postParse.
+    sym->resolve(Defined{this, StringRef(), binding, stOther, type, value, size,
+                         nullptr});
   }
 
   // Undefined symbols (excluding those defined relative to non-prevailing
-  // sections) can trigger recursive fetch. Process defined symbols first so
+  // sections) can trigger recursive extract. Process defined symbols first so
   // that the relative order between a defined symbol and an undefined symbol
   // does not change the symbol resolution behavior. In addition, a set of
   // interconnected symbols will all be resolved to the same file, instead of
   // being resolved to different files.
   for (unsigned i : undefineds) {
     const Elf_Sym &eSym = eSyms[i];
-    StringRefZ name = this->stringTable.data() + eSym.st_name;
-    this->symbols[i]->resolve(Undefined{this, name, eSym.getBinding(),
-                                        eSym.st_other, eSym.getType()});
-    this->symbols[i]->referenced = true;
+    Symbol *sym = symbols[i];
+    sym->resolve(Undefined{this, StringRef(), eSym.getBinding(), eSym.st_other,
+                           eSym.getType()});
+    sym->isUsedInRegularObj = true;
+    sym->referenced = true;
   }
 }
 
-ArchiveFile::ArchiveFile(std::unique_ptr<Archive> &&file)
-    : InputFile(ArchiveKind, file->getMemoryBufferRef()),
-      file(std::move(file)) {}
+template <class ELFT>
+void ObjFile<ELFT>::initSectionsAndLocalSyms(bool ignoreComdats) {
+  if (!justSymbols)
+    initializeSections(ignoreComdats, getObj());
 
-void ArchiveFile::parse() {
-  for (const Archive::Symbol &sym : file->symbols())
-    symtab->addSymbol(LazyArchive{*this, sym});
+  if (!firstGlobal)
+    return;
+  SymbolUnion *locals = makeThreadLocalN<SymbolUnion>(firstGlobal);
+  memset(locals, 0, sizeof(SymbolUnion) * firstGlobal);
 
-  // Inform a future invocation of ObjFile<ELFT>::initializeSymbols() that this
-  // archive has been processed.
-  parsed = true;
-}
+  ArrayRef<Elf_Sym> eSyms = this->getELFSyms<ELFT>();
+  for (size_t i = 0, end = firstGlobal; i != end; ++i) {
+    const Elf_Sym &eSym = eSyms[i];
+    uint32_t secIdx = eSym.st_shndx;
+    if (LLVM_UNLIKELY(secIdx == SHN_XINDEX))
+      secIdx = check(getExtendedSymbolTableIndex<ELFT>(eSym, i, shndxTable));
+    else if (secIdx >= SHN_LORESERVE)
+      secIdx = 0;
+    if (LLVM_UNLIKELY(secIdx >= sections.size()))
+      fatal(toString(this) + ": invalid section index: " + Twine(secIdx));
+    if (LLVM_UNLIKELY(eSym.getBinding() != STB_LOCAL))
+      error(toString(this) + ": non-local symbol (" + Twine(i) +
+            ") found at index < .symtab's sh_info (" + Twine(end) + ")");
+
+    InputSectionBase *sec = sections[secIdx];
+    uint8_t type = eSym.getType();
+    if (type == STT_FILE)
+      sourceFile = CHECK(eSym.getName(stringTable), this);
+    if (LLVM_UNLIKELY(stringTable.size() <= eSym.st_name))
+      fatal(toString(this) + ": invalid symbol name offset");
+    StringRef name(stringTable.data() + eSym.st_name);
 
-// Returns a buffer pointing to a member file containing a given symbol.
-void ArchiveFile::fetch(const Archive::Symbol &sym) {
-  Archive::Child c =
-      CHECK(sym.getMember(), toString(this) +
-                                 ": could not get the member for symbol " +
-                                 toELFString(sym));
+    symbols[i] = reinterpret_cast<Symbol *>(locals + i);
+    if (eSym.st_shndx == SHN_UNDEF || sec == &InputSection::discarded)
+      new (symbols[i]) Undefined(this, name, STB_LOCAL, eSym.st_other, type,
+                                 /*discardedSecIdx=*/secIdx);
+    else
+      new (symbols[i]) Defined(this, name, STB_LOCAL, eSym.st_other, type,
+                               eSym.st_value, eSym.st_size, sec);
+    symbols[i]->partition = 1;
+    symbols[i]->isUsedInRegularObj = true;
+  }
+}
 
-  if (!seen.insert(c.getChildOffset()).second)
-    return;
+// Called after all ObjFile::parse is called for all ObjFiles. This checks
+// duplicate symbols and may do symbol property merge in the future.
+template <class ELFT> void ObjFile<ELFT>::postParse() {
+  static std::mutex mu;
+  ArrayRef<Elf_Sym> eSyms = this->getELFSyms<ELFT>();
+  for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i) {
+    const Elf_Sym &eSym = eSyms[i];
+    Symbol &sym = *symbols[i];
+    uint32_t secIdx = eSym.st_shndx;
+    uint8_t binding = eSym.getBinding();
+    if (LLVM_UNLIKELY(binding != STB_GLOBAL && binding != STB_WEAK &&
+                      binding != STB_GNU_UNIQUE))
+      errorOrWarn(toString(this) + ": symbol (" + Twine(i) +
+                  ") has invalid binding: " + Twine((int)binding));
+
+    // st_value of STT_TLS represents the assigned offset, not the actual
+    // address which is used by STT_FUNC and STT_OBJECT. STT_TLS symbols can
+    // only be referenced by special TLS relocations. It is usually an error if
+    // a STT_TLS symbol is replaced by a non-STT_TLS symbol, vice versa.
+    if (LLVM_UNLIKELY(sym.isTls()) && eSym.getType() != STT_TLS &&
+        eSym.getType() != STT_NOTYPE)
+      errorOrWarn("TLS attribute mismatch: " + toString(sym) + "\n>>> in " +
+                  toString(sym.file) + "\n>>> in " + toString(this));
+
+    // Handle non-COMMON defined symbol below. !sym.file allows a symbol
+    // assignment to redefine a symbol without an error.
+    if (!sym.file || !sym.isDefined() || secIdx == SHN_UNDEF ||
+        secIdx == SHN_COMMON)
+      continue;
 
-  MemoryBufferRef mb =
-      CHECK(c.getMemoryBufferRef(),
-            toString(this) +
-                ": could not get the buffer for the member defining symbol " +
-                toELFString(sym));
+    if (LLVM_UNLIKELY(secIdx == SHN_XINDEX))
+      secIdx = check(getExtendedSymbolTableIndex<ELFT>(eSym, i, shndxTable));
+    else if (secIdx >= SHN_LORESERVE)
+      secIdx = 0;
+    if (LLVM_UNLIKELY(secIdx >= sections.size()))
+      fatal(toString(this) + ": invalid section index: " + Twine(secIdx));
+    InputSectionBase *sec = sections[secIdx];
+    if (sec == &InputSection::discarded) {
+      if (sym.traced) {
+        printTraceSymbol(Undefined{this, sym.getName(), sym.binding,
+                                   sym.stOther, sym.type, secIdx},
+                         sym.getName());
+      }
+      if (sym.file == this) {
+        std::lock_guard<std::mutex> lock(mu);
+        ctx.nonPrevailingSyms.emplace_back(&sym, secIdx);
+      }
+      continue;
+    }
 
-  if (tar && c.getParent()->isThin())
-    tar->append(relativeToRoot(CHECK(c.getFullName(), this)), mb.getBuffer());
+    if (sym.file == this) {
+      cast<Defined>(sym).section = sec;
+      continue;
+    }
 
-  InputFile *file = createObjectFile(mb, getName(), c.getChildOffset());
-  file->groupId = groupId;
-  parseFile(file);
+    if (sym.binding == STB_WEAK || binding == STB_WEAK)
+      continue;
+    std::lock_guard<std::mutex> lock(mu);
+    ctx.duplicates.push_back({&sym, this, sec, eSym.st_value});
+  }
 }
 
 // The handling of tentative definitions (COMMON symbols) in archives is murky.
@@ -1305,9 +1234,10 @@ static bool isBitcodeNonCommonDef(MemoryBufferRef mb, StringRef symName,
 }
 
 template <class ELFT>
-static bool isNonCommonDef(MemoryBufferRef mb, StringRef symName,
+static bool isNonCommonDef(ELFKind ekind, MemoryBufferRef mb, StringRef symName,
                            StringRef archiveName) {
-  ObjFile<ELFT> *obj = make<ObjFile<ELFT>>(mb, archiveName);
+  ObjFile<ELFT> *obj = make<ObjFile<ELFT>>(ekind, mb, archiveName);
+  obj->init();
   StringRef stringtable = obj->getStringTable();
 
   for (auto sym : obj->template getGlobalELFSyms<ELFT>()) {
@@ -1323,74 +1253,43 @@ static bool isNonCommonDef(MemoryBufferRef mb, StringRef symName,
                            StringRef archiveName) {
   switch (getELFKind(mb, archiveName)) {
   case ELF32LEKind:
-    return isNonCommonDef<ELF32LE>(mb, symName, archiveName);
+    return isNonCommonDef<ELF32LE>(ELF32LEKind, mb, symName, archiveName);
   case ELF32BEKind:
-    return isNonCommonDef<ELF32BE>(mb, symName, archiveName);
+    return isNonCommonDef<ELF32BE>(ELF32BEKind, mb, symName, archiveName);
   case ELF64LEKind:
-    return isNonCommonDef<ELF64LE>(mb, symName, archiveName);
+    return isNonCommonDef<ELF64LE>(ELF64LEKind, mb, symName, archiveName);
   case ELF64BEKind:
-    return isNonCommonDef<ELF64BE>(mb, symName, archiveName);
+    return isNonCommonDef<ELF64BE>(ELF64BEKind, mb, symName, archiveName);
   default:
     llvm_unreachable("getELFKind");
   }
 }
 
-bool ArchiveFile::shouldFetchForCommon(const Archive::Symbol &sym) {
-  Archive::Child c =
-      CHECK(sym.getMember(), toString(this) +
-                                 ": could not get the member for symbol " +
-                                 toELFString(sym));
-  MemoryBufferRef mb =
-      CHECK(c.getMemoryBufferRef(),
-            toString(this) +
-                ": could not get the buffer for the member defining symbol " +
-                toELFString(sym));
-
-  if (isBitcode(mb))
-    return isBitcodeNonCommonDef(mb, sym.getName(), getName());
-
-  return isNonCommonDef(mb, sym.getName(), getName());
-}
-
-size_t ArchiveFile::getMemberCount() const {
-  size_t count = 0;
-  Error err = Error::success();
-  for (const Archive::Child &c : file->children(err)) {
-    (void)c;
-    ++count;
-  }
-  // This function is used by --print-archive-stats=, where an error does not
-  // really matter.
-  consumeError(std::move(err));
-  return count;
-}
-
 unsigned SharedFile::vernauxNum;
 
+SharedFile::SharedFile(MemoryBufferRef m, StringRef defaultSoName)
+    : ELFFileBase(SharedKind, getELFKind(m, ""), m), soName(defaultSoName),
+      isNeeded(!config->asNeeded) {}
+
 // Parse the version definitions in the object file if present, and return a
 // vector whose nth element contains a pointer to the Elf_Verdef for version
 // identifier n. Version identifiers that are not definitions map to nullptr.
 template <typename ELFT>
-static std::vector<const void *> parseVerdefs(const uint8_t *base,
-                                              const typename ELFT::Shdr *sec) {
+static SmallVector<const void *, 0>
+parseVerdefs(const uint8_t *base, const typename ELFT::Shdr *sec) {
   if (!sec)
     return {};
 
-  // We cannot determine the largest verdef identifier without inspecting
-  // every Elf_Verdef, but both bfd and gold assign verdef identifiers
-  // sequentially starting from 1, so we predict that the largest identifier
-  // will be verdefCount.
-  unsigned verdefCount = sec->sh_info;
-  std::vector<const void *> verdefs(verdefCount + 1);
-
   // Build the Verdefs array by following the chain of Elf_Verdef objects
   // from the start of the .gnu.version_d section.
+  SmallVector<const void *, 0> verdefs;
   const uint8_t *verdef = base + sec->sh_offset;
-  for (unsigned i = 0; i != verdefCount; ++i) {
+  for (unsigned i = 0, e = sec->sh_info; i != e; ++i) {
     auto *curVerdef = reinterpret_cast<const typename ELFT::Verdef *>(verdef);
     verdef += curVerdef->vd_next;
     unsigned verdefIndex = curVerdef->vd_ndx;
-    verdefs.resize(verdefIndex + 1);
+    if (verdefIndex >= verdefs.size())
+      verdefs.resize(verdefIndex + 1);
     verdefs[verdefIndex] = curVerdef;
   }
   return verdefs;
@@ -1469,7 +1368,7 @@ template <class ELFT> void SharedFile::parse() {
 
   ArrayRef<Elf_Dyn> dynamicTags;
   const ELFFile<ELFT> obj = this->getObj<ELFT>();
-  ArrayRef<Elf_Shdr> sections = CHECK(obj.sections(), this);
+  ArrayRef<Elf_Shdr> sections = getELFShdrs<ELFT>();
 
   StringRef sectionStringTable =
       CHECK(obj.getSectionStringTable(sections), this);
@@ -1527,9 +1426,10 @@ template <class ELFT> void SharedFile::parse() {
   }
 
   // DSOs are uniquified not by filename but by soname.
-  DenseMap<StringRef, SharedFile *>::iterator it;
+  DenseMap<CachedHashStringRef, SharedFile *>::iterator it;
   bool wasInserted;
-  std::tie(it, wasInserted) = symtab->soNames.try_emplace(soName, this);
+  std::tie(it, wasInserted) =
+      symtab.soNames.try_emplace(CachedHashStringRef(soName), this);
 
   // If a DSO appears more than once on the command line with and without
   // --as-needed, --no-as-needed takes precedence over --as-needed because a
@@ -1539,7 +1439,7 @@ template <class ELFT> void SharedFile::parse() {
   if (!wasInserted)
     return;
 
-  sharedFiles.push_back(this);
+  ctx.sharedFiles.push_back(this);
 
   verdefs = parseVerdefs<ELFT>(obj.base(), verdefSec);
   std::vector<uint32_t> verneeds = parseVerneed<ELFT>(obj, verneedSec);
@@ -1565,37 +1465,37 @@ template <class ELFT> void SharedFile::parse() {
 
   // Add symbols to the symbol table.
   ArrayRef<Elf_Sym> syms = this->getGlobalELFSyms<ELFT>();
-  for (size_t i = 0; i < syms.size(); ++i) {
+  for (size_t i = 0, e = syms.size(); i != e; ++i) {
     const Elf_Sym &sym = syms[i];
 
     // ELF spec requires that all local symbols precede weak or global
     // symbols in each symbol table, and the index of first non-local symbol
     // is stored to sh_info. If a local symbol appears after some non-local
     // symbol, that's a violation of the spec.
-    StringRef name = CHECK(sym.getName(this->stringTable), this);
+    StringRef name = CHECK(sym.getName(stringTable), this);
     if (sym.getBinding() == STB_LOCAL) {
-      warn("found local symbol '" + name +
-           "' in global part of symbol table in file " + toString(this));
+      errorOrWarn(toString(this) + ": invalid local symbol '" + name +
+                  "' in global part of symbol table");
       continue;
     }
 
-    uint16_t idx = versyms[i] & ~VERSYM_HIDDEN;
+    const uint16_t ver = versyms[i], idx = ver & ~VERSYM_HIDDEN;
     if (sym.isUndefined()) {
       // For unversioned undefined symbols, VER_NDX_GLOBAL makes more sense but
       // as of binutils 2.34, GNU ld produces VER_NDX_LOCAL.
-      if (idx != VER_NDX_LOCAL && idx != VER_NDX_GLOBAL) {
+      if (ver != VER_NDX_LOCAL && ver != VER_NDX_GLOBAL) {
         if (idx >= verneeds.size()) {
           error("corrupt input file: version need index " + Twine(idx) +
                 " for symbol " + name + " is out of bounds\n>>> defined in " +
                 toString(this));
           continue;
         }
-        StringRef verName = this->stringTable.data() + verneeds[idx];
+        StringRef verName = stringTable.data() + verneeds[idx];
         versionedNameBuffer.clear();
-        name =
-            saver.save((name + "@" + verName).toStringRef(versionedNameBuffer));
+        name = saver().save(
+            (name + "@" + verName).toStringRef(versionedNameBuffer));
       }
-      Symbol *s = symtab->addSymbol(
+      Symbol *s = symtab.addSymbol(
           Undefined{this, name, sym.getBinding(), sym.st_other, sym.getType()});
       s->exportDynamic = true;
       if (s->isUndefined() && sym.getBinding() != STB_WEAK &&
@@ -1604,40 +1504,43 @@ template <class ELFT> void SharedFile::parse() {
       continue;
     }
 
-    // MIPS BFD linker puts _gp_disp symbol into DSO files and incorrectly
-    // assigns VER_NDX_LOCAL to this section global symbol. Here is a
-    // workaround for this bug.
-    if (config->emachine == EM_MIPS && idx == VER_NDX_LOCAL &&
-        name == "_gp_disp")
+    if (ver == VER_NDX_LOCAL ||
+        (ver != VER_NDX_GLOBAL && idx >= verdefs.size())) {
+      // In GNU ld < 2.31 (before 3be08ea4728b56d35e136af4e6fd3086ade17764), the
+      // MIPS port puts _gp_disp symbol into DSO files and incorrectly assigns
+      // VER_NDX_LOCAL. Workaround this bug.
+      if (config->emachine == EM_MIPS && name == "_gp_disp")
+        continue;
+      error("corrupt input file: version definition index " + Twine(idx) +
+            " for symbol " + name + " is out of bounds\n>>> defined in " +
+            toString(this));
       continue;
+    }
 
     uint32_t alignment = getAlignment<ELFT>(sections, sym);
-    if (!(versyms[i] & VERSYM_HIDDEN)) {
-      symtab->addSymbol(SharedSymbol{*this, name, sym.getBinding(),
-                                     sym.st_other, sym.getType(), sym.st_value,
-                                     sym.st_size, alignment, idx});
+    if (ver == idx) {
+      auto *s = symtab.addSymbol(
+          SharedSymbol{*this, name, sym.getBinding(), sym.st_other,
+                       sym.getType(), sym.st_value, sym.st_size, alignment});
+      if (s->file == this)
+        s->verdefIndex = ver;
     }
 
     // Also add the symbol with the versioned name to handle undefined symbols
     // with explicit versions.
-    if (idx == VER_NDX_GLOBAL)
-      continue;
-
-    if (idx >= verdefs.size() || idx == VER_NDX_LOCAL) {
-      error("corrupt input file: version definition index " + Twine(idx) +
-            " for symbol " + name + " is out of bounds\n>>> defined in " +
-            toString(this));
+    if (ver == VER_NDX_GLOBAL)
       continue;
-    }
 
     StringRef verName =
-        this->stringTable.data() +
+        stringTable.data() +
         reinterpret_cast<const Elf_Verdef *>(verdefs[idx])->getAux()->vda_name;
     versionedNameBuffer.clear();
     name = (name + "@" + verName).toStringRef(versionedNameBuffer);
-    symtab->addSymbol(SharedSymbol{*this, saver.save(name), sym.getBinding(),
-                                   sym.st_other, sym.getType(), sym.st_value,
-                                   sym.st_size, alignment, idx});
+    auto *s = symtab.addSymbol(
+        SharedSymbol{*this, saver().save(name), sym.getBinding(), sym.st_other,
+                     sym.getType(), sym.st_value, sym.st_size, alignment});
+    if (s->file == this)
+      s->verdefIndex = idx;
   }
 }
 
@@ -1660,6 +1563,8 @@ static uint16_t getBitcodeMachineKind(StringRef path, const Triple &t) {
     return EM_ARM;
   case Triple::avr:
     return EM_AVR;
+  case Triple::hexagon:
+    return EM_HEXAGON;
   case Triple::mips:
   case Triple::mipsel:
   case Triple::mips64:
@@ -1701,9 +1606,10 @@ static uint8_t getOsAbi(const Triple &t) {
 }
 
 BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
-                         uint64_t offsetInArchive)
+                         uint64_t offsetInArchive, bool lazy)
     : InputFile(BitcodeKind, mb) {
-  this->archiveName = std::string(archiveName);
+  this->archiveName = archiveName;
+  this->lazy = lazy;
 
   std::string path = mb.getBufferIdentifier().str();
   if (config->thinLTOIndexOnly)
@@ -1715,11 +1621,10 @@ BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
   // into consideration at LTO time (which very likely causes undefined
   // symbols later in the link stage). So we append file offset to make
   // filename unique.
-  StringRef name =
-      archiveName.empty()
-          ? saver.save(path)
-          : saver.save(archiveName + "(" + path::filename(path) + " at " +
-                       utostr(offsetInArchive) + ")");
+  StringRef name = archiveName.empty()
+                       ? saver().save(path)
+                       : saver().save(archiveName + "(" + path::filename(path) +
+                                      " at " + utostr(offsetInArchive) + ")");
   MemoryBufferRef mbref(mb.getBuffer(), name);
 
   obj = CHECK(lto::InputFile::create(mbref), this);
@@ -1742,53 +1647,85 @@ static uint8_t mapVisibility(GlobalValue::VisibilityTypes gvVisibility) {
   llvm_unreachable("unknown visibility");
 }
 
-template <class ELFT>
-static Symbol *createBitcodeSymbol(const std::vector<bool> &keptComdats,
-                                   const lto::InputFile::Symbol &objSym,
-                                   BitcodeFile &f) {
-  StringRef name = saver.save(objSym.getName());
+static void
+createBitcodeSymbol(Symbol *&sym, const std::vector<bool> &keptComdats,
+                    const lto::InputFile::Symbol &objSym, BitcodeFile &f) {
   uint8_t binding = objSym.isWeak() ? STB_WEAK : STB_GLOBAL;
   uint8_t type = objSym.isTLS() ? STT_TLS : STT_NOTYPE;
   uint8_t visibility = mapVisibility(objSym.getVisibility());
-  bool canOmitFromDynSym = objSym.canBeOmittedFromSymbolTable();
+
+  if (!sym)
+    sym = symtab.insert(saver().save(objSym.getName()));
 
   int c = objSym.getComdatIndex();
   if (objSym.isUndefined() || (c != -1 && !keptComdats[c])) {
-    Undefined newSym(&f, name, binding, visibility, type);
-    if (canOmitFromDynSym)
-      newSym.exportDynamic = false;
-    Symbol *ret = symtab->addSymbol(newSym);
-    ret->referenced = true;
-    return ret;
+    Undefined newSym(&f, StringRef(), binding, visibility, type);
+    sym->resolve(newSym);
+    sym->referenced = true;
+    return;
   }
 
-  if (objSym.isCommon())
-    return symtab->addSymbol(
-        CommonSymbol{&f, name, binding, visibility, STT_OBJECT,
-                     objSym.getCommonAlignment(), objSym.getCommonSize()});
-
-  Defined newSym(&f, name, binding, visibility, type, 0, 0, nullptr);
-  if (canOmitFromDynSym)
-    newSym.exportDynamic = false;
-  return symtab->addSymbol(newSym);
+  if (objSym.isCommon()) {
+    sym->resolve(CommonSymbol{&f, StringRef(), binding, visibility, STT_OBJECT,
+                              objSym.getCommonAlignment(),
+                              objSym.getCommonSize()});
+  } else {
+    Defined newSym(&f, StringRef(), binding, visibility, type, 0, 0, nullptr);
+    if (objSym.canBeOmittedFromSymbolTable())
+      newSym.exportDynamic = false;
+    sym->resolve(newSym);
+  }
 }
 
-template <class ELFT> void BitcodeFile::parse() {
-  std::vector<bool> keptComdats;
+void BitcodeFile::parse() {
   for (std::pair<StringRef, Comdat::SelectionKind> s : obj->getComdatTable()) {
     keptComdats.push_back(
         s.second == Comdat::NoDeduplicate ||
-        symtab->comdatGroups.try_emplace(CachedHashStringRef(s.first), this)
+        symtab.comdatGroups.try_emplace(CachedHashStringRef(s.first), this)
             .second);
   }
 
-  for (const lto::InputFile::Symbol &objSym : obj->symbols())
-    symbols.push_back(createBitcodeSymbol<ELFT>(keptComdats, objSym, *this));
+  if (numSymbols == 0) {
+    numSymbols = obj->symbols().size();
+    symbols = std::make_unique<Symbol *[]>(numSymbols);
+  }
+  // Process defined symbols first. See the comment in
+  // ObjFile<ELFT>::initializeSymbols.
+  for (auto [i, irSym] : llvm::enumerate(obj->symbols()))
+    if (!irSym.isUndefined())
+      createBitcodeSymbol(symbols[i], keptComdats, irSym, *this);
+  for (auto [i, irSym] : llvm::enumerate(obj->symbols()))
+    if (irSym.isUndefined())
+      createBitcodeSymbol(symbols[i], keptComdats, irSym, *this);
 
   for (auto l : obj->getDependentLibraries())
     addDependentLibrary(l, this);
 }
 
+void BitcodeFile::parseLazy() {
+  numSymbols = obj->symbols().size();
+  symbols = std::make_unique<Symbol *[]>(numSymbols);
+  for (auto [i, irSym] : llvm::enumerate(obj->symbols()))
+    if (!irSym.isUndefined()) {
+      auto *sym = symtab.insert(saver().save(irSym.getName()));
+      sym->resolve(LazyObject{*this});
+      symbols[i] = sym;
+    }
+}
+
+void BitcodeFile::postParse() {
+  for (auto [i, irSym] : llvm::enumerate(obj->symbols())) {
+    const Symbol &sym = *symbols[i];
+    if (sym.file == this || !sym.isDefined() || irSym.isUndefined() ||
+        irSym.isCommon() || irSym.isWeak())
+      continue;
+    int c = irSym.getComdatIndex();
+    if (c != -1 && !keptComdats[c])
+      continue;
+    reportDuplicate(sym, this, nullptr, 0);
+  }
+}
+
 void BinaryFile::parse() {
   ArrayRef<uint8_t> data = arrayRefFromStringRef(mb.getBuffer());
   auto *section = make<InputSection>(this, SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
@@ -1804,132 +1741,75 @@ void BinaryFile::parse() {
     if (!isAlnum(s[i]))
       s[i] = '_';
 
-  symtab->addSymbol(Defined{nullptr, saver.save(s + "_start"), STB_GLOBAL,
-                            STV_DEFAULT, STT_OBJECT, 0, 0, section});
-  symtab->addSymbol(Defined{nullptr, saver.save(s + "_end"), STB_GLOBAL,
-                            STV_DEFAULT, STT_OBJECT, data.size(), 0, section});
-  symtab->addSymbol(Defined{nullptr, saver.save(s + "_size"), STB_GLOBAL,
-                            STV_DEFAULT, STT_OBJECT, data.size(), 0, nullptr});
+  llvm::StringSaver &saver = lld::saver();
+
+  symtab.addAndCheckDuplicate(Defined{nullptr, saver.save(s + "_start"),
+                                      STB_GLOBAL, STV_DEFAULT, STT_OBJECT, 0, 0,
+                                      section});
+  symtab.addAndCheckDuplicate(Defined{nullptr, saver.save(s + "_end"),
+                                      STB_GLOBAL, STV_DEFAULT, STT_OBJECT,
+                                      data.size(), 0, section});
+  symtab.addAndCheckDuplicate(Defined{nullptr, saver.save(s + "_size"),
+                                      STB_GLOBAL, STV_DEFAULT, STT_OBJECT,
+                                      data.size(), 0, nullptr});
 }
 
-InputFile *elf::createObjectFile(MemoryBufferRef mb, StringRef archiveName,
-                                 uint64_t offsetInArchive) {
-  if (isBitcode(mb))
-    return make<BitcodeFile>(mb, archiveName, offsetInArchive);
-
+ELFFileBase *elf::createObjFile(MemoryBufferRef mb, StringRef archiveName,
+                                bool lazy) {
+  ELFFileBase *f;
   switch (getELFKind(mb, archiveName)) {
   case ELF32LEKind:
-    return make<ObjFile<ELF32LE>>(mb, archiveName);
+    f = make<ObjFile<ELF32LE>>(ELF32LEKind, mb, archiveName);
+    break;
   case ELF32BEKind:
-    return make<ObjFile<ELF32BE>>(mb, archiveName);
+    f = make<ObjFile<ELF32BE>>(ELF32BEKind, mb, archiveName);
+    break;
   case ELF64LEKind:
-    return make<ObjFile<ELF64LE>>(mb, archiveName);
+    f = make<ObjFile<ELF64LE>>(ELF64LEKind, mb, archiveName);
+    break;
   case ELF64BEKind:
-    return make<ObjFile<ELF64BE>>(mb, archiveName);
+    f = make<ObjFile<ELF64BE>>(ELF64BEKind, mb, archiveName);
+    break;
   default:
     llvm_unreachable("getELFKind");
   }
+  f->init();
+  f->lazy = lazy;
+  return f;
 }
 
-void LazyObjFile::fetch() {
-  if (fetched)
-    return;
-  fetched = true;
-
-  InputFile *file = createObjectFile(mb, archiveName, offsetInArchive);
-  file->groupId = groupId;
-
-  // Copy symbol vector so that the new InputFile doesn't have to
-  // insert the same defined symbols to the symbol table again.
-  file->symbols = std::move(symbols);
-
-  parseFile(file);
-}
-
-template <class ELFT> void LazyObjFile::parse() {
-  using Elf_Sym = typename ELFT::Sym;
-
-  // A lazy object file wraps either a bitcode file or an ELF file.
-  if (isBitcode(this->mb)) {
-    std::unique_ptr<lto::InputFile> obj =
-        CHECK(lto::InputFile::create(this->mb), this);
-    for (const lto::InputFile::Symbol &sym : obj->symbols()) {
-      if (sym.isUndefined())
-        continue;
-      symtab->addSymbol(LazyObject{*this, saver.save(sym.getName())});
-    }
-    return;
-  }
-
-  if (getELFKind(this->mb, archiveName) != config->ekind) {
-    error("incompatible file: " + this->mb.getBufferIdentifier());
-    return;
-  }
-
-  // Find a symbol table.
-  ELFFile<ELFT> obj = check(ELFFile<ELFT>::create(mb.getBuffer()));
-  ArrayRef<typename ELFT::Shdr> sections = CHECK(obj.sections(), this);
+template <class ELFT> void ObjFile<ELFT>::parseLazy() {
+  const ArrayRef<typename ELFT::Sym> eSyms = this->getELFSyms<ELFT>();
+  numSymbols = eSyms.size();
+  symbols = std::make_unique<Symbol *[]>(numSymbols);
 
-  for (const typename ELFT::Shdr &sec : sections) {
-    if (sec.sh_type != SHT_SYMTAB)
+  // resolve() may trigger this->extract() if an existing symbol is an undefined
+  // symbol. If that happens, this function has served its purpose, and we can
+  // exit from the loop early.
+  for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i) {
+    if (eSyms[i].st_shndx == SHN_UNDEF)
       continue;
-
-    // A symbol table is found.
-    ArrayRef<Elf_Sym> eSyms = CHECK(obj.symbols(&sec), this);
-    uint32_t firstGlobal = sec.sh_info;
-    StringRef strtab = CHECK(obj.getStringTableForSymtab(sec, sections), this);
-    this->symbols.resize(eSyms.size());
-
-    // Get existing symbols or insert placeholder symbols.
-    for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i)
-      if (eSyms[i].st_shndx != SHN_UNDEF)
-        this->symbols[i] = symtab->insert(CHECK(eSyms[i].getName(strtab), this));
-
-    // Replace existing symbols with LazyObject symbols.
-    //
-    // resolve() may trigger this->fetch() if an existing symbol is an
-    // undefined symbol. If that happens, this LazyObjFile has served
-    // its purpose, and we can exit from the loop early.
-    for (Symbol *sym : this->symbols) {
-      if (!sym)
-        continue;
-      sym->resolve(LazyObject{*this, sym->getName()});
-
-      // If fetched, stop iterating because this->symbols has been transferred
-      // to the instantiated ObjFile.
-      if (fetched)
-        return;
-    }
-    return;
+    symbols[i] = symtab.insert(CHECK(eSyms[i].getName(stringTable), this));
+    symbols[i]->resolve(LazyObject{*this});
+    if (!lazy)
+      break;
   }
 }
 
-bool LazyObjFile::shouldFetchForCommon(const StringRef &name) {
-  if (isBitcode(mb))
+bool InputFile::shouldExtractForCommon(StringRef name) {
+  if (isa<BitcodeFile>(this))
     return isBitcodeNonCommonDef(mb, name, archiveName);
 
   return isNonCommonDef(mb, name, archiveName);
 }
 
 std::string elf::replaceThinLTOSuffix(StringRef path) {
-  StringRef suffix = config->thinLTOObjectSuffixReplace.first;
-  StringRef repl = config->thinLTOObjectSuffixReplace.second;
-
+  auto [suffix, repl] = config->thinLTOObjectSuffixReplace;
   if (path.consume_back(suffix))
     return (path + repl).str();
   return std::string(path);
 }
 
-template void BitcodeFile::parse<ELF32LE>();
-template void BitcodeFile::parse<ELF32BE>();
-template void BitcodeFile::parse<ELF64LE>();
-template void BitcodeFile::parse<ELF64BE>();
-
-template void LazyObjFile::parse<ELF32LE>();
-template void LazyObjFile::parse<ELF32BE>();
-template void LazyObjFile::parse<ELF64LE>();
-template void LazyObjFile::parse<ELF64BE>();
-
 template class elf::ObjFile<ELF32LE>;
 template class elf::ObjFile<ELF32BE>;
 template class elf::ObjFile<ELF64LE>;
index 4d64a65..273885e 100644 (file)
 #define LLD_ELF_INPUT_FILES_H
 
 #include "Config.h"
+#include "Symbols.h"
 #include "lld/Common/ErrorHandler.h"
 #include "lld/Common/LLVM.h"
 #include "lld/Common/Reproduce.h"
-#include "llvm/ADT/CachedHashString.h"
 #include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/IR/Comdat.h"
-#include "llvm/Object/Archive.h"
+#include "llvm/BinaryFormat/Magic.h"
 #include "llvm/Object/ELF.h"
-#include "llvm/Object/IRObjectFile.h"
+#include "llvm/Support/MemoryBufferRef.h"
 #include "llvm/Support/Threading.h"
-#include <map>
 
 namespace llvm {
 struct DILineInfo;
@@ -41,27 +38,29 @@ void parseGNUWarning(StringRef name, ArrayRef<char> data, size_t size);
 
 namespace elf {
 
-using llvm::object::Archive;
-
+class InputSection;
 class Symbol;
 
-// If -reproduce option is given, all input files are written
-// to this tar archive.
+// If --reproduce is specified, all input files are written to this tar archive.
 extern std::unique_ptr<llvm::TarWriter> tar;
 
 // Opens a given file.
-llvm::Optional<MemoryBufferRef> readFile(StringRef path);
+std::optional<MemoryBufferRef> readFile(StringRef path);
 
 // Add symbols in File to the symbol table.
 void parseFile(InputFile *file);
 
 // The root class of input files.
 class InputFile {
+protected:
+  std::unique_ptr<Symbol *[]> symbols;
+  uint32_t numSymbols = 0;
+  SmallVector<InputSectionBase *, 0> sections;
+
 public:
-  enum Kind {
+  enum Kind : uint8_t {
     ObjKind,
     SharedKind,
-    LazyObjKind,
     ArchiveKind,
     BitcodeKind,
     BinaryKind,
@@ -86,40 +85,51 @@ public:
 
   // Returns object file symbols. It is a runtime error to call this
   // function on files of other types.
-  ArrayRef<Symbol *> getSymbols() { return getMutableSymbols(); }
-
-  MutableArrayRef<Symbol *> getMutableSymbols() {
+  ArrayRef<Symbol *> getSymbols() const {
     assert(fileKind == BinaryKind || fileKind == ObjKind ||
            fileKind == BitcodeKind);
-    return symbols;
+    return {symbols.get(), numSymbols};
   }
 
   // Get filename to use for linker script processing.
   StringRef getNameForScript() const;
 
-  // If not empty, this stores the name of the archive containing this file.
-  // We use this string for creating error messages.
-  std::string archiveName;
+  // Check if a non-common symbol should be extracted to override a common
+  // definition.
+  bool shouldExtractForCommon(StringRef name);
+
+  // .got2 in the current file. This is used by PPC32 -fPIC/-fPIE to compute
+  // offsets in PLT call stubs.
+  InputSection *ppc32Got2 = nullptr;
+
+  // Index of MIPS GOT built for this file.
+  uint32_t mipsGotIndex = -1;
+
+  // groupId is used for --warn-backrefs which is an optional error
+  // checking feature. All files within the same --{start,end}-group or
+  // --{start,end}-lib get the same group ID. Otherwise, each file gets a new
+  // group ID. For more info, see checkDependency() in SymbolTable.cpp.
+  uint32_t groupId;
+  static bool isInGroup;
+  static uint32_t nextGroupId;
 
   // If this is an architecture-specific file, the following members
   // have ELF type (i.e. ELF{32,64}{LE,BE}) and target machine type.
-  ELFKind ekind = ELFNoneKind;
   uint16_t emachine = llvm::ELF::EM_NONE;
+  const Kind fileKind;
+  ELFKind ekind = ELFNoneKind;
   uint8_t osabi = 0;
   uint8_t abiVersion = 0;
 
-  // Cache for toString(). Only toString() should use this member.
-  mutable std::string toStringCache;
-
-  std::string getSrcMsg(const Symbol &sym, InputSectionBase &sec,
-                        uint64_t offset);
+  // True if this is a relocatable object file/bitcode file between --start-lib
+  // and --end-lib.
+  bool lazy = false;
 
   // True if this is an argument for --just-symbols. Usually false.
   bool justSymbols = false;
 
-  // outSecOff of .got2 in the current file. This is used by PPC32 -fPIC/-fPIE
-  // to compute offsets in PLT call stubs.
-  uint32_t ppc32Got2OutSecOff = 0;
+  std::string getSrcMsg(const Symbol &sym, InputSectionBase &sec,
+                        uint64_t offset);
 
   // On PPC64 we need to keep track of which files contain small code model
   // relocations that access the .toc section. To minimize the chance of a
@@ -136,41 +146,51 @@ public:
   // R_PPC64_TLSLD. Disable TLS relaxation to avoid bad code generation.
   bool ppc64DisableTLSRelax = false;
 
-  // groupId is used for --warn-backrefs which is an optional error
-  // checking feature. All files within the same --{start,end}-group or
-  // --{start,end}-lib get the same group ID. Otherwise, each file gets a new
-  // group ID. For more info, see checkDependency() in SymbolTable.cpp.
-  uint32_t groupId;
-  static bool isInGroup;
-  static uint32_t nextGroupId;
-
-  // Index of MIPS GOT built for this file.
-  llvm::Optional<size_t> mipsGotIndex;
-
-  std::vector<Symbol *> symbols;
-
 protected:
   InputFile(Kind k, MemoryBufferRef m);
-  std::vector<InputSectionBase *> sections;
 
-private:
-  const Kind fileKind;
+public:
+  // If not empty, this stores the name of the archive containing this file.
+  // We use this string for creating error messages.
+  SmallString<0> archiveName;
+  // Cache for toString(). Only toString() should use this member.
+  mutable SmallString<0> toStringCache;
 
+private:
   // Cache for getNameForScript().
-  mutable std::string nameForScriptCache;
+  mutable SmallString<0> nameForScriptCache;
 };
 
 class ELFFileBase : public InputFile {
 public:
-  ELFFileBase(Kind k, MemoryBufferRef m);
+  ELFFileBase(Kind k, ELFKind ekind, MemoryBufferRef m);
   static bool classof(const InputFile *f) { return f->isElf(); }
 
+  void init();
   template <typename ELFT> llvm::object::ELFFile<ELFT> getObj() const {
     return check(llvm::object::ELFFile<ELFT>::create(mb.getBuffer()));
   }
 
   StringRef getStringTable() const { return stringTable; }
 
+  ArrayRef<Symbol *> getLocalSymbols() {
+    if (numSymbols == 0)
+      return {};
+    return llvm::ArrayRef(symbols.get() + 1, firstGlobal - 1);
+  }
+  ArrayRef<Symbol *> getGlobalSymbols() {
+    return llvm::ArrayRef(symbols.get() + firstGlobal,
+                          numSymbols - firstGlobal);
+  }
+  MutableArrayRef<Symbol *> getMutableGlobalSymbols() {
+    return llvm::MutableArrayRef(symbols.get() + firstGlobal,
+                                     numSymbols - firstGlobal);
+  }
+
+  template <typename ELFT> typename ELFT::ShdrRange getELFShdrs() const {
+    return typename ELFT::ShdrRange(
+        reinterpret_cast<const typename ELFT::Shdr *>(elfShdrs), numELFShdrs);
+  }
   template <typename ELFT> typename ELFT::SymRange getELFSyms() const {
     return typename ELFT::SymRange(
         reinterpret_cast<const typename ELFT::Sym *>(elfSyms), numELFSyms);
@@ -181,12 +201,18 @@ public:
 
 protected:
   // Initializes this class's member variables.
-  template <typename ELFT> void init();
+  template <typename ELFT> void init(InputFile::Kind k);
 
+  StringRef stringTable;
+  const void *elfShdrs = nullptr;
   const void *elfSyms = nullptr;
-  size_t numELFSyms = 0;
+  uint32_t numELFShdrs = 0;
+  uint32_t numELFSyms = 0;
   uint32_t firstGlobal = 0;
-  StringRef stringTable;
+
+public:
+  uint32_t andFeatures = 0;
+  bool hasCommonSyms = false;
 };
 
 // .o file.
@@ -200,20 +226,19 @@ public:
     return this->ELFFileBase::getObj<ELFT>();
   }
 
-  ArrayRef<Symbol *> getLocalSymbols();
-  ArrayRef<Symbol *> getGlobalSymbols();
-
-  ObjFile(MemoryBufferRef m, StringRef archiveName) : ELFFileBase(ObjKind, m) {
-    this->archiveName = std::string(archiveName);
+  ObjFile(ELFKind ekind, MemoryBufferRef m, StringRef archiveName)
+      : ELFFileBase(ObjKind, ekind, m) {
+    this->archiveName = archiveName;
   }
 
   void parse(bool ignoreComdats = false);
+  void parseLazy();
 
   StringRef getShtGroupSignature(ArrayRef<Elf_Shdr> sections,
                                  const Elf_Shdr &sec);
 
   Symbol &getSymbol(uint32_t symbolIndex) const {
-    if (symbolIndex >= this->symbols.size())
+    if (symbolIndex >= numSymbols)
       fatal(toString(this) + ": invalid symbol index");
     return *this->symbols[symbolIndex];
   }
@@ -225,21 +250,26 @@ public:
     return getSymbol(symIndex);
   }
 
-  llvm::Optional<llvm::DILineInfo> getDILineInfo(InputSectionBase *, uint64_t);
-  llvm::Optional<std::pair<std::string, unsigned>> getVariableLoc(StringRef name);
-
-  // MIPS GP0 value defined by this file. This value represents the gp value
-  // used to create the relocatable object and required to support
-  // R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations.
-  uint32_t mipsGp0 = 0;
-
-  uint32_t andFeatures = 0;
+  std::optional<llvm::DILineInfo> getDILineInfo(InputSectionBase *, uint64_t);
+  std::optional<std::pair<std::string, unsigned>>
+  getVariableLoc(StringRef name);
 
   // Name of source file obtained from STT_FILE symbol value,
   // or empty string if there is no such symbol in object file
   // symbol table.
   StringRef sourceFile;
 
+  // Pointer to this input file's .llvm_addrsig section, if it has one.
+  const Elf_Shdr *addrsigSec = nullptr;
+
+  // SHT_LLVM_CALL_GRAPH_PROFILE section index.
+  uint32_t cgProfileSectionIndex = 0;
+
+  // MIPS GP0 value defined by this file. This value represents the gp value
+  // used to create the relocatable object and required to support
+  // R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations.
+  uint32_t mipsGp0 = 0;
+
   // True if the file defines functions compiled with
   // -fsplit-stack. Usually false.
   bool splitStack = false;
@@ -248,23 +278,22 @@ public:
   // but had one or more functions with the no_split_stack attribute.
   bool someNoSplitStack = false;
 
-  // Pointer to this input file's .llvm_addrsig section, if it has one.
-  const Elf_Shdr *addrsigSec = nullptr;
-
-  // SHT_LLVM_CALL_GRAPH_PROFILE section index.
-  uint32_t cgProfileSectionIndex = 0;
-
   // Get cached DWARF information.
   DWARFCache *getDwarf();
 
+  void initSectionsAndLocalSyms(bool ignoreComdats);
+  void postParse();
+
 private:
-  void initializeSections(bool ignoreComdats);
-  void initializeSymbols();
+  void initializeSections(bool ignoreComdats,
+                          const llvm::object::ELFFile<ELFT> &obj);
+  void initializeSymbols(const llvm::object::ELFFile<ELFT> &obj);
   void initializeJustSymbols();
 
-  InputSectionBase *getRelocTarget(const Elf_Shdr &sec);
-  InputSectionBase *createInputSection(const Elf_Shdr &sec);
-  StringRef getSectionName(const Elf_Shdr &sec);
+  InputSectionBase *getRelocTarget(uint32_t idx, const Elf_Shdr &sec,
+                                   uint32_t info);
+  InputSectionBase *createInputSection(uint32_t idx, const Elf_Shdr &sec,
+                                       StringRef name);
 
   bool shouldMerge(const Elf_Shdr &sec, StringRef name);
 
@@ -282,9 +311,6 @@ private:
   // If the section does not exist (which is common), the array is empty.
   ArrayRef<Elf_Word> shndxTable;
 
-  // .shstrtab contents.
-  StringRef sectionStringTable;
-
   // Debugging information to retrieve source file and line for error
   // reporting. Linker may find reasonable number of errors in a
   // single object file, so we cache debugging information in order to
@@ -293,91 +319,35 @@ private:
   llvm::once_flag initDwarf;
 };
 
-// LazyObjFile is analogous to ArchiveFile in the sense that
-// the file contains lazy symbols. The difference is that
-// LazyObjFile wraps a single file instead of multiple files.
-//
-// This class is used for --start-lib and --end-lib options which
-// instruct the linker to link object files between them with the
-// archive file semantics.
-class LazyObjFile : public InputFile {
-public:
-  LazyObjFile(MemoryBufferRef m, StringRef archiveName,
-              uint64_t offsetInArchive)
-      : InputFile(LazyObjKind, m), offsetInArchive(offsetInArchive) {
-    this->archiveName = std::string(archiveName);
-  }
-
-  static bool classof(const InputFile *f) { return f->kind() == LazyObjKind; }
-
-  template <class ELFT> void parse();
-  void fetch();
-
-  // Check if a non-common symbol should be fetched to override a common
-  // definition.
-  bool shouldFetchForCommon(const StringRef &name);
-
-  bool fetched = false;
-
-private:
-  uint64_t offsetInArchive;
-};
-
-// An ArchiveFile object represents a .a file.
-class ArchiveFile : public InputFile {
-public:
-  explicit ArchiveFile(std::unique_ptr<Archive> &&file);
-  static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; }
-  void parse();
-
-  // Pulls out an object file that contains a definition for Sym and
-  // returns it. If the same file was instantiated before, this
-  // function does nothing (so we don't instantiate the same file
-  // more than once.)
-  void fetch(const Archive::Symbol &sym);
-
-  // Check if a non-common symbol should be fetched to override a common
-  // definition.
-  bool shouldFetchForCommon(const Archive::Symbol &sym);
-
-  size_t getMemberCount() const;
-  size_t getFetchedMemberCount() const { return seen.size(); }
-
-  bool parsed = false;
-
-private:
-  std::unique_ptr<Archive> file;
-  llvm::DenseSet<uint64_t> seen;
-};
-
 class BitcodeFile : public InputFile {
 public:
   BitcodeFile(MemoryBufferRef m, StringRef archiveName,
-              uint64_t offsetInArchive);
+              uint64_t offsetInArchive, bool lazy);
   static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; }
-  template <class ELFT> void parse();
+  void parse();
+  void parseLazy();
+  void postParse();
   std::unique_ptr<llvm::lto::InputFile> obj;
+  std::vector<bool> keptComdats;
 };
 
 // .so file.
 class SharedFile : public ELFFileBase {
 public:
-  SharedFile(MemoryBufferRef m, StringRef defaultSoName)
-      : ELFFileBase(SharedKind, m), soName(std::string(defaultSoName)),
-        isNeeded(!config->asNeeded) {}
+  SharedFile(MemoryBufferRef m, StringRef defaultSoName);
 
   // This is actually a vector of Elf_Verdef pointers.
-  std::vector<const void *> verdefs;
+  SmallVector<const void *, 0> verdefs;
 
   // If the output file needs Elf_Verneed data structures for this file, this is
   // a vector of Elf_Vernaux version identifiers that map onto the entries in
   // Verdefs, otherwise it is empty.
-  std::vector<unsigned> vernauxs;
+  SmallVector<uint32_t, 0> vernauxs;
 
   static unsigned vernauxNum;
 
-  std::vector<StringRef> dtNeeded;
-  std::string soName;
+  SmallVector<StringRef, 0> dtNeeded;
+  StringRef soName;
 
   static bool classof(const InputFile *f) { return f->kind() == SharedKind; }
 
@@ -388,7 +358,7 @@ public:
 
   // Non-weak undefined symbols which are not yet resolved when the SO is
   // parsed. Only filled for `--no-allow-shlib-undefined`.
-  std::vector<Symbol *> requiredSymbols;
+  SmallVector<Symbol *, 0> requiredSymbols;
 
 private:
   template <typename ELFT>
@@ -403,22 +373,11 @@ public:
   void parse();
 };
 
-InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName = "",
-                            uint64_t offsetInArchive = 0);
-
-inline bool isBitcode(MemoryBufferRef mb) {
-  return identify_magic(mb.getBuffer()) == llvm::file_magic::bitcode;
-}
+ELFFileBase *createObjFile(MemoryBufferRef mb, StringRef archiveName = "",
+                           bool lazy = false);
 
 std::string replaceThinLTOSuffix(StringRef path);
 
-extern std::vector<ArchiveFile *> archiveFiles;
-extern std::vector<BinaryFile *> binaryFiles;
-extern std::vector<BitcodeFile *> bitcodeFiles;
-extern std::vector<LazyObjFile *> lazyObjFiles;
-extern std::vector<InputFile *> objectFiles;
-extern std::vector<SharedFile *> sharedFiles;
-
 } // namespace elf
 } // namespace lld
 
index 7d952e9..df24f99 100644 (file)
@@ -8,27 +8,20 @@
 
 #include "InputSection.h"
 #include "Config.h"
-#include "EhFrame.h"
 #include "InputFiles.h"
-#include "LinkerScript.h"
 #include "OutputSections.h"
 #include "Relocations.h"
 #include "SymbolTable.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
 #include "Target.h"
-#include "Thunks.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Compression.h"
 #include "llvm/Support/Endian.h"
-#include "llvm/Support/Threading.h"
 #include "llvm/Support/xxhash.h"
 #include <algorithm>
 #include <mutex>
-#include <set>
-#include <unordered_set>
 #include <vector>
 
 using namespace llvm;
@@ -40,7 +33,6 @@ using namespace llvm::sys;
 using namespace lld;
 using namespace lld::elf;
 
-std::vector<InputSectionBase *> elf::inputSections;
 DenseSet<std::pair<const Symbol *, uint64_t>> elf::ppc64noTocRelax;
 
 // Returns a string to construct an error message.
@@ -52,59 +44,35 @@ template <class ELFT>
 static ArrayRef<uint8_t> getSectionContents(ObjFile<ELFT> &file,
                                             const typename ELFT::Shdr &hdr) {
   if (hdr.sh_type == SHT_NOBITS)
-    return makeArrayRef<uint8_t>(nullptr, hdr.sh_size);
+    return ArrayRef<uint8_t>(nullptr, hdr.sh_size);
   return check(file.getObj().getSectionContents(hdr));
 }
 
 InputSectionBase::InputSectionBase(InputFile *file, uint64_t flags,
                                    uint32_t type, uint64_t entsize,
                                    uint32_t link, uint32_t info,
-                                   uint32_t alignment, ArrayRef<uint8_t> data,
+                                   uint32_t addralign, ArrayRef<uint8_t> data,
                                    StringRef name, Kind sectionKind)
-    : SectionBase(sectionKind, name, flags, entsize, alignment, type, info,
+    : SectionBase(sectionKind, name, flags, entsize, addralign, type, info,
                   link),
-      file(file), rawData(data) {
+      file(file), content_(data.data()), size(data.size()) {
   // In order to reduce memory allocation, we assume that mergeable
   // sections are smaller than 4 GiB, which is not an unreasonable
   // assumption as of 2017.
-  if (sectionKind == SectionBase::Merge && rawData.size() > UINT32_MAX)
+  if (sectionKind == SectionBase::Merge && content().size() > UINT32_MAX)
     error(toString(this) + ": section too large");
 
-  numRelocations = 0;
-  areRelocsRela = false;
-
   // The ELF spec states that a value of 0 means the section has
   // no alignment constraints.
-  uint32_t v = std::max<uint32_t>(alignment, 1);
+  uint32_t v = std::max<uint32_t>(addralign, 1);
   if (!isPowerOf2_64(v))
     fatal(toString(this) + ": sh_addralign is not a power of 2");
-  this->alignment = v;
-
-  // In ELF, each section can be compressed by zlib, and if compressed,
-  // section name may be mangled by appending "z" (e.g. ".zdebug_info").
-  // If that's the case, demangle section name so that we can handle a
-  // section as if it weren't compressed.
-  if ((flags & SHF_COMPRESSED) || name.startswith(".zdebug")) {
-    if (!zlib::isAvailable())
-      error(toString(file) + ": contains a compressed section, " +
-            "but zlib is not available");
-    switch (config->ekind) {
-    case ELF32LEKind:
-      parseCompressedHeader<ELF32LE>();
-      break;
-    case ELF32BEKind:
-      parseCompressedHeader<ELF32BE>();
-      break;
-    case ELF64LEKind:
-      parseCompressedHeader<ELF64LE>();
-      break;
-    case ELF64BEKind:
-      parseCompressedHeader<ELF64BE>();
-      break;
-    default:
-      llvm_unreachable("unknown ELFT");
-    }
-  }
+  this->addralign = v;
+
+  // If SHF_COMPRESSED is set, parse the header. The legacy .zdebug format is no
+  // longer supported.
+  if (flags & SHF_COMPRESSED)
+    invokeELFT(parseCompressedHeader);
 }
 
 // Drop SHF_GROUP bit unless we are producing a re-linkable object file.
@@ -117,32 +85,14 @@ static uint64_t getFlags(uint64_t flags) {
   return flags;
 }
 
-// GNU assembler 2.24 and LLVM 4.0.0's MC (the newest release as of
-// March 2017) fail to infer section types for sections starting with
-// ".init_array." or ".fini_array.". They set SHT_PROGBITS instead of
-// SHF_INIT_ARRAY. As a result, the following assembler directive
-// creates ".init_array.100" with SHT_PROGBITS, for example.
-//
-//   .section .init_array.100, "aw"
-//
-// This function forces SHT_{INIT,FINI}_ARRAY so that we can handle
-// incorrect inputs as if they were correct from the beginning.
-static uint64_t getType(uint64_t type, StringRef name) {
-  if (type == SHT_PROGBITS && name.startswith(".init_array."))
-    return SHT_INIT_ARRAY;
-  if (type == SHT_PROGBITS && name.startswith(".fini_array."))
-    return SHT_FINI_ARRAY;
-  return type;
-}
-
 template <class ELFT>
 InputSectionBase::InputSectionBase(ObjFile<ELFT> &file,
                                    const typename ELFT::Shdr &hdr,
                                    StringRef name, Kind sectionKind)
-    : InputSectionBase(&file, getFlags(hdr.sh_flags),
-                       getType(hdr.sh_type, name), hdr.sh_entsize, hdr.sh_link,
-                       hdr.sh_info, hdr.sh_addralign,
-                       getSectionContents(file, hdr), name, sectionKind) {
+    : InputSectionBase(&file, getFlags(hdr.sh_flags), hdr.sh_type,
+                       hdr.sh_entsize, hdr.sh_link, hdr.sh_info,
+                       hdr.sh_addralign, getSectionContents(file, hdr), name,
+                       sectionKind) {
   // We reject object files having insanely large alignments even though
   // they are allowed by the spec. I think 4GB is a reasonable limitation.
   // We might want to relax this in the future.
@@ -153,31 +103,52 @@ InputSectionBase::InputSectionBase(ObjFile<ELFT> &file,
 size_t InputSectionBase::getSize() const {
   if (auto *s = dyn_cast<SyntheticSection>(this))
     return s->getSize();
-  if (uncompressedSize >= 0)
-    return uncompressedSize;
-  return rawData.size() - bytesDropped;
+  return size - bytesDropped;
 }
 
-void InputSectionBase::uncompress() const {
-  size_t size = uncompressedSize;
-  char *uncompressedBuf;
+template <class ELFT>
+static void decompressAux(const InputSectionBase &sec, uint8_t *out,
+                          size_t size) {
+  auto *hdr = reinterpret_cast<const typename ELFT::Chdr *>(sec.content_);
+  auto compressed = ArrayRef<uint8_t>(sec.content_, sec.compressedSize)
+                        .slice(sizeof(typename ELFT::Chdr));
+  if (Error e = hdr->ch_type == ELFCOMPRESS_ZLIB
+                    ? compression::zlib::decompress(compressed, out, size)
+                    : compression::zstd::decompress(compressed, out, size))
+    fatal(toString(&sec) +
+          ": decompress failed: " + llvm::toString(std::move(e)));
+}
+
+void InputSectionBase::decompress() const {
+  uint8_t *uncompressedBuf;
   {
     static std::mutex mu;
     std::lock_guard<std::mutex> lock(mu);
-    uncompressedBuf = bAlloc.Allocate<char>(size);
+    uncompressedBuf = bAlloc().Allocate<uint8_t>(size);
   }
 
-  if (Error e = zlib::uncompress(toStringRef(rawData), uncompressedBuf, size))
-    fatal(toString(this) +
-          ": uncompress failed: " + llvm::toString(std::move(e)));
-  rawData = makeArrayRef((uint8_t *)uncompressedBuf, size);
-  uncompressedSize = -1;
+  invokeELFT(decompressAux, *this, uncompressedBuf, size);
+  content_ = uncompressedBuf;
+  compressed = false;
 }
 
-uint64_t InputSectionBase::getOffsetInFile() const {
-  const uint8_t *fileStart = (const uint8_t *)file->mb.getBufferStart();
-  const uint8_t *secStart = data().begin();
-  return secStart - fileStart;
+template <class ELFT> RelsOrRelas<ELFT> InputSectionBase::relsOrRelas() const {
+  if (relSecIdx == 0)
+    return {};
+  RelsOrRelas<ELFT> ret;
+  typename ELFT::Shdr shdr =
+      cast<ELFFileBase>(file)->getELFShdrs<ELFT>()[relSecIdx];
+  if (shdr.sh_type == SHT_REL) {
+    ret.rels = ArrayRef(reinterpret_cast<const typename ELFT::Rel *>(
+                            file->mb.getBufferStart() + shdr.sh_offset),
+                        shdr.sh_size / sizeof(typename ELFT::Rel));
+  } else {
+    assert(shdr.sh_type == SHT_RELA);
+    ret.relas = ArrayRef(reinterpret_cast<const typename ELFT::Rela *>(
+                             file->mb.getBufferStart() + shdr.sh_offset),
+                         shdr.sh_size / sizeof(typename ELFT::Rela));
+  }
+  return ret;
 }
 
 uint64_t SectionBase::getOffset(uint64_t offset) const {
@@ -189,16 +160,24 @@ uint64_t SectionBase::getOffset(uint64_t offset) const {
   }
   case Regular:
   case Synthetic:
-    return cast<InputSection>(this)->getOffset(offset);
-  case EHFrame:
-    // The file crtbeginT.o has relocations pointing to the start of an empty
-    // .eh_frame that is known to be the first in the link. It does that to
-    // identify the start of the output .eh_frame.
+    return cast<InputSection>(this)->outSecOff + offset;
+  case EHFrame: {
+    // Two code paths may reach here. First, clang_rt.crtbegin.o and GCC
+    // crtbeginT.o may reference the start of an empty .eh_frame to identify the
+    // start of the output .eh_frame. Just return offset.
+    //
+    // Second, InputSection::copyRelocations on .eh_frame. Some pieces may be
+    // discarded due to GC/ICF. We should compute the output section offset.
+    const EhInputSection *es = cast<EhInputSection>(this);
+    if (!es->content().empty())
+      if (InputSection *isec = es->getParent())
+        return isec->outSecOff + es->getParentOffset(offset);
     return offset;
+  }
   case Merge:
     const MergeInputSection *ms = cast<MergeInputSection>(this);
     if (InputSection *isec = ms->getParent())
-      return isec->getOffset(ms->getParentOffset(offset));
+      return isec->outSecOff + ms->getParentOffset(offset);
     return ms->getParentOffset(offset);
   }
   llvm_unreachable("invalid section kind");
@@ -226,46 +205,33 @@ OutputSection *SectionBase::getOutputSection() {
 // by zlib-compressed data. This function parses a header to initialize
 // `uncompressedSize` member and remove the header from `rawData`.
 template <typename ELFT> void InputSectionBase::parseCompressedHeader() {
-  // Old-style header
-  if (name.startswith(".zdebug")) {
-    if (!toStringRef(rawData).startswith("ZLIB")) {
-      error(toString(this) + ": corrupted compressed section header");
-      return;
-    }
-    rawData = rawData.slice(4);
-
-    if (rawData.size() < 8) {
-      error(toString(this) + ": corrupted compressed section header");
-      return;
-    }
-
-    uncompressedSize = read64be(rawData.data());
-    rawData = rawData.slice(8);
-
-    // Restore the original section name.
-    // (e.g. ".zdebug_info" -> ".debug_info")
-    name = saver.save("." + name.substr(2));
-    return;
-  }
-
-  assert(flags & SHF_COMPRESSED);
   flags &= ~(uint64_t)SHF_COMPRESSED;
 
   // New-style header
-  if (rawData.size() < sizeof(typename ELFT::Chdr)) {
+  if (content().size() < sizeof(typename ELFT::Chdr)) {
     error(toString(this) + ": corrupted compressed section");
     return;
   }
 
-  auto *hdr = reinterpret_cast<const typename ELFT::Chdr *>(rawData.data());
-  if (hdr->ch_type != ELFCOMPRESS_ZLIB) {
-    error(toString(this) + ": unsupported compression type");
+  auto *hdr = reinterpret_cast<const typename ELFT::Chdr *>(content().data());
+  if (hdr->ch_type == ELFCOMPRESS_ZLIB) {
+    if (!compression::zlib::isAvailable())
+      error(toString(this) + " is compressed with ELFCOMPRESS_ZLIB, but lld is "
+                             "not built with zlib support");
+  } else if (hdr->ch_type == ELFCOMPRESS_ZSTD) {
+    if (!compression::zstd::isAvailable())
+      error(toString(this) + " is compressed with ELFCOMPRESS_ZSTD, but lld is "
+                             "not built with zstd support");
+  } else {
+    error(toString(this) + ": unsupported compression type (" +
+          Twine(hdr->ch_type) + ")");
     return;
   }
 
-  uncompressedSize = hdr->ch_size;
-  alignment = std::max<uint32_t>(hdr->ch_addralign, 1);
-  rawData = rawData.slice(sizeof(*hdr));
+  compressed = true;
+  compressedSize = size;
+  size = hdr->ch_size;
+  addralign = std::max<uint32_t>(hdr->ch_addralign, 1);
 }
 
 InputSection *InputSectionBase::getLinkOrderDep() const {
@@ -276,7 +242,6 @@ InputSection *InputSectionBase::getLinkOrderDep() const {
 }
 
 // Find a function symbol that encloses a given location.
-template <class ELFT>
 Defined *InputSectionBase::getEnclosingFunction(uint64_t offset) {
   for (Symbol *b : file->getSymbols())
     if (Defined *d = dyn_cast<Defined>(b))
@@ -286,32 +251,20 @@ Defined *InputSectionBase::getEnclosingFunction(uint64_t offset) {
   return nullptr;
 }
 
-// Returns a source location string. Used to construct an error message.
-template <class ELFT>
+// Returns an object file location string. Used to construct an error message.
 std::string InputSectionBase::getLocation(uint64_t offset) {
-  std::string secAndOffset = (name + "+0x" + utohexstr(offset)).str();
+  std::string secAndOffset =
+      (name + "+0x" + Twine::utohexstr(offset) + ")").str();
 
   // We don't have file for synthetic sections.
-  if (getFile<ELFT>() == nullptr)
-    return (config->outputFile + ":(" + secAndOffset + ")")
-        .str();
-
-  // First check if we can get desired values from debugging information.
-  if (Optional<DILineInfo> info = getFile<ELFT>()->getDILineInfo(this, offset))
-    return info->FileName + ":" + std::to_string(info->Line) + ":(" +
-           secAndOffset + ")";
-
-  // File->sourceFile contains STT_FILE symbol that contains a
-  // source file name. If it's missing, we use an object file name.
-  std::string srcFile = std::string(getFile<ELFT>()->sourceFile);
-  if (srcFile.empty())
-    srcFile = toString(file);
+  if (file == nullptr)
+    return (config->outputFile + ":(" + secAndOffset).str();
 
-  if (Defined *d = getEnclosingFunction<ELFT>(offset))
-    return srcFile + ":(function " + toString(*d) + ": " + secAndOffset + ")";
+  std::string filename = toString(file);
+  if (Defined *d = getEnclosingFunction(offset))
+    return filename + ":(function " + toString(*d) + ": " + secAndOffset;
 
-  // If there's no symbol, print out the offset in the section.
-  return (srcFile + ":(" + secAndOffset + ")");
+  return filename + ":(" + secAndOffset;
 }
 
 // This function is intended to be used for constructing an error message.
@@ -338,11 +291,13 @@ std::string InputSectionBase::getObjMsg(uint64_t off) {
 
   std::string archive;
   if (!file->archiveName.empty())
-    archive = " in archive " + file->archiveName;
+    archive = (" in archive " + file->archiveName).str();
 
-  // Find a symbol that encloses a given location.
+  // Find a symbol that encloses a given location. getObjMsg may be called
+  // before ObjFile::initSectionsAndLocalSyms where local symbols are
+  // initialized.
   for (Symbol *b : file->getSymbols())
-    if (auto *d = dyn_cast<Defined>(b))
+    if (auto *d = dyn_cast_or_null<Defined>(b))
       if (d->section == this && d->value <= off && off < d->value + d->size)
         return filename + ":(" + toString(*d) + ")" + archive;
 
@@ -354,10 +309,10 @@ std::string InputSectionBase::getObjMsg(uint64_t off) {
 InputSection InputSection::discarded(nullptr, 0, 0, 0, ArrayRef<uint8_t>(), "");
 
 InputSection::InputSection(InputFile *f, uint64_t flags, uint32_t type,
-                           uint32_t alignment, ArrayRef<uint8_t> data,
+                           uint32_t addralign, ArrayRef<uint8_t> data,
                            StringRef name, Kind k)
     : InputSectionBase(f, flags, type,
-                       /*Entsize*/ 0, /*Link*/ 0, /*Info*/ 0, alignment, data,
+                       /*Entsize*/ 0, /*Link*/ 0, /*Info*/ 0, addralign, data,
                        name, k) {}
 
 template <class ELFT>
@@ -365,15 +320,6 @@ InputSection::InputSection(ObjFile<ELFT> &f, const typename ELFT::Shdr &header,
                            StringRef name)
     : InputSectionBase(f, header, name, InputSectionBase::Regular) {}
 
-bool InputSection::classof(const SectionBase *s) {
-  return s->kind() == SectionBase::Regular ||
-         s->kind() == SectionBase::Synthetic;
-}
-
-OutputSection *InputSection::getParent() const {
-  return cast_or_null<OutputSection>(parent);
-}
-
 // Copy SHT_GROUP section contents. Used only for the -r option.
 template <class ELFT> void InputSection::copyShtGroup(uint8_t *buf) {
   // ELFT::Word is the 32-bit integral type in the target endianness.
@@ -388,7 +334,7 @@ template <class ELFT> void InputSection::copyShtGroup(uint8_t *buf) {
   // different in the output. We also need to handle combined or discarded
   // members.
   ArrayRef<InputSectionBase *> sections = file->getSections();
-  std::unordered_set<uint32_t> seen;
+  DenseSet<uint32_t> seen;
   for (uint32_t idx : from.slice(1)) {
     OutputSection *osec = sections[idx]->getOutputSection();
     if (osec && seen.insert(osec->sectionIndex).second)
@@ -408,7 +354,9 @@ InputSectionBase *InputSection::getRelocatedSection() const {
 // for each relocation. So we copy relocations one by one.
 template <class ELFT, class RelTy>
 void InputSection::copyRelocations(uint8_t *buf, ArrayRef<RelTy> rels) {
+  const TargetInfo &target = *elf::target;
   InputSectionBase *sec = getRelocatedSection();
+  (void)sec->contentMaybeDecompress(); // uncompress if needed
 
   for (const RelTy &rel : rels) {
     RelType type = rel.getType(config->isMips64EL);
@@ -446,8 +394,7 @@ void InputSection::copyRelocations(uint8_t *buf, ArrayRef<RelTy> rels) {
             sec->name != ".gcc_except_table" && sec->name != ".got2" &&
             sec->name != ".toc") {
           uint32_t secIdx = cast<Undefined>(sym).discardedSecIdx;
-          Elf_Shdr_Impl<ELFT> sec =
-              CHECK(file->getObj().sections(), file)[secIdx];
+          Elf_Shdr_Impl<ELFT> sec = file->template getELFShdrs<ELFT>()[secIdx];
           warn("relocation refers to a discarded section: " +
                CHECK(file->getObj().getSectionName(sec), file) +
                "\n>>> referenced by " + getObjMsg(p->r_offset));
@@ -455,19 +402,19 @@ void InputSection::copyRelocations(uint8_t *buf, ArrayRef<RelTy> rels) {
         p->setSymbolAndType(0, 0, false);
         continue;
       }
-      SectionBase *section = d->section->repl;
+      SectionBase *section = d->section;
       if (!section->isLive()) {
         p->setSymbolAndType(0, 0, false);
         continue;
       }
 
       int64_t addend = getAddend<ELFT>(rel);
-      const uint8_t *bufLoc = sec->data().begin() + rel.r_offset;
+      const uint8_t *bufLoc = sec->content().begin() + rel.r_offset;
       if (!RelTy::IsRela)
-        addend = target->getImplicitAddend(bufLoc, type);
+        addend = target.getImplicitAddend(bufLoc, type);
 
       if (config->emachine == EM_MIPS &&
-          target->getRelExpr(type, sym, bufLoc) == R_MIPS_GOTREL) {
+          target.getRelExpr(type, sym, bufLoc) == R_MIPS_GOTREL) {
         // Some MIPS relocations depend on "gp" value. By default,
         // this value has 0x7ff0 offset from a .got section. But
         // relocatable files produced by a compiler or a linker
@@ -484,16 +431,16 @@ void InputSection::copyRelocations(uint8_t *buf, ArrayRef<RelTy> rels) {
 
       if (RelTy::IsRela)
         p->r_addend = sym.getVA(addend) - section->getOutputSection()->addr;
-      else if (config->relocatable && type != target->noneRel)
-        sec->relocations.push_back({R_ABS, type, rel.r_offset, addend, &sym});
+      else if (config->relocatable && type != target.noneRel)
+        sec->addReloc({R_ABS, type, rel.r_offset, addend, &sym});
     } else if (config->emachine == EM_PPC && type == R_PPC_PLTREL24 &&
-               p->r_addend >= 0x8000) {
+               p->r_addend >= 0x8000 && sec->file->ppc32Got2) {
       // Similar to R_MIPS_GPREL{16,32}. If the addend of R_PPC_PLTREL24
       // indicates that r30 is relative to the input section .got2
       // (r_addend>=0x8000), after linking, r30 should be relative to the output
       // section .got2 . To compensate for the shift, adjust r_addend by
-      // ppc32Got2OutSecOff.
-      p->r_addend += sec->file->ppc32Got2OutSecOff;
+      // ppc32Got->outSecOff.
+      p->r_addend += sec->file->ppc32Got2->outSecOff;
     }
   }
 }
@@ -508,6 +455,7 @@ static uint32_t getARMUndefinedRelativeWeakVA(RelType type, uint32_t a,
   switch (type) {
   // Unresolved branch relocations to weak references resolve to next
   // instruction, this will be either 2 or 4 bytes on from P.
+  case R_ARM_THM_JUMP8:
   case R_ARM_THM_JUMP11:
     return p + 2 + a;
   case R_ARM_CALL:
@@ -598,14 +546,14 @@ static uint64_t getARMStaticBase(const Symbol &sym) {
 static Relocation *getRISCVPCRelHi20(const Symbol *sym, uint64_t addend) {
   const Defined *d = cast<Defined>(sym);
   if (!d->section) {
-    error("R_RISCV_PCREL_LO12 relocation points to an absolute symbol: " +
-          sym->getName());
+    errorOrWarn("R_RISCV_PCREL_LO12 relocation points to an absolute symbol: " +
+                sym->getName());
     return nullptr;
   }
   InputSection *isec = cast<InputSection>(d->section);
 
   if (addend != 0)
-    warn("Non-zero addend in R_RISCV_PCREL_LO12 relocation to " +
+    warn("non-zero addend in R_RISCV_PCREL_LO12 relocation to " +
          isec->getObjMsg(d->value) + " is ignored");
 
   // Relocations are sorted by offset, so we can use std::equal_range to do
@@ -613,7 +561,7 @@ static Relocation *getRISCVPCRelHi20(const Symbol *sym, uint64_t addend) {
   Relocation r;
   r.offset = d->value;
   auto range =
-      std::equal_range(isec->relocations.begin(), isec->relocations.end(), r,
+      std::equal_range(isec->relocs().begin(), isec->relocs().end(), r,
                        [](const Relocation &lhs, const Relocation &rhs) {
                          return lhs.offset < rhs.offset;
                        });
@@ -623,8 +571,9 @@ static Relocation *getRISCVPCRelHi20(const Symbol *sym, uint64_t addend) {
         it->type == R_RISCV_TLS_GD_HI20 || it->type == R_RISCV_TLS_GOT_HI20)
       return &*it;
 
-  error("R_RISCV_PCREL_LO12 relocation points to " + isec->getObjMsg(d->value) +
-        " without an associated R_RISCV_PCREL_HI20 relocation");
+  errorOrWarn("R_RISCV_PCREL_LO12 relocation points to " +
+              isec->getObjMsg(d->value) +
+              " without an associated R_RISCV_PCREL_HI20 relocation");
   return nullptr;
 }
 
@@ -687,6 +636,8 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
     return sym.getVA(a);
   case R_ADDEND:
     return a;
+  case R_RELAX_HINT:
+    return 0;
   case R_ARM_SBREL:
     return sym.getVA(a) - getARMStaticBase(sym);
   case R_GOT:
@@ -770,11 +721,13 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
     if (expr == R_ARM_PCA)
       // Some PC relative ARM (Thumb) relocations align down the place.
       p = p & 0xfffffffc;
-    if (sym.isUndefWeak()) {
+    if (sym.isUndefined()) {
       // On ARM and AArch64 a branch to an undefined weak resolves to the next
       // instruction, otherwise the place. On RISCV, resolve an undefined weak
       // to the same instruction to cause an infinite loop (making the user
       // aware of the issue) while ensuring no overflow.
+      // Note: if the symbol is hidden, its binding has been converted to local,
+      // so we just check isUndefined() here.
       if (config->emachine == EM_ARM)
         dest = getARMUndefinedRelativeWeakVA(type, a, p);
       else if (config->emachine == EM_AARCH64)
@@ -795,6 +748,8 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
   case R_PLT_PC:
   case R_PPC64_CALL_PLT:
     return sym.getPltVA() + a - p;
+  case R_PLT_GOTPLT:
+    return sym.getPltVA() + a - in.gotPlt->getVA();
   case R_PPC32_PLTREL:
     // R_PPC_PLTREL24 uses the addend (usually 0 or 0x8000) to indicate r30
     // stores _GLOBAL_OFFSET_TABLE_ or .got2+0x8000. The addend is ignored for
@@ -829,7 +784,7 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
     // --noinhibit-exec, even a non-weak undefined reference may reach here.
     // Just return A, which matches R_ABS, and the behavior of some dynamic
     // loaders.
-    if (sym.isUndefined() || sym.isLazy())
+    if (sym.isUndefined())
       return a;
     return getTlsTpOffset(sym) + a;
   case R_RELAX_TLS_GD_TO_LE_NEG:
@@ -840,12 +795,13 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
   case R_SIZE:
     return sym.getSize() + a;
   case R_TLSDESC:
-    return in.got->getGlobalDynAddr(sym) + a;
+    return in.got->getTlsDescAddr(sym) + a;
   case R_TLSDESC_PC:
-    return in.got->getGlobalDynAddr(sym) + a - p;
+    return in.got->getTlsDescAddr(sym) + a - p;
+  case R_TLSDESC_GOTPLT:
+    return in.got->getTlsDescAddr(sym) + a - in.gotPlt->getVA();
   case R_AARCH64_TLSDESC_PAGE:
-    return getAArch64Page(in.got->getGlobalDynAddr(sym) + a) -
-           getAArch64Page(p);
+    return getAArch64Page(in.got->getTlsDescAddr(sym) + a) - getAArch64Page(p);
   case R_TLSGD_GOT:
     return in.got->getGlobalDynOffset(sym) + a;
   case R_TLSGD_GOTPLT:
@@ -873,11 +829,12 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
 template <class ELFT, class RelTy>
 void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
   const unsigned bits = sizeof(typename ELFT::uint) * 8;
+  const TargetInfo &target = *elf::target;
   const bool isDebug = isDebugSection(*this);
   const bool isDebugLocOrRanges =
       isDebug && (name == ".debug_loc" || name == ".debug_ranges");
   const bool isDebugLine = isDebug && name == ".debug_line";
-  Optional<uint64_t> tombstone;
+  std::optional<uint64_t> tombstone;
   for (const auto &patAndValue : llvm::reverse(config->deadRelocInNonAlloc))
     if (patAndValue.first.match(this->name)) {
       tombstone = patAndValue.second;
@@ -898,47 +855,15 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
     uint8_t *bufLoc = buf + offset;
     int64_t addend = getAddend<ELFT>(rel);
     if (!RelTy::IsRela)
-      addend += target->getImplicitAddend(bufLoc, type);
+      addend += target.getImplicitAddend(bufLoc, type);
 
     Symbol &sym = getFile<ELFT>()->getRelocTargetSym(rel);
-    RelExpr expr = target->getRelExpr(type, sym, bufLoc);
+    RelExpr expr = target.getRelExpr(type, sym, bufLoc);
     if (expr == R_NONE)
       continue;
 
-    if (expr == R_SIZE) {
-      target->relocateNoSym(bufLoc, type,
-                            SignExtend64<bits>(sym.getSize() + addend));
-      continue;
-    }
-
-    // R_ABS/R_DTPREL and some other relocations can be used from non-SHF_ALLOC
-    // sections.
-    if (expr != R_ABS && expr != R_DTPREL && expr != R_GOTPLTREL &&
-        expr != R_RISCV_ADD) {
-      std::string msg = getLocation<ELFT>(offset) +
-                        ": has non-ABS relocation " + toString(type) +
-                        " against symbol '" + toString(sym) + "'";
-      if (expr != R_PC && expr != R_ARM_PCA) {
-        error(msg);
-        return;
-      }
-
-      // If the control reaches here, we found a PC-relative relocation in a
-      // non-ALLOC section. Since non-ALLOC section is not loaded into memory
-      // at runtime, the notion of PC-relative doesn't make sense here. So,
-      // this is a usage error. However, GNU linkers historically accept such
-      // relocations without any errors and relocate them as if they were at
-      // address 0. For bug-compatibilty, we accept them with warnings. We
-      // know Steel Bank Common Lisp as of 2018 have this bug.
-      warn(msg);
-      target->relocateNoSym(
-          bufLoc, type,
-          SignExtend64<bits>(sym.getVA(addend - offset - outSecOff)));
-      continue;
-    }
-
     if (tombstone ||
-        (isDebug && (type == target->symbolicRel || expr == R_DTPREL))) {
+        (isDebug && (type == target.symbolicRel || expr == R_DTPREL))) {
       // Resolve relocations in .debug_* referencing (discarded symbols or ICF
       // folded section symbols) to a tombstone value. Resolving to addend is
       // unsatisfactory because the result address range may collide with a
@@ -956,10 +881,10 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
       //
       // If the referenced symbol is discarded (made Undefined), or the
       // section defining the referenced symbol is garbage collected,
-      // sym.getOutputSection() is nullptr. `ds->section->repl != ds->section`
-      // catches the ICF folded case. However, resolving a relocation in
-      // .debug_line to -1 would stop debugger users from setting breakpoints on
-      // the folded-in function, so exclude .debug_line.
+      // sym.getOutputSection() is nullptr. `ds->folded` catches the ICF folded
+      // case. However, resolving a relocation in .debug_line to -1 would stop
+      // debugger users from setting breakpoints on the folded-in function, so
+      // exclude .debug_line.
       //
       // For pre-DWARF-v5 .debug_loc and .debug_ranges, -1 is a reserved value
       // (base address selection entry), use 1 (which is used by GNU ld for
@@ -968,16 +893,52 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
       // TODO To reduce disruption, we use 0 instead of -1 as the tombstone
       // value. Enable -1 in a future release.
       auto *ds = dyn_cast<Defined>(&sym);
-      if (!sym.getOutputSection() ||
-          (ds && ds->section->repl != ds->section && !isDebugLine)) {
+      if (!sym.getOutputSection() || (ds && ds->folded && !isDebugLine)) {
         // If -z dead-reloc-in-nonalloc= is specified, respect it.
         const uint64_t value = tombstone ? SignExtend64<bits>(*tombstone)
                                          : (isDebugLocOrRanges ? 1 : 0);
-        target->relocateNoSym(bufLoc, type, value);
+        target.relocateNoSym(bufLoc, type, value);
         continue;
       }
     }
-    target->relocateNoSym(bufLoc, type, SignExtend64<bits>(sym.getVA(addend)));
+
+    // For a relocatable link, only tombstone values are applied.
+    if (config->relocatable)
+      continue;
+
+    if (expr == R_SIZE) {
+      target.relocateNoSym(bufLoc, type,
+                           SignExtend64<bits>(sym.getSize() + addend));
+      continue;
+    }
+
+    // R_ABS/R_DTPREL and some other relocations can be used from non-SHF_ALLOC
+    // sections.
+    if (expr == R_ABS || expr == R_DTPREL || expr == R_GOTPLTREL ||
+        expr == R_RISCV_ADD) {
+      target.relocateNoSym(bufLoc, type, SignExtend64<bits>(sym.getVA(addend)));
+      continue;
+    }
+
+    std::string msg = getLocation(offset) + ": has non-ABS relocation " +
+                      toString(type) + " against symbol '" + toString(sym) +
+                      "'";
+    if (expr != R_PC && expr != R_ARM_PCA) {
+      error(msg);
+      return;
+    }
+
+    // If the control reaches here, we found a PC-relative relocation in a
+    // non-ALLOC section. Since non-ALLOC section is not loaded into memory
+    // at runtime, the notion of PC-relative doesn't make sense here. So,
+    // this is a usage error. However, GNU linkers historically accept such
+    // relocations without any errors and relocate them as if they were at
+    // address 0. For bug-compatibility, we accept them with warnings. We
+    // know Steel Bank Common Lisp as of 2018 have this bug.
+    warn(msg);
+    target.relocateNoSym(
+        bufLoc, type,
+        SignExtend64<bits>(sym.getVA(addend - offset - outSecOff)));
   }
 }
 
@@ -989,7 +950,7 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
 static void relocateNonAllocForRelocatable(InputSection *sec, uint8_t *buf) {
   const unsigned bits = config->is64 ? 64 : 32;
 
-  for (const Relocation &rel : sec->relocations) {
+  for (const Relocation &rel : sec->relocs()) {
     // InputSection::copyRelocations() adds only R_ABS relocations.
     assert(rel.expr == R_ABS);
     uint8_t *bufLoc = buf + rel.offset;
@@ -1000,145 +961,38 @@ static void relocateNonAllocForRelocatable(InputSection *sec, uint8_t *buf) {
 
 template <class ELFT>
 void InputSectionBase::relocate(uint8_t *buf, uint8_t *bufEnd) {
-  if (flags & SHF_EXECINSTR)
+  if ((flags & SHF_EXECINSTR) && LLVM_UNLIKELY(getFile<ELFT>()->splitStack))
     adjustSplitStackFunctionPrologues<ELFT>(buf, bufEnd);
 
   if (flags & SHF_ALLOC) {
-    relocateAlloc(buf, bufEnd);
+    target->relocateAlloc(*this, buf);
     return;
   }
 
   auto *sec = cast<InputSection>(this);
   if (config->relocatable)
     relocateNonAllocForRelocatable(sec, buf);
-  else if (sec->areRelocsRela)
-    sec->relocateNonAlloc<ELFT>(buf, sec->template relas<ELFT>());
+  // For a relocatable link, also call relocateNonAlloc() to rewrite applicable
+  // locations with tombstone values.
+  const RelsOrRelas<ELFT> rels = sec->template relsOrRelas<ELFT>();
+  if (rels.areRelocsRel())
+    sec->relocateNonAlloc<ELFT>(buf, rels.rels);
   else
-    sec->relocateNonAlloc<ELFT>(buf, sec->template rels<ELFT>());
-}
-
-void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) {
-  assert(flags & SHF_ALLOC);
-  const unsigned bits = config->wordsize * 8;
-  uint64_t lastPPCRelaxedRelocOff = UINT64_C(-1);
-
-  for (const Relocation &rel : relocations) {
-    if (rel.expr == R_NONE)
-      continue;
-    uint64_t offset = rel.offset;
-    uint8_t *bufLoc = buf + offset;
-    RelType type = rel.type;
-
-    uint64_t addrLoc = getOutputSection()->addr + offset;
-    if (auto *sec = dyn_cast<InputSection>(this))
-      addrLoc += sec->outSecOff;
-    RelExpr expr = rel.expr;
-    uint64_t targetVA = SignExtend64(
-        getRelocTargetVA(file, type, rel.addend, addrLoc, *rel.sym, expr),
-        bits);
-
-    switch (expr) {
-    case R_RELAX_GOT_PC:
-    case R_RELAX_GOT_PC_NOPIC:
-      target->relaxGot(bufLoc, rel, targetVA);
-      break;
-    case R_PPC64_RELAX_GOT_PC: {
-      // The R_PPC64_PCREL_OPT relocation must appear immediately after
-      // R_PPC64_GOT_PCREL34 in the relocations table at the same offset.
-      // We can only relax R_PPC64_PCREL_OPT if we have also relaxed
-      // the associated R_PPC64_GOT_PCREL34 since only the latter has an
-      // associated symbol. So save the offset when relaxing R_PPC64_GOT_PCREL34
-      // and only relax the other if the saved offset matches.
-      if (type == R_PPC64_GOT_PCREL34)
-        lastPPCRelaxedRelocOff = offset;
-      if (type == R_PPC64_PCREL_OPT && offset != lastPPCRelaxedRelocOff)
-        break;
-      target->relaxGot(bufLoc, rel, targetVA);
-      break;
-    }
-    case R_PPC64_RELAX_TOC:
-      // rel.sym refers to the STT_SECTION symbol associated to the .toc input
-      // section. If an R_PPC64_TOC16_LO (.toc + addend) references the TOC
-      // entry, there may be R_PPC64_TOC16_HA not paired with
-      // R_PPC64_TOC16_LO_DS. Don't relax. This loses some relaxation
-      // opportunities but is safe.
-      if (ppc64noTocRelax.count({rel.sym, rel.addend}) ||
-          !tryRelaxPPC64TocIndirection(rel, bufLoc))
-        target->relocate(bufLoc, rel, targetVA);
-      break;
-    case R_RELAX_TLS_IE_TO_LE:
-      target->relaxTlsIeToLe(bufLoc, rel, targetVA);
-      break;
-    case R_RELAX_TLS_LD_TO_LE:
-    case R_RELAX_TLS_LD_TO_LE_ABS:
-      target->relaxTlsLdToLe(bufLoc, rel, targetVA);
-      break;
-    case R_RELAX_TLS_GD_TO_LE:
-    case R_RELAX_TLS_GD_TO_LE_NEG:
-      target->relaxTlsGdToLe(bufLoc, rel, targetVA);
-      break;
-    case R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC:
-    case R_RELAX_TLS_GD_TO_IE:
-    case R_RELAX_TLS_GD_TO_IE_ABS:
-    case R_RELAX_TLS_GD_TO_IE_GOT_OFF:
-    case R_RELAX_TLS_GD_TO_IE_GOTPLT:
-      target->relaxTlsGdToIe(bufLoc, rel, targetVA);
-      break;
-    case R_PPC64_CALL:
-      // If this is a call to __tls_get_addr, it may be part of a TLS
-      // sequence that has been relaxed and turned into a nop. In this
-      // case, we don't want to handle it as a call.
-      if (read32(bufLoc) == 0x60000000) // nop
-        break;
-
-      // Patch a nop (0x60000000) to a ld.
-      if (rel.sym->needsTocRestore) {
-        // gcc/gfortran 5.4, 6.3 and earlier versions do not add nop for
-        // recursive calls even if the function is preemptible. This is not
-        // wrong in the common case where the function is not preempted at
-        // runtime. Just ignore.
-        if ((bufLoc + 8 > bufEnd || read32(bufLoc + 4) != 0x60000000) &&
-            rel.sym->file != file) {
-          // Use substr(6) to remove the "__plt_" prefix.
-          errorOrWarn(getErrorLocation(bufLoc) + "call to " +
-                      lld::toString(*rel.sym).substr(6) +
-                      " lacks nop, can't restore toc");
-          break;
-        }
-        write32(bufLoc + 4, 0xe8410018); // ld %r2, 24(%r1)
-      }
-      target->relocate(bufLoc, rel, targetVA);
-      break;
-    default:
-      target->relocate(bufLoc, rel, targetVA);
-      break;
-    }
-  }
-
-  // Apply jumpInstrMods.  jumpInstrMods are created when the opcode of
-  // a jmp insn must be modified to shrink the jmp insn or to flip the jmp
-  // insn.  This is primarily used to relax and optimize jumps created with
-  // basic block sections.
-  if (isa<InputSection>(this)) {
-    for (const JumpInstrMod &jumpMod : jumpInstrMods) {
-      uint64_t offset = jumpMod.offset;
-      uint8_t *bufLoc = buf + offset;
-      target->applyJumpInstrMod(bufLoc, jumpMod.original, jumpMod.size);
-    }
-  }
+    sec->relocateNonAlloc<ELFT>(buf, rels.relas);
 }
 
 // For each function-defining prologue, find any calls to __morestack,
 // and replace them with calls to __morestack_non_split.
 static void switchMorestackCallsToMorestackNonSplit(
-    DenseSet<Defined *> &prologues, std::vector<Relocation *> &morestackCalls) {
+    DenseSet<Defined *> &prologues,
+    SmallVector<Relocation *, 0> &morestackCalls) {
 
   // If the target adjusted a function's prologue, all calls to
   // __morestack inside that function should be switched to
   // __morestack_non_split.
-  Symbol *moreStackNonSplit = symtab->find("__morestack_non_split");
+  Symbol *moreStackNonSplit = symtab.find("__morestack_non_split");
   if (!moreStackNonSplit) {
-    error("Mixing split-stack objects requires a definition of "
+    error("mixing split-stack objects requires a definition of "
           "__morestack_non_split");
     return;
   }
@@ -1180,17 +1034,10 @@ static bool enclosingPrologueAttempted(uint64_t offset,
 template <class ELFT>
 void InputSectionBase::adjustSplitStackFunctionPrologues(uint8_t *buf,
                                                          uint8_t *end) {
-  if (!getFile<ELFT>()->splitStack)
-    return;
   DenseSet<Defined *> prologues;
-  std::vector<Relocation *> morestackCalls;
-
-  for (Relocation &rel : relocations) {
-    // Local symbols can't possibly be cross-calls, and should have been
-    // resolved long before this line.
-    if (rel.sym->isLocal())
-      continue;
+  SmallVector<Relocation *, 0> morestackCalls;
 
+  for (Relocation &rel : relocs()) {
     // Ignore calls into the split-stack api.
     if (rel.sym->getName().startswith("__morestack")) {
       if (rel.sym->getName().equals("__morestack"))
@@ -1217,7 +1064,7 @@ void InputSectionBase::adjustSplitStackFunctionPrologues(uint8_t *buf,
     if (enclosingPrologueAttempted(rel.offset, prologues))
       continue;
 
-    if (Defined *f = getEnclosingFunction<ELFT>(rel.offset)) {
+    if (Defined *f = getEnclosingFunction(rel.offset)) {
       prologues.insert(f);
       if (target->adjustPrologueForCrossSplitStack(buf + f->value, end,
                                                    f->stOther))
@@ -1234,53 +1081,50 @@ void InputSectionBase::adjustSplitStackFunctionPrologues(uint8_t *buf,
 }
 
 template <class ELFT> void InputSection::writeTo(uint8_t *buf) {
-  if (type == SHT_NOBITS)
+  if (LLVM_UNLIKELY(type == SHT_NOBITS))
     return;
-
-  if (auto *s = dyn_cast<SyntheticSection>(this)) {
-    s->writeTo(buf + outSecOff);
-    return;
-  }
-
   // If -r or --emit-relocs is given, then an InputSection
   // may be a relocation section.
-  if (type == SHT_RELA) {
-    copyRelocations<ELFT>(buf + outSecOff, getDataAs<typename ELFT::Rela>());
+  if (LLVM_UNLIKELY(type == SHT_RELA)) {
+    copyRelocations<ELFT>(buf, getDataAs<typename ELFT::Rela>());
     return;
   }
-  if (type == SHT_REL) {
-    copyRelocations<ELFT>(buf + outSecOff, getDataAs<typename ELFT::Rel>());
+  if (LLVM_UNLIKELY(type == SHT_REL)) {
+    copyRelocations<ELFT>(buf, getDataAs<typename ELFT::Rel>());
     return;
   }
 
   // If -r is given, we may have a SHT_GROUP section.
-  if (type == SHT_GROUP) {
-    copyShtGroup<ELFT>(buf + outSecOff);
+  if (LLVM_UNLIKELY(type == SHT_GROUP)) {
+    copyShtGroup<ELFT>(buf);
     return;
   }
 
   // If this is a compressed section, uncompress section contents directly
   // to the buffer.
-  if (uncompressedSize >= 0) {
-    size_t size = uncompressedSize;
-    if (Error e = zlib::uncompress(toStringRef(rawData),
-                                   (char *)(buf + outSecOff), size))
+  if (compressed) {
+    auto *hdr = reinterpret_cast<const typename ELFT::Chdr *>(content_);
+    auto compressed = ArrayRef<uint8_t>(content_, compressedSize)
+                          .slice(sizeof(typename ELFT::Chdr));
+    size_t size = this->size;
+    if (Error e = hdr->ch_type == ELFCOMPRESS_ZLIB
+                      ? compression::zlib::decompress(compressed, buf, size)
+                      : compression::zstd::decompress(compressed, buf, size))
       fatal(toString(this) +
-            ": uncompress failed: " + llvm::toString(std::move(e)));
-    uint8_t *bufEnd = buf + outSecOff + size;
-    relocate<ELFT>(buf + outSecOff, bufEnd);
+            ": decompress failed: " + llvm::toString(std::move(e)));
+    uint8_t *bufEnd = buf + size;
+    relocate<ELFT>(buf, bufEnd);
     return;
   }
 
   // Copy section contents from source object file to output file
   // and then apply relocations.
-  memcpy(buf + outSecOff, data().data(), data().size());
-  uint8_t *bufEnd = buf + outSecOff + data().size();
-  relocate<ELFT>(buf + outSecOff, bufEnd);
+  memcpy(buf, content().data(), content().size());
+  relocate<ELFT>(buf, buf + content().size());
 }
 
 void InputSection::replace(InputSection *other) {
-  alignment = std::max(alignment, other->alignment);
+  addralign = std::max(addralign, other->addralign);
 
   // When a section is replaced with another section that was allocated to
   // another partition, the replacement section (and its associated sections)
@@ -1306,85 +1150,105 @@ SyntheticSection *EhInputSection::getParent() const {
   return cast_or_null<SyntheticSection>(parent);
 }
 
-// Returns the index of the first relocation that points to a region between
-// Begin and Begin+Size.
-template <class IntTy, class RelTy>
-static unsigned getReloc(IntTy begin, IntTy size, const ArrayRef<RelTy> &rels,
-                         unsigned &relocI) {
-  // Start search from RelocI for fast access. That works because the
-  // relocations are sorted in .eh_frame.
-  for (unsigned n = rels.size(); relocI < n; ++relocI) {
-    const RelTy &rel = rels[relocI];
-    if (rel.r_offset < begin)
-      continue;
-
-    if (rel.r_offset < begin + size)
-      return relocI;
-    return -1;
-  }
-  return -1;
-}
-
 // .eh_frame is a sequence of CIE or FDE records.
 // This function splits an input section into records and returns them.
 template <class ELFT> void EhInputSection::split() {
-  if (areRelocsRela)
-    split<ELFT>(relas<ELFT>());
-  else
-    split<ELFT>(rels<ELFT>());
+  const RelsOrRelas<ELFT> rels = relsOrRelas<ELFT>();
+  // getReloc expects the relocations to be sorted by r_offset. See the comment
+  // in scanRelocs.
+  if (rels.areRelocsRel()) {
+    SmallVector<typename ELFT::Rel, 0> storage;
+    split<ELFT>(sortRels(rels.rels, storage));
+  } else {
+    SmallVector<typename ELFT::Rela, 0> storage;
+    split<ELFT>(sortRels(rels.relas, storage));
+  }
 }
 
 template <class ELFT, class RelTy>
 void EhInputSection::split(ArrayRef<RelTy> rels) {
-  // getReloc expects the relocations to be sorted by r_offset. See the comment
-  // in scanRelocs.
-  SmallVector<RelTy, 0> storage;
-  rels = sortRels(rels, storage);
-
+  ArrayRef<uint8_t> d = content();
+  const char *msg = nullptr;
   unsigned relI = 0;
-  for (size_t off = 0, end = data().size(); off != end;) {
-    size_t size = readEhRecordSize(this, off);
-    pieces.emplace_back(off, this, size, getReloc(off, size, rels, relI));
-    // The empty record is the end marker.
-    if (size == 4)
+  while (!d.empty()) {
+    if (d.size() < 4) {
+      msg = "CIE/FDE too small";
+      break;
+    }
+    uint64_t size = endian::read32<ELFT::TargetEndianness>(d.data());
+    if (size == 0) // ZERO terminator
       break;
-    off += size;
+    uint32_t id = endian::read32<ELFT::TargetEndianness>(d.data() + 4);
+    size += 4;
+    if (LLVM_UNLIKELY(size > d.size())) {
+      // If it is 0xFFFFFFFF, the next 8 bytes contain the size instead,
+      // but we do not support that format yet.
+      msg = size == UINT32_MAX + uint64_t(4)
+                ? "CIE/FDE too large"
+                : "CIE/FDE ends past the end of the section";
+      break;
+    }
+
+    // Find the first relocation that points to [off,off+size). Relocations
+    // have been sorted by r_offset.
+    const uint64_t off = d.data() - content().data();
+    while (relI != rels.size() && rels[relI].r_offset < off)
+      ++relI;
+    unsigned firstRel = -1;
+    if (relI != rels.size() && rels[relI].r_offset < off + size)
+      firstRel = relI;
+    (id == 0 ? cies : fdes).emplace_back(off, this, size, firstRel);
+    d = d.slice(size);
   }
+  if (msg)
+    errorOrWarn("corrupted .eh_frame: " + Twine(msg) + "\n>>> defined in " +
+                getObjMsg(d.data() - content().data()));
 }
 
-static size_t findNull(StringRef s, size_t entSize) {
-  // Optimize the common case.
-  if (entSize == 1)
-    return s.find(0);
+// Return the offset in an output section for a given input offset.
+uint64_t EhInputSection::getParentOffset(uint64_t offset) const {
+  auto it = partition_point(
+      fdes, [=](EhSectionPiece p) { return p.inputOff <= offset; });
+  if (it == fdes.begin() || it[-1].inputOff + it[-1].size <= offset) {
+    it = partition_point(
+        cies, [=](EhSectionPiece p) { return p.inputOff <= offset; });
+    if (it == cies.begin()) // invalid piece
+      return offset;
+  }
+  if (it[-1].outputOff == -1) // invalid piece
+    return offset - it[-1].inputOff;
+  return it[-1].outputOff + (offset - it[-1].inputOff);
+}
 
+static size_t findNull(StringRef s, size_t entSize) {
   for (unsigned i = 0, n = s.size(); i != n; i += entSize) {
     const char *b = s.begin() + i;
     if (std::all_of(b, b + entSize, [](char c) { return c == 0; }))
       return i;
   }
-  return StringRef::npos;
-}
-
-SyntheticSection *MergeInputSection::getParent() const {
-  return cast_or_null<SyntheticSection>(parent);
+  llvm_unreachable("");
 }
 
 // Split SHF_STRINGS section. Such section is a sequence of
 // null-terminated strings.
-void MergeInputSection::splitStrings(ArrayRef<uint8_t> data, size_t entSize) {
-  size_t off = 0;
-  bool isAlloc = flags & SHF_ALLOC;
-  StringRef s = toStringRef(data);
-
-  while (!s.empty()) {
-    size_t end = findNull(s, entSize);
-    if (end == StringRef::npos)
-      fatal(toString(this) + ": string is not null terminated");
-    size_t size = end + entSize;
-
-    pieces.emplace_back(off, xxHash64(s.substr(0, size)), !isAlloc);
-    s = s.substr(size);
-    off += size;
+void MergeInputSection::splitStrings(StringRef s, size_t entSize) {
+  const bool live = !(flags & SHF_ALLOC) || !config->gcSections;
+  const char *p = s.data(), *end = s.data() + s.size();
+  if (!std::all_of(end - entSize, end, [](char c) { return c == 0; }))
+    fatal(toString(this) + ": string is not null terminated");
+  if (entSize == 1) {
+    // Optimize the common case.
+    do {
+      size_t size = strlen(p);
+      pieces.emplace_back(p - s.begin(), xxHash64(StringRef(p, size)), live);
+      p += size + 1;
+    } while (p != end);
+  } else {
+    do {
+      size_t size = findNull(StringRef(p, end - p), entSize);
+      pieces.emplace_back(p - s.begin(), xxHash64(StringRef(p, size)), live);
+      p += size + entSize;
+    } while (p != end);
   }
 }
 
@@ -1394,10 +1258,11 @@ void MergeInputSection::splitNonStrings(ArrayRef<uint8_t> data,
                                         size_t entSize) {
   size_t size = data.size();
   assert((size % entSize) == 0);
-  bool isAlloc = flags & SHF_ALLOC;
+  const bool live = !(flags & SHF_ALLOC) || !config->gcSections;
 
-  for (size_t i = 0; i != size; i += entSize)
-    pieces.emplace_back(i, xxHash64(data.slice(i, entSize)), !isAlloc);
+  pieces.resize_for_overwrite(size / entSize);
+  for (size_t i = 0, j = 0; i != size; i += entSize, j++)
+    pieces[j] = {i, (uint32_t)xxHash64(data.slice(i, entSize)), live};
 }
 
 template <class ELFT>
@@ -1422,31 +1287,22 @@ void MergeInputSection::splitIntoPieces() {
   assert(pieces.empty());
 
   if (flags & SHF_STRINGS)
-    splitStrings(data(), entsize);
+    splitStrings(toStringRef(contentMaybeDecompress()), entsize);
   else
-    splitNonStrings(data(), entsize);
+    splitNonStrings(contentMaybeDecompress(), entsize);
 }
 
-SectionPiece *MergeInputSection::getSectionPiece(uint64_t offset) {
-  if (this->data().size() <= offset)
+SectionPiece &MergeInputSection::getSectionPiece(uint64_t offset) {
+  if (content().size() <= offset)
     fatal(toString(this) + ": offset is outside the section");
-
-  // If Offset is not at beginning of a section piece, it is not in the map.
-  // In that case we need to  do a binary search of the original section piece vector.
-  auto it = partition_point(
-      pieces, [=](SectionPiece p) { return p.inputOff <= offset; });
-  return &it[-1];
+  return partition_point(
+      pieces, [=](SectionPiece p) { return p.inputOff <= offset; })[-1];
 }
 
-// Returns the offset in an output section for a given input offset.
-// Because contents of a mergeable section is not contiguous in output,
-// it is not just an addition to a base output offset.
+// Return the offset in an output section for a given input offset.
 uint64_t MergeInputSection::getParentOffset(uint64_t offset) const {
-  // If Offset is not at beginning of a section piece, it is not in the map.
-  // In that case we need to search from the original section piece vector.
-  const SectionPiece &piece = *getSectionPiece(offset);
-  uint64_t addend = offset - piece.inputOff;
-  return piece.outputOff + addend;
+  const SectionPiece &piece = getSectionPiece(offset);
+  return piece.outputOff + (offset - piece.inputOff);
 }
 
 template InputSection::InputSection(ObjFile<ELF32LE> &, const ELF32LE::Shdr &,
@@ -1458,16 +1314,16 @@ template InputSection::InputSection(ObjFile<ELF64LE> &, const ELF64LE::Shdr &,
 template InputSection::InputSection(ObjFile<ELF64BE> &, const ELF64BE::Shdr &,
                                     StringRef);
 
-template std::string InputSectionBase::getLocation<ELF32LE>(uint64_t);
-template std::string InputSectionBase::getLocation<ELF32BE>(uint64_t);
-template std::string InputSectionBase::getLocation<ELF64LE>(uint64_t);
-template std::string InputSectionBase::getLocation<ELF64BE>(uint64_t);
-
 template void InputSection::writeTo<ELF32LE>(uint8_t *);
 template void InputSection::writeTo<ELF32BE>(uint8_t *);
 template void InputSection::writeTo<ELF64LE>(uint8_t *);
 template void InputSection::writeTo<ELF64BE>(uint8_t *);
 
+template RelsOrRelas<ELF32LE> InputSectionBase::relsOrRelas<ELF32LE>() const;
+template RelsOrRelas<ELF32BE> InputSectionBase::relsOrRelas<ELF32BE>() const;
+template RelsOrRelas<ELF64LE> InputSectionBase::relsOrRelas<ELF64LE>() const;
+template RelsOrRelas<ELF64BE> InputSectionBase::relsOrRelas<ELF64BE>() const;
+
 template MergeInputSection::MergeInputSection(ObjFile<ELF32LE> &,
                                               const ELF32LE::Shdr &, StringRef);
 template MergeInputSection::MergeInputSection(ObjFile<ELF32BE> &,
index d362cfc..24e4ae6 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "LinkerScript.h"
 #include "Config.h"
+#include "InputFiles.h"
 #include "InputSection.h"
 #include "OutputSections.h"
 #include "SymbolTable.h"
@@ -19,7 +20,7 @@
 #include "SyntheticSections.h"
 #include "Target.h"
 #include "Writer.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
 #include "lld/Common/Strings.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Parallel.h"
-#include "llvm/Support/Path.h"
 #include "llvm/Support/TimeProfiler.h"
 #include <algorithm>
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
-#include <iterator>
 #include <limits>
 #include <string>
 #include <vector>
@@ -47,25 +44,82 @@ using namespace llvm::support::endian;
 using namespace lld;
 using namespace lld::elf;
 
-LinkerScript *elf::script;
+std::unique_ptr<LinkerScript> elf::script;
 
-static uint64_t getOutputSectionVA(SectionBase *sec) {
-  OutputSection *os = sec->getOutputSection();
-  assert(os && "input section has no output section assigned");
-  return os ? os->addr : 0;
+static bool isSectionPrefix(StringRef prefix, StringRef name) {
+  return name.consume_front(prefix) && (name.empty() || name[0] == '.');
+}
+
+static StringRef getOutputSectionName(const InputSectionBase *s) {
+  if (config->relocatable)
+    return s->name;
+
+  // This is for --emit-relocs. If .text.foo is emitted as .text.bar, we want
+  // to emit .rela.text.foo as .rela.text.bar for consistency (this is not
+  // technically required, but not doing it is odd). This code guarantees that.
+  if (auto *isec = dyn_cast<InputSection>(s)) {
+    if (InputSectionBase *rel = isec->getRelocatedSection()) {
+      OutputSection *out = rel->getOutputSection();
+      if (s->type == SHT_RELA)
+        return saver().save(".rela" + out->name);
+      return saver().save(".rel" + out->name);
+    }
+  }
+
+  // A BssSection created for a common symbol is identified as "COMMON" in
+  // linker scripts. It should go to .bss section.
+  if (s->name == "COMMON")
+    return ".bss";
+
+  if (script->hasSectionsCommand)
+    return s->name;
+
+  // When no SECTIONS is specified, emulate GNU ld's internal linker scripts
+  // by grouping sections with certain prefixes.
+
+  // GNU ld places text sections with prefix ".text.hot.", ".text.unknown.",
+  // ".text.unlikely.", ".text.startup." or ".text.exit." before others.
+  // We provide an option -z keep-text-section-prefix to group such sections
+  // into separate output sections. This is more flexible. See also
+  // sortISDBySectionOrder().
+  // ".text.unknown" means the hotness of the section is unknown. When
+  // SampleFDO is used, if a function doesn't have sample, it could be very
+  // cold or it could be a new function never being sampled. Those functions
+  // will be kept in the ".text.unknown" section.
+  // ".text.split." holds symbols which are split out from functions in other
+  // input sections. For example, with -fsplit-machine-functions, placing the
+  // cold parts in .text.split instead of .text.unlikely mitigates against poor
+  // profile inaccuracy. Techniques such as hugepage remapping can make
+  // conservative decisions at the section granularity.
+  if (isSectionPrefix(".text", s->name)) {
+    if (config->zKeepTextSectionPrefix)
+      for (StringRef v : {".text.hot", ".text.unknown", ".text.unlikely",
+                          ".text.startup", ".text.exit", ".text.split"})
+        if (isSectionPrefix(v.substr(5), s->name.substr(5)))
+          return v;
+    return ".text";
+  }
+
+  for (StringRef v :
+       {".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss",
+        ".gcc_except_table", ".init_array", ".fini_array", ".tbss", ".tdata",
+        ".ARM.exidx", ".ARM.extab", ".ctors", ".dtors",
+        ".openbsd.randomdata.", ".openbsd.mutable."})
+    if (isSectionPrefix(v, s->name))
+      return v;
+
+  return s->name;
 }
 
 uint64_t ExprValue::getValue() const {
   if (sec)
-    return alignTo(sec->getOffset(val) + getOutputSectionVA(sec),
-                   alignment);
-  return alignTo(val, alignment);
+    return alignToPowerOf2(sec->getOutputSection()->addr + sec->getOffset(val),
+                           alignment);
+  return alignToPowerOf2(val, alignment);
 }
 
 uint64_t ExprValue::getSecAddr() const {
-  if (sec)
-    return sec->getOffset(0) + getOutputSectionVA(sec);
-  return 0;
+  return sec ? sec->getOutputSection()->addr + sec->getOffset(0) : 0;
 }
 
 uint64_t ExprValue::getSectionOffset() const {
@@ -77,52 +131,51 @@ uint64_t ExprValue::getSectionOffset() const {
   return getValue() - getSecAddr();
 }
 
-OutputSection *LinkerScript::createOutputSection(StringRef name,
-                                                 StringRef location) {
-  OutputSection *&secRef = nameToOutputSection[name];
-  OutputSection *sec;
-  if (secRef && secRef->location.empty()) {
+OutputDesc *LinkerScript::createOutputSection(StringRef name,
+                                              StringRef location) {
+  OutputDesc *&secRef = nameToOutputSection[CachedHashStringRef(name)];
+  OutputDesc *sec;
+  if (secRef && secRef->osec.location.empty()) {
     // There was a forward reference.
     sec = secRef;
   } else {
-    sec = make<OutputSection>(name, SHT_PROGBITS, 0);
+    sec = make<OutputDesc>(name, SHT_PROGBITS, 0);
     if (!secRef)
       secRef = sec;
   }
-  sec->location = std::string(location);
+  sec->osec.location = std::string(location);
   return sec;
 }
 
-OutputSection *LinkerScript::getOrCreateOutputSection(StringRef name) {
-  OutputSection *&cmdRef = nameToOutputSection[name];
+OutputDesc *LinkerScript::getOrCreateOutputSection(StringRef name) {
+  OutputDesc *&cmdRef = nameToOutputSection[CachedHashStringRef(name)];
   if (!cmdRef)
-    cmdRef = make<OutputSection>(name, SHT_PROGBITS, 0);
+    cmdRef = make<OutputDesc>(name, SHT_PROGBITS, 0);
   return cmdRef;
 }
 
 // Expands the memory region by the specified size.
 static void expandMemoryRegion(MemoryRegion *memRegion, uint64_t size,
-                               StringRef regionName, StringRef secName) {
+                               StringRef secName) {
   memRegion->curPos += size;
   uint64_t newSize = memRegion->curPos - (memRegion->origin)().getValue();
   uint64_t length = (memRegion->length)().getValue();
   if (newSize > length)
-    error("section '" + secName + "' will not fit in region '" + regionName +
-          "': overflowed by " + Twine(newSize - length) + " bytes");
+    error("section '" + secName + "' will not fit in region '" +
+          memRegion->name + "': overflowed by " + Twine(newSize - length) +
+          " bytes");
 }
 
 void LinkerScript::expandMemoryRegions(uint64_t size) {
-  if (ctx->memRegion)
-    expandMemoryRegion(ctx->memRegion, size, ctx->memRegion->name,
-                       ctx->outSec->name);
+  if (state->memRegion)
+    expandMemoryRegion(state->memRegion, size, state->outSec->name);
   // Only expand the LMARegion if it is different from memRegion.
-  if (ctx->lmaRegion && ctx->memRegion != ctx->lmaRegion)
-    expandMemoryRegion(ctx->lmaRegion, size, ctx->lmaRegion->name,
-                       ctx->outSec->name);
+  if (state->lmaRegion && state->memRegion != state->lmaRegion)
+    expandMemoryRegion(state->lmaRegion, size, state->outSec->name);
 }
 
 void LinkerScript::expandOutputSection(uint64_t size) {
-  ctx->outSec->size += size;
+  state->outSec->size += size;
   expandMemoryRegions(size);
 }
 
@@ -130,7 +183,7 @@ void LinkerScript::setDot(Expr e, const Twine &loc, bool inSec) {
   uint64_t val = e().getValue();
   if (val < dot && inSec)
     error(loc + ": unable to move location counter backward for: " +
-          ctx->outSec->name);
+          state->outSec->name);
 
   // Update to location counter means update to section size.
   if (inSec)
@@ -151,8 +204,8 @@ static bool shouldDefineSym(SymbolAssignment *cmd) {
 
   // If a symbol was in PROVIDE(), we need to define it only
   // when it is a referenced undefined symbol.
-  Symbol *b = symtab->find(cmd->name);
-  if (b && !b->isDefined())
+  Symbol *b = symtab.find(cmd->name);
+  if (b && !b->isDefined() && !b->isCommon())
     return true;
   return false;
 }
@@ -184,9 +237,10 @@ void LinkerScript::addSymbol(SymbolAssignment *cmd) {
   Defined newSym(nullptr, cmd->name, STB_GLOBAL, visibility, value.type,
                  symValue, 0, sec);
 
-  Symbol *sym = symtab->insert(cmd->name);
+  Symbol *sym = symtab.insert(cmd->name);
   sym->mergeProperties(newSym);
-  sym->replace(newSym);
+  newSym.overwrite(*sym);
+  sym->isUsedInRegularObj = true;
   cmd->sym = cast<Defined>(sym);
 }
 
@@ -201,12 +255,13 @@ static void declareSymbol(SymbolAssignment *cmd) {
                  nullptr);
 
   // We can't calculate final value right now.
-  Symbol *sym = symtab->insert(cmd->name);
+  Symbol *sym = symtab.insert(cmd->name);
   sym->mergeProperties(newSym);
-  sym->replace(newSym);
+  newSym.overwrite(*sym);
 
   cmd->sym = cast<Defined>(sym);
   cmd->provide = false;
+  sym->isUsedInRegularObj = true;
   sym->scriptDefined = true;
 }
 
@@ -216,20 +271,20 @@ using SymbolAssignmentMap =
 // Collect section/value pairs of linker-script-defined symbols. This is used to
 // check whether symbol values converge.
 static SymbolAssignmentMap
-getSymbolAssignmentValues(const std::vector<BaseCommand *> &sectionCommands) {
+getSymbolAssignmentValues(ArrayRef<SectionCommand *> sectionCommands) {
   SymbolAssignmentMap ret;
-  for (BaseCommand *base : sectionCommands) {
-    if (auto *cmd = dyn_cast<SymbolAssignment>(base)) {
-      if (cmd->sym) // sym is nullptr for dot.
-        ret.try_emplace(cmd->sym,
-                        std::make_pair(cmd->sym->section, cmd->sym->value));
+  for (SectionCommand *cmd : sectionCommands) {
+    if (auto *assign = dyn_cast<SymbolAssignment>(cmd)) {
+      if (assign->sym) // sym is nullptr for dot.
+        ret.try_emplace(assign->sym, std::make_pair(assign->sym->section,
+                                                    assign->sym->value));
       continue;
     }
-    for (BaseCommand *sub_base : cast<OutputSection>(base)->sectionCommands)
-      if (auto *cmd = dyn_cast<SymbolAssignment>(sub_base))
-        if (cmd->sym)
-          ret.try_emplace(cmd->sym,
-                          std::make_pair(cmd->sym->section, cmd->sym->value));
+    for (SectionCommand *subCmd : cast<OutputDesc>(cmd)->osec.commands)
+      if (auto *assign = dyn_cast<SymbolAssignment>(subCmd))
+        if (assign->sym)
+          ret.try_emplace(assign->sym, std::make_pair(assign->sym->section,
+                                                      assign->sym->value));
   }
   return ret;
 }
@@ -251,25 +306,26 @@ getChangedSymbolAssignment(const SymbolAssignmentMap &oldValues) {
 // Process INSERT [AFTER|BEFORE] commands. For each command, we move the
 // specified output section to the designated place.
 void LinkerScript::processInsertCommands() {
-  std::vector<OutputSection *> moves;
+  SmallVector<OutputDesc *, 0> moves;
   for (const InsertCommand &cmd : insertCommands) {
     for (StringRef name : cmd.names) {
       // If base is empty, it may have been discarded by
-      // adjustSectionsBeforeSorting(). We do not handle such output sections.
-      auto from = llvm::find_if(sectionCommands, [&](BaseCommand *base) {
-        return isa<OutputSection>(base) &&
-               cast<OutputSection>(base)->name == name;
+      // adjustOutputSections(). We do not handle such output sections.
+      auto from = llvm::find_if(sectionCommands, [&](SectionCommand *subCmd) {
+        return isa<OutputDesc>(subCmd) &&
+               cast<OutputDesc>(subCmd)->osec.name == name;
       });
       if (from == sectionCommands.end())
         continue;
-      moves.push_back(cast<OutputSection>(*from));
+      moves.push_back(cast<OutputDesc>(*from));
       sectionCommands.erase(from);
     }
 
-    auto insertPos = llvm::find_if(sectionCommands, [&cmd](BaseCommand *base) {
-      auto *to = dyn_cast<OutputSection>(base);
-      return to != nullptr && to->name == cmd.where;
-    });
+    auto insertPos =
+        llvm::find_if(sectionCommands, [&cmd](SectionCommand *subCmd) {
+          auto *to = dyn_cast<OutputDesc>(subCmd);
+          return to != nullptr && to->osec.name == cmd.where;
+        });
     if (insertPos == sectionCommands.end()) {
       error("unable to insert " + cmd.names[0] +
             (cmd.isAfter ? " after " : " before ") + cmd.where);
@@ -286,10 +342,10 @@ void LinkerScript::processInsertCommands() {
 // we don't know their final values until late stages of link. Here we scan
 // over symbol assignment commands and create placeholder symbols if needed.
 void LinkerScript::declareSymbols() {
-  assert(!ctx);
-  for (BaseCommand *base : sectionCommands) {
-    if (auto *cmd = dyn_cast<SymbolAssignment>(base)) {
-      declareSymbol(cmd);
+  assert(!state);
+  for (SectionCommand *cmd : sectionCommands) {
+    if (auto *assign = dyn_cast<SymbolAssignment>(cmd)) {
+      declareSymbol(assign);
       continue;
     }
 
@@ -297,12 +353,12 @@ void LinkerScript::declareSymbols() {
     // we can't say for sure if it is going to be included or not.
     // Skip such sections for now. Improve the checks if we ever
     // need symbols from that sections to be declared early.
-    auto *sec = cast<OutputSection>(base);
-    if (sec->constraint != ConstraintKind::NoConstraint)
+    const OutputSection &sec = cast<OutputDesc>(cmd)->osec;
+    if (sec.constraint != ConstraintKind::NoConstraint)
       continue;
-    for (BaseCommand *base2 : sec->sectionCommands)
-      if (auto *cmd = dyn_cast<SymbolAssignment>(base2))
-        declareSymbol(cmd);
+    for (SectionCommand *cmd : sec.commands)
+      if (auto *assign = dyn_cast<SymbolAssignment>(cmd))
+        declareSymbol(assign);
   }
 }
 
@@ -383,7 +439,7 @@ static void sortSections(MutableArrayRef<InputSectionBase *> vec,
     // ">" is not a mistake. Sections with larger alignments are placed
     // before sections with smaller alignments in order to reduce the
     // amount of padding necessary. This is compatible with GNU.
-    return a->alignment > b->alignment;
+    return a->addralign > b->addralign;
   };
   auto nameComparator = [](InputSectionBase *a, InputSectionBase *b) {
     return a->name < b->name;
@@ -430,11 +486,11 @@ static void sortInputSections(MutableArrayRef<InputSectionBase *> vec,
 }
 
 // Compute and remember which sections the InputSectionDescription matches.
-std::vector<InputSectionBase *>
+SmallVector<InputSectionBase *, 0>
 LinkerScript::computeInputSections(const InputSectionDescription *cmd,
                                    ArrayRef<InputSectionBase *> sections) {
-  std::vector<InputSectionBase *> ret;
-  std::vector<size_t> indexes;
+  SmallVector<InputSectionBase *, 0> ret;
+  SmallVector<size_t, 0> indexes;
   DenseSet<size_t> seen;
   auto sortByPositionThenCommandLine = [&](size_t begin, size_t end) {
     llvm::sort(MutableArrayRef<size_t>(indexes).slice(begin, end - begin));
@@ -457,7 +513,7 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
       if (!sec->isLive() || sec->parent || seen.contains(i))
         continue;
 
-      // For -emit-relocs we have to ignore entries like
+      // For --emit-relocs we have to ignore entries like
       //   .rela.dyn : { *(.rela.data) }
       // which are common because they are in the default bfd script.
       // We do not ignore SHT_REL[A] linker-synthesized sections here because
@@ -504,50 +560,40 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
   return ret;
 }
 
-void LinkerScript::discard(InputSectionBase *s) {
-  if (s == in.shStrTab || s == mainPart->relrDyn)
-    error("discarding " + s->name + " section is not allowed");
-
-  // You can discard .hash and .gnu.hash sections by linker scripts. Since
-  // they are synthesized sections, we need to handle them differently than
-  // other regular sections.
-  if (s == mainPart->gnuHashTab)
-    mainPart->gnuHashTab = nullptr;
-  if (s == mainPart->hashTab)
-    mainPart->hashTab = nullptr;
-
-  s->markDead();
-  s->parent = nullptr;
-  for (InputSection *ds : s->dependentSections)
-    discard(ds);
+void LinkerScript::discard(InputSectionBase &s) {
+  if (&s == in.shStrTab.get())
+    error("discarding " + s.name + " section is not allowed");
+
+  s.markDead();
+  s.parent = nullptr;
+  for (InputSection *sec : s.dependentSections)
+    discard(*sec);
 }
 
 void LinkerScript::discardSynthetic(OutputSection &outCmd) {
   for (Partition &part : partitions) {
     if (!part.armExidx || !part.armExidx->isLive())
       continue;
-    std::vector<InputSectionBase *> secs(part.armExidx->exidxSections.begin(),
-                                         part.armExidx->exidxSections.end());
-    for (BaseCommand *base : outCmd.sectionCommands)
-      if (auto *cmd = dyn_cast<InputSectionDescription>(base)) {
-        std::vector<InputSectionBase *> matches =
-            computeInputSections(cmd, secs);
-        for (InputSectionBase *s : matches)
-          discard(s);
-      }
+    SmallVector<InputSectionBase *, 0> secs(
+        part.armExidx->exidxSections.begin(),
+        part.armExidx->exidxSections.end());
+    for (SectionCommand *cmd : outCmd.commands)
+      if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
+        for (InputSectionBase *s : computeInputSections(isd, secs))
+          discard(*s);
   }
 }
 
-std::vector<InputSectionBase *>
+SmallVector<InputSectionBase *, 0>
 LinkerScript::createInputSectionList(OutputSection &outCmd) {
-  std::vector<InputSectionBase *> ret;
+  SmallVector<InputSectionBase *, 0> ret;
 
-  for (BaseCommand *base : outCmd.sectionCommands) {
-    if (auto *cmd = dyn_cast<InputSectionDescription>(base)) {
-      cmd->sectionBases = computeInputSections(cmd, inputSections);
-      for (InputSectionBase *s : cmd->sectionBases)
+  for (SectionCommand *cmd : outCmd.commands) {
+    if (auto *isd = dyn_cast<InputSectionDescription>(cmd)) {
+      isd->sectionBases = computeInputSections(isd, ctx.inputSections);
+      for (InputSectionBase *s : isd->sectionBases)
         s->parent = &outCmd;
-      ret.insert(ret.end(), cmd->sectionBases.begin(), cmd->sectionBases.end());
+      ret.insert(ret.end(), isd->sectionBases.begin(), isd->sectionBases.end());
     }
   }
   return ret;
@@ -556,15 +602,15 @@ LinkerScript::createInputSectionList(OutputSection &outCmd) {
 // Create output sections described by SECTIONS commands.
 void LinkerScript::processSectionCommands() {
   auto process = [this](OutputSection *osec) {
-    std::vector<InputSectionBase *> v = createInputSectionList(*osec);
+    SmallVector<InputSectionBase *, 0> v = createInputSectionList(*osec);
 
     // The output section name `/DISCARD/' is special.
     // Any input section assigned to it is discarded.
     if (osec->name == "/DISCARD/") {
       for (InputSectionBase *s : v)
-        discard(s);
+        discard(*s);
       discardSynthetic(*osec);
-      osec->sectionCommands.clear();
+      osec->commands.clear();
       return false;
     }
 
@@ -578,7 +624,7 @@ void LinkerScript::processSectionCommands() {
     if (!matchConstraints(v, osec->constraint)) {
       for (InputSectionBase *s : v)
         s->parent = nullptr;
-      osec->sectionCommands.clear();
+      osec->commands.clear();
       return false;
     }
 
@@ -588,7 +634,7 @@ void LinkerScript::processSectionCommands() {
     if (osec->subalignExpr) {
       uint32_t subalign = osec->subalignExpr().getValue();
       for (InputSectionBase *s : v)
-        s->alignment = subalign;
+        s->addralign = subalign;
     }
 
     // Set the partition field the same way OutputSection::recordSection()
@@ -600,16 +646,20 @@ void LinkerScript::processSectionCommands() {
 
   // Process OVERWRITE_SECTIONS first so that it can overwrite the main script
   // or orphans.
-  DenseMap<StringRef, OutputSection *> map;
+  DenseMap<CachedHashStringRef, OutputDesc *> map;
   size_t i = 0;
-  for (OutputSection *osec : overwriteSections)
-    if (process(osec) && !map.try_emplace(osec->name, osec).second)
+  for (OutputDesc *osd : overwriteSections) {
+    OutputSection *osec = &osd->osec;
+    if (process(osec) &&
+        !map.try_emplace(CachedHashStringRef(osec->name), osd).second)
       warn("OVERWRITE_SECTIONS specifies duplicate " + osec->name);
-  for (BaseCommand *&base : sectionCommands)
-    if (auto *osec = dyn_cast<OutputSection>(base)) {
-      if (OutputSection *overwrite = map.lookup(osec->name)) {
-        log(overwrite->location + " overwrites " + osec->name);
-        overwrite->sectionIndex = i++;
+  }
+  for (SectionCommand *&base : sectionCommands)
+    if (auto *osd = dyn_cast<OutputDesc>(base)) {
+      OutputSection *osec = &osd->osec;
+      if (OutputDesc *overwrite = map.lookup(CachedHashStringRef(osec->name))) {
+        log(overwrite->osec.location + " overwrites " + osec->name);
+        overwrite->osec.sectionIndex = i++;
         base = overwrite;
       } else if (process(osec)) {
         osec->sectionIndex = i++;
@@ -619,9 +669,9 @@ void LinkerScript::processSectionCommands() {
   // If an OVERWRITE_SECTIONS specified output section is not in
   // sectionCommands, append it to the end. The section will be inserted by
   // orphan placement.
-  for (OutputSection *osec : overwriteSections)
-    if (osec->partition == 1 && osec->sectionIndex == UINT32_MAX)
-      sectionCommands.push_back(osec);
+  for (OutputDesc *osd : overwriteSections)
+    if (osd->osec.partition == 1 && osd->osec.sectionIndex == UINT32_MAX)
+      sectionCommands.push_back(osd);
 }
 
 void LinkerScript::processSymbolAssignments() {
@@ -632,44 +682,42 @@ void LinkerScript::processSymbolAssignments() {
   aether = make<OutputSection>("", 0, SHF_ALLOC);
   aether->sectionIndex = 1;
 
-  // ctx captures the local AddressState and makes it accessible deliberately.
+  // `st` captures the local AddressState and makes it accessible deliberately.
   // This is needed as there are some cases where we cannot just thread the
   // current state through to a lambda function created by the script parser.
-  AddressState state;
-  ctx = &state;
-  ctx->outSec = aether;
+  AddressState st;
+  state = &st;
+  st.outSec = aether;
 
-  for (BaseCommand *base : sectionCommands) {
-    if (auto *cmd = dyn_cast<SymbolAssignment>(base))
-      addSymbol(cmd);
+  for (SectionCommand *cmd : sectionCommands) {
+    if (auto *assign = dyn_cast<SymbolAssignment>(cmd))
+      addSymbol(assign);
     else
-      for (BaseCommand *sub_base : cast<OutputSection>(base)->sectionCommands)
-        if (auto *cmd = dyn_cast<SymbolAssignment>(sub_base))
-          addSymbol(cmd);
+      for (SectionCommand *subCmd : cast<OutputDesc>(cmd)->osec.commands)
+        if (auto *assign = dyn_cast<SymbolAssignment>(subCmd))
+          addSymbol(assign);
   }
 
-  ctx = nullptr;
+  state = nullptr;
 }
 
-static OutputSection *findByName(ArrayRef<BaseCommand *> vec,
+static OutputSection *findByName(ArrayRef<SectionCommand *> vec,
                                  StringRef name) {
-  for (BaseCommand *base : vec)
-    if (auto *sec = dyn_cast<OutputSection>(base))
-      if (sec->name == name)
-        return sec;
+  for (SectionCommand *cmd : vec)
+    if (auto *osd = dyn_cast<OutputDesc>(cmd))
+      if (osd->osec.name == name)
+        return &osd->osec;
   return nullptr;
 }
 
-static OutputSection *createSection(InputSectionBase *isec,
-                                    StringRef outsecName) {
-  OutputSection *sec = script->createOutputSection(outsecName, "<internal>");
-  sec->recordSection(isec);
-  return sec;
+static OutputDesc *createSection(InputSectionBase *isec, StringRef outsecName) {
+  OutputDesc *osd = script->createOutputSection(outsecName, "<internal>");
+  osd->osec.recordSection(isec);
+  return osd;
 }
 
-static OutputSection *
-addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map,
-            InputSectionBase *isec, StringRef outsecName) {
+static OutputDesc *addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map,
+                               InputSectionBase *isec, StringRef outsecName) {
   // Sections with SHT_GROUP or SHF_GROUP attributes reach here only when the -r
   // option is given. A section with SHT_GROUP defines a "section group", and
   // its members have SHF_GROUP attribute. Usually these flags have already been
@@ -696,8 +744,9 @@ addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map,
       return nullptr;
     }
 
-    out->relocationSection = createSection(isec, outsecName);
-    return out->relocationSection;
+    OutputDesc *osd = createSection(isec, outsecName);
+    out->relocationSection = &osd->osec;
+    return osd;
   }
 
   //  The ELF spec just says
@@ -753,8 +802,7 @@ addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map,
       // end up being linked to the same output section. The casts are fine
       // because everything in the map was created by the orphan placement code.
       auto *firstIsec = cast<InputSectionBase>(
-          cast<InputSectionDescription>(sec->sectionCommands[0])
-              ->sectionBases[0]);
+          cast<InputSectionDescription>(sec->commands[0])->sectionBases[0]);
       OutputSection *firstIsecOut =
           firstIsec->flags & SHF_LINK_ORDER
               ? firstIsec->getLinkOrderDep()->getOutputSection()
@@ -767,18 +815,17 @@ addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map,
     return nullptr;
   }
 
-  OutputSection *sec = createSection(isec, outsecName);
-  v.push_back(sec);
-  return sec;
+  OutputDesc *osd = createSection(isec, outsecName);
+  v.push_back(&osd->osec);
+  return osd;
 }
 
 // Add sections that didn't match any sections command.
 void LinkerScript::addOrphanSections() {
   StringMap<TinyPtrVector<OutputSection *>> map;
-  std::vector<OutputSection *> v;
+  SmallVector<OutputDesc *, 0> v;
 
-  std::function<void(InputSectionBase *)> add;
-  add = [&](InputSectionBase *s) {
+  auto add = [&](InputSectionBase *s) {
     if (s->isLive() && !s->parent) {
       orphanSections.push_back(s);
 
@@ -788,24 +835,24 @@ void LinkerScript::addOrphanSections() {
       } else if (OutputSection *sec = findByName(sectionCommands, name)) {
         sec->recordSection(s);
       } else {
-        if (OutputSection *os = addInputSec(map, s, name))
-          v.push_back(os);
+        if (OutputDesc *osd = addInputSec(map, s, name))
+          v.push_back(osd);
         assert(isa<MergeInputSection>(s) ||
                s->getOutputSection()->sectionIndex == UINT32_MAX);
       }
     }
-
-    if (config->relocatable)
-      for (InputSectionBase *depSec : s->dependentSections)
-        if (depSec->flags & SHF_LINK_ORDER)
-          add(depSec);
   };
 
   // For further --emit-reloc handling code we need target output section
   // to be created before we create relocation output section, so we want
   // to create target sections first. We do not want priority handling
   // for synthetic sections because them are special.
-  for (InputSectionBase *isec : inputSections) {
+  size_t n = 0;
+  for (InputSectionBase *isec : ctx.inputSections) {
+    // Process InputSection and MergeInputSection.
+    if (LLVM_LIKELY(isa<InputSection>(isec)))
+      ctx.inputSections[n++] = isec;
+
     // In -r links, SHF_LINK_ORDER sections are added while adding their parent
     // sections because we need to know the parent's output section before we
     // can select an output section for the SHF_LINK_ORDER section.
@@ -817,7 +864,13 @@ void LinkerScript::addOrphanSections() {
         if (auto *relIS = dyn_cast_or_null<InputSectionBase>(rel->parent))
           add(relIS);
     add(isec);
+    if (config->relocatable)
+      for (InputSectionBase *depSec : isec->dependentSections)
+        if (depSec->flags & SHF_LINK_ORDER)
+          add(depSec);
   }
+  // Keep just InputSection.
+  ctx.inputSections.resize(n);
 
   // If no SECTIONS command was given, we should insert sections commands
   // before others, so that we can handle scripts which refers them,
@@ -848,68 +901,50 @@ void LinkerScript::diagnoseOrphanHandling() const {
   }
 }
 
-uint64_t LinkerScript::advance(uint64_t size, unsigned alignment) {
-  dot = alignTo(dot, alignment) + size;
-  return dot;
-}
-
-void LinkerScript::output(InputSection *s) {
-  assert(ctx->outSec == s->getParent());
-  uint64_t before = advance(0, 1);
-  uint64_t pos = advance(s->getSize(), s->alignment);
-  s->outSecOff = pos - s->getSize() - ctx->outSec->addr;
-
-  // Update output section size after adding each section. This is so that
-  // SIZEOF works correctly in the case below:
-  // .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) }
-  expandOutputSection(pos - before);
-}
-
-void LinkerScript::switchTo(OutputSection *sec) {
-  ctx->outSec = sec;
-
-  uint64_t pos = advance(0, 1);
-  if (sec->addrExpr && script->hasSectionsCommand) {
-    // The alignment is ignored.
-    ctx->outSec->addr = pos;
-  } else {
-    // ctx->outSec->alignment is the max of ALIGN and the maximum of input
-    // section alignments.
-    ctx->outSec->addr = advance(0, ctx->outSec->alignment);
-    expandMemoryRegions(ctx->outSec->addr - pos);
-  }
-}
-
 // This function searches for a memory region to place the given output
 // section in. If found, a pointer to the appropriate memory region is
-// returned. Otherwise, a nullptr is returned.
-MemoryRegion *LinkerScript::findMemoryRegion(OutputSection *sec) {
+// returned in the first member of the pair. Otherwise, a nullptr is returned.
+// The second member of the pair is a hint that should be passed to the
+// subsequent call of this method.
+std::pair<MemoryRegion *, MemoryRegion *>
+LinkerScript::findMemoryRegion(OutputSection *sec, MemoryRegion *hint) {
+  // Non-allocatable sections are not part of the process image.
+  if (!(sec->flags & SHF_ALLOC)) {
+    if (!sec->memoryRegionName.empty())
+      warn("ignoring memory region assignment for non-allocatable section '" +
+           sec->name + "'");
+    return {nullptr, nullptr};
+  }
+
   // If a memory region name was specified in the output section command,
   // then try to find that region first.
   if (!sec->memoryRegionName.empty()) {
     if (MemoryRegion *m = memoryRegions.lookup(sec->memoryRegionName))
-      return m;
+      return {m, m};
     error("memory region '" + sec->memoryRegionName + "' not declared");
-    return nullptr;
+    return {nullptr, nullptr};
   }
 
   // If at least one memory region is defined, all sections must
   // belong to some memory region. Otherwise, we don't need to do
   // anything for memory regions.
   if (memoryRegions.empty())
-    return nullptr;
+    return {nullptr, nullptr};
+
+  // An orphan section should continue the previous memory region.
+  if (sec->sectionIndex == UINT32_MAX && hint)
+    return {hint, hint};
 
   // See if a region can be found by matching section flags.
   for (auto &pair : memoryRegions) {
     MemoryRegion *m = pair.second;
-    if ((m->flags & sec->flags) && (m->negFlags & sec->flags) == 0)
-      return m;
+    if (m->compatibleWith(sec->flags))
+      return {m, nullptr};
   }
 
   // Otherwise, no suitable region was found.
-  if (sec->flags & SHF_ALLOC)
-    error("no memory region specified for section '" + sec->name + "'");
-  return nullptr;
+  error("no memory region specified for section '" + sec->name + "'");
+  return {nullptr, nullptr};
 }
 
 static OutputSection *findFirstSection(PhdrEntry *load) {
@@ -923,11 +958,11 @@ static OutputSection *findFirstSection(PhdrEntry *load) {
 // for a single sections command (e.g. ".text { *(.text); }").
 void LinkerScript::assignOffsets(OutputSection *sec) {
   const bool isTbss = (sec->flags & SHF_TLS) && sec->type == SHT_NOBITS;
-  const bool sameMemRegion = ctx->memRegion == sec->memRegion;
-  const bool prevLMARegionIsDefault = ctx->lmaRegion == nullptr;
+  const bool sameMemRegion = state->memRegion == sec->memRegion;
+  const bool prevLMARegionIsDefault = state->lmaRegion == nullptr;
   const uint64_t savedDot = dot;
-  ctx->memRegion = sec->memRegion;
-  ctx->lmaRegion = sec->lmaRegion;
+  state->memRegion = sec->memRegion;
+  state->lmaRegion = sec->lmaRegion;
 
   if (!(sec->flags & SHF_ALLOC)) {
     // Non-SHF_ALLOC sections have zero addresses.
@@ -935,13 +970,13 @@ void LinkerScript::assignOffsets(OutputSection *sec) {
   } else if (isTbss) {
     // Allow consecutive SHF_TLS SHT_NOBITS output sections. The address range
     // starts from the end address of the previous tbss section.
-    if (ctx->tbssAddr == 0)
-      ctx->tbssAddr = dot;
+    if (state->tbssAddr == 0)
+      state->tbssAddr = dot;
     else
-      dot = ctx->tbssAddr;
+      dot = state->tbssAddr;
   } else {
-    if (ctx->memRegion)
-      dot = ctx->memRegion->curPos;
+    if (state->memRegion)
+      dot = state->memRegion->curPos;
     if (sec->addrExpr)
       setDot(sec->addrExpr, sec->location, false);
 
@@ -949,31 +984,51 @@ void LinkerScript::assignOffsets(OutputSection *sec) {
     // expression so that it now starts past the current curPos of the enclosing
     // region, we need to expand the current region to account for the space
     // between the previous section, if any, and the start of this section.
-    if (ctx->memRegion && ctx->memRegion->curPos < dot)
-      expandMemoryRegion(ctx->memRegion, dot - ctx->memRegion->curPos,
-                         ctx->memRegion->name, sec->name);
+    if (state->memRegion && state->memRegion->curPos < dot)
+      expandMemoryRegion(state->memRegion, dot - state->memRegion->curPos,
+                         sec->name);
   }
 
+  // This section was previously a call to switchTo(), but switchTo()
+  // was unrolled here.
+  // On OpenBSD, we had consistently moved the call to switchTo()
+  // below the next section.
+  state->outSec = sec;
+  if (sec->addrExpr && script->hasSectionsCommand) {
+    // The alignment is ignored.
+    sec->addr = dot;
+  } else {
+    // sec->alignment is the max of ALIGN and the maximum of input
+    // section alignments.
+    const uint64_t pos = dot;
+    dot = alignToPowerOf2(dot, sec->addralign);
+    sec->addr = dot;
+    expandMemoryRegions(dot - pos);
+  }
 
-  // ctx->lmaOffset is LMA minus VMA. If LMA is explicitly specified via AT() or
-  // AT>, recompute ctx->lmaOffset; otherwise, if both previous/current LMA
+  // state->lmaOffset is LMA minus VMA. If LMA is explicitly specified via AT()
+  // or AT>, recompute state->lmaOffset; otherwise, if both previous/current LMA
   // region is the default, and the two sections are in the same memory region,
   // reuse previous lmaOffset; otherwise, reset lmaOffset to 0. This emulates
   // heuristics described in
   // https://sourceware.org/binutils/docs/ld/Output-Section-LMA.html
-  if (sec->lmaExpr)
-    ctx->lmaOffset = sec->lmaExpr().getValue() - dot;
-  else if (MemoryRegion *mr = sec->lmaRegion)
-    ctx->lmaOffset = alignTo(mr->curPos, sec->alignment) - dot;
-  else if (!sameMemRegion || !prevLMARegionIsDefault)
-    ctx->lmaOffset = 0;
+  if (sec->lmaExpr) {
+    state->lmaOffset = sec->lmaExpr().getValue() - dot;
+  } else if (MemoryRegion *mr = sec->lmaRegion) {
+    uint64_t lmaStart = alignToPowerOf2(mr->curPos, sec->addralign);
+    if (mr->curPos < lmaStart)
+      expandMemoryRegion(mr, lmaStart - mr->curPos, sec->name);
+    state->lmaOffset = lmaStart - dot;
+  } else if (!sameMemRegion || !prevLMARegionIsDefault) {
+    state->lmaOffset = 0;
+  }
 
-  switchTo(sec);
+  // On OpenBSD, the switchTo() call was here.
 
-  // Propagate ctx->lmaOffset to the first "non-header" section.
-  if (PhdrEntry *l = ctx->outSec->ptLoad)
+  // Propagate state->lmaOffset to the first "non-header" section.
+  if (PhdrEntry *l = sec->ptLoad)
     if (sec == findFirstSection(l))
-      l->lmaOffset = ctx->lmaOffset;
+      l->lmaOffset = state->lmaOffset;
 
   // We can call this method multiple times during the creation of
   // thunks and want to start over calculation each time.
@@ -982,28 +1037,38 @@ void LinkerScript::assignOffsets(OutputSection *sec) {
   // We visited SectionsCommands from processSectionCommands to
   // layout sections. Now, we visit SectionsCommands again to fix
   // section offsets.
-  for (BaseCommand *base : sec->sectionCommands) {
+  for (SectionCommand *cmd : sec->commands) {
     // This handles the assignments to symbol or to the dot.
-    if (auto *cmd = dyn_cast<SymbolAssignment>(base)) {
-      cmd->addr = dot;
-      assignSymbol(cmd, true);
-      cmd->size = dot - cmd->addr;
+    if (auto *assign = dyn_cast<SymbolAssignment>(cmd)) {
+      assign->addr = dot;
+      assignSymbol(assign, true);
+      assign->size = dot - assign->addr;
       continue;
     }
 
     // Handle BYTE(), SHORT(), LONG(), or QUAD().
-    if (auto *cmd = dyn_cast<ByteCommand>(base)) {
-      cmd->offset = dot - ctx->outSec->addr;
-      dot += cmd->size;
-      expandOutputSection(cmd->size);
+    if (auto *data = dyn_cast<ByteCommand>(cmd)) {
+      data->offset = dot - sec->addr;
+      dot += data->size;
+      expandOutputSection(data->size);
       continue;
     }
 
     // Handle a single input section description command.
     // It calculates and assigns the offsets for each section and also
     // updates the output section size.
-    for (InputSection *sec : cast<InputSectionDescription>(base)->sections)
-      output(sec);
+    for (InputSection *isec : cast<InputSectionDescription>(cmd)->sections) {
+      assert(isec->getParent() == sec);
+      const uint64_t pos = dot;
+      dot = alignToPowerOf2(dot, isec->addralign);
+      isec->outSecOff = dot - sec->addr;
+      dot += isec->getSize();
+
+      // Update output section size after adding each section. This is so that
+      // SIZEOF works correctly in the case below:
+      // .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) }
+      expandOutputSection(dot - pos);
+    }
   }
 
   // Non-SHF_ALLOC sections do not affect the addresses of other OutputSections
@@ -1012,12 +1077,12 @@ void LinkerScript::assignOffsets(OutputSection *sec) {
     dot = savedDot;
   } else if (isTbss) {
     // NOBITS TLS sections are similar. Additionally save the end address.
-    ctx->tbssAddr = dot;
+    state->tbssAddr = dot;
     dot = savedDot;
   }
 }
 
-static bool isDiscardable(OutputSection &sec) {
+static bool isDiscardable(const OutputSection &sec) {
   if (sec.name == "/DISCARD/")
     return true;
 
@@ -1033,21 +1098,26 @@ static bool isDiscardable(OutputSection &sec) {
   if (sec.usedInExpression)
     return false;
 
-  for (BaseCommand *base : sec.sectionCommands) {
-    if (auto cmd = dyn_cast<SymbolAssignment>(base))
+  for (SectionCommand *cmd : sec.commands) {
+    if (auto assign = dyn_cast<SymbolAssignment>(cmd))
       // Don't create empty output sections just for unreferenced PROVIDE
       // symbols.
-      if (cmd->name != "." && !cmd->sym)
+      if (assign->name != "." && !assign->sym)
         continue;
 
-    if (!isa<InputSectionDescription>(*base))
+    if (!isa<InputSectionDescription>(*cmd))
       return false;
   }
   return true;
 }
 
+bool LinkerScript::isDiscarded(const OutputSection *sec) const {
+  return hasSectionsCommand && (getFirstInputSection(sec) == nullptr) &&
+         isDiscardable(*sec);
+}
+
 static void maybePropagatePhdrs(OutputSection &sec,
-                                std::vector<StringRef> &phdrs) {
+                                SmallVector<StringRef, 0> &phdrs) {
   if (sec.phdrs.empty()) {
     // To match the bfd linker script behaviour, only propagate program
     // headers to sections that are allocated.
@@ -1058,7 +1128,7 @@ static void maybePropagatePhdrs(OutputSection &sec,
   }
 }
 
-void LinkerScript::adjustSectionsBeforeSorting() {
+void LinkerScript::adjustOutputSections() {
   // If the output section contains only symbol assignments, create a
   // corresponding output section. The issue is what to do with linker script
   // like ".foo : { symbol = 42; }". One option would be to convert it to
@@ -1081,25 +1151,27 @@ void LinkerScript::adjustSectionsBeforeSorting() {
   // the previous sections. Only a few flags are needed to keep the impact low.
   uint64_t flags = SHF_ALLOC;
 
-  std::vector<StringRef> defPhdrs;
-  for (BaseCommand *&cmd : sectionCommands) {
-    auto *sec = dyn_cast<OutputSection>(cmd);
-    if (!sec)
+  SmallVector<StringRef, 0> defPhdrs;
+  for (SectionCommand *&cmd : sectionCommands) {
+    if (!isa<OutputDesc>(cmd))
       continue;
+    auto *sec = &cast<OutputDesc>(cmd)->osec;
 
     // Handle align (e.g. ".foo : ALIGN(16) { ... }").
     if (sec->alignExpr)
-      sec->alignment =
-          std::max<uint32_t>(sec->alignment, sec->alignExpr().getValue());
+      sec->addralign =
+          std::max<uint32_t>(sec->addralign, sec->alignExpr().getValue());
 
-    // The input section might have been removed (if it was an empty synthetic
-    // section), but we at least know the flags.
-    if (sec->hasInputSections)
+    bool isEmpty = (getFirstInputSection(sec) == nullptr);
+    bool discardable = isEmpty && isDiscardable(*sec);
+    // If sec has at least one input section and not discarded, remember its
+    // flags to be inherited by subsequent output sections. (sec may contain
+    // just one empty synthetic section.)
+    if (sec->hasInputSections && !discardable)
       flags = sec->flags;
 
     // We do not want to keep any special flags for output section
     // in case it is empty.
-    bool isEmpty = (getFirstInputSection(sec) == nullptr);
     if (isEmpty)
       sec->flags = flags & ((sec->nonAlloc ? 0 : (uint64_t)SHF_ALLOC) |
                             SHF_WRITE | SHF_EXECINSTR);
@@ -1116,7 +1188,7 @@ void LinkerScript::adjustSectionsBeforeSorting() {
     if (sec->sectionIndex != UINT32_MAX)
       maybePropagatePhdrs(*sec, defPhdrs);
 
-    if (isEmpty && isDiscardable(*sec)) {
+    if (discardable) {
       sec->markDead();
       cmd = nullptr;
     }
@@ -1128,20 +1200,22 @@ void LinkerScript::adjustSectionsBeforeSorting() {
   // clutter the output.
   // We instead remove trivially empty sections. The bfd linker seems even
   // more aggressive at removing them.
-  llvm::erase_if(sectionCommands, [&](BaseCommand *base) { return !base; });
+  llvm::erase_if(sectionCommands, [&](SectionCommand *cmd) { return !cmd; });
 }
 
 void LinkerScript::adjustSectionsAfterSorting() {
   // Try and find an appropriate memory region to assign offsets in.
-  for (BaseCommand *base : sectionCommands) {
-    if (auto *sec = dyn_cast<OutputSection>(base)) {
+  MemoryRegion *hint = nullptr;
+  for (SectionCommand *cmd : sectionCommands) {
+    if (auto *osd = dyn_cast<OutputDesc>(cmd)) {
+      OutputSection *sec = &osd->osec;
       if (!sec->lmaRegionName.empty()) {
         if (MemoryRegion *m = memoryRegions.lookup(sec->lmaRegionName))
           sec->lmaRegion = m;
         else
           error("memory region '" + sec->lmaRegionName + "' not declared");
       }
-      sec->memRegion = findMemoryRegion(sec);
+      std::tie(sec->memRegion, hint) = findMemoryRegion(sec, hint);
     }
   }
 
@@ -1151,7 +1225,7 @@ void LinkerScript::adjustSectionsAfterSorting() {
   // Below is an example of such linker script:
   // PHDRS { seg PT_LOAD; }
   // SECTIONS { .aaa : { *(.aaa) } }
-  std::vector<StringRef> defPhdrs;
+  SmallVector<StringRef, 0> defPhdrs;
   auto firstPtLoad = llvm::find_if(phdrsCommands, [](const PhdrsCommand &cmd) {
     return cmd.type == PT_LOAD;
   });
@@ -1160,9 +1234,9 @@ void LinkerScript::adjustSectionsAfterSorting() {
 
   // Walk the commands and propagate the program headers to commands that don't
   // explicitly specify them.
-  for (BaseCommand *base : sectionCommands)
-    if (auto *sec = dyn_cast<OutputSection>(base))
-      maybePropagatePhdrs(*sec, defPhdrs);
+  for (SectionCommand *cmd : sectionCommands)
+    if (auto *osd = dyn_cast<OutputDesc>(cmd))
+      maybePropagatePhdrs(osd->osec, defPhdrs);
 }
 
 static uint64_t computeBase(uint64_t min, bool allocateHeaders) {
@@ -1181,7 +1255,7 @@ static uint64_t computeBase(uint64_t min, bool allocateHeaders) {
 // We check if the headers fit below the first allocated section. If there isn't
 // enough space for these sections, we'll remove them from the PT_LOAD segment,
 // and we'll also remove the PT_PHDR segment.
-void LinkerScript::allocateHeaders(std::vector<PhdrEntry *> &phdrs) {
+void LinkerScript::allocateHeaders(SmallVector<PhdrEntry *, 0> &phdrs) {
   uint64_t min = std::numeric_limits<uint64_t>::max();
   for (OutputSection *sec : outputSections)
     if (sec->flags & SHF_ALLOC)
@@ -1235,7 +1309,7 @@ const Defined *LinkerScript::assignAddresses() {
   if (script->hasSectionsCommand) {
     // With a linker script, assignment of addresses to headers is covered by
     // allocateHeaders().
-    dot = config->imageBase.getValueOr(0);
+    dot = config->imageBase.value_or(0);
   } else {
     // Assign addresses to headers right now.
     dot = target->getImageBase();
@@ -1244,34 +1318,34 @@ const Defined *LinkerScript::assignAddresses() {
     dot += getHeaderSize();
   }
 
-  auto deleter = std::make_unique<AddressState>();
-  ctx = deleter.get();
+  AddressState st;
+  state = &st;
   errorOnMissingSection = true;
-  switchTo(aether);
+  st.outSec = aether;
 
   SymbolAssignmentMap oldValues = getSymbolAssignmentValues(sectionCommands);
-  for (BaseCommand *base : sectionCommands) {
-    if (auto *cmd = dyn_cast<SymbolAssignment>(base)) {
-      cmd->addr = dot;
-      assignSymbol(cmd, false);
-      cmd->size = dot - cmd->addr;
+  for (SectionCommand *cmd : sectionCommands) {
+    if (auto *assign = dyn_cast<SymbolAssignment>(cmd)) {
+      assign->addr = dot;
+      assignSymbol(assign, false);
+      assign->size = dot - assign->addr;
       continue;
     }
-    assignOffsets(cast<OutputSection>(base));
+    assignOffsets(&cast<OutputDesc>(cmd)->osec);
   }
 
-  ctx = nullptr;
+  state = nullptr;
   return getChangedSymbolAssignment(oldValues);
 }
 
 // Creates program headers as instructed by PHDRS linker script command.
-std::vector<PhdrEntry *> LinkerScript::createPhdrs() {
-  std::vector<PhdrEntry *> ret;
+SmallVector<PhdrEntry *, 0> LinkerScript::createPhdrs() {
+  SmallVector<PhdrEntry *, 0> ret;
 
   // Process PHDRS and FILEHDR keywords because they are not
   // real output sections and cannot be added in the following loop.
   for (const PhdrsCommand &cmd : phdrsCommands) {
-    PhdrEntry *phdr = make<PhdrEntry>(cmd.type, cmd.flags ? *cmd.flags : PF_R);
+    PhdrEntry *phdr = make<PhdrEntry>(cmd.type, cmd.flags.value_or(PF_R));
 
     if (cmd.hasFilehdr)
       phdr->add(Out::elfHeader);
@@ -1290,7 +1364,7 @@ std::vector<PhdrEntry *> LinkerScript::createPhdrs() {
     // Assign headers specified by linker script
     for (size_t id : getPhdrIndices(sec)) {
       ret[id]->add(sec);
-      if (!phdrsCommands[id].flags.hasValue())
+      if (!phdrsCommands[id].flags)
         ret[id]->p_flags |= sec->getPhdrFlags();
     }
   }
@@ -1313,13 +1387,13 @@ bool LinkerScript::needsInterpSection() {
 
 ExprValue LinkerScript::getSymbolValue(StringRef name, const Twine &loc) {
   if (name == ".") {
-    if (ctx)
-      return {ctx->outSec, false, dot - ctx->outSec->addr, loc};
+    if (state)
+      return {state->outSec, false, dot - state->outSec->addr, loc};
     error(loc + ": unable to get location counter value");
     return 0;
   }
 
-  if (Symbol *sym = symtab->find(name)) {
+  if (Symbol *sym = symtab.find(name)) {
     if (auto *ds = dyn_cast<Defined>(sym)) {
       ExprValue v{ds->section, false, ds->value, loc};
       // Retain the original st_type, so that the alias will get the same
@@ -1338,21 +1412,21 @@ ExprValue LinkerScript::getSymbolValue(StringRef name, const Twine &loc) {
 }
 
 // Returns the index of the segment named Name.
-static Optional<size_t> getPhdrIndex(ArrayRef<PhdrsCommand> vec,
-                                     StringRef name) {
+static std::optional<size_t> getPhdrIndex(ArrayRef<PhdrsCommand> vec,
+                                          StringRef name) {
   for (size_t i = 0; i < vec.size(); ++i)
     if (vec[i].name == name)
       return i;
-  return None;
+  return std::nullopt;
 }
 
 // Returns indices of ELF headers containing specific section. Each index is a
 // zero based number of ELF header listed within PHDRS {} script block.
-std::vector<size_t> LinkerScript::getPhdrIndices(OutputSection *cmd) {
-  std::vector<size_t> ret;
+SmallVector<size_t, 0> LinkerScript::getPhdrIndices(OutputSection *cmd) {
+  SmallVector<size_t, 0> ret;
 
   for (StringRef s : cmd->phdrs) {
-    if (Optional<size_t> idx = getPhdrIndex(phdrsCommands, s))
+    if (std::optional<size_t> idx = getPhdrIndex(phdrsCommands, s))
       ret.push_back(*idx);
     else if (s != "NONE")
       error(cmd->location + ": program header '" + s +
index b13e0c5..b531d76 100644 (file)
@@ -50,10 +50,9 @@ def Bdynamic: F<"Bdynamic">, HelpText<"Link against shared libraries (default)">
 
 def Bstatic: F<"Bstatic">, HelpText<"Do not link against shared libraries">;
 
-def build_id: F<"build-id">, HelpText<"Alias for --build-id=fast">;
-
-def build_id_eq: J<"build-id=">, HelpText<"Generate build ID note">,
+def build_id: J<"build-id=">, HelpText<"Generate build ID note">,
   MetaVarName<"[fast,md5,sha1,uuid,0x<hexstring>]">;
+def : F<"build-id">, Alias<build_id>, AliasArgs<["fast"]>, HelpText<"Alias for --build-id=fast">;
 
 defm check_sections: B<"check-sections",
     "Check section addresses for overlaps (default)",
@@ -61,7 +60,7 @@ defm check_sections: B<"check-sections",
 
 defm compress_debug_sections:
   Eq<"compress-debug-sections", "Compress DWARF debug sections">,
-  MetaVarName<"[none,zlib]">;
+  MetaVarName<"[none,zlib,zstd]">;
 
 defm defsym: Eq<"defsym", "Define a symbol alias">, MetaVarName<"<symbol>=<value>">;
 
@@ -79,9 +78,6 @@ defm split_stack_adjust_size
          "non-split-stack function">,
       MetaVarName<"<value>">;
 
-defm library_path:
-  Eq<"library-path", "Add a directory to the library search path">, MetaVarName<"<dir>">;
-
 def O: JoinedOrSeparate<["-"], "O">, HelpText<"Optimize output file size">;
 
 defm Tbss: Eq<"Tbss", "Same as --section-start with .bss as the sectionname">;
@@ -119,21 +115,19 @@ defm call_graph_profile_sort: BB<"call-graph-profile-sort",
     "Reorder sections with call graph profile (default)",
     "Do not reorder sections with call graph profile">;
 
-// -chroot doesn't have a help text because it is an internal option.
-def chroot: Separate<["--", "-"], "chroot">;
+// --chroot doesn't have a help text because it is an internal option.
+def chroot: Separate<["--"], "chroot">;
 
-defm color_diagnostics: B<"color-diagnostics",
-  "Alias for --color-diagnostics=always",
-  "Alias for --color-diagnostics=never">;
-def color_diagnostics_eq: J<"color-diagnostics=">,
+def color_diagnostics: JJ<"color-diagnostics=">,
   HelpText<"Use colors in diagnostics (default: auto)">,
   MetaVarName<"[auto,always,never]">;
+def : Flag<["--"], "color-diagnostics">, Alias<color_diagnostics>, AliasArgs<["always"]>,
+  HelpText<"Alias for --color-diagnostics=always">;
+def : Flag<["--"], "no-color-diagnostics">, Alias<color_diagnostics>, AliasArgs<["never"]>,
+  HelpText<"Alias for --color-diagnostics=never">;
 
-def cref: FF<"cref">, HelpText<"Output cross reference table">;
-
-defm define_common: B<"define-common",
-    "Assign space to common symbols",
-    "Do not assign space to common symbols">;
+def cref: FF<"cref">,
+  HelpText<"Output cross reference table. If -Map is specified, print to the map file">;
 
 defm demangle: B<"demangle",
     "Demangle symbol names (default)",
@@ -156,10 +150,8 @@ def discard_none: F<"discard-none">,
 defm dynamic_linker: Eq<"dynamic-linker", "Which dynamic linker to use">;
 
 defm dynamic_list : Eq<"dynamic-list",
-   "Read a list of dynamic symbols. (executable) Put matched non-local defined"
-   "symbols to the dynamic symbol table. (shared object) References to matched"
-   "non-local STV_DEFAULT symbols shouldn't be bound to definitions within the "
-   "shared object. Implies -Bsymbolic but does not set DF_SYMBOLIC">,
+   "Similar to --export-dynamic-symbol-list. When creating a shared object, "
+   "this additionally implies -Bsymbolic but does not set DF_SYMBOLIC">,
    MetaVarName<"<file>">;
 
 def eb: F<"EB">, HelpText<"Select the big-endian format in OUTPUT_FORMAT">;
@@ -184,7 +176,7 @@ defm entry: Eq<"entry", "Name of entry point symbol">,
   MetaVarName<"<entry>">;
 
 defm error_limit:
-  Eq<"error-limit", "Maximum number of errors to emit before stopping (0 = no limit)">;
+  EEq<"error-limit", "Maximum number of errors to emit before stopping (0 = no limit)">;
 
 def error_unresolved_symbols: F<"error-unresolved-symbols">,
   HelpText<"Report unresolved symbols as errors">;
@@ -209,6 +201,10 @@ defm export_dynamic_symbol : EEq<"export-dynamic-symbol",
     "Does not imply -Bsymbolic.">,
     MetaVarName<"glob">;
 
+defm export_dynamic_symbol_list : EEq<"export-dynamic-symbol-list",
+   "Read a list of dynamic symbol patterns. Apply --export-dynamic-symbol on each pattern">,
+    MetaVarName<"file">;
+
 defm fatal_warnings: B<"fatal-warnings",
     "Treat warnings as errors",
     "Do not treat warnings as errors (default)">;
@@ -252,10 +248,10 @@ defm ignore_function_address_equality: B<"ignore-function-address-equality",
   "lld can break the address equality of functions",
   "lld cannot break the address equality of functions">;
 
-def ignore_data_address_equality: F<"ignore-data-address-equality">,
+def ignore_data_address_equality: FF<"ignore-data-address-equality">,
   HelpText<"lld can break the address equality of data">;
 
-defm image_base: Eq<"image-base", "Set the base address">;
+defm image_base: EEq<"image-base", "Set the base address">;
 
 defm init: Eq<"init", "Specify an initializer function">,
   MetaVarName<"<symbol>">;
@@ -264,8 +260,10 @@ defm just_symbols: Eq<"just-symbols", "Just link symbols">;
 
 defm keep_unique: Eq<"keep-unique", "Do not fold this symbol during ICF">;
 
-defm library: Eq<"library", "Root name of library to use">,
-  MetaVarName<"<libName>">;
+def library: JoinedOrSeparate<["-"], "l">, MetaVarName<"<libname>">,
+  HelpText<"Search for library <libname>">;
+def library_path: JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">,
+  HelpText<"Add <dir> to the library search path">;
 
 def m: JoinedOrSeparate<["-"], "m">, HelpText<"Set target emulation">;
 
@@ -300,11 +298,14 @@ def no_omagic: F<"no-omagic">, MetaVarName<"<magic>">,
 def no_undefined: F<"no-undefined">,
   HelpText<"Report unresolved symbols even if the linker is creating a shared library">;
 
+def no_warnings: FF<"no-warnings">, HelpText<"Suppress warnings and cancel --fatal-warnings">;
+def : Flag<["-"], "w">, Alias<no_warnings>, HelpText<"Alias for --no-warnings">;
+
 def o: JoinedOrSeparate<["-"], "o">, MetaVarName<"<path>">,
   HelpText<"Path to file to write output">;
 
-def oformat: Separate<["--"], "oformat">, MetaVarName<"<format>">,
-  HelpText<"Specify the binary format for the output object file">;
+defm oformat: EEq<"oformat", "Specify the binary format for the output object file">,
+  MetaVarName<"[elf,binary]">;
 
 def omagic: FF<"omagic">, MetaVarName<"<magic>">,
   HelpText<"Set the text and data sections to be readable and writable, do not page align sections, link against static libraries">;
@@ -313,7 +314,7 @@ defm orphan_handling:
   Eq<"orphan-handling", "Control how orphan sections are handled when linker script used">;
 
 defm pack_dyn_relocs:
-  Eq<"pack-dyn-relocs", "Pack dynamic relocations in the given format">,
+  EEq<"pack-dyn-relocs", "Pack dynamic relocations in the given format">,
   MetaVarName<"[none,android,relr,android+relr]">;
 
 defm use_android_relr_tags: BB<"use-android-relr-tags",
@@ -337,22 +338,26 @@ defm print_icf_sections: B<"print-icf-sections",
 
 def print_archive_stats: J<"print-archive-stats=">,
   HelpText<"Write archive usage statistics to the specified file. "
-           "Print the numbers of members and fetched members for each archive">;
+           "Print the numbers of members and extracted members for each archive">;
 
 defm print_symbol_order: Eq<"print-symbol-order",
   "Print a symbol order specified by --call-graph-ordering-file into the specified file">;
 
 def pop_state: F<"pop-state">,
-  HelpText<"Undo the effect of -push-state">;
+  HelpText<"Restore the states saved by --push-state">;
 
 def push_state: F<"push-state">,
-  HelpText<"Save the current state of -as-needed, -static and -whole-archive">;
+  HelpText<"Save the current state of --as-needed, -static and --whole-archive">;
 
 def print_map: F<"print-map">,
   HelpText<"Print a link map to the standard output">;
 
+defm relax: BB<"relax",
+  "Enable target-specific relaxations if supported (default)",
+  "Disable target-specific relaxations">;
+
 defm reproduce:
-  Eq<"reproduce",
+  EEq<"reproduce",
      "Write tar file containing inputs and command to reproduce link">;
 
 defm rosegment: BB<"rosegment",
@@ -390,7 +395,7 @@ def strip_all: F<"strip-all">, HelpText<"Strip all symbols. Implies --strip-debu
 def strip_debug: F<"strip-debug">, HelpText<"Strip debugging information">;
 
 defm symbol_ordering_file:
-  Eq<"symbol-ordering-file", "Layout sections to place symbols in the order specified by symbol ordering file">;
+  EEq<"symbol-ordering-file", "Layout sections to place symbols in the order specified by symbol ordering file">;
 
 defm sysroot: Eq<"sysroot", "Set the system root">;
 
@@ -403,12 +408,14 @@ defm target2:
   MetaVarName<"<type>">;
 
 defm threads
-    : Eq<"threads",
+    : EEq<"threads",
          "Number of threads. '1' disables multi-threading. By default all "
          "available hardware threads are used">;
 
-def time_trace: FF<"time-trace">, HelpText<"Record time trace">;
-def time_trace_file_eq: JJ<"time-trace-file=">, HelpText<"Specify time trace output file">;
+def time_trace_eq: JJ<"time-trace=">, MetaVarName<"<file>">,
+  HelpText<"Record time trace to <file>">;
+def : FF<"time-trace">, Alias<time_trace_eq>,
+  HelpText<"Record time trace to file next to output">;
 
 defm time_trace_granularity: EEq<"time-trace-granularity",
   "Minimum time granularity (in microseconds) traced by time profiler">;
@@ -437,10 +444,10 @@ defm unresolved_symbols:
   Eq<"unresolved-symbols", "Determine how to handle unresolved symbols">;
 
 defm undefined_version: B<"undefined-version",
-  "Allow unused version in version script (default)",
+  "Allow unused version in version script (disabled by default)",
   "Report version scripts that refer undefined symbols">;
 
-defm rsp_quoting: Eq<"rsp-quoting", "Quoting style for response files">,
+defm rsp_quoting: EEq<"rsp-quoting", "Quoting style for response files">,
   MetaVarName<"[posix,windows]">;
 
 def v: Flag<["-"], "v">, HelpText<"Display the version number">;
@@ -449,22 +456,19 @@ def verbose: F<"verbose">, HelpText<"Verbose mode">;
 
 def version: F<"version">, HelpText<"Display the version number and exit">;
 
-def power10_stubs: F<"power10-stubs">, HelpText<"Alias for --power10-stubs=auto">;
-
-def no_power10_stubs: F<"no-power10-stubs">, HelpText<"Alias for --power10-stubs=no">;
-
-def power10_stubs_eq:
-  J<"power10-stubs=">, HelpText<
-                     "Enables Power10 instructions in all stubs without options, "
-                     "options override previous flags."
-                     "auto: Allow Power10 instructions in stubs if applicable."
-                     "no:   No Power10 instructions in stubs.">;
+def power10_stubs_eq: JJ<"power10-stubs=">, MetaVarName<"<mode>">,
+  HelpText<"Whether to use Power10 instructions in call stubs for R_PPC64_REL24_NOTOC and TOC/NOTOC "
+  "interworking (yes (default): use; no: don't use). \"auto\" is currently the same as \"yes\"">;
+def power10_stubs: FF<"power10-stubs">, Alias<power10_stubs_eq>, AliasArgs<["yes"]>,
+  HelpText<"Alias for --power10-stubs=auto">;
+def no_power10_stubs: FF<"no-power10-stubs">, Alias<power10_stubs_eq>, AliasArgs<["no"]>,
+  HelpText<"Alias for --power10-stubs=no">;
 
 defm version_script: Eq<"version-script", "Read a version script">;
 
 defm warn_backrefs: BB<"warn-backrefs",
-    "Warn about backward symbol references to fetch archive members",
-    "Do not warn about backward symbol references to fetch archive members (default)">;
+    "Warn about backward symbol references to extract archive members",
+    "Do not warn about backward symbol references to extract archive members (default)">;
 
 defm warn_backrefs_exclude
     : EEq<"warn-backrefs-exclude",
@@ -491,6 +495,8 @@ defm whole_archive: B<"whole-archive",
     "Force load of all members in a static library",
     "Do not force load of all members in a static library (default)">;
 
+def why_extract: JJ<"why-extract=">, HelpText<"Print to a file about why archive members are extracted">;
+
 defm wrap : Eq<"wrap", "Redirect symbol references to __wrap_symbol and "
                        "__real_symbol references to symbol">,
             MetaVarName<"<symbol>">;
@@ -498,9 +504,11 @@ defm wrap : Eq<"wrap", "Redirect symbol references to __wrap_symbol and "
 def z: JoinedOrSeparate<["-"], "z">, MetaVarName<"<option>">,
   HelpText<"Linker option extensions">;
 
-def visual_studio_diagnostics_format : F<"vs-diagnostics">,
+def visual_studio_diagnostics_format : FF<"vs-diagnostics">,
 HelpText<"Format diagnostics for Visual Studio compatibility">;
 
+def package_metadata: JJ<"package-metadata=">, HelpText<"Emit package metadata note">;
+
 // Aliases
 def: Separate<["-"], "f">, Alias<auxiliary>, HelpText<"Alias for --auxiliary">;
 def: F<"call_shared">, Alias<Bdynamic>, HelpText<"Alias for --Bdynamic">;
@@ -508,9 +516,6 @@ def: F<"dy">, Alias<Bdynamic>, HelpText<"Alias for --Bdynamic">;
 def: F<"dn">, Alias<Bstatic>, HelpText<"Alias for --Bstatic">;
 def: F<"non_shared">, Alias<Bstatic>, HelpText<"Alias for --Bstatic">;
 def: F<"static">, Alias<Bstatic>, HelpText<"Alias for --Bstatic">;
-def: Flag<["-"], "d">, Alias<define_common>, HelpText<"Alias for --define-common">;
-def: F<"dc">, Alias<define_common>, HelpText<"Alias for --define-common">;
-def: F<"dp">, Alias<define_common>, HelpText<"Alias for --define-common">;
 def: Flag<["-"], "x">, Alias<discard_all>, HelpText<"Alias for --discard-all">;
 def: Flag<["-"], "X">, Alias<discard_locals>, HelpText<"Alias for --discard-locals">;
 def: Flag<["-"], "q">, Alias<emit_relocs>, HelpText<"Alias for --emit-relocs">;
@@ -519,14 +524,15 @@ def: JoinedOrSeparate<["-"], "e">, Alias<entry>, HelpText<"Alias for --entry">;
 def: Flag<["-"], "E">, Alias<export_dynamic>, HelpText<"Alias for --export-dynamic">;
 def: Separate<["-"], "F">, Alias<filter>, HelpText<"Alias for --filter">;
 def: Separate<["-"], "b">, Alias<format>, HelpText<"Alias for --format">;
-def: JoinedOrSeparate<["-"], "l">, Alias<library>, HelpText<"Alias for --library">;
-def: JoinedOrSeparate<["-"], "L">, Alias<library_path>, HelpText<"Alias for --library-path">;
-def: F<"nopie">, Alias<no_pie>, HelpText<"Alias for --no-pie">;
-def: F<"no-pic-executable">, Alias<no_pie>, HelpText<"Alias for --no-pie">;
+def: Separate<["--", "-"], "library">, Alias<library>;
+def: Joined<["--", "-"], "library=">, Alias<library>;
+def: Separate<["--", "-"], "library-path">, Alias<library_path>;
+def: Joined<["--", "-"], "library-path=">, Alias<library_path>;
 def: Flag<["-"], "n">, Alias<nmagic>, HelpText<"Alias for --nmagic">;
 def: Flag<["-"], "N">, Alias<omagic>, HelpText<"Alias for --omagic">;
 def: Joined<["--"], "output=">, Alias<o>, HelpText<"Alias for -o">;
 def: Separate<["--"], "output">, Alias<o>, HelpText<"Alias for -o">;
+def: F<"nopie">, Alias<no_pie>, HelpText<"Alias for --no-pie">;
 def: F<"pic-executable">, Alias<pie>, HelpText<"Alias for --pie">;
 def: Flag<["-"], "M">, Alias<print_map>, HelpText<"Alias for --print-map">;
 def: Flag<["-"], "r">, Alias<relocatable>, HelpText<"Alias for --relocatable">;
@@ -541,7 +547,7 @@ def: Flag<["-"], "t">, Alias<trace>, HelpText<"Alias for --trace">;
 def: Joined<["-", "--"], "Ttext-segment=">, Alias<Ttext_segment>;
 def: JoinedOrSeparate<["-"], "y">, Alias<trace_symbol>, HelpText<"Alias for --trace-symbol">;
 def: JoinedOrSeparate<["-"], "u">, Alias<undefined>, HelpText<"Alias for --undefined">;
-def: Flag<["-"], "V">, Alias<version>, HelpText<"Alias for --version">;
+def: Flag<["-"], "V">, Alias<v>, HelpText<"Alias for -v">;
 
 // LTO-related options.
 def lto_aa_pipeline: JJ<"lto-aa-pipeline=">,
@@ -550,9 +556,8 @@ def lto_debug_pass_manager: FF<"lto-debug-pass-manager">,
   HelpText<"Debug new pass manager">;
 def lto_emit_asm: FF<"lto-emit-asm">,
   HelpText<"Emit assembly code">;
-defm lto_legacy_pass_manager: BB<"lto-legacy-pass-manager",
-  "Use the legacy pass manager in LLVM",
-  "Use the new pass manager in LLVM">;
+def no_lto_legacy_pass_manager: FF<"no-lto-legacy-pass-manager">,
+  HelpText<"Use the new pass manager in LLVM">;
 def lto_newpm_passes: JJ<"lto-newpm-passes=">,
   HelpText<"Passes to run during LTO">;
 def lto_O: JJ<"lto-O">, MetaVarName<"<opt-level>">,
@@ -563,14 +568,15 @@ def lto_cs_profile_generate: FF<"lto-cs-profile-generate">,
   HelpText<"Perform context sensitive PGO instrumentation">;
 def lto_cs_profile_file: JJ<"lto-cs-profile-file=">,
   HelpText<"Context sensitive profile file path">;
+defm lto_pgo_warn_mismatch: BB<"lto-pgo-warn-mismatch",
+  "turn on warnings about profile cfg mismatch (default)>",
+  "turn off warnings about profile cfg mismatch">;
 def lto_obj_path_eq: JJ<"lto-obj-path=">;
 def lto_sample_profile: JJ<"lto-sample-profile=">,
   HelpText<"Sample profile file path">;
 defm lto_whole_program_visibility: BB<"lto-whole-program-visibility",
   "Asserts that the LTO link has whole program visibility",
   "Asserts that the LTO link does not have whole program visibility">;
-def lto_pseudo_probe_for_profiling: F<"lto-pseudo-probe-for-profiling">,
-  HelpText<"Emit pseudo probes for sample profiling">;
 def disable_verify: F<"disable-verify">;
 defm mllvm: Eq<"mllvm", "Additional arguments to forward to LLVM's option processing">;
 def opt_remarks_filename: Separate<["--"], "opt-remarks-filename">,
@@ -586,6 +592,8 @@ def opt_remarks_with_hotness: FF<"opt-remarks-with-hotness">,
 def opt_remarks_format: Separate<["--"], "opt-remarks-format">,
   HelpText<"The format used for serializing remarks (default: YAML)">;
 def save_temps: F<"save-temps">, HelpText<"Save intermediate LTO compilation results">;
+def save_temps_eq: JJ<"save-temps=">, HelpText<"Save select intermediate LTO compilation results">,
+  Values<"resolution,preopt,promote,internalize,import,opt,precodegen,prelink,combinedindex">;
 def lto_basic_block_sections: JJ<"lto-basic-block-sections=">,
   HelpText<"Enable basic block sections for LTO">;
 defm lto_unique_basic_block_section_names: BB<"lto-unique-basic-block-section-names",
@@ -599,14 +607,15 @@ def thinlto_cache_dir: JJ<"thinlto-cache-dir=">,
   HelpText<"Path to ThinLTO cached object file directory">;
 defm thinlto_cache_policy: EEq<"thinlto-cache-policy", "Pruning policy for the ThinLTO cache">;
 def thinlto_emit_imports_files: FF<"thinlto-emit-imports-files">;
+def thinlto_emit_index_files: FF<"thinlto-emit-index-files">;
 def thinlto_index_only: FF<"thinlto-index-only">;
 def thinlto_index_only_eq: JJ<"thinlto-index-only=">;
-def thinlto_jobs: JJ<"thinlto-jobs=">,
+def thinlto_jobs_eq: JJ<"thinlto-jobs=">,
   HelpText<"Number of ThinLTO jobs. Default to --threads=">;
 def thinlto_object_suffix_replace_eq: JJ<"thinlto-object-suffix-replace=">;
 def thinlto_prefix_replace_eq: JJ<"thinlto-prefix-replace=">;
 def thinlto_single_module_eq: JJ<"thinlto-single-module=">,
-  HelpText<"Specific a single module to compile in ThinLTO mode, for debugging only">;
+  HelpText<"Specify a single module to compile in ThinLTO mode, for debugging only">;
 
 def: J<"plugin-opt=O">, Alias<lto_O>, HelpText<"Alias for --lto-O">;
 def: F<"plugin-opt=debug-pass-manager">,
@@ -617,13 +626,11 @@ def plugin_opt_dwo_dir_eq: J<"plugin-opt=dwo_dir=">,
 def plugin_opt_emit_asm: F<"plugin-opt=emit-asm">,
   Alias<lto_emit_asm>, HelpText<"Alias for --lto-emit-asm">;
 def plugin_opt_emit_llvm: F<"plugin-opt=emit-llvm">;
-def: J<"plugin-opt=jobs=">, Alias<thinlto_jobs>, HelpText<"Alias for --thinlto-jobs">;
+def: J<"plugin-opt=jobs=">, Alias<thinlto_jobs_eq>, HelpText<"Alias for --thinlto-jobs=">;
 def: J<"plugin-opt=lto-partitions=">, Alias<lto_partitions>, HelpText<"Alias for --lto-partitions">;
 def plugin_opt_mcpu_eq: J<"plugin-opt=mcpu=">;
 def: F<"plugin-opt=new-pass-manager">,
   Alias<no_lto_legacy_pass_manager>, HelpText<"Alias for --no-lto-legacy-pass-manager">;
-def: F<"plugin-opt=legacy-pass-manager">,
-  Alias<lto_legacy_pass_manager>, HelpText<"Alias for --no-legacy-pass-manager">;
 def: F<"plugin-opt=cs-profile-generate">,
   Alias<lto_cs_profile_generate>, HelpText<"Alias for --lto-cs-profile-generate">;
 def: J<"plugin-opt=cs-profile-path=">,
@@ -631,6 +638,10 @@ def: J<"plugin-opt=cs-profile-path=">,
 def: J<"plugin-opt=obj-path=">,
   Alias<lto_obj_path_eq>,
   HelpText<"Alias for --lto-obj-path=">;
+def plugin_opt_opaque_pointers: F<"plugin-opt=opaque-pointers">,
+  HelpText<"Use opaque pointers in IR during LTO (default)">;
+def plugin_opt_no_opaque_pointers: F<"plugin-opt=no-opaque-pointers">,
+  HelpText<"Use typed pointers in IR during LTO">;
 def: J<"plugin-opt=opt-remarks-filename=">,
   Alias<opt_remarks_filename>,
   HelpText<"Alias for --opt-remarks-filename">;
@@ -646,11 +657,11 @@ def: F<"plugin-opt=opt-remarks-with-hotness">,
 def: J<"plugin-opt=opt-remarks-hotness-threshold=">,
   Alias<opt_remarks_hotness_threshold>,
   HelpText<"Alias for --opt-remarks-hotness-threshold">;
-def: J<"plugin-opt=pseudo-probe-for-profiling">,
-  Alias<lto_pseudo_probe_for_profiling>, HelpText<"Alias for --lto-pseudo-probe-for-profiling">;
 def: J<"plugin-opt=sample-profile=">,
   Alias<lto_sample_profile>, HelpText<"Alias for --lto-sample-profile">;
 def: F<"plugin-opt=save-temps">, Alias<save_temps>, HelpText<"Alias for --save-temps">;
+def plugin_opt_stats_file: J<"plugin-opt=stats-file=">,
+  HelpText<"Filename to write LTO statistics to">;
 def: F<"plugin-opt=thinlto-emit-imports-files">,
   Alias<thinlto_emit_imports_files>,
   HelpText<"Alias for --thinlto-emit-imports-files">;
@@ -689,17 +700,14 @@ def: J<"plugin-opt=-pass-through=">;
 def plugin_opt_eq : J<"plugin-opt=">;
 
 // Options listed below are silently ignored for now for compatibility.
-def: F<"detect-odr-violations">;
+def: Flag<["-"], "d">;
 def: Flag<["-"], "g">;
 def: F<"long-plt">;
-def: F<"no-add-needed">;
+def: FF<"no-add-needed">;
 def: F<"no-copy-dt-needed-entries">;
 def: F<"no-ctors-in-init-array">;
 def: F<"no-keep-memory">;
-def: F<"no-pipeline-knowledge">;
-def: F<"no-relax">;
 def: F<"no-warn-mismatch">;
-def: Flag<["-"], "p">;
 def: Separate<["--", "-"], "rpath-link">;
 def: J<"rpath-link=">;
 def: F<"secure-plt">;
@@ -709,7 +717,6 @@ def: F<"warn-execstack">;
 def: F<"warn-once">;
 def: F<"warn-shared-textrel">;
 def: JoinedOrSeparate<["-"], "G">;
-def: F<"Qy">;
 
 // Hidden option used for testing MIPS multi-GOT implementation.
 defm mips_got_size:
@@ -721,3 +728,17 @@ defm check_dynamic_relocations: BB<"check-dynamic-relocations",
     "Perform additional validation of the written dynamic relocations",
     "Do not perform additional validation of the written dynamic relocations">,
   Flags<[HelpHidden]>;
+
+defm load_pass_plugins: EEq<"load-pass-plugin", "Load passes from plugin library">;
+
+// Hidden options, used by clang's -fsanitize=memtag-* options to emit an ELF
+// note to designate what kinds of memory (stack/heap) should be protected using
+// ARM's MTE on armv8.5+. A binary's desire for stack MTE can't be obtained
+// implicitly, so we have a specific bit in the note to signal to the loader to
+// remap the stack as PROT_MTE.
+defm android_memtag_stack: BB<"android-memtag-stack",
+    "Instruct the dynamic loader to prepare for MTE stack instrumentation", "">;
+defm android_memtag_heap: BB<"android-memtag-heap",
+    "Instruct the dynamic loader to enable MTE protection for the heap", "">;
+defm android_memtag_mode: EEq<"android-memtag-mode",
+    "Instruct the dynamic loader to start under MTE mode {async, sync, none}">;
index 114780e..80b3615 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "Relocations.h"
 #include "Config.h"
+#include "InputFiles.h"
 #include "LinkerScript.h"
 #include "OutputSections.h"
 #include "SymbolTable.h"
 #include "Thunks.h"
 #include "lld/Common/ErrorHandler.h"
 #include "lld/Common/Memory.h"
-#include "lld/Common/Strings.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/Demangle/Demangle.h"
 #include "llvm/Support/Endian.h"
-#include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 
 using namespace llvm;
@@ -65,19 +64,19 @@ using namespace llvm::support::endian;
 using namespace lld;
 using namespace lld::elf;
 
-static Optional<std::string> getLinkerScriptLocation(const Symbol &sym) {
-  for (BaseCommand *base : script->sectionCommands)
-    if (auto *cmd = dyn_cast<SymbolAssignment>(base))
-      if (cmd->sym == &sym)
-        return cmd->location;
-  return None;
+static std::optional<std::string> getLinkerScriptLocation(const Symbol &sym) {
+  for (SectionCommand *cmd : script->sectionCommands)
+    if (auto *assign = dyn_cast<SymbolAssignment>(cmd))
+      if (assign->sym == &sym)
+        return assign->location;
+  return std::nullopt;
 }
 
 static std::string getDefinedLocation(const Symbol &sym) {
   const char msg[] = "\n>>> defined in ";
   if (sym.file)
     return msg + toString(sym.file);
-  if (Optional<std::string> loc = getLinkerScriptLocation(sym))
+  if (std::optional<std::string> loc = getLinkerScriptLocation(sym))
     return msg + *loc;
   return "";
 }
@@ -100,9 +99,12 @@ void elf::reportRangeError(uint8_t *loc, const Relocation &rel, const Twine &v,
                            int64_t min, uint64_t max) {
   ErrorPlace errPlace = getErrorPlace(loc);
   std::string hint;
-  if (rel.sym && !rel.sym->isLocal())
-    hint = "; references " + lld::toString(*rel.sym) +
-           getDefinedLocation(*rel.sym);
+  if (rel.sym && !rel.sym->isSection())
+    hint = "; references " + lld::toString(*rel.sym);
+  if (!errPlace.srcLoc.empty())
+    hint += "\n>>> referenced by " + errPlace.srcLoc;
+  if (rel.sym && !rel.sym->isSection())
+    hint += getDefinedLocation(*rel.sym);
 
   if (errPlace.isec && errPlace.isec->name.startswith(".debug"))
     hint += "; consider recompiling with -fdebug-types-section to reduce size "
@@ -124,213 +126,27 @@ void elf::reportRangeError(uint8_t *loc, int64_t v, int n, const Symbol &sym,
               Twine(llvm::maxIntN(n)) + "]" + hint);
 }
 
-namespace {
-// Build a bitmask with one bit set for each RelExpr.
-//
-// Constexpr function arguments can't be used in static asserts, so we
-// use template arguments to build the mask.
-// But function template partial specializations don't exist (needed
-// for base case of the recursion), so we need a dummy struct.
-template <RelExpr... Exprs> struct RelExprMaskBuilder {
-  static inline uint64_t build() { return 0; }
-};
+// Build a bitmask with one bit set for each 64 subset of RelExpr.
+static constexpr uint64_t buildMask() { return 0; }
 
-// Specialization for recursive case.
-template <RelExpr Head, RelExpr... Tail>
-struct RelExprMaskBuilder<Head, Tail...> {
-  static inline uint64_t build() {
-    static_assert(0 <= Head && Head < 64,
-                  "RelExpr is too large for 64-bit mask!");
-    return (uint64_t(1) << Head) | RelExprMaskBuilder<Tail...>::build();
-  }
-};
-} // namespace
-
-// Return true if `Expr` is one of `Exprs`.
-// There are fewer than 64 RelExpr's, so we can represent any set of
-// RelExpr's as a constant bit mask and test for membership with a
-// couple cheap bitwise operations.
-template <RelExpr... Exprs> bool oneof(RelExpr expr) {
-  assert(0 <= expr && (int)expr < 64 &&
-         "RelExpr is too large for 64-bit mask!");
-  return (uint64_t(1) << expr) & RelExprMaskBuilder<Exprs...>::build();
+template <typename... Tails>
+static constexpr uint64_t buildMask(int head, Tails... tails) {
+  return (0 <= head && head < 64 ? uint64_t(1) << head : 0) |
+         buildMask(tails...);
 }
 
-// This function is similar to the `handleTlsRelocation`. MIPS does not
-// support any relaxations for TLS relocations so by factoring out MIPS
-// handling in to the separate function we can simplify the code and do not
-// pollute other `handleTlsRelocation` by MIPS `ifs` statements.
-// Mips has a custom MipsGotSection that handles the writing of GOT entries
-// without dynamic relocations.
-static unsigned handleMipsTlsRelocation(RelType type, Symbol &sym,
-                                        InputSectionBase &c, uint64_t offset,
-                                        int64_t addend, RelExpr expr) {
-  if (expr == R_MIPS_TLSLD) {
-    in.mipsGot->addTlsIndex(*c.file);
-    c.relocations.push_back({expr, type, offset, addend, &sym});
-    return 1;
-  }
-  if (expr == R_MIPS_TLSGD) {
-    in.mipsGot->addDynTlsEntry(*c.file, sym);
-    c.relocations.push_back({expr, type, offset, addend, &sym});
-    return 1;
-  }
-  return 0;
-}
-
-// Notes about General Dynamic and Local Dynamic TLS models below. They may
-// require the generation of a pair of GOT entries that have associated dynamic
-// relocations. The pair of GOT entries created are of the form GOT[e0] Module
-// Index (Used to find pointer to TLS block at run-time) GOT[e1] Offset of
-// symbol in TLS block.
-//
-// Returns the number of relocations processed.
-template <class ELFT>
-static unsigned
-handleTlsRelocation(RelType type, Symbol &sym, InputSectionBase &c,
-                    typename ELFT::uint offset, int64_t addend, RelExpr expr) {
-  if (!sym.isTls())
-    return 0;
-
-  if (config->emachine == EM_MIPS)
-    return handleMipsTlsRelocation(type, sym, c, offset, addend, expr);
-
-  if (oneof<R_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC>(
-          expr) &&
-      config->shared) {
-    if (in.got->addDynTlsEntry(sym)) {
-      uint64_t off = in.got->getGlobalDynOffset(sym);
-      mainPart->relaDyn->addAddendOnlyRelocIfNonPreemptible(
-          target->tlsDescRel, in.got, off, sym, target->tlsDescRel);
-    }
-    if (expr != R_TLSDESC_CALL)
-      c.relocations.push_back({expr, type, offset, addend, &sym});
-    return 1;
-  }
-
-  // ARM, Hexagon and RISC-V do not support GD/LD to IE/LE relaxation.  For
-  // PPC64, if the file has missing R_PPC64_TLSGD/R_PPC64_TLSLD, disable
-  // relaxation as well.
-  bool toExecRelax = !config->shared && config->emachine != EM_ARM &&
-                     config->emachine != EM_HEXAGON &&
-                     config->emachine != EM_RISCV &&
-                     !c.file->ppc64DisableTLSRelax;
-
-  // If we are producing an executable and the symbol is non-preemptable, it
-  // must be defined and the code sequence can be relaxed to use Local-Exec.
-  //
-  // ARM and RISC-V do not support any relaxations for TLS relocations, however,
-  // we can omit the DTPMOD dynamic relocations and resolve them at link time
-  // because them are always 1. This may be necessary for static linking as
-  // DTPMOD may not be expected at load time.
-  bool isLocalInExecutable = !sym.isPreemptible && !config->shared;
-
-  // Local Dynamic is for access to module local TLS variables, while still
-  // being suitable for being dynamically loaded via dlopen. GOT[e0] is the
-  // module index, with a special value of 0 for the current module. GOT[e1] is
-  // unused. There only needs to be one module index entry.
-  if (oneof<R_TLSLD_GOT, R_TLSLD_GOTPLT, R_TLSLD_PC, R_TLSLD_HINT>(
-          expr)) {
-    // Local-Dynamic relocs can be relaxed to Local-Exec.
-    if (toExecRelax) {
-      c.relocations.push_back(
-          {target->adjustTlsExpr(type, R_RELAX_TLS_LD_TO_LE), type, offset,
-           addend, &sym});
-      return target->getTlsGdRelaxSkip(type);
-    }
-    if (expr == R_TLSLD_HINT)
-      return 1;
-    if (in.got->addTlsIndex()) {
-      if (isLocalInExecutable)
-        in.got->relocations.push_back(
-            {R_ADDEND, target->symbolicRel, in.got->getTlsIndexOff(), 1, &sym});
-      else
-        mainPart->relaDyn->addReloc(
-            {target->tlsModuleIndexRel, in.got, in.got->getTlsIndexOff()});
-    }
-    c.relocations.push_back({expr, type, offset, addend, &sym});
-    return 1;
-  }
-
-  // Local-Dynamic relocs can be relaxed to Local-Exec.
-  if (expr == R_DTPREL && toExecRelax) {
-    c.relocations.push_back({target->adjustTlsExpr(type, R_RELAX_TLS_LD_TO_LE),
-                             type, offset, addend, &sym});
-    return 1;
-  }
-
-  // Local-Dynamic sequence where offset of tls variable relative to dynamic
-  // thread pointer is stored in the got. This cannot be relaxed to Local-Exec.
-  if (expr == R_TLSLD_GOT_OFF) {
-    if (!sym.isInGot()) {
-      in.got->addEntry(sym);
-      uint64_t off = sym.getGotOffset();
-      in.got->relocations.push_back(
-          {R_ABS, target->tlsOffsetRel, off, 0, &sym});
-    }
-    c.relocations.push_back({expr, type, offset, addend, &sym});
-    return 1;
-  }
-
-  if (oneof<R_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC,
-            R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC>(expr)) {
-    if (!toExecRelax) {
-      if (in.got->addDynTlsEntry(sym)) {
-        uint64_t off = in.got->getGlobalDynOffset(sym);
-
-        if (isLocalInExecutable)
-          // Write one to the GOT slot.
-          in.got->relocations.push_back(
-              {R_ADDEND, target->symbolicRel, off, 1, &sym});
-        else
-          mainPart->relaDyn->addSymbolReloc(target->tlsModuleIndexRel, in.got,
-                                            off, sym);
-
-        // If the symbol is preemptible we need the dynamic linker to write
-        // the offset too.
-        uint64_t offsetOff = off + config->wordsize;
-        if (sym.isPreemptible)
-          mainPart->relaDyn->addSymbolReloc(target->tlsOffsetRel, in.got,
-                                            offsetOff, sym);
-        else
-          in.got->relocations.push_back(
-              {R_ABS, target->tlsOffsetRel, offsetOff, 0, &sym});
-      }
-      c.relocations.push_back({expr, type, offset, addend, &sym});
-      return 1;
-    }
-
-    // Global-Dynamic relocs can be relaxed to Initial-Exec or Local-Exec
-    // depending on the symbol being locally defined or not.
-    if (sym.isPreemptible) {
-      c.relocations.push_back(
-          {target->adjustTlsExpr(type, R_RELAX_TLS_GD_TO_IE), type, offset,
-           addend, &sym});
-      if (!sym.isInGot()) {
-        in.got->addEntry(sym);
-        mainPart->relaDyn->addSymbolReloc(target->tlsGotRel, in.got,
-                                          sym.getGotOffset(), sym);
-      }
-    } else {
-      c.relocations.push_back(
-          {target->adjustTlsExpr(type, R_RELAX_TLS_GD_TO_LE), type, offset,
-           addend, &sym});
-    }
-    return target->getTlsGdRelaxSkip(type);
-  }
-
-  // Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally
-  // defined.
-  if (oneof<R_GOT, R_GOTPLT, R_GOT_PC, R_AARCH64_GOT_PAGE_PC, R_GOT_OFF,
-            R_TLSIE_HINT>(expr) &&
-      toExecRelax && isLocalInExecutable) {
-    c.relocations.push_back({R_RELAX_TLS_IE_TO_LE, type, offset, addend, &sym});
-    return 1;
-  }
-
-  if (expr == R_TLSIE_HINT)
-    return 1;
-  return 0;
+// Return true if `Expr` is one of `Exprs`.
+// There are more than 64 but less than 128 RelExprs, so we divide the set of
+// exprs into [0, 64) and [64, 128) and represent each range as a constant
+// 64-bit mask. Then we decide which mask to test depending on the value of
+// expr and use a simple shift and bitwise-and to test for membership.
+template <RelExpr... Exprs> static bool oneof(RelExpr expr) {
+  assert(0 <= expr && (int)expr < 128 &&
+         "RelExpr is too large for 128-bit mask!");
+
+  if (expr >= 64)
+    return (uint64_t(1) << (expr - 64)) & buildMask((Exprs - 64)...);
+  return (uint64_t(1) << expr) & buildMask(Exprs...);
 }
 
 static RelType getMipsPairType(RelType type, bool isLocal) {
@@ -374,7 +190,8 @@ static bool isAbsoluteValue(const Symbol &sym) {
 
 // Returns true if Expr refers a PLT entry.
 static bool needsPlt(RelExpr expr) {
-  return oneof<R_PLT_PC, R_PPC32_PLTREL, R_PPC64_CALL_PLT, R_PLT>(expr);
+  return oneof<R_PLT, R_PLT_PC, R_PLT_GOTPLT, R_PPC32_PLTREL, R_PPC64_CALL_PLT>(
+      expr);
 }
 
 // Returns true if Expr refers a GOT entry. Note that this function
@@ -394,73 +211,6 @@ static bool isRelExpr(RelExpr expr) {
                R_RISCV_PC_INDIRECT, R_PPC64_RELAX_GOT_PC>(expr);
 }
 
-// Returns true if a given relocation can be computed at link-time.
-//
-// For instance, we know the offset from a relocation to its target at
-// link-time if the relocation is PC-relative and refers a
-// non-interposable function in the same executable. This function
-// will return true for such relocation.
-//
-// If this function returns false, that means we need to emit a
-// dynamic relocation so that the relocation will be fixed at load-time.
-static bool isStaticLinkTimeConstant(RelExpr e, RelType type, const Symbol &sym,
-                                     InputSectionBase &s, uint64_t relOff) {
-  // These expressions always compute a constant
-  if (oneof<R_DTPREL, R_GOTPLT, R_GOT_OFF, R_TLSLD_GOT_OFF,
-            R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOTREL, R_MIPS_GOT_OFF,
-            R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC, R_MIPS_TLSGD,
-            R_AARCH64_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC, R_GOTPLTONLY_PC,
-            R_PLT_PC, R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC, R_PPC32_PLTREL,
-            R_PPC64_CALL_PLT, R_PPC64_RELAX_TOC, R_RISCV_ADD, R_TLSDESC_CALL,
-            R_TLSDESC_PC, R_AARCH64_TLSDESC_PAGE, R_TLSLD_HINT, R_TLSIE_HINT,
-            R_AARCH64_GOT_PAGE>(
-          e))
-    return true;
-
-  // These never do, except if the entire file is position dependent or if
-  // only the low bits are used.
-  if (e == R_GOT || e == R_PLT || e == R_TLSDESC)
-    return target->usesOnlyLowPageBits(type) || !config->isPic;
-
-  if (sym.isPreemptible)
-    return false;
-  if (!config->isPic)
-    return true;
-
-  // The size of a non preemptible symbol is a constant.
-  if (e == R_SIZE)
-    return true;
-
-  // For the target and the relocation, we want to know if they are
-  // absolute or relative.
-  bool absVal = isAbsoluteValue(sym);
-  bool relE = isRelExpr(e);
-  if (absVal && !relE)
-    return true;
-  if (!absVal && relE)
-    return true;
-  if (!absVal && !relE)
-    return target->usesOnlyLowPageBits(type);
-
-  assert(absVal && relE);
-
-  // Allow R_PLT_PC (optimized to R_PC here) to a hidden undefined weak symbol
-  // in PIC mode. This is a little strange, but it allows us to link function
-  // calls to such symbols (e.g. glibc/stdlib/exit.c:__run_exit_handlers).
-  // Normally such a call will be guarded with a comparison, which will load a
-  // zero from the GOT.
-  if (sym.isUndefWeak())
-    return true;
-
-  // We set the final symbols values for linker script defined symbols later.
-  // They always can be computed as a link time constant.
-  if (sym.scriptDefined)
-      return true;
-
-  error("relocation " + toString(type) + " cannot refer to absolute symbol: " +
-        toString(sym) + getLocation(s, sym, relOff));
-  return true;
-}
 
 static RelExpr toPlt(RelExpr expr) {
   switch (expr) {
@@ -486,6 +236,8 @@ static RelExpr fromPlt(RelExpr expr) {
     return R_PPC64_CALL;
   case R_PLT:
     return R_ABS;
+  case R_PLT_GOTPLT:
+    return R_GOTPLTREL;
   default:
     return expr;
   }
@@ -496,7 +248,7 @@ template <class ELFT> static bool isReadOnly(SharedSymbol &ss) {
   using Elf_Phdr = typename ELFT::Phdr;
 
   // Determine if the symbol is read-only by scanning the DSO's program headers.
-  const SharedFile &file = ss.getFile();
+  const auto &file = cast<SharedFile>(*ss.file);
   for (const Elf_Phdr &phdr :
        check(file.template getObj<ELFT>().program_headers()))
     if ((phdr.p_type == ELF::PT_LOAD || phdr.p_type == ELF::PT_GNU_RELRO) &&
@@ -515,7 +267,7 @@ template <class ELFT>
 static SmallSet<SharedSymbol *, 4> getSymbolsAt(SharedSymbol &ss) {
   using Elf_Sym = typename ELFT::Sym;
 
-  SharedFile &file = ss.getFile();
+  const auto &file = cast<SharedFile>(*ss.file);
 
   SmallSet<SharedSymbol *, 4> ret;
   for (const Elf_Sym &s : file.template getGlobalELFSyms<ELFT>()) {
@@ -523,7 +275,7 @@ static SmallSet<SharedSymbol *, 4> getSymbolsAt(SharedSymbol &ss) {
         s.getType() == STT_TLS || s.st_value != ss.value)
       continue;
     StringRef name = check(s.getName(file.getStringTable()));
-    Symbol *sym = symtab->find(name);
+    Symbol *sym = symtab.find(name);
     if (auto *alias = dyn_cast_or_null<SharedSymbol>(sym))
       ret.insert(alias);
   }
@@ -542,18 +294,19 @@ static SmallSet<SharedSymbol *, 4> getSymbolsAt(SharedSymbol &ss) {
 // in .bss and in the case of a canonical plt entry it is in .plt. This function
 // replaces the existing symbol with a Defined pointing to the appropriate
 // location.
-static void replaceWithDefined(Symbol &sym, SectionBase *sec, uint64_t value,
+static void replaceWithDefined(Symbol &sym, SectionBase &sec, uint64_t value,
                                uint64_t size) {
   Symbol old = sym;
+  Defined(sym.file, StringRef(), sym.binding, sym.stOther, sym.type, value,
+          size, &sec)
+      .overwrite(sym);
 
-  sym.replace(Defined{sym.file, sym.getName(), sym.binding, sym.stOther,
-                      sym.type, value, size, sec});
-
-  sym.pltIndex = old.pltIndex;
-  sym.gotIndex = old.gotIndex;
   sym.verdefIndex = old.verdefIndex;
   sym.exportDynamic = true;
   sym.isUsedInRegularObj = true;
+  // A copy relocated alias may need a GOT entry.
+  sym.flags.store(old.flags.load(std::memory_order_relaxed) & NEEDS_GOT,
+                  std::memory_order_relaxed);
 }
 
 // Reserve space in .bss or .bss.rel.ro for copy relocation.
@@ -613,10 +366,10 @@ template <class ELFT> static void addCopyRelSymbol(SharedSymbol &ss) {
 
   // At this point, sectionBases has been migrated to sections. Append sec to
   // sections.
-  if (osec->sectionCommands.empty() ||
-      !isa<InputSectionDescription>(osec->sectionCommands.back()))
-    osec->sectionCommands.push_back(make<InputSectionDescription>(""));
-  auto *isd = cast<InputSectionDescription>(osec->sectionCommands.back());
+  if (osec->commands.empty() ||
+      !isa<InputSectionDescription>(osec->commands.back()))
+    osec->commands.push_back(make<InputSectionDescription>(""));
+  auto *isd = cast<InputSectionDescription>(osec->commands.back());
   isd->sections.push_back(sec);
   osec->commitSection(sec);
 
@@ -624,21 +377,98 @@ template <class ELFT> static void addCopyRelSymbol(SharedSymbol &ss) {
   // dynamic symbol for each one. This causes the copy relocation to correctly
   // interpose any aliases.
   for (SharedSymbol *sym : getSymbolsAt<ELFT>(ss))
-    replaceWithDefined(*sym, sec, 0, sym->size);
+    replaceWithDefined(*sym, *sec, 0, sym->size);
 
-  mainPart->relaDyn->addSymbolReloc(target->copyRel, sec, 0, ss);
+  mainPart->relaDyn->addSymbolReloc(target->copyRel, *sec, 0, ss);
 }
 
+// .eh_frame sections are mergeable input sections, so their input
+// offsets are not linearly mapped to output section. For each input
+// offset, we need to find a section piece containing the offset and
+// add the piece's base address to the input offset to compute the
+// output offset. That isn't cheap.
+//
+// This class is to speed up the offset computation. When we process
+// relocations, we access offsets in the monotonically increasing
+// order. So we can optimize for that access pattern.
+//
+// For sections other than .eh_frame, this class doesn't do anything.
+namespace {
+class OffsetGetter {
+public:
+  OffsetGetter() = default;
+  explicit OffsetGetter(InputSectionBase &sec) {
+    if (auto *eh = dyn_cast<EhInputSection>(&sec)) {
+      cies = eh->cies;
+      fdes = eh->fdes;
+      i = cies.begin();
+      j = fdes.begin();
+    }
+  }
+
+  // Translates offsets in input sections to offsets in output sections.
+  // Given offset must increase monotonically. We assume that Piece is
+  // sorted by inputOff.
+  uint64_t get(uint64_t off) {
+    if (cies.empty())
+      return off;
+
+    while (j != fdes.end() && j->inputOff <= off)
+      ++j;
+    auto it = j;
+    if (j == fdes.begin() || j[-1].inputOff + j[-1].size <= off) {
+      while (i != cies.end() && i->inputOff <= off)
+        ++i;
+      if (i == cies.begin() || i[-1].inputOff + i[-1].size <= off)
+        fatal(".eh_frame: relocation is not in any piece");
+      it = i;
+    }
+
+    // Offset -1 means that the piece is dead (i.e. garbage collected).
+    if (it[-1].outputOff == -1)
+      return -1;
+    return it[-1].outputOff + (off - it[-1].inputOff);
+  }
+
+private:
+  ArrayRef<EhSectionPiece> cies, fdes;
+  ArrayRef<EhSectionPiece>::iterator i, j;
+};
+
+// This class encapsulates states needed to scan relocations for one
+// InputSectionBase.
+class RelocationScanner {
+public:
+  template <class ELFT> void scanSection(InputSectionBase &s);
+
+private:
+  InputSectionBase *sec;
+  OffsetGetter getter;
+
+  // End of relocations, used by Mips/PPC64.
+  const void *end = nullptr;
+
+  template <class RelTy> RelType getMipsN32RelType(RelTy *&rel) const;
+  template <class ELFT, class RelTy>
+  int64_t computeMipsAddend(const RelTy &rel, RelExpr expr, bool isLocal) const;
+  bool isStaticLinkTimeConstant(RelExpr e, RelType type, const Symbol &sym,
+                                uint64_t relOff) const;
+  void processAux(RelExpr expr, RelType type, uint64_t offset, Symbol &sym,
+                  int64_t addend) const;
+  template <class ELFT, class RelTy> void scanOne(RelTy *&i);
+  template <class ELFT, class RelTy> void scan(ArrayRef<RelTy> rels);
+};
+} // namespace
+
 // MIPS has an odd notion of "paired" relocations to calculate addends.
 // For example, if a relocation is of R_MIPS_HI16, there must be a
 // R_MIPS_LO16 relocation after that, and an addend is calculated using
 // the two relocations.
 template <class ELFT, class RelTy>
-static int64_t computeMipsAddend(const RelTy &rel, const RelTy *end,
-                                 InputSectionBase &sec, RelExpr expr,
-                                 bool isLocal) {
+int64_t RelocationScanner::computeMipsAddend(const RelTy &rel, RelExpr expr,
+                                             bool isLocal) const {
   if (expr == R_MIPS_GOTREL && isLocal)
-    return sec.getFile<ELFT>()->mipsGp0;
+    return sec->getFile<ELFT>()->mipsGp0;
 
   // The ABI says that the paired relocation is used only for REL.
   // See p. 4-17 at ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
@@ -650,12 +480,12 @@ static int64_t computeMipsAddend(const RelTy &rel, const RelTy *end,
   if (pairTy == R_MIPS_NONE)
     return 0;
 
-  const uint8_t *buf = sec.data().data();
+  const uint8_t *buf = sec->content().data();
   uint32_t symIndex = rel.getSymbol(config->isMips64EL);
 
   // To make things worse, paired relocations might not be contiguous in
   // the relocation table, so we need to do linear search. *sigh*
-  for (const RelTy *ri = &rel; ri != end; ++ri)
+  for (const RelTy *ri = &rel; ri != static_cast<const RelTy *>(end); ++ri)
     if (ri->getType(config->isMips64EL) == pairTy &&
         ri->getSymbol(config->isMips64EL) == symIndex)
       return target->getImplicitAddend(buf + ri->r_offset, pairTy);
@@ -665,31 +495,6 @@ static int64_t computeMipsAddend(const RelTy &rel, const RelTy *end,
   return 0;
 }
 
-// Returns an addend of a given relocation. If it is RELA, an addend
-// is in a relocation itself. If it is REL, we need to read it from an
-// input section.
-template <class ELFT, class RelTy>
-static int64_t computeAddend(const RelTy &rel, const RelTy *end,
-                             InputSectionBase &sec, RelExpr expr,
-                             bool isLocal) {
-  int64_t addend;
-  RelType type = rel.getType(config->isMips64EL);
-
-  if (RelTy::IsRela) {
-    addend = getAddend<ELFT>(rel);
-  } else {
-    const uint8_t *buf = sec.data().data();
-    addend = target->getImplicitAddend(buf + rel.r_offset, type);
-  }
-
-  if (config->emachine == EM_PPC64 && config->isPic && type == R_PPC64_TOC)
-    addend += getPPC64TocBase();
-  if (config->emachine == EM_MIPS)
-    addend += computeMipsAddend<ELFT>(rel, end, sec, expr, isLocal);
-
-  return addend;
-}
-
 // Custom error message if Sym is defined in a discarded section.
 template <class ELFT>
 static std::string maybeReportDiscarded(Undefined &sym) {
@@ -697,8 +502,8 @@ static std::string maybeReportDiscarded(Undefined &sym) {
   if (!file || !sym.discardedSecIdx ||
       file->getSections()[sym.discardedSecIdx] != &InputSection::discarded)
     return "";
-  ArrayRef<Elf_Shdr_Impl<ELFT>> objSections =
-      CHECK(file->getObj().sections(), file);
+  ArrayRef<typename ELFT::Shdr> objSections =
+      file->template getELFShdrs<ELFT>();
 
   std::string msg;
   if (sym.type == ELF::STT_SECTION) {
@@ -718,17 +523,25 @@ static std::string maybeReportDiscarded(Undefined &sym) {
   // If the discarded section is a COMDAT.
   StringRef signature = file->getShtGroupSignature(objSections, elfSec);
   if (const InputFile *prevailing =
-          symtab->comdatGroups.lookup(CachedHashStringRef(signature)))
+          symtab.comdatGroups.lookup(CachedHashStringRef(signature))) {
     msg += "\n>>> section group signature: " + signature.str() +
            "\n>>> prevailing definition is in " + toString(prevailing);
+    if (sym.nonPrevailing) {
+      msg += "\n>>> or the symbol in the prevailing group had STB_WEAK "
+             "binding and the symbol in a non-prevailing group had STB_GLOBAL "
+             "binding. Mixing groups with STB_WEAK and STB_GLOBAL binding "
+             "signature is not supported";
+    }
+  }
   return msg;
 }
 
+namespace {
 // Undefined diagnostics are collected in a vector and emitted once all of
 // them are known, so that some postprocessing on the list of undefined symbols
 // can happen before lld emits diagnostics.
 struct UndefinedDiag {
-  Symbol *sym;
+  Undefined *sym;
   struct Loc {
     InputSectionBase *sec;
     uint64_t offset;
@@ -737,7 +550,9 @@ struct UndefinedDiag {
   bool isWarning;
 };
 
-static std::vector<UndefinedDiag> undefs;
+std::vector<UndefinedDiag> undefs;
+std::mutex relocMutex;
+}
 
 // Check whether the definition name def is a mangled function name that matches
 // the reference name ref.
@@ -757,12 +572,12 @@ static bool canSuggestExternCForCXX(StringRef ref, StringRef def) {
 // Suggest an alternative spelling of an "undefined symbol" diagnostic. Returns
 // the suggested symbol, which is either in the symbol table, or in the same
 // file of sym.
-template <class ELFT>
 static const Symbol *getAlternativeSpelling(const Undefined &sym,
                                             std::string &pre_hint,
                                             std::string &post_hint) {
   DenseMap<StringRef, const Symbol *> map;
-  if (auto *file = dyn_cast_or_null<ObjFile<ELFT>>(sym.file)) {
+  if (sym.file && sym.file->kind() == InputFile::ObjKind) {
+    auto *file = cast<ELFFileBase>(sym.file);
     // If sym is a symbol defined in a discarded section, maybeReportDiscarded()
     // will give an error. Don't suggest an alternative spelling.
     if (file && sym.discardedSecIdx != 0 &&
@@ -781,7 +596,7 @@ static const Symbol *getAlternativeSpelling(const Undefined &sym,
       return s;
 
     // If in the symbol table and not undefined.
-    if (const Symbol *s = symtab->find(newName))
+    if (const Symbol *s = symtab.find(newName))
       if (!s->isUndefined())
         return s;
 
@@ -830,7 +645,7 @@ static const Symbol *getAlternativeSpelling(const Undefined &sym,
   for (auto &it : map)
     if (name.equals_insensitive(it.first))
       return it.second;
-  for (Symbol *sym : symtab->symbols())
+  for (Symbol *sym : symtab.getSymbols())
     if (!sym->isUndefined() && name.equals_insensitive(sym->getName()))
       return sym;
 
@@ -856,7 +671,7 @@ static const Symbol *getAlternativeSpelling(const Undefined &sym,
         break;
       }
     if (!s)
-      for (Symbol *sym : symtab->symbols())
+      for (Symbol *sym : symtab.getSymbols())
         if (canSuggestExternCForCXX(name, sym->getName())) {
           s = sym;
           break;
@@ -871,13 +686,12 @@ static const Symbol *getAlternativeSpelling(const Undefined &sym,
   return nullptr;
 }
 
-template <class ELFT>
 static void reportUndefinedSymbol(const UndefinedDiag &undef,
                                   bool correctSpelling) {
-  Symbol &sym = *undef.sym;
+  Undefined &sym = *undef.sym;
 
   auto visibility = [&]() -> std::string {
-    switch (sym.visibility) {
+    switch (sym.visibility()) {
     case STV_INTERNAL:
       return "internal ";
     case STV_HIDDEN:
@@ -889,7 +703,23 @@ static void reportUndefinedSymbol(const UndefinedDiag &undef,
     }
   };
 
-  std::string msg = maybeReportDiscarded<ELFT>(cast<Undefined>(sym));
+  std::string msg;
+  switch (config->ekind) {
+  case ELF32LEKind:
+    msg = maybeReportDiscarded<ELF32LE>(sym);
+    break;
+  case ELF32BEKind:
+    msg = maybeReportDiscarded<ELF32BE>(sym);
+    break;
+  case ELF64LEKind:
+    msg = maybeReportDiscarded<ELF64LE>(sym);
+    break;
+  case ELF64BEKind:
+    msg = maybeReportDiscarded<ELF64BE>(sym);
+    break;
+  default:
+    llvm_unreachable("");
+  }
   if (msg.empty())
     msg = "undefined " + visibility() + "symbol: " + toString(sym);
 
@@ -915,8 +745,8 @@ static void reportUndefinedSymbol(const UndefinedDiag &undef,
 
   if (correctSpelling) {
     std::string pre_hint = ": ", post_hint;
-    if (const Symbol *corrected = getAlternativeSpelling<ELFT>(
-            cast<Undefined>(sym), pre_hint, post_hint)) {
+    if (const Symbol *corrected =
+            getAlternativeSpelling(sym, pre_hint, post_hint)) {
       msg += "\n>>> did you mean" + pre_hint + toString(*corrected) + post_hint;
       if (corrected->file)
         msg += "\n>>> defined in: " + toString(corrected->file);
@@ -927,6 +757,12 @@ static void reportUndefinedSymbol(const UndefinedDiag &undef,
     msg +=
         "\n>>> the vtable symbol may be undefined because the class is missing "
         "its key function (see https://lld.llvm.org/missingkeyfunction)";
+  if (config->gcSections && config->zStartStopGC &&
+      sym.getName().startswith("__start_")) {
+    msg += "\n>>> the encapsulation symbol needs to be retained under "
+           "--gc-sections properly; consider -z nostart-stop-gc "
+           "(see https://lld.llvm.org/ELF/start-stop-gc)";
+  }
 
   if (undef.isWarning)
     warn(msg);
@@ -934,7 +770,7 @@ static void reportUndefinedSymbol(const UndefinedDiag &undef,
     error(msg, ErrorTag::SymbolNotFound, {sym.getName()});
 }
 
-template <class ELFT> void elf::reportUndefinedSymbols() {
+void elf::reportUndefinedSymbols() {
   // Find the first "undefined symbol" diagnostic for each diagnostic, and
   // collect all "referenced from" lines at the first diagnostic.
   DenseMap<Symbol *, UndefinedDiag *> firstRef;
@@ -948,9 +784,9 @@ template <class ELFT> void elf::reportUndefinedSymbols() {
   }
 
   // Enable spell corrector for the first 2 diagnostics.
-  for (auto it : enumerate(undefs))
-    if (!it.value().locs.empty())
-      reportUndefinedSymbol<ELFT>(it.value(), it.index() < 2);
+  for (const auto &[i, undef] : llvm::enumerate(undefs))
+    if (!undef.locs.empty())
+      reportUndefinedSymbol(undef, i < 2);
   undefs.clear();
 }
 
@@ -968,20 +804,19 @@ static void reportGNUWarning(Symbol &sym, InputSectionBase &sec,
 
 // Report an undefined symbol if necessary.
 // Returns true if the undefined symbol will produce an error message.
-static bool maybeReportUndefined(Symbol &sym, InputSectionBase &sec,
+static bool maybeReportUndefined(Undefined &sym, InputSectionBase &sec,
                                  uint64_t offset) {
-  if (!sym.isUndefined())
-    return false;
+  std::lock_guard<std::mutex> lock(relocMutex);
   // If versioned, issue an error (even if the symbol is weak) because we don't
   // know the defining filename which is required to construct a Verneed entry.
-  if (*sym.getVersionSuffix() == '@') {
+  if (sym.hasVersionSuffix) {
     undefs.push_back({&sym, {{&sec, offset}}, false});
     return true;
   }
   if (sym.isWeak())
     return false;
 
-  bool canBeExternal = !sym.isLocal() && sym.visibility == STV_DEFAULT;
+  bool canBeExternal = !sym.isLocal() && sym.visibility() == STV_DEFAULT;
   if (config->unresolvedSymbols == UnresolvedPolicy::Ignore && canBeExternal)
     return false;
 
@@ -994,8 +829,7 @@ static bool maybeReportUndefined(Symbol &sym, InputSectionBase &sec,
   // PPC32 .got2 is similar but cannot be fixed. Multiple .got2 is infeasible
   // because .LC0-.LTOC is not representable if the two labels are in different
   // .got2
-  if (cast<Undefined>(sym).discardedSecIdx != 0 &&
-      (sec.name == ".got2" || sec.name == ".toc"))
+  if (sym.discardedSecIdx != 0 && (sec.name == ".got2" || sec.name == ".toc"))
     return false;
 
   bool isWarning =
@@ -1010,66 +844,22 @@ static bool maybeReportUndefined(Symbol &sym, InputSectionBase &sec,
 // packs all relocations into the single relocation record. Here we emulate
 // this for the N32 ABI. Iterate over relocation with the same offset and put
 // theirs types into the single bit-set.
-template <class RelTy> static RelType getMipsN32RelType(RelTy *&rel, RelTy *end) {
+template <class RelTy>
+RelType RelocationScanner::getMipsN32RelType(RelTy *&rel) const {
   RelType type = 0;
   uint64_t offset = rel->r_offset;
 
   int n = 0;
-  while (rel != end && rel->r_offset == offset)
+  while (rel != static_cast<const RelTy *>(end) && rel->r_offset == offset)
     type |= (rel++)->getType(config->isMips64EL) << (8 * n++);
   return type;
 }
 
-// .eh_frame sections are mergeable input sections, so their input
-// offsets are not linearly mapped to output section. For each input
-// offset, we need to find a section piece containing the offset and
-// add the piece's base address to the input offset to compute the
-// output offset. That isn't cheap.
-//
-// This class is to speed up the offset computation. When we process
-// relocations, we access offsets in the monotonically increasing
-// order. So we can optimize for that access pattern.
-//
-// For sections other than .eh_frame, this class doesn't do anything.
-namespace {
-class OffsetGetter {
-public:
-  explicit OffsetGetter(InputSectionBase &sec) {
-    if (auto *eh = dyn_cast<EhInputSection>(&sec))
-      pieces = eh->pieces;
-  }
-
-  // Translates offsets in input sections to offsets in output sections.
-  // Given offset must increase monotonically. We assume that Piece is
-  // sorted by inputOff.
-  uint64_t get(uint64_t off) {
-    if (pieces.empty())
-      return off;
-
-    while (i != pieces.size() && pieces[i].inputOff + pieces[i].size <= off)
-      ++i;
-    if (i == pieces.size())
-      fatal(".eh_frame: relocation is not in any piece");
-
-    // Pieces must be contiguous, so there must be no holes in between.
-    assert(pieces[i].inputOff <= off && "Relocation not in any piece");
-
-    // Offset -1 means that the piece is dead (i.e. garbage collected).
-    if (pieces[i].outputOff == -1)
-      return -1;
-    return pieces[i].outputOff + off - pieces[i].inputOff;
-  }
-
-private:
-  ArrayRef<EhSectionPiece> pieces;
-  size_t i = 0;
-};
-} // namespace
-
-static void addRelativeReloc(InputSectionBase *isec, uint64_t offsetInSec,
+template <bool shard = false>
+static void addRelativeReloc(InputSectionBase &isec, uint64_t offsetInSec,
                              Symbol &sym, int64_t addend, RelExpr expr,
                              RelType type) {
-  Partition &part = isec->getPartition();
+  Partition &part = isec.getPartition();
 
   // Add a relative relocation. If relrDyn section is enabled, and the
   // relocation offset is guaranteed to be even, add the relocation to
@@ -1077,55 +867,58 @@ static void addRelativeReloc(InputSectionBase *isec, uint64_t offsetInSec,
   // relrDyn sections don't support odd offsets. Also, relrDyn sections
   // don't store the addend values, so we must write it to the relocated
   // address.
-  if (part.relrDyn && isec->alignment >= 2 && offsetInSec % 2 == 0) {
-    isec->relocations.push_back({expr, type, offsetInSec, addend, &sym});
-    part.relrDyn->relocs.push_back({isec, offsetInSec});
+  if (part.relrDyn && isec.addralign >= 2 && offsetInSec % 2 == 0) {
+    isec.addReloc({expr, type, offsetInSec, addend, &sym});
+    if (shard)
+      part.relrDyn->relocsVec[parallel::getThreadIndex()].push_back(
+          {&isec, offsetInSec});
+    else
+      part.relrDyn->relocs.push_back({&isec, offsetInSec});
     return;
   }
-  part.relaDyn->addRelativeReloc(target->relativeRel, isec, offsetInSec, sym,
-                                 addend, type, expr);
+  part.relaDyn->addRelativeReloc<shard>(target->relativeRel, isec, offsetInSec,
+                                        sym, addend, type, expr);
 }
 
 template <class PltSection, class GotPltSection>
-static void addPltEntry(PltSection *plt, GotPltSection *gotPlt,
-                        RelocationBaseSection *rel, RelType type, Symbol &sym) {
-  plt->addEntry(sym);
-  gotPlt->addEntry(sym);
-  rel->addReloc({type, gotPlt, sym.getGotPltOffset(),
-                 sym.isPreemptible ? DynamicReloc::AgainstSymbol
-                                   : DynamicReloc::AddendOnlyWithTargetVA,
-                 sym, 0, R_ABS});
+static void addPltEntry(PltSection &plt, GotPltSection &gotPlt,
+                        RelocationBaseSection &rel, RelType type, Symbol &sym) {
+  plt.addEntry(sym);
+  gotPlt.addEntry(sym);
+  rel.addReloc({type, &gotPlt, sym.getGotPltOffset(),
+                sym.isPreemptible ? DynamicReloc::AgainstSymbol
+                                  : DynamicReloc::AddendOnlyWithTargetVA,
+                sym, 0, R_ABS});
 }
 
 static void addGotEntry(Symbol &sym) {
   in.got->addEntry(sym);
-
-  RelExpr expr = sym.isTls() ? R_TPREL : R_ABS;
   uint64_t off = sym.getGotOffset();
 
-  // If a GOT slot value can be calculated at link-time, which is now,
-  // we can just fill that out.
-  //
-  // (We don't actually write a value to a GOT slot right now, but we
-  // add a static relocation to a Relocations vector so that
-  // InputSection::relocate will do the work for us. We may be able
-  // to just write a value now, but it is a TODO.)
-  bool isLinkTimeConstant =
-      !sym.isPreemptible && (!config->isPic || isAbsolute(sym));
-  if (isLinkTimeConstant) {
-    in.got->relocations.push_back({expr, target->symbolicRel, off, 0, &sym});
+  // If preemptible, emit a GLOB_DAT relocation.
+  if (sym.isPreemptible) {
+    mainPart->relaDyn->addReloc({target->gotRel, in.got.get(), off,
+                                 DynamicReloc::AgainstSymbol, sym, 0, R_ABS});
     return;
   }
 
-  // Otherwise, we emit a dynamic relocation to .rel[a].dyn so that
-  // the GOT slot will be fixed at load-time.
-  if (!sym.isTls() && !sym.isPreemptible && config->isPic) {
-    addRelativeReloc(in.got, off, sym, 0, R_ABS, target->symbolicRel);
+  // Otherwise, the value is either a link-time constant or the load base
+  // plus a constant.
+  if (!config->isPic || isAbsolute(sym))
+    in.got->addConstant({R_ABS, target->symbolicRel, off, 0, &sym});
+  else
+    addRelativeReloc(*in.got, off, sym, 0, R_ABS, target->symbolicRel);
+}
+
+static void addTpOffsetGotEntry(Symbol &sym) {
+  in.got->addEntry(sym);
+  uint64_t off = sym.getGotOffset();
+  if (!sym.isPreemptible && !config->isPic) {
+    in.got->addConstant({R_TPREL, target->symbolicRel, off, 0, &sym});
     return;
   }
   mainPart->relaDyn->addAddendOnlyRelocIfNonPreemptible(
-      sym.isTls() ? target->tlsGotRel : target->gotRel, in.got, off, sym,
-      target->symbolicRel);
+      target->tlsGotRel, *in.got, off, sym, target->symbolicRel);
 }
 
 // Return true if we can define a symbol in the executable that
@@ -1135,9 +928,8 @@ static bool canDefineSymbolInExecutable(Symbol &sym) {
   // If the symbol has default visibility the symbol defined in the
   // executable will preempt it.
   // Note that we want the visibility of the shared symbol itself, not
-  // the visibility of the symbol in the output file we are producing. That is
-  // why we use Sym.stOther.
-  if ((sym.stOther & 0x3) == STV_DEFAULT)
+  // the visibility of the symbol in the output file we are producing.
+  if (!sym.dsoProtected)
     return true;
 
   // If we are allowed to break address equality of functions, defining
@@ -1148,6 +940,72 @@ static bool canDefineSymbolInExecutable(Symbol &sym) {
           (sym.isObject() && config->ignoreDataAddressEquality));
 }
 
+// Returns true if a given relocation can be computed at link-time.
+// This only handles relocation types expected in processAux.
+//
+// For instance, we know the offset from a relocation to its target at
+// link-time if the relocation is PC-relative and refers a
+// non-interposable function in the same executable. This function
+// will return true for such relocation.
+//
+// If this function returns false, that means we need to emit a
+// dynamic relocation so that the relocation will be fixed at load-time.
+bool RelocationScanner::isStaticLinkTimeConstant(RelExpr e, RelType type,
+                                                 const Symbol &sym,
+                                                 uint64_t relOff) const {
+  // These expressions always compute a constant
+  if (oneof<R_GOTPLT, R_GOT_OFF, R_RELAX_HINT, R_MIPS_GOT_LOCAL_PAGE,
+            R_MIPS_GOTREL, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC,
+            R_AARCH64_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC, R_GOTPLTONLY_PC,
+            R_PLT_PC, R_PLT_GOTPLT, R_PPC32_PLTREL, R_PPC64_CALL_PLT,
+            R_PPC64_RELAX_TOC, R_RISCV_ADD, R_AARCH64_GOT_PAGE>(e))
+    return true;
+
+  // These never do, except if the entire file is position dependent or if
+  // only the low bits are used.
+  if (e == R_GOT || e == R_PLT)
+    return target->usesOnlyLowPageBits(type) || !config->isPic;
+
+  if (sym.isPreemptible)
+    return false;
+  if (!config->isPic)
+    return true;
+
+  // The size of a non preemptible symbol is a constant.
+  if (e == R_SIZE)
+    return true;
+
+  // For the target and the relocation, we want to know if they are
+  // absolute or relative.
+  bool absVal = isAbsoluteValue(sym);
+  bool relE = isRelExpr(e);
+  if (absVal && !relE)
+    return true;
+  if (!absVal && relE)
+    return true;
+  if (!absVal && !relE)
+    return target->usesOnlyLowPageBits(type);
+
+  assert(absVal && relE);
+
+  // Allow R_PLT_PC (optimized to R_PC here) to a hidden undefined weak symbol
+  // in PIC mode. This is a little strange, but it allows us to link function
+  // calls to such symbols (e.g. glibc/stdlib/exit.c:__run_exit_handlers).
+  // Normally such a call will be guarded with a comparison, which will load a
+  // zero from the GOT.
+  if (sym.isUndefWeak())
+    return true;
+
+  // We set the final symbols values for linker script defined symbols later.
+  // They always can be computed as a link time constant.
+  if (sym.scriptDefined)
+      return true;
+
+  error("relocation " + toString(type) + " cannot refer to absolute symbol: " +
+        toString(sym) + getLocation(*sec, sym, relOff));
+  return true;
+}
+
 // 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.
@@ -1161,10 +1019,58 @@ static bool canDefineSymbolInExecutable(Symbol &sym) {
 // sections. Given that it is ro, we will need an extra PT_LOAD. This
 // complicates things for the dynamic linker and means we would have to reserve
 // space for the extra PT_LOAD even if we end up not using it.
-template <class ELFT, class RelTy>
-static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type,
-                            uint64_t offset, Symbol &sym, const RelTy &rel,
-                            int64_t addend) {
+void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
+                                   Symbol &sym, int64_t addend) const {
+  // If non-ifunc non-preemptible, change PLT to direct call and optimize GOT
+  // indirection.
+  const bool isIfunc = sym.isGnuIFunc();
+  if (!sym.isPreemptible && (!isIfunc || config->zIfuncNoplt)) {
+    if (expr != R_GOT_PC) {
+      // The 0x8000 bit of r_addend of R_PPC_PLTREL24 is used to choose call
+      // stub type. It should be ignored if optimized to R_PC.
+      if (config->emachine == EM_PPC && expr == R_PPC32_PLTREL)
+        addend &= ~0x8000;
+      // R_HEX_GD_PLT_B22_PCREL (call a@GDPLT) is transformed into
+      // call __tls_get_addr even if the symbol is non-preemptible.
+      if (!(config->emachine == EM_HEXAGON &&
+            (type == R_HEX_GD_PLT_B22_PCREL ||
+             type == R_HEX_GD_PLT_B22_PCREL_X ||
+             type == R_HEX_GD_PLT_B32_PCREL_X)))
+        expr = fromPlt(expr);
+    } else if (!isAbsoluteValue(sym)) {
+      expr =
+          target->adjustGotPcExpr(type, addend, sec->content().data() + offset);
+    }
+  }
+
+  // We were asked not to generate PLT entries for ifuncs. Instead, pass the
+  // direct relocation on through.
+  if (LLVM_UNLIKELY(isIfunc) && config->zIfuncNoplt) {
+    std::lock_guard<std::mutex> lock(relocMutex);
+    sym.exportDynamic = true;
+    mainPart->relaDyn->addSymbolReloc(type, *sec, offset, sym, addend, type);
+    return;
+  }
+
+  if (needsGot(expr)) {
+    if (config->emachine == EM_MIPS) {
+      // MIPS ABI has special rules to process GOT entries and doesn't
+      // require relocation entries for them. A special case is TLS
+      // relocations. In that case dynamic loader applies dynamic
+      // relocations to initialize TLS GOT entries.
+      // 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
+      in.mipsGot->addEntry(*sec->file, sym, addend, expr);
+    } else {
+      sym.setFlags(NEEDS_GOT);
+    }
+  } else if (needsPlt(expr)) {
+    sym.setFlags(NEEDS_PLT);
+  } else if (LLVM_UNLIKELY(isIfunc)) {
+    sym.setFlags(HAS_DIRECT_RELOC);
+  }
+
   // If the relocation is known to be a link-time constant, we know no dynamic
   // relocation will be created, pass the control to relocateAlloc() or
   // relocateNonAlloc() to resolve it.
@@ -1179,23 +1085,32 @@ static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type,
   // -shared matches the spirit of its -z undefs default. -pie has freedom on
   // choices, and we choose dynamic relocations to be consistent with the
   // handling of GOT-generating relocations.
-  if (isStaticLinkTimeConstant(expr, type, sym, sec, offset) ||
+  if (isStaticLinkTimeConstant(expr, type, sym, offset) ||
       (!config->isPic && sym.isUndefWeak())) {
-    sec.relocations.push_back({expr, type, offset, addend, &sym});
+    sec->addReloc({expr, type, offset, addend, &sym});
     return;
   }
 
-  bool canWrite = (sec.flags & SHF_WRITE) || !config->zText;
+  // Use a simple -z notext rule that treats all sections except .eh_frame as
+  // writable. GNU ld does not produce dynamic relocations in .eh_frame (and our
+  // SectionBase::getOffset would incorrectly adjust the offset).
+  //
+  // For MIPS, we don't implement GNU ld's DW_EH_PE_absptr to DW_EH_PE_pcrel
+  // conversion. We still emit a dynamic relocation.
+  bool canWrite = (sec->flags & SHF_WRITE) ||
+                  !(config->zText ||
+                    (isa<EhInputSection>(sec) && config->emachine != EM_MIPS));
   if (canWrite) {
     RelType rel = target->getDynRel(type);
     if (expr == R_GOT || (rel == target->symbolicRel && !sym.isPreemptible)) {
-      addRelativeReloc(&sec, offset, sym, addend, expr, type);
+      addRelativeReloc<true>(*sec, offset, sym, addend, expr, type);
       return;
     } else if (rel != 0) {
       if (config->emachine == EM_MIPS && rel == target->symbolicRel)
         rel = target->relativeRel;
-      sec.getPartition().relaDyn->addSymbolReloc(rel, &sec, offset, sym, addend,
-                                                 type);
+      std::lock_guard<std::mutex> lock(relocMutex);
+      sec->getPartition().relaDyn->addSymbolReloc(rel, *sec, offset, sym,
+                                                  addend, type);
 
       // MIPS ABI turns using of GOT and dynamic relocations inside out.
       // While regular ABI uses dynamic relocations to fill up GOT entries
@@ -1213,7 +1128,7 @@ static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type,
       // a dynamic relocation.
       // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf p.4-19
       if (config->emachine == EM_MIPS)
-        in.mipsGot->addEntry(*sec.file, sym, addend, expr);
+        in.mipsGot->addEntry(*sec->file, sym, addend, expr);
       return;
     }
   }
@@ -1223,7 +1138,7 @@ static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type,
   if (!config->shared) {
     if (!canDefineSymbolInExecutable(sym)) {
       errorOrWarn("cannot preempt symbol: " + toString(sym) +
-                  getLocation(sec, sym, offset));
+                  getLocation(*sec, sym, offset));
       return;
     }
 
@@ -1234,10 +1149,10 @@ static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type,
           error("unresolvable relocation " + toString(type) +
                 " against symbol '" + toString(*ss) +
                 "'; recompile with -fPIC or remove '-z nocopyreloc'" +
-                getLocation(sec, sym, offset));
-        addCopyRelSymbol<ELFT>(*ss);
+                getLocation(*sec, sym, offset));
+        sym.setFlags(NEEDS_COPY);
       }
-      sec.relocations.push_back({expr, type, offset, addend, &sym});
+      sec->addReloc({expr, type, offset, addend, &sym});
       return;
     }
 
@@ -1272,84 +1187,204 @@ static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type,
       if (config->pie && config->emachine == EM_386)
         errorOrWarn("symbol '" + toString(sym) +
                     "' cannot be preempted; recompile with -fPIE" +
-                    getLocation(sec, sym, offset));
-      if (!sym.isInPlt())
-        addPltEntry(in.plt, in.gotPlt, in.relaPlt, target->pltRel, sym);
-      if (!sym.isDefined()) {
-        replaceWithDefined(
-            sym, in.plt,
-            target->pltHeaderSize + target->pltEntrySize * sym.pltIndex, 0);
-        if (config->emachine == EM_PPC) {
-          // PPC32 canonical PLT entries are at the beginning of .glink
-          cast<Defined>(sym).value = in.plt->headerSize;
-          in.plt->headerSize += 16;
-          cast<PPC32GlinkSection>(in.plt)->canonical_plts.push_back(&sym);
-        }
-      }
-      sym.needsPltAddr = true;
-      sec.relocations.push_back({expr, type, offset, addend, &sym});
+                    getLocation(*sec, sym, offset));
+      sym.setFlags(NEEDS_COPY | NEEDS_PLT);
+      sec->addReloc({expr, type, offset, addend, &sym});
       return;
     }
   }
 
-  if (config->isPic) {
-    if (!canWrite && !isRelExpr(expr))
-      errorOrWarn(
-          "can't create dynamic relocation " + toString(type) + " against " +
-          (sym.getName().empty() ? "local symbol"
-                                 : "symbol: " + toString(sym)) +
-          " in readonly segment; recompile object files with -fPIC "
-          "or pass '-Wl,-z,notext' to allow text relocations in the output" +
-          getLocation(sec, sym, offset));
-    else
-      errorOrWarn(
-          "relocation " + toString(type) + " cannot be used against " +
-          (sym.getName().empty() ? "local symbol" : "symbol " + toString(sym)) +
-          "; recompile with -fPIC" + getLocation(sec, sym, offset));
-    return;
+  errorOrWarn("relocation " + toString(type) + " cannot be used against " +
+              (sym.getName().empty() ? "local symbol"
+                                     : "symbol '" + toString(sym) + "'") +
+              "; recompile with -fPIC" + getLocation(*sec, sym, offset));
+}
+
+// This function is similar to the `handleTlsRelocation`. MIPS does not
+// support any relaxations for TLS relocations so by factoring out MIPS
+// handling in to the separate function we can simplify the code and do not
+// pollute other `handleTlsRelocation` by MIPS `ifs` statements.
+// Mips has a custom MipsGotSection that handles the writing of GOT entries
+// without dynamic relocations.
+static unsigned handleMipsTlsRelocation(RelType type, Symbol &sym,
+                                        InputSectionBase &c, uint64_t offset,
+                                        int64_t addend, RelExpr expr) {
+  if (expr == R_MIPS_TLSLD) {
+    in.mipsGot->addTlsIndex(*c.file);
+    c.addReloc({expr, type, offset, addend, &sym});
+    return 1;
+  }
+  if (expr == R_MIPS_TLSGD) {
+    in.mipsGot->addDynTlsEntry(*c.file, sym);
+    c.addReloc({expr, type, offset, addend, &sym});
+    return 1;
+  }
+  return 0;
+}
+
+// Notes about General Dynamic and Local Dynamic TLS models below. They may
+// require the generation of a pair of GOT entries that have associated dynamic
+// relocations. The pair of GOT entries created are of the form GOT[e0] Module
+// Index (Used to find pointer to TLS block at run-time) GOT[e1] Offset of
+// symbol in TLS block.
+//
+// Returns the number of relocations processed.
+static unsigned handleTlsRelocation(RelType type, Symbol &sym,
+                                    InputSectionBase &c, uint64_t offset,
+                                    int64_t addend, RelExpr expr) {
+  if (expr == R_TPREL || expr == R_TPREL_NEG) {
+    if (config->shared) {
+      errorOrWarn("relocation " + toString(type) + " against " + toString(sym) +
+                  " cannot be used with -shared" + getLocation(c, sym, offset));
+      return 1;
+    }
+    return 0;
+  }
+
+  if (config->emachine == EM_MIPS)
+    return handleMipsTlsRelocation(type, sym, c, offset, addend, expr);
+
+  if (oneof<R_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC,
+            R_TLSDESC_GOTPLT>(expr) &&
+      config->shared) {
+    if (expr != R_TLSDESC_CALL) {
+      sym.setFlags(NEEDS_TLSDESC);
+      c.addReloc({expr, type, offset, addend, &sym});
+    }
+    return 1;
+  }
+
+  // ARM, Hexagon and RISC-V do not support GD/LD to IE/LE relaxation.  For
+  // PPC64, if the file has missing R_PPC64_TLSGD/R_PPC64_TLSLD, disable
+  // relaxation as well.
+  bool toExecRelax = !config->shared && config->emachine != EM_ARM &&
+                     config->emachine != EM_HEXAGON &&
+                     config->emachine != EM_RISCV &&
+                     !c.file->ppc64DisableTLSRelax;
+
+  // If we are producing an executable and the symbol is non-preemptable, it
+  // must be defined and the code sequence can be relaxed to use Local-Exec.
+  //
+  // ARM and RISC-V do not support any relaxations for TLS relocations, however,
+  // we can omit the DTPMOD dynamic relocations and resolve them at link time
+  // because them are always 1. This may be necessary for static linking as
+  // DTPMOD may not be expected at load time.
+  bool isLocalInExecutable = !sym.isPreemptible && !config->shared;
+
+  // Local Dynamic is for access to module local TLS variables, while still
+  // being suitable for being dynamically loaded via dlopen. GOT[e0] is the
+  // module index, with a special value of 0 for the current module. GOT[e1] is
+  // unused. There only needs to be one module index entry.
+  if (oneof<R_TLSLD_GOT, R_TLSLD_GOTPLT, R_TLSLD_PC, R_TLSLD_HINT>(
+          expr)) {
+    // Local-Dynamic relocs can be relaxed to Local-Exec.
+    if (toExecRelax) {
+      c.addReloc({target->adjustTlsExpr(type, R_RELAX_TLS_LD_TO_LE), type,
+                  offset, addend, &sym});
+      return target->getTlsGdRelaxSkip(type);
+    }
+    if (expr == R_TLSLD_HINT)
+      return 1;
+    ctx.needsTlsLd.store(true, std::memory_order_relaxed);
+    c.addReloc({expr, type, offset, addend, &sym});
+    return 1;
+  }
+
+  // Local-Dynamic relocs can be relaxed to Local-Exec.
+  if (expr == R_DTPREL) {
+    if (toExecRelax)
+      expr = target->adjustTlsExpr(type, R_RELAX_TLS_LD_TO_LE);
+    c.addReloc({expr, type, offset, addend, &sym});
+    return 1;
+  }
+
+  // Local-Dynamic sequence where offset of tls variable relative to dynamic
+  // thread pointer is stored in the got. This cannot be relaxed to Local-Exec.
+  if (expr == R_TLSLD_GOT_OFF) {
+    sym.setFlags(NEEDS_GOT_DTPREL);
+    c.addReloc({expr, type, offset, addend, &sym});
+    return 1;
+  }
+
+  if (oneof<R_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC,
+            R_TLSDESC_GOTPLT, R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC>(expr)) {
+    if (!toExecRelax) {
+      sym.setFlags(NEEDS_TLSGD);
+      c.addReloc({expr, type, offset, addend, &sym});
+      return 1;
+    }
+
+    // Global-Dynamic relocs can be relaxed to Initial-Exec or Local-Exec
+    // depending on the symbol being locally defined or not.
+    if (sym.isPreemptible) {
+      sym.setFlags(NEEDS_TLSGD_TO_IE);
+      c.addReloc({target->adjustTlsExpr(type, R_RELAX_TLS_GD_TO_IE), type,
+                  offset, addend, &sym});
+    } else {
+      c.addReloc({target->adjustTlsExpr(type, R_RELAX_TLS_GD_TO_LE), type,
+                  offset, addend, &sym});
+    }
+    return target->getTlsGdRelaxSkip(type);
+  }
+
+  if (oneof<R_GOT, R_GOTPLT, R_GOT_PC, R_AARCH64_GOT_PAGE_PC, R_GOT_OFF,
+            R_TLSIE_HINT>(expr)) {
+    ctx.hasTlsIe.store(true, std::memory_order_relaxed);
+    // Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally
+    // defined.
+    if (toExecRelax && isLocalInExecutable) {
+      c.addReloc({R_RELAX_TLS_IE_TO_LE, type, offset, addend, &sym});
+    } else if (expr != R_TLSIE_HINT) {
+      sym.setFlags(NEEDS_TLSIE);
+      // R_GOT needs a relative relocation for PIC on i386 and Hexagon.
+      if (expr == R_GOT && config->isPic && !target->usesOnlyLowPageBits(type))
+        addRelativeReloc<true>(c, offset, sym, addend, expr, type);
+      else
+        c.addReloc({expr, type, offset, addend, &sym});
+    }
+    return 1;
   }
 
-  errorOrWarn("symbol '" + toString(sym) + "' has no type" +
-              getLocation(sec, sym, offset));
+  return 0;
 }
 
-template <class ELFT, class RelTy>
-static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
-                      RelTy *start, RelTy *end) {
+template <class ELFT, class RelTy> void RelocationScanner::scanOne(RelTy *&i) {
   const RelTy &rel = *i;
   uint32_t symIndex = rel.getSymbol(config->isMips64EL);
-  Symbol &sym = sec.getFile<ELFT>()->getSymbol(symIndex);
+  Symbol &sym = sec->getFile<ELFT>()->getSymbol(symIndex);
   RelType type;
-
-  // Deal with MIPS oddity.
   if (config->mipsN32Abi) {
-    type = getMipsN32RelType(i, end);
+    type = getMipsN32RelType(i);
   } else {
     type = rel.getType(config->isMips64EL);
     ++i;
   }
-
   // Get an offset in an output section this relocation is applied to.
-  uint64_t offset = getOffset.get(rel.r_offset);
+  uint64_t offset = getter.get(rel.r_offset);
   if (offset == uint64_t(-1))
     return;
 
-  // Error if the target symbol is undefined. Symbol index 0 may be used by
-  // marker relocations, e.g. R_*_NONE and R_ARM_V4BX. Don't error on them.
-  if (symIndex != 0 && maybeReportUndefined(sym, sec, rel.r_offset))
-    return;
-
-  reportGNUWarning(sym, sec, rel.r_offset);
+  reportGNUWarning(sym, *sec, rel.r_offset);
 
-  const uint8_t *relocatedAddr = sec.data().begin() + rel.r_offset;
-  RelExpr expr = target->getRelExpr(type, sym, relocatedAddr);
+  RelExpr expr = target->getRelExpr(type, sym, sec->content().data() + offset);
+  int64_t addend = RelTy::IsRela
+                       ? getAddend<ELFT>(rel)
+                       : target->getImplicitAddend(
+                             sec->content().data() + rel.r_offset, type);
+  if (LLVM_UNLIKELY(config->emachine == EM_MIPS))
+    addend += computeMipsAddend<ELFT>(rel, expr, sym.isLocal());
+  else if (config->emachine == EM_PPC64 && config->isPic && type == R_PPC64_TOC)
+    addend += getPPC64TocBase();
 
   // Ignore R_*_NONE and other marker relocations.
   if (expr == R_NONE)
     return;
 
-  // Read an addend.
-  int64_t addend = computeAddend<ELFT>(rel, end, sec, expr, sym.isLocal());
+  // Error if the target symbol is undefined. Symbol index 0 may be used by
+  // marker relocations, e.g. R_*_NONE and R_ARM_V4BX. Don't error on them.
+  if (sym.isUndefined() && symIndex != 0 &&
+      maybeReportUndefined(cast<Undefined>(sym), *sec, offset))
+    return;
 
   if (config->emachine == EM_PPC64) {
     // We can separate the small code model relocations into 2 categories:
@@ -1360,8 +1395,8 @@ static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
     // have got-based small code model relocs. The .toc sections get placed
     // after the end of the linker allocated .got section and we do sort those
     // so sections addressed with small code model relocations come first.
-    if (isPPC64SmallCodeModelTocReloc(type))
-      sec.file->ppc64SmallCodeModelTocRelocs = true;
+    if (type == R_PPC64_TOC16 || type == R_PPC64_TOC16_DS)
+      sec->file->ppc64SmallCodeModelTocRelocs = true;
 
     // Record the TOC entry (.toc + addend) as not relaxable. See the comment in
     // InputSectionBase::relocateAlloc().
@@ -1374,7 +1409,7 @@ static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
       if (i == end) {
         errorOrWarn("R_PPC64_TLSGD/R_PPC64_TLSLD may not be the last "
                     "relocation" +
-                    getLocation(sec, sym, offset));
+                    getLocation(*sec, sym, offset));
         return;
       }
 
@@ -1385,179 +1420,29 @@ static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
     }
   }
 
-  // Relax relocations.
-  //
-  // If we know that a PLT entry will be resolved within the same ELF module, we
-  // can skip PLT access and directly jump to the destination function. For
-  // example, if we are linking a main executable, all dynamic symbols that can
-  // be resolved within the executable will actually be resolved that way at
-  // runtime, because the main executable is always at the beginning of a search
-  // list. We can leverage that fact.
-  if (!sym.isPreemptible && (!sym.isGnuIFunc() || config->zIfuncNoplt)) {
-    if (expr != R_GOT_PC) {
-      // The 0x8000 bit of r_addend of R_PPC_PLTREL24 is used to choose call
-      // stub type. It should be ignored if optimized to R_PC.
-      if (config->emachine == EM_PPC && expr == R_PPC32_PLTREL)
-        addend &= ~0x8000;
-      // R_HEX_GD_PLT_B22_PCREL (call a@GDPLT) is transformed into
-      // call __tls_get_addr even if the symbol is non-preemptible.
-      if (!(config->emachine == EM_HEXAGON &&
-           (type == R_HEX_GD_PLT_B22_PCREL ||
-            type == R_HEX_GD_PLT_B22_PCREL_X ||
-            type == R_HEX_GD_PLT_B32_PCREL_X)))
-      expr = fromPlt(expr);
-    } else if (!isAbsoluteValue(sym)) {
-      expr = target->adjustGotPcExpr(type, addend, relocatedAddr);
-    }
-  }
-
   // If the relocation does not emit a GOT or GOTPLT entry but its computation
   // uses their addresses, we need GOT or GOTPLT to be created.
   //
-  // The 4 types that relative GOTPLT are all x86 and x86-64 specific.
-  if (oneof<R_GOTPLTONLY_PC, R_GOTPLTREL, R_GOTPLT, R_TLSGD_GOTPLT>(expr)) {
-    in.gotPlt->hasGotPltOffRel = true;
+  // The 5 types that relative GOTPLT are all x86 and x86-64 specific.
+  if (oneof<R_GOTPLTONLY_PC, R_GOTPLTREL, R_GOTPLT, R_PLT_GOTPLT,
+            R_TLSDESC_GOTPLT, R_TLSGD_GOTPLT>(expr)) {
+    in.gotPlt->hasGotPltOffRel.store(true, std::memory_order_relaxed);
   } else if (oneof<R_GOTONLY_PC, R_GOTREL, R_PPC32_PLTREL, R_PPC64_TOCBASE,
                    R_PPC64_RELAX_TOC>(expr)) {
-    in.got->hasGotOffRel = true;
+    in.got->hasGotOffRel.store(true, std::memory_order_relaxed);
   }
 
   // Process TLS relocations, including relaxing TLS relocations. Note that
-  // R_TPREL and R_TPREL_NEG relocations are resolved in processRelocAux.
-  if (expr == R_TPREL || expr == R_TPREL_NEG) {
-    if (config->shared) {
-      errorOrWarn("relocation " + toString(type) + " against " + toString(sym) +
-                  " cannot be used with -shared" +
-                  getLocation(sec, sym, offset));
+  // R_TPREL and R_TPREL_NEG relocations are resolved in processAux.
+  if (sym.isTls()) {
+    if (unsigned processed =
+            handleTlsRelocation(type, sym, *sec, offset, addend, expr)) {
+      i += processed - 1;
       return;
     }
-  } else if (unsigned processed = handleTlsRelocation<ELFT>(
-                 type, sym, sec, offset, addend, expr)) {
-    i += (processed - 1);
-    return;
-  }
-
-  // We were asked not to generate PLT entries for ifuncs. Instead, pass the
-  // direct relocation on through.
-  if (sym.isGnuIFunc() && config->zIfuncNoplt) {
-    sym.exportDynamic = true;
-    mainPart->relaDyn->addSymbolReloc(type, &sec, offset, sym, addend, type);
-    return;
-  }
-
-  // Non-preemptible ifuncs require special handling. First, handle the usual
-  // case where the symbol isn't one of these.
-  if (!sym.isGnuIFunc() || sym.isPreemptible) {
-    // If a relocation needs PLT, we create PLT and GOTPLT slots for the symbol.
-    if (needsPlt(expr) && !sym.isInPlt())
-      addPltEntry(in.plt, in.gotPlt, in.relaPlt, target->pltRel, sym);
-
-    // Create a GOT slot if a relocation needs GOT.
-    if (needsGot(expr)) {
-      if (config->emachine == EM_MIPS) {
-        // MIPS ABI has special rules to process GOT entries and doesn't
-        // require relocation entries for them. A special case is TLS
-        // relocations. In that case dynamic loader applies dynamic
-        // relocations to initialize TLS GOT entries.
-        // 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
-        in.mipsGot->addEntry(*sec.file, sym, addend, expr);
-      } else if (!sym.isInGot()) {
-        addGotEntry(sym);
-      }
-    }
-  } else {
-    // Handle a reference to a non-preemptible ifunc. These are special in a
-    // few ways:
-    //
-    // - Unlike most non-preemptible symbols, non-preemptible ifuncs do not have
-    //   a fixed value. But assuming that all references to the ifunc are
-    //   GOT-generating or PLT-generating, the handling of an ifunc is
-    //   relatively straightforward. We create a PLT entry in Iplt, which is
-    //   usually at the end of .plt, which makes an indirect call using a
-    //   matching GOT entry in igotPlt, which is usually at the end of .got.plt.
-    //   The GOT entry is relocated using an IRELATIVE relocation in relaIplt,
-    //   which is usually at the end of .rela.plt. Unlike most relocations in
-    //   .rela.plt, which may be evaluated lazily without -z now, dynamic
-    //   loaders evaluate IRELATIVE relocs eagerly, which means that for
-    //   IRELATIVE relocs only, GOT-generating relocations can point directly to
-    //   .got.plt without requiring a separate GOT entry.
-    //
-    // - Despite the fact that an ifunc does not have a fixed value, compilers
-    //   that are not passed -fPIC will assume that they do, and will emit
-    //   direct (non-GOT-generating, non-PLT-generating) relocations to the
-    //   symbol. This means that if a direct relocation to the symbol is
-    //   seen, the linker must set a value for the symbol, and this value must
-    //   be consistent no matter what type of reference is made to the symbol.
-    //   This can be done by creating a PLT entry for the symbol in the way
-    //   described above and making it canonical, that is, making all references
-    //   point to the PLT entry instead of the resolver. In lld we also store
-    //   the address of the PLT entry in the dynamic symbol table, which means
-    //   that the symbol will also have the same value in other modules.
-    //   Because the value loaded from the GOT needs to be consistent with
-    //   the value computed using a direct relocation, a non-preemptible ifunc
-    //   may end up with two GOT entries, one in .got.plt that points to the
-    //   address returned by the resolver and is used only by the PLT entry,
-    //   and another in .got that points to the PLT entry and is used by
-    //   GOT-generating relocations.
-    //
-    // - The fact that these symbols do not have a fixed value makes them an
-    //   exception to the general rule that a statically linked executable does
-    //   not require any form of dynamic relocation. To handle these relocations
-    //   correctly, the IRELATIVE relocations are stored in an array which a
-    //   statically linked executable's startup code must enumerate using the
-    //   linker-defined symbols __rela?_iplt_{start,end}.
-    if (!sym.isInPlt()) {
-      // Create PLT and GOTPLT slots for the symbol.
-      sym.isInIplt = true;
-
-      // Create a copy of the symbol to use as the target of the IRELATIVE
-      // relocation in the igotPlt. This is in case we make the PLT canonical
-      // later, which would overwrite the original symbol.
-      //
-      // FIXME: Creating a copy of the symbol here is a bit of a hack. All
-      // that's really needed to create the IRELATIVE is the section and value,
-      // so ideally we should just need to copy those.
-      auto *directSym = make<Defined>(cast<Defined>(sym));
-      addPltEntry(in.iplt, in.igotPlt, in.relaIplt, target->iRelativeRel,
-                  *directSym);
-      sym.pltIndex = directSym->pltIndex;
-    }
-    if (needsGot(expr)) {
-      // Redirect GOT accesses to point to the Igot.
-      //
-      // This field is also used to keep track of whether we ever needed a GOT
-      // entry. If we did and we make the PLT canonical later, we'll need to
-      // create a GOT entry pointing to the PLT entry for Sym.
-      sym.gotInIgot = true;
-    } else if (!needsPlt(expr)) {
-      // Make the ifunc's PLT entry canonical by changing the value of its
-      // symbol to redirect all references to point to it.
-      auto &d = cast<Defined>(sym);
-      d.section = in.iplt;
-      d.value = sym.pltIndex * target->ipltEntrySize;
-      d.size = 0;
-      // It's important to set the symbol type here so that dynamic loaders
-      // don't try to call the PLT as if it were an ifunc resolver.
-      d.type = STT_FUNC;
-
-      if (sym.gotInIgot) {
-        // We previously encountered a GOT generating reference that we
-        // redirected to the Igot. Now that the PLT entry is canonical we must
-        // clear the redirection to the Igot and add a GOT entry. As we've
-        // changed the symbol type to STT_FUNC future GOT generating references
-        // will naturally use this GOT entry.
-        //
-        // We don't need to worry about creating a MIPS GOT here because ifuncs
-        // aren't a thing on MIPS.
-        sym.gotInIgot = false;
-        addGotEntry(sym);
-      }
-    }
   }
 
-  processRelocAux<ELFT>(sec, expr, type, offset, sym, rel, addend);
+  processAux(expr, type, offset, sym, addend);
 }
 
 // R_PPC64_TLSGD/R_PPC64_TLSLD is required to mark `bl __tls_get_addr` for
@@ -1598,14 +1483,12 @@ static void checkPPC64TLSRelax(InputSectionBase &sec, ArrayRef<RelTy> rels) {
 }
 
 template <class ELFT, class RelTy>
-static void scanRelocs(InputSectionBase &sec, ArrayRef<RelTy> rels) {
-  OffsetGetter getOffset(sec);
-
-  // Not all relocations end up in Sec.Relocations, but a lot do.
-  sec.relocations.reserve(rels.size());
+void RelocationScanner::scan(ArrayRef<RelTy> rels) {
+  // Not all relocations end up in Sec->Relocations, but a lot do.
+  sec->relocations.reserve(rels.size());
 
   if (config->emachine == EM_PPC64)
-    checkPPC64TLSRelax<RelTy>(sec, rels);
+    checkPPC64TLSRelax<RelTy>(*sec, rels);
 
   // For EhInputSection, OffsetGetter expects the relocations to be sorted by
   // r_offset. In rare cases (.eh_frame pieces are reordered by a linker
@@ -1614,24 +1497,254 @@ static void scanRelocs(InputSectionBase &sec, ArrayRef<RelTy> rels) {
   if (isa<EhInputSection>(sec))
     rels = sortRels(rels, storage);
 
-  for (auto i = rels.begin(), end = rels.end(); i != end;)
-    scanReloc<ELFT>(sec, getOffset, i, rels.begin(), end);
+  end = static_cast<const void *>(rels.end());
+  for (auto i = rels.begin(); i != end;)
+    scanOne<ELFT>(i);
 
   // Sort relocations by offset for more efficient searching for
   // R_RISCV_PCREL_HI20 and R_PPC64_ADDR64.
   if (config->emachine == EM_RISCV ||
-      (config->emachine == EM_PPC64 && sec.name == ".toc"))
-    llvm::stable_sort(sec.relocations,
+      (config->emachine == EM_PPC64 && sec->name == ".toc"))
+    llvm::stable_sort(sec->relocs(),
                       [](const Relocation &lhs, const Relocation &rhs) {
                         return lhs.offset < rhs.offset;
                       });
 }
 
-template <class ELFT> void elf::scanRelocations(InputSectionBase &s) {
-  if (s.areRelocsRela)
-    scanRelocs<ELFT>(s, s.relas<ELFT>());
+template <class ELFT> void RelocationScanner::scanSection(InputSectionBase &s) {
+  sec = &s;
+  getter = OffsetGetter(s);
+  const RelsOrRelas<ELFT> rels = s.template relsOrRelas<ELFT>();
+  if (rels.areRelocsRel())
+    scan<ELFT>(rels.rels);
   else
-    scanRelocs<ELFT>(s, s.rels<ELFT>());
+    scan<ELFT>(rels.relas);
+}
+
+template <class ELFT> void elf::scanRelocations() {
+  // Scan all relocations. Each relocation goes through a series of tests to
+  // determine if it needs special treatment, such as creating GOT, PLT,
+  // copy relocations, etc. Note that relocations for non-alloc sections are
+  // directly processed by InputSection::relocateNonAlloc.
+
+  // Deterministic parallellism needs sorting relocations which is unsuitable
+  // for -z nocombreloc. MIPS and PPC64 use global states which are not suitable
+  // for parallelism.
+  bool serial = !config->zCombreloc || config->emachine == EM_MIPS ||
+                config->emachine == EM_PPC64;
+  parallel::TaskGroup tg;
+  for (ELFFileBase *f : ctx.objectFiles) {
+    auto fn = [f]() {
+      RelocationScanner scanner;
+      for (InputSectionBase *s : f->getSections()) {
+        if (s && s->kind() == SectionBase::Regular && s->isLive() &&
+            (s->flags & SHF_ALLOC) &&
+            !(s->type == SHT_ARM_EXIDX && config->emachine == EM_ARM))
+          scanner.template scanSection<ELFT>(*s);
+      }
+    };
+    if (serial)
+      fn();
+    else
+      tg.execute(fn);
+  }
+
+  // Both the main thread and thread pool index 0 use getThreadIndex()==0. Be
+  // careful that they don't concurrently run scanSections. When serial is
+  // true, fn() has finished at this point, so running execute is safe.
+  tg.execute([] {
+    RelocationScanner scanner;
+    for (Partition &part : partitions) {
+      for (EhInputSection *sec : part.ehFrame->sections)
+        scanner.template scanSection<ELFT>(*sec);
+      if (part.armExidx && part.armExidx->isLive())
+        for (InputSection *sec : part.armExidx->exidxSections)
+          scanner.template scanSection<ELFT>(*sec);
+    }
+  });
+}
+
+static bool handleNonPreemptibleIfunc(Symbol &sym, uint16_t flags) {
+  // Handle a reference to a non-preemptible ifunc. These are special in a
+  // few ways:
+  //
+  // - Unlike most non-preemptible symbols, non-preemptible ifuncs do not have
+  //   a fixed value. But assuming that all references to the ifunc are
+  //   GOT-generating or PLT-generating, the handling of an ifunc is
+  //   relatively straightforward. We create a PLT entry in Iplt, which is
+  //   usually at the end of .plt, which makes an indirect call using a
+  //   matching GOT entry in igotPlt, which is usually at the end of .got.plt.
+  //   The GOT entry is relocated using an IRELATIVE relocation in relaIplt,
+  //   which is usually at the end of .rela.plt. Unlike most relocations in
+  //   .rela.plt, which may be evaluated lazily without -z now, dynamic
+  //   loaders evaluate IRELATIVE relocs eagerly, which means that for
+  //   IRELATIVE relocs only, GOT-generating relocations can point directly to
+  //   .got.plt without requiring a separate GOT entry.
+  //
+  // - Despite the fact that an ifunc does not have a fixed value, compilers
+  //   that are not passed -fPIC will assume that they do, and will emit
+  //   direct (non-GOT-generating, non-PLT-generating) relocations to the
+  //   symbol. This means that if a direct relocation to the symbol is
+  //   seen, the linker must set a value for the symbol, and this value must
+  //   be consistent no matter what type of reference is made to the symbol.
+  //   This can be done by creating a PLT entry for the symbol in the way
+  //   described above and making it canonical, that is, making all references
+  //   point to the PLT entry instead of the resolver. In lld we also store
+  //   the address of the PLT entry in the dynamic symbol table, which means
+  //   that the symbol will also have the same value in other modules.
+  //   Because the value loaded from the GOT needs to be consistent with
+  //   the value computed using a direct relocation, a non-preemptible ifunc
+  //   may end up with two GOT entries, one in .got.plt that points to the
+  //   address returned by the resolver and is used only by the PLT entry,
+  //   and another in .got that points to the PLT entry and is used by
+  //   GOT-generating relocations.
+  //
+  // - The fact that these symbols do not have a fixed value makes them an
+  //   exception to the general rule that a statically linked executable does
+  //   not require any form of dynamic relocation. To handle these relocations
+  //   correctly, the IRELATIVE relocations are stored in an array which a
+  //   statically linked executable's startup code must enumerate using the
+  //   linker-defined symbols __rela?_iplt_{start,end}.
+  if (!sym.isGnuIFunc() || sym.isPreemptible || config->zIfuncNoplt)
+    return false;
+  // Skip unreferenced non-preemptible ifunc.
+  if (!(flags & (NEEDS_GOT | NEEDS_PLT | HAS_DIRECT_RELOC)))
+    return true;
+
+  sym.isInIplt = true;
+
+  // Create an Iplt and the associated IRELATIVE relocation pointing to the
+  // original section/value pairs. For non-GOT non-PLT relocation case below, we
+  // may alter section/value, so create a copy of the symbol to make
+  // section/value fixed.
+  auto *directSym = makeDefined(cast<Defined>(sym));
+  directSym->allocateAux();
+  addPltEntry(*in.iplt, *in.igotPlt, *in.relaIplt, target->iRelativeRel,
+              *directSym);
+  sym.allocateAux();
+  symAux.back().pltIdx = symAux[directSym->auxIdx].pltIdx;
+
+  if (flags & HAS_DIRECT_RELOC) {
+    // Change the value to the IPLT and redirect all references to it.
+    auto &d = cast<Defined>(sym);
+    d.section = in.iplt.get();
+    d.value = d.getPltIdx() * target->ipltEntrySize;
+    d.size = 0;
+    // It's important to set the symbol type here so that dynamic loaders
+    // don't try to call the PLT as if it were an ifunc resolver.
+    d.type = STT_FUNC;
+
+    if (flags & NEEDS_GOT)
+      addGotEntry(sym);
+  } else if (flags & NEEDS_GOT) {
+    // Redirect GOT accesses to point to the Igot.
+    sym.gotInIgot = true;
+  }
+  return true;
+}
+
+void elf::postScanRelocations() {
+  auto fn = [](Symbol &sym) {
+    auto flags = sym.flags.load(std::memory_order_relaxed);
+    if (handleNonPreemptibleIfunc(sym, flags))
+      return;
+    if (!sym.needsDynReloc())
+      return;
+    sym.allocateAux();
+
+    if (flags & NEEDS_GOT)
+      addGotEntry(sym);
+    if (flags & NEEDS_PLT)
+      addPltEntry(*in.plt, *in.gotPlt, *in.relaPlt, target->pltRel, sym);
+    if (flags & NEEDS_COPY) {
+      if (sym.isObject()) {
+        invokeELFT(addCopyRelSymbol, cast<SharedSymbol>(sym));
+        // NEEDS_COPY is cleared for sym and its aliases so that in
+        // later iterations aliases won't cause redundant copies.
+        assert(!sym.hasFlag(NEEDS_COPY));
+      } else {
+        assert(sym.isFunc() && sym.hasFlag(NEEDS_PLT));
+        if (!sym.isDefined()) {
+          replaceWithDefined(sym, *in.plt,
+                             target->pltHeaderSize +
+                                 target->pltEntrySize * sym.getPltIdx(),
+                             0);
+          sym.setFlags(NEEDS_COPY);
+          if (config->emachine == EM_PPC) {
+            // PPC32 canonical PLT entries are at the beginning of .glink
+            cast<Defined>(sym).value = in.plt->headerSize;
+            in.plt->headerSize += 16;
+            cast<PPC32GlinkSection>(*in.plt).canonical_plts.push_back(&sym);
+          }
+        }
+      }
+    }
+
+    if (!sym.isTls())
+      return;
+    bool isLocalInExecutable = !sym.isPreemptible && !config->shared;
+    GotSection *got = in.got.get();
+
+    if (flags & NEEDS_TLSDESC) {
+      got->addTlsDescEntry(sym);
+      mainPart->relaDyn->addAddendOnlyRelocIfNonPreemptible(
+          target->tlsDescRel, *got, got->getTlsDescOffset(sym), sym,
+          target->tlsDescRel);
+    }
+    if (flags & NEEDS_TLSGD) {
+      got->addDynTlsEntry(sym);
+      uint64_t off = got->getGlobalDynOffset(sym);
+      if (isLocalInExecutable)
+        // Write one to the GOT slot.
+        got->addConstant({R_ADDEND, target->symbolicRel, off, 1, &sym});
+      else
+        mainPart->relaDyn->addSymbolReloc(target->tlsModuleIndexRel, *got, off,
+                                          sym);
+
+      // If the symbol is preemptible we need the dynamic linker to write
+      // the offset too.
+      uint64_t offsetOff = off + config->wordsize;
+      if (sym.isPreemptible)
+        mainPart->relaDyn->addSymbolReloc(target->tlsOffsetRel, *got, offsetOff,
+                                          sym);
+      else
+        got->addConstant({R_ABS, target->tlsOffsetRel, offsetOff, 0, &sym});
+    }
+    if (flags & NEEDS_TLSGD_TO_IE) {
+      got->addEntry(sym);
+      mainPart->relaDyn->addSymbolReloc(target->tlsGotRel, *got,
+                                        sym.getGotOffset(), sym);
+    }
+    if (flags & NEEDS_GOT_DTPREL) {
+      got->addEntry(sym);
+      got->addConstant(
+          {R_ABS, target->tlsOffsetRel, sym.getGotOffset(), 0, &sym});
+    }
+
+    if ((flags & NEEDS_TLSIE) && !(flags & NEEDS_TLSGD_TO_IE))
+      addTpOffsetGotEntry(sym);
+  };
+
+  GotSection *got = in.got.get();
+  if (ctx.needsTlsLd.load(std::memory_order_relaxed) && got->addTlsIndex()) {
+    static Undefined dummy(nullptr, "", STB_LOCAL, 0, 0);
+    if (config->shared)
+      mainPart->relaDyn->addReloc(
+          {target->tlsModuleIndexRel, got, got->getTlsIndexOff()});
+    else
+      got->addConstant(
+          {R_ADDEND, target->symbolicRel, got->getTlsIndexOff(), 1, &dummy});
+  }
+
+  assert(symAux.size() == 1);
+  for (Symbol *sym : symtab.getSymbols())
+    fn(*sym);
+
+  // Local symbols may need the aforementioned non-preemptible ifunc and GOT
+  // handling. They don't need regular PLT.
+  for (ELFFileBase *file : ctx.objectFiles)
+    for (Symbol *sym : file->getLocalSymbols())
+      fn(*sym);
 }
 
 static bool mergeCmp(const InputSection *a, const InputSection *b) {
@@ -1639,7 +1752,8 @@ static bool mergeCmp(const InputSection *a, const InputSection *b) {
   if (a->outSecOff < b->outSecOff)
     return true;
 
-  if (a->outSecOff == b->outSecOff) {
+  // FIXME dyn_cast<ThunkSection> is non-null for any SyntheticSection.
+  if (a->outSecOff == b->outSecOff && a != b) {
     auto *ta = dyn_cast<ThunkSection>(a);
     auto *tb = dyn_cast<ThunkSection>(b);
 
@@ -1665,7 +1779,7 @@ static void forEachInputSectionDescription(
   for (OutputSection *os : outputSections) {
     if (!(os->flags & SHF_ALLOC) || !(os->flags & SHF_EXECINSTR))
       continue;
-    for (BaseCommand *bc : os->sectionCommands)
+    for (SectionCommand *bc : os->commands)
       if (auto *isd = dyn_cast<InputSectionDescription>(bc))
         fn(os, isd);
   }
@@ -1787,7 +1901,7 @@ void ThunkCreator::mergeThunks(ArrayRef<OutputSection *> outputSections) {
                           });
 
         // Merge sorted vectors of Thunks and InputSections by outSecOff
-        std::vector<InputSection *> tmp;
+        SmallVector<InputSection *, 0> tmp;
         tmp.reserve(isd->sections.size() + newThunks.size());
 
         std::merge(isd->sections.begin(), isd->sections.end(),
@@ -1798,6 +1912,19 @@ void ThunkCreator::mergeThunks(ArrayRef<OutputSection *> outputSections) {
       });
 }
 
+static int64_t getPCBias(RelType type) {
+  if (config->emachine != EM_ARM)
+    return 0;
+  switch (type) {
+  case R_ARM_THM_JUMP19:
+  case R_ARM_THM_JUMP24:
+  case R_ARM_THM_CALL:
+    return 4;
+  default:
+    return 8;
+  }
+}
+
 // Find or create a ThunkSection within the InputSectionDescription (ISD) that
 // is in range of Src. An ISD maps to a range of InputSections described by a
 // linker script section pattern such as { .text .text.* }.
@@ -1806,10 +1933,12 @@ ThunkSection *ThunkCreator::getISDThunkSec(OutputSection *os,
                                            InputSectionDescription *isd,
                                            const Relocation &rel,
                                            uint64_t src) {
+  // See the comment in getThunk for -pcBias below.
+  const int64_t pcBias = getPCBias(rel.type);
   for (std::pair<ThunkSection *, uint32_t> tp : isd->thunkSections) {
     ThunkSection *ts = tp.first;
-    uint64_t tsBase = os->addr + ts->outSecOff + rel.addend;
-    uint64_t tsLimit = tsBase + ts->getSize() + rel.addend;
+    uint64_t tsBase = os->addr + ts->outSecOff - pcBias;
+    uint64_t tsLimit = tsBase + ts->getSize();
     if (target->inBranchRange(rel.type, src,
                               (src > tsLimit) ? tsBase : tsLimit))
       return ts;
@@ -1842,7 +1971,7 @@ ThunkSection *ThunkCreator::getISThunkSec(InputSection *isec) {
   // Find InputSectionRange within Target Output Section (TOS) that the
   // InputSection (IS) that we need to precede is in.
   OutputSection *tos = isec->getParent();
-  for (BaseCommand *bc : tos->sectionCommands) {
+  for (SectionCommand *bc : tos->commands) {
     auto *isd = dyn_cast<InputSectionDescription>(bc);
     if (!isd || isd->sections.empty())
       continue;
@@ -1960,19 +2089,6 @@ static bool isThunkSectionCompatible(InputSection *source,
   return true;
 }
 
-static int64_t getPCBias(RelType type) {
-  if (config->emachine != EM_ARM)
-    return 0;
-  switch (type) {
-  case R_ARM_THM_JUMP19:
-  case R_ARM_THM_JUMP24:
-  case R_ARM_THM_CALL:
-    return 4;
-  default:
-    return 8;
-  }
-}
-
 std::pair<Thunk *, bool> ThunkCreator::getThunk(InputSection *isec,
                                                 Relocation &rel, uint64_t src) {
   std::vector<Thunk *> *thunkVec = nullptr;
@@ -1980,7 +2096,8 @@ std::pair<Thunk *, bool> ThunkCreator::getThunk(InputSection *isec,
   // out in the relocation addend. We compensate for the PC bias so that
   // an Arm and Thumb relocation to the same destination get the same keyAddend,
   // which is usually 0.
-  int64_t keyAddend = rel.addend + getPCBias(rel.type);
+  const int64_t pcBias = getPCBias(rel.type);
+  const int64_t keyAddend = rel.addend + pcBias;
 
   // We use a ((section, offset), addend) pair to find the thunk position if
   // possible so that we create only one thunk for aliased symbols or ICFed
@@ -1989,8 +2106,8 @@ std::pair<Thunk *, bool> ThunkCreator::getThunk(InputSection *isec,
   // non-Thunk target, so we cannot fold offset + addend.
   if (auto *d = dyn_cast<Defined>(rel.sym))
     if (!d->isInPlt() && d->section)
-      thunkVec = &thunkedSymbolsBySectionAndAddend[{
-          {d->section->repl, d->value}, keyAddend}];
+      thunkVec = &thunkedSymbolsBySectionAndAddend[{{d->section, d->value},
+                                                    keyAddend}];
   if (!thunkVec)
     thunkVec = &thunkedSymbols[{rel.sym, keyAddend}];
 
@@ -1999,7 +2116,7 @@ std::pair<Thunk *, bool> ThunkCreator::getThunk(InputSection *isec,
     if (isThunkSectionCompatible(isec, t->getThunkTargetSym()->section) &&
         t->isCompatibleWith(*isec, rel) &&
         target->inBranchRange(rel.type, src,
-                              t->getThunkTargetSym()->getVA(rel.addend)))
+                              t->getThunkTargetSym()->getVA(-pcBias)))
       return std::make_pair(t, false);
 
   // No existing compatible Thunk in range, create a new one
@@ -2049,7 +2166,9 @@ bool ThunkCreator::normalizeExistingThunk(Relocation &rel, uint64_t src) {
 // made no changes. If the target requires range extension thunks, currently
 // ARM, then any future change in offset between caller and callee risks a
 // relocation out of range error.
-bool ThunkCreator::createThunks(ArrayRef<OutputSection *> outputSections) {
+bool ThunkCreator::createThunks(uint32_t pass,
+                                ArrayRef<OutputSection *> outputSections) {
+  this->pass = pass;
   bool addressesChanged = false;
 
   if (pass == 0 && target->getThunkSectionSpacing())
@@ -2063,7 +2182,7 @@ bool ThunkCreator::createThunks(ArrayRef<OutputSection *> outputSections) {
   forEachInputSectionDescription(
       outputSections, [&](OutputSection *os, InputSectionDescription *isd) {
         for (InputSection *isec : isd->sections)
-          for (Relocation &rel : isec->relocations) {
+          for (Relocation &rel : isec->relocs()) {
             uint64_t src = isec->getVA(rel.offset);
 
             // If we are a relocation to an existing Thunk, check if it is
@@ -2111,7 +2230,6 @@ bool ThunkCreator::createThunks(ArrayRef<OutputSection *> outputSections) {
 
   // Merge all created synthetic ThunkSections back into OutputSection
   mergeThunks(outputSections);
-  ++pass;
   return addressesChanged;
 }
 
@@ -2124,7 +2242,7 @@ bool elf::hexagonNeedsTLSSymbol(ArrayRef<OutputSection *> outputSections) {
   forEachInputSectionDescription(
       outputSections, [&](OutputSection *os, InputSectionDescription *isd) {
         for (InputSection *isec : isd->sections)
-          for (Relocation &rel : isec->relocations)
+          for (Relocation &rel : isec->relocs())
             if (rel.sym->type == llvm::ELF::STT_TLS && rel.expr == R_PLT_PC) {
               needTlsSymbol = true;
               return;
@@ -2134,17 +2252,18 @@ bool elf::hexagonNeedsTLSSymbol(ArrayRef<OutputSection *> outputSections) {
 }
 
 void elf::hexagonTLSSymbolUpdate(ArrayRef<OutputSection *> outputSections) {
-  Symbol *sym = symtab->find("__tls_get_addr");
+  Symbol *sym = symtab.find("__tls_get_addr");
   if (!sym)
     return;
   bool needEntry = true;
   forEachInputSectionDescription(
       outputSections, [&](OutputSection *os, InputSectionDescription *isd) {
         for (InputSection *isec : isd->sections)
-          for (Relocation &rel : isec->relocations)
+          for (Relocation &rel : isec->relocs())
             if (rel.sym->type == llvm::ELF::STT_TLS && rel.expr == R_PLT_PC) {
               if (needEntry) {
-                addPltEntry(in.plt, in.gotPlt, in.relaPlt, target->pltRel,
+                sym->allocateAux();
+                addPltEntry(*in.plt, *in.gotPlt, *in.relaPlt, target->pltRel,
                             *sym);
                 needEntry = false;
               }
@@ -2153,11 +2272,7 @@ void elf::hexagonTLSSymbolUpdate(ArrayRef<OutputSection *> outputSections) {
       });
 }
 
-template void elf::scanRelocations<ELF32LE>(InputSectionBase &);
-template void elf::scanRelocations<ELF32BE>(InputSectionBase &);
-template void elf::scanRelocations<ELF64LE>(InputSectionBase &);
-template void elf::scanRelocations<ELF64BE>(InputSectionBase &);
-template void elf::reportUndefinedSymbols<ELF32LE>();
-template void elf::reportUndefinedSymbols<ELF32BE>();
-template void elf::reportUndefinedSymbols<ELF64LE>();
-template void elf::reportUndefinedSymbols<ELF64BE>();
+template void elf::scanRelocations<ELF32LE>();
+template void elf::scanRelocations<ELF32BE>();
+template void elf::scanRelocations<ELF64LE>();
+template void elf::scanRelocations<ELF64BE>();
index a9b96e3..7e706f1 100644 (file)
 #include "ScriptParser.h"
 #include "Config.h"
 #include "Driver.h"
-#include "InputSection.h"
+#include "InputFiles.h"
 #include "LinkerScript.h"
 #include "OutputSections.h"
 #include "ScriptLexer.h"
+#include "SymbolTable.h"
 #include "Symbols.h"
 #include "Target.h"
-#include "lld/Common/Memory.h"
+#include "lld/Common/CommonLinkerContext.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
@@ -31,7 +32,7 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/Path.h"
-#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/SaveAndRestore.h"
 #include "llvm/Support/TimeProfiler.h"
 #include <cassert>
 #include <limits>
@@ -91,14 +92,14 @@ private:
   std::array<uint8_t, 4> readFill();
   bool readSectionDirective(OutputSection *cmd, StringRef tok1, StringRef tok2);
   void readSectionAddressType(OutputSection *cmd);
-  OutputSection *readOverlaySectionDescription();
-  OutputSection *readOutputSectionDescription(StringRef outSec);
-  std::vector<BaseCommand *> readOverlay();
-  std::vector<StringRef> readOutputSectionPhdrs();
+  OutputDesc *readOverlaySectionDescription();
+  OutputDesc *readOutputSectionDescription(StringRef outSec);
+  SmallVector<SectionCommand *, 0> readOverlay();
+  SmallVector<StringRef, 0> readOutputSectionPhdrs();
   std::pair<uint64_t, uint64_t> readInputSectionFlags();
   InputSectionDescription *readInputSectionDescription(StringRef tok);
   StringMatcher readFilePatterns();
-  std::vector<SectionPattern> readInputSectionsList();
+  SmallVector<SectionPattern, 0> readInputSectionsList();
   InputSectionDescription *readInputSectionRules(StringRef filePattern,
                                                  uint64_t withFlags,
                                                  uint64_t withoutFlags);
@@ -113,7 +114,8 @@ private:
   Expr getPageSize();
 
   Expr readMemoryAssignment(StringRef, StringRef, StringRef);
-  std::pair<uint32_t, uint32_t> readMemoryAttributes();
+  void readMemoryAttributes(uint32_t &flags, uint32_t &invFlags,
+                            uint32_t &negFlags, uint32_t &negInvFlags);
 
   Expr combine(StringRef op, Expr l, Expr r);
   Expr readExpr();
@@ -124,16 +126,19 @@ private:
   Expr readParenExpr();
 
   // For parsing version script.
-  std::vector<SymbolVersion> readVersionExtern();
+  SmallVector<SymbolVersion, 0> readVersionExtern();
   void readAnonymousDeclaration();
   void readVersionDeclaration(StringRef verStr);
 
-  std::pair<std::vector<SymbolVersion>, std::vector<SymbolVersion>>
+  std::pair<SmallVector<SymbolVersion, 0>, SmallVector<SymbolVersion, 0>>
   readSymbols();
 
-  // True if a script being read is in a subdirectory specified by -sysroot.
+  // True if a script being read is in the --sysroot directory.
   bool isUnderSysroot = false;
 
+  bool seenDataAlign = false;
+  bool seenRelroEnd = false;
+
   // A set to detect an INCLUDE() cycle.
   StringSet<> seen;
 };
@@ -180,8 +185,8 @@ static ExprValue bitOr(ExprValue a, ExprValue b) {
 
 void ScriptParser::readDynamicList() {
   expect("{");
-  std::vector<SymbolVersion> locals;
-  std::vector<SymbolVersion> globals;
+  SmallVector<SymbolVersion, 0> locals;
+  SmallVector<SymbolVersion, 0> globals;
   std::tie(locals, globals) = readSymbols();
   expect(";");
 
@@ -289,7 +294,7 @@ void ScriptParser::addFile(StringRef s) {
     SmallString<128> pathData;
     StringRef path = (config->sysroot + s).toStringRef(pathData);
     if (sys::fs::exists(path))
-      driver->addFile(saver.save(path), /*withLOption=*/false);
+      ctx.driver.addFile(saver().save(path), /*withLOption=*/false);
     else
       setError("cannot find " + s + " inside " + config->sysroot);
     return;
@@ -297,17 +302,17 @@ void ScriptParser::addFile(StringRef s) {
 
   if (s.startswith("/")) {
     // Case 1: s is an absolute path. Just open it.
-    driver->addFile(s, /*withLOption=*/false);
+    ctx.driver.addFile(s, /*withLOption=*/false);
   } else if (s.startswith("=")) {
     // Case 2: relative to the sysroot.
     if (config->sysroot.empty())
-      driver->addFile(s.substr(1), /*withLOption=*/false);
+      ctx.driver.addFile(s.substr(1), /*withLOption=*/false);
     else
-      driver->addFile(saver.save(config->sysroot + "/" + s.substr(1)),
-                      /*withLOption=*/false);
+      ctx.driver.addFile(saver().save(config->sysroot + "/" + s.substr(1)),
+                         /*withLOption=*/false);
   } else if (s.startswith("-l")) {
     // Case 3: search in the list of library paths.
-    driver->addLibrary(s.substr(2));
+    ctx.driver.addLibrary(s.substr(2));
   } else {
     // Case 4: s is a relative path. Search in the directory of the script file.
     std::string filename = std::string(getCurrentMB().getBufferIdentifier());
@@ -316,17 +321,17 @@ void ScriptParser::addFile(StringRef s) {
       SmallString<0> path(directory);
       sys::path::append(path, s);
       if (sys::fs::exists(path)) {
-        driver->addFile(path, /*withLOption=*/false);
+        ctx.driver.addFile(path, /*withLOption=*/false);
         return;
       }
     }
     // Then search in the current working directory.
     if (sys::fs::exists(s)) {
-      driver->addFile(s, /*withLOption=*/false);
+      ctx.driver.addFile(s, /*withLOption=*/false);
     } else {
       // Finally, search in the list of library paths.
-      if (Optional<std::string> path = findFromSearchPaths(s))
-        driver->addFile(saver.save(*path), /*withLOption=*/true);
+      if (std::optional<std::string> path = findFromSearchPaths(s))
+        ctx.driver.addFile(saver().save(*path), /*withLOption=*/true);
       else
         setError("unable to find " + s);
     }
@@ -347,7 +352,7 @@ void ScriptParser::readEntry() {
   expect("(");
   StringRef tok = next();
   if (config->entry.empty())
-    config->entry = tok;
+    config->entry = unquote(tok);
   expect(")");
 }
 
@@ -374,8 +379,8 @@ void ScriptParser::readInclude() {
     return;
   }
 
-  if (Optional<std::string> path = searchScript(tok)) {
-    if (Optional<MemoryBufferRef> mb = readFile(*path))
+  if (std::optional<std::string> path = searchScript(tok)) {
+    if (std::optional<MemoryBufferRef> mb = readFile(*path))
       tokenize(*mb);
     return;
   }
@@ -411,6 +416,7 @@ void ScriptParser::readOutputArch() {
 static std::pair<ELFKind, uint16_t> parseBfdName(StringRef s) {
   return StringSwitch<std::pair<ELFKind, uint16_t>>(s)
       .Case("elf32-i386", {ELF32LEKind, EM_386})
+      .Case("elf32-avr", {ELF32LEKind, EM_AVR})
       .Case("elf32-iamcu", {ELF32LEKind, EM_IAMCU})
       .Case("elf32-littlearm", {ELF32LEKind, EM_ARM})
       .Case("elf32-x86-64", {ELF32LEKind, EM_X86_64})
@@ -518,7 +524,7 @@ void ScriptParser::readSearchDir() {
 // sections that use the same virtual memory range and normally would trigger
 // linker's sections sanity check failures.
 // https://sourceware.org/binutils/docs/ld/Overlay-Description.html#Overlay-Description
-std::vector<BaseCommand *> ScriptParser::readOverlay() {
+SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
   // VA and LMA expressions are optional, though for simplicity of
   // implementation we assume they are not. That is what OVERLAY was designed
   // for first of all: to allow sections with overlapping VAs at different LMAs.
@@ -528,19 +534,19 @@ std::vector<BaseCommand *> ScriptParser::readOverlay() {
   Expr lmaExpr = readParenExpr();
   expect("{");
 
-  std::vector<BaseCommand *> v;
+  SmallVector<SectionCommand *, 0> v;
   OutputSection *prev = nullptr;
   while (!errorCount() && !consume("}")) {
     // VA is the same for all sections. The LMAs are consecutive in memory
     // starting from the base load address specified.
-    OutputSection *os = readOverlaySectionDescription();
-    os->addrExpr = addrExpr;
+    OutputDesc *osd = readOverlaySectionDescription();
+    osd->osec.addrExpr = addrExpr;
     if (prev)
-      os->lmaExpr = [=] { return prev->getLMA() + prev->size; };
+      osd->osec.lmaExpr = [=] { return prev->getLMA() + prev->size; };
     else
-      os->lmaExpr = lmaExpr;
-    v.push_back(os);
-    prev = os;
+      osd->osec.lmaExpr = lmaExpr;
+    v.push_back(osd);
+    prev = &osd->osec;
   }
 
   // According to the specification, at the end of the overlay, the location
@@ -549,8 +555,8 @@ std::vector<BaseCommand *> ScriptParser::readOverlay() {
   // Here we want to create the Dot assignment command to achieve that.
   Expr moveDot = [=] {
     uint64_t max = 0;
-    for (BaseCommand *cmd : v)
-      max = std::max(max, cast<OutputSection>(cmd)->size);
+    for (SectionCommand *cmd : v)
+      max = std::max(max, cast<OutputDesc>(cmd)->osec.size);
     return addrExpr().getValue() + max;
   };
   v.push_back(make<SymbolAssignment>(".", moveDot, getCurrentLocation()));
@@ -565,11 +571,11 @@ void ScriptParser::readOverwriteSections() {
 
 void ScriptParser::readSections() {
   expect("{");
-  std::vector<BaseCommand *> v;
+  SmallVector<SectionCommand *, 0> v;
   while (!errorCount() && !consume("}")) {
     StringRef tok = next();
     if (tok == "OVERLAY") {
-      for (BaseCommand *cmd : readOverlay())
+      for (SectionCommand *cmd : readOverlay())
         v.push_back(cmd);
       continue;
     } else if (tok == "INCLUDE") {
@@ -577,11 +583,19 @@ void ScriptParser::readSections() {
       continue;
     }
 
-    if (BaseCommand *cmd = readAssignment(tok))
+    if (SectionCommand *cmd = readAssignment(tok))
       v.push_back(cmd);
     else
       v.push_back(readOutputSectionDescription(tok));
   }
+
+  // If DATA_SEGMENT_RELRO_END is absent, for sections after DATA_SEGMENT_ALIGN,
+  // the relro fields should be cleared.
+  if (!seenRelroEnd)
+    for (SectionCommand *cmd : v)
+      if (auto *osd = dyn_cast<OutputDesc>(cmd))
+        osd->osec.relro = false;
+
   script->sectionCommands.insert(script->sectionCommands.end(), v.begin(),
                                  v.end());
 
@@ -596,10 +610,10 @@ void ScriptParser::readSections() {
   else if (!consume("BEFORE"))
     setError("expected AFTER/BEFORE, but got '" + next() + "'");
   StringRef where = next();
-  std::vector<StringRef> names;
-  for (BaseCommand *cmd : v)
-    if (auto *os = dyn_cast<OutputSection>(cmd))
-      names.push_back(os->name);
+  SmallVector<StringRef, 0> names;
+  for (SectionCommand *cmd : v)
+    if (auto *os = dyn_cast<OutputDesc>(cmd))
+      names.push_back(os->osec.name);
   if (!names.empty())
     script->insertCommands.push_back({std::move(names), isAfter, where});
 }
@@ -610,7 +624,7 @@ void ScriptParser::readTarget() {
   // for --format. We recognize only /^elf/ and "binary" in the linker
   // script as well.
   expect("(");
-  StringRef tok = next();
+  StringRef tok = unquote(next());
   expect(")");
 
   if (tok.startswith("elf"))
@@ -623,14 +637,16 @@ void ScriptParser::readTarget() {
 
 static int precedence(StringRef op) {
   return StringSwitch<int>(op)
-      .Cases("*", "/", "%", 8)
-      .Cases("+", "-", 7)
-      .Cases("<<", ">>", 6)
-      .Cases("<", "<=", ">", ">=", "==", "!=", 5)
-      .Case("&", 4)
-      .Case("|", 3)
-      .Case("&&", 2)
-      .Case("||", 1)
+      .Cases("*", "/", "%", 10)
+      .Cases("+", "-", 9)
+      .Cases("<<", ">>", 8)
+      .Cases("<", "<=", ">", ">=", 7)
+      .Cases("==", "!=", 6)
+      .Case("&", 5)
+      .Case("|", 4)
+      .Case("&&", 3)
+      .Case("||", 2)
+      .Case("?", 1)
       .Default(-1);
 }
 
@@ -671,8 +687,8 @@ SortSectionPolicy ScriptParser::readSortKind() {
 // is parsed as ".foo", ".bar" with "a.o", and ".baz" with "b.o".
 // The semantics of that is section .foo in any file, section .bar in
 // any file but a.o, and section .baz in any file but b.o.
-std::vector<SectionPattern> ScriptParser::readInputSectionsList() {
-  std::vector<SectionPattern> ret;
+SmallVector<SectionPattern, 0> ScriptParser::readInputSectionsList() {
+  SmallVector<SectionPattern, 0> ret;
   while (!errorCount() && peek() != ")") {
     StringMatcher excludeFilePat;
     if (consume("EXCLUDE_FILE")) {
@@ -717,7 +733,7 @@ ScriptParser::readInputSectionRules(StringRef filePattern, uint64_t withFlags,
   while (!errorCount() && !consume(")")) {
     SortSectionPolicy outer = readSortKind();
     SortSectionPolicy inner = SortSectionPolicy::Default;
-    std::vector<SectionPattern> v;
+    SmallVector<SectionPattern, 0> v;
     if (outer != SortSectionPolicy::Default) {
       expect("(");
       inner = readSortKind();
@@ -786,19 +802,45 @@ Expr ScriptParser::readAssert() {
   };
 }
 
+#define ECase(X)                                                               \
+  { #X, X }
+constexpr std::pair<const char *, unsigned> typeMap[] = {
+    ECase(SHT_PROGBITS),   ECase(SHT_NOTE),       ECase(SHT_NOBITS),
+    ECase(SHT_INIT_ARRAY), ECase(SHT_FINI_ARRAY), ECase(SHT_PREINIT_ARRAY),
+};
+#undef ECase
+
 // Tries to read the special directive for an output section definition which
-// can be one of following: "(NOLOAD)", "(COPY)", "(INFO)" or "(OVERLAY)".
-// Tok1 and Tok2 are next 2 tokens peeked. See comment for readSectionAddressType below.
+// can be one of following: "(NOLOAD)", "(COPY)", "(INFO)", "(OVERLAY)", and
+// "(TYPE=<value>)".
+// Tok1 and Tok2 are next 2 tokens peeked. See comment for
+// readSectionAddressType below.
 bool ScriptParser::readSectionDirective(OutputSection *cmd, StringRef tok1, StringRef tok2) {
   if (tok1 != "(")
     return false;
-  if (tok2 != "NOLOAD" && tok2 != "COPY" && tok2 != "INFO" && tok2 != "OVERLAY")
+  if (tok2 != "NOLOAD" && tok2 != "COPY" && tok2 != "INFO" &&
+      tok2 != "OVERLAY" && tok2 != "TYPE")
     return false;
 
   expect("(");
   if (consume("NOLOAD")) {
-    cmd->noload = true;
     cmd->type = SHT_NOBITS;
+    cmd->typeIsSet = true;
+  } else if (consume("TYPE")) {
+    expect("=");
+    StringRef value = peek();
+    auto it = llvm::find_if(typeMap, [=](auto e) { return e.first == value; });
+    if (it != std::end(typeMap)) {
+      // The value is a recognized literal SHT_*.
+      cmd->type = it->second;
+      skip();
+    } else if (value.startswith("SHT_")) {
+      setError("unknown section type " + value);
+    } else {
+      // Otherwise, read an expression.
+      cmd->type = readExpr()().getValue();
+    }
+    cmd->typeIsSet = true;
   } else {
     skip(); // This is "COPY", "INFO" or "OVERLAY".
     cmd->nonAlloc = true;
@@ -819,7 +861,11 @@ bool ScriptParser::readSectionDirective(OutputSection *cmd, StringRef tok1, Stri
 // https://sourceware.org/binutils/docs/ld/Output-Section-Address.html
 // https://sourceware.org/binutils/docs/ld/Output-Section-Type.html
 void ScriptParser::readSectionAddressType(OutputSection *cmd) {
-  if (readSectionDirective(cmd, peek(), peek2()))
+  // Temporarily set inExpr to support TYPE=<value> without spaces.
+  bool saved = std::exchange(inExpr, true);
+  bool isDirective = readSectionDirective(cmd, peek(), peek2());
+  inExpr = saved;
+  if (isDirective)
     return;
 
   cmd->addrExpr = readExpr();
@@ -838,45 +884,46 @@ static Expr checkAlignment(Expr e, std::string &loc) {
   };
 }
 
-OutputSection *ScriptParser::readOverlaySectionDescription() {
-  OutputSection *cmd =
-      script->createOutputSection(next(), getCurrentLocation());
-  cmd->inOverlay = true;
+OutputDesc *ScriptParser::readOverlaySectionDescription() {
+  OutputDesc *osd = script->createOutputSection(next(), getCurrentLocation());
+  osd->osec.inOverlay = true;
   expect("{");
   while (!errorCount() && !consume("}")) {
     uint64_t withFlags = 0;
     uint64_t withoutFlags = 0;
     if (consume("INPUT_SECTION_FLAGS"))
       std::tie(withFlags, withoutFlags) = readInputSectionFlags();
-    cmd->sectionCommands.push_back(
+    osd->osec.commands.push_back(
         readInputSectionRules(next(), withFlags, withoutFlags));
   }
-  return cmd;
+  return osd;
 }
 
-OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
-  OutputSection *cmd =
-      script->createOutputSection(outSec, getCurrentLocation());
+OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
+  OutputDesc *cmd = script->createOutputSection(outSec, getCurrentLocation());
+  OutputSection *osec = &cmd->osec;
+  // Maybe relro. Will reset to false if DATA_SEGMENT_RELRO_END is absent.
+  osec->relro = seenDataAlign && !seenRelroEnd;
 
   size_t symbolsReferenced = script->referencedSymbols.size();
 
   if (peek() != ":")
-    readSectionAddressType(cmd);
+    readSectionAddressType(osec);
   expect(":");
 
   std::string location = getCurrentLocation();
   if (consume("AT"))
-    cmd->lmaExpr = readParenExpr();
+    osec->lmaExpr = readParenExpr();
   if (consume("ALIGN"))
-    cmd->alignExpr = checkAlignment(readParenExpr(), location);
+    osec->alignExpr = checkAlignment(readParenExpr(), location);
   if (consume("SUBALIGN"))
-    cmd->subalignExpr = checkAlignment(readParenExpr(), location);
+    osec->subalignExpr = checkAlignment(readParenExpr(), location);
 
   // Parse constraints.
   if (consume("ONLY_IF_RO"))
-    cmd->constraint = ConstraintKind::ReadOnly;
+    osec->constraint = ConstraintKind::ReadOnly;
   if (consume("ONLY_IF_RW"))
-    cmd->constraint = ConstraintKind::ReadWrite;
+    osec->constraint = ConstraintKind::ReadWrite;
   expect("{");
 
   while (!errorCount() && !consume("}")) {
@@ -884,9 +931,9 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
     if (tok == ";") {
       // Empty commands are allowed. Do nothing here.
     } else if (SymbolAssignment *assign = readAssignment(tok)) {
-      cmd->sectionCommands.push_back(assign);
+      osec->commands.push_back(assign);
     } else if (ByteCommand *data = readByteCommand(tok)) {
-      cmd->sectionCommands.push_back(data);
+      osec->commands.push_back(data);
     } else if (tok == "CONSTRUCTORS") {
       // CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors
       // by name. This is for very old file formats such as ECOFF/XCOFF.
@@ -897,13 +944,15 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
       // https://sourceware.org/binutils/docs/ld/Output-Section-Data.html
       if (peek() != "(")
         setError("( expected, but got " + peek());
-      cmd->filler = readFill();
+      osec->filler = readFill();
     } else if (tok == "SORT") {
       readSort();
     } else if (tok == "INCLUDE") {
       readInclude();
+    } else if (tok == "(" || tok == ")") {
+      setError("expected filename pattern");
     } else if (peek() == "(") {
-      cmd->sectionCommands.push_back(readInputSectionDescription(tok));
+      osec->commands.push_back(readInputSectionDescription(tok));
     } else {
       // We have a file name and no input sections description. It is not a
       // commonly used syntax, but still acceptable. In that case, all sections
@@ -913,27 +962,27 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
       // case above.
       auto *isd = make<InputSectionDescription>(tok);
       isd->sectionPatterns.push_back({{}, StringMatcher("*")});
-      cmd->sectionCommands.push_back(isd);
+      osec->commands.push_back(isd);
     }
   }
 
   if (consume(">"))
-    cmd->memoryRegionName = std::string(next());
+    osec->memoryRegionName = std::string(next());
 
   if (consume("AT")) {
     expect(">");
-    cmd->lmaRegionName = std::string(next());
+    osec->lmaRegionName = std::string(next());
   }
 
-  if (cmd->lmaExpr && !cmd->lmaRegionName.empty())
+  if (osec->lmaExpr && !osec->lmaRegionName.empty())
     error("section can't have both LMA and a load region");
 
-  cmd->phdrs = readOutputSectionPhdrs();
+  osec->phdrs = readOutputSectionPhdrs();
 
   if (peek() == "=" || peek().startswith("=")) {
     inExpr = true;
     consume("=");
-    cmd->filler = readFill();
+    osec->filler = readFill();
     inExpr = false;
   }
 
@@ -941,7 +990,7 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
   consume(",");
 
   if (script->referencedSymbols.size() > symbolsReferenced)
-    cmd->expressionsUseSymbols = true;
+    osec->expressionsUseSymbols = true;
   return cmd;
 }
 
@@ -968,7 +1017,14 @@ std::array<uint8_t, 4> ScriptParser::readFill() {
 
 SymbolAssignment *ScriptParser::readProvideHidden(bool provide, bool hidden) {
   expect("(");
-  SymbolAssignment *cmd = readSymbolAssignment(next());
+  StringRef name = next(), eq = peek();
+  if (eq != "=") {
+    setError("= expected, but got " + next());
+    while (!atEOF() && next() != ")")
+      ;
+    return nullptr;
+  }
+  SymbolAssignment *cmd = readSymbolAssignment(name);
   cmd->provide = provide;
   cmd->hidden = hidden;
   expect(")");
@@ -982,14 +1038,24 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef tok) {
 
   size_t oldPos = pos;
   SymbolAssignment *cmd = nullptr;
-  if (peek() == "=" || peek() == "+=")
+  const StringRef op = peek();
+  if (op.startswith("=")) {
+    // Support = followed by an expression without whitespace.
+    SaveAndRestore saved(inExpr, true);
+    cmd = readSymbolAssignment(tok);
+  } else if ((op.size() == 2 && op[1] == '=' && strchr("*/+-&|", op[0])) ||
+             op == "<<=" || op == ">>=") {
     cmd = readSymbolAssignment(tok);
-  else if (tok == "PROVIDE")
+  } else if (tok == "PROVIDE") {
+    SaveAndRestore saved(inExpr, true);
     cmd = readProvideHidden(true, false);
-  else if (tok == "HIDDEN")
+  } else if (tok == "HIDDEN") {
+    SaveAndRestore saved(inExpr, true);
     cmd = readProvideHidden(false, true);
-  else if (tok == "PROVIDE_HIDDEN")
+  } else if (tok == "PROVIDE_HIDDEN") {
+    SaveAndRestore saved(inExpr, true);
     cmd = readProvideHidden(true, true);
+  }
 
   if (cmd) {
     cmd->commandString =
@@ -1003,11 +1069,38 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef tok) {
 SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) {
   name = unquote(name);
   StringRef op = next();
-  assert(op == "=" || op == "+=");
+  assert(op == "=" || op == "*=" || op == "/=" || op == "+=" || op == "-=" ||
+         op == "&=" || op == "|=" || op == "<<=" || op == ">>=");
+  // Note: GNU ld does not support %= or ^=.
   Expr e = readExpr();
-  if (op == "+=") {
+  if (op != "=") {
     std::string loc = getCurrentLocation();
-    e = [=] { return add(script->getSymbolValue(name, loc), e()); };
+    e = [=, c = op[0]]() -> ExprValue {
+      ExprValue lhs = script->getSymbolValue(name, loc);
+      switch (c) {
+      case '*':
+        return lhs.getValue() * e().getValue();
+      case '/':
+        if (uint64_t rv = e().getValue())
+          return lhs.getValue() / rv;
+        error(loc + ": division by zero");
+        return 0;
+      case '+':
+        return add(lhs, e());
+      case '-':
+        return sub(lhs, e());
+      case '<':
+        return lhs.getValue() << e().getValue();
+      case '>':
+        return lhs.getValue() >> e().getValue();
+      case '&':
+        return lhs.getValue() & e().getValue();
+      case '|':
+        return lhs.getValue() | e().getValue();
+      default:
+        llvm_unreachable("");
+      }
+    };
   }
   return make<SymbolAssignment>(name, e, getCurrentLocation());
 }
@@ -1081,11 +1174,11 @@ Expr ScriptParser::combine(StringRef op, Expr l, Expr r) {
 Expr ScriptParser::readExpr1(Expr lhs, int minPrec) {
   while (!atEOF() && !errorCount()) {
     // Read an operator and an expression.
-    if (consume("?"))
-      return readTernary(lhs);
     StringRef op1 = peek();
     if (precedence(op1) < minPrec)
       break;
+    if (consume("?"))
+      return readTernary(lhs);
     skip();
     Expr rhs = readPrimary();
 
@@ -1128,33 +1221,33 @@ Expr ScriptParser::readConstant() {
 // Parses Tok as an integer. It recognizes hexadecimal (prefixed with
 // "0x" or suffixed with "H") and decimal numbers. Decimal numbers may
 // have "K" (Ki) or "M" (Mi) suffixes.
-static Optional<uint64_t> parseInt(StringRef tok) {
+static std::optional<uint64_t> parseInt(StringRef tok) {
   // Hexadecimal
   uint64_t val;
   if (tok.startswith_insensitive("0x")) {
     if (!to_integer(tok.substr(2), val, 16))
-      return None;
+      return std::nullopt;
     return val;
   }
   if (tok.endswith_insensitive("H")) {
     if (!to_integer(tok.drop_back(), val, 16))
-      return None;
+      return std::nullopt;
     return val;
   }
 
   // Decimal
   if (tok.endswith_insensitive("K")) {
     if (!to_integer(tok.drop_back(), val, 10))
-      return None;
+      return std::nullopt;
     return val * 1024;
   }
   if (tok.endswith_insensitive("M")) {
     if (!to_integer(tok.drop_back(), val, 10))
-      return None;
+      return std::nullopt;
     return val * 1024 * 1024;
   }
   if (!to_integer(tok, val, 10))
-    return None;
+    return std::nullopt;
   return val;
 }
 
@@ -1176,11 +1269,11 @@ ByteCommand *ScriptParser::readByteCommand(StringRef tok) {
   return make<ByteCommand>(e, size, commandString);
 }
 
-static llvm::Optional<uint64_t> parseFlag(StringRef tok) {
-  if (llvm::Optional<uint64_t> asInt = parseInt(tok))
+static std::optional<uint64_t> parseFlag(StringRef tok) {
+  if (std::optional<uint64_t> asInt = parseInt(tok))
     return asInt;
 #define CASE_ENT(enum) #enum, ELF::enum
-  return StringSwitch<llvm::Optional<uint64_t>>(tok)
+  return StringSwitch<std::optional<uint64_t>>(tok)
       .Case(CASE_ENT(SHF_WRITE))
       .Case(CASE_ENT(SHF_ALLOC))
       .Case(CASE_ENT(SHF_EXECINSTR))
@@ -1194,7 +1287,7 @@ static llvm::Optional<uint64_t> parseFlag(StringRef tok) {
       .Case(CASE_ENT(SHF_COMPRESSED))
       .Case(CASE_ENT(SHF_EXCLUDE))
       .Case(CASE_ENT(SHF_ARM_PURECODE))
-      .Default(None);
+      .Default(std::nullopt);
 #undef CASE_ENT
 }
 
@@ -1215,7 +1308,7 @@ std::pair<uint64_t, uint64_t> ScriptParser::readInputSectionFlags() {
    while (!errorCount()) {
     StringRef tok = unquote(next());
     bool without = tok.consume_front("!");
-    if (llvm::Optional<uint64_t> flag = parseFlag(tok)) {
+    if (std::optional<uint64_t> flag = parseFlag(tok)) {
       if (without)
         withoutFlags |= *flag;
       else
@@ -1243,9 +1336,9 @@ StringRef ScriptParser::readParenLiteral() {
   return tok;
 }
 
-static void checkIfExists(OutputSection *cmd, StringRef location) {
-  if (cmd->location.empty() && script->errorOnMissingSection)
-    error(location + ": undefined section " + cmd->name);
+static void checkIfExists(const OutputSection &osec, StringRef location) {
+  if (osec.location.empty() && script->errorOnMissingSection)
+    error(location + ": undefined section " + osec.name);
 }
 
 static bool isValidSymbolName(StringRef s) {
@@ -1287,11 +1380,11 @@ Expr ScriptParser::readPrimary() {
   }
   if (tok == "ADDR") {
     StringRef name = readParenLiteral();
-    OutputSection *sec = script->getOrCreateOutputSection(name);
-    sec->usedInExpression = true;
+    OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
+    osec->usedInExpression = true;
     return [=]() -> ExprValue {
-      checkIfExists(sec, location);
-      return {sec, false, 0, location};
+      checkIfExists(*osec, location);
+      return {osec, false, 0, location};
     };
   }
   if (tok == "ALIGN") {
@@ -1299,7 +1392,7 @@ Expr ScriptParser::readPrimary() {
     Expr e = readExpr();
     if (consume(")")) {
       e = checkAlignment(e, location);
-      return [=] { return alignTo(script->getDot(), e().getValue()); };
+      return [=] { return alignToPowerOf2(script->getDot(), e().getValue()); };
     }
     expect(",");
     Expr e2 = checkAlignment(readExpr(), location);
@@ -1312,10 +1405,10 @@ Expr ScriptParser::readPrimary() {
   }
   if (tok == "ALIGNOF") {
     StringRef name = readParenLiteral();
-    OutputSection *cmd = script->getOrCreateOutputSection(name);
+    OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
     return [=] {
-      checkIfExists(cmd, location);
-      return cmd->alignment;
+      checkIfExists(*osec, location);
+      return osec->addralign;
     };
   }
   if (tok == "ASSERT")
@@ -1328,8 +1421,10 @@ Expr ScriptParser::readPrimary() {
     expect(",");
     readExpr();
     expect(")");
+    seenDataAlign = true;
     return [=] {
-      return alignTo(script->getDot(), std::max((uint64_t)1, e().getValue()));
+      uint64_t align = std::max(uint64_t(1), e().getValue());
+      return (script->getDot() + align - 1) & -align;
     };
   }
   if (tok == "DATA_SEGMENT_END") {
@@ -1347,13 +1442,14 @@ Expr ScriptParser::readPrimary() {
     expect(",");
     readExpr();
     expect(")");
+    seenRelroEnd = true;
     Expr e = getPageSize();
-    return [=] { return alignTo(script->getDot(), e().getValue()); };
+    return [=] { return alignToPowerOf2(script->getDot(), e().getValue()); };
   }
   if (tok == "DEFINED") {
     StringRef name = unquote(readParenLiteral());
     return [=] {
-      Symbol *b = symtab->find(name);
+      Symbol *b = symtab.find(name);
       return (b && b->isDefined()) ? 1 : 0;
     };
   }
@@ -1367,11 +1463,11 @@ Expr ScriptParser::readPrimary() {
   }
   if (tok == "LOADADDR") {
     StringRef name = readParenLiteral();
-    OutputSection *cmd = script->getOrCreateOutputSection(name);
-    cmd->usedInExpression = true;
+    OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
+    osec->usedInExpression = true;
     return [=] {
-      checkIfExists(cmd, location);
-      return cmd->getLMA();
+      checkIfExists(*osec, location);
+      return osec->getLMA();
     };
   }
   if (tok == "LOG2CEIL") {
@@ -1411,7 +1507,7 @@ Expr ScriptParser::readPrimary() {
   }
   if (tok == "SIZEOF") {
     StringRef name = readParenLiteral();
-    OutputSection *cmd = script->getOrCreateOutputSection(name);
+    OutputSection *cmd = &script->getOrCreateOutputSection(name)->osec;
     // Linker script does not create an output section if its content is empty.
     // We want to allow SIZEOF(.foo) where .foo is a section which happened to
     // be empty.
@@ -1425,12 +1521,13 @@ Expr ScriptParser::readPrimary() {
     return [=] { return script->getSymbolValue(tok, location); };
 
   // Tok is a literal number.
-  if (Optional<uint64_t> val = parseInt(tok))
+  if (std::optional<uint64_t> val = parseInt(tok))
     return [=] { return *val; };
 
   // Tok is a symbol name.
-  tok = unquote(tok);
-  if (!isValidSymbolName(tok))
+  if (tok.startswith("\""))
+    tok = unquote(tok);
+  else if (!isValidSymbolName(tok))
     setError("malformed number: " + tok);
   script->referencedSymbols.push_back(tok);
   return [=] { return script->getSymbolValue(tok, location); };
@@ -1450,8 +1547,8 @@ Expr ScriptParser::readParenExpr() {
   return e;
 }
 
-std::vector<StringRef> ScriptParser::readOutputSectionPhdrs() {
-  std::vector<StringRef> phdrs;
+SmallVector<StringRef, 0> ScriptParser::readOutputSectionPhdrs() {
+  SmallVector<StringRef, 0> phdrs;
   while (!errorCount() && peek().startswith(":")) {
     StringRef tok = next();
     phdrs.push_back((tok.size() == 1) ? next() : tok.substr(1));
@@ -1463,7 +1560,7 @@ std::vector<StringRef> ScriptParser::readOutputSectionPhdrs() {
 // name of a program header type or a constant (e.g. "0x3").
 unsigned ScriptParser::readPhdrType() {
   StringRef tok = next();
-  if (Optional<uint64_t> val = parseInt(tok))
+  if (std::optional<uint64_t> val = parseInt(tok))
     return *val;
 
   unsigned ret = StringSwitch<unsigned>(tok)
@@ -1493,8 +1590,8 @@ unsigned ScriptParser::readPhdrType() {
 
 // Reads an anonymous version declaration.
 void ScriptParser::readAnonymousDeclaration() {
-  std::vector<SymbolVersion> locals;
-  std::vector<SymbolVersion> globals;
+  SmallVector<SymbolVersion, 0> locals;
+  SmallVector<SymbolVersion, 0> globals;
   std::tie(locals, globals) = readSymbols();
   for (const SymbolVersion &pat : locals)
     config->versionDefinitions[VER_NDX_LOCAL].localPatterns.push_back(pat);
@@ -1508,8 +1605,8 @@ void ScriptParser::readAnonymousDeclaration() {
 // e.g. "VerStr { global: foo; bar; local: *; };".
 void ScriptParser::readVersionDeclaration(StringRef verStr) {
   // Read a symbol list.
-  std::vector<SymbolVersion> locals;
-  std::vector<SymbolVersion> globals;
+  SmallVector<SymbolVersion, 0> locals;
+  SmallVector<SymbolVersion, 0> globals;
   std::tie(locals, globals) = readSymbols();
 
   // Create a new version definition and add that to the global symbols.
@@ -1534,11 +1631,11 @@ bool elf::hasWildcard(StringRef s) {
 }
 
 // Reads a list of symbols, e.g. "{ global: foo; bar; local: *; };".
-std::pair<std::vector<SymbolVersion>, std::vector<SymbolVersion>>
+std::pair<SmallVector<SymbolVersion, 0>, SmallVector<SymbolVersion, 0>>
 ScriptParser::readSymbols() {
-  std::vector<SymbolVersion> locals;
-  std::vector<SymbolVersion> globals;
-  std::vector<SymbolVersion> *v = &globals;
+  SmallVector<SymbolVersion, 0> locals;
+  SmallVector<SymbolVersion, 0> globals;
+  SmallVector<SymbolVersion, 0> *v = &globals;
 
   while (!errorCount()) {
     if (consume("}"))
@@ -1553,7 +1650,7 @@ ScriptParser::readSymbols() {
     }
 
     if (consume("extern")) {
-      std::vector<SymbolVersion> ext = readVersionExtern();
+      SmallVector<SymbolVersion, 0> ext = readVersionExtern();
       v->insert(v->end(), ext.begin(), ext.end());
     } else {
       StringRef tok = next();
@@ -1569,14 +1666,14 @@ ScriptParser::readSymbols() {
 //
 // The last semicolon is optional. E.g. this is OK:
 // "extern "C++" { ns::*; "f(int, double)" };"
-std::vector<SymbolVersion> ScriptParser::readVersionExtern() {
+SmallVector<SymbolVersion, 0> ScriptParser::readVersionExtern() {
   StringRef tok = next();
   bool isCXX = tok == "\"C++\"";
   if (!isCXX && tok != "\"C\"")
     setError("Unknown language");
   expect("{");
 
-  std::vector<SymbolVersion> ret;
+  SmallVector<SymbolVersion, 0> ret;
   while (!errorCount() && peek() != "}") {
     StringRef tok = next();
     ret.push_back(
@@ -1614,9 +1711,11 @@ void ScriptParser::readMemory() {
     }
 
     uint32_t flags = 0;
+    uint32_t invFlags = 0;
     uint32_t negFlags = 0;
+    uint32_t negInvFlags = 0;
     if (consume("(")) {
-      std::tie(flags, negFlags) = readMemoryAttributes();
+      readMemoryAttributes(flags, invFlags, negFlags, negInvFlags);
       expect(")");
     }
     expect(":");
@@ -1626,7 +1725,8 @@ void ScriptParser::readMemory() {
     Expr length = readMemoryAssignment("LENGTH", "len", "l");
 
     // Add the memory region to the region map.
-    MemoryRegion *mr = make<MemoryRegion>(tok, origin, length, flags, negFlags);
+    MemoryRegion *mr = make<MemoryRegion>(tok, origin, length, flags, invFlags,
+                                          negFlags, negInvFlags);
     if (!script->memoryRegions.insert({tok, mr}).second)
       setError("region '" + tok + "' already defined");
   }
@@ -1635,30 +1735,34 @@ void ScriptParser::readMemory() {
 // This function parses the attributes used to match against section
 // flags when placing output sections in a memory region. These flags
 // are only used when an explicit memory region name is not used.
-std::pair<uint32_t, uint32_t> ScriptParser::readMemoryAttributes() {
-  uint32_t flags = 0;
-  uint32_t negFlags = 0;
+void ScriptParser::readMemoryAttributes(uint32_t &flags, uint32_t &invFlags,
+                                        uint32_t &negFlags,
+                                        uint32_t &negInvFlags) {
   bool invert = false;
 
   for (char c : next().lower()) {
-    uint32_t flag = 0;
-    if (c == '!')
+    if (c == '!') {
       invert = !invert;
-    else if (c == 'w')
-      flag = SHF_WRITE;
+      std::swap(flags, negFlags);
+      std::swap(invFlags, negInvFlags);
+      continue;
+    }
+    if (c == 'w')
+      flags |= SHF_WRITE;
     else if (c == 'x')
-      flag = SHF_EXECINSTR;
+      flags |= SHF_EXECINSTR;
     else if (c == 'a')
-      flag = SHF_ALLOC;
-    else if (c != 'r')
+      flags |= SHF_ALLOC;
+    else if (c == 'r')
+      invFlags |= SHF_WRITE;
+    else
       setError("invalid memory region attribute");
+  }
 
-    if (invert)
-      negFlags |= flag;
-    else
-      flags |= flag;
+  if (invert) {
+    std::swap(flags, negFlags);
+    std::swap(invFlags, negInvFlags);
   }
-  return {flags, negFlags};
 }
 
 void elf::readLinkerScript(MemoryBufferRef mb) {
index da1684a..a47d75d 100644 (file)
 
 #include "SymbolTable.h"
 #include "Config.h"
-#include "LinkerScript.h"
+#include "InputFiles.h"
 #include "Symbols.h"
-#include "SyntheticSections.h"
 #include "lld/Common/ErrorHandler.h"
 #include "lld/Common/Memory.h"
 #include "lld/Common/Strings.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/Demangle/Demangle.h"
 
 using namespace llvm;
 using namespace llvm::object;
@@ -29,10 +29,10 @@ using namespace llvm::ELF;
 using namespace lld;
 using namespace lld::elf;
 
-SymbolTable *elf::symtab;
+SymbolTable elf::symtab;
 
 void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) {
-  // Swap symbols as instructed by -wrap.
+  // Redirect __real_foo to the original foo and foo to the original __wrap_foo.
   int &idx1 = symMap[CachedHashStringRef(sym->getName())];
   int &idx2 = symMap[CachedHashStringRef(real->getName())];
   int &idx3 = symMap[CachedHashStringRef(wrap->getName())];
@@ -40,9 +40,15 @@ void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) {
   idx2 = idx1;
   idx1 = idx3;
 
-  if (real->exportDynamic)
-    sym->exportDynamic = true;
-  if (!real->isUsedInRegularObj && sym->isUndefined())
+  // Propagate symbol usage information to the redirected symbols.
+  if (sym->isUsedInRegularObj)
+    wrap->isUsedInRegularObj = true;
+  if (real->isUsedInRegularObj)
+    sym->isUsedInRegularObj = true;
+  else if (!sym->isDefined())
+    // Now that all references to sym have been redirected to wrap, if there are
+    // no references to real (which has been redirected to sym), we only need to
+    // keep sym if it was defined, otherwise it's unused and can be dropped.
     sym->isUsedInRegularObj = false;
 
   // Now renaming is complete, and no one refers to real. We drop real from
@@ -64,41 +70,44 @@ Symbol *SymbolTable::insert(StringRef name) {
   // Since this is a hot path, the following string search code is
   // optimized for speed. StringRef::find(char) is much faster than
   // StringRef::find(StringRef).
+  StringRef stem = name;
   size_t pos = name.find('@');
   if (pos != StringRef::npos && pos + 1 < name.size() && name[pos + 1] == '@')
-    name = name.take_front(pos);
-
-  auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()});
-  int &symIndex = p.first->second;
-  bool isNew = p.second;
-
-  if (!isNew)
-    return symVector[symIndex];
+    stem = name.take_front(pos);
+
+  auto p = symMap.insert({CachedHashStringRef(stem), (int)symVector.size()});
+  if (!p.second) {
+    Symbol *sym = symVector[p.first->second];
+    if (stem.size() != name.size()) {
+      sym->setName(name);
+      sym->hasVersionSuffix = true;
+    }
+    return sym;
+  }
 
   Symbol *sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
   symVector.push_back(sym);
 
-  // *sym was not initialized by a constructor. Fields that may get referenced
-  // when it is a placeholder must be initialized here.
+  // *sym was not initialized by a constructor. Initialize all Symbol fields.
+  memset(sym, 0, sizeof(Symbol));
   sym->setName(name);
-  sym->symbolKind = Symbol::PlaceholderKind;
-  sym->versionId = VER_NDX_GLOBAL;
-  sym->visibility = STV_DEFAULT;
-  sym->isUsedInRegularObj = false;
-  sym->exportDynamic = false;
-  sym->inDynamicList = false;
-  sym->canInline = true;
-  sym->referenced = false;
-  sym->traced = false;
-  sym->gwarn = false;
-  sym->scriptDefined = false;
   sym->partition = 1;
+  sym->verdefIndex = -1;
+  sym->gwarn = false;
+  sym->versionId = VER_NDX_GLOBAL;
+  if (pos != StringRef::npos)
+    sym->hasVersionSuffix = true;
   return sym;
 }
 
-Symbol *SymbolTable::addSymbol(const Symbol &newSym) {
+// This variant of addSymbol is used by BinaryFile::parse to check duplicate
+// symbol errors.
+Symbol *SymbolTable::addAndCheckDuplicate(const Defined &newSym) {
   Symbol *sym = insert(newSym.getName());
+  if (sym->isDefined())
+    sym->checkDuplicate(newSym);
   sym->resolve(newSym);
+  sym->isUsedInRegularObj = true;
   return sym;
 }
 
@@ -106,15 +115,12 @@ Symbol *SymbolTable::find(StringRef name) {
   auto it = symMap.find(CachedHashStringRef(name));
   if (it == symMap.end())
     return nullptr;
-  Symbol *sym = symVector[it->second];
-  if (sym->isPlaceholder())
-    return nullptr;
-  return sym;
+  return symVector[it->second];
 }
 
 // A version script/dynamic list is only meaningful for a Defined symbol.
 // A CommonSymbol will be converted to a Defined in replaceCommonSymbols().
-// A lazy symbol may be made Defined if an LTO libcall fetches it.
+// A lazy symbol may be made Defined if an LTO libcall extracts it.
 static bool canBeVersioned(const Symbol &sym) {
   return sym.isDefined() || sym.isCommon() || sym.isLazy();
 }
@@ -132,7 +138,7 @@ static bool canBeVersioned(const Symbol &sym) {
 // other than trying to match a pattern against all demangled symbols.
 // So, if "extern C++" feature is used, we need to demangle all known
 // symbols.
-StringMap<std::vector<Symbol *>> &SymbolTable::getDemangledSyms() {
+StringMap<SmallVector<Symbol *, 0>> &SymbolTable::getDemangledSyms() {
   if (!demangledSyms) {
     demangledSyms.emplace();
     std::string demangled;
@@ -141,19 +147,19 @@ StringMap<std::vector<Symbol *>> &SymbolTable::getDemangledSyms() {
         StringRef name = sym->getName();
         size_t pos = name.find('@');
         if (pos == std::string::npos)
-          demangled = demangleItanium(name);
+          demangled = demangle(name.str());
         else if (pos + 1 == name.size() || name[pos + 1] == '@')
-          demangled = demangleItanium(name.substr(0, pos));
+          demangled = demangle(name.substr(0, pos).str());
         else
           demangled =
-              (demangleItanium(name.substr(0, pos)) + name.substr(pos)).str();
+              (demangle(name.substr(0, pos).str()) + name.substr(pos)).str();
         (*demangledSyms)[demangled].push_back(sym);
       }
   }
   return *demangledSyms;
 }
 
-std::vector<Symbol *> SymbolTable::findByVersion(SymbolVersion ver) {
+SmallVector<Symbol *, 0> SymbolTable::findByVersion(SymbolVersion ver) {
   if (ver.isExternCpp)
     return getDemangledSyms().lookup(ver.name);
   if (Symbol *sym = find(ver.name))
@@ -162,9 +168,9 @@ std::vector<Symbol *> SymbolTable::findByVersion(SymbolVersion ver) {
   return {};
 }
 
-std::vector<Symbol *> SymbolTable::findAllByVersion(SymbolVersion ver,
-                                                    bool includeNonDefault) {
-  std::vector<Symbol *> res;
+SmallVector<Symbol *, 0> SymbolTable::findAllByVersion(SymbolVersion ver,
+                                                       bool includeNonDefault) {
+  SmallVector<Symbol *, 0> res;
   SingleStringMatcher m(ver.name);
   auto check = [&](StringRef name) {
     size_t pos = name.find('@');
@@ -189,10 +195,9 @@ std::vector<Symbol *> SymbolTable::findAllByVersion(SymbolVersion ver,
   return res;
 }
 
-// Handles -dynamic-list.
 void SymbolTable::handleDynamicList() {
+  SmallVector<Symbol *, 0> syms;
   for (SymbolVersion &ver : config->dynamicList) {
-    std::vector<Symbol *> syms;
     if (ver.hasWildcard)
       syms = findAllByVersion(ver, /*includeNonDefault=*/true);
     else
@@ -209,7 +214,7 @@ bool SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
                                      StringRef versionName,
                                      bool includeNonDefault) {
   // Get a list of symbols which we need to assign the version to.
-  std::vector<Symbol *> syms = findByVersion(ver);
+  SmallVector<Symbol *, 0> syms = findByVersion(ver);
 
   auto getName = [](uint16_t ver) -> std::string {
     if (ver == VER_NDX_LOCAL)
@@ -230,7 +235,7 @@ bool SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
 
     // If the version has not been assigned, verdefIndex is -1. Use an arbitrary
     // number (0) to indicate the version has been assigned.
-    if (sym->verdefIndex == UINT32_C(-1)) {
+    if (sym->verdefIndex == uint16_t(-1)) {
       sym->verdefIndex = 0;
       sym->versionId = versionId;
     }
@@ -249,7 +254,7 @@ void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId,
   // so we set a version to a symbol only if no version has been assigned
   // to the symbol. This behavior is compatible with GNU.
   for (Symbol *sym : findAllByVersion(ver, includeNonDefault))
-    if (sym->verdefIndex == UINT32_C(-1)) {
+    if (sym->verdefIndex == uint16_t(-1)) {
       sym->verdefIndex = 0;
       sym->versionId = versionId;
     }
@@ -264,7 +269,6 @@ void SymbolTable::scanVersionScript() {
   SmallString<128> buf;
   // First, we assign versions to exact matching symbols,
   // i.e. version definitions not containing any glob meta-characters.
-  std::vector<Symbol *> syms;
   for (VersionDefinition &v : config->versionDefinitions) {
     auto assignExact = [&](SymbolVersion pat, uint16_t id, StringRef ver) {
       bool found =
@@ -274,8 +278,8 @@ void SymbolTable::scanVersionScript() {
                                    pat.isExternCpp, /*hasWildCard=*/false},
                                   id, ver, /*includeNonDefault=*/true);
       if (!found && !config->undefinedVersion)
-        errorOrWarn("version script assignment of '" + ver + "' to symbol '" +
-                    pat.name + "' failed: symbol not defined");
+        warn("version script assignment of '" + ver + "' to symbol '" +
+             pat.name + "' failed: symbol not defined");
     };
     for (SymbolVersion &pat : v.nonLocalPatterns)
       if (!pat.hasWildcard)
@@ -320,7 +324,8 @@ void SymbolTable::scanVersionScript() {
   // can contain versions in the form of <name>@<version>.
   // Let them parse and update their names to exclude version suffix.
   for (Symbol *sym : symVector)
-    sym->parseSymbolVersion();
+    if (sym->hasVersionSuffix)
+      sym->parseSymbolVersion();
 
   // isPreemptible is false at this point. To correctly compute the binding of a
   // Defined (which is used by includeInDynsym()), we need to know if it is
index 8138501..96ae7a5 100644 (file)
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "Symbols.h"
+#include "Driver.h"
 #include "InputFiles.h"
 #include "InputSection.h"
 #include "OutputSections.h"
 #include "Target.h"
 #include "Writer.h"
 #include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Strings.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
+#include "llvm/Demangle/Demangle.h"
+#include "llvm/Support/Compiler.h"
 #include <cstring>
 
 using namespace llvm;
@@ -26,16 +25,34 @@ using namespace llvm::ELF;
 using namespace lld;
 using namespace lld::elf;
 
+static_assert(sizeof(SymbolUnion) <= 64, "SymbolUnion too large");
+
+template <typename T> struct AssertSymbol {
+  static_assert(std::is_trivially_destructible<T>(),
+                "Symbol types must be trivially destructible");
+  static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
+  static_assert(alignof(T) <= alignof(SymbolUnion),
+                "SymbolUnion not aligned enough");
+};
+
+LLVM_ATTRIBUTE_UNUSED static inline void assertSymbols() {
+  AssertSymbol<Defined>();
+  AssertSymbol<CommonSymbol>();
+  AssertSymbol<Undefined>();
+  AssertSymbol<SharedSymbol>();
+  AssertSymbol<LazyObject>();
+}
+
 // Returns a symbol for an error message.
-static std::string demangle(StringRef symName) {
+static std::string maybeDemangleSymbol(StringRef symName) {
   if (elf::config->demangle)
-    return demangleItanium(symName);
-  return std::string(symName);
+    return demangle(symName.str());
+  return symName.str();
 }
 
 std::string lld::toString(const elf::Symbol &sym) {
   StringRef name = sym.getName();
-  std::string ret = demangle(name);
+  std::string ret = maybeDemangleSymbol(name);
 
   const char *suffix = sym.getVersionSuffix();
   if (*suffix == '@')
@@ -43,10 +60,6 @@ std::string lld::toString(const elf::Symbol &sym) {
   return ret;
 }
 
-std::string lld::toELFString(const Archive::Symbol &b) {
-  return demangle(b.getName());
-}
-
 Defined *ElfSym::bss;
 Defined *ElfSym::data;
 Defined *ElfSym::etext1;
@@ -61,12 +74,10 @@ Defined *ElfSym::mipsGpDisp;
 Defined *ElfSym::mipsLocalGp;
 Defined *ElfSym::relaIpltStart;
 Defined *ElfSym::relaIpltEnd;
-Defined *ElfSym::riscvGlobalPointer;
 Defined *ElfSym::tlsModuleBase;
-DenseMap<const Symbol *, std::pair<const InputFile *, const InputFile *>>
-    elf::backwardReferences;
+SmallVector<SymbolAux, 0> elf::symAux;
 
-static uint64_t getSymVA(const Symbol &sym, int64_t &addend) {
+static uint64_t getSymVA(const Symbol &sym, int64_t addend) {
   switch (sym.kind()) {
   case Symbol::DefinedKind: {
     auto &d = cast<Defined>(sym);
@@ -77,7 +88,6 @@ static uint64_t getSymVA(const Symbol &sym, int64_t &addend) {
       return d.value;
 
     assert(isec != &InputSection::discarded);
-    isec = isec->repl;
 
     uint64_t offset = d.value;
 
@@ -92,10 +102,8 @@ static uint64_t getSymVA(const Symbol &sym, int64_t &addend) {
     // To make this work, we incorporate the addend into the section
     // offset (and zero out the addend for later processing) so that
     // we find the right object in the section.
-    if (d.isSection()) {
+    if (d.isSection())
       offset += addend;
-      addend = 0;
-    }
 
     // In the typical case, this is actually very simple and boils
     // down to adding together 3 numbers:
@@ -108,6 +116,8 @@ static uint64_t getSymVA(const Symbol &sym, int64_t &addend) {
     // line (and how they get built), then you have a pretty good
     // understanding of the linker.
     uint64_t va = isec->getVA(offset);
+    if (d.isSection())
+      va -= addend;
 
     // MIPS relocatable files can mix regular and microMIPS code.
     // Linker needs to distinguish such code. To do so microMIPS
@@ -119,7 +129,7 @@ static uint64_t getSymVA(const Symbol &sym, int64_t &addend) {
     // field etc) do the same trick as compiler uses to mark microMIPS
     // for CPU - set the less-significant bit.
     if (config->emachine == EM_MIPS && isMicroMips() &&
-        ((sym.stOther & STO_MIPS_MICROMIPS) || sym.needsPltAddr))
+        ((sym.stOther & STO_MIPS_MICROMIPS) || sym.hasFlag(NEEDS_COPY)))
       va |= 1;
 
     if (d.isTls() && !config->relocatable) {
@@ -138,10 +148,8 @@ static uint64_t getSymVA(const Symbol &sym, int64_t &addend) {
   case Symbol::SharedKind:
   case Symbol::UndefinedKind:
     return 0;
-  case Symbol::LazyArchiveKind:
   case Symbol::LazyObjectKind:
-    assert(sym.isUsedInRegularObj && "lazy symbol reached writer");
-    return 0;
+    llvm_unreachable("lazy symbol reached writer");
   case Symbol::CommonKind:
     llvm_unreachable("common symbol reached writer");
   case Symbol::PlaceholderKind:
@@ -151,8 +159,7 @@ static uint64_t getSymVA(const Symbol &sym, int64_t &addend) {
 }
 
 uint64_t Symbol::getVA(int64_t addend) const {
-  uint64_t outVA = getSymVA(*this, addend);
-  return outVA + addend;
+  return getSymVA(*this, addend) + addend;
 }
 
 uint64_t Symbol::getGotVA() const {
@@ -162,7 +169,7 @@ uint64_t Symbol::getGotVA() const {
 }
 
 uint64_t Symbol::getGotOffset() const {
-  return gotIndex * target->gotEntrySize;
+  return getGotIdx() * target->gotEntrySize;
 }
 
 uint64_t Symbol::getGotPltVA() const {
@@ -173,15 +180,15 @@ uint64_t Symbol::getGotPltVA() const {
 
 uint64_t Symbol::getGotPltOffset() const {
   if (isInIplt)
-    return pltIndex * target->gotEntrySize;
-  return (pltIndex + target->gotPltHeaderEntriesNum) * target->gotEntrySize;
+    return getPltIdx() * target->gotEntrySize;
+  return (getPltIdx() + target->gotPltHeaderEntriesNum) * target->gotEntrySize;
 }
 
 uint64_t Symbol::getPltVA() const {
   uint64_t outVA = isInIplt
-                       ? in.iplt->getVA() + pltIndex * target->ipltEntrySize
+                       ? in.iplt->getVA() + getPltIdx() * target->ipltEntrySize
                        : in.plt->getVA() + in.plt->headerSize +
-                             pltIndex * target->pltEntrySize;
+                             getPltIdx() * target->pltEntrySize;
 
   // While linking microMIPS code PLT code are always microMIPS
   // code. Set the less-significant bit to track that fact.
@@ -200,7 +207,7 @@ uint64_t Symbol::getSize() const {
 OutputSection *Symbol::getOutputSection() const {
   if (auto *s = dyn_cast<Defined>(this)) {
     if (auto *sec = s->section)
-      return sec->repl->getOutputSection();
+      return sec->getOutputSection();
     return nullptr;
   }
   return nullptr;
@@ -214,15 +221,16 @@ void Symbol::parseSymbolVersion() {
     return;
   StringRef s = getName();
   size_t pos = s.find('@');
-  if (pos == 0 || pos == StringRef::npos)
+  if (pos == StringRef::npos)
     return;
   StringRef verstr = s.substr(pos + 1);
-  if (verstr.empty())
-    return;
 
   // Truncate the symbol name so that it doesn't include the version string.
   nameSize = pos;
 
+  if (verstr.empty())
+    return;
+
   // If this is not in this DSO, it is not a definition.
   if (!isDefined())
     return;
@@ -255,44 +263,23 @@ void Symbol::parseSymbolVersion() {
           verstr);
 }
 
-void Symbol::fetch() const {
-  if (auto *sym = dyn_cast<LazyArchive>(this)) {
-    cast<ArchiveFile>(sym->file)->fetch(sym->sym);
-    return;
-  }
-
-  if (auto *sym = dyn_cast<LazyObject>(this)) {
-    dyn_cast<LazyObjFile>(sym->file)->fetch();
-    return;
+void Symbol::extract() const {
+  if (file->lazy) {
+    file->lazy = false;
+    parseFile(file);
   }
-
-  llvm_unreachable("Symbol::fetch() is called on a non-lazy symbol");
-}
-
-MemoryBufferRef LazyArchive::getMemberBuffer() {
-  Archive::Child c =
-      CHECK(sym.getMember(),
-            "could not get the member for symbol " + toELFString(sym));
-
-  return CHECK(c.getMemoryBufferRef(),
-               "could not get the buffer for the member defining symbol " +
-                   toELFString(sym));
 }
 
 uint8_t Symbol::computeBinding() const {
-  if (config->relocatable)
-    return binding;
-  if ((visibility != STV_DEFAULT && visibility != STV_PROTECTED) ||
-      (versionId == VER_NDX_LOCAL && !isLazy()))
+  auto v = visibility();
+  if ((v != STV_DEFAULT && v != STV_PROTECTED) || versionId == VER_NDX_LOCAL)
     return STB_LOCAL;
-  if (!config->gnuUnique && binding == STB_GNU_UNIQUE)
+  if (binding == STB_GNU_UNIQUE && !config->gnuUnique)
     return STB_GLOBAL;
   return binding;
 }
 
 bool Symbol::includeInDynsym() const {
-  if (!config->hasDynSymTab)
-    return false;
   if (computeBinding() == STB_LOCAL)
     return false;
   if (!isDefined() && !isCommon())
@@ -300,26 +287,31 @@ bool Symbol::includeInDynsym() const {
     // expects undefined weak symbols not to exist in .dynsym, e.g.
     // __pthread_mutex_lock reference in _dl_add_to_namespace_list,
     // __pthread_initialize_minimal reference in csu/libc-start.c.
-    return !(config->noDynamicLinker && isUndefWeak());
+    return !(isUndefWeak() && config->noDynamicLinker);
 
   return exportDynamic || inDynamicList;
 }
 
 // Print out a log message for --trace-symbol.
-void elf::printTraceSymbol(const Symbol *sym) {
+void elf::printTraceSymbol(const Symbol &sym, StringRef name) {
   std::string s;
-  if (sym->isUndefined())
+  if (sym.isUndefined())
     s = ": reference to ";
-  else if (sym->isLazy())
+  else if (sym.isLazy())
     s = ": lazy definition of ";
-  else if (sym->isShared())
+  else if (sym.isShared())
     s = ": shared definition of ";
-  else if (sym->isCommon())
+  else if (sym.isCommon())
     s = ": common definition of ";
   else
     s = ": definition of ";
 
-  message(toString(sym->file) + s + sym->getName());
+  message(toString(sym.file) + s + name);
+}
+
+static void recordWhyExtract(const InputFile *reference,
+                             const InputFile &extracted, const Symbol &sym) {
+  ctx.whyExtractRecords.emplace_back(toString(reference), &extracted, sym);
 }
 
 void elf::maybeWarnUnorderableSymbol(const Symbol *sym) {
@@ -348,18 +340,18 @@ void elf::maybeWarnUnorderableSymbol(const Symbol *sym) {
     report(": unable to order absolute symbol: ");
   else if (d && isa<OutputSection>(d->section))
     report(": unable to order synthetic symbol: ");
-  else if (d && !d->section->repl->isLive())
+  else if (d && !d->section->isLive())
     report(": unable to order discarded symbol: ");
 }
 
 // Returns true if a symbol can be replaced at load-time by a symbol
 // with the same name defined in other ELF executable or DSO.
 bool elf::computeIsPreemptible(const Symbol &sym) {
-  assert(!sym.isLocal());
+  assert(!sym.isLocal() || sym.isPlaceholder());
 
   // Only symbols with default visibility that appear in dynsym can be
   // preempted. Symbols with protected visibility cannot be preempted.
-  if (!sym.includeInDynsym() || sym.visibility != STV_DEFAULT)
+  if (!sym.includeInDynsym() || sym.visibility() != STV_DEFAULT)
     return false;
 
   // At this point copy relocations have not been created yet, so any
@@ -382,32 +374,6 @@ bool elf::computeIsPreemptible(const Symbol &sym) {
   return true;
 }
 
-void elf::reportBackrefs() {
-  for (auto &it : backwardReferences) {
-    const Symbol &sym = *it.first;
-    std::string to = toString(it.second.second);
-    // Some libraries have known problems and can cause noise. Filter them out
-    // with --warn-backrefs-exclude=. to may look like *.o or *.a(*.o).
-    bool exclude = false;
-    for (const llvm::GlobPattern &pat : config->warnBackrefsExclude)
-      if (pat.match(to)) {
-        exclude = true;
-        break;
-      }
-    if (!exclude)
-      warn("backward reference detected: " + sym.getName() + " in " +
-           toString(it.second.first) + " refers to " + to);
-  }
-}
-
-static uint8_t getMinVisibility(uint8_t va, uint8_t vb) {
-  if (va == STV_DEFAULT)
-    return vb;
-  if (vb == STV_DEFAULT)
-    return va;
-  return std::min(va, vb);
-}
-
 // Merge symbol properties.
 //
 // When we have many symbols of the same name, we choose one of them,
@@ -416,64 +382,36 @@ static uint8_t getMinVisibility(uint8_t va, uint8_t vb) {
 void Symbol::mergeProperties(const Symbol &other) {
   if (other.exportDynamic)
     exportDynamic = true;
-  if (other.isUsedInRegularObj)
-    isUsedInRegularObj = true;
 
   // DSO symbols do not affect visibility in the output.
-  if (!other.isShared())
-    visibility = getMinVisibility(visibility, other.visibility);
-}
-
-void Symbol::resolve(const Symbol &other) {
-  mergeProperties(other);
-
-  if (isPlaceholder()) {
-    replace(other);
-    return;
-  }
-
-  switch (other.kind()) {
-  case Symbol::UndefinedKind:
-    resolveUndefined(cast<Undefined>(other));
-    break;
-  case Symbol::CommonKind:
-    resolveCommon(cast<CommonSymbol>(other));
-    break;
-  case Symbol::DefinedKind:
-    resolveDefined(cast<Defined>(other));
-    break;
-  case Symbol::LazyArchiveKind:
-    resolveLazy(cast<LazyArchive>(other));
-    break;
-  case Symbol::LazyObjectKind:
-    resolveLazy(cast<LazyObject>(other));
-    break;
-  case Symbol::SharedKind:
-    resolveShared(cast<SharedSymbol>(other));
-    break;
-  case Symbol::PlaceholderKind:
-    llvm_unreachable("bad symbol kind");
+  if (!other.isShared() && other.visibility() != STV_DEFAULT) {
+    uint8_t v = visibility(), ov = other.visibility();
+    setVisibility(v == STV_DEFAULT ? ov : std::min(v, ov));
   }
 }
 
-void Symbol::resolveUndefined(const Undefined &other) {
+void Symbol::resolve(const Undefined &other) {
+  if (other.visibility() != STV_DEFAULT) {
+    uint8_t v = visibility(), ov = other.visibility();
+    setVisibility(v == STV_DEFAULT ? ov : std::min(v, ov));
+  }
   // An undefined symbol with non default visibility must be satisfied
   // in the same DSO.
   //
   // If this is a non-weak defined symbol in a discarded section, override the
   // existing undefined symbol for better error message later.
-  if ((isShared() && other.visibility != STV_DEFAULT) ||
+  if (isPlaceholder() || (isShared() && other.visibility() != STV_DEFAULT) ||
       (isUndefined() && other.binding != STB_WEAK && other.discardedSecIdx)) {
-    replace(other);
+    other.overwrite(*this);
     return;
   }
 
   if (traced)
-    printTraceSymbol(&other);
+    printTraceSymbol(other, getName());
 
   if (isLazy()) {
-    // An undefined weak will not fetch archive members. See comment on Lazy in
-    // Symbols.h for the details.
+    // An undefined weak will not extract archive members. See comment on Lazy
+    // in Symbols.h for the details.
     if (other.binding == STB_WEAK) {
       binding = STB_WEAK;
       type = other.type;
@@ -483,9 +421,9 @@ void Symbol::resolveUndefined(const Undefined &other) {
     // Do extra check for --warn-backrefs.
     //
     // --warn-backrefs is an option to prevent an undefined reference from
-    // fetching an archive member written earlier in the command line. It can be
-    // used to keep compatibility with GNU linkers to some degree.
-    // I'll explain the feature and why you may find it useful in this comment.
+    // extracting an archive member written earlier in the command line. It can
+    // be used to keep compatibility with GNU linkers to some degree. I'll
+    // explain the feature and why you may find it useful in this comment.
     //
     // lld's symbol resolution semantics is more relaxed than traditional Unix
     // linkers. For example,
@@ -532,7 +470,10 @@ void Symbol::resolveUndefined(const Undefined &other) {
     // group assignment rule simulates the traditional linker's semantics.
     bool backref = config->warnBackrefs && other.file &&
                    file->groupId < other.file->groupId;
-    fetch();
+    extract();
+
+    if (!config->whyExtract.empty())
+      recordWhyExtract(other.file, *file, *this);
 
     // We don't report backward references to weak symbols as they can be
     // overridden later.
@@ -543,12 +484,13 @@ void Symbol::resolveUndefined(const Undefined &other) {
     // definition. this->file needs to be saved because in the case of LTO it
     // may be reset to nullptr or be replaced with a file named lto.tmp.
     if (backref && !isWeak())
-      backwardReferences.try_emplace(this, std::make_pair(other.file, file));
+      ctx.backwardReferences.try_emplace(this,
+                                         std::make_pair(other.file, file));
     return;
   }
 
   // Undefined symbols in a SharedFile do not change the binding.
-  if (dyn_cast_or_null<SharedFile>(other.file))
+  if (isa_and_nonnull<SharedFile>(other.file))
     return;
 
   if (isUndefined() || isShared()) {
@@ -560,79 +502,41 @@ void Symbol::resolveUndefined(const Undefined &other) {
   }
 }
 
-// Using .symver foo,foo@@VER unfortunately creates two symbols: foo and
-// foo@@VER. We want to effectively ignore foo, so give precedence to
-// foo@@VER.
-// FIXME: If users can transition to using
-// .symver foo,foo@@@VER
-// we can delete this hack.
-static int compareVersion(StringRef a, StringRef b) {
-  bool x = a.contains("@@");
-  bool y = b.contains("@@");
-  if (!x && y)
-    return 1;
-  if (x && !y)
-    return -1;
-  return 0;
-}
-
-// Compare two symbols. Return 1 if the new symbol should win, -1 if
-// the new symbol should lose, or 0 if there is a conflict.
-int Symbol::compare(const Symbol *other) const {
-  assert(other->isDefined() || other->isCommon());
-
-  if (!isDefined() && !isCommon())
-    return 1;
-
-  if (int cmp = compareVersion(getName(), other->getName()))
-    return cmp;
-
-  if (other->isWeak())
-    return -1;
-
-  if (isWeak())
-    return 1;
-
-  if (isCommon() && other->isCommon()) {
-    if (config->warnCommon)
-      warn("multiple common of " + getName());
-    return 0;
-  }
-
-  if (isCommon()) {
+// Compare two symbols. Return true if the new symbol should win.
+bool Symbol::shouldReplace(const Defined &other) const {
+  if (LLVM_UNLIKELY(isCommon())) {
     if (config->warnCommon)
       warn("common " + getName() + " is overridden");
-    return 1;
+    return !other.isWeak();
   }
+  if (!isDefined())
+    return true;
 
-  if (other->isCommon()) {
-    if (config->warnCommon)
-      warn("common " + getName() + " is overridden");
-    return -1;
-  }
-
-  auto *oldSym = cast<Defined>(this);
-  auto *newSym = cast<Defined>(other);
-
-  if (dyn_cast_or_null<BitcodeFile>(other->file))
-    return 0;
-
-  if (!oldSym->section && !newSym->section && oldSym->value == newSym->value &&
-      newSym->binding == STB_GLOBAL)
-    return -1;
-
-  return 0;
+  // Incoming STB_GLOBAL overrides STB_WEAK/STB_GNU_UNIQUE. -fgnu-unique changes
+  // some vague linkage data in COMDAT from STB_WEAK to STB_GNU_UNIQUE. Treat
+  // STB_GNU_UNIQUE like STB_WEAK so that we prefer the first among all
+  // STB_WEAK/STB_GNU_UNIQUE copies. If we prefer an incoming STB_GNU_UNIQUE to
+  // an existing STB_WEAK, there may be discarded section errors because the
+  // selected copy may be in a non-prevailing COMDAT.
+  return !isGlobal() && other.isGlobal();
 }
 
-static void reportDuplicate(Symbol *sym, InputFile *newFile,
-                            InputSectionBase *errSec, uint64_t errOffset) {
+void elf::reportDuplicate(const Symbol &sym, const InputFile *newFile,
+                          InputSectionBase *errSec, uint64_t errOffset) {
   if (config->allowMultipleDefinition)
     return;
-
-  Defined *d = cast<Defined>(sym);
+  // In glibc<2.32, crti.o has .gnu.linkonce.t.__x86.get_pc_thunk.bx, which
+  // is sort of proto-comdat. There is actually no duplicate if we have
+  // full support for .gnu.linkonce.
+  const Defined *d = dyn_cast<Defined>(&sym);
+  if (!d || d->getName() == "__x86.get_pc_thunk.bx")
+    return;
+  // Allow absolute symbols with the same value for GNU ld compatibility.
+  if (!d->section && !errSec && errOffset && d->value == errOffset)
+    return;
   if (!d->section || !errSec) {
-    error("duplicate symbol: " + toString(*sym) + "\n>>> defined in " +
-          toString(sym->file) + "\n>>> defined in " + toString(newFile));
+    error("duplicate symbol: " + toString(sym) + "\n>>> defined in " +
+          toString(sym.file) + "\n>>> defined in " + toString(newFile));
     return;
   }
 
@@ -644,12 +548,12 @@ static void reportDuplicate(Symbol *sym, InputFile *newFile,
   //   >>> defined at baz.c:563
   //   >>>            baz.o in archive libbaz.a
   auto *sec1 = cast<InputSectionBase>(d->section);
-  std::string src1 = sec1->getSrcMsg(*sym, d->value);
+  std::string src1 = sec1->getSrcMsg(sym, d->value);
   std::string obj1 = sec1->getObjMsg(d->value);
-  std::string src2 = errSec->getSrcMsg(*sym, errOffset);
+  std::string src2 = errSec->getSrcMsg(sym, errOffset);
   std::string obj2 = errSec->getObjMsg(errOffset);
 
-  std::string msg = "duplicate symbol: " + toString(*sym) + "\n>>> defined at ";
+  std::string msg = "duplicate symbol: " + toString(sym) + "\n>>> defined at ";
   if (!src1.empty())
     msg += src1 + "\n>>>            ";
   msg += obj1 + "\n>>> defined at ";
@@ -659,106 +563,119 @@ static void reportDuplicate(Symbol *sym, InputFile *newFile,
   error(msg);
 }
 
-void Symbol::resolveCommon(const CommonSymbol &other) {
-  int cmp = compare(&other);
-  if (cmp < 0)
+void Symbol::checkDuplicate(const Defined &other) const {
+  if (isDefined() && !isWeak() && !other.isWeak())
+    reportDuplicate(*this, other.file,
+                    dyn_cast_or_null<InputSectionBase>(other.section),
+                    other.value);
+}
+
+void Symbol::resolve(const CommonSymbol &other) {
+  if (other.exportDynamic)
+    exportDynamic = true;
+  if (other.visibility() != STV_DEFAULT) {
+    uint8_t v = visibility(), ov = other.visibility();
+    setVisibility(v == STV_DEFAULT ? ov : std::min(v, ov));
+  }
+  if (isDefined() && !isWeak()) {
+    if (config->warnCommon)
+      warn("common " + getName() + " is overridden");
     return;
+  }
 
-  if (cmp > 0) {
-    if (auto *s = dyn_cast<SharedSymbol>(this)) {
-      // Increase st_size if the shared symbol has a larger st_size. The shared
-      // symbol may be created from common symbols. The fact that some object
-      // files were linked into a shared object first should not change the
-      // regular rule that picks the largest st_size.
-      uint64_t size = s->size;
-      replace(other);
-      if (size > cast<CommonSymbol>(this)->size)
-        cast<CommonSymbol>(this)->size = size;
-    } else {
-      replace(other);
+  if (CommonSymbol *oldSym = dyn_cast<CommonSymbol>(this)) {
+    if (config->warnCommon)
+      warn("multiple common of " + getName());
+    oldSym->alignment = std::max(oldSym->alignment, other.alignment);
+    if (oldSym->size < other.size) {
+      oldSym->file = other.file;
+      oldSym->size = other.size;
     }
     return;
   }
 
-  CommonSymbol *oldSym = cast<CommonSymbol>(this);
-
-  oldSym->alignment = std::max(oldSym->alignment, other.alignment);
-  if (oldSym->size < other.size) {
-    oldSym->file = other.file;
-    oldSym->size = other.size;
+  if (auto *s = dyn_cast<SharedSymbol>(this)) {
+    // Increase st_size if the shared symbol has a larger st_size. The shared
+    // symbol may be created from common symbols. The fact that some object
+    // files were linked into a shared object first should not change the
+    // regular rule that picks the largest st_size.
+    uint64_t size = s->size;
+    other.overwrite(*this);
+    if (size > cast<CommonSymbol>(this)->size)
+      cast<CommonSymbol>(this)->size = size;
+  } else {
+    other.overwrite(*this);
   }
 }
 
-void Symbol::resolveDefined(const Defined &other) {
-  int cmp = compare(&other);
-  if (cmp > 0)
-    replace(other);
-  else if (cmp == 0)
-    reportDuplicate(this, other.file,
-                    dyn_cast_or_null<InputSectionBase>(other.section),
-                    other.value);
+void Symbol::resolve(const Defined &other) {
+  if (other.exportDynamic)
+    exportDynamic = true;
+  if (other.visibility() != STV_DEFAULT) {
+    uint8_t v = visibility(), ov = other.visibility();
+    setVisibility(v == STV_DEFAULT ? ov : std::min(v, ov));
+  }
+  if (shouldReplace(other))
+    other.overwrite(*this);
 }
 
-template <class LazyT>
-static void replaceCommon(Symbol &oldSym, const LazyT &newSym) {
-  backwardReferences.erase(&oldSym);
-  oldSym.replace(newSym);
-  newSym.fetch();
-}
+void Symbol::resolve(const LazyObject &other) {
+  if (isPlaceholder()) {
+    other.overwrite(*this);
+    return;
+  }
 
-template <class LazyT> void Symbol::resolveLazy(const LazyT &other) {
   // For common objects, we want to look for global or weak definitions that
-  // should be fetched as the canonical definition instead.
-  if (isCommon() && elf::config->fortranCommon) {
-    if (auto *laSym = dyn_cast<LazyArchive>(&other)) {
-      ArchiveFile *archive = cast<ArchiveFile>(laSym->file);
-      const Archive::Symbol &archiveSym = laSym->sym;
-      if (archive->shouldFetchForCommon(archiveSym)) {
-        replaceCommon(*this, other);
-        return;
-      }
-    } else if (auto *loSym = dyn_cast<LazyObject>(&other)) {
-      LazyObjFile *obj = cast<LazyObjFile>(loSym->file);
-      if (obj->shouldFetchForCommon(loSym->getName())) {
-        replaceCommon(*this, other);
-        return;
-      }
-    }
+  // should be extracted as the canonical definition instead.
+  if (LLVM_UNLIKELY(isCommon()) && elf::config->fortranCommon &&
+      other.file->shouldExtractForCommon(getName())) {
+    ctx.backwardReferences.erase(this);
+    other.overwrite(*this);
+    other.extract();
+    return;
   }
 
   if (!isUndefined()) {
     // See the comment in resolveUndefined().
     if (isDefined())
-      backwardReferences.erase(this);
+      ctx.backwardReferences.erase(this);
     return;
   }
 
-  // An undefined weak will not fetch archive members. See comment on Lazy in
+  // An undefined weak will not extract archive members. See comment on Lazy in
   // Symbols.h for the details.
   if (isWeak()) {
     uint8_t ty = type;
-    replace(other);
+    other.overwrite(*this);
     type = ty;
     binding = STB_WEAK;
     return;
   }
 
-  other.fetch();
+  const InputFile *oldFile = file;
+  other.extract();
+  if (!config->whyExtract.empty())
+    recordWhyExtract(oldFile, *file, *this);
 }
 
-void Symbol::resolveShared(const SharedSymbol &other) {
+void Symbol::resolve(const SharedSymbol &other) {
+  exportDynamic = true;
+  if (isPlaceholder()) {
+    other.overwrite(*this);
+    return;
+  }
   if (isCommon()) {
     // See the comment in resolveCommon() above.
     if (other.size > cast<CommonSymbol>(this)->size)
       cast<CommonSymbol>(this)->size = other.size;
     return;
   }
-  if (visibility == STV_DEFAULT && (isUndefined() || isLazy())) {
+  if (visibility() == STV_DEFAULT && (isUndefined() || isLazy())) {
     // An undefined symbol with non default visibility must be satisfied
     // in the same DSO.
     uint8_t bind = binding;
-    replace(other);
+    other.overwrite(*this);
     binding = bind;
   } else if (traced)
-    printTraceSymbol(&other);
+    printTraceSymbol(other, getName());
 }
index 3a4f851..19ffc8f 100644 (file)
 #ifndef LLD_ELF_SYMBOLS_H
 #define LLD_ELF_SYMBOLS_H
 
-#include "InputFiles.h"
-#include "InputSection.h"
+#include "Config.h"
 #include "lld/Common/LLVM.h"
-#include "lld/Common/Strings.h"
+#include "lld/Common/Memory.h"
 #include "llvm/ADT/DenseMap.h"
-#include "llvm/Object/Archive.h"
 #include "llvm/Object/ELF.h"
+#include "llvm/Support/Compiler.h"
+#include <tuple>
 
 namespace lld {
+namespace elf {
+class Symbol;
+}
 // Returns a string representation for a symbol for diagnostics.
 std::string toString(const elf::Symbol &);
 
-// There are two different ways to convert an Archive::Symbol to a string:
-// One for Microsoft name mangling and one for Itanium name mangling.
-// Call the functions toCOFFString and toELFString, not just toString.
-std::string toELFString(const llvm::object::Archive::Symbol &);
-
 namespace elf {
 class CommonSymbol;
 class Defined;
-class InputFile;
-class LazyArchive;
-class LazyObject;
+class OutputSection;
+class SectionBase;
+class InputSectionBase;
 class SharedSymbol;
 class Symbol;
 class Undefined;
+class LazyObject;
+class InputFile;
 
-// This is a StringRef-like container that doesn't run strlen().
-//
-// ELF string tables contain a lot of null-terminated strings. Most of them
-// are not necessary for the linker because they are names of local symbols,
-// and the linker doesn't use local symbol names for name resolution. So, we
-// use this class to represents strings read from string tables.
-struct StringRefZ {
-  StringRefZ(const char *s) : data(s), size(-1) {}
-  StringRefZ(StringRef s) : data(s.data()), size(s.size()) {}
-
-  const char *data;
-  const uint32_t size;
+void printTraceSymbol(const Symbol &sym, StringRef name);
+
+enum {
+  NEEDS_GOT = 1 << 0,
+  NEEDS_PLT = 1 << 1,
+  HAS_DIRECT_RELOC = 1 << 2,
+  // True if this symbol needs a canonical PLT entry, or (during
+  // postScanRelocations) a copy relocation.
+  NEEDS_COPY = 1 << 3,
+  NEEDS_TLSDESC = 1 << 4,
+  NEEDS_TLSGD = 1 << 5,
+  NEEDS_TLSGD_TO_IE = 1 << 6,
+  NEEDS_GOT_DTPREL = 1 << 7,
+  NEEDS_TLSIE = 1 << 8,
+};
+
+// Some index properties of a symbol are stored separately in this auxiliary
+// struct to decrease sizeof(SymbolUnion) in the majority of cases.
+struct SymbolAux {
+  uint32_t gotIdx = -1;
+  uint32_t pltIdx = -1;
+  uint32_t tlsDescIdx = -1;
+  uint32_t tlsGdIdx = -1;
 };
 
+LLVM_LIBRARY_VISIBILITY extern SmallVector<SymbolAux, 0> symAux;
+
 // The base class for real symbol classes.
 class Symbol {
 public:
@@ -63,7 +76,6 @@ public:
     CommonKind,
     SharedKind,
     UndefinedKind,
-    LazyArchiveKind,
     LazyObjectKind,
   };
 
@@ -72,39 +84,38 @@ public:
   // The file from which this symbol was created.
   InputFile *file;
 
+  // The default copy constructor is deleted due to atomic flags. Define one for
+  // places where no atomic is needed.
+  Symbol(const Symbol &o) { memcpy(this, &o, sizeof(o)); }
+
 protected:
   const char *nameData;
-  mutable uint32_t nameSize;
+  // 32-bit size saves space.
+  uint32_t nameSize;
 
 public:
-  uint32_t dynsymIndex = 0;
-  uint32_t gotIndex = -1;
-  uint32_t pltIndex = -1;
-
-  uint32_t globalDynIndex = -1;
-
-  // This field is a index to the symbol's version definition.
-  uint32_t verdefIndex = -1;
-
-  // Version definition index.
-  uint16_t versionId;
+  // The next three fields have the same meaning as the ELF symbol attributes.
+  // type and binding are placed in this order to optimize generating st_info,
+  // which is defined as (binding << 4) + (type & 0xf), on a little-endian
+  // system.
+  uint8_t type : 4; // symbol type
 
   // Symbol binding. This is not overwritten by replace() to track
   // changes during resolution. In particular:
   //  - An undefined weak is still weak when it resolves to a shared library.
-  //  - An undefined weak will not fetch archive members, but we have to
+  //  - An undefined weak will not extract archive members, but we have to
   //    remember it is weak.
-  uint8_t binding;
+  uint8_t binding : 4;
 
-  // The following fields have the same meaning as the ELF symbol attributes.
-  uint8_t type;    // symbol type
   uint8_t stOther; // st_other field value
 
   uint8_t symbolKind;
 
-  // Symbol visibility. This is the computed minimum visibility of all
-  // observed non-DSO symbols.
-  uint8_t visibility : 2;
+  // The partition whose dynamic symbol table contains this symbol's definition.
+  uint8_t partition;
+
+  // True if this symbol is preemptible at load time.
+  uint8_t isPreemptible : 1;
 
   // True if the symbol was used for linking and thus need to be added to the
   // output file's symbol table. This is true for all symbols except for
@@ -112,11 +123,18 @@ public:
   // are unreferenced except by other bitcode objects.
   uint8_t isUsedInRegularObj : 1;
 
+  // True if an undefined or shared symbol is used from a live section.
+  //
+  // NOTE: In Writer.cpp the field is used to mark local defined symbols
+  // which are referenced by relocations when -r or --emit-relocs is given.
+  uint8_t used : 1;
+
   // Used by a Defined symbol with protected or default visibility, to record
   // whether it is required to be exported into .dynsym. This is set when any of
   // the following conditions hold:
   //
-  // - If there is an interposable symbol from a DSO.
+  // - If there is an interposable symbol from a DSO. Note: We also do this for
+  //   STV_PROTECTED symbols which can't be interposed (to match BFD behavior).
   // - If -shared or --export-dynamic is specified, any symbol in an object
   //   file/bitcode sets this property, unless suppressed by LTO
   //   canBeOmittedFromSymbolTable().
@@ -127,28 +145,35 @@ public:
   // exported into .dynsym.
   uint8_t inDynamicList : 1;
 
-  // False if LTO shouldn't inline whatever this symbol points to. If a symbol
-  // is overwritten after LTO, LTO shouldn't inline the symbol because it
-  // doesn't know the final contents of the symbol.
-  uint8_t canInline : 1;
-
   // Used to track if there has been at least one undefined reference to the
   // symbol. For Undefined and SharedSymbol, the binding may change to STB_WEAK
   // if the first undefined reference from a non-shared object is weak.
-  //
-  // This is also used to retain __wrap_foo when foo is referenced.
   uint8_t referenced : 1;
 
+  // Used to track if this symbol will be referenced after wrapping is performed
+  // (i.e. this will be true for foo if __real_foo is referenced, and will be
+  // true for __wrap_foo if foo is referenced).
+  uint8_t referencedAfterWrap : 1;
+
   // True if this symbol is specified by --trace-symbol option.
   uint8_t traced : 1;
 
+  // True if the name contains '@'.
+  uint8_t hasVersionSuffix : 1;
+
   // True if the .gnu.warning.SYMBOL is set for the symbol
   uint8_t gwarn : 1;
 
-  inline void replace(const Symbol &newSym);
+  // Symbol visibility. This is the computed minimum visibility of all
+  // observed non-DSO symbols.
+  uint8_t visibility() const { return stOther & 3; }
+  void setVisibility(uint8_t visibility) {
+    stOther = (stOther & ~3) | visibility;
+  }
 
   bool includeInDynsym() const;
   uint8_t computeBinding() const;
+  bool isGlobal() const { return binding == llvm::ELF::STB_GLOBAL; }
   bool isWeak() const { return binding == llvm::ELF::STB_WEAK; }
 
   bool isUndefined() const { return symbolKind == UndefinedKind; }
@@ -159,22 +184,13 @@ public:
 
   bool isLocal() const { return binding == llvm::ELF::STB_LOCAL; }
 
-  bool isLazy() const {
-    return symbolKind == LazyArchiveKind || symbolKind == LazyObjectKind;
-  }
+  bool isLazy() const { return symbolKind == LazyObjectKind; }
 
   // True if this is an undefined weak symbol. This only works once
   // all input files have been added.
-  bool isUndefWeak() const {
-    // See comment on lazy symbols for details.
-    return isWeak() && (isUndefined() || isLazy());
-  }
+  bool isUndefWeak() const { return isWeak() && isUndefined(); }
 
-  StringRef getName() const {
-    if (nameSize == (uint32_t)-1)
-      nameSize = strlen(nameData);
-    return {nameData, nameSize};
-  }
+  StringRef getName() const { return {nameData, nameSize}; }
 
   void setName(StringRef s) {
     nameData = s.data();
@@ -187,13 +203,15 @@ public:
   //
   // For @@, the name has been truncated by insert(). For @, the name has been
   // truncated by Symbol::parseSymbolVersion().
-  const char *getVersionSuffix() const {
-    (void)getName();
-    return nameData + nameSize;
-  }
+  const char *getVersionSuffix() const { return nameData + nameSize; }
+
+  uint32_t getGotIdx() const { return symAux[auxIdx].gotIdx; }
+  uint32_t getPltIdx() const { return symAux[auxIdx].pltIdx; }
+  uint32_t getTlsDescIdx() const { return symAux[auxIdx].tlsDescIdx; }
+  uint32_t getTlsGdIdx() const { return symAux[auxIdx].tlsGdIdx; }
 
-  bool isInGot() const { return gotIndex != -1U; }
-  bool isInPlt() const { return pltIndex != -1U; }
+  bool isInGot() const { return getGotIdx() != uint32_t(-1); }
+  bool isInPlt() const { return getPltIdx() != uint32_t(-1); }
 
   uint64_t getVA(int64_t addend = 0) const;
 
@@ -219,47 +237,40 @@ public:
   // For example, if "this" is an undefined symbol and a new symbol is
   // a defined symbol, "this" is replaced with the new symbol.
   void mergeProperties(const Symbol &other);
-  void resolve(const Symbol &other);
+  void resolve(const Undefined &other);
+  void resolve(const CommonSymbol &other);
+  void resolve(const Defined &other);
+  void resolve(const LazyObject &other);
+  void resolve(const SharedSymbol &other);
 
-  // If this is a lazy symbol, fetch an input file and add the symbol
+  // If this is a lazy symbol, extract an input file and add the symbol
   // in the file to the symbol table. Calling this function on
   // non-lazy object causes a runtime error.
-  void fetch() const;
+  void extract() const;
 
-  static bool isExportDynamic(Kind k, uint8_t visibility) {
-    if (k == SharedKind)
-      return visibility == llvm::ELF::STV_DEFAULT;
-    return config->shared || config->exportDynamic;
-  }
+  void checkDuplicate(const Defined &other) const;
 
 private:
-  void resolveUndefined(const Undefined &other);
-  void resolveCommon(const CommonSymbol &other);
-  void resolveDefined(const Defined &other);
-  template <class LazyT> void resolveLazy(const LazyT &other);
-  void resolveShared(const SharedSymbol &other);
-
-  int compare(const Symbol *other) const;
-
-  inline size_t getSymbolSize() const;
+  bool shouldReplace(const Defined &other) const;
 
 protected:
-  Symbol(Kind k, InputFile *file, StringRefZ name, uint8_t binding,
+  Symbol(Kind k, InputFile *file, StringRef name, uint8_t binding,
          uint8_t stOther, uint8_t type)
-      : file(file), nameData(name.data), nameSize(name.size), binding(binding),
-        type(type), stOther(stOther), symbolKind(k), visibility(stOther & 3),
-        isUsedInRegularObj(!file || file->kind() == InputFile::ObjKind),
-        exportDynamic(isExportDynamic(k, visibility)), inDynamicList(false),
-        canInline(false), referenced(false), traced(false), gwarn(false), needsPltAddr(false),
-        isInIplt(false), gotInIgot(false), isPreemptible(false),
-        used(!config->gcSections), needsTocRestore(false),
-        scriptDefined(false) {}
+      : file(file), nameData(name.data()), nameSize(name.size()), type(type),
+        binding(binding), stOther(stOther), symbolKind(k),
+        exportDynamic(false), gwarn(false) {}
+
+  void overwrite(Symbol &sym, Kind k) const {
+    if (sym.traced)
+      printTraceSymbol(*this, sym.getName());
+    sym.file = file;
+    sym.type = type;
+    sym.binding = binding;
+    sym.stOther = (stOther & ~3) | sym.visibility();
+    sym.symbolKind = k;
+  }
 
 public:
-  // True the symbol should point to its PLT entry.
-  // For SharedSymbol only.
-  uint8_t needsPltAddr : 1;
-
   // True if this symbol is in the Iplt sub-section of the Plt and the Igot
   // sub-section of the .got.plt or .got.
   uint8_t isInIplt : 1;
@@ -268,24 +279,55 @@ public:
   // Igot. This will be true only for certain non-preemptible ifuncs.
   uint8_t gotInIgot : 1;
 
-  // True if this symbol is preemptible at load time.
-  uint8_t isPreemptible : 1;
-
-  // True if an undefined or shared symbol is used from a live section.
-  //
-  // NOTE: In Writer.cpp the field is used to mark local defined symbols
-  // which are referenced by relocations when -r or --emit-relocs is given.
-  uint8_t used : 1;
+  // True if defined relative to a section discarded by ICF.
+  uint8_t folded : 1;
 
   // True if a call to this symbol needs to be followed by a restore of the
   // PPC64 toc pointer.
   uint8_t needsTocRestore : 1;
 
-  // True if this symbol is defined by a linker script.
+  // True if this symbol is defined by a symbol assignment or wrapped by --wrap.
+  //
+  // LTO shouldn't inline the symbol because it doesn't know the final content
+  // of the symbol.
   uint8_t scriptDefined : 1;
 
-  // The partition whose dynamic symbol table contains this symbol's definition.
-  uint8_t partition = 1;
+  // True if defined in a DSO as protected visibility.
+  uint8_t dsoProtected : 1;
+
+  // Temporary flags used to communicate which symbol entries need PLT and GOT
+  // entries during postScanRelocations();
+  std::atomic<uint16_t> flags;
+
+  // A symAux index used to access GOT/PLT entry indexes. This is allocated in
+  // postScanRelocations().
+  uint32_t auxIdx;
+  uint32_t dynsymIndex;
+
+  // This field is a index to the symbol's version definition.
+  uint16_t verdefIndex;
+
+  // Version definition index.
+  uint16_t versionId;
+
+  void setFlags(uint16_t bits) {
+    flags.fetch_or(bits, std::memory_order_relaxed);
+  }
+  bool hasFlag(uint16_t bit) const {
+    assert(bit && (bit & (bit - 1)) == 0 && "bit must be a power of 2");
+    return flags.load(std::memory_order_relaxed) & bit;
+  }
+
+  bool needsDynReloc() const {
+    return flags.load(std::memory_order_relaxed) &
+           (NEEDS_COPY | NEEDS_GOT | NEEDS_PLT | NEEDS_TLSDESC | NEEDS_TLSGD |
+            NEEDS_TLSGD_TO_IE | NEEDS_GOT_DTPREL | NEEDS_TLSIE);
+  }
+  void allocateAux() {
+    assert(auxIdx == 0);
+    auxIdx = symAux.size();
+    symAux.emplace_back();
+  }
 
   bool isSection() const { return type == llvm::ELF::STT_SECTION; }
   bool isTls() const { return type == llvm::ELF::STT_TLS; }
@@ -298,10 +340,20 @@ public:
 // Represents a symbol that is defined in the current output file.
 class Defined : public Symbol {
 public:
-  Defined(InputFile *file, StringRefZ name, uint8_t binding, uint8_t stOther,
+  Defined(InputFile *file, StringRef name, uint8_t binding, uint8_t stOther,
           uint8_t type, uint64_t value, uint64_t size, SectionBase *section)
       : Symbol(DefinedKind, file, name, binding, stOther, type), value(value),
-        size(size), section(section) {}
+        size(size), section(section) {
+    exportDynamic = config->exportDynamic;
+  }
+  void overwrite(Symbol &sym) const {
+    Symbol::overwrite(sym, DefinedKind);
+    sym.verdefIndex = -1;
+    auto &s = static_cast<Defined &>(sym);
+    s.value = value;
+    s.size = size;
+    s.section = section;
+  }
 
   static bool classof(const Symbol *s) { return s->isDefined(); }
 
@@ -333,10 +385,18 @@ public:
 // section. (Therefore, the later passes don't see any CommonSymbols.)
 class CommonSymbol : public Symbol {
 public:
-  CommonSymbol(InputFile *file, StringRefZ name, uint8_t binding,
+  CommonSymbol(InputFile *file, StringRef name, uint8_t binding,
                uint8_t stOther, uint8_t type, uint64_t alignment, uint64_t size)
       : Symbol(CommonKind, file, name, binding, stOther, type),
-        alignment(alignment), size(size) {}
+        alignment(alignment), size(size) {
+    exportDynamic = config->exportDynamic;
+  }
+  void overwrite(Symbol &sym) const {
+    Symbol::overwrite(sym, CommonKind);
+    auto &s = static_cast<CommonSymbol &>(sym);
+    s.alignment = alignment;
+    s.size = size;
+  }
 
   static bool classof(const Symbol *s) { return s->isCommon(); }
 
@@ -346,15 +406,22 @@ public:
 
 class Undefined : public Symbol {
 public:
-  Undefined(InputFile *file, StringRefZ name, uint8_t binding, uint8_t stOther,
+  Undefined(InputFile *file, StringRef name, uint8_t binding, uint8_t stOther,
             uint8_t type, uint32_t discardedSecIdx = 0)
       : Symbol(UndefinedKind, file, name, binding, stOther, type),
         discardedSecIdx(discardedSecIdx) {}
+  void overwrite(Symbol &sym) const {
+    Symbol::overwrite(sym, UndefinedKind);
+    auto &s = static_cast<Undefined &>(sym);
+    s.discardedSecIdx = discardedSecIdx;
+    s.nonPrevailing = nonPrevailing;
+  }
 
   static bool classof(const Symbol *s) { return s->kind() == UndefinedKind; }
 
   // The section index if in a discarded section, 0 otherwise.
   uint32_t discardedSecIdx;
+  bool nonPrevailing = false;
 };
 
 class SharedSymbol : public Symbol {
@@ -363,10 +430,11 @@ public:
 
   SharedSymbol(InputFile &file, StringRef name, uint8_t binding,
                uint8_t stOther, uint8_t type, uint64_t value, uint64_t size,
-               uint32_t alignment, uint32_t verdefIndex)
+               uint32_t alignment)
       : Symbol(SharedKind, &file, name, binding, stOther, type), value(value),
         size(size), alignment(alignment) {
-    this->verdefIndex = verdefIndex;
+    exportDynamic = true;
+    dsoProtected = visibility() == llvm::ELF::STV_PROTECTED;
     // GNU ifunc is a mechanism to allow user-supplied functions to
     // resolve PLT slot values at load-time. This is contrary to the
     // regular symbol resolution scheme in which symbols are resolved just
@@ -386,49 +454,35 @@ public:
     if (this->type == llvm::ELF::STT_GNU_IFUNC)
       this->type = llvm::ELF::STT_FUNC;
   }
-
-  SharedFile &getFile() const { return *cast<SharedFile>(file); }
+  void overwrite(Symbol &sym) const {
+    Symbol::overwrite(sym, SharedKind);
+    auto &s = static_cast<SharedSymbol &>(sym);
+    s.dsoProtected = dsoProtected;
+    s.value = value;
+    s.size = size;
+    s.alignment = alignment;
+  }
 
   uint64_t value; // st_value
   uint64_t size;  // st_size
   uint32_t alignment;
 };
 
-// LazyArchive and LazyObject represent a symbols that is not yet in the link,
-// but we know where to find it if needed. If the resolver finds both Undefined
-// and Lazy for the same name, it will ask the Lazy to load a file.
+// LazyObject symbols represent symbols in object files between --start-lib and
+// --end-lib options. LLD also handles traditional archives as if all the files
+// in the archive are surrounded by --start-lib and --end-lib.
 //
 // A special complication is the handling of weak undefined symbols. They should
 // not load a file, but we have to remember we have seen both the weak undefined
 // and the lazy. We represent that with a lazy symbol with a weak binding. This
 // means that code looking for undefined symbols normally also has to take lazy
 // symbols into consideration.
-
-// This class represents a symbol defined in an archive file. It is
-// created from an archive file header, and it knows how to load an
-// object file from an archive to replace itself with a defined
-// symbol.
-class LazyArchive : public Symbol {
-public:
-  LazyArchive(InputFile &file, const llvm::object::Archive::Symbol s)
-      : Symbol(LazyArchiveKind, &file, s.getName(), llvm::ELF::STB_GLOBAL,
-               llvm::ELF::STV_DEFAULT, llvm::ELF::STT_NOTYPE),
-        sym(s) {}
-
-  static bool classof(const Symbol *s) { return s->kind() == LazyArchiveKind; }
-
-  MemoryBufferRef getMemberBuffer();
-
-  const llvm::object::Archive::Symbol sym;
-};
-
-// LazyObject symbols represents symbols in object files between
-// --start-lib and --end-lib options.
 class LazyObject : public Symbol {
 public:
-  LazyObject(InputFile &file, StringRef name)
-      : Symbol(LazyObjectKind, &file, name, llvm::ELF::STB_GLOBAL,
+  LazyObject(InputFile &file)
+      : Symbol(LazyObjectKind, &file, {}, llvm::ELF::STB_GLOBAL,
                llvm::ELF::STV_DEFAULT, llvm::ELF::STT_NOTYPE) {}
+  void overwrite(Symbol &sym) const { Symbol::overwrite(sym, LazyObjectKind); }
 
   static bool classof(const Symbol *s) { return s->kind() == LazyObjectKind; }
 };
@@ -468,9 +522,6 @@ struct ElfSym {
   static Defined *relaIpltStart;
   static Defined *relaIpltEnd;
 
-  // __global_pointer$ for RISC-V.
-  static Defined *riscvGlobalPointer;
-
   // _TLS_MODULE_BASE_ on targets that support TLSDESC.
   static Defined *tlsModuleBase;
 };
@@ -478,119 +529,32 @@ struct ElfSym {
 // A buffer class that is large enough to hold any Symbol-derived
 // object. We allocate memory using this class and instantiate a symbol
 // using the placement new.
+
+// It is important to keep the size of SymbolUnion small for performance and
+// memory usage reasons. 64 bytes is a soft limit based on the size of Defined
+// on a 64-bit system. This is enforced by a static_assert in Symbols.cpp.
 union SymbolUnion {
   alignas(Defined) char a[sizeof(Defined)];
   alignas(CommonSymbol) char b[sizeof(CommonSymbol)];
   alignas(Undefined) char c[sizeof(Undefined)];
   alignas(SharedSymbol) char d[sizeof(SharedSymbol)];
-  alignas(LazyArchive) char e[sizeof(LazyArchive)];
-  alignas(LazyObject) char f[sizeof(LazyObject)];
-};
-
-// It is important to keep the size of SymbolUnion small for performance and
-// memory usage reasons. 80 bytes is a soft limit based on the size of Defined
-// on a 64-bit system.
-static_assert(sizeof(SymbolUnion) <= 80, "SymbolUnion too large");
-
-template <typename T> struct AssertSymbol {
-  static_assert(std::is_trivially_destructible<T>(),
-                "Symbol types must be trivially destructible");
-  static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
-  static_assert(alignof(T) <= alignof(SymbolUnion),
-                "SymbolUnion not aligned enough");
+  alignas(LazyObject) char e[sizeof(LazyObject)];
 };
 
-static inline void assertSymbols() {
-  AssertSymbol<Defined>();
-  AssertSymbol<CommonSymbol>();
-  AssertSymbol<Undefined>();
-  AssertSymbol<SharedSymbol>();
-  AssertSymbol<LazyArchive>();
-  AssertSymbol<LazyObject>();
-}
-
-void printTraceSymbol(const Symbol *sym);
-
-size_t Symbol::getSymbolSize() const {
-  switch (kind()) {
-  case CommonKind:
-    return sizeof(CommonSymbol);
-  case DefinedKind:
-    return sizeof(Defined);
-  case LazyArchiveKind:
-    return sizeof(LazyArchive);
-  case LazyObjectKind:
-    return sizeof(LazyObject);
-  case SharedKind:
-    return sizeof(SharedSymbol);
-  case UndefinedKind:
-    return sizeof(Undefined);
-  case PlaceholderKind:
-    return sizeof(Symbol);
-  }
-  llvm_unreachable("unknown symbol kind");
-}
-
-// replace() replaces "this" object with a given symbol by memcpy'ing
-// it over to "this". This function is called as a result of name
-// resolution, e.g. to replace an undefind symbol with a defined symbol.
-void Symbol::replace(const Symbol &newSym) {
-  using llvm::ELF::STT_TLS;
-
-  // st_value of STT_TLS represents the assigned offset, not the actual address
-  // which is used by STT_FUNC and STT_OBJECT. STT_TLS symbols can only be
-  // referenced by special TLS relocations. It is usually an error if a STT_TLS
-  // symbol is replaced by a non-STT_TLS symbol, vice versa. There are two
-  // exceptions: (a) a STT_NOTYPE lazy/undefined symbol can be replaced by a
-  // STT_TLS symbol, (b) a STT_TLS undefined symbol can be replaced by a
-  // STT_NOTYPE lazy symbol.
-  if (symbolKind != PlaceholderKind && !newSym.isLazy() &&
-      (type == STT_TLS) != (newSym.type == STT_TLS) &&
-      type != llvm::ELF::STT_NOTYPE)
-    error("TLS attribute mismatch: " + toString(*this) + "\n>>> defined in " +
-          toString(newSym.file) + "\n>>> defined in " + toString(file));
-
-  Symbol old = *this;
-  memcpy(this, &newSym, newSym.getSymbolSize());
-
-  // old may be a placeholder. The referenced fields must be initialized in
-  // SymbolTable::insert.
-  versionId = old.versionId;
-  visibility = old.visibility;
-  isUsedInRegularObj = old.isUsedInRegularObj;
-  exportDynamic = old.exportDynamic;
-  inDynamicList = old.inDynamicList;
-  canInline = old.canInline;
-  referenced = old.referenced;
-  traced = old.traced;
-  gwarn = old.gwarn;
-  isPreemptible = old.isPreemptible;
-  scriptDefined = old.scriptDefined;
-  partition = old.partition;
-
-  // Symbol length is computed lazily. If we already know a symbol length,
-  // propagate it.
-  if (nameData == old.nameData && nameSize == 0 && old.nameSize != 0)
-    nameSize = old.nameSize;
-
-  // Print out a log message if --trace-symbol was specified.
-  // This is for debugging.
-  if (traced)
-    printTraceSymbol(this);
+template <typename... T> Defined *makeDefined(T &&...args) {
+  auto *sym = getSpecificAllocSingleton<SymbolUnion>().Allocate();
+  memset(sym, 0, sizeof(Symbol));
+  auto &s = *new (reinterpret_cast<Defined *>(sym)) Defined(std::forward<T>(args)...);
+  return &s;
 }
 
+void reportDuplicate(const Symbol &sym, const InputFile *newFile,
+                     InputSectionBase *errSec, uint64_t errOffset);
 void maybeWarnUnorderableSymbol(const Symbol *sym);
 bool computeIsPreemptible(const Symbol &sym);
-void reportBackrefs();
 
 extern llvm::DenseMap<StringRef, StringRef> gnuWarnings;
 
-// A mapping from a symbol to an InputFile referencing it backward. Used by
-// --warn-backrefs.
-extern llvm::DenseMap<const Symbol *,
-                      std::pair<const InputFile *, const InputFile *>>
-    backwardReferences;
-
 } // namespace elf
 } // namespace lld
 
index 32248aa..e7c437b 100644 (file)
 
 #include "SyntheticSections.h"
 #include "Config.h"
+#include "DWARF.h"
+#include "EhFrame.h"
 #include "InputFiles.h"
 #include "LinkerScript.h"
 #include "OutputSections.h"
 #include "SymbolTable.h"
 #include "Symbols.h"
 #include "Target.h"
+#include "Thunks.h"
 #include "Writer.h"
+#include "lld/Common/CommonLinkerContext.h"
 #include "lld/Common/DWARF.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/Memory.h"
 #include "lld/Common/Strings.h"
 #include "lld/Common/Version.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SetOperations.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/BinaryFormat/ELF.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
-#include "llvm/Object/ELFObjectFile.h"
-#include "llvm/Support/Compression.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/LEB128.h"
-#include "llvm/Support/MD5.h"
 #include "llvm/Support/Parallel.h"
 #include "llvm/Support/TimeProfiler.h"
 #include <cstdlib>
-#include <thread>
 
 using namespace llvm;
 using namespace llvm::dwarf;
@@ -73,7 +73,7 @@ static ArrayRef<uint8_t> getVersion() {
   // This is only for testing.
   StringRef s = getenv("LLD_VERSION");
   if (s.empty())
-    s = saver.save(Twine("Linker: ") + getLLDVersion());
+    s = saver().save(Twine("Linker: ") + getLLDVersion());
 
   // +1 to include the terminating '\0'.
   return {(const uint8_t *)s.data(), s.size() + 1};
@@ -84,8 +84,10 @@ static ArrayRef<uint8_t> getVersion() {
 // by "readelf --string-dump .comment <file>".
 // The returned object is a mergeable string section.
 MergeInputSection *elf::createCommentSection() {
-  return make<MergeInputSection>(SHF_MERGE | SHF_STRINGS, SHT_PROGBITS, 1,
-                                 getVersion(), ".comment");
+  auto *sec = make<MergeInputSection>(SHF_MERGE | SHF_STRINGS, SHT_PROGBITS, 1,
+                                      getVersion(), ".comment");
+  sec->splitIntoPieces();
+  return sec;
 }
 
 // .MIPS.abiflags section.
@@ -101,18 +103,18 @@ template <class ELFT> void MipsAbiFlagsSection<ELFT>::writeTo(uint8_t *buf) {
 }
 
 template <class ELFT>
-MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() {
+std::unique_ptr<MipsAbiFlagsSection<ELFT>> MipsAbiFlagsSection<ELFT>::create() {
   Elf_Mips_ABIFlags flags = {};
   bool create = false;
 
-  for (InputSectionBase *sec : inputSections) {
+  for (InputSectionBase *sec : ctx.inputSections) {
     if (sec->type != SHT_MIPS_ABIFLAGS)
       continue;
     sec->markDead();
     create = true;
 
     std::string filename = toString(sec->file);
-    const size_t size = sec->data().size();
+    const size_t size = sec->content().size();
     // Older version of BFD (such as the default FreeBSD linker) concatenate
     // .MIPS.abiflags instead of merging. To allow for this case (or potential
     // zero padding) we ignore everything after the first Elf_Mips_ABIFlags
@@ -121,7 +123,8 @@ MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() {
             Twine(size) + " instead of " + Twine(sizeof(Elf_Mips_ABIFlags)));
       return nullptr;
     }
-    auto *s = reinterpret_cast<const Elf_Mips_ABIFlags *>(sec->data().data());
+    auto *s =
+        reinterpret_cast<const Elf_Mips_ABIFlags *>(sec->content().data());
     if (s->version != 0) {
       error(filename + ": unexpected .MIPS.abiflags version " +
             Twine(s->version));
@@ -143,7 +146,7 @@ MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() {
   };
 
   if (create)
-    return make<MipsAbiFlagsSection<ELFT>>(flags);
+    return std::make_unique<MipsAbiFlagsSection<ELFT>>(flags);
   return nullptr;
 }
 
@@ -166,13 +169,13 @@ template <class ELFT> void MipsOptionsSection<ELFT>::writeTo(uint8_t *buf) {
 }
 
 template <class ELFT>
-MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() {
+std::unique_ptr<MipsOptionsSection<ELFT>> MipsOptionsSection<ELFT>::create() {
   // N64 ABI only.
   if (!ELFT::Is64Bits)
     return nullptr;
 
-  std::vector<InputSectionBase *> sections;
-  for (InputSectionBase *sec : inputSections)
+  SmallVector<InputSectionBase *, 0> sections;
+  for (InputSectionBase *sec : ctx.inputSections)
     if (sec->type == SHT_MIPS_OPTIONS)
       sections.push_back(sec);
 
@@ -184,7 +187,7 @@ MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() {
     sec->markDead();
 
     std::string filename = toString(sec->file);
-    ArrayRef<uint8_t> d = sec->data();
+    ArrayRef<uint8_t> d = sec->content();
 
     while (!d.empty()) {
       if (d.size() < sizeof(Elf_Mips_Options)) {
@@ -205,7 +208,7 @@ MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() {
     }
   };
 
-  return make<MipsOptionsSection<ELFT>>(reginfo);
+  return std::make_unique<MipsOptionsSection<ELFT>>(reginfo);
 }
 
 // MIPS .reginfo section.
@@ -223,13 +226,13 @@ template <class ELFT> void MipsReginfoSection<ELFT>::writeTo(uint8_t *buf) {
 }
 
 template <class ELFT>
-MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() {
+std::unique_ptr<MipsReginfoSection<ELFT>> MipsReginfoSection<ELFT>::create() {
   // Section should be alive for O32 and N32 ABIs only.
   if (ELFT::Is64Bits)
     return nullptr;
 
-  std::vector<InputSectionBase *> sections;
-  for (InputSectionBase *sec : inputSections)
+  SmallVector<InputSectionBase *, 0> sections;
+  for (InputSectionBase *sec : ctx.inputSections)
     if (sec->type == SHT_MIPS_REGINFO)
       sections.push_back(sec);
 
@@ -240,22 +243,22 @@ MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() {
   for (InputSectionBase *sec : sections) {
     sec->markDead();
 
-    if (sec->data().size() != sizeof(Elf_Mips_RegInfo)) {
+    if (sec->content().size() != sizeof(Elf_Mips_RegInfo)) {
       error(toString(sec->file) + ": invalid size of .reginfo section");
       return nullptr;
     }
 
-    auto *r = reinterpret_cast<const Elf_Mips_RegInfo *>(sec->data().data());
+    auto *r = reinterpret_cast<const Elf_Mips_RegInfo *>(sec->content().data());
     reginfo.ri_gprmask |= r->ri_gprmask;
     sec->getFile<ELFT>()->mipsGp0 = r->ri_gp_value;
   };
 
-  return make<MipsReginfoSection<ELFT>>(reginfo);
+  return std::make_unique<MipsReginfoSection<ELFT>>(reginfo);
 }
 
 InputSection *elf::createInterpSection() {
   // StringSaver guarantees that the returned string ends with '\0'.
-  StringRef s = saver.save(config->dynamicLinker);
+  StringRef s = saver().save(config->dynamicLinker);
   ArrayRef<uint8_t> contents = {(const uint8_t *)s.data(), s.size() + 1};
 
   return make<InputSection>(nullptr, SHF_ALLOC, SHT_PROGBITS, 1, contents,
@@ -264,8 +267,8 @@ InputSection *elf::createInterpSection() {
 
 Defined *elf::addSyntheticLocal(StringRef name, uint8_t type, uint64_t value,
                                 uint64_t size, InputSectionBase &section) {
-  auto *s = make<Defined>(section.file, name, STB_LOCAL, STV_DEFAULT, type,
-                          value, size, &section);
+  Defined *s = makeDefined(section.file, name, STB_LOCAL, STV_DEFAULT, type,
+                           value, size, &section);
   if (in.symTab)
     in.symTab->addSymbol(s);
   return s;
@@ -391,7 +394,7 @@ Defined *EhFrameSection::isFdeLive(EhSectionPiece &fde, ArrayRef<RelTy> rels) {
   // FDEs for garbage-collected or merged-by-ICF sections, or sections in
   // another partition, are dead.
   if (auto *d = dyn_cast<Defined>(&b))
-    if (d->section && d->section->partition == partition)
+    if (!d->folded && d->section && d->section->partition == partition)
       return d;
   return nullptr;
 }
@@ -403,26 +406,17 @@ Defined *EhFrameSection::isFdeLive(EhSectionPiece &fde, ArrayRef<RelTy> rels) {
 template <class ELFT, class RelTy>
 void EhFrameSection::addRecords(EhInputSection *sec, ArrayRef<RelTy> rels) {
   offsetToCie.clear();
-  for (EhSectionPiece &piece : sec->pieces) {
-    // The empty record is the end marker.
-    if (piece.size == 4)
-      return;
-
-    size_t offset = piece.inputOff;
-    uint32_t id = read32(piece.data().data() + 4);
-    if (id == 0) {
-      offsetToCie[offset] = addCie<ELFT>(piece, rels);
-      continue;
-    }
-
-    uint32_t cieOffset = offset + 4 - id;
-    CieRecord *rec = offsetToCie[cieOffset];
+  for (EhSectionPiece &cie : sec->cies)
+    offsetToCie[cie.inputOff] = addCie<ELFT>(cie, rels);
+  for (EhSectionPiece &fde : sec->fdes) {
+    uint32_t id = endian::read32<ELFT::TargetEndianness>(fde.data().data() + 4);
+    CieRecord *rec = offsetToCie[fde.inputOff + 4 - id];
     if (!rec)
       fatal(toString(sec) + ": invalid CIE reference");
 
-    if (!isFdeLive<ELFT>(piece, rels))
+    if (!isFdeLive<ELFT>(fde, rels))
       continue;
-    rec->fdes.push_back(&piece);
+    rec->fdes.push_back(&fde);
     numFdes++;
   }
 }
@@ -431,20 +425,11 @@ template <class ELFT>
 void EhFrameSection::addSectionAux(EhInputSection *sec) {
   if (!sec->isLive())
     return;
-  if (sec->areRelocsRela)
-    addRecords<ELFT>(sec, sec->template relas<ELFT>());
+  const RelsOrRelas<ELFT> rels = sec->template relsOrRelas<ELFT>();
+  if (rels.areRelocsRel())
+    addRecords<ELFT>(sec, rels.rels);
   else
-    addRecords<ELFT>(sec, sec->template rels<ELFT>());
-}
-
-void EhFrameSection::addSection(EhInputSection *sec) {
-  sec->parent = this;
-
-  alignment = std::max(alignment, sec->alignment);
-  sections.push_back(sec);
-
-  for (auto *ds : sec->dependentSections)
-    dependentSections.push_back(ds);
+    addRecords<ELFT>(sec, rels.relas);
 }
 
 // Used by ICF<ELFT>::handleLSDA(). This function is very similar to
@@ -453,25 +438,16 @@ template <class ELFT, class RelTy>
 void EhFrameSection::iterateFDEWithLSDAAux(
     EhInputSection &sec, ArrayRef<RelTy> rels, DenseSet<size_t> &ciesWithLSDA,
     llvm::function_ref<void(InputSection &)> fn) {
-  for (EhSectionPiece &piece : sec.pieces) {
-    // Skip ZERO terminator.
-    if (piece.size == 4)
-      continue;
-
-    size_t offset = piece.inputOff;
-    uint32_t id =
-        endian::read32<ELFT::TargetEndianness>(piece.data().data() + 4);
-    if (id == 0) {
-      if (hasLSDA(piece))
-        ciesWithLSDA.insert(offset);
-      continue;
-    }
-    uint32_t cieOffset = offset + 4 - id;
-    if (ciesWithLSDA.count(cieOffset) == 0)
+  for (EhSectionPiece &cie : sec.cies)
+    if (hasLSDA(cie))
+      ciesWithLSDA.insert(cie.inputOff);
+  for (EhSectionPiece &fde : sec.fdes) {
+    uint32_t id = endian::read32<ELFT::TargetEndianness>(fde.data().data() + 4);
+    if (!ciesWithLSDA.contains(fde.inputOff + 4 - id))
       continue;
 
     // The CIE has a LSDA argument. Call fn with d's section.
-    if (Defined *d = isFdeLive<ELFT>(piece, rels))
+    if (Defined *d = isFdeLive<ELFT>(fde, rels))
       if (auto *s = dyn_cast_or_null<InputSection>(d->section))
         fn(*s);
   }
@@ -483,25 +459,18 @@ void EhFrameSection::iterateFDEWithLSDA(
   DenseSet<size_t> ciesWithLSDA;
   for (EhInputSection *sec : sections) {
     ciesWithLSDA.clear();
-    if (sec->areRelocsRela)
-      iterateFDEWithLSDAAux<ELFT>(*sec, sec->template relas<ELFT>(),
-                                  ciesWithLSDA, fn);
+    const RelsOrRelas<ELFT> rels = sec->template relsOrRelas<ELFT>();
+    if (rels.areRelocsRel())
+      iterateFDEWithLSDAAux<ELFT>(*sec, rels.rels, ciesWithLSDA, fn);
     else
-      iterateFDEWithLSDAAux<ELFT>(*sec, sec->template rels<ELFT>(),
-                                  ciesWithLSDA, fn);
+      iterateFDEWithLSDAAux<ELFT>(*sec, rels.relas, ciesWithLSDA, fn);
   }
 }
 
 static void writeCieFde(uint8_t *buf, ArrayRef<uint8_t> d) {
   memcpy(buf, d.data(), d.size());
-
-  size_t aligned = alignTo(d.size(), config->wordsize);
-
-  // Zero-clear trailing padding if it exists.
-  memset(buf + d.size(), 0, aligned - d.size());
-
   // Fix the size field. -4 since size does not include the size field itself.
-  write32(buf, aligned - 4);
+  write32(buf, d.size() - 4);
 }
 
 void EhFrameSection::finalizeContents() {
@@ -531,11 +500,11 @@ void EhFrameSection::finalizeContents() {
   size_t off = 0;
   for (CieRecord *rec : cieRecords) {
     rec->cie->outputOff = off;
-    off += alignTo(rec->cie->size, config->wordsize);
+    off += rec->cie->size;
 
     for (EhSectionPiece *fde : rec->fdes) {
       fde->outputOff = off;
-      off += alignTo(fde->size, config->wordsize);
+      off += fde->size;
     }
   }
 
@@ -551,9 +520,9 @@ void EhFrameSection::finalizeContents() {
 // Returns data for .eh_frame_hdr. .eh_frame_hdr is a binary search table
 // to get an FDE from an address to which FDE is applied. This function
 // returns a list of such pairs.
-std::vector<EhFrameSection::FdeData> EhFrameSection::getFdeData() const {
+SmallVector<EhFrameSection::FdeData, 0> EhFrameSection::getFdeData() const {
   uint8_t *buf = Out::bufferStart + getParent()->offset + outSecOff;
-  std::vector<FdeData> ret;
+  SmallVector<FdeData, 0> ret;
 
   uint64_t va = getPartition().ehFrameHdr->getVA();
   for (CieRecord *rec : cieRecords) {
@@ -637,7 +606,7 @@ void EhFrameSection::writeTo(uint8_t *buf) {
   // in the output buffer, but relocateAlloc() still works because
   // getOffset() takes care of discontiguous section pieces.
   for (EhInputSection *s : sections)
-    s->relocateAlloc(buf, nullptr);
+    target->relocateAlloc(*s, buf);
 
   if (getPartition().ehFrameHdr && getPartition().ehFrameHdr->getParent())
     getPartition().ehFrameHdr->write();
@@ -649,15 +618,22 @@ GotSection::GotSection()
   numEntries = target->gotHeaderEntriesNum;
 }
 
+void GotSection::addConstant(const Relocation &r) { relocations.push_back(r); }
 void GotSection::addEntry(Symbol &sym) {
-  sym.gotIndex = numEntries;
-  ++numEntries;
+  assert(sym.auxIdx == symAux.size() - 1);
+  symAux.back().gotIdx = numEntries++;
+}
+
+bool GotSection::addTlsDescEntry(Symbol &sym) {
+  assert(sym.auxIdx == symAux.size() - 1);
+  symAux.back().tlsDescIdx = numEntries;
+  numEntries += 2;
+  return true;
 }
 
 bool GotSection::addDynTlsEntry(Symbol &sym) {
-  if (sym.globalDynIndex != -1U)
-    return false;
-  sym.globalDynIndex = numEntries;
+  assert(sym.auxIdx == symAux.size() - 1);
+  symAux.back().tlsGdIdx = numEntries;
   // Global Dynamic TLS entries take two GOT slots.
   numEntries += 2;
   return true;
@@ -673,12 +649,20 @@ bool GotSection::addTlsIndex() {
   return true;
 }
 
+uint32_t GotSection::getTlsDescOffset(const Symbol &sym) const {
+  return sym.getTlsDescIdx() * config->wordsize;
+}
+
+uint64_t GotSection::getTlsDescAddr(const Symbol &sym) const {
+  return getVA() + getTlsDescOffset(sym);
+}
+
 uint64_t GotSection::getGlobalDynAddr(const Symbol &b) const {
-  return this->getVA() + b.globalDynIndex * config->wordsize;
+  return this->getVA() + b.getTlsGdIdx() * config->wordsize;
 }
 
 uint64_t GotSection::getGlobalDynOffset(const Symbol &b) const {
-  return b.globalDynIndex * config->wordsize;
+  return b.getTlsGdIdx() * config->wordsize;
 }
 
 void GotSection::finalizeContents() {
@@ -696,8 +680,11 @@ bool GotSection::isNeeded() const {
 }
 
 void GotSection::writeTo(uint8_t *buf) {
+  // On PPC64 .got may be needed but empty. Skip the write.
+  if (size == 0)
+    return;
   target->writeGotHeader(buf);
-  relocateAlloc(buf, buf + size);
+  target->relocateAlloc(*this, buf);
 }
 
 static uint64_t getMipsPageAddr(uint64_t addr) {
@@ -763,18 +750,18 @@ size_t MipsGotSection::FileGot::getIndexedEntriesNum() const {
 }
 
 MipsGotSection::FileGot &MipsGotSection::getGot(InputFile &f) {
-  if (!f.mipsGotIndex.hasValue()) {
+  if (f.mipsGotIndex == uint32_t(-1)) {
     gots.emplace_back();
     gots.back().file = &f;
     f.mipsGotIndex = gots.size() - 1;
   }
-  return gots[*f.mipsGotIndex];
+  return gots[f.mipsGotIndex];
 }
 
 uint64_t MipsGotSection::getPageEntryOffset(const InputFile *f,
                                             const Symbol &sym,
                                             int64_t addend) const {
-  const FileGot &g = gots[*f->mipsGotIndex];
+  const FileGot &g = gots[f->mipsGotIndex];
   uint64_t index = 0;
   if (const OutputSection *outSec = sym.getOutputSection()) {
     uint64_t secAddr = getMipsPageAddr(outSec->addr);
@@ -788,7 +775,7 @@ uint64_t MipsGotSection::getPageEntryOffset(const InputFile *f,
 
 uint64_t MipsGotSection::getSymEntryOffset(const InputFile *f, const Symbol &s,
                                            int64_t addend) const {
-  const FileGot &g = gots[*f->mipsGotIndex];
+  const FileGot &g = gots[f->mipsGotIndex];
   Symbol *sym = const_cast<Symbol *>(&s);
   if (sym->isTls())
     return g.tls.lookup(sym) * config->wordsize;
@@ -798,13 +785,13 @@ uint64_t MipsGotSection::getSymEntryOffset(const InputFile *f, const Symbol &s,
 }
 
 uint64_t MipsGotSection::getTlsIndexOffset(const InputFile *f) const {
-  const FileGot &g = gots[*f->mipsGotIndex];
+  const FileGot &g = gots[f->mipsGotIndex];
   return g.dynTlsSymbols.lookup(nullptr) * config->wordsize;
 }
 
 uint64_t MipsGotSection::getGlobalDynOffset(const InputFile *f,
                                             const Symbol &s) const {
-  const FileGot &g = gots[*f->mipsGotIndex];
+  const FileGot &g = gots[f->mipsGotIndex];
   Symbol *sym = const_cast<Symbol *>(&s);
   return g.dynTlsSymbols.lookup(sym) * config->wordsize;
 }
@@ -900,10 +887,10 @@ void MipsGotSection::build() {
          got.pagesMap) {
       const OutputSection *os = p.first;
       uint64_t secSize = 0;
-      for (BaseCommand *cmd : os->sectionCommands) {
+      for (SectionCommand *cmd : os->commands) {
         if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
           for (InputSection *isec : isd->sections) {
-            uint64_t off = alignTo(secSize, isec->alignment);
+            uint64_t off = alignToPowerOf2(secSize, isec->addralign);
             secSize = off + isec->getSize();
           }
       }
@@ -972,12 +959,18 @@ void MipsGotSection::build() {
     }
   }
 
-  // Update Symbol::gotIndex field to use this
+  // Update SymbolAux::gotIdx field to use this
   // value later in the `sortMipsSymbols` function.
-  for (auto &p : primGot->global)
-    p.first->gotIndex = p.second;
-  for (auto &p : primGot->relocs)
-    p.first->gotIndex = p.second;
+  for (auto &p : primGot->global) {
+    if (p.first->auxIdx == 0)
+      p.first->allocateAux();
+    symAux.back().gotIdx = p.second;
+  }
+  for (auto &p : primGot->relocs) {
+    if (p.first->auxIdx == 0)
+      p.first->allocateAux();
+    symAux.back().gotIdx = p.second;
+  }
 
   // Create dynamic relocations.
   for (FileGot &got : gots) {
@@ -1007,14 +1000,14 @@ void MipsGotSection::build() {
         // thread-locals that have been marked as local through a linker script)
         if (!s->isPreemptible && !config->shared)
           continue;
-        mainPart->relaDyn->addSymbolReloc(target->tlsModuleIndexRel, this,
+        mainPart->relaDyn->addSymbolReloc(target->tlsModuleIndexRel, *this,
                                           offset, *s);
         // However, we can skip writing the TLS offset reloc for non-preemptible
         // symbols since it is known even in shared libraries
         if (!s->isPreemptible)
           continue;
         offset += config->wordsize;
-        mainPart->relaDyn->addSymbolReloc(target->tlsOffsetRel, this, offset,
+        mainPart->relaDyn->addSymbolReloc(target->tlsOffsetRel, *this, offset,
                                           *s);
       }
     }
@@ -1027,7 +1020,7 @@ void MipsGotSection::build() {
     // Dynamic relocations for "global" entries.
     for (const std::pair<Symbol *, size_t> &p : got.global) {
       uint64_t offset = p.second * config->wordsize;
-      mainPart->relaDyn->addSymbolReloc(target->relativeRel, this, offset,
+      mainPart->relaDyn->addSymbolReloc(target->relativeRel, *this, offset,
                                         *p.first);
     }
     if (!config->isPic)
@@ -1061,10 +1054,9 @@ uint64_t MipsGotSection::getGp(const InputFile *f) const {
   // For files without related GOT or files refer a primary GOT
   // returns "common" _gp value. For secondary GOTs calculate
   // individual _gp values.
-  if (!f || !f->mipsGotIndex.hasValue() || *f->mipsGotIndex == 0)
+  if (!f || f->mipsGotIndex == uint32_t(-1) || f->mipsGotIndex == 0)
     return ElfSym::mipsGp->getVA(0);
-  return getVA() + gots[*f->mipsGotIndex].startIndex * config->wordsize +
-         0x7ff0;
+  return getVA() + gots[f->mipsGotIndex].startIndex * config->wordsize + 0x7ff0;
 }
 
 void MipsGotSection::writeTo(uint8_t *buf) {
@@ -1119,7 +1111,7 @@ void MipsGotSection::writeTo(uint8_t *buf) {
       if (p.first == nullptr && !config->shared)
         write(p.second, nullptr, 1);
       else if (p.first && !p.first->isPreemptible) {
-        // If we are emitting a shared libary with relocations we mustn't write
+        // If we are emitting a shared library with relocations we mustn't write
         // anything to the GOT here. When using Elf_Rel relocations the value
         // one will be treated as an addend and will cause crashes at runtime
         if (!config->shared)
@@ -1146,7 +1138,8 @@ GotPltSection::GotPltSection()
 }
 
 void GotPltSection::addEntry(Symbol &sym) {
-  assert(sym.pltIndex == entries.size());
+  assert(sym.auxIdx == symAux.size() - 1 &&
+         symAux.back().pltIdx == entries.size());
   entries.push_back(&sym);
 }
 
@@ -1191,7 +1184,7 @@ IgotPltSection::IgotPltSection()
                        target->gotEntrySize, getIgotPltName()) {}
 
 void IgotPltSection::addEntry(Symbol &sym) {
-  assert(sym.pltIndex == entries.size());
+  assert(symAux.back().pltIdx == entries.size());
   entries.push_back(&sym);
 }
 
@@ -1210,7 +1203,9 @@ StringTableSection::StringTableSection(StringRef name, bool dynamic)
     : SyntheticSection(dynamic ? (uint64_t)SHF_ALLOC : 0, SHT_STRTAB, 1, name),
       dynamic(dynamic) {
   // ELF string tables start with a NUL byte.
-  addString("");
+  strings.push_back("");
+  stringMap.try_emplace(CachedHashStringRef(""), 0);
+  size = 1;
 }
 
 // Adds a string to the string table. If `hashIt` is true we hash and check for
@@ -1219,10 +1214,12 @@ StringTableSection::StringTableSection(StringRef name, bool dynamic)
 // them with some other string that happens to be the same.
 unsigned StringTableSection::addString(StringRef s, bool hashIt) {
   if (hashIt) {
-    auto r = stringMap.insert(std::make_pair(s, this->size));
+    auto r = stringMap.try_emplace(CachedHashStringRef(s), size);
     if (!r.second)
       return r.first->second;
   }
+  if (s.empty())
+    return 0;
   unsigned ret = this->size;
   this->size = this->size + s.size() + 1;
   strings.push_back(s);
@@ -1258,43 +1255,6 @@ DynamicSection<ELFT>::DynamicSection()
     this->flags = SHF_ALLOC;
 }
 
-template <class ELFT>
-void DynamicSection<ELFT>::add(int32_t tag, std::function<uint64_t()> fn) {
-  entries.push_back({tag, fn});
-}
-
-template <class ELFT>
-void DynamicSection<ELFT>::addInt(int32_t tag, uint64_t val) {
-  entries.push_back({tag, [=] { return val; }});
-}
-
-template <class ELFT>
-void DynamicSection<ELFT>::addInSec(int32_t tag, InputSection *sec) {
-  entries.push_back({tag, [=] { return sec->getVA(0); }});
-}
-
-template <class ELFT>
-void DynamicSection<ELFT>::addInSecRelative(int32_t tag, InputSection *sec) {
-  size_t tagOffset = entries.size() * entsize;
-  entries.push_back(
-      {tag, [=] { return sec->getVA(0) - (getVA() + tagOffset); }});
-}
-
-template <class ELFT>
-void DynamicSection<ELFT>::addOutSec(int32_t tag, OutputSection *sec) {
-  entries.push_back({tag, [=] { return sec->addr; }});
-}
-
-template <class ELFT>
-void DynamicSection<ELFT>::addSize(int32_t tag, OutputSection *sec) {
-  entries.push_back({tag, [=] { return sec->size; }});
-}
-
-template <class ELFT>
-void DynamicSection<ELFT>::addSym(int32_t tag, Symbol *sym) {
-  entries.push_back({tag, [=] { return sym->getVA(); }});
-}
-
 // The output section .rela.dyn may include these synthetic sections:
 //
 // - part.relaDyn
@@ -1303,15 +1263,13 @@ void DynamicSection<ELFT>::addSym(int32_t tag, Symbol *sym) {
 //   .rela.dyn
 //
 // DT_RELASZ is the total size of the included sections.
-static std::function<uint64_t()> addRelaSz(RelocationBaseSection *relaDyn) {
-  return [=]() {
-    size_t size = relaDyn->getSize();
-    if (in.relaIplt->getParent() == relaDyn->getParent())
-      size += in.relaIplt->getSize();
-    if (in.relaPlt->getParent() == relaDyn->getParent())
-      size += in.relaPlt->getSize();
-    return size;
-  };
+static uint64_t addRelaSz(const RelocationBaseSection &relaDyn) {
+  size_t size = relaDyn.getSize();
+  if (in.relaIplt->getParent() == relaDyn.getParent())
+    size += in.relaIplt->getSize();
+  if (in.relaPlt->getParent() == relaDyn.getParent())
+    size += in.relaPlt->getSize();
+  return size;
 }
 
 // A Linker script may assign the RELA relocation sections to the same
@@ -1327,9 +1285,19 @@ static uint64_t addPltRelSz() {
 }
 
 // Add remaining entries to complete .dynamic contents.
-template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
+template <class ELFT>
+std::vector<std::pair<int32_t, uint64_t>>
+DynamicSection<ELFT>::computeContents() {
   elf::Partition &part = getPartition();
   bool isMain = part.name.empty();
+  std::vector<std::pair<int32_t, uint64_t>> entries;
+
+  auto addInt = [&](int32_t tag, uint64_t val) {
+    entries.emplace_back(tag, val);
+  };
+  auto addInSec = [&](int32_t tag, const InputSection &sec) {
+    entries.emplace_back(tag, sec.getVA());
+  };
 
   for (StringRef s : config->filterList)
     addInt(DT_FILTER, part.dynStrTab->addString(s));
@@ -1340,7 +1308,7 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
     addInt(config->enableNewDtags ? DT_RUNPATH : DT_RPATH,
            part.dynStrTab->addString(config->rpath));
 
-  for (SharedFile *file : sharedFiles)
+  for (SharedFile *file : ctx.sharedFiles)
     if (file->isNeeded)
       addInt(DT_NEEDED, part.dynStrTab->addString(file->soName));
 
@@ -1382,7 +1350,7 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
   }
   if (!config->zText)
     dtFlags |= DF_TEXTREL;
-  if (config->hasStaticTlsModel)
+  if (ctx.hasTlsIe && config->shared)
     dtFlags |= DF_STATIC_TLS;
 
   if (dtFlags)
@@ -1401,14 +1369,12 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
   if (!config->shared && !config->relocatable && !config->zRodynamic)
     addInt(DT_DEBUG, 0);
 
-  if (OutputSection *sec = part.dynStrTab->getParent())
-    this->link = sec->sectionIndex;
-
   if (part.relaDyn->isNeeded() ||
       (in.relaIplt->isNeeded() &&
        part.relaDyn->getParent() == in.relaIplt->getParent())) {
-    addInSec(part.relaDyn->dynamicTag, part.relaDyn);
-    entries.push_back({part.relaDyn->sizeDynamicTag, addRelaSz(part.relaDyn)});
+    addInSec(part.relaDyn->dynamicTag, *part.relaDyn);
+    entries.emplace_back(part.relaDyn->sizeDynamicTag,
+                         addRelaSz(*part.relaDyn));
 
     bool isRela = config->isRela;
     addInt(isRela ? DT_RELAENT : DT_RELENT,
@@ -1423,11 +1389,12 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
         addInt(isRela ? DT_RELACOUNT : DT_RELCOUNT, numRelativeRels);
     }
   }
-  if (part.relrDyn && !part.relrDyn->relocs.empty()) {
+  if (part.relrDyn && part.relrDyn->getParent() &&
+      !part.relrDyn->relocs.empty()) {
     addInSec(config->useAndroidRelrTags ? DT_ANDROID_RELR : DT_RELR,
-             part.relrDyn);
-    addSize(config->useAndroidRelrTags ? DT_ANDROID_RELRSZ : DT_RELRSZ,
-            part.relrDyn->getParent());
+             *part.relrDyn);
+    addInt(config->useAndroidRelrTags ? DT_ANDROID_RELRSZ : DT_RELRSZ,
+           part.relrDyn->getParent()->size);
     addInt(config->useAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT,
            sizeof(Elf_Relr));
   }
@@ -1438,14 +1405,14 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
   // case, so here we always use relaPlt as marker for the beginning of
   // .rel[a].plt section.
   if (isMain && (in.relaPlt->isNeeded() || in.relaIplt->isNeeded())) {
-    addInSec(DT_JMPREL, in.relaPlt);
-    entries.push_back({DT_PLTRELSZ, addPltRelSz});
+    addInSec(DT_JMPREL, *in.relaPlt);
+    entries.emplace_back(DT_PLTRELSZ, addPltRelSz());
     switch (config->emachine) {
     case EM_MIPS:
-      addInSec(DT_MIPS_PLTGOT, in.gotPlt);
+      addInSec(DT_MIPS_PLTGOT, *in.gotPlt);
       break;
     case EM_SPARCV9:
-      addInSec(DT_PLTGOT, in.plt);
+      addInSec(DT_PLTGOT, *in.plt);
       break;
     case EM_AARCH64:
       if (llvm::find_if(in.relaPlt->relocs, [](const DynamicReloc &r) {
@@ -1453,9 +1420,17 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
                   r.sym->stOther & STO_AARCH64_VARIANT_PCS;
           }) != in.relaPlt->relocs.end())
         addInt(DT_AARCH64_VARIANT_PCS, 0);
-      LLVM_FALLTHROUGH;
+      addInSec(DT_PLTGOT, *in.gotPlt);
+      break;
+    case EM_RISCV:
+      if (llvm::any_of(in.relaPlt->relocs, [](const DynamicReloc &r) {
+            return r.type == target->pltRel &&
+                   (r.sym->stOther & STO_RISCV_VARIANT_CC);
+          }))
+        addInt(DT_RISCV_VARIANT_CC, 0);
+      [[fallthrough]];
     default:
-      addInSec(DT_PLTGOT, in.gotPlt);
+      addInSec(DT_PLTGOT, *in.gotPlt);
       break;
     }
     addInt(DT_PLTREL, config->isRela ? DT_RELA : DT_REL);
@@ -1468,49 +1443,49 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
       addInt(DT_AARCH64_PAC_PLT, 0);
   }
 
-  addInSec(DT_SYMTAB, part.dynSymTab);
+  addInSec(DT_SYMTAB, *part.dynSymTab);
   addInt(DT_SYMENT, sizeof(Elf_Sym));
-  addInSec(DT_STRTAB, part.dynStrTab);
+  addInSec(DT_STRTAB, *part.dynStrTab);
   addInt(DT_STRSZ, part.dynStrTab->getSize());
   if (!config->zText)
     addInt(DT_TEXTREL, 0);
-  if (part.gnuHashTab)
-    addInSec(DT_GNU_HASH, part.gnuHashTab);
-  if (part.hashTab)
-    addInSec(DT_HASH, part.hashTab);
+  if (part.gnuHashTab && part.gnuHashTab->getParent())
+    addInSec(DT_GNU_HASH, *part.gnuHashTab);
+  if (part.hashTab && part.hashTab->getParent())
+    addInSec(DT_HASH, *part.hashTab);
 
   if (isMain) {
     if (Out::preinitArray) {
-      addOutSec(DT_PREINIT_ARRAY, Out::preinitArray);
-      addSize(DT_PREINIT_ARRAYSZ, Out::preinitArray);
+      addInt(DT_PREINIT_ARRAY, Out::preinitArray->addr);
+      addInt(DT_PREINIT_ARRAYSZ, Out::preinitArray->size);
     }
     if (Out::initArray) {
-      addOutSec(DT_INIT_ARRAY, Out::initArray);
-      addSize(DT_INIT_ARRAYSZ, Out::initArray);
+      addInt(DT_INIT_ARRAY, Out::initArray->addr);
+      addInt(DT_INIT_ARRAYSZ, Out::initArray->size);
     }
     if (Out::finiArray) {
-      addOutSec(DT_FINI_ARRAY, Out::finiArray);
-      addSize(DT_FINI_ARRAYSZ, Out::finiArray);
+      addInt(DT_FINI_ARRAY, Out::finiArray->addr);
+      addInt(DT_FINI_ARRAYSZ, Out::finiArray->size);
     }
 
-    if (Symbol *b = symtab->find(config->init))
+    if (Symbol *b = symtab.find(config->init))
       if (b->isDefined())
-        addSym(DT_INIT, b);
-    if (Symbol *b = symtab->find(config->fini))
+        addInt(DT_INIT, b->getVA());
+    if (Symbol *b = symtab.find(config->fini))
       if (b->isDefined())
-        addSym(DT_FINI, b);
+        addInt(DT_FINI, b->getVA());
   }
 
   if (part.verSym && part.verSym->isNeeded())
-    addInSec(DT_VERSYM, part.verSym);
+    addInSec(DT_VERSYM, *part.verSym);
   if (part.verDef && part.verDef->isLive()) {
-    addInSec(DT_VERDEF, part.verDef);
+    addInSec(DT_VERDEF, *part.verDef);
     addInt(DT_VERDEFNUM, getVerDefNum());
   }
   if (part.verNeed && part.verNeed->isNeeded()) {
-    addInSec(DT_VERNEED, part.verNeed);
+    addInSec(DT_VERNEED, *part.verNeed);
     unsigned needNum = 0;
-    for (SharedFile *f : sharedFiles)
+    for (SharedFile *f : ctx.sharedFiles)
       if (!f->vernauxs.empty())
         ++needNum;
     addInt(DT_VERNEEDNUM, needNum);
@@ -1521,50 +1496,51 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
     addInt(DT_MIPS_FLAGS, RHF_NOTPOT);
     addInt(DT_MIPS_BASE_ADDRESS, target->getImageBase());
     addInt(DT_MIPS_SYMTABNO, part.dynSymTab->getNumSymbols());
-
-    add(DT_MIPS_LOCAL_GOTNO, [] { return in.mipsGot->getLocalEntriesNum(); });
+    addInt(DT_MIPS_LOCAL_GOTNO, in.mipsGot->getLocalEntriesNum());
 
     if (const Symbol *b = in.mipsGot->getFirstGlobalEntry())
       addInt(DT_MIPS_GOTSYM, b->dynsymIndex);
     else
       addInt(DT_MIPS_GOTSYM, part.dynSymTab->getNumSymbols());
-    addInSec(DT_PLTGOT, in.mipsGot);
+    addInSec(DT_PLTGOT, *in.mipsGot);
     if (in.mipsRldMap) {
       if (!config->pie)
-        addInSec(DT_MIPS_RLD_MAP, in.mipsRldMap);
+        addInSec(DT_MIPS_RLD_MAP, *in.mipsRldMap);
       // Store the offset to the .rld_map section
       // relative to the address of the tag.
-      addInSecRelative(DT_MIPS_RLD_MAP_REL, in.mipsRldMap);
+      addInt(DT_MIPS_RLD_MAP_REL,
+             in.mipsRldMap->getVA() - (getVA() + entries.size() * entsize));
     }
   }
 
   // DT_PPC_GOT indicates to glibc Secure PLT is used. If DT_PPC_GOT is absent,
   // glibc assumes the old-style BSS PLT layout which we don't support.
   if (config->emachine == EM_PPC)
-    add(DT_PPC_GOT, [] { return in.got->getVA(); });
+    addInSec(DT_PPC_GOT, *in.got);
 
   // Glink dynamic tag is required by the V2 abi if the plt section isn't empty.
   if (config->emachine == EM_PPC64 && in.plt->isNeeded()) {
     // The Glink tag points to 32 bytes before the first lazy symbol resolution
     // stub, which starts directly after the header.
-    entries.push_back({DT_PPC64_GLINK, [=] {
-                         unsigned offset = target->pltHeaderSize - 32;
-                         return in.plt->getVA(0) + offset;
-                       }});
+    addInt(DT_PPC64_GLINK, in.plt->getVA() + target->pltHeaderSize - 32);
   }
 
   addInt(DT_NULL, 0);
+  return entries;
+}
 
-  getParent()->link = this->link;
-  this->size = entries.size() * this->entsize;
+template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
+  if (OutputSection *sec = getPartition().dynStrTab->getParent())
+    getParent()->link = sec->sectionIndex;
+  this->size = computeContents().size() * this->entsize;
 }
 
 template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *buf) {
   auto *p = reinterpret_cast<Elf_Dyn *>(buf);
 
-  for (std::pair<int32_t, std::function<uint64_t()>> &kv : entries) {
+  for (std::pair<int32_t, uint64_t> kv : computeContents()) {
     p->d_tag = kv.first;
-    p->d_un.d_val = kv.second();
+    p->d_un.d_val = kv.second;
     ++p;
   }
 }
@@ -1593,72 +1569,65 @@ int64_t DynamicReloc::computeAddend() const {
 }
 
 uint32_t DynamicReloc::getSymIndex(SymbolTableBaseSection *symTab) const {
-  if (needsDynSymIndex())
-    return symTab->getSymbolIndex(sym);
-  return 0;
+  if (!needsDynSymIndex())
+    return 0;
+
+  size_t index = symTab->getSymbolIndex(sym);
+  assert((index != 0 || (type != target->gotRel && type != target->pltRel) ||
+          !mainPart->dynSymTab->getParent()) &&
+         "GOT or PLT relocation must refer to symbol in dynamic symbol table");
+  return index;
 }
 
 RelocationBaseSection::RelocationBaseSection(StringRef name, uint32_t type,
                                              int32_t dynamicTag,
-                                             int32_t sizeDynamicTag)
+                                             int32_t sizeDynamicTag,
+                                             bool combreloc,
+                                             unsigned concurrency)
     : SyntheticSection(SHF_ALLOC, type, config->wordsize, name),
-      dynamicTag(dynamicTag), sizeDynamicTag(sizeDynamicTag) {}
+      dynamicTag(dynamicTag), sizeDynamicTag(sizeDynamicTag),
+      relocsVec(concurrency), combreloc(combreloc) {}
 
-void RelocationBaseSection::addSymbolReloc(RelType dynType,
-                                           InputSectionBase *isec,
-                                           uint64_t offsetInSec, Symbol &sym,
-                                           int64_t addend,
-                                           Optional<RelType> addendRelType) {
+void RelocationBaseSection::addSymbolReloc(
+    RelType dynType, InputSectionBase &isec, uint64_t offsetInSec, Symbol &sym,
+    int64_t addend, std::optional<RelType> addendRelType) {
   addReloc(DynamicReloc::AgainstSymbol, dynType, isec, offsetInSec, sym, addend,
            R_ADDEND, addendRelType ? *addendRelType : target->noneRel);
 }
 
-void RelocationBaseSection::addRelativeReloc(
-    RelType dynType, InputSectionBase *inputSec, uint64_t offsetInSec,
-    Symbol &sym, int64_t addend, RelType addendRelType, RelExpr expr) {
-  // This function should only be called for non-preemptible symbols or
-  // RelExpr values that refer to an address inside the output file (e.g. the
-  // address of the GOT entry for a potentially preemptible symbol).
-  assert((!sym.isPreemptible || expr == R_GOT) &&
-         "cannot add relative relocation against preemptible symbol");
-  assert(expr != R_ADDEND && "expected non-addend relocation expression");
-  addReloc(DynamicReloc::AddendOnlyWithTargetVA, dynType, inputSec, offsetInSec,
-           sym, addend, expr, addendRelType);
-}
-
 void RelocationBaseSection::addAddendOnlyRelocIfNonPreemptible(
-    RelType dynType, InputSectionBase *isec, uint64_t offsetInSec, Symbol &sym,
+    RelType dynType, GotSection &sec, uint64_t offsetInSec, Symbol &sym,
     RelType addendRelType) {
   // No need to write an addend to the section for preemptible symbols.
   if (sym.isPreemptible)
-    addReloc({dynType, isec, offsetInSec, DynamicReloc::AgainstSymbol, sym, 0,
+    addReloc({dynType, &sec, offsetInSec, DynamicReloc::AgainstSymbol, sym, 0,
               R_ABS});
   else
-    addReloc(DynamicReloc::AddendOnlyWithTargetVA, dynType, isec, offsetInSec,
+    addReloc(DynamicReloc::AddendOnlyWithTargetVA, dynType, sec, offsetInSec,
              sym, 0, R_ABS, addendRelType);
 }
 
-void RelocationBaseSection::addReloc(DynamicReloc::Kind kind, RelType dynType,
-                                     InputSectionBase *inputSec,
-                                     uint64_t offsetInSec, Symbol &sym,
-                                     int64_t addend, RelExpr expr,
-                                     RelType addendRelType) {
-  // Write the addends to the relocated address if required. We skip
-  // it if the written value would be zero.
-  if (config->writeAddends && (expr != R_ADDEND || addend != 0))
-    inputSec->relocations.push_back(
-        {expr, addendRelType, offsetInSec, addend, &sym});
-  addReloc({dynType, inputSec, offsetInSec, kind, sym, addend, expr});
+void RelocationBaseSection::mergeRels() {
+  size_t newSize = relocs.size();
+  for (const auto &v : relocsVec)
+    newSize += v.size();
+  relocs.reserve(newSize);
+  for (const auto &v : relocsVec)
+    llvm::append_range(relocs, v);
+  relocsVec.clear();
 }
 
-void RelocationBaseSection::addReloc(const DynamicReloc &reloc) {
-  if (reloc.type == target->relativeRel)
-    ++numRelativeRelocs;
-  relocs.push_back(reloc);
+void RelocationBaseSection::partitionRels() {
+  if (!combreloc)
+    return;
+  const RelType relativeRel = target->relativeRel;
+  numRelativeRelocs =
+      llvm::partition(relocs, [=](auto &r) { return r.type == relativeRel; }) -
+      relocs.begin();
 }
 
 void RelocationBaseSection::finalizeContents() {
-  SymbolTableBaseSection *symTab = getPartition().dynSymTab;
+  SymbolTableBaseSection *symTab = getPartition().dynSymTab.get();
 
   // When linking glibc statically, .rel{,a}.plt contains R_*_IRELATIVE
   // relocations due to IFUNC (e.g. strcpy). sh_link will be set to 0 in that
@@ -1668,68 +1637,87 @@ void RelocationBaseSection::finalizeContents() {
   else
     getParent()->link = 0;
 
-  if (in.relaPlt == this) {
+  if (in.relaPlt.get() == this && in.gotPlt->getParent()) {
     getParent()->flags |= ELF::SHF_INFO_LINK;
     getParent()->info = in.gotPlt->getParent()->sectionIndex;
   }
-  if (in.relaIplt == this) {
+  if (in.relaIplt.get() == this && in.igotPlt->getParent()) {
     getParent()->flags |= ELF::SHF_INFO_LINK;
     getParent()->info = in.igotPlt->getParent()->sectionIndex;
   }
 }
 
-RelrBaseSection::RelrBaseSection()
-    : SyntheticSection(SHF_ALLOC,
-                       config->useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR,
-                       config->wordsize, ".relr.dyn") {}
+void DynamicReloc::computeRaw(SymbolTableBaseSection *symtab) {
+  r_offset = getOffset();
+  r_sym = getSymIndex(symtab);
+  addend = computeAddend();
+  kind = AddendOnly; // Catch errors
+}
 
-template <class ELFT>
-static void encodeDynamicReloc(SymbolTableBaseSection *symTab,
-                               typename ELFT::Rela *p,
-                               const DynamicReloc &rel) {
-  if (config->isRela)
-    p->r_addend = rel.computeAddend();
-  p->r_offset = rel.getOffset();
-  p->setSymbolAndType(rel.getSymIndex(symTab), rel.type, config->isMips64EL);
+void RelocationBaseSection::computeRels() {
+  SymbolTableBaseSection *symTab = getPartition().dynSymTab.get();
+  parallelForEach(relocs,
+                  [symTab](DynamicReloc &rel) { rel.computeRaw(symTab); });
+  // Sort by (!IsRelative,SymIndex,r_offset). DT_REL[A]COUNT requires us to
+  // place R_*_RELATIVE first. SymIndex is to improve locality, while r_offset
+  // is to make results easier to read.
+  if (combreloc) {
+    auto nonRelative = relocs.begin() + numRelativeRelocs;
+    parallelSort(relocs.begin(), nonRelative,
+                 [&](auto &a, auto &b) { return a.r_offset < b.r_offset; });
+    // Non-relative relocations are few, so don't bother with parallelSort.
+    llvm::sort(nonRelative, relocs.end(), [&](auto &a, auto &b) {
+      return std::tie(a.r_sym, a.r_offset) < std::tie(b.r_sym, b.r_offset);
+    });
+  }
 }
 
 template <class ELFT>
-RelocationSection<ELFT>::RelocationSection(StringRef name, bool sort)
+RelocationSection<ELFT>::RelocationSection(StringRef name, bool combreloc,
+                                           unsigned concurrency)
     : RelocationBaseSection(name, config->isRela ? SHT_RELA : SHT_REL,
                             config->isRela ? DT_RELA : DT_REL,
-                            config->isRela ? DT_RELASZ : DT_RELSZ),
-      sort(sort) {
+                            config->isRela ? DT_RELASZ : DT_RELSZ, combreloc,
+                            concurrency) {
   this->entsize = config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
 }
 
 template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *buf) {
-  SymbolTableBaseSection *symTab = getPartition().dynSymTab;
-
-  // Sort by (!IsRelative,SymIndex,r_offset). DT_REL[A]COUNT requires us to
-  // place R_*_RELATIVE first. SymIndex is to improve locality, while r_offset
-  // is to make results easier to read.
-  if (sort)
-    llvm::stable_sort(
-        relocs, [&](const DynamicReloc &a, const DynamicReloc &b) {
-          return std::make_tuple(a.type != target->relativeRel,
-                                 a.getSymIndex(symTab), a.getOffset()) <
-                 std::make_tuple(b.type != target->relativeRel,
-                                 b.getSymIndex(symTab), b.getOffset());
-        });
-
+  computeRels();
   for (const DynamicReloc &rel : relocs) {
-    encodeDynamicReloc<ELFT>(symTab, reinterpret_cast<Elf_Rela *>(buf), rel);
+    auto *p = reinterpret_cast<Elf_Rela *>(buf);
+    p->r_offset = rel.r_offset;
+    p->setSymbolAndType(rel.r_sym, rel.type, config->isMips64EL);
+    if (config->isRela)
+      p->r_addend = rel.addend;
     buf += config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
   }
 }
 
+RelrBaseSection::RelrBaseSection(unsigned concurrency)
+    : SyntheticSection(SHF_ALLOC,
+                       config->useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR,
+                       config->wordsize, ".relr.dyn"),
+      relocsVec(concurrency) {}
+
+void RelrBaseSection::mergeRels() {
+  size_t newSize = relocs.size();
+  for (const auto &v : relocsVec)
+    newSize += v.size();
+  relocs.reserve(newSize);
+  for (const auto &v : relocsVec)
+    llvm::append_range(relocs, v);
+  relocsVec.clear();
+}
+
 template <class ELFT>
 AndroidPackedRelocationSection<ELFT>::AndroidPackedRelocationSection(
-    StringRef name)
+    StringRef name, unsigned concurrency)
     : RelocationBaseSection(
           name, config->isRela ? SHT_ANDROID_RELA : SHT_ANDROID_REL,
           config->isRela ? DT_ANDROID_RELA : DT_ANDROID_REL,
-          config->isRela ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ) {
+          config->isRela ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ,
+          /*combreloc=*/false, concurrency) {
   this->entsize = 1;
 }
 
@@ -1796,7 +1784,10 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
 
   for (const DynamicReloc &rel : relocs) {
     Elf_Rela r;
-    encodeDynamicReloc<ELFT>(getPartition().dynSymTab, &r, rel);
+    r.r_offset = rel.getOffset();
+    r.setSymbolAndType(rel.getSymIndex(getPartition().dynSymTab.get()),
+                       rel.type, false);
+    r.r_addend = config->isRela ? rel.computeAddend() : 0;
 
     if (r.getType(config->isMips64EL) == target->relativeRel)
       relatives.push_back(r);
@@ -1840,12 +1831,12 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
   //
   // For Rela, we also want to sort by r_addend when r_info is the same. This
   // enables us to group by r_addend as well.
-  llvm::stable_sort(nonRelatives, [](const Elf_Rela &a, const Elf_Rela &b) {
+  llvm::sort(nonRelatives, [](const Elf_Rela &a, const Elf_Rela &b) {
     if (a.r_info != b.r_info)
       return a.r_info < b.r_info;
-    if (config->isRela)
+    if (a.r_addend != b.r_addend)
       return a.r_addend < b.r_addend;
-    return false;
+    return a.r_offset < b.r_offset;
   });
 
   // Group relocations with the same r_info. Note that each group emits a group
@@ -1909,9 +1900,9 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
     add(config->wordsize);
     add(target->relativeRel);
     if (config->isRela) {
-      for (auto i = g.begin() + 1, e = g.end(); i != e; ++i) {
-        add(i->r_addend - addend);
-        addend = i->r_addend;
+      for (const auto &i : llvm::drop_begin(g)) {
+        add(i.r_addend - addend);
+        addend = i.r_addend;
       }
     }
 
@@ -1973,7 +1964,9 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
   return relocData.size() != oldSize;
 }
 
-template <class ELFT> RelrSection<ELFT>::RelrSection() {
+template <class ELFT>
+RelrSection<ELFT>::RelrSection(unsigned concurrency)
+    : RelrBaseSection(concurrency) {
   this->entsize = config->wordsize;
 }
 
@@ -2020,42 +2013,30 @@ template <class ELFT> bool RelrSection<ELFT>::updateAllocSize() {
   const size_t nBits = wordsize * 8 - 1;
 
   // Get offsets for all relative relocations and sort them.
-  std::vector<uint64_t> offsets;
-  for (const RelativeReloc &rel : relocs)
-    offsets.push_back(rel.getOffset());
-  llvm::sort(offsets);
+  std::unique_ptr<uint64_t[]> offsets(new uint64_t[relocs.size()]);
+  for (auto [i, r] : llvm::enumerate(relocs))
+    offsets[i] = r.getOffset();
+  llvm::sort(offsets.get(), offsets.get() + relocs.size());
 
   // For each leading relocation, find following ones that can be folded
   // as a bitmap and fold them.
-  for (size_t i = 0, e = offsets.size(); i < e;) {
+  for (size_t i = 0, e = relocs.size(); i != e;) {
     // Add a leading relocation.
     relrRelocs.push_back(Elf_Relr(offsets[i]));
     uint64_t base = offsets[i] + wordsize;
     ++i;
 
     // Find foldable relocations to construct bitmaps.
-    while (i < e) {
+    for (;;) {
       uint64_t bitmap = 0;
-
-      while (i < e) {
-        uint64_t delta = offsets[i] - base;
-
-        // If it is too far, it cannot be folded.
-        if (delta >= nBits * wordsize)
+      for (; i != e; ++i) {
+        uint64_t d = offsets[i] - base;
+        if (d >= nBits * wordsize || d % wordsize)
           break;
-
-        // If it is not a multiple of wordsize away, it cannot be folded.
-        if (delta % wordsize)
-          break;
-
-        // Fold it.
-        bitmap |= 1ULL << (delta / wordsize);
-        ++i;
+        bitmap |= uint64_t(1) << (d / wordsize);
       }
-
       if (!bitmap)
         break;
-
       relrRelocs.push_back(Elf_Relr((bitmap << 1) | 1));
       base += nBits * wordsize;
     }
@@ -2089,7 +2070,7 @@ static bool sortMipsSymbols(const SymbolTableEntry &l,
   // Sort entries related to non-local preemptible symbols by GOT indexes.
   // All other entries go to the beginning of a dynsym in arbitrary order.
   if (l.sym->isInGot() && r.sym->isInGot())
-    return l.sym->gotIndex < r.sym->gotIndex;
+    return l.sym->getGotIdx() < r.sym->getGotIdx();
   if (!l.sym->isInGot() && !r.sym->isInGot())
     return false;
   return !l.sym->isInGot();
@@ -2120,7 +2101,7 @@ void SymbolTableBaseSection::finalizeContents() {
 
   // Only the main partition's dynsym indexes are stored in the symbols
   // themselves. All other partitions use a lookup table.
-  if (this == mainPart->dynSymTab) {
+  if (this == mainPart->dynSymTab.get()) {
     size_t i = 0;
     for (const SymbolTableEntry &s : symbols)
       s.sym->dynsymIndex = ++i;
@@ -2137,9 +2118,8 @@ void SymbolTableBaseSection::finalizeContents() {
 void SymbolTableBaseSection::sortSymTabSymbols() {
   // Move all local symbols before global symbols.
   auto e = std::stable_partition(
-      symbols.begin(), symbols.end(), [](const SymbolTableEntry &s) {
-        return s.sym->isLocal() || s.sym->computeBinding() == STB_LOCAL;
-      });
+      symbols.begin(), symbols.end(),
+      [](const SymbolTableEntry &s) { return s.sym->isLocal(); });
   size_t numLocals = e - symbols.begin();
   getParent()->info = numLocals + 1;
 
@@ -2148,12 +2128,12 @@ void SymbolTableBaseSection::sortSymTabSymbols() {
   // symbols, they are already naturally placed first in each group. That
   // happens because STT_FILE is always the first symbol in the object and hence
   // precede all other local symbols we add for a file.
-  MapVector<InputFile *, std::vector<SymbolTableEntry>> arr;
+  MapVector<InputFile *, SmallVector<SymbolTableEntry, 0>> arr;
   for (const SymbolTableEntry &s : llvm::make_range(symbols.begin(), e))
     arr[s.sym->file].push_back(s);
 
   auto i = symbols.begin();
-  for (std::pair<InputFile *, std::vector<SymbolTableEntry>> &p : arr)
+  for (auto &p : arr)
     for (SymbolTableEntry &entry : p.second)
       *i++ = entry;
 }
@@ -2161,17 +2141,15 @@ void SymbolTableBaseSection::sortSymTabSymbols() {
 void SymbolTableBaseSection::addSymbol(Symbol *b) {
   // Adding a local symbol to a .dynsym is a bug.
   assert(this->type != SHT_DYNSYM || !b->isLocal());
-
-  bool hashIt = b->isLocal();
-  symbols.push_back({b, strTabSec.addString(b->getName(), hashIt)});
+  symbols.push_back({b, strTabSec.addString(b->getName(), false)});
 }
 
 size_t SymbolTableBaseSection::getSymbolIndex(Symbol *sym) {
-  if (this == mainPart->dynSymTab)
+  if (this == mainPart->dynSymTab.get())
     return sym->dynsymIndex;
 
   // Initializes symbol lookup tables lazily. This is used only for -r,
-  // -emit-relocs and dynsyms in partitions other than the main one.
+  // --emit-relocs and dynsyms in partitions other than the main one.
   llvm::call_once(onceFlag, [&] {
     symbolIndexMap.reserve(symbols.size());
     size_t i = 0;
@@ -2197,16 +2175,15 @@ SymbolTableSection<ELFT>::SymbolTableSection(StringTableSection &strTabSec)
 }
 
 static BssSection *getCommonSec(Symbol *sym) {
-  if (!config->defineCommon)
+  if (config->relocatable)
     if (auto *d = dyn_cast<Defined>(sym))
       return dyn_cast_or_null<BssSection>(d->section);
   return nullptr;
 }
 
 static uint32_t getSymSectionIndex(Symbol *sym) {
-  if (getCommonSec(sym))
-    return SHN_COMMON;
-  if (!isa<Defined>(sym) || sym->needsPltAddr)
+  assert(!(sym->hasFlag(NEEDS_COPY) && sym->isObject()));
+  if (!isa<Defined>(sym) || sym->hasFlag(NEEDS_COPY))
     return SHN_UNDEF;
   if (const OutputSection *os = sym->getOutputSection())
     return os->sectionIndex >= SHN_LORESERVE ? (uint32_t)SHN_XINDEX
@@ -2217,7 +2194,6 @@ static uint32_t getSymSectionIndex(Symbol *sym) {
 // Write the internal symbol table contents to the output symbol table.
 template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) {
   // The first entry is a null entry as per the ELF spec.
-  memset(buf, 0, sizeof(Elf_Sym));
   buf += sizeof(Elf_Sym);
 
   auto *eSym = reinterpret_cast<Elf_Sym *>(buf);
@@ -2226,49 +2202,35 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) {
     Symbol *sym = ent.sym;
     bool isDefinedHere = type == SHT_SYMTAB || sym->partition == partition;
 
-    // Set st_info and st_other.
-    eSym->st_other = 0;
-    if (sym->isLocal()) {
-      eSym->setBindingAndType(STB_LOCAL, sym->type);
+    // Set st_name, st_info and st_other.
+    eSym->st_name = ent.strTabOffset;
+    eSym->setBindingAndType(sym->binding, sym->type);
+    eSym->st_other = sym->stOther;
+
+    if (BssSection *commonSec = getCommonSec(sym)) {
+      // When -r is specified, a COMMON symbol is not allocated. Its st_shndx
+      // holds SHN_COMMON and st_value holds the alignment.
+      eSym->st_shndx = SHN_COMMON;
+      eSym->st_value = commonSec->addralign;
+      eSym->st_size = cast<Defined>(sym)->size;
     } else {
-      eSym->setBindingAndType(sym->computeBinding(), sym->type);
-      eSym->setVisibility(sym->visibility);
+      const uint32_t shndx = getSymSectionIndex(sym);
+      if (isDefinedHere) {
+        eSym->st_shndx = shndx;
+        eSym->st_value = sym->getVA();
+        // Copy symbol size if it is a defined symbol. st_size is not
+        // significant for undefined symbols, so whether copying it or not is up
+        // to us if that's the case. We'll leave it as zero because by not
+        // setting a value, we can get the exact same outputs for two sets of
+        // input files that differ only in undefined symbol size in DSOs.
+        eSym->st_size = shndx != SHN_UNDEF ? cast<Defined>(sym)->size : 0;
+      } else {
+        eSym->st_shndx = 0;
+        eSym->st_value = 0;
+        eSym->st_size = 0;
+      }
     }
 
-    // The 3 most significant bits of st_other are used by OpenPOWER ABI.
-    // See getPPC64GlobalEntryToLocalEntryOffset() for more details.
-    if (config->emachine == EM_PPC64)
-      eSym->st_other |= sym->stOther & 0xe0;
-    // The most significant bit of st_other is used by AArch64 ABI for the
-    // variant PCS.
-    else if (config->emachine == EM_AARCH64)
-      eSym->st_other |= sym->stOther & STO_AARCH64_VARIANT_PCS;
-
-    eSym->st_name = ent.strTabOffset;
-    if (isDefinedHere)
-      eSym->st_shndx = getSymSectionIndex(ent.sym);
-    else
-      eSym->st_shndx = 0;
-
-    // Copy symbol size if it is a defined symbol. st_size is not significant
-    // for undefined symbols, so whether copying it or not is up to us if that's
-    // the case. We'll leave it as zero because by not setting a value, we can
-    // get the exact same outputs for two sets of input files that differ only
-    // in undefined symbol size in DSOs.
-    if (eSym->st_shndx == SHN_UNDEF || !isDefinedHere)
-      eSym->st_size = 0;
-    else
-      eSym->st_size = sym->getSize();
-
-    // st_value is usually an address of a symbol, but that has a special
-    // meaning for uninstantiated common symbols (--no-define-common).
-    if (BssSection *commonSec = getCommonSec(ent.sym))
-      eSym->st_value = commonSec->alignment;
-    else if (isDefinedHere)
-      eSym->st_value = sym->getVA();
-    else
-      eSym->st_value = 0;
-
     ++eSym;
   }
 
@@ -2281,7 +2243,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) {
 
     for (SymbolTableEntry &ent : symbols) {
       Symbol *sym = ent.sym;
-      if (sym->isInPlt() && sym->needsPltAddr)
+      if (sym->isInPlt() && sym->hasFlag(NEEDS_COPY))
         eSym->st_other |= STO_MIPS_PLT;
       if (isMicroMips()) {
         // We already set the less-significant bit for symbols
@@ -2292,7 +2254,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) {
         // like `objdump` will be able to deal with a correct
         // symbol position.
         if (sym->isDefined() &&
-            ((sym->stOther & STO_MIPS_MICROMIPS) || sym->needsPltAddr)) {
+            ((sym->stOther & STO_MIPS_MICROMIPS) || sym->hasFlag(NEEDS_COPY))) {
           if (!strTabSec.isDynamic())
             eSym->st_value &= ~1;
           eSym->st_other |= STO_MIPS_MICROMIPS;
@@ -2318,7 +2280,7 @@ void SymtabShndxSection::writeTo(uint8_t *buf) {
   // we need to write actual index, otherwise, we must write SHN_UNDEF(0).
   buf += 4; // Ignore .symtab[0] entry.
   for (const SymbolTableEntry &entry : in.symTab->getSymbols()) {
-    if (getSymSectionIndex(entry.sym) == SHN_XINDEX)
+    if (!getCommonSec(entry.sym) && getSymSectionIndex(entry.sym) == SHN_XINDEX)
       write32(buf, entry.sym->getOutputSection()->sectionIndex);
     buf += 4;
   }
@@ -2331,8 +2293,8 @@ bool SymtabShndxSection::isNeeded() const {
   // late, and we do not know them here. For simplicity, we just always create
   // a .symtab_shndx section when the amount of output sections is huge.
   size_t size = 0;
-  for (BaseCommand *base : script->sectionCommands)
-    if (isa<OutputSection>(base))
+  for (SectionCommand *cmd : script->sectionCommands)
+    if (isa<OutputDesc>(cmd))
       ++size;
   return size >= SHN_LORESERVE;
 }
@@ -2350,8 +2312,7 @@ size_t SymtabShndxSection::getSize() const {
 // is to help the dynamic linker resolve symbols quickly. If ELF files
 // don't have them, the dynamic linker has to do linear search on all
 // dynamic symbols, which makes programs slower. Therefore, a .hash
-// section is added to a DSO by default. A .gnu.hash is added if you
-// give the -hash-style=gnu or -hash-style=both option.
+// section is added to a DSO by default.
 //
 // The Unix semantics of resolving dynamic symbols is somewhat expensive.
 // Each ELF file has a list of DSOs that the ELF file depends on and a
@@ -2374,8 +2335,8 @@ size_t SymtabShndxSection::getSize() const {
 // and better version of .hash. .hash is just an on-disk hash table, but
 // .gnu.hash has a bloom filter in addition to a hash table to skip
 // DSOs very quickly. If you are sure that your dynamic linker knows
-// about .gnu.hash, you want to specify -hash-style=gnu. Otherwise, a
-// safe bet is to specify -hash-style=both for backward compatibility.
+// about .gnu.hash, you want to specify --hash-style=gnu. Otherwise, a
+// safe bet is to specify --hash-style=both for backward compatibility.
 GnuHashTableSection::GnuHashTableSection()
     : SyntheticSection(SHF_ALLOC, SHT_GNU_HASH, config->wordsize, ".gnu.hash") {
 }
@@ -2400,11 +2361,6 @@ void GnuHashTableSection::finalizeContents() {
 }
 
 void GnuHashTableSection::writeTo(uint8_t *buf) {
-  // The output buffer is not guaranteed to be zero-cleared because we pre-
-  // fill executable sections with trap instructions. This is a precaution
-  // for that case, which happens only when -no-rosegment is given.
-  memset(buf, 0, size);
-
   // Write a header.
   write32(buf, nBuckets);
   write32(buf + 4, getPartition().dynSymTab->getNumSymbols() - symbols.size());
@@ -2412,21 +2368,8 @@ void GnuHashTableSection::writeTo(uint8_t *buf) {
   write32(buf + 12, Shift2);
   buf += 16;
 
-  // Write a bloom filter and a hash table.
-  writeBloomFilter(buf);
-  buf += config->wordsize * maskWords;
-  writeHashTable(buf);
-}
-
-// This function writes a 2-bit bloom filter. This bloom filter alone
-// usually filters out 80% or more of all symbol lookups [1].
-// The dynamic linker uses the hash table only when a symbol is not
-// filtered out by a bloom filter.
-//
-// [1] Ulrich Drepper (2011), "How To Write Shared Libraries" (Ver. 4.1.2),
-//     p.9, https://www.akkadia.org/drepper/dsohowto.pdf
-void GnuHashTableSection::writeBloomFilter(uint8_t *buf) {
-  unsigned c = config->is64 ? 64 : 32;
+  // Write the 2-bit bloom filter.
+  const unsigned c = config->is64 ? 64 : 32;
   for (const Entry &sym : symbols) {
     // When C = 64, we choose a word with bits [6:...] and set 1 to two bits in
     // the word using bits [0:5] and [26:31].
@@ -2436,9 +2379,9 @@ void GnuHashTableSection::writeBloomFilter(uint8_t *buf) {
     val |= uint64_t(1) << ((sym.hash >> Shift2) % c);
     writeUint(buf + i * config->wordsize, val);
   }
-}
+  buf += config->wordsize * maskWords;
 
-void GnuHashTableSection::writeHashTable(uint8_t *buf) {
+  // Write the hash table.
   uint32_t *buckets = reinterpret_cast<uint32_t *>(buf);
   uint32_t oldBucket = -1;
   uint32_t *values = buckets + nBuckets;
@@ -2461,20 +2404,13 @@ void GnuHashTableSection::writeHashTable(uint8_t *buf) {
   }
 }
 
-static uint32_t hashGnu(StringRef name) {
-  uint32_t h = 5381;
-  for (uint8_t c : name)
-    h = (h << 5) + h + c;
-  return h;
-}
-
 // Add symbols to this symbol hash table. Note that this function
 // destructively sort a given vector -- which is needed because
 // GNU-style hash table places some sorting requirements.
-void GnuHashTableSection::addSymbols(std::vector<SymbolTableEntry> &v) {
+void GnuHashTableSection::addSymbols(SmallVectorImpl<SymbolTableEntry> &v) {
   // We cannot use 'auto' for Mid because GCC 6.1 cannot deduce
   // its type correctly.
-  std::vector<SymbolTableEntry>::iterator mid =
+  auto mid =
       std::stable_partition(v.begin(), v.end(), [&](const SymbolTableEntry &s) {
         return !s.sym->isDefined() || s.sym->partition != partition;
       });
@@ -2500,8 +2436,9 @@ void GnuHashTableSection::addSymbols(std::vector<SymbolTableEntry> &v) {
     symbols.push_back({b, ent.strTabOffset, hash, bucketIdx});
   }
 
-  llvm::stable_sort(symbols, [](const Entry &l, const Entry &r) {
-    return l.bucketIdx < r.bucketIdx;
+  llvm::sort(symbols, [](const Entry &l, const Entry &r) {
+    return std::tie(l.bucketIdx, l.strTabOffset) <
+           std::tie(r.bucketIdx, r.strTabOffset);
   });
 
   v.erase(mid, v.end());
@@ -2515,7 +2452,7 @@ HashTableSection::HashTableSection()
 }
 
 void HashTableSection::finalizeContents() {
-  SymbolTableBaseSection *symTab = getPartition().dynSymTab;
+  SymbolTableBaseSection *symTab = getPartition().dynSymTab.get();
 
   if (OutputSection *sec = symTab->getParent())
     getParent()->link = sec->sectionIndex;
@@ -2529,11 +2466,7 @@ void HashTableSection::finalizeContents() {
 }
 
 void HashTableSection::writeTo(uint8_t *buf) {
-  SymbolTableBaseSection *symTab = getPartition().dynSymTab;
-
-  // See comment in GnuHashTableSection::writeTo.
-  memset(buf, 0, size);
-
+  SymbolTableBaseSection *symTab = getPartition().dynSymTab.get();
   unsigned numSymbols = symTab->getNumSymbols();
 
   uint32_t *p = reinterpret_cast<uint32_t *>(buf);
@@ -2559,7 +2492,7 @@ PltSection::PltSection()
   // On PowerPC, this section contains lazy symbol resolvers.
   if (config->emachine == EM_PPC64) {
     name = ".glink";
-    alignment = 4;
+    addralign = 4;
   }
 
   // On x86 when IBT is enabled, this section contains the second PLT (lazy
@@ -2587,7 +2520,8 @@ void PltSection::writeTo(uint8_t *buf) {
 }
 
 void PltSection::addEntry(Symbol &sym) {
-  sym.pltIndex = entries.size();
+  assert(sym.auxIdx == symAux.size() - 1);
+  symAux.back().pltIdx = entries.size();
   entries.push_back(&sym);
 }
 
@@ -2616,7 +2550,7 @@ IpltSection::IpltSection()
     : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, ".iplt") {
   if (config->emachine == EM_PPC || config->emachine == EM_PPC64) {
     name = ".glink";
-    alignment = 4;
+    addralign = 4;
   }
 }
 
@@ -2633,7 +2567,8 @@ size_t IpltSection::getSize() const {
 }
 
 void IpltSection::addEntry(Symbol &sym) {
-  sym.pltIndex = entries.size();
+  assert(sym.auxIdx == symAux.size() - 1);
+  symAux.back().pltIdx = entries.size();
   entries.push_back(&sym);
 }
 
@@ -2648,7 +2583,7 @@ void IpltSection::addSymbols() {
 
 PPC32GlinkSection::PPC32GlinkSection() {
   name = ".glink";
-  alignment = 4;
+  addralign = 4;
 }
 
 void PPC32GlinkSection::writeTo(uint8_t *buf) {
@@ -2748,30 +2683,17 @@ size_t GdbIndexSection::computeSymtabSize() const {
   return std::max<size_t>(NextPowerOf2(symbols.size() * 4 / 3), 1024);
 }
 
-// Compute the output section size.
-void GdbIndexSection::initOutputSize() {
-  size = sizeof(GdbIndexHeader) + computeSymtabSize() * 8;
-
-  for (GdbChunk &chunk : chunks)
-    size += chunk.compilationUnits.size() * 16 + chunk.addressAreas.size() * 20;
-
-  // Add the constant pool size if exists.
-  if (!symbols.empty()) {
-    GdbSymbol &sym = symbols.back();
-    size += sym.nameOff + sym.name.size() + 1;
-  }
-}
-
-static std::vector<GdbIndexSection::CuEntry> readCuList(DWARFContext &dwarf) {
-  std::vector<GdbIndexSection::CuEntry> ret;
+static SmallVector<GdbIndexSection::CuEntry, 0>
+readCuList(DWARFContext &dwarf) {
+  SmallVector<GdbIndexSection::CuEntry, 0> ret;
   for (std::unique_ptr<DWARFUnit> &cu : dwarf.compile_units())
     ret.push_back({cu->getOffset(), cu->getLength() + 4});
   return ret;
 }
 
-static std::vector<GdbIndexSection::AddressEntry>
+static SmallVector<GdbIndexSection::AddressEntry, 0>
 readAddressAreas(DWARFContext &dwarf, InputSection *sec) {
-  std::vector<GdbIndexSection::AddressEntry> ret;
+  SmallVector<GdbIndexSection::AddressEntry, 0> ret;
 
   uint32_t cuIdx = 0;
   for (std::unique_ptr<DWARFUnit> &cu : dwarf.compile_units()) {
@@ -2802,13 +2724,13 @@ readAddressAreas(DWARFContext &dwarf, InputSection *sec) {
 }
 
 template <class ELFT>
-static std::vector<GdbIndexSection::NameAttrEntry>
+static SmallVector<GdbIndexSection::NameAttrEntry, 0>
 readPubNamesAndTypes(const LLDDwarfObj<ELFT> &obj,
-                     const std::vector<GdbIndexSection::CuEntry> &cus) {
+                     const SmallVectorImpl<GdbIndexSection::CuEntry> &cus) {
   const LLDDWARFSection &pubNames = obj.getGnuPubnamesSection();
   const LLDDWARFSection &pubTypes = obj.getGnuPubtypesSection();
 
-  std::vector<GdbIndexSection::NameAttrEntry> ret;
+  SmallVector<GdbIndexSection::NameAttrEntry, 0> ret;
   for (const LLDDWARFSection *pub : {&pubNames, &pubTypes}) {
     DWARFDataExtractor data(obj, *pub, config->isLE, config->wordsize);
     DWARFDebugPubTable table;
@@ -2835,15 +2757,16 @@ readPubNamesAndTypes(const LLDDwarfObj<ELFT> &obj,
 
 // Create a list of symbols from a given list of symbol names and types
 // by uniquifying them by name.
-static std::vector<GdbIndexSection::GdbSymbol>
-createSymbols(ArrayRef<std::vector<GdbIndexSection::NameAttrEntry>> nameAttrs,
-              const std::vector<GdbIndexSection::GdbChunk> &chunks) {
+static std::pair<SmallVector<GdbIndexSection::GdbSymbol, 0>, size_t>
+createSymbols(
+    ArrayRef<SmallVector<GdbIndexSection::NameAttrEntry, 0>> nameAttrs,
+    const SmallVector<GdbIndexSection::GdbChunk, 0> &chunks) {
   using GdbSymbol = GdbIndexSection::GdbSymbol;
   using NameAttrEntry = GdbIndexSection::NameAttrEntry;
 
   // For each chunk, compute the number of compilation units preceding it.
   uint32_t cuIdx = 0;
-  std::vector<uint32_t> cuIdxs(chunks.size());
+  std::unique_ptr<uint32_t[]> cuIdxs(new uint32_t[chunks.size()]);
   for (uint32_t i = 0, e = chunks.size(); i != e; ++i) {
     cuIdxs[i] = cuIdx;
     cuIdx += chunks[i].compilationUnits.size();
@@ -2853,18 +2776,18 @@ createSymbols(ArrayRef<std::vector<GdbIndexSection::NameAttrEntry>> nameAttrs,
   // of millions for very large executables, so we use multi-threading to
   // speed it up.
   constexpr size_t numShards = 32;
-  size_t concurrency = PowerOf2Floor(
-      std::min<size_t>(hardware_concurrency(parallel::strategy.ThreadsRequested)
-                           .compute_thread_count(),
-                       numShards));
+  const size_t concurrency =
+      PowerOf2Floor(std::min<size_t>(config->threadCount, numShards));
 
   // A sharded map to uniquify symbols by name.
-  std::vector<DenseMap<CachedHashStringRef, size_t>> map(numShards);
+  auto map =
+      std::make_unique<DenseMap<CachedHashStringRef, size_t>[]>(numShards);
   size_t shift = 32 - countTrailingZeros(numShards);
 
   // Instantiate GdbSymbols while uniqufying them by name.
-  std::vector<std::vector<GdbSymbol>> symbols(numShards);
-  parallelForEachN(0, concurrency, [&](size_t threadId) {
+  auto symbols = std::make_unique<SmallVector<GdbSymbol, 0>[]>(numShards);
+
+  parallelFor(0, concurrency, [&](size_t threadId) {
     uint32_t i = 0;
     for (ArrayRef<NameAttrEntry> entries : nameAttrs) {
       for (const NameAttrEntry &ent : entries) {
@@ -2887,14 +2810,15 @@ createSymbols(ArrayRef<std::vector<GdbIndexSection::NameAttrEntry>> nameAttrs,
   });
 
   size_t numSymbols = 0;
-  for (ArrayRef<GdbSymbol> v : symbols)
+  for (ArrayRef<GdbSymbol> v : ArrayRef(symbols.get(), numShards))
     numSymbols += v.size();
 
   // The return type is a flattened vector, so we'll copy each vector
   // contents to Ret.
-  std::vector<GdbSymbol> ret;
+  SmallVector<GdbSymbol, 0> ret;
   ret.reserve(numSymbols);
-  for (std::vector<GdbSymbol> &vec : symbols)
+  for (SmallVector<GdbSymbol, 0> &vec :
+       MutableArrayRef(symbols.get(), numShards))
     for (GdbSymbol &sym : vec)
       ret.push_back(std::move(sym));
 
@@ -2909,18 +2833,24 @@ createSymbols(ArrayRef<std::vector<GdbIndexSection::NameAttrEntry>> nameAttrs,
     sym.nameOff = off;
     off += sym.name.size() + 1;
   }
+  // If off overflows, the last symbol's nameOff likely overflows.
+  if (!isUInt<32>(off))
+    errorOrWarn("--gdb-index: constant pool size (" + Twine(off) +
+                ") exceeds UINT32_MAX");
 
-  return ret;
+  return {ret, off};
 }
 
 // Returns a newly-created .gdb_index section.
 template <class ELFT> GdbIndexSection *GdbIndexSection::create() {
+  llvm::TimeTraceScope timeScope("Create gdb index");
+
   // Collect InputFiles with .debug_info. See the comment in
   // LLDDwarfObj<ELFT>::LLDDwarfObj. If we do lightweight parsing in the future,
   // note that isec->data() may uncompress the full content, which should be
   // parallelized.
   SetVector<InputFile *> files;
-  for (InputSectionBase *s : inputSections) {
+  for (InputSectionBase *s : ctx.inputSections) {
     InputSection *isec = dyn_cast<InputSection>(s);
     if (!isec)
       continue;
@@ -2933,17 +2863,17 @@ template <class ELFT> GdbIndexSection *GdbIndexSection::create() {
       files.insert(isec->file);
   }
   // Drop .rel[a].debug_gnu_pub{names,types} for --emit-relocs.
-  llvm::erase_if(inputSections, [](InputSectionBase *s) {
+  llvm::erase_if(ctx.inputSections, [](InputSectionBase *s) {
     if (auto *isec = dyn_cast<InputSection>(s))
       if (InputSectionBase *rel = isec->getRelocatedSection())
         return !rel->isLive();
     return !s->isLive();
   });
 
-  std::vector<GdbChunk> chunks(files.size());
-  std::vector<std::vector<NameAttrEntry>> nameAttrs(files.size());
+  SmallVector<GdbChunk, 0> chunks(files.size());
+  SmallVector<SmallVector<NameAttrEntry, 0>, 0> nameAttrs(files.size());
 
-  parallelForEachN(0, files.size(), [&](size_t i) {
+  parallelFor(0, files.size(), [&](size_t i) {
     // To keep memory usage low, we don't want to keep cached DWARFContext, so
     // avoid getDwarf() here.
     ObjFile<ELFT> *file = cast<ObjFile<ELFT>>(files[i]);
@@ -2960,8 +2890,14 @@ template <class ELFT> GdbIndexSection *GdbIndexSection::create() {
 
   auto *ret = make<GdbIndexSection>();
   ret->chunks = std::move(chunks);
-  ret->symbols = createSymbols(nameAttrs, ret->chunks);
-  ret->initOutputSize();
+  std::tie(ret->symbols, ret->size) = createSymbols(nameAttrs, ret->chunks);
+
+  // Count the areas other than the constant pool.
+  ret->size += sizeof(GdbIndexHeader) + ret->computeSymtabSize() * 8;
+  for (GdbChunk &chunk : ret->chunks)
+    ret->size +=
+        chunk.compilationUnits.size() * 16 + chunk.addressAreas.size() * 20;
+
   return ret;
 }
 
@@ -3054,8 +2990,7 @@ void EhFrameHeader::writeTo(uint8_t *buf) {
 void EhFrameHeader::write() {
   uint8_t *buf = Out::bufferStart + getParent()->offset + outSecOff;
   using FdeData = EhFrameSection::FdeData;
-
-  std::vector<FdeData> fdes = getPartition().ehFrame->getFdeData();
+  SmallVector<FdeData, 0> fdes = getPartition().ehFrame->getFdeData();
 
   buf[0] = 1;
   buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4;
@@ -3163,10 +3098,10 @@ size_t VersionTableSection::getSize() const {
 void VersionTableSection::writeTo(uint8_t *buf) {
   buf += 2;
   for (const SymbolTableEntry &s : getPartition().dynSymTab->getSymbols()) {
-    // Use the original versionId for an unfetched lazy symbol (undefined weak),
-    // which must be VER_NDX_GLOBAL (an undefined versioned symbol is an error).
-    write16(buf, s.sym->isLazy() ? static_cast<uint16_t>(VER_NDX_GLOBAL)
-                                 : s.sym->versionId);
+    // For an unextracted lazy symbol (undefined weak), it must have been
+    // converted to Undefined and have VER_NDX_GLOBAL version here.
+    assert(!s.sym->isLazy());
+    write16(buf, s.sym->versionId);
     buf += 2;
   }
 }
@@ -3202,21 +3137,30 @@ VersionNeedSection<ELFT>::VersionNeedSection()
                        ".gnu.version_r") {}
 
 template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() {
-  for (SharedFile *f : sharedFiles) {
+  for (SharedFile *f : ctx.sharedFiles) {
     if (f->vernauxs.empty())
       continue;
     verneeds.emplace_back();
     Verneed &vn = verneeds.back();
     vn.nameStrTab = getPartition().dynStrTab->addString(f->soName);
+    bool isLibc = config->relrGlibc && f->soName.startswith("libc.so.");
+    bool isGlibc2 = false;
     for (unsigned i = 0; i != f->vernauxs.size(); ++i) {
       if (f->vernauxs[i] == 0)
         continue;
       auto *verdef =
           reinterpret_cast<const typename ELFT::Verdef *>(f->verdefs[i]);
-      vn.vernauxs.push_back(
-          {verdef->vd_hash, f->vernauxs[i],
-           getPartition().dynStrTab->addString(f->getStringTable().data() +
-                                               verdef->getAux()->vda_name)});
+      StringRef ver(f->getStringTable().data() + verdef->getAux()->vda_name);
+      if (isLibc && ver.startswith("GLIBC_2."))
+        isGlibc2 = true;
+      vn.vernauxs.push_back({verdef->vd_hash, f->vernauxs[i],
+                             getPartition().dynStrTab->addString(ver)});
+    }
+    if (isGlibc2) {
+      const char *ver = "GLIBC_ABI_DT_RELR";
+      vn.vernauxs.push_back({hashSysV(ver),
+                             ++SharedFile::vernauxNum + getVerDefNum(),
+                             getPartition().dynStrTab->addString(ver)});
     }
   }
 
@@ -3267,14 +3211,14 @@ template <class ELFT> bool VersionNeedSection<ELFT>::isNeeded() const {
 void MergeSyntheticSection::addSection(MergeInputSection *ms) {
   ms->parent = this;
   sections.push_back(ms);
-  assert(alignment == ms->alignment || !(ms->flags & SHF_STRINGS));
-  alignment = std::max(alignment, ms->alignment);
+  assert(addralign == ms->addralign || !(ms->flags & SHF_STRINGS));
+  addralign = std::max(addralign, ms->addralign);
 }
 
 MergeTailSection::MergeTailSection(StringRef name, uint32_t type,
                                    uint64_t flags, uint32_t alignment)
     : MergeSyntheticSection(name, type, flags, alignment),
-      builder(StringTableBuilder::RAW, alignment) {}
+      builder(StringTableBuilder::RAW, llvm::Align(alignment)) {}
 
 size_t MergeTailSection::getSize() const { return builder.getSize(); }
 
@@ -3301,8 +3245,8 @@ void MergeTailSection::finalizeContents() {
 }
 
 void MergeNoTailSection::writeTo(uint8_t *buf) {
-  for (size_t i = 0; i < numShards; ++i)
-    shards[i].write(buf + shardOffsets[i]);
+  parallelFor(0, numShards,
+              [&](size_t i) { shards[i].write(buf + shardOffsets[i]); });
 }
 
 // This function is very hot (i.e. it can take several seconds to finish)
@@ -3316,17 +3260,15 @@ void MergeNoTailSection::writeTo(uint8_t *buf) {
 void MergeNoTailSection::finalizeContents() {
   // Initializes string table builders.
   for (size_t i = 0; i < numShards; ++i)
-    shards.emplace_back(StringTableBuilder::RAW, alignment);
+    shards.emplace_back(StringTableBuilder::RAW, llvm::Align(addralign));
 
   // Concurrency level. Must be a power of 2 to avoid expensive modulo
   // operations in the following tight loop.
-  size_t concurrency = PowerOf2Floor(
-      std::min<size_t>(hardware_concurrency(parallel::strategy.ThreadsRequested)
-                           .compute_thread_count(),
-                       numShards));
+  const size_t concurrency =
+      PowerOf2Floor(std::min<size_t>(config->threadCount, numShards));
 
   // Add section pieces to the builders.
-  parallelForEachN(0, concurrency, [&](size_t threadId) {
+  parallelFor(0, concurrency, [&](size_t threadId) {
     for (MergeInputSection *sec : sections) {
       for (size_t i = 0, e = sec->pieces.size(); i != e; ++i) {
         if (!sec->pieces[i].live)
@@ -3343,7 +3285,7 @@ void MergeNoTailSection::finalizeContents() {
   for (size_t i = 0; i < numShards; ++i) {
     shards[i].finalizeInOrder();
     if (shards[i].getSize() > 0)
-      off = alignTo(off, alignment);
+      off = alignToPowerOf2(off, addralign);
     shardOffsets[i] = off;
     off += shards[i].getSize();
   }
@@ -3359,24 +3301,42 @@ void MergeNoTailSection::finalizeContents() {
   });
 }
 
-MergeSyntheticSection *elf::createMergeSynthetic(StringRef name, uint32_t type,
-                                                 uint64_t flags,
-                                                 uint32_t alignment) {
-  bool shouldTailMerge = (flags & SHF_STRINGS) && config->optimize >= 2;
-  if (shouldTailMerge)
-    return make<MergeTailSection>(name, type, flags, alignment);
-  return make<MergeNoTailSection>(name, type, flags, alignment);
-}
-
 template <class ELFT> void elf::splitSections() {
   llvm::TimeTraceScope timeScope("Split sections");
   // splitIntoPieces needs to be called on each MergeInputSection
   // before calling finalizeContents().
-  parallelForEach(inputSections, [](InputSectionBase *sec) {
-    if (auto *s = dyn_cast<MergeInputSection>(sec))
-      s->splitIntoPieces();
-    else if (auto *eh = dyn_cast<EhInputSection>(sec))
-      eh->split<ELFT>();
+  parallelForEach(ctx.objectFiles, [](ELFFileBase *file) {
+    for (InputSectionBase *sec : file->getSections()) {
+      if (!sec)
+        continue;
+      if (auto *s = dyn_cast<MergeInputSection>(sec))
+        s->splitIntoPieces();
+      else if (auto *eh = dyn_cast<EhInputSection>(sec))
+        eh->split<ELFT>();
+    }
+  });
+}
+
+void elf::combineEhSections() {
+  llvm::TimeTraceScope timeScope("Combine EH sections");
+  for (EhInputSection *sec : ctx.ehInputSections) {
+    EhFrameSection &eh = *sec->getPartition().ehFrame;
+    sec->parent = &eh;
+    eh.addralign = std::max(eh.addralign, sec->addralign);
+    eh.sections.push_back(sec);
+    llvm::append_range(eh.dependentSections, sec->dependentSections);
+  }
+
+  if (!mainPart->armExidx)
+    return;
+  llvm::erase_if(ctx.inputSections, [](InputSectionBase *s) {
+    // Ignore dead sections and the partition end marker (.part.end),
+    // whose partition number is out of bounds.
+    if (!s->isLive() || s->partition == 255)
+      return false;
+    Partition &part = s->getPartition();
+    return s->kind() == SectionBase::Regular && part.armExidx &&
+           part.armExidx->addSection(cast<InputSection>(s));
   });
 }
 
@@ -3478,11 +3438,11 @@ static bool isDuplicateArmExidxSec(InputSection *prev, InputSection *cur) {
 }
 
 // The .ARM.exidx table must be sorted in ascending order of the address of the
-// functions the table describes. Optionally duplicate adjacent table entries
-// can be removed. At the end of the function the executableSections must be
-// sorted in ascending order of address, Sentinel is set to the InputSection
-// with the highest address and any InputSections that have mergeable
-// .ARM.exidx table entries are removed from it.
+// functions the table describes. std::optionally duplicate adjacent table
+// entries can be removed. At the end of the function the executableSections
+// must be sorted in ascending order of address, Sentinel is set to the
+// InputSection with the highest address and any InputSections that have
+// mergeable .ARM.exidx table entries are removed from it.
 void ARMExidxSyntheticSection::finalizeContents() {
   // The executableSections and exidxSections that we use to derive the final
   // contents of this SyntheticSection are populated before
@@ -3518,9 +3478,9 @@ void ARMExidxSyntheticSection::finalizeContents() {
   };
   llvm::stable_sort(executableSections, compareByFilePosition);
   sentinel = executableSections.back();
-  // Optionally merge adjacent duplicate entries.
+  // std::optionally merge adjacent duplicate entries.
   if (config->mergeArmExidx) {
-    std::vector<InputSection *> selectedSections;
+    SmallVector<InputSection *, 0> selectedSections;
     selectedSections.reserve(executableSections.size());
     selectedSections.push_back(executableSections[0]);
     size_t prev = 0;
@@ -3572,8 +3532,8 @@ void ARMExidxSyntheticSection::writeTo(uint8_t *buf) {
   for (InputSection *isec : executableSections) {
     assert(isec->getParent() != nullptr);
     if (InputSection *d = findExidxSection(isec)) {
-      memcpy(buf + offset, d->data().data(), d->data().size());
-      d->relocateAlloc(buf + d->outSecOff, buf + d->outSecOff + d->getSize());
+      memcpy(buf + offset, d->content().data(), d->content().size());
+      target->relocateAlloc(*d, buf + d->outSecOff);
       offset += d->getSize();
     } else {
       // A Linker generated CANTUNWIND section.
@@ -3593,13 +3553,8 @@ void ARMExidxSyntheticSection::writeTo(uint8_t *buf) {
 }
 
 bool ARMExidxSyntheticSection::isNeeded() const {
-  return llvm::find_if(exidxSections, [](InputSection *isec) {
-           return isec->isLive();
-         }) != exidxSections.end();
-}
-
-bool ARMExidxSyntheticSection::classof(const SectionBase *d) {
-  return d->kind() == InputSectionBase::Synthetic && d->type == SHT_ARM_EXIDX;
+  return llvm::any_of(exidxSections,
+                      [](InputSection *isec) { return isec->isLive(); });
 }
 
 ThunkSection::ThunkSection(OutputSection *os, uint64_t off)
@@ -3635,7 +3590,7 @@ InputSection *ThunkSection::getTargetInputSection() const {
 bool ThunkSection::assignOffsets() {
   uint64_t off = 0;
   for (Thunk *t : thunks) {
-    off = alignTo(off, t->alignment);
+    off = alignToPowerOf2(off, t->alignment);
     t->setOffset(off);
     uint32_t size = t->size();
     t->getThunkTargetSym()->size = size;
@@ -3652,8 +3607,8 @@ PPC32Got2Section::PPC32Got2Section()
 bool PPC32Got2Section::isNeeded() const {
   // See the comment below. This is not needed if there is no other
   // InputSection.
-  for (BaseCommand *base : getParent()->sectionCommands)
-    if (auto *isd = dyn_cast<InputSectionDescription>(base))
+  for (SectionCommand *cmd : getParent()->commands)
+    if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
       for (InputSection *isec : isd->sections)
         if (isec != this)
           return true;
@@ -3665,14 +3620,12 @@ void PPC32Got2Section::finalizeContents() {
   // .got2 . This function computes outSecOff of each .got2 to be used in
   // PPC32PltCallStub::writeTo(). The purpose of this empty synthetic section is
   // to collect input sections named ".got2".
-  uint32_t offset = 0;
-  for (BaseCommand *base : getParent()->sectionCommands)
-    if (auto *isd = dyn_cast<InputSectionDescription>(base)) {
+  for (SectionCommand *cmd : getParent()->commands)
+    if (auto *isd = dyn_cast<InputSectionDescription>(cmd)) {
       for (InputSection *isec : isd->sections) {
-        if (isec == this)
-          continue;
-        isec->file->ppc32Got2OutSecOff = offset;
-        offset += (uint32_t)isec->getSize();
+        // isec->file may be nullptr for MergeSyntheticSection.
+        if (isec != this && isec->file)
+          isec->file->ppc32Got2 = isec;
       }
     }
 }
@@ -3691,12 +3644,12 @@ uint64_t PPC64LongBranchTargetSection::getEntryVA(const Symbol *sym,
   return getVA() + entry_index.find({sym, addend})->second * 8;
 }
 
-Optional<uint32_t> PPC64LongBranchTargetSection::addEntry(const Symbol *sym,
-                                                          int64_t addend) {
+std::optional<uint32_t>
+PPC64LongBranchTargetSection::addEntry(const Symbol *sym, int64_t addend) {
   auto res =
       entry_index.try_emplace(std::make_pair(sym, addend), entries.size());
   if (!res.second)
-    return None;
+    return std::nullopt;
   entries.emplace_back(sym, addend);
   return res.first->second;
 }
@@ -3708,7 +3661,7 @@ size_t PPC64LongBranchTargetSection::getSize() const {
 void PPC64LongBranchTargetSection::writeTo(uint8_t *buf) {
   // If linking non-pic we have the final addresses of the targets and they get
   // written to the table directly. For pic the dynamic linker will allocate
-  // the section and fill it it.
+  // the section and fill it.
   if (config->isPic)
     return;
 
@@ -3743,9 +3696,9 @@ static uint8_t getAbiVersion() {
     return 0;
   }
 
-  if (config->emachine == EM_AMDGPU) {
-    uint8_t ver = objectFiles[0]->abiVersion;
-    for (InputFile *file : makeArrayRef(objectFiles).slice(1))
+  if (config->emachine == EM_AMDGPU && !ctx.objectFiles.empty()) {
+    uint8_t ver = ctx.objectFiles[0]->abiVersion;
+    for (InputFile *file : ArrayRef(ctx.objectFiles).slice(1))
       if (file->abiVersion != ver)
         error("incompatible ABI version: " + toString(file));
     return ver;
@@ -3755,10 +3708,6 @@ static uint8_t getAbiVersion() {
 }
 
 template <typename ELFT> void elf::writeEhdr(uint8_t *buf, Partition &part) {
-  // For executable segments, the trap instructions are written before writing
-  // the header. Setting Elf header bytes to zero ensures that any unused bytes
-  // in header are zero-cleared, instead of having trap instructions.
-  memset(buf, 0, sizeof(typename ELFT::Ehdr));
   memcpy(buf, "\177ELF", 4);
 
   auto *eHdr = reinterpret_cast<typename ELFT::Ehdr *>(buf);
@@ -3846,8 +3795,9 @@ void PartitionIndexSection::writeTo(uint8_t *buf) {
     write32(buf, mainPart->dynStrTab->getVA() + partitions[i].nameStrTab - va);
     write32(buf + 4, partitions[i].elfHeader->getVA() - (va + 4));
 
-    SyntheticSection *next =
-        i == partitions.size() - 1 ? in.partEnd : partitions[i + 1].elfHeader;
+    SyntheticSection *next = i == partitions.size() - 1
+                                 ? in.partEnd.get()
+                                 : partitions[i + 1].elfHeader.get();
     write32(buf + 8, next->getVA() - partitions[i].elfHeader->getVA());
 
     va += 12;
@@ -3855,6 +3805,78 @@ void PartitionIndexSection::writeTo(uint8_t *buf) {
   }
 }
 
+void InStruct::reset() {
+  attributes.reset();
+  riscvAttributes.reset();
+  bss.reset();
+  bssRelRo.reset();
+  got.reset();
+  gotPlt.reset();
+  igotPlt.reset();
+  ppc64LongBranchTarget.reset();
+  mipsAbiFlags.reset();
+  mipsGot.reset();
+  mipsOptions.reset();
+  mipsReginfo.reset();
+  mipsRldMap.reset();
+  partEnd.reset();
+  partIndex.reset();
+  plt.reset();
+  iplt.reset();
+  ppc32Got2.reset();
+  ibtPlt.reset();
+  relaPlt.reset();
+  relaIplt.reset();
+  shStrTab.reset();
+  strTab.reset();
+  symTab.reset();
+  symTabShndx.reset();
+}
+
+constexpr char kMemtagAndroidNoteName[] = "Android";
+void MemtagAndroidNote::writeTo(uint8_t *buf) {
+  static_assert(sizeof(kMemtagAndroidNoteName) == 8,
+                "ABI check for Android 11 & 12.");
+  assert((config->androidMemtagStack || config->androidMemtagHeap) &&
+         "Should only be synthesizing a note if heap || stack is enabled.");
+
+  write32(buf, sizeof(kMemtagAndroidNoteName));
+  write32(buf + 4, sizeof(uint32_t));
+  write32(buf + 8, ELF::NT_ANDROID_TYPE_MEMTAG);
+  memcpy(buf + 12, kMemtagAndroidNoteName, sizeof(kMemtagAndroidNoteName));
+  buf += 12 + sizeof(kMemtagAndroidNoteName);
+
+  uint32_t value = 0;
+  value |= config->androidMemtagMode;
+  if (config->androidMemtagHeap)
+    value |= ELF::NT_MEMTAG_HEAP;
+  // Note, MTE stack is an ABI break. Attempting to run an MTE stack-enabled
+  // binary on Android 11 or 12 will result in a checkfail in the loader.
+  if (config->androidMemtagStack)
+    value |= ELF::NT_MEMTAG_STACK;
+  write32(buf, value); // note value
+}
+
+size_t MemtagAndroidNote::getSize() const {
+  return sizeof(llvm::ELF::Elf64_Nhdr) +
+         /*namesz=*/sizeof(kMemtagAndroidNoteName) +
+         /*descsz=*/sizeof(uint32_t);
+}
+
+void PackageMetadataNote::writeTo(uint8_t *buf) {
+  write32(buf, 4);
+  write32(buf + 4, config->packageMetadata.size() + 1);
+  write32(buf + 8, FDO_PACKAGING_METADATA);
+  memcpy(buf + 12, "FDO", 4);
+  memcpy(buf + 16, config->packageMetadata.data(),
+         config->packageMetadata.size());
+}
+
+size_t PackageMetadataNote::getSize() const {
+  return sizeof(llvm::ELF::Elf64_Nhdr) + 4 +
+         alignTo(config->packageMetadata.size() + 1, 4);
+}
+
 InStruct elf::in;
 
 std::vector<Partition> elf::partitions;
index bc79fcd..391eb6b 100644 (file)
 #ifndef LLD_ELF_SYNTHETIC_SECTIONS_H
 #define LLD_ELF_SYNTHETIC_SECTIONS_H
 
-#include "DWARF.h"
-#include "EhFrame.h"
+#include "Config.h"
 #include "InputSection.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/MC/StringTableBuilder.h"
+#include "llvm/Support/Compiler.h"
 #include "llvm/Support/Endian.h"
-#include <functional>
+#include "llvm/Support/Parallel.h"
+#include "llvm/Support/Threading.h"
 
-namespace lld {
-namespace elf {
+namespace lld::elf {
 class Defined;
 struct PhdrEntry;
 class SymbolTableBaseSection;
-class VersionNeedBaseSection;
-
-class SyntheticSection : public InputSection {
-public:
-  SyntheticSection(uint64_t flags, uint32_t type, uint32_t alignment,
-                   StringRef name)
-      : InputSection(nullptr, flags, type, alignment, {}, name,
-                     InputSectionBase::Synthetic) {
-    markLive();
-  }
-
-  virtual ~SyntheticSection() = default;
-  virtual void writeTo(uint8_t *buf) = 0;
-  virtual size_t getSize() const = 0;
-  virtual void finalizeContents() {}
-  // If the section has the SHF_ALLOC flag and the size may be changed if
-  // thunks are added, update the section size.
-  virtual bool updateAllocSize() { return false; }
-  virtual bool isNeeded() const { return true; }
-
-  static bool classof(const SectionBase *d) {
-    return d->kind() == InputSectionBase::Synthetic;
-  }
-};
 
 struct CieRecord {
   EhSectionPiece *cie = nullptr;
-  std::vector<EhSectionPiece *> fdes;
+  SmallVector<EhSectionPiece *, 0> fdes;
 };
 
 // Section for .eh_frame.
@@ -77,9 +53,7 @@ public:
     return SyntheticSection::classof(d) && d->name == ".eh_frame";
   }
 
-  void addSection(EhInputSection *sec);
-
-  std::vector<EhInputSection *> sections;
+  SmallVector<EhInputSection *, 0> sections;
   size_t numFdes = 0;
 
   struct FdeData {
@@ -87,7 +61,7 @@ public:
     uint32_t fdeVARel;
   };
 
-  std::vector<FdeData> getFdeData() const;
+  SmallVector<FdeData, 0> getFdeData() const;
   ArrayRef<CieRecord *> getCieRecords() const { return cieRecords; }
   template <class ELFT>
   void iterateFDEWithLSDA(llvm::function_ref<void(InputSection &)> fn);
@@ -115,13 +89,13 @@ private:
 
   uint64_t getFdePc(uint8_t *buf, size_t off, uint8_t enc) const;
 
-  std::vector<CieRecord *> cieRecords;
+  SmallVector<CieRecord *, 0> cieRecords;
 
   // CIE records are uniquified by their contents and personality functions.
   llvm::DenseMap<std::pair<ArrayRef<uint8_t>, Symbol *>, CieRecord *> cieMap;
 };
 
-class GotSection : public SyntheticSection {
+class GotSection final : public SyntheticSection {
 public:
   GotSection();
   size_t getSize() const override { return size; }
@@ -129,9 +103,13 @@ public:
   bool isNeeded() const override;
   void writeTo(uint8_t *buf) override;
 
+  void addConstant(const Relocation &r);
   void addEntry(Symbol &sym);
+  bool addTlsDescEntry(Symbol &sym);
   bool addDynTlsEntry(Symbol &sym);
   bool addTlsIndex();
+  uint32_t getTlsDescOffset(const Symbol &sym) const;
+  uint64_t getTlsDescAddr(const Symbol &sym) const;
   uint64_t getGlobalDynAddr(const Symbol &b) const;
   uint64_t getGlobalDynOffset(const Symbol &b) const;
 
@@ -140,7 +118,7 @@ public:
 
   // Flag to force GOT to be in output if we have relocations
   // that relies on its address.
-  bool hasGotOffRel = false;
+  std::atomic<bool> hasGotOffRel = false;
 
 protected:
   size_t numEntries = 0;
@@ -157,7 +135,7 @@ public:
   size_t getSize() const override { return 0; }
 };
 
-class GnuPropertySection : public SyntheticSection {
+class GnuPropertySection final : public SyntheticSection {
 public:
   GnuPropertySection();
   void writeTo(uint8_t *buf) override;
@@ -186,10 +164,8 @@ private:
 // respectively.
 class BssSection final : public SyntheticSection {
 public:
-  BssSection(StringRef name, uint64_t size, uint32_t alignment);
-  void writeTo(uint8_t *) override {
-    llvm_unreachable("unexpected writeTo() call for SHT_NOBITS section");
-  }
+  BssSection(StringRef name, uint64_t size, uint32_t addralign);
+  void writeTo(uint8_t *) override {}
   bool isNeeded() const override { return size != 0; }
   size_t getSize() const override { return size; }
 
@@ -384,10 +360,10 @@ public:
 
   // Flag to force GotPlt to be in output if we have relocations
   // that relies on its address.
-  bool hasGotPltOffRel = false;
+  std::atomic<bool> hasGotPltOffRel = false;
 
 private:
-  std::vector<const Symbol *> entries;
+  SmallVector<const Symbol *, 0> entries;
 };
 
 // The IgotPltSection is a Got associated with the PltSection for GNU Ifunc
@@ -403,7 +379,7 @@ public:
   bool isNeeded() const override { return !entries.empty(); }
 
 private:
-  std::vector<const Symbol *> entries;
+  SmallVector<const Symbol *, 0> entries;
 };
 
 class StringTableSection final : public SyntheticSection {
@@ -419,8 +395,8 @@ private:
 
   uint64_t size = 0;
 
-  llvm::DenseMap<StringRef, unsigned> stringMap;
-  std::vector<StringRef> strings;
+  llvm::DenseMap<llvm::CachedHashStringRef, unsigned> stringMap;
+  SmallVector<StringRef, 0> strings;
 };
 
 class DynamicReloc {
@@ -449,21 +425,21 @@ public:
   DynamicReloc(RelType type, const InputSectionBase *inputSec,
                uint64_t offsetInSec, Kind kind, Symbol &sym, int64_t addend,
                RelExpr expr)
-      : type(type), sym(&sym), inputSec(inputSec), offsetInSec(offsetInSec),
-        kind(kind), expr(expr), addend(addend) {}
+      : sym(&sym), inputSec(inputSec), offsetInSec(offsetInSec), type(type),
+        addend(addend), kind(kind), expr(expr) {}
   /// This constructor records a relative relocation with no symbol.
   DynamicReloc(RelType type, const InputSectionBase *inputSec,
                uint64_t offsetInSec, int64_t addend = 0)
-      : type(type), sym(nullptr), inputSec(inputSec), offsetInSec(offsetInSec),
-        kind(AddendOnly), expr(R_ADDEND), addend(addend) {}
+      : sym(nullptr), inputSec(inputSec), offsetInSec(offsetInSec), type(type),
+        addend(addend), kind(AddendOnly), expr(R_ADDEND) {}
   /// This constructor records dynamic relocation settings used by the MIPS
   /// multi-GOT implementation.
   DynamicReloc(RelType type, const InputSectionBase *inputSec,
                uint64_t offsetInSec, const OutputSection *outputSec,
                int64_t addend)
-      : type(type), sym(nullptr), inputSec(inputSec), offsetInSec(offsetInSec),
-        kind(MipsMultiGotPage), expr(R_ADDEND), addend(addend),
-        outputSec(outputSec) {}
+      : sym(nullptr), outputSec(outputSec), inputSec(inputSec),
+        offsetInSec(offsetInSec), type(type), addend(addend),
+        kind(MipsMultiGotPage), expr(R_ADDEND) {}
 
   uint64_t getOffset() const;
   uint32_t getSymIndex(SymbolTableBaseSection *symTab) const;
@@ -476,26 +452,29 @@ public:
   /// address/the address of the corresponding GOT entry/etc.
   int64_t computeAddend() const;
 
-  RelType type;
+  void computeRaw(SymbolTableBaseSection *symtab);
+
   Symbol *sym;
+  const OutputSection *outputSec = nullptr;
   const InputSectionBase *inputSec;
   uint64_t offsetInSec;
+  uint64_t r_offset;
+  RelType type;
+  uint32_t r_sym;
+  // Initially input addend, then the output addend after
+  // RelocationSection<ELFT>::writeTo.
+  int64_t addend;
 
 private:
   Kind kind;
   // The kind of expression used to calculate the added (required e.g. for
   // relative GOT relocations).
   RelExpr expr;
-  int64_t addend;
-  const OutputSection *outputSec = nullptr;
 };
 
 template <class ELFT> class DynamicSection final : public SyntheticSection {
   LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
 
-  // finalizeContents() fills this vector with the section contents.
-  std::vector<std::pair<int32_t, std::function<uint64_t()>>> entries;
-
 public:
   DynamicSection();
   void finalizeContents() override;
@@ -503,46 +482,61 @@ public:
   size_t getSize() const override { return size; }
 
 private:
-  void add(int32_t tag, std::function<uint64_t()> fn);
-  void addInt(int32_t tag, uint64_t val);
-  void addInSec(int32_t tag, InputSection *sec);
-  void addInSecRelative(int32_t tag, InputSection *sec);
-  void addOutSec(int32_t tag, OutputSection *sec);
-  void addSize(int32_t tag, OutputSection *sec);
-  void addSym(int32_t tag, Symbol *sym);
-
+  std::vector<std::pair<int32_t, uint64_t>> computeContents();
   uint64_t size = 0;
 };
 
 class RelocationBaseSection : public SyntheticSection {
 public:
   RelocationBaseSection(StringRef name, uint32_t type, int32_t dynamicTag,
-                        int32_t sizeDynamicTag);
+                        int32_t sizeDynamicTag, bool combreloc,
+                        unsigned concurrency);
   /// Add a dynamic relocation without writing an addend to the output section.
   /// This overload can be used if the addends are written directly instead of
   /// using relocations on the input section (e.g. MipsGotSection::writeTo()).
-  void addReloc(const DynamicReloc &reloc);
+  template <bool shard = false> void addReloc(const DynamicReloc &reloc) {
+    relocs.push_back(reloc);
+  }
   /// Add a dynamic relocation against \p sym with an optional addend.
-  void addSymbolReloc(RelType dynType, InputSectionBase *isec,
+  void addSymbolReloc(RelType dynType, InputSectionBase &isec,
                       uint64_t offsetInSec, Symbol &sym, int64_t addend = 0,
-                      llvm::Optional<RelType> addendRelType = llvm::None);
+                      std::optional<RelType> addendRelType = {});
   /// Add a relative dynamic relocation that uses the target address of \p sym
   /// (i.e. InputSection::getRelocTargetVA()) + \p addend as the addend.
-  void addRelativeReloc(RelType dynType, InputSectionBase *isec,
+  /// This function should only be called for non-preemptible symbols or
+  /// RelExpr values that refer to an address inside the output file (e.g. the
+  /// address of the GOT entry for a potentially preemptible symbol).
+  template <bool shard = false>
+  void addRelativeReloc(RelType dynType, InputSectionBase &isec,
                         uint64_t offsetInSec, Symbol &sym, int64_t addend,
-                        RelType addendRelType, RelExpr expr);
+                        RelType addendRelType, RelExpr expr) {
+    assert(expr != R_ADDEND && "expected non-addend relocation expression");
+    addReloc<shard>(DynamicReloc::AddendOnlyWithTargetVA, dynType, isec,
+                    offsetInSec, sym, addend, expr, addendRelType);
+  }
   /// Add a dynamic relocation using the target address of \p sym as the addend
   /// if \p sym is non-preemptible. Otherwise add a relocation against \p sym.
-  void addAddendOnlyRelocIfNonPreemptible(RelType dynType,
-                                          InputSectionBase *isec,
+  void addAddendOnlyRelocIfNonPreemptible(RelType dynType, GotSection &sec,
                                           uint64_t offsetInSec, Symbol &sym,
                                           RelType addendRelType);
-  void addReloc(DynamicReloc::Kind kind, RelType dynType,
-                InputSectionBase *inputSec, uint64_t offsetInSec, Symbol &sym,
-                int64_t addend, RelExpr expr, RelType addendRelType);
-  bool isNeeded() const override { return !relocs.empty(); }
+  template <bool shard = false>
+  void addReloc(DynamicReloc::Kind kind, RelType dynType, InputSectionBase &sec,
+                uint64_t offsetInSec, Symbol &sym, int64_t addend, RelExpr expr,
+                RelType addendRelType) {
+    // Write the addends to the relocated address if required. We skip
+    // it if the written value would be zero.
+    if (config->writeAddends && (expr != R_ADDEND || addend != 0))
+      sec.addReloc({expr, addendRelType, offsetInSec, addend, &sym});
+    addReloc<shard>({dynType, &sec, offsetInSec, kind, sym, addend, expr});
+  }
+  bool isNeeded() const override {
+    return !relocs.empty() ||
+           llvm::any_of(relocsVec, [](auto &v) { return !v.empty(); });
+  }
   size_t getSize() const override { return relocs.size() * this->entsize; }
   size_t getRelativeRelocCount() const { return numRelativeRelocs; }
+  void mergeRels();
+  void partitionRels();
   void finalizeContents() override;
   static bool classof(const SectionBase *d) {
     return SyntheticSection::classof(d) &&
@@ -550,23 +544,30 @@ public:
             d->type == llvm::ELF::SHT_RELR);
   }
   int32_t dynamicTag, sizeDynamicTag;
-  std::vector<DynamicReloc> relocs;
+  SmallVector<DynamicReloc, 0> relocs;
 
 protected:
-  size_t numRelativeRelocs = 0;
+  void computeRels();
+  // Used when parallel relocation scanning adds relocations. The elements
+  // will be moved into relocs by mergeRel().
+  SmallVector<SmallVector<DynamicReloc, 0>, 0> relocsVec;
+  size_t numRelativeRelocs = 0; // used by -z combreloc
+  bool combreloc;
 };
 
+template <>
+inline void RelocationBaseSection::addReloc<true>(const DynamicReloc &reloc) {
+  relocsVec[llvm::parallel::getThreadIndex()].push_back(reloc);
+}
+
 template <class ELFT>
 class RelocationSection final : public RelocationBaseSection {
   using Elf_Rel = typename ELFT::Rel;
   using Elf_Rela = typename ELFT::Rela;
 
 public:
-  RelocationSection(StringRef name, bool sort);
+  RelocationSection(StringRef name, bool combreloc, unsigned concurrency);
   void writeTo(uint8_t *buf) override;
-
-private:
-  bool sort;
 };
 
 template <class ELFT>
@@ -575,7 +576,7 @@ class AndroidPackedRelocationSection final : public RelocationBaseSection {
   using Elf_Rela = typename ELFT::Rela;
 
 public:
-  AndroidPackedRelocationSection(StringRef name);
+  AndroidPackedRelocationSection(StringRef name, unsigned concurrency);
 
   bool updateAllocSize() override;
   size_t getSize() const override { return relocData.size(); }
@@ -596,9 +597,14 @@ struct RelativeReloc {
 
 class RelrBaseSection : public SyntheticSection {
 public:
-  RelrBaseSection();
-  bool isNeeded() const override { return !relocs.empty(); }
-  std::vector<RelativeReloc> relocs;
+  RelrBaseSection(unsigned concurrency);
+  void mergeRels();
+  bool isNeeded() const override {
+    return !relocs.empty() ||
+           llvm::any_of(relocsVec, [](auto &v) { return !v.empty(); });
+  }
+  SmallVector<RelativeReloc, 0> relocs;
+  SmallVector<SmallVector<RelativeReloc, 0>, 0> relocsVec;
 };
 
 // RelrSection is used to encode offsets for relative relocations.
@@ -609,7 +615,7 @@ template <class ELFT> class RelrSection final : public RelrBaseSection {
   using Elf_Relr = typename ELFT::Relr;
 
 public:
-  RelrSection();
+  RelrSection(unsigned concurrency);
 
   bool updateAllocSize() override;
   size_t getSize() const override { return relrRelocs.size() * this->entsize; }
@@ -618,7 +624,7 @@ public:
   }
 
 private:
-  std::vector<Elf_Relr> relrRelocs;
+  SmallVector<Elf_Relr, 0> relrRelocs;
 };
 
 struct SymbolTableEntry {
@@ -640,7 +646,7 @@ protected:
   void sortSymTabSymbols();
 
   // A vector of symbols and their string table offsets.
-  std::vector<SymbolTableEntry> symbols;
+  SmallVector<SymbolTableEntry, 0> symbols;
 
   StringTableSection &strTabSec;
 
@@ -679,15 +685,12 @@ public:
 
   // Adds symbols to the hash table.
   // Sorts the input to satisfy GNU hash section requirements.
-  void addSymbols(std::vector<SymbolTableEntry> &symbols);
+  void addSymbols(llvm::SmallVectorImpl<SymbolTableEntry> &symbols);
 
 private:
   // See the comment in writeBloomFilter.
   enum { Shift2 = 26 };
 
-  void writeBloomFilter(uint8_t *buf);
-  void writeHashTable(uint8_t *buf);
-
   struct Entry {
     Symbol *sym;
     size_t strTabOffset;
@@ -695,7 +698,7 @@ private:
     uint32_t bucketIdx;
   };
 
-  std::vector<Entry> symbols;
+  SmallVector<Entry, 0> symbols;
   size_t maskWords;
   size_t nBuckets = 0;
   size_t size = 0;
@@ -735,7 +738,7 @@ public:
 
   size_t headerSize;
 
-  std::vector<const Symbol *> entries;
+  SmallVector<const Symbol *, 0> entries;
 };
 
 // Used for non-preemptible ifuncs. It does not have a header. Each entry is
@@ -743,7 +746,7 @@ public:
 // runtime. PltSection can only contain entries associated with JUMP_SLOT
 // relocations, so IPLT entries are in a separate section.
 class IpltSection final : public SyntheticSection {
-  std::vector<const Symbol *> entries;
+  SmallVector<const Symbol *, 0> entries;
 
 public:
   IpltSection();
@@ -760,7 +763,7 @@ public:
   void writeTo(uint8_t *buf) override;
   size_t getSize() const override;
 
-  std::vector<const Symbol *> canonical_plts;
+  SmallVector<const Symbol *, 0> canonical_plts;
   static constexpr size_t footerSize = 64;
 };
 
@@ -794,13 +797,13 @@ public:
 
   struct GdbChunk {
     InputSection *sec;
-    std::vector<AddressEntry> addressAreas;
-    std::vector<CuEntry> compilationUnits;
+    SmallVector<AddressEntry, 0> addressAreas;
+    SmallVector<CuEntry, 0> compilationUnits;
   };
 
   struct GdbSymbol {
     llvm::CachedHashStringRef name;
-    std::vector<uint32_t> cuVector;
+    SmallVector<uint32_t, 0> cuVector;
     uint32_t nameOff;
     uint32_t cuVectorOff;
   };
@@ -821,15 +824,14 @@ private:
     llvm::support::ulittle32_t constantPoolOff;
   };
 
-  void initOutputSize();
   size_t computeSymtabSize() const;
 
   // Each chunk contains information gathered from debug sections of a
   // single object file.
-  std::vector<GdbChunk> chunks;
+  SmallVector<GdbChunk, 0> chunks;
 
   // A symbol table for this .gdb_index section.
-  std::vector<GdbSymbol> symbols;
+  SmallVector<GdbSymbol, 0> symbols;
 
   size_t size;
 };
@@ -873,7 +875,7 @@ private:
   StringRef getFileDefName();
 
   unsigned fileDefNameOff;
-  std::vector<unsigned> verDefNameOffs;
+  SmallVector<unsigned, 0> verDefNameOffs;
 };
 
 // The .gnu.version section specifies the required version of each symbol in the
@@ -912,7 +914,7 @@ class VersionNeedSection final : public SyntheticSection {
     std::vector<Vernaux> vernauxs;
   };
 
-  std::vector<Verneed> verneeds;
+  SmallVector<Verneed, 0> verneeds;
 
 public:
   VersionNeedSection();
@@ -929,18 +931,18 @@ public:
 class MergeSyntheticSection : public SyntheticSection {
 public:
   void addSection(MergeInputSection *ms);
-  std::vector<MergeInputSection *> sections;
+  SmallVector<MergeInputSection *, 0> sections;
 
 protected:
   MergeSyntheticSection(StringRef name, uint32_t type, uint64_t flags,
-                        uint32_t alignment)
-      : SyntheticSection(flags, type, alignment, name) {}
+                        uint32_t addralign)
+      : SyntheticSection(flags, type, addralign, name) {}
 };
 
 class MergeTailSection final : public MergeSyntheticSection {
 public:
   MergeTailSection(StringRef name, uint32_t type, uint64_t flags,
-                   uint32_t alignment);
+                   uint32_t addralign);
 
   size_t getSize() const override;
   void writeTo(uint8_t *buf) override;
@@ -953,8 +955,8 @@ private:
 class MergeNoTailSection final : public MergeSyntheticSection {
 public:
   MergeNoTailSection(StringRef name, uint32_t type, uint64_t flags,
-                     uint32_t alignment)
-      : MergeSyntheticSection(name, type, flags, alignment) {}
+                     uint32_t addralign)
+      : MergeSyntheticSection(name, type, flags, addralign) {}
 
   size_t getSize() const override { return size; }
   void writeTo(uint8_t *buf) override;
@@ -965,7 +967,7 @@ private:
   // The reason why we don't want to use the least significant bits is
   // because DenseMap also uses lower bits to determine a bucket ID.
   // If we use lower bits, it significantly increases the probability of
-  // hash collisons.
+  // hash collisions.
   size_t getShardId(uint32_t hash) {
     assert((hash >> 31) == 0);
     return hash >> (31 - llvm::countTrailingZeros(numShards));
@@ -976,7 +978,7 @@ private:
 
   // String table contents
   constexpr static size_t numShards = 32;
-  std::vector<llvm::StringTableBuilder> shards;
+  SmallVector<llvm::StringTableBuilder, 0> shards;
   size_t shardOffsets[numShards];
 };
 
@@ -986,7 +988,7 @@ class MipsAbiFlagsSection final : public SyntheticSection {
   using Elf_Mips_ABIFlags = llvm::object::Elf_Mips_ABIFlags<ELFT>;
 
 public:
-  static MipsAbiFlagsSection *create();
+  static std::unique_ptr<MipsAbiFlagsSection> create();
 
   MipsAbiFlagsSection(Elf_Mips_ABIFlags flags);
   size_t getSize() const override { return sizeof(Elf_Mips_ABIFlags); }
@@ -1002,7 +1004,7 @@ template <class ELFT> class MipsOptionsSection final : public SyntheticSection {
   using Elf_Mips_RegInfo = llvm::object::Elf_Mips_RegInfo<ELFT>;
 
 public:
-  static MipsOptionsSection *create();
+  static std::unique_ptr<MipsOptionsSection<ELFT>> create();
 
   MipsOptionsSection(Elf_Mips_RegInfo reginfo);
   void writeTo(uint8_t *buf) override;
@@ -1020,7 +1022,7 @@ template <class ELFT> class MipsReginfoSection final : public SyntheticSection {
   using Elf_Mips_RegInfo = llvm::object::Elf_Mips_RegInfo<ELFT>;
 
 public:
-  static MipsReginfoSection *create();
+  static std::unique_ptr<MipsReginfoSection> create();
 
   MipsReginfoSection(Elf_Mips_RegInfo reginfo);
   size_t getSize() const override { return sizeof(Elf_Mips_RegInfo); }
@@ -1034,7 +1036,7 @@ private:
 // 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
-class MipsRldMapSection : public SyntheticSection {
+class MipsRldMapSection final : public SyntheticSection {
 public:
   MipsRldMapSection();
   size_t getSize() const override { return config->wordsize; }
@@ -1090,11 +1092,14 @@ public:
   void finalizeContents() override;
   InputSection *getLinkOrderDep() const;
 
-  static bool classof(const SectionBase *d);
+  static bool classof(const SectionBase *sec) {
+    return sec->kind() == InputSectionBase::Synthetic &&
+           sec->type == llvm::ELF::SHT_ARM_EXIDX;
+  }
 
   // Links to the ARMExidxSections so we can transfer the relocations once the
   // layout is known.
-  std::vector<InputSection *> exidxSections;
+  SmallVector<InputSection *, 0> exidxSections;
 
 private:
   size_t size = 0;
@@ -1103,7 +1108,7 @@ private:
   // InputObjects, we store pointers to the executable sections that need
   // .ARM.exidx sections. We can then use the dependentSections of these to
   // either find the .ARM.exidx section or know that we need to generate one.
-  std::vector<InputSection *> executableSections;
+  SmallVector<InputSection *, 0> executableSections;
 
   // The executable InputSection with the highest address to use for the
   // sentinel. We store separately from ExecutableSections as merging of
@@ -1114,7 +1119,7 @@ private:
 
 // A container for one or more linker generated thunks. Instances of these
 // thunks including ARM interworking and Mips LA25 PI to non-PI thunks.
-class ThunkSection : public SyntheticSection {
+class ThunkSection final : public SyntheticSection {
 public:
   // ThunkSection in OS, with desired outSecOff of Off
   ThunkSection(OutputSection *os, uint64_t off);
@@ -1134,7 +1139,7 @@ public:
   bool roundUpSizeForErrata = false;
 
 private:
-  std::vector<Thunk *> thunks;
+  SmallVector<Thunk *, 0> thunks;
   size_t size = 0;
 };
 
@@ -1158,20 +1163,20 @@ class PPC64LongBranchTargetSection final : public SyntheticSection {
 public:
   PPC64LongBranchTargetSection();
   uint64_t getEntryVA(const Symbol *sym, int64_t addend);
-  llvm::Optional<uint32_t> addEntry(const Symbol *sym, int64_t addend);
+  std::optional<uint32_t> addEntry(const Symbol *sym, int64_t addend);
   size_t getSize() const override;
   void writeTo(uint8_t *buf) override;
   bool isNeeded() const override;
   void finalizeContents() override { finalized = true; }
 
 private:
-  std::vector<std::pair<const Symbol *, int64_t>> entries;
+  SmallVector<std::pair<const Symbol *, int64_t>, 0> entries;
   llvm::DenseMap<std::pair<const Symbol *, int64_t>, uint32_t> entry_index;
   bool finalized = false;
 };
 
 template <typename ELFT>
-class PartitionElfHeaderSection : public SyntheticSection {
+class PartitionElfHeaderSection final : public SyntheticSection {
 public:
   PartitionElfHeaderSection();
   size_t getSize() const override;
@@ -1179,14 +1184,14 @@ public:
 };
 
 template <typename ELFT>
-class PartitionProgramHeadersSection : public SyntheticSection {
+class PartitionProgramHeadersSection final : public SyntheticSection {
 public:
   PartitionProgramHeadersSection();
   size_t getSize() const override;
   void writeTo(uint8_t *buf) override;
 };
 
-class PartitionIndexSection : public SyntheticSection {
+class PartitionIndexSection final : public SyntheticSection {
 public:
   PartitionIndexSection();
   size_t getSize() const override;
@@ -1194,11 +1199,31 @@ public:
   void writeTo(uint8_t *buf) override;
 };
 
+// See the following link for the Android-specific loader code that operates on
+// this section:
+// https://cs.android.com/android/platform/superproject/+/master:bionic/libc/bionic/libc_init_static.cpp;drc=9425b16978f9c5aa8f2c50c873db470819480d1d;l=192
+class MemtagAndroidNote final : public SyntheticSection {
+public:
+  MemtagAndroidNote()
+      : SyntheticSection(llvm::ELF::SHF_ALLOC, llvm::ELF::SHT_NOTE,
+                         /*alignment=*/4, ".note.android.memtag") {}
+  void writeTo(uint8_t *buf) override;
+  size_t getSize() const override;
+};
+
+class PackageMetadataNote final : public SyntheticSection {
+public:
+  PackageMetadataNote()
+      : SyntheticSection(llvm::ELF::SHF_ALLOC, llvm::ELF::SHT_NOTE,
+                         /*alignment=*/4, ".note.package") {}
+  void writeTo(uint8_t *buf) override;
+  size_t getSize() const override;
+};
+
 InputSection *createInterpSection();
 MergeInputSection *createCommentSection();
-MergeSyntheticSection *createMergeSynthetic(StringRef name, uint32_t type,
-                                            uint64_t flags, uint32_t alignment);
 template <class ELFT> void splitSections();
+void combineEhSections();
 
 template <typename ELFT> void writeEhdr(uint8_t *buf, Partition &part);
 template <typename ELFT> void writePhdrs(uint8_t *buf, Partition &part);
@@ -1213,29 +1238,31 @@ struct Partition {
   StringRef name;
   uint64_t nameStrTab;
 
-  SyntheticSection *elfHeader;
-  SyntheticSection *programHeaders;
-  std::vector<PhdrEntry *> phdrs;
-
-  ARMExidxSyntheticSection *armExidx;
-  BuildIdSection *buildId;
-  SyntheticSection *dynamic;
-  StringTableSection *dynStrTab;
-  SymbolTableBaseSection *dynSymTab;
-  EhFrameHeader *ehFrameHdr;
-  EhFrameSection *ehFrame;
-  GnuHashTableSection *gnuHashTab;
-  HashTableSection *hashTab;
-  RelocationBaseSection *relaDyn;
-  RelrBaseSection *relrDyn;
-  VersionDefinitionSection *verDef;
-  SyntheticSection *verNeed;
-  VersionTableSection *verSym;
+  std::unique_ptr<SyntheticSection> elfHeader;
+  std::unique_ptr<SyntheticSection> programHeaders;
+  SmallVector<PhdrEntry *, 0> phdrs;
+
+  std::unique_ptr<ARMExidxSyntheticSection> armExidx;
+  std::unique_ptr<BuildIdSection> buildId;
+  std::unique_ptr<SyntheticSection> dynamic;
+  std::unique_ptr<StringTableSection> dynStrTab;
+  std::unique_ptr<SymbolTableBaseSection> dynSymTab;
+  std::unique_ptr<EhFrameHeader> ehFrameHdr;
+  std::unique_ptr<EhFrameSection> ehFrame;
+  std::unique_ptr<GnuHashTableSection> gnuHashTab;
+  std::unique_ptr<HashTableSection> hashTab;
+  std::unique_ptr<MemtagAndroidNote> memtagAndroidNote;
+  std::unique_ptr<PackageMetadataNote> packageMetadataNote;
+  std::unique_ptr<RelocationBaseSection> relaDyn;
+  std::unique_ptr<RelrBaseSection> relrDyn;
+  std::unique_ptr<VersionDefinitionSection> verDef;
+  std::unique_ptr<SyntheticSection> verNeed;
+  std::unique_ptr<VersionTableSection> verSym;
 
   unsigned getNumber() const { return this - &partitions[0] + 1; }
 };
 
-extern Partition *mainPart;
+LLVM_LIBRARY_VISIBILITY extern Partition *mainPart;
 
 inline Partition &SectionBase::getPartition() const {
   assert(isLive());
@@ -1245,32 +1272,37 @@ inline Partition &SectionBase::getPartition() const {
 // Linker generated sections which can be used as inputs and are not specific to
 // a partition.
 struct InStruct {
-  InputSection *attributes;
-  BssSection *bss;
-  BssSection *bssRelRo;
-  GotSection *got;
-  GotPltSection *gotPlt;
-  IgotPltSection *igotPlt;
-  PPC64LongBranchTargetSection *ppc64LongBranchTarget;
-  MipsGotSection *mipsGot;
-  MipsRldMapSection *mipsRldMap;
-  SyntheticSection *partEnd;
-  SyntheticSection *partIndex;
-  PltSection *plt;
-  IpltSection *iplt;
-  PPC32Got2Section *ppc32Got2;
-  IBTPltSection *ibtPlt;
-  RelocationBaseSection *relaPlt;
-  RelocationBaseSection *relaIplt;
-  StringTableSection *shStrTab;
-  StringTableSection *strTab;
-  SymbolTableBaseSection *symTab;
-  SymtabShndxSection *symTabShndx;
+  std::unique_ptr<InputSection> attributes;
+  std::unique_ptr<SyntheticSection> riscvAttributes;
+  std::unique_ptr<BssSection> bss;
+  std::unique_ptr<BssSection> bssRelRo;
+  std::unique_ptr<GotSection> got;
+  std::unique_ptr<GotPltSection> gotPlt;
+  std::unique_ptr<IgotPltSection> igotPlt;
+  std::unique_ptr<PPC64LongBranchTargetSection> ppc64LongBranchTarget;
+  std::unique_ptr<SyntheticSection> mipsAbiFlags;
+  std::unique_ptr<MipsGotSection> mipsGot;
+  std::unique_ptr<SyntheticSection> mipsOptions;
+  std::unique_ptr<SyntheticSection> mipsReginfo;
+  std::unique_ptr<MipsRldMapSection> mipsRldMap;
+  std::unique_ptr<SyntheticSection> partEnd;
+  std::unique_ptr<SyntheticSection> partIndex;
+  std::unique_ptr<PltSection> plt;
+  std::unique_ptr<IpltSection> iplt;
+  std::unique_ptr<PPC32Got2Section> ppc32Got2;
+  std::unique_ptr<IBTPltSection> ibtPlt;
+  std::unique_ptr<RelocationBaseSection> relaPlt;
+  std::unique_ptr<RelocationBaseSection> relaIplt;
+  std::unique_ptr<StringTableSection> shStrTab;
+  std::unique_ptr<StringTableSection> strTab;
+  std::unique_ptr<SymbolTableBaseSection> symTab;
+  std::unique_ptr<SymtabShndxSection> symTabShndx;
+
+  void reset();
 };
 
-extern InStruct in;
+LLVM_LIBRARY_VISIBILITY extern InStruct in;
 
-} // namespace elf
-} // namespace lld
+} // namespace lld::elf
 
 #endif
index e8de5f0..76aea25 100644 (file)
@@ -11,6 +11,7 @@
 #include "ARMErrataFix.h"
 #include "CallGraphSort.h"
 #include "Config.h"
+#include "InputFiles.h"
 #include "LinkerScript.h"
 #include "MapFile.h"
 #include "OutputSections.h"
 #include "SyntheticSections.h"
 #include "Target.h"
 #include "lld/Common/Arrays.h"
+#include "lld/Common/CommonLinkerContext.h"
 #include "lld/Common/Filesystem.h"
-#include "lld/Common/Memory.h"
 #include "lld/Common/Strings.h"
 #include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/BLAKE3.h"
 #include "llvm/Support/Parallel.h"
 #include "llvm/Support/RandomNumberGenerator.h"
-#include "llvm/Support/SHA1.h"
 #include "llvm/Support/TimeProfiler.h"
 #include "llvm/Support/xxhash.h"
 #include <climits>
@@ -55,7 +55,6 @@ public:
 private:
   void copyLocalSymbols();
   void addSectionSymbols();
-  void forEachRelSec(llvm::function_ref<void(InputSectionBase &)> fn);
   void sortSections();
   void resolveShfLinkOrder();
   void finalizeAddressDependentContent();
@@ -65,7 +64,7 @@ private:
   void checkExecuteOnly();
   void setReservedSymbolSections();
 
-  std::vector<PhdrEntry *> createPhdrs(Partition &part);
+  SmallVector<PhdrEntry *, 0> createPhdrs(Partition &part);
   void addPhdrForSection(Partition &part, unsigned shType, unsigned pType,
                          unsigned pFlags);
   void assignFileOffsets();
@@ -84,75 +83,13 @@ private:
 
   void addRelIpltSymbols();
   void addStartEndSymbols();
-  void addStartStopSymbols(OutputSection *sec);
+  void addStartStopSymbols(OutputSection &osec);
 
   uint64_t fileSize;
   uint64_t sectionHeaderOff;
 };
 } // anonymous namespace
 
-static bool isSectionPrefix(StringRef prefix, StringRef name) {
-  return name.startswith(prefix) || name == prefix.drop_back();
-}
-
-StringRef elf::getOutputSectionName(const InputSectionBase *s) {
-  if (config->relocatable)
-    return s->name;
-
-  // This is for --emit-relocs. If .text.foo is emitted as .text.bar, we want
-  // to emit .rela.text.foo as .rela.text.bar for consistency (this is not
-  // technically required, but not doing it is odd). This code guarantees that.
-  if (auto *isec = dyn_cast<InputSection>(s)) {
-    if (InputSectionBase *rel = isec->getRelocatedSection()) {
-      OutputSection *out = rel->getOutputSection();
-      if (s->type == SHT_RELA)
-        return saver.save(".rela" + out->name);
-      return saver.save(".rel" + out->name);
-    }
-  }
-
-  // A BssSection created for a common symbol is identified as "COMMON" in
-  // linker scripts. It should go to .bss section.
-  if (s->name == "COMMON")
-    return ".bss";
-
-  if (script->hasSectionsCommand)
-    return s->name;
-
-  // When no SECTIONS is specified, emulate GNU ld's internal linker scripts
-  // by grouping sections with certain prefixes.
-
-  // GNU ld places text sections with prefix ".text.hot.", ".text.unknown.",
-  // ".text.unlikely.", ".text.startup." or ".text.exit." before others.
-  // We provide an option -z keep-text-section-prefix to group such sections
-  // into separate output sections. This is more flexible. See also
-  // sortISDBySectionOrder().
-  // ".text.unknown" means the hotness of the section is unknown. When
-  // SampleFDO is used, if a function doesn't have sample, it could be very
-  // cold or it could be a new function never being sampled. Those functions
-  // will be kept in the ".text.unknown" section.
-  // ".text.split." holds symbols which are split out from functions in other
-  // input sections. For example, with -fsplit-machine-functions, placing the
-  // cold parts in .text.split instead of .text.unlikely mitigates against poor
-  // profile inaccuracy. Techniques such as hugepage remapping can make
-  // conservative decisions at the section granularity.
-  if (config->zKeepTextSectionPrefix)
-    for (StringRef v : {".text.hot.", ".text.unknown.", ".text.unlikely.",
-                        ".text.startup.", ".text.exit.", ".text.split."})
-      if (isSectionPrefix(v, s->name))
-        return v.drop_back();
-
-  for (StringRef v :
-       {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.",
-        ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.",
-        ".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab.",
-        ".openbsd.randomdata.", ".openbsd.mutable." })
-    if (isSectionPrefix(v, s->name))
-      return v.drop_back();
-
-  return s->name;
-}
-
 static bool needsInterpSection() {
   return !config->relocatable && !config->shared &&
          !config->dynamicLinker.empty() && script->needsInterpSection();
@@ -162,7 +99,7 @@ template <class ELFT> void elf::writeResult() {
   Writer<ELFT>().run();
 }
 
-static void removeEmptyPTLoad(std::vector<PhdrEntry *> &phdrs) {
+static void removeEmptyPTLoad(SmallVector<PhdrEntry *, 0> &phdrs) {
   auto it = std::stable_partition(
       phdrs.begin(), phdrs.end(), [&](const PhdrEntry *p) {
         if (p->p_type != PT_LOAD)
@@ -183,64 +120,44 @@ static void removeEmptyPTLoad(std::vector<PhdrEntry *> &phdrs) {
 }
 
 void elf::copySectionsIntoPartitions() {
-  std::vector<InputSectionBase *> newSections;
+  SmallVector<InputSectionBase *, 0> newSections;
+  const size_t ehSize = ctx.ehInputSections.size();
   for (unsigned part = 2; part != partitions.size() + 1; ++part) {
-    for (InputSectionBase *s : inputSections) {
-      if (!(s->flags & SHF_ALLOC) || !s->isLive())
-        continue;
-      InputSectionBase *copy;
-      if (s->type == SHT_NOTE)
-        copy = make<InputSection>(cast<InputSection>(*s));
-      else if (auto *es = dyn_cast<EhInputSection>(s))
-        copy = make<EhInputSection>(*es);
-      else
+    for (InputSectionBase *s : ctx.inputSections) {
+      if (!(s->flags & SHF_ALLOC) || !s->isLive() || s->type != SHT_NOTE)
         continue;
+      auto *copy = make<InputSection>(cast<InputSection>(*s));
       copy->partition = part;
       newSections.push_back(copy);
     }
-  }
-
-  inputSections.insert(inputSections.end(), newSections.begin(),
-                       newSections.end());
-}
-
-void elf::combineEhSections() {
-  llvm::TimeTraceScope timeScope("Combine EH sections");
-  for (InputSectionBase *&s : inputSections) {
-    // Ignore dead sections and the partition end marker (.part.end),
-    // whose partition number is out of bounds.
-    if (!s->isLive() || s->partition == 255)
-      continue;
-
-    Partition &part = s->getPartition();
-    if (auto *es = dyn_cast<EhInputSection>(s)) {
-      part.ehFrame->addSection(es);
-      s = nullptr;
-    } else if (s->kind() == SectionBase::Regular && part.armExidx &&
-               part.armExidx->addSection(cast<InputSection>(s))) {
-      s = nullptr;
+    for (size_t i = 0; i != ehSize; ++i) {
+      assert(ctx.ehInputSections[i]->isLive());
+      auto *copy = make<EhInputSection>(*ctx.ehInputSections[i]);
+      copy->partition = part;
+      ctx.ehInputSections.push_back(copy);
     }
   }
 
-  std::vector<InputSectionBase *> &v = inputSections;
-  v.erase(std::remove(v.begin(), v.end(), nullptr), v.end());
+  ctx.inputSections.insert(ctx.inputSections.end(), newSections.begin(),
+                           newSections.end());
 }
 
 static Defined *addOptionalRegular(StringRef name, SectionBase *sec,
-                                   uint64_t val, uint8_t stOther = STV_HIDDEN,
-                                   uint8_t binding = STB_GLOBAL) {
-  Symbol *s = symtab->find(name);
-  if (!s || s->isDefined())
+                                   uint64_t val, uint8_t stOther = STV_HIDDEN) {
+  Symbol *s = symtab.find(name);
+  if (!s || s->isDefined() || s->isCommon())
     return nullptr;
 
-  s->resolve(Defined{/*file=*/nullptr, name, binding, stOther, STT_NOTYPE, val,
+  s->resolve(Defined{nullptr, StringRef(), STB_GLOBAL, stOther, STT_NOTYPE, val,
                      /*size=*/0, sec});
+  s->isUsedInRegularObj = true;
   return cast<Defined>(s);
 }
 
 static Defined *addAbsolute(StringRef name) {
-  Symbol *sym = symtab->addSymbol(Defined{nullptr, name, STB_GLOBAL, STV_HIDDEN,
-                                          STT_NOTYPE, 0, 0, nullptr});
+  Symbol *sym = symtab.addSymbol(Defined{nullptr, name, STB_GLOBAL, STV_HIDDEN,
+                                         STT_NOTYPE, 0, 0, nullptr});
+  sym->isUsedInRegularObj = true;
   return cast<Defined>(sym);
 }
 
@@ -257,14 +174,14 @@ void elf::addReservedSymbols() {
 
     // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between
     // start of function and 'gp' pointer into GOT.
-    if (symtab->find("_gp_disp"))
+    if (symtab.find("_gp_disp"))
       ElfSym::mipsGpDisp = addAbsolute("_gp_disp");
 
     // The __gnu_local_gp is a magic symbol equal to the current value of 'gp'
     // pointer. This symbol is used in the code generated by .cpload pseudo-op
     // in case of using -mno-shared option.
     // https://sourceware.org/ml/binutils/2004-12/msg00094.html
-    if (symtab->find("__gnu_local_gp"))
+    if (symtab.find("__gnu_local_gp"))
       ElfSym::mipsLocalGp = addAbsolute("__gnu_local_gp");
   } else if (config->emachine == EM_PPC) {
     // glibc *crt1.o has a undefined reference to _SDA_BASE_. Since we don't
@@ -285,7 +202,7 @@ void elf::addReservedSymbols() {
   StringRef gotSymName =
       (config->emachine == EM_PPC64) ? ".TOC." : "_GLOBAL_OFFSET_TABLE_";
 
-  if (Symbol *s = symtab->find(gotSymName)) {
+  if (Symbol *s = symtab.find(gotSymName)) {
     if (s->isDefined()) {
       error(toString(s->file) + " cannot redefine linker defined symbol '" +
             gotSymName + "'");
@@ -296,7 +213,7 @@ void elf::addReservedSymbols() {
     if (config->emachine == EM_PPC64)
       gotOff = 0x8000;
 
-    s->resolve(Defined{/*file=*/nullptr, gotSymName, STB_GLOBAL, STV_HIDDEN,
+    s->resolve(Defined{/*file=*/nullptr, StringRef(), STB_GLOBAL, STV_HIDDEN,
                        STT_NOTYPE, gotOff, /*size=*/0, Out::elfHeader});
     ElfSym::globalOffsetTable = cast<Defined>(s);
   }
@@ -335,17 +252,20 @@ void elf::addReservedSymbols() {
 }
 
 static OutputSection *findSection(StringRef name, unsigned partition = 1) {
-  for (BaseCommand *base : script->sectionCommands)
-    if (auto *sec = dyn_cast<OutputSection>(base))
-      if (sec->name == name && sec->partition == partition)
-        return sec;
+  for (SectionCommand *cmd : script->sectionCommands)
+    if (auto *osd = dyn_cast<OutputDesc>(cmd))
+      if (osd->osec.name == name && osd->osec.partition == partition)
+        return &osd->osec;
   return nullptr;
 }
 
 template <class ELFT> void elf::createSyntheticSections() {
   // Initialize all pointers with NULL. This is needed because
   // you can call lld::elf::main more than once as a library.
-  memset(&Out::first, 0, sizeof(Out));
+  Out::tlsPhdr = nullptr;
+  Out::preinitArray = nullptr;
+  Out::initArray = nullptr;
+  Out::finiArray = nullptr;
 
   // Add the .interp section first because it is not a SyntheticSection.
   // The removeUnusedSyntheticSections() function relies on the
@@ -354,129 +274,142 @@ template <class ELFT> void elf::createSyntheticSections() {
     for (size_t i = 1; i <= partitions.size(); ++i) {
       InputSection *sec = createInterpSection();
       sec->partition = i;
-      inputSections.push_back(sec);
+      ctx.inputSections.push_back(sec);
     }
   }
 
-  auto add = [](SyntheticSection *sec) { inputSections.push_back(sec); };
+  auto add = [](SyntheticSection &sec) { ctx.inputSections.push_back(&sec); };
 
-  in.shStrTab = make<StringTableSection>(".shstrtab", false);
+  in.shStrTab = std::make_unique<StringTableSection>(".shstrtab", false);
 
   Out::programHeaders = make<OutputSection>("", 0, SHF_ALLOC);
-  Out::programHeaders->alignment = config->wordsize;
+  Out::programHeaders->addralign = config->wordsize;
 
   if (config->strip != StripPolicy::All) {
-    in.strTab = make<StringTableSection>(".strtab", false);
-    in.symTab = make<SymbolTableSection<ELFT>>(*in.strTab);
-    in.symTabShndx = make<SymtabShndxSection>();
+    in.strTab = std::make_unique<StringTableSection>(".strtab", false);
+    in.symTab = std::make_unique<SymbolTableSection<ELFT>>(*in.strTab);
+    in.symTabShndx = std::make_unique<SymtabShndxSection>();
   }
 
-  in.bss = make<BssSection>(".bss", 0, 1);
-  add(in.bss);
+  in.bss = std::make_unique<BssSection>(".bss", 0, 1);
+  add(*in.bss);
 
   // If there is a SECTIONS command and a .data.rel.ro section name use name
   // .data.rel.ro.bss so that we match in the .data.rel.ro output section.
   // This makes sure our relro is contiguous.
-  bool hasDataRelRo =
-      script->hasSectionsCommand && findSection(".data.rel.ro", 0);
-  in.bssRelRo =
-      make<BssSection>(hasDataRelRo ? ".data.rel.ro.bss" : ".bss.rel.ro", 0, 1);
-  add(in.bssRelRo);
+  bool hasDataRelRo = script->hasSectionsCommand && findSection(".data.rel.ro");
+  in.bssRelRo = std::make_unique<BssSection>(
+      hasDataRelRo ? ".data.rel.ro.bss" : ".bss.rel.ro", 0, 1);
+  add(*in.bssRelRo);
 
   // Add MIPS-specific sections.
   if (config->emachine == EM_MIPS) {
     if (!config->shared && config->hasDynSymTab) {
-      in.mipsRldMap = make<MipsRldMapSection>();
-      add(in.mipsRldMap);
+      in.mipsRldMap = std::make_unique<MipsRldMapSection>();
+      add(*in.mipsRldMap);
     }
-    if (auto *sec = MipsAbiFlagsSection<ELFT>::create())
-      add(sec);
-    if (auto *sec = MipsOptionsSection<ELFT>::create())
-      add(sec);
-    if (auto *sec = MipsReginfoSection<ELFT>::create())
-      add(sec);
+    if ((in.mipsAbiFlags = MipsAbiFlagsSection<ELFT>::create()))
+      add(*in.mipsAbiFlags);
+    if ((in.mipsOptions = MipsOptionsSection<ELFT>::create()))
+      add(*in.mipsOptions);
+    if ((in.mipsReginfo = MipsReginfoSection<ELFT>::create()))
+      add(*in.mipsReginfo);
   }
 
   StringRef relaDynName = config->isRela ? ".rela.dyn" : ".rel.dyn";
 
+  const unsigned threadCount = config->threadCount;
   for (Partition &part : partitions) {
-    auto add = [&](SyntheticSection *sec) {
-      sec->partition = part.getNumber();
-      inputSections.push_back(sec);
+    auto add = [&](SyntheticSection &sec) {
+      sec.partition = part.getNumber();
+      ctx.inputSections.push_back(&sec);
     };
 
     if (!part.name.empty()) {
-      part.elfHeader = make<PartitionElfHeaderSection<ELFT>>();
+      part.elfHeader = std::make_unique<PartitionElfHeaderSection<ELFT>>();
       part.elfHeader->name = part.name;
-      add(part.elfHeader);
+      add(*part.elfHeader);
 
-      part.programHeaders = make<PartitionProgramHeadersSection<ELFT>>();
-      add(part.programHeaders);
+      part.programHeaders =
+          std::make_unique<PartitionProgramHeadersSection<ELFT>>();
+      add(*part.programHeaders);
     }
 
     if (config->buildId != BuildIdKind::None) {
-      part.buildId = make<BuildIdSection>();
-      add(part.buildId);
+      part.buildId = std::make_unique<BuildIdSection>();
+      add(*part.buildId);
+    }
+
+    part.dynStrTab = std::make_unique<StringTableSection>(".dynstr", true);
+    part.dynSymTab =
+        std::make_unique<SymbolTableSection<ELFT>>(*part.dynStrTab);
+    part.dynamic = std::make_unique<DynamicSection<ELFT>>();
+
+    if (config->emachine == EM_AARCH64 &&
+        config->androidMemtagMode != ELF::NT_MEMTAG_LEVEL_NONE) {
+      part.memtagAndroidNote = std::make_unique<MemtagAndroidNote>();
+      add(*part.memtagAndroidNote);
     }
 
-    part.dynStrTab = make<StringTableSection>(".dynstr", true);
-    part.dynSymTab = make<SymbolTableSection<ELFT>>(*part.dynStrTab);
-    part.dynamic = make<DynamicSection<ELFT>>();
     if (config->androidPackDynRelocs)
-      part.relaDyn = make<AndroidPackedRelocationSection<ELFT>>(relaDynName);
+      part.relaDyn = std::make_unique<AndroidPackedRelocationSection<ELFT>>(
+          relaDynName, threadCount);
     else
-      part.relaDyn =
-          make<RelocationSection<ELFT>>(relaDynName, config->zCombreloc);
+      part.relaDyn = std::make_unique<RelocationSection<ELFT>>(
+          relaDynName, config->zCombreloc, threadCount);
 
     if (config->hasDynSymTab) {
-      part.dynSymTab = make<SymbolTableSection<ELFT>>(*part.dynStrTab);
-      add(part.dynSymTab);
+      add(*part.dynSymTab);
 
-      part.verSym = make<VersionTableSection>();
-      add(part.verSym);
+      part.verSym = std::make_unique<VersionTableSection>();
+      add(*part.verSym);
 
       if (!namedVersionDefs().empty()) {
-        part.verDef = make<VersionDefinitionSection>();
-        add(part.verDef);
+        part.verDef = std::make_unique<VersionDefinitionSection>();
+        add(*part.verDef);
       }
 
-      part.verNeed = make<VersionNeedSection<ELFT>>();
-      add(part.verNeed);
+      part.verNeed = std::make_unique<VersionNeedSection<ELFT>>();
+      add(*part.verNeed);
 
       if (config->gnuHash) {
-        part.gnuHashTab = make<GnuHashTableSection>();
-        add(part.gnuHashTab);
+        part.gnuHashTab = std::make_unique<GnuHashTableSection>();
+        add(*part.gnuHashTab);
       }
 
       if (config->sysvHash) {
-        part.hashTab = make<HashTableSection>();
-        add(part.hashTab);
+        part.hashTab = std::make_unique<HashTableSection>();
+        add(*part.hashTab);
       }
 
-      add(part.dynamic);
-      add(part.dynStrTab);
-      add(part.relaDyn);
+      add(*part.dynamic);
+      add(*part.dynStrTab);
+      add(*part.relaDyn);
     }
 
     if (config->relrPackDynRelocs) {
-      part.relrDyn = make<RelrSection<ELFT>>();
-      add(part.relrDyn);
+      part.relrDyn = std::make_unique<RelrSection<ELFT>>(threadCount);
+      add(*part.relrDyn);
     }
 
     if (!config->relocatable) {
       if (config->ehFrameHdr) {
-        part.ehFrameHdr = make<EhFrameHeader>();
-        add(part.ehFrameHdr);
+        part.ehFrameHdr = std::make_unique<EhFrameHeader>();
+        add(*part.ehFrameHdr);
+      }
+      part.ehFrame = std::make_unique<EhFrameSection>();
+      add(*part.ehFrame);
+
+      if (config->emachine == EM_ARM) {
+        // This section replaces all the individual .ARM.exidx InputSections.
+        part.armExidx = std::make_unique<ARMExidxSyntheticSection>();
+        add(*part.armExidx);
       }
-      part.ehFrame = make<EhFrameSection>();
-      add(part.ehFrame);
     }
 
-    if (config->emachine == EM_ARM && !config->relocatable) {
-      // The ARMExidxsyntheticsection replaces all the individual .ARM.exidx
-      // InputSections.
-      part.armExidx = make<ARMExidxSyntheticSection>();
-      add(part.armExidx);
+    if (!config->packageMetadata.empty()) {
+      part.packageMetadataNote = std::make_unique<PackageMetadataNote>();
+      add(*part.packageMetadataNote);
     }
   }
 
@@ -484,41 +417,42 @@ template <class ELFT> void elf::createSyntheticSections() {
     // Create the partition end marker. This needs to be in partition number 255
     // so that it is sorted after all other partitions. It also has other
     // special handling (see createPhdrs() and combineEhSections()).
-    in.partEnd = make<BssSection>(".part.end", config->maxPageSize, 1);
+    in.partEnd =
+        std::make_unique<BssSection>(".part.end", config->maxPageSize, 1);
     in.partEnd->partition = 255;
-    add(in.partEnd);
+    add(*in.partEnd);
 
-    in.partIndex = make<PartitionIndexSection>();
-    addOptionalRegular("__part_index_begin", in.partIndex, 0);
-    addOptionalRegular("__part_index_end", in.partIndex,
+    in.partIndex = std::make_unique<PartitionIndexSection>();
+    addOptionalRegular("__part_index_begin", in.partIndex.get(), 0);
+    addOptionalRegular("__part_index_end", in.partIndex.get(),
                        in.partIndex->getSize());
-    add(in.partIndex);
+    add(*in.partIndex);
   }
 
   // Add .got. MIPS' .got is so different from the other archs,
   // it has its own class.
   if (config->emachine == EM_MIPS) {
-    in.mipsGot = make<MipsGotSection>();
-    add(in.mipsGot);
+    in.mipsGot = std::make_unique<MipsGotSection>();
+    add(*in.mipsGot);
   } else {
-    in.got = make<GotSection>();
-    add(in.got);
+    in.got = std::make_unique<GotSection>();
+    add(*in.got);
   }
 
   if (config->emachine == EM_PPC) {
-    in.ppc32Got2 = make<PPC32Got2Section>();
-    add(in.ppc32Got2);
+    in.ppc32Got2 = std::make_unique<PPC32Got2Section>();
+    add(*in.ppc32Got2);
   }
 
   if (config->emachine == EM_PPC64) {
-    in.ppc64LongBranchTarget = make<PPC64LongBranchTargetSection>();
-    add(in.ppc64LongBranchTarget);
+    in.ppc64LongBranchTarget = std::make_unique<PPC64LongBranchTargetSection>();
+    add(*in.ppc64LongBranchTarget);
   }
 
-  in.gotPlt = make<GotPltSection>();
-  add(in.gotPlt);
-  in.igotPlt = make<IgotPltSection>();
-  add(in.igotPlt);
+  in.gotPlt = std::make_unique<GotPltSection>();
+  add(*in.gotPlt);
+  in.igotPlt = std::make_unique<IgotPltSection>();
+  add(*in.igotPlt);
 
   // _GLOBAL_OFFSET_TABLE_ is defined relative to either .got.plt or .got. Treat
   // it as a relocation and ensure the referenced section is created.
@@ -530,13 +464,14 @@ template <class ELFT> void elf::createSyntheticSections() {
   }
 
   if (config->gdbIndex)
-    add(GdbIndexSection::create<ELFT>());
+    add(*GdbIndexSection::create<ELFT>());
 
   // We always need to add rel[a].plt to output if it has entries.
   // Even for static linking it can contain R_[*]_IRELATIVE relocations.
-  in.relaPlt = make<RelocationSection<ELFT>>(
-      config->isRela ? ".rela.plt" : ".rel.plt", /*sort=*/false);
-  add(in.relaPlt);
+  in.relaPlt = std::make_unique<RelocationSection<ELFT>>(
+      config->isRela ? ".rela.plt" : ".rel.plt", /*sort=*/false,
+      /*threadCount=*/1);
+  add(*in.relaPlt);
 
   // The relaIplt immediately follows .rel[a].dyn to ensure that the IRelative
   // relocations are processed last by the dynamic loader. We cannot place the
@@ -544,25 +479,27 @@ template <class ELFT> void elf::createSyntheticSections() {
   // that would cause a section type mismatch. However, because the Android
   // dynamic loader reads .rel.plt after .rel.dyn, we can get the desired
   // behaviour by placing the iplt section in .rel.plt.
-  in.relaIplt = make<RelocationSection<ELFT>>(
+  in.relaIplt = std::make_unique<RelocationSection<ELFT>>(
       config->androidPackDynRelocs ? in.relaPlt->name : relaDynName,
-      /*sort=*/false);
-  add(in.relaIplt);
+      /*sort=*/false, /*threadCount=*/1);
+  add(*in.relaIplt);
 
   if ((config->emachine == EM_386 || config->emachine == EM_X86_64) &&
       (config->andFeatures & GNU_PROPERTY_X86_FEATURE_1_IBT)) {
-    in.ibtPlt = make<IBTPltSection>();
-    add(in.ibtPlt);
+    in.ibtPlt = std::make_unique<IBTPltSection>();
+    add(*in.ibtPlt);
   }
 
-  in.plt = config->emachine == EM_PPC ? make<PPC32GlinkSection>()
-                                      : make<PltSection>();
-  add(in.plt);
-  in.iplt = make<IpltSection>();
-  add(in.iplt);
+  if (config->emachine == EM_PPC)
+    in.plt = std::make_unique<PPC32GlinkSection>();
+  else
+    in.plt = std::make_unique<PltSection>();
+  add(*in.plt);
+  in.iplt = std::make_unique<IpltSection>();
+  add(*in.iplt);
 
   if (config->andFeatures)
-    add(make<GnuPropertySection>());
+    add(*make<GnuPropertySection>());
 
   // .note.GNU-stack is always added when we are creating a re-linkable
   // object file. Other linkers are using the presence of this marker
@@ -570,15 +507,15 @@ template <class ELFT> void elf::createSyntheticSections() {
   // is irrelevant these days. Stack area should always be non-executable
   // by default. So we emit this section unconditionally.
   if (config->relocatable)
-    add(make<GnuStackSection>());
+    add(*make<GnuStackSection>());
 
   if (in.symTab)
-    add(in.symTab);
+    add(*in.symTab);
   if (in.symTabShndx)
-    add(in.symTabShndx);
-  add(in.shStrTab);
+    add(*in.symTabShndx);
+  add(*in.shStrTab);
   if (in.strTab)
-    add(in.strTab);
+    add(*in.strTab);
 }
 
 // The main function of the writer.
@@ -594,12 +531,9 @@ template <class ELFT> void Writer<ELFT>::run() {
   // finalizeSections does that.
   finalizeSections();
   checkExecuteOnly();
-  if (errorCount())
-    return;
 
-  // If -compressed-debug-sections is specified, we need to compress
-  // .debug_* sections. Do it right now because it changes the size of
-  // output sections.
+  // If --compressed-debug-sections is specified, compress .debug_* sections.
+  // Do it right now because it changes the size of output sections.
   for (OutputSection *sec : outputSections)
     sec->maybeCompress<ELFT>();
 
@@ -620,17 +554,10 @@ template <class ELFT> void Writer<ELFT>::run() {
   for (Partition &part : partitions)
     setPhdrs(part);
 
-  if (config->relocatable)
-    for (OutputSection *sec : outputSections)
-      sec->addr = 0;
-
-  // Handle --print-map(-M)/--Map, --cref and --print-archive-stats=. Dump them
-  // before checkSections() because the files may be useful in case
-  // checkSections() or openFile() fails, for example, due to an erroneous file
-  // size.
-  writeMapFile();
-  writeCrossReferenceTable();
-  writeArchiveStats();
+  // Handle --print-map(-M)/--Map and --cref. Dump them before checkSections()
+  // because the files may be useful in case checkSections() or openFile()
+  // fails, for example, due to an erroneous file size.
+  writeMapAndCref();
 
   if (config->checkSections)
     checkSections();
@@ -662,7 +589,8 @@ template <class ELFT> void Writer<ELFT>::run() {
       return;
 
     if (auto e = buffer->commit())
-      error("failed to write to the output file: " + toString(std::move(e)));
+      fatal("failed to write output '" + buffer->getPath() +
+            "': " + toString(std::move(e)));
   }
 }
 
@@ -683,12 +611,8 @@ template <class ELFT> static void markUsedLocalSymbols() {
   // See MarkLive<ELFT>::resolveReloc().
   if (config->gcSections)
     return;
-  // Without --gc-sections, the field is initialized with "true".
-  // Drop the flag first and then rise for symbols referenced in relocations.
-  for (InputFile *file : objectFiles) {
+  for (ELFFileBase *file : ctx.objectFiles) {
     ObjFile<ELFT> *f = cast<ObjFile<ELFT>>(file);
-    for (Symbol *b : f->getLocalSymbols())
-      b->used = false;
     for (InputSectionBase *s : f->getSections()) {
       InputSection *isec = dyn_cast_or_null<InputSection>(s);
       if (!isec)
@@ -707,7 +631,7 @@ static bool shouldKeepInSymtab(const Defined &sym) {
 
   // If --emit-reloc or -r is given, preserve symbols referenced by relocations
   // from live sections.
-  if (config->copyRelocs && sym.used)
+  if (sym.used && config->copyRelocs)
     return true;
 
   // Exclude local symbols pointing to .ARM.exidx sections.
@@ -729,39 +653,25 @@ static bool shouldKeepInSymtab(const Defined &sym) {
   // * --discard-locals is used.
   // * The symbol is in a SHF_MERGE section, which is normally the reason for
   //   the assembler keeping the .L symbol.
-  StringRef name = sym.getName();
-  bool isLocal = name.startswith(".L") || name.empty();
-  if (!isLocal)
-    return true;
-
-  if (config->discard == DiscardPolicy::Locals)
+  if ((sym.getName().startswith(".L") || sym.getName().empty()) &&
+      (config->discard == DiscardPolicy::Locals ||
+       (sym.section && (sym.section->flags & SHF_MERGE))))
     return false;
-
-  SectionBase *sec = sym.section;
-  return !sec || !(sec->flags & SHF_MERGE);
+  return true;
 }
 
 static bool includeInSymtab(const Symbol &b) {
-  if (!b.isLocal() && !b.isUsedInRegularObj)
-    return false;
-
   if (auto *d = dyn_cast<Defined>(&b)) {
     // Always include absolute symbols.
     SectionBase *sec = d->section;
     if (!sec)
       return true;
-    sec = sec->repl;
-
-    // Exclude symbols pointing to garbage-collected sections.
-    if (isa<InputSectionBase>(sec) && !sec->isLive())
-      return false;
 
     if (auto *s = dyn_cast<MergeInputSection>(sec))
-      if (!s->getSectionPiece(d->value)->live)
-        return false;
-    return true;
+      return s->getSectionPiece(d->value).live;
+    return sec->isLive();
   }
-  return b.used;
+  return b.used || !config->gcSections;
 }
 
 // Local symbols are not in the linker's symbol table. This function scans
@@ -772,20 +682,16 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
   llvm::TimeTraceScope timeScope("Add local symbols");
   if (config->copyRelocs && config->discard != DiscardPolicy::None)
     markUsedLocalSymbols<ELFT>();
-  for (InputFile *file : objectFiles) {
-    ObjFile<ELFT> *f = cast<ObjFile<ELFT>>(file);
-    for (Symbol *b : f->getLocalSymbols()) {
+  for (ELFFileBase *file : ctx.objectFiles) {
+    for (Symbol *b : file->getLocalSymbols()) {
       assert(b->isLocal() && "should have been caught in initializeSymbols()");
       auto *dr = dyn_cast<Defined>(b);
 
       // No reason to keep local undefined symbol in symtab.
       if (!dr)
         continue;
-      if (!includeInSymtab(*b))
-        continue;
-      if (!shouldKeepInSymtab(*dr))
-        continue;
-      in.symTab->addSymbol(b);
+      if (includeInSymtab(*b) && shouldKeepInSymtab(*dr))
+        in.symTab->addSymbol(b);
     }
   }
 }
@@ -795,36 +701,42 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
 // referring to a section (that happens if the section is a synthetic one), we
 // don't create a section symbol for that section.
 template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
-  for (BaseCommand *base : script->sectionCommands) {
-    auto *sec = dyn_cast<OutputSection>(base);
-    if (!sec)
+  for (SectionCommand *cmd : script->sectionCommands) {
+    auto *osd = dyn_cast<OutputDesc>(cmd);
+    if (!osd)
       continue;
-    auto i = llvm::find_if(sec->sectionCommands, [](BaseCommand *base) {
-      if (auto *isd = dyn_cast<InputSectionDescription>(base))
-        return !isd->sections.empty();
-      return false;
-    });
-    if (i == sec->sectionCommands.end())
-      continue;
-    InputSectionBase *isec = cast<InputSectionDescription>(*i)->sections[0];
-
-    // Relocations are not using REL[A] section symbols.
-    if (isec->type == SHT_REL || isec->type == SHT_RELA)
-      continue;
-
-    // Unlike other synthetic sections, mergeable output sections contain data
-    // copied from input sections, and there may be a relocation pointing to its
-    // contents if -r or -emit-reloc are given.
-    if (isa<SyntheticSection>(isec) && !(isec->flags & SHF_MERGE))
+    OutputSection &osec = osd->osec;
+    InputSectionBase *isec = nullptr;
+    // Iterate over all input sections and add a STT_SECTION symbol if any input
+    // section may be a relocation target.
+    for (SectionCommand *cmd : osec.commands) {
+      auto *isd = dyn_cast<InputSectionDescription>(cmd);
+      if (!isd)
+        continue;
+      for (InputSectionBase *s : isd->sections) {
+        // Relocations are not using REL[A] section symbols.
+        if (s->type == SHT_REL || s->type == SHT_RELA)
+          continue;
+
+        // Unlike other synthetic sections, mergeable output sections contain
+        // data copied from input sections, and there may be a relocation
+        // pointing to its contents if -r or --emit-reloc is given.
+        if (isa<SyntheticSection>(s) && !(s->flags & SHF_MERGE))
+          continue;
+
+        isec = s;
+        break;
+      }
+    }
+    if (!isec)
       continue;
 
     // Set the symbol to be relative to the output section so that its st_value
     // equals the output section address. Note, there may be a gap between the
     // start of the output section and isec.
-    auto *sym =
-        make<Defined>(isec->file, "", STB_LOCAL, /*stOther=*/0, STT_SECTION,
-                      /*value=*/0, /*size=*/0, isec->getOutputSection());
-    in.symTab->addSymbol(sym);
+    in.symTab->addSymbol(makeDefined(isec->file, "", STB_LOCAL, /*stOther=*/0,
+                                     STT_SECTION,
+                                     /*value=*/0, /*size=*/0, &osec));
   }
 }
 
@@ -837,6 +749,8 @@ template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
 static bool isRelroSection(const OutputSection *sec) {
   if (!config->zRelro)
     return false;
+  if (sec->relro)
+    return true;
 
   uint64_t flags = sec->flags;
 
@@ -939,31 +853,31 @@ enum RankFlags {
   RF_MIPS_NOT_GOT = 1 << 0
 };
 
-static unsigned getSectionRank(const OutputSection *sec) {
-  unsigned rank = sec->partition * RF_PARTITION;
+static unsigned getSectionRank(const OutputSection &osec) {
+  unsigned rank = osec.partition * RF_PARTITION;
 
   // We want to put section specified by -T option first, so we
   // can start assigning VA starting from them later.
-  if (config->sectionStartMap.count(sec->name))
+  if (config->sectionStartMap.count(osec.name))
     return rank;
   rank |= RF_NOT_ADDR_SET;
 
   // Allocatable sections go first to reduce the total PT_LOAD size and
   // so debug info doesn't change addresses in actual code.
-  if (!(sec->flags & SHF_ALLOC))
+  if (!(osec.flags & SHF_ALLOC))
     return rank | RF_NOT_ALLOC;
 
-  if (sec->type == SHT_LLVM_PART_EHDR)
+  if (osec.type == SHT_LLVM_PART_EHDR)
     return rank;
   rank |= RF_NOT_PART_EHDR;
 
-  if (sec->type == SHT_LLVM_PART_PHDR)
+  if (osec.type == SHT_LLVM_PART_PHDR)
     return rank;
   rank |= RF_NOT_PART_PHDR;
 
   // Put .interp first because some loaders want to see that section
   // on the first page of the executable file when loaded into memory.
-  if (sec->name == ".interp")
+  if (osec.name == ".interp")
     return rank;
   rank |= RF_NOT_INTERP;
 
@@ -971,7 +885,7 @@ static unsigned getSectionRank(const OutputSection *sec) {
   // they are likely to be included in a core file even if core file size is
   // limited. In particular, we want a .note.gnu.build-id and a .note.tag to be
   // included in a core to match core files with executables.
-  if (sec->type == SHT_NOTE)
+  if (osec.type == SHT_NOTE)
     return rank;
   rank |= RF_NOT_NOTE;
 
@@ -986,8 +900,8 @@ static unsigned getSectionRank(const OutputSection *sec) {
   //   between .text and .data.
   // * Writable sections come last, such that .bss lands at the very
   //   end of the last PT_LOAD.
-  bool isExec = sec->flags & SHF_EXECINSTR;
-  bool isWrite = sec->flags & SHF_WRITE;
+  bool isExec = osec.flags & SHF_EXECINSTR;
+  bool isWrite = osec.flags & SHF_WRITE;
 
   if (isExec) {
     if (isWrite)
@@ -996,7 +910,7 @@ static unsigned getSectionRank(const OutputSection *sec) {
       rank |= RF_EXEC;
   } else if (isWrite) {
     rank |= RF_WRITE;
-  } else if (sec->type == SHT_PROGBITS) {
+  } else if (osec.type == SHT_PROGBITS) {
     // Make non-executable and non-writable PROGBITS sections (e.g .rodata
     // .eh_frame) closer to .text. They likely contain PC or GOT relative
     // relocations and there could be relocation overflow if other huge sections
@@ -1009,7 +923,7 @@ static unsigned getSectionRank(const OutputSection *sec) {
   // where | marks where page alignment happens. An alternative ordering is
   // PT_LOAD(.data | PT_GNU_RELRO( .data.rel.ro .bss.rel.ro) | .bss), but it may
   // waste more bytes due to 2 alignment places.
-  if (!isRelroSection(sec))
+  if (!isRelroSection(&osec))
     rank |= RF_NOT_RELRO;
 
   // If we got here we know that both A and B are in the same PT_LOAD.
@@ -1018,12 +932,12 @@ static unsigned getSectionRank(const OutputSection *sec) {
   // PT_LOAD, so stick TLS sections directly before the other RelRo R/W
   // sections. Since p_filesz can be less than p_memsz, place NOBITS sections
   // after PROGBITS.
-  if (!(sec->flags & SHF_TLS))
+  if (!(osec.flags & SHF_TLS))
     rank |= RF_NOT_TLS;
 
   // Within TLS sections, or within other RelRo sections, or within non-RelRo
   // sections, place non-NOBITS sections first.
-  if (sec->type == SHT_NOBITS)
+  if (osec.type == SHT_NOBITS)
     rank |= RF_BSS;
 
   // Some architectures have additional ordering restrictions for sections
@@ -1035,7 +949,7 @@ static unsigned getSectionRank(const OutputSection *sec) {
     // 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).
-    StringRef name = sec->name;
+    StringRef name = osec.name;
     if (name != ".tocbss")
       rank |= RF_PPC_NOT_TOCBSS;
 
@@ -1055,19 +969,20 @@ static unsigned getSectionRank(const OutputSection *sec) {
   if (config->emachine == EM_MIPS) {
     // All sections with SHF_MIPS_GPREL flag should be grouped together
     // because data in these sections is addressable with a gp relative address.
-    if (sec->flags & SHF_MIPS_GPREL)
+    if (osec.flags & SHF_MIPS_GPREL)
       rank |= RF_MIPS_GPREL;
 
-    if (sec->name != ".got")
+    if (osec.name != ".got")
       rank |= RF_MIPS_NOT_GOT;
   }
 
   return rank;
 }
 
-static bool compareSections(const BaseCommand *aCmd, const BaseCommand *bCmd) {
-  const OutputSection *a = cast<OutputSection>(aCmd);
-  const OutputSection *b = cast<OutputSection>(bCmd);
+static bool compareSections(const SectionCommand *aCmd,
+                            const SectionCommand *bCmd) {
+  const OutputSection *a = &cast<OutputDesc>(aCmd)->osec;
+  const OutputSection *b = &cast<OutputDesc>(bCmd)->osec;
 
   if (a->sortRank != b->sortRank)
     return a->sortRank < b->sortRank;
@@ -1082,7 +997,7 @@ void PhdrEntry::add(OutputSection *sec) {
   lastSec = sec;
   if (!firstSec)
     firstSec = sec;
-  p_align = std::max(p_align, sec->alignment);
+  p_align = std::max(p_align, sec->addralign);
   if (p_type == PT_LOAD)
     sec->ptLoad = this;
 }
@@ -1094,7 +1009,7 @@ void PhdrEntry::add(OutputSection *sec) {
 // need these symbols, since IRELATIVE relocs are resolved through GOT
 // and PLT. For details, see http://www.airs.com/blog/archives/403.
 template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {
-  if (config->relocatable || config->isPic)
+  if (config->isPic)
     return;
 
   // By default, __rela_iplt_{start,end} belong to a dummy section 0
@@ -1103,31 +1018,11 @@ template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {
   // sure that .rela.plt exists in output.
   ElfSym::relaIpltStart = addOptionalRegular(
       config->isRela ? "__rela_iplt_start" : "__rel_iplt_start",
-      Out::elfHeader, 0, STV_HIDDEN, STB_WEAK);
+      Out::elfHeader, 0, STV_HIDDEN);
 
   ElfSym::relaIpltEnd = addOptionalRegular(
       config->isRela ? "__rela_iplt_end" : "__rel_iplt_end",
-      Out::elfHeader, 0, STV_HIDDEN, STB_WEAK);
-}
-
-template <class ELFT>
-void Writer<ELFT>::forEachRelSec(
-    llvm::function_ref<void(InputSectionBase &)> fn) {
-  // Scan all relocations. Each relocation goes through a series
-  // of tests to determine if it needs special treatment, such as
-  // creating GOT, PLT, copy relocations, etc.
-  // Note that relocations for non-alloc sections are directly
-  // processed by InputSection::relocateNonAlloc.
-  for (InputSectionBase *isec : inputSections)
-    if (isec->isLive() && isa<InputSection>(isec) && (isec->flags & SHF_ALLOC))
-      fn(*isec);
-  for (Partition &part : partitions) {
-    for (EhInputSection *es : part.ehFrame->sections)
-      fn(*es);
-    if (part.armExidx && part.armExidx->isLive())
-      for (InputSection *ex : part.armExidx->exidxSections)
-        fn(*ex);
-  }
+      Out::elfHeader, 0, STV_HIDDEN);
 }
 
 // This function generates assignments for predefined symbols (e.g. _end or
@@ -1139,17 +1034,17 @@ template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() {
   if (ElfSym::globalOffsetTable) {
     // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention usually
     // to the start of the .got or .got.plt section.
-    InputSection *gotSection = in.gotPlt;
+    InputSection *sec = in.gotPlt.get();
     if (!target->gotBaseSymInGotPlt)
-      gotSection = in.mipsGot ? cast<InputSection>(in.mipsGot)
-                              : cast<InputSection>(in.got);
-    ElfSym::globalOffsetTable->section = gotSection;
+      sec = in.mipsGot ? cast<InputSection>(in.mipsGot.get())
+                       : cast<InputSection>(in.got.get());
+    ElfSym::globalOffsetTable->section = sec;
   }
 
   // .rela_iplt_{start,end} mark the start and the end of in.relaIplt.
   if (ElfSym::relaIpltStart && in.relaIplt->isNeeded()) {
-    ElfSym::relaIpltStart->section = in.relaIplt;
-    ElfSym::relaIpltEnd->section = in.relaIplt;
+    ElfSym::relaIpltStart->section = in.relaIplt.get();
+    ElfSym::relaIpltEnd->section = in.relaIplt.get();
     ElfSym::relaIpltEnd->value = in.relaIplt->getSize();
   }
 
@@ -1221,13 +1116,11 @@ template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() {
 // The more branches in getSectionRank that match, the more similar they are.
 // Since each branch corresponds to a bit flag, we can just use
 // countLeadingZeros.
-static int getRankProximityAux(OutputSection *a, OutputSection *b) {
-  return countLeadingZeros(a->sortRank ^ b->sortRank);
-}
-
-static int getRankProximity(OutputSection *a, BaseCommand *b) {
-  auto *sec = dyn_cast<OutputSection>(b);
-  return (sec && sec->hasInputSections) ? getRankProximityAux(a, sec) : -1;
+static int getRankProximity(OutputSection *a, SectionCommand *b) {
+  auto *osd = dyn_cast<OutputDesc>(b);
+  return (osd && osd->osec.hasInputSections)
+             ? countLeadingZeros(a->sortRank ^ osd->osec.sortRank)
+             : -1;
 }
 
 // When placing orphan sections, we want to place them after symbol assignments
@@ -1244,7 +1137,7 @@ static int getRankProximity(OutputSection *a, BaseCommand *b) {
 //  /* The RW PT_LOAD starts here*/
 //  rw_sec : { *(rw_sec) }
 // would mean that the RW PT_LOAD would become unaligned.
-static bool shouldSkip(BaseCommand *cmd) {
+static bool shouldSkip(SectionCommand *cmd) {
   if (auto *assign = dyn_cast<SymbolAssignment>(cmd))
     return assign->name != ".";
   return false;
@@ -1253,36 +1146,48 @@ static bool shouldSkip(BaseCommand *cmd) {
 // We want to place orphan sections so that they share as much
 // characteristics with their neighbors as possible. For example, if
 // both are rw, or both are tls.
-static std::vector<BaseCommand *>::iterator
-findOrphanPos(std::vector<BaseCommand *>::iterator b,
-              std::vector<BaseCommand *>::iterator e) {
-  OutputSection *sec = cast<OutputSection>(*e);
+static SmallVectorImpl<SectionCommand *>::iterator
+findOrphanPos(SmallVectorImpl<SectionCommand *>::iterator b,
+              SmallVectorImpl<SectionCommand *>::iterator e) {
+  OutputSection *sec = &cast<OutputDesc>(*e)->osec;
 
   // Find the first element that has as close a rank as possible.
-  auto i = std::max_element(b, e, [=](BaseCommand *a, BaseCommand *b) {
+  auto i = std::max_element(b, e, [=](SectionCommand *a, SectionCommand *b) {
     return getRankProximity(sec, a) < getRankProximity(sec, b);
   });
   if (i == e)
     return e;
+  if (!isa<OutputDesc>(*i))
+    return e;
+  auto foundSec = &cast<OutputDesc>(*i)->osec;
 
   // Consider all existing sections with the same proximity.
   int proximity = getRankProximity(sec, *i);
+  unsigned sortRank = sec->sortRank;
+  if (script->hasPhdrsCommands() || !script->memoryRegions.empty())
+    // Prevent the orphan section to be placed before the found section. If
+    // custom program headers are defined, that helps to avoid adding it to a
+    // previous segment and changing flags of that segment, for example, making
+    // a read-only segment writable. If memory regions are defined, an orphan
+    // section should continue the same region as the found section to better
+    // resemble the behavior of GNU ld.
+    sortRank = std::max(sortRank, foundSec->sortRank);
   for (; i != e; ++i) {
-    auto *curSec = dyn_cast<OutputSection>(*i);
-    if (!curSec || !curSec->hasInputSections)
+    auto *curSecDesc = dyn_cast<OutputDesc>(*i);
+    if (!curSecDesc || !curSecDesc->osec.hasInputSections)
       continue;
-    if (getRankProximity(sec, curSec) != proximity ||
-        sec->sortRank < curSec->sortRank)
+    if (getRankProximity(sec, curSecDesc) != proximity ||
+        sortRank < curSecDesc->osec.sortRank)
       break;
   }
 
-  auto isOutputSecWithInputSections = [](BaseCommand *cmd) {
-    auto *os = dyn_cast<OutputSection>(cmd);
-    return os && os->hasInputSections;
+  auto isOutputSecWithInputSections = [](SectionCommand *cmd) {
+    auto *osd = dyn_cast<OutputDesc>(cmd);
+    return osd && osd->osec.hasInputSections;
   };
-  auto j = std::find_if(llvm::make_reverse_iterator(i),
-                        llvm::make_reverse_iterator(b),
-                        isOutputSecWithInputSections);
+  auto j =
+      std::find_if(std::make_reverse_iterator(i), std::make_reverse_iterator(b),
+                   isOutputSecWithInputSections);
   i = j.base();
 
   // As a special case, if the orphan section is the last section, put
@@ -1304,7 +1209,7 @@ static void maybeShuffle(DenseMap<const InputSectionBase *, int> &order) {
   if (config->shuffleSections.empty())
     return;
 
-  std::vector<InputSectionBase *> matched, sections = inputSections;
+  SmallVector<InputSectionBase *, 0> matched, sections = ctx.inputSections;
   matched.reserve(sections.size());
   for (const auto &patAndSeed : config->shuffleSections) {
     matched.clear();
@@ -1340,7 +1245,7 @@ static void maybeShuffle(DenseMap<const InputSectionBase *, int> &order) {
 // Builds section order for handling --symbol-ordering-file.
 static DenseMap<const InputSectionBase *, int> buildSectionOrder() {
   DenseMap<const InputSectionBase *, int> sectionOrder;
-  // Use the rarely used option -call-graph-ordering-file to sort sections.
+  // Use the rarely used option --call-graph-ordering-file to sort sections.
   if (!config->callGraphProfile.empty())
     return computeCallGraphProfileOrder();
 
@@ -1355,14 +1260,14 @@ static DenseMap<const InputSectionBase *, int> buildSectionOrder() {
   // Build a map from symbols to their priorities. Symbols that didn't
   // appear in the symbol ordering file have the lowest priority 0.
   // All explicitly mentioned symbols have negative (higher) priorities.
-  DenseMap<StringRef, SymbolOrderEntry> symbolOrder;
+  DenseMap<CachedHashStringRef, SymbolOrderEntry> symbolOrder;
   int priority = -config->symbolOrderingFile.size();
   for (StringRef s : config->symbolOrderingFile)
-    symbolOrder.insert({s, {priority++, false}});
+    symbolOrder.insert({CachedHashStringRef(s), {priority++, false}});
 
   // Build a map from sections to their priorities.
   auto addSym = [&](Symbol &sym) {
-    auto it = symbolOrder.find(sym.getName());
+    auto it = symbolOrder.find(CachedHashStringRef(sym.getName()));
     if (it == symbolOrder.end())
       return;
     SymbolOrderEntry &ent = it->second;
@@ -1372,7 +1277,7 @@ static DenseMap<const InputSectionBase *, int> buildSectionOrder() {
 
     if (auto *d = dyn_cast<Defined>(&sym)) {
       if (auto *sec = dyn_cast_or_null<InputSectionBase>(d->section)) {
-        int &priority = sectionOrder[cast<InputSectionBase>(sec->repl)];
+        int &priority = sectionOrder[cast<InputSectionBase>(sec)];
         priority = std::min(priority, ent.priority);
       }
     }
@@ -1380,21 +1285,17 @@ static DenseMap<const InputSectionBase *, int> buildSectionOrder() {
 
   // We want both global and local symbols. We get the global ones from the
   // symbol table and iterate the object files for the local ones.
-  for (Symbol *sym : symtab->symbols())
-    if (!sym->isLazy())
-      addSym(*sym);
+  for (Symbol *sym : symtab.getSymbols())
+    addSym(*sym);
 
-  for (InputFile *file : objectFiles)
-    for (Symbol *sym : file->getSymbols()) {
-      if (!sym->isLocal())
-        break;
+  for (ELFFileBase *file : ctx.objectFiles)
+    for (Symbol *sym : file->getLocalSymbols())
       addSym(*sym);
-    }
 
   if (config->warnSymbolOrdering)
     for (auto orderEntry : symbolOrder)
       if (!orderEntry.second.present)
-        warn("symbol ordering file: no such symbol: " + orderEntry.first);
+        warn("symbol ordering file: no such symbol: " + orderEntry.first.val());
 
   return sectionOrder;
 }
@@ -1402,12 +1303,16 @@ static DenseMap<const InputSectionBase *, int> buildSectionOrder() {
 // Sorts the sections in ISD according to the provided section order.
 static void
 sortISDBySectionOrder(InputSectionDescription *isd,
-                      const DenseMap<const InputSectionBase *, int> &order) {
-  std::vector<InputSection *> unorderedSections;
-  std::vector<std::pair<InputSection *, int>> orderedSections;
+                      const DenseMap<const InputSectionBase *, int> &order,
+                      bool executableOutputSection) {
+  SmallVector<InputSection *, 0> unorderedSections;
+  SmallVector<std::pair<InputSection *, int>, 0> orderedSections;
   uint64_t unorderedSize = 0;
+  uint64_t totalSize = 0;
 
   for (InputSection *isec : isd->sections) {
+    if (executableOutputSection)
+      totalSize += isec->getSize();
     auto i = order.find(isec);
     if (i == order.end()) {
       unorderedSections.push_back(isec);
@@ -1445,8 +1350,15 @@ sortISDBySectionOrder(InputSectionDescription *isd,
   // of the second block of cold code can call the hot code without a thunk. So
   // we effectively double the amount of code that could potentially call into
   // the hot code without a thunk.
+  //
+  // The above is not necessary if total size of input sections in this "isd"
+  // is small. Note that we assume all input sections are executable if the
+  // output section is executable (which is not always true but supposed to
+  // cover most cases).
   size_t insPt = 0;
-  if (target->getThunkSectionSpacing() && !orderedSections.empty()) {
+  if (executableOutputSection && !orderedSections.empty() &&
+      target->getThunkSectionSpacing() &&
+      totalSize >= target->getThunkSectionSpacing()) {
     uint64_t unorderedPos = 0;
     for (; insPt != unorderedSections.size(); ++insPt) {
       unorderedPos += unorderedSections[insPt]->getSize();
@@ -1456,17 +1368,17 @@ sortISDBySectionOrder(InputSectionDescription *isd,
   }
 
   isd->sections.clear();
-  for (InputSection *isec : makeArrayRef(unorderedSections).slice(0, insPt))
+  for (InputSection *isec : ArrayRef(unorderedSections).slice(0, insPt))
     isd->sections.push_back(isec);
   for (std::pair<InputSection *, int> p : orderedSections)
     isd->sections.push_back(p.first);
-  for (InputSection *isec : makeArrayRef(unorderedSections).slice(insPt))
+  for (InputSection *isec : ArrayRef(unorderedSections).slice(insPt))
     isd->sections.push_back(isec);
 }
 
-static void sortSection(OutputSection *sec,
+static void sortSection(OutputSection &osec,
                         const DenseMap<const InputSectionBase *, int> &order) {
-  StringRef name = sec->name;
+  StringRef name = osec.name;
 
   // Never sort these.
   if (name == ".init" || name == ".fini")
@@ -1477,7 +1389,7 @@ static void sortSection(OutputSection *sec,
   // sections in the required order from the beginning so that the in.relaIplt
   // section is placed last in an output section. Here we just do not apply
   // sorting for an output section which holds the in.relaIplt section.
-  if (in.relaIplt->getParent() == sec)
+  if (in.relaIplt->getParent() == &osec)
     return;
 
   // Sort input sections by priority using the list provided by
@@ -1485,41 +1397,30 @@ static void sortSection(OutputSection *sec,
   // digit radix sort. The sections may be sorted stably again by a more
   // significant key.
   if (!order.empty())
-    for (BaseCommand *b : sec->sectionCommands)
+    for (SectionCommand *b : osec.commands)
       if (auto *isd = dyn_cast<InputSectionDescription>(b))
-        sortISDBySectionOrder(isd, order);
-
-  // Sort input sections by section name suffixes for
-  // __attribute__((init_priority(N))).
-  if (name == ".init_array" || name == ".fini_array") {
-    if (!script->hasSectionsCommand)
-      sec->sortInitFini();
-    return;
-  }
+        sortISDBySectionOrder(isd, order, osec.flags & SHF_EXECINSTR);
 
-  // Sort input sections by the special rule for .ctors and .dtors.
-  if (name == ".ctors" || name == ".dtors") {
-    if (!script->hasSectionsCommand)
-      sec->sortCtorsDtors();
+  if (script->hasSectionsCommand)
     return;
-  }
 
-  // .toc is allocated just after .got and is accessed using GOT-relative
-  // relocations. Object files compiled with small code model have an
-  // addressable range of [.got, .got + 0xFFFC] for GOT-relative relocations.
-  // To reduce the risk of relocation overflow, .toc contents are sorted so that
-  // sections having smaller relocation offsets are at beginning of .toc
-  if (config->emachine == EM_PPC64 && name == ".toc") {
-    if (script->hasSectionsCommand)
-      return;
-    assert(sec->sectionCommands.size() == 1);
-    auto *isd = cast<InputSectionDescription>(sec->sectionCommands[0]);
+  if (name == ".init_array" || name == ".fini_array") {
+    osec.sortInitFini();
+  } else if (name == ".ctors" || name == ".dtors") {
+    osec.sortCtorsDtors();
+  } else if (config->emachine == EM_PPC64 && name == ".toc") {
+    // .toc is allocated just after .got and is accessed using GOT-relative
+    // relocations. Object files compiled with small code model have an
+    // addressable range of [.got, .got + 0xFFFC] for GOT-relative relocations.
+    // To reduce the risk of relocation overflow, .toc contents are sorted so
+    // that sections having smaller relocation offsets are at beginning of .toc
+    assert(osec.commands.size() == 1);
+    auto *isd = cast<InputSectionDescription>(osec.commands[0]);
     llvm::stable_sort(isd->sections,
                       [](const InputSection *a, const InputSection *b) -> bool {
                         return a->file->ppc64SmallCodeModelTocRelocs &&
                                !b->file->ppc64SmallCodeModelTocRelocs;
                       });
-    return;
   }
 }
 
@@ -1529,51 +1430,42 @@ template <class ELFT> void Writer<ELFT>::sortInputSections() {
   // Build the order once since it is expensive.
   DenseMap<const InputSectionBase *, int> order = buildSectionOrder();
   maybeShuffle(order);
-  for (BaseCommand *base : script->sectionCommands)
-    if (auto *sec = dyn_cast<OutputSection>(base))
-      sortSection(sec, order);
+  for (SectionCommand *cmd : script->sectionCommands)
+    if (auto *osd = dyn_cast<OutputDesc>(cmd))
+      sortSection(osd->osec, order);
 }
 
 template <class ELFT> void Writer<ELFT>::sortSections() {
   llvm::TimeTraceScope timeScope("Sort sections");
-  script->adjustSectionsBeforeSorting();
 
   // Don't sort if using -r. It is not necessary and we want to preserve the
   // relative order for SHF_LINK_ORDER sections.
-  if (config->relocatable)
+  if (config->relocatable) {
+    script->adjustOutputSections();
     return;
+  }
 
   sortInputSections();
 
-  for (BaseCommand *base : script->sectionCommands) {
-    auto *os = dyn_cast<OutputSection>(base);
-    if (!os)
-      continue;
-    os->sortRank = getSectionRank(os);
-
-    // We want to assign rude approximation values to outSecOff fields
-    // to know the relative order of the input sections. We use it for
-    // sorting SHF_LINK_ORDER sections. See resolveShfLinkOrder().
-    uint64_t i = 0;
-    for (InputSection *sec : getInputSections(os))
-      sec->outSecOff = i++;
-  }
-
+  for (SectionCommand *cmd : script->sectionCommands)
+    if (auto *osd = dyn_cast<OutputDesc>(cmd))
+      osd->osec.sortRank = getSectionRank(osd->osec);
   if (!script->hasSectionsCommand) {
     // We know that all the OutputSections are contiguous in this case.
-    auto isSection = [](BaseCommand *base) { return isa<OutputSection>(base); };
+    auto isSection = [](SectionCommand *cmd) { return isa<OutputDesc>(cmd); };
     std::stable_sort(
         llvm::find_if(script->sectionCommands, isSection),
         llvm::find_if(llvm::reverse(script->sectionCommands), isSection).base(),
         compareSections);
-
-    // Process INSERT commands. From this point onwards the order of
-    // script->sectionCommands is fixed.
-    script->processInsertCommands();
-    return;
   }
 
+  // Process INSERT commands and update output section attributes. From this
+  // point onwards the order of script->sectionCommands is fixed.
   script->processInsertCommands();
+  script->adjustOutputSections();
+
+  if (!script->hasSectionsCommand)
+    return;
 
   // Orphan sections are sections present in the input files which are
   // not explicitly placed into the output file by the linker script.
@@ -1616,9 +1508,9 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
 
   auto i = script->sectionCommands.begin();
   auto e = script->sectionCommands.end();
-  auto nonScriptI = std::find_if(i, e, [](BaseCommand *base) {
-    if (auto *sec = dyn_cast<OutputSection>(base))
-      return sec->sectionIndex == UINT32_MAX;
+  auto nonScriptI = std::find_if(i, e, [](SectionCommand *cmd) {
+    if (auto *osd = dyn_cast<OutputDesc>(cmd))
+      return osd->osec.sectionIndex == UINT32_MAX;
     return false;
   });
 
@@ -1630,7 +1522,7 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
   // the script with ". = 0xabcd" and the expectation is that every section is
   // after that.
   auto firstSectionOrDotAssignment =
-      std::find_if(i, e, [](BaseCommand *cmd) { return !shouldSkip(cmd); });
+      std::find_if(i, e, [](SectionCommand *cmd) { return !shouldSkip(cmd); });
   if (firstSectionOrDotAssignment != e &&
       isa<SymbolAssignment>(**firstSectionOrDotAssignment))
     ++firstSectionOrDotAssignment;
@@ -1638,13 +1530,13 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
 
   while (nonScriptI != e) {
     auto pos = findOrphanPos(i, nonScriptI);
-    OutputSection *orphan = cast<OutputSection>(*nonScriptI);
+    OutputSection *orphan = &cast<OutputDesc>(*nonScriptI)->osec;
 
     // As an optimization, find all sections with the same sort rank
     // and insert them with one rotate.
     unsigned rank = orphan->sortRank;
-    auto end = std::find_if(nonScriptI + 1, e, [=](BaseCommand *cmd) {
-      return cast<OutputSection>(cmd)->sortRank != rank;
+    auto end = std::find_if(nonScriptI + 1, e, [=](SectionCommand *cmd) {
+      return cast<OutputDesc>(cmd)->osec.sortRank != rank;
     });
     std::rotate(pos, nonScriptI, end);
     nonScriptI = end;
@@ -1682,10 +1574,10 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {
 
     // Link order may be distributed across several InputSectionDescriptions.
     // Sorting is performed separately.
-    std::vector<InputSection **> scriptSections;
-    std::vector<InputSection *> sections;
-    for (BaseCommand *base : sec->sectionCommands) {
-      auto *isd = dyn_cast<InputSectionDescription>(base);
+    SmallVector<InputSection **, 0> scriptSections;
+    SmallVector<InputSection *, 0> sections;
+    for (SectionCommand *cmd : sec->commands) {
+      auto *isd = dyn_cast<InputSectionDescription>(cmd);
       if (!isd)
         continue;
       bool hasLinkOrder = false;
@@ -1733,21 +1625,24 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
   // can assign Virtual Addresses to OutputSections that are not monotonically
   // increasing.
   for (Partition &part : partitions)
-    finalizeSynthetic(part.armExidx);
+    finalizeSynthetic(part.armExidx.get());
   resolveShfLinkOrder();
 
   // Converts call x@GDPLT to call __tls_get_addr
   if (config->emachine == EM_HEXAGON)
     hexagonTLSSymbolUpdate(outputSections);
 
-  int assignPasses = 0;
+  uint32_t pass = 0, assignPasses = 0;
   for (;;) {
-    bool changed = target->needsThunks && tc.createThunks(outputSections);
+    bool changed = target->needsThunks ? tc.createThunks(pass, outputSections)
+                                       : target->relaxOnce(pass);
+    ++pass;
 
     // With Thunk Size much smaller than branch range we expect to
     // converge quickly; if we get to 15 something has gone wrong.
-    if (changed && tc.pass >= 15) {
-      error("thunk creation not converged");
+    if (changed && pass >= 15) {
+      error(target->needsThunks ? "thunk creation not converged"
+                                : "relaxation not converged");
       break;
     }
 
@@ -1785,15 +1680,23 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
       }
     }
   }
+  if (!config->relocatable && config->emachine == EM_RISCV)
+    riscvFinalizeRelax(pass);
+
+  if (config->relocatable)
+    for (OutputSection *sec : outputSections)
+      sec->addr = 0;
 
   // If addrExpr is set, the address may not be a multiple of the alignment.
   // Warn because this is error-prone.
-  for (BaseCommand *cmd : script->sectionCommands)
-    if (auto *os = dyn_cast<OutputSection>(cmd))
-      if (os->addr % os->alignment != 0)
-        warn("address (0x" + Twine::utohexstr(os->addr) + ") of section " +
-             os->name + " is not a multiple of alignment (" +
-             Twine(os->alignment) + ")");
+  for (SectionCommand *cmd : script->sectionCommands)
+    if (auto *osd = dyn_cast<OutputDesc>(cmd)) {
+      OutputSection *osec = &osd->osec;
+      if (osec->addr % osec->addralign != 0)
+        warn("address (0x" + Twine::utohexstr(osec->addr) + ") of section " +
+             osec->name + " is not a multiple of alignment (" +
+             Twine(osec->addralign) + ")");
+    }
 }
 
 // If Input Sections have been shrunk (basic block sections) then
@@ -1801,7 +1704,7 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
 // block sections, input sections can shrink when the jump instructions at
 // the end of the section are relaxed.
 static void fixSymbolsAfterShrinking() {
-  for (InputFile *File : objectFiles) {
+  for (InputFile *File : ctx.objectFiles) {
     parallelForEach(File->getSymbols(), [&](Symbol *Sym) {
       auto *def = dyn_cast<Defined>(Sym);
       if (!def)
@@ -1811,11 +1714,11 @@ static void fixSymbolsAfterShrinking() {
       if (!sec)
         return;
 
-      const InputSectionBase *inputSec = dyn_cast<InputSectionBase>(sec->repl);
+      const InputSectionBase *inputSec = dyn_cast<InputSectionBase>(sec);
       if (!inputSec || !inputSec->bytesDropped)
         return;
 
-      const size_t OldSize = inputSec->data().size();
+      const size_t OldSize = inputSec->content().size();
       const size_t NewSize = OldSize - inputSec->bytesDropped;
 
       if (def->value > NewSize && def->value <= OldSize) {
@@ -1845,6 +1748,7 @@ static void fixSymbolsAfterShrinking() {
 // option is used.
 template <class ELFT> void Writer<ELFT>::optimizeBasicBlockJumps() {
   assert(config->optimizeBBJumps);
+  SmallVector<InputSection *, 0> storage;
 
   script->assignAddresses();
   // For every output section that has executable input sections, this
@@ -1853,21 +1757,19 @@ template <class ELFT> void Writer<ELFT>::optimizeBasicBlockJumps() {
   //      jump to the following section as it is not required.
   //   2. If there are two consecutive jump instructions, it checks
   //      if they can be flipped and one can be deleted.
-  for (OutputSection *os : outputSections) {
-    if (!(os->flags & SHF_EXECINSTR))
+  for (OutputSection *osec : outputSections) {
+    if (!(osec->flags & SHF_EXECINSTR))
       continue;
-    std::vector<InputSection *> sections = getInputSections(os);
-    std::vector<unsigned> result(sections.size());
+    ArrayRef<InputSection *> sections = getInputSections(*osec, storage);
+    size_t numDeleted = 0;
     // Delete all fall through jump instructions.  Also, check if two
     // consecutive jump instructions can be flipped so that a fall
     // through jmp instruction can be deleted.
-    parallelForEachN(0, sections.size(), [&](size_t i) {
+    for (size_t i = 0, e = sections.size(); i != e; ++i) {
       InputSection *next = i + 1 < sections.size() ? sections[i + 1] : nullptr;
-      InputSection &is = *sections[i];
-      result[i] =
-          target->deleteFallThruJmpInsn(is, is.getFile<ELFT>(), next) ? 1 : 0;
-    });
-    size_t numDeleted = std::count(result.begin(), result.end(), 1);
+      InputSection &sec = *sections[i];
+      numDeleted += target->deleteFallThruJmpInsn(sec, sec.file, next);
+    }
     if (numDeleted > 0) {
       script->assignAddresses();
       LLVM_DEBUG(llvm::dbgs()
@@ -1877,11 +1779,9 @@ template <class ELFT> void Writer<ELFT>::optimizeBasicBlockJumps() {
 
   fixSymbolsAfterShrinking();
 
-  for (OutputSection *os : outputSections) {
-    std::vector<InputSection *> sections = getInputSections(os);
-    for (InputSection *is : sections)
+  for (OutputSection *osec : outputSections)
+    for (InputSection *is : getInputSections(*osec, storage))
       is->trim();
-  }
 }
 
 // In order to allow users to manipulate linker-synthesized sections,
@@ -1900,161 +1800,158 @@ static void removeUnusedSyntheticSections() {
   // All input synthetic sections that can be empty are placed after
   // all regular ones. Reverse iterate to find the first synthetic section
   // after a non-synthetic one which will be our starting point.
-  auto start = std::find_if(inputSections.rbegin(), inputSections.rend(),
-                            [](InputSectionBase *s) {
-                              return !isa<SyntheticSection>(s);
-                            })
-                   .base();
-
-  DenseSet<InputSectionDescription *> isdSet;
-  // Mark unused synthetic sections for deletion
-  auto end = std::stable_partition(
-      start, inputSections.end(), [&](InputSectionBase *s) {
-        SyntheticSection *ss = dyn_cast<SyntheticSection>(s);
-        OutputSection *os = ss->getParent();
-        if (!os || ss->isNeeded())
-          return true;
-
-        // If we reach here, then ss is an unused synthetic section and we want
-        // to remove it from the corresponding input section description, and
-        // orphanSections.
-        for (BaseCommand *b : os->sectionCommands)
-          if (auto *isd = dyn_cast<InputSectionDescription>(b))
-            isdSet.insert(isd);
-
-        llvm::erase_if(
-            script->orphanSections,
-            [=](const InputSectionBase *isec) { return isec == ss; });
-
-        return false;
+  auto start =
+      llvm::find_if(llvm::reverse(ctx.inputSections), [](InputSectionBase *s) {
+        return !isa<SyntheticSection>(s);
+      }).base();
+
+  // Remove unused synthetic sections from ctx.inputSections;
+  DenseSet<InputSectionBase *> unused;
+  auto end =
+      std::remove_if(start, ctx.inputSections.end(), [&](InputSectionBase *s) {
+        auto *sec = cast<SyntheticSection>(s);
+        if (sec->getParent() && sec->isNeeded())
+          return false;
+        unused.insert(sec);
+        return true;
       });
-
-  DenseSet<InputSectionBase *> unused(end, inputSections.end());
-  for (auto *isd : isdSet)
-    llvm::erase_if(isd->sections,
-                   [=](InputSection *isec) { return unused.count(isec); });
-
-  // Erase unused synthetic sections.
-  inputSections.erase(end, inputSections.end());
+  ctx.inputSections.erase(end, ctx.inputSections.end());
+
+  // Remove unused synthetic sections from the corresponding input section
+  // description and orphanSections.
+  for (auto *sec : unused)
+    if (OutputSection *osec = cast<SyntheticSection>(sec)->getParent())
+      for (SectionCommand *cmd : osec->commands)
+        if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
+          llvm::erase_if(isd->sections, [&](InputSection *isec) {
+            return unused.count(isec);
+          });
+  llvm::erase_if(script->orphanSections, [&](const InputSectionBase *sec) {
+    return unused.count(sec);
+  });
 }
 
 // Create output section objects and add them to OutputSections.
 template <class ELFT> void Writer<ELFT>::finalizeSections() {
-  Out::preinitArray = findSection(".preinit_array");
-  Out::initArray = findSection(".init_array");
-  Out::finiArray = findSection(".fini_array");
-
-  // The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop
-  // symbols for sections, so that the runtime can get the start and end
-  // addresses of each section by section name. Add such symbols.
   if (!config->relocatable) {
+    Out::preinitArray = findSection(".preinit_array");
+    Out::initArray = findSection(".init_array");
+    Out::finiArray = findSection(".fini_array");
+
+    // The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop
+    // symbols for sections, so that the runtime can get the start and end
+    // addresses of each section by section name. Add such symbols.
     addStartEndSymbols();
-    for (BaseCommand *base : script->sectionCommands)
-      if (auto *sec = dyn_cast<OutputSection>(base))
-        addStartStopSymbols(sec);
-  }
-
-  // Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type.
-  // It should be okay as no one seems to care about the type.
-  // Even the author of gold doesn't remember why gold behaves that way.
-  // https://sourceware.org/ml/binutils/2002-03/msg00360.html
-  if (mainPart->dynamic->parent)
-    symtab->addSymbol(Defined{/*file=*/nullptr, "_DYNAMIC", STB_WEAK,
-                              STV_HIDDEN, STT_NOTYPE,
-                              /*value=*/0, /*size=*/0, mainPart->dynamic});
-
-  // Define __rel[a]_iplt_{start,end} symbols if needed.
-  addRelIpltSymbols();
-
-  // RISC-V's gp can address +/- 2 KiB, set it to .sdata + 0x800. This symbol
-  // should only be defined in an executable. If .sdata does not exist, its
-  // value/section does not matter but it has to be relative, so set its
-  // st_shndx arbitrarily to 1 (Out::elfHeader).
-  if (config->emachine == EM_RISCV && !config->shared) {
-    OutputSection *sec = findSection(".sdata");
-    ElfSym::riscvGlobalPointer =
-        addOptionalRegular("__global_pointer$", sec ? sec : Out::elfHeader,
-                           0x800, STV_DEFAULT, STB_GLOBAL);
-  }
-
-  if (config->emachine == EM_X86_64) {
-    // On targets that support TLSDESC, _TLS_MODULE_BASE_ is defined in such a
-    // way that:
-    //
-    // 1) Without relaxation: it produces a dynamic TLSDESC relocation that
-    // computes 0.
-    // 2) With LD->LE relaxation: _TLS_MODULE_BASE_@tpoff = 0 (lowest address in
-    // the TLS block).
-    //
-    // 2) is special cased in @tpoff computation. To satisfy 1), we define it as
-    // an absolute symbol of zero. This is different from GNU linkers which
-    // define _TLS_MODULE_BASE_ relative to the first TLS section.
-    Symbol *s = symtab->find("_TLS_MODULE_BASE_");
-    if (s && s->isUndefined()) {
-      s->resolve(Defined{/*file=*/nullptr, s->getName(), STB_GLOBAL, STV_HIDDEN,
-                         STT_TLS, /*value=*/0, 0,
-                         /*section=*/nullptr});
-      ElfSym::tlsModuleBase = cast<Defined>(s);
+    for (SectionCommand *cmd : script->sectionCommands)
+      if (auto *osd = dyn_cast<OutputDesc>(cmd))
+        addStartStopSymbols(osd->osec);
+
+    // Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type.
+    // It should be okay as no one seems to care about the type.
+    // Even the author of gold doesn't remember why gold behaves that way.
+    // https://sourceware.org/ml/binutils/2002-03/msg00360.html
+    if (mainPart->dynamic->parent) {
+      Symbol *s = symtab.addSymbol(Defined{
+          /*file=*/nullptr, "_DYNAMIC", STB_WEAK, STV_HIDDEN, STT_NOTYPE,
+          /*value=*/0, /*size=*/0, mainPart->dynamic.get()});
+      s->isUsedInRegularObj = true;
+    }
+
+    // Define __rel[a]_iplt_{start,end} symbols if needed.
+    addRelIpltSymbols();
+
+    // RISC-V's gp can address +/- 2 KiB, set it to .sdata + 0x800. This symbol
+    // should only be defined in an executable. If .sdata does not exist, its
+    // value/section does not matter but it has to be relative, so set its
+    // st_shndx arbitrarily to 1 (Out::elfHeader).
+    if (config->emachine == EM_RISCV && !config->shared) {
+      OutputSection *sec = findSection(".sdata");
+      addOptionalRegular("__global_pointer$", sec ? sec : Out::elfHeader, 0x800,
+                         STV_DEFAULT);
+    }
+
+    if (config->emachine == EM_386 || config->emachine == EM_X86_64) {
+      // On targets that support TLSDESC, _TLS_MODULE_BASE_ is defined in such a
+      // way that:
+      //
+      // 1) Without relaxation: it produces a dynamic TLSDESC relocation that
+      // computes 0.
+      // 2) With LD->LE relaxation: _TLS_MODULE_BASE_@tpoff = 0 (lowest address
+      // in the TLS block).
+      //
+      // 2) is special cased in @tpoff computation. To satisfy 1), we define it
+      // as an absolute symbol of zero. This is different from GNU linkers which
+      // define _TLS_MODULE_BASE_ relative to the first TLS section.
+      Symbol *s = symtab.find("_TLS_MODULE_BASE_");
+      if (s && s->isUndefined()) {
+        s->resolve(Defined{/*file=*/nullptr, StringRef(), STB_GLOBAL,
+                           STV_HIDDEN, STT_TLS, /*value=*/0, 0,
+                           /*section=*/nullptr});
+        ElfSym::tlsModuleBase = cast<Defined>(s);
+      }
     }
-  }
 
-  {
-    llvm::TimeTraceScope timeScope("Finalize .eh_frame");
     // This responsible for splitting up .eh_frame section into
     // pieces. The relocation scan uses those pieces, so this has to be
     // earlier.
-    for (Partition &part : partitions)
-      finalizeSynthetic(part.ehFrame);
-  }
+    {
+      llvm::TimeTraceScope timeScope("Finalize .eh_frame");
+      for (Partition &part : partitions)
+        finalizeSynthetic(part.ehFrame.get());
+    }
 
-  for (Symbol *sym : symtab->symbols())
-    sym->isPreemptible = computeIsPreemptible(*sym);
+    if (config->hasDynSymTab) {
+      parallelForEach(symtab.getSymbols(), [](Symbol *sym) {
+        sym->isPreemptible = computeIsPreemptible(*sym);
+      });
+    }
+  }
 
   // Change values of linker-script-defined symbols from placeholders (assigned
   // by declareSymbols) to actual definitions.
   script->processSymbolAssignments();
 
-  {
+  if (!config->relocatable) {
     llvm::TimeTraceScope timeScope("Scan relocations");
     // Scan relocations. This must be done after every symbol is declared so
     // that we can correctly decide if a dynamic relocation is needed. This is
     // called after processSymbolAssignments() because it needs to know whether
     // a linker-script-defined symbol is absolute.
     ppc64noTocRelax.clear();
-    if (!config->relocatable) {
-      forEachRelSec(scanRelocations<ELFT>);
-      reportUndefinedSymbols<ELFT>();
-    }
-  }
-
-  if (in.plt && in.plt->isNeeded())
-    in.plt->addSymbols();
-  if (in.iplt && in.iplt->isNeeded())
-    in.iplt->addSymbols();
-
-  if (config->unresolvedSymbolsInShlib != UnresolvedPolicy::Ignore) {
-    auto diagnose =
-        config->unresolvedSymbolsInShlib == UnresolvedPolicy::ReportError
-            ? errorOrWarn
-            : warn;
-    // Error on undefined symbols in a shared object, if all of its DT_NEEDED
-    // entries are seen. These cases would otherwise lead to runtime errors
-    // reported by the dynamic linker.
-    //
-    // ld.bfd traces all DT_NEEDED to emulate the logic of the dynamic linker to
-    // catch more cases. That is too much for us. Our approach resembles the one
-    // used in ld.gold, achieves a good balance to be useful but not too smart.
-    for (SharedFile *file : sharedFiles) {
-      bool allNeededIsKnown =
-          llvm::all_of(file->dtNeeded, [&](StringRef needed) {
-            return symtab->soNames.count(needed);
-          });
-      if (!allNeededIsKnown)
-        continue;
-      for (Symbol *sym : file->requiredSymbols)
-        if (sym->isUndefined() && !sym->isWeak())
-          diagnose(toString(file) + ": undefined reference to " +
-                   toString(*sym) + " [--no-allow-shlib-undefined]");
+    scanRelocations<ELFT>();
+    reportUndefinedSymbols();
+    postScanRelocations();
+
+    if (in.plt && in.plt->isNeeded())
+      in.plt->addSymbols();
+    if (in.iplt && in.iplt->isNeeded())
+      in.iplt->addSymbols();
+
+    if (config->unresolvedSymbolsInShlib != UnresolvedPolicy::Ignore) {
+      auto diagnose =
+          config->unresolvedSymbolsInShlib == UnresolvedPolicy::ReportError
+              ? errorOrWarn
+              : warn;
+      // Error on undefined symbols in a shared object, if all of its DT_NEEDED
+      // entries are seen. These cases would otherwise lead to runtime errors
+      // reported by the dynamic linker.
+      //
+      // ld.bfd traces all DT_NEEDED to emulate the logic of the dynamic linker
+      // to catch more cases. That is too much for us. Our approach resembles
+      // the one used in ld.gold, achieves a good balance to be useful but not
+      // too smart.
+      for (SharedFile *file : ctx.sharedFiles) {
+        bool allNeededIsKnown =
+            llvm::all_of(file->dtNeeded, [&](StringRef needed) {
+              return symtab.soNames.count(CachedHashStringRef(needed));
+            });
+        if (!allNeededIsKnown)
+          continue;
+        for (Symbol *sym : file->requiredSymbols)
+          if (sym->isUndefined() && !sym->isWeak())
+            diagnose("undefined reference due to --no-allow-shlib-undefined: " +
+                     toString(*sym) + "\n>>> referenced by " + toString(file));
+      }
     }
   }
 
@@ -2062,9 +1959,11 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
     llvm::TimeTraceScope timeScope("Add symbols to symtabs");
     // Now that we have defined all possible global symbols including linker-
     // synthesized ones. Visit all symbols to give the finishing touches.
-    for (Symbol *sym : symtab->symbols()) {
-      if (!includeInSymtab(*sym))
+    for (Symbol *sym : symtab.getSymbols()) {
+      if (!sym->isUsedInRegularObj || !includeInSymtab(*sym))
         continue;
+      if (!config->relocatable)
+        sym->binding = sym->computeBinding();
       if (in.symTab)
         in.symTab->addSymbol(sym);
 
@@ -2089,10 +1988,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
     }
   }
 
-  // Do not proceed if there was an undefined symbol.
-  if (errorCount())
-    return;
-
   if (in.mipsGot)
     in.mipsGot->build();
 
@@ -2101,11 +1996,15 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
 
   sortSections();
 
-  // Now that we have the final list, create a list of all the
-  // OutputSections for convenience.
-  for (BaseCommand *base : script->sectionCommands)
-    if (auto *sec = dyn_cast<OutputSection>(base))
-      outputSections.push_back(sec);
+  // Create a list of OutputSections, assign sectionIndex, and populate
+  // in.shStrTab.
+  for (SectionCommand *cmd : script->sectionCommands)
+    if (auto *osd = dyn_cast<OutputDesc>(cmd)) {
+      OutputSection *osec = &osd->osec;
+      outputSections.push_back(osec);
+      osec->sectionIndex = outputSections.size();
+      osec->shName = in.shStrTab->addString(osec->name);
+    }
 
   // Prefer command line supplied address over other constraints.
   for (OutputSection *sec : outputSections) {
@@ -2117,7 +2016,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
   // With the outputSections available check for GDPLT relocations
   // and add __tls_get_addr symbol if needed.
   if (config->emachine == EM_HEXAGON && hexagonNeedsTLSSymbol(outputSections)) {
-    Symbol *sym = symtab->addSymbol(Undefined{
+    Symbol *sym = symtab.addSymbol(Undefined{
         nullptr, "__tls_get_addr", STB_GLOBAL, STV_DEFAULT, STT_NOTYPE});
     sym->isPreemptible = true;
     partitions[0].dynSymTab->addSymbol(sym);
@@ -2127,12 +2026,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
   // to 1 to make __ehdr_start defined. The section number is not
   // particularly relevant.
   Out::elfHeader->sectionIndex = 1;
-
-  for (size_t i = 0, e = outputSections.size(); i != e; ++i) {
-    OutputSection *sec = outputSections[i];
-    sec->sectionIndex = i + 1;
-    sec->shName = in.shStrTab->addString(sec->name);
-  }
+  Out::elfHeader->size = sizeof(typename ELFT::Ehdr);
 
   // Binary and relocatable output does not have PHDRS.
   // The headers have to be created before finalize as that can influence the
@@ -2170,35 +2064,44 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
   {
     llvm::TimeTraceScope timeScope("Finalize synthetic sections");
 
-    finalizeSynthetic(in.bss);
-    finalizeSynthetic(in.bssRelRo);
-    finalizeSynthetic(in.symTabShndx);
-    finalizeSynthetic(in.shStrTab);
-    finalizeSynthetic(in.strTab);
-    finalizeSynthetic(in.got);
-    finalizeSynthetic(in.mipsGot);
-    finalizeSynthetic(in.igotPlt);
-    finalizeSynthetic(in.gotPlt);
-    finalizeSynthetic(in.relaIplt);
-    finalizeSynthetic(in.relaPlt);
-    finalizeSynthetic(in.plt);
-    finalizeSynthetic(in.iplt);
-    finalizeSynthetic(in.ppc32Got2);
-    finalizeSynthetic(in.partIndex);
+    finalizeSynthetic(in.bss.get());
+    finalizeSynthetic(in.bssRelRo.get());
+    finalizeSynthetic(in.symTabShndx.get());
+    finalizeSynthetic(in.shStrTab.get());
+    finalizeSynthetic(in.strTab.get());
+    finalizeSynthetic(in.got.get());
+    finalizeSynthetic(in.mipsGot.get());
+    finalizeSynthetic(in.igotPlt.get());
+    finalizeSynthetic(in.gotPlt.get());
+    finalizeSynthetic(in.relaIplt.get());
+    finalizeSynthetic(in.relaPlt.get());
+    finalizeSynthetic(in.plt.get());
+    finalizeSynthetic(in.iplt.get());
+    finalizeSynthetic(in.ppc32Got2.get());
+    finalizeSynthetic(in.partIndex.get());
 
     // Dynamic section must be the last one in this list and dynamic
     // symbol table section (dynSymTab) must be the first one.
     for (Partition &part : partitions) {
-      finalizeSynthetic(part.dynSymTab);
-      finalizeSynthetic(part.gnuHashTab);
-      finalizeSynthetic(part.hashTab);
-      finalizeSynthetic(part.verDef);
-      finalizeSynthetic(part.relaDyn);
-      finalizeSynthetic(part.relrDyn);
-      finalizeSynthetic(part.ehFrameHdr);
-      finalizeSynthetic(part.verSym);
-      finalizeSynthetic(part.verNeed);
-      finalizeSynthetic(part.dynamic);
+      if (part.relaDyn) {
+        part.relaDyn->mergeRels();
+        // Compute DT_RELACOUNT to be used by part.dynamic.
+        part.relaDyn->partitionRels();
+        finalizeSynthetic(part.relaDyn.get());
+      }
+      if (part.relrDyn) {
+        part.relrDyn->mergeRels();
+        finalizeSynthetic(part.relrDyn.get());
+      }
+
+      finalizeSynthetic(part.dynSymTab.get());
+      finalizeSynthetic(part.gnuHashTab.get());
+      finalizeSynthetic(part.hashTab.get());
+      finalizeSynthetic(part.verDef.get());
+      finalizeSynthetic(part.ehFrameHdr.get());
+      finalizeSynthetic(part.verSym.get());
+      finalizeSynthetic(part.verNeed.get());
+      finalizeSynthetic(part.dynamic.get());
     }
   }
 
@@ -2227,6 +2130,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
   //    sometimes using forward symbol declarations. We want to set the correct
   //    values. They also might change after adding the thunks.
   finalizeAddressDependentContent();
+
+  // All information needed for OutputSection part of Map file is available.
   if (errorCount())
     return;
 
@@ -2234,8 +2139,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
     llvm::TimeTraceScope timeScope("Finalize synthetic sections");
     // finalizeAddressDependentContent may have added local symbols to the
     // static symbol table.
-    finalizeSynthetic(in.symTab);
-    finalizeSynthetic(in.ppc64LongBranchTarget);
+    finalizeSynthetic(in.symTab.get());
+    finalizeSynthetic(in.ppc64LongBranchTarget.get());
   }
 
   // Relaxation to delete inter-basic block jumps created by basic block
@@ -2252,18 +2157,20 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
 }
 
 // Ensure data sections are not mixed with executable sections when
-// -execute-only is used. -execute-only is a feature to make pages executable
-// but not readable, and the feature is currently supported only on AArch64.
+// --execute-only is used. --execute-only make pages executable but not
+// readable.
 template <class ELFT> void Writer<ELFT>::checkExecuteOnly() {
   if (!config->executeOnly)
     return;
 
-  for (OutputSection *os : outputSections)
-    if (os->flags & SHF_EXECINSTR)
-      for (InputSection *isec : getInputSections(os))
+  SmallVector<InputSection *, 0> storage;
+  for (OutputSection *osec : outputSections)
+    if (osec->flags & SHF_EXECINSTR)
+      for (InputSection *isec : getInputSections(*osec, storage))
         if (!(isec->flags & SHF_EXECINSTR))
-          error("cannot place " + toString(isec) + " into " + toString(os->name) +
-                ": -execute-only does not support intermingling data and code");
+          error("cannot place " + toString(isec) + " into " +
+                toString(osec->name) +
+                ": --execute-only does not support intermingling data and code");
 }
 
 // The linker is expected to define SECNAME_start and SECNAME_end
@@ -2290,7 +2197,7 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
     Default = Out::elfHeader;
 
   auto define = [=](StringRef start, StringRef end, OutputSection *os) {
-    if (os) {
+    if (os && !script->isDiscarded(os)) {
       addOptionalRegular(start, os, 0);
       addOptionalRegular(end, os, -1);
     } else {
@@ -2313,13 +2220,13 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
 // 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(OutputSection *sec) {
-  StringRef s = sec->name;
+void Writer<ELFT>::addStartStopSymbols(OutputSection &osec) {
+  StringRef s = osec.name;
   if (!isValidCIdentifier(s))
     return;
-  addOptionalRegular(saver.save("__start_" + s), sec, 0,
+  addOptionalRegular(saver().save("__start_" + s), &osec, 0,
                      config->zStartStopVisibility);
-  addOptionalRegular(saver.save("__stop_" + s), sec, -1,
+  addOptionalRegular(saver().save("__stop_" + s), &osec, -1,
                      config->zStartStopVisibility);
 }
 
@@ -2352,8 +2259,8 @@ static uint64_t computeFlags(uint64_t flags) {
 // Decide which program headers to create and which sections to include in each
 // one.
 template <class ELFT>
-std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs(Partition &part) {
-  std::vector<PhdrEntry *> ret;
+SmallVector<PhdrEntry *, 0> Writer<ELFT>::createPhdrs(Partition &part) {
+  SmallVector<PhdrEntry *, 0> ret;
   auto addHdr = [&](unsigned type, unsigned flags) -> PhdrEntry * {
     ret.push_back(make<PhdrEntry>(type, flags));
     return ret.back();
@@ -2514,7 +2421,7 @@ std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs(Partition &part) {
     if (sec->partition != partNo)
       continue;
     if (sec->type == SHT_NOTE && (sec->flags & SHF_ALLOC)) {
-      if (!note || sec->lmaExpr || note->lastSec->alignment != sec->alignment)
+      if (!note || sec->lmaExpr || note->lastSec->addralign != sec->addralign)
         note = addHdr(PT_NOTE, PF_R);
       note->add(sec);
     } else {
@@ -2548,7 +2455,7 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
     OutputSection *cmd = p->firstSec;
     if (!cmd)
       return;
-    cmd->alignExpr = [align = cmd->alignment]() { return align; };
+    cmd->alignExpr = [align = cmd->addralign]() { return align; };
     if (!cmd->addrExpr) {
       // Prefer advancing to align(dot, maxPageSize) + dot%maxPageSize to avoid
       // padding in the file contents.
@@ -2568,7 +2475,7 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
            (prev->p_flags & PF_X) != (p->p_flags & PF_X)) ||
           cmd->type == SHT_LLVM_PART_EHDR)
         cmd->addrExpr = [] {
-          return alignTo(script->getDot(), config->maxPageSize);
+          return alignToPowerOf2(script->getDot(), config->maxPageSize);
         };
       // PT_TLS is at the start of the first RW PT_LOAD. If `p` includes PT_TLS,
       // it must be the RW. Align to p_align(PT_TLS) to make sure
@@ -2585,13 +2492,13 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
       // blocks correctly. We need to keep the workaround for a while.
       else if (Out::tlsPhdr && Out::tlsPhdr->firstSec == p->firstSec)
         cmd->addrExpr = [] {
-          return alignTo(script->getDot(), config->maxPageSize) +
-                 alignTo(script->getDot() % config->maxPageSize,
-                         Out::tlsPhdr->p_align);
+          return alignToPowerOf2(script->getDot(), config->maxPageSize) +
+                 alignToPowerOf2(script->getDot() % config->maxPageSize,
+                                 Out::tlsPhdr->p_align);
         };
       else
         cmd->addrExpr = [] {
-          return alignTo(script->getDot(), config->maxPageSize) +
+          return alignToPowerOf2(script->getDot(), config->maxPageSize) +
                  script->getDot() % config->maxPageSize;
         };
     }
@@ -2642,14 +2549,15 @@ static uint64_t computeFileOffset(OutputSection *os, uint64_t off) {
     return alignTo(off, os->ptLoad->p_align, os->addr);
 
   // File offsets are not significant for .bss sections other than the first one
-  // in a PT_LOAD. By convention, we keep section offsets monotonically
+  // in a PT_LOAD/PT_TLS. By convention, we keep section offsets monotonically
   // increasing rather than setting to zero.
-   if (os->type == SHT_NOBITS)
+  if (os->type == SHT_NOBITS &&
+      (!Out::tlsPhdr || Out::tlsPhdr->firstSec != os))
      return off;
 
   // If the section is not in a PT_LOAD, we just have to align it.
   if (!os->ptLoad)
-    return alignTo(off, os->alignment);
+     return alignToPowerOf2(off, os->addralign);
 
   // If two sections share the same PT_LOAD the file offset is calculated
   // using this formula: Off2 = Off1 + (VA2 - VA1).
@@ -2657,17 +2565,6 @@ static uint64_t computeFileOffset(OutputSection *os, uint64_t off) {
   return first->offset + os->addr - first->addr;
 }
 
-// Set an in-file position to a given section and returns the end position of
-// the section.
-static uint64_t setFileOffset(OutputSection *os, uint64_t off) {
-  off = computeFileOffset(os, off);
-  os->offset = off;
-
-  if (os->type == SHT_NOBITS)
-    return off;
-  return off + os->size;
-}
-
 template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() {
   // Compute the minimum LMA of all non-empty non-NOBITS sections as minAddr.
   auto needsOffset = [](OutputSection &sec) {
@@ -2695,9 +2592,8 @@ static std::string rangeToString(uint64_t addr, uint64_t len) {
 
 // Assign file offsets to output sections.
 template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
-  uint64_t off = 0;
-  off = setFileOffset(Out::elfHeader, off);
-  off = setFileOffset(Out::programHeaders, off);
+  Out::programHeaders->offset = Out::elfHeader->size;
+  uint64_t off = Out::elfHeader->size + Out::programHeaders->size;
 
   PhdrEntry *lastRX = nullptr;
   for (Partition &part : partitions)
@@ -2710,20 +2606,25 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
   for (OutputSection *sec : outputSections) {
     if (!(sec->flags & SHF_ALLOC))
       continue;
-    off = setFileOffset(sec, off);
+    off = computeFileOffset(sec, off);
+    sec->offset = off;
+    if (sec->type != SHT_NOBITS)
+      off += sec->size;
 
     // If this is a last section of the last executable segment and that
     // segment is the last loadable segment, align the offset of the
     // following section to avoid loading non-segments parts of the file.
     if (config->zSeparate != SeparateSegmentKind::None && lastRX &&
         lastRX->lastSec == sec)
-      off = alignTo(off, config->commonPageSize);
+      off = alignToPowerOf2(off, config->maxPageSize);
   }
-  for (OutputSection *sec : outputSections)
-    if (!(sec->flags & SHF_ALLOC))
-      off = setFileOffset(sec, off);
+  for (OutputSection *osec : outputSections)
+    if (!(osec->flags & SHF_ALLOC)) {
+      osec->offset = alignToPowerOf2(off, osec->addralign);
+      off = osec->offset + osec->size;
+    }
 
-  sectionHeaderOff = alignTo(off, config->wordsize);
+  sectionHeaderOff = alignToPowerOf2(off, config->wordsize);
   fileSize = sectionHeaderOff + (outputSections.size() + 1) * sizeof(Elf_Shdr);
 
   // Our logic assumes that sections have rising VA within the same segment.
@@ -2775,8 +2676,9 @@ template <class ELFT> void Writer<ELFT>::setPhdrs(Partition &part) {
       // musl/glibc ld.so rounds the size down, so we need to round up
       // to protect the last page. This is a no-op on FreeBSD which always
       // rounds up.
-      p->p_memsz = alignTo(p->p_offset + p->p_memsz, config->commonPageSize) -
-                   p->p_offset;
+      p->p_memsz =
+          alignToPowerOf2(p->p_offset + p->p_memsz, config->commonPageSize) -
+          p->p_offset;
     }
   }
 }
@@ -2827,7 +2729,7 @@ template <class ELFT> void Writer<ELFT>::checkSections() {
   // First, check that section's VAs fit in available address space for target.
   for (OutputSection *os : outputSections)
     if ((os->addr + os->size < os->addr) ||
-        (!ELFT::Is64Bits && os->addr + os->size > UINT32_MAX))
+        (!ELFT::Is64Bits && os->addr + os->size > uint64_t(UINT32_MAX) + 1))
       errorOrWarn("section " + os->name + " at 0x" + utohexstr(os->addr) +
                   " of size 0x" + utohexstr(os->size) +
                   " exceeds available address space");
@@ -2877,11 +2779,10 @@ template <class ELFT> void Writer<ELFT>::checkSections() {
 // 2. the ENTRY(symbol) command in a linker control script;
 // 3. the value of the symbol _start, if present;
 // 4. the number represented by the entry symbol, if it is a number;
-// 5. the address of the first byte of the .text section, if present;
-// 6. the address 0.
+// 5. the address 0.
 static uint64_t getEntryAddr() {
   // Case 1, 2 or 3
-  if (Symbol *b = symtab->find(config->entry))
+  if (Symbol *b = symtab.find(config->entry))
     return b->getVA();
 
   // Case 4
@@ -2890,14 +2791,6 @@ static uint64_t getEntryAddr() {
     return addr;
 
   // Case 5
-  if (OutputSection *sec = findSection(".text")) {
-    if (config->warnMissingEntry)
-      warn("cannot find entry symbol " + config->entry + "; defaulting to 0x" +
-           utohexstr(sec->addr));
-    return sec->addr;
-  }
-
-  // Case 6
   if (config->warnMissingEntry)
     warn("cannot find entry symbol " + config->entry +
          "; not setting start address");
@@ -2982,9 +2875,10 @@ template <class ELFT> void Writer<ELFT>::openFile() {
 }
 
 template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
+  parallel::TaskGroup tg;
   for (OutputSection *sec : outputSections)
     if (sec->flags & SHF_ALLOC)
-      sec->writeTo<ELFT>(Out::bufferStart + sec->offset);
+      sec->writeTo<ELFT>(Out::bufferStart + sec->offset, tg);
 }
 
 static void fillTrap(uint8_t *i, uint8_t *end) {
@@ -3003,10 +2897,11 @@ template <class ELFT> void Writer<ELFT>::writeTrapInstr() {
     // Fill the last page.
     for (PhdrEntry *p : part.phdrs)
       if (p->p_type == PT_LOAD && (p->p_flags & PF_X))
-        fillTrap(Out::bufferStart + alignDown(p->firstSec->offset + p->p_filesz,
-                                              config->commonPageSize),
-                 Out::bufferStart + alignTo(p->firstSec->offset + p->p_filesz,
-                                            config->commonPageSize));
+        fillTrap(Out::bufferStart +
+                     alignDown(p->firstSec->offset + p->p_filesz, 4),
+                 Out::bufferStart +
+                     alignToPowerOf2(p->firstSec->offset + p->p_filesz,
+                                     config->maxPageSize));
 
     // Round up the file size of the last segment to the page boundary iff it is
     // an executable segment to ensure that other tools don't accidentally
@@ -3018,22 +2913,29 @@ template <class ELFT> void Writer<ELFT>::writeTrapInstr() {
 
     if (last && (last->p_flags & PF_X))
       last->p_memsz = last->p_filesz =
-          alignTo(last->p_filesz, config->commonPageSize);
+          alignToPowerOf2(last->p_filesz, config->maxPageSize);
   }
 }
 
 // Write section contents to a mmap'ed file.
 template <class ELFT> void Writer<ELFT>::writeSections() {
-  // In -r or -emit-relocs mode, write the relocation sections first as in
-  // ELf_Rel targets we might find out that we need to modify the relocated
-  // section while doing it.
-  for (OutputSection *sec : outputSections)
-    if (sec->type == SHT_REL || sec->type == SHT_RELA)
-      sec->writeTo<ELFT>(Out::bufferStart + sec->offset);
+  llvm::TimeTraceScope timeScope("Write sections");
 
-  for (OutputSection *sec : outputSections)
-    if (sec->type != SHT_REL && sec->type != SHT_RELA)
-      sec->writeTo<ELFT>(Out::bufferStart + sec->offset);
+  {
+    // In -r or --emit-relocs mode, write the relocation sections first as in
+    // ELf_Rel targets we might find out that we need to modify the relocated
+    // section while doing it.
+    parallel::TaskGroup tg;
+    for (OutputSection *sec : outputSections)
+      if (sec->type == SHT_REL || sec->type == SHT_RELA)
+        sec->writeTo<ELFT>(Out::bufferStart + sec->offset, tg);
+  }
+  {
+    parallel::TaskGroup tg;
+    for (OutputSection *sec : outputSections)
+      if (sec->type != SHT_REL && sec->type != SHT_RELA)
+        sec->writeTo<ELFT>(Out::bufferStart + sec->offset, tg);
+  }
 
   // Finally, check that all dynamic relocation addends were written correctly.
   if (config->checkDynamicRelocs && config->writeAddends) {
@@ -3052,15 +2954,16 @@ computeHash(llvm::MutableArrayRef<uint8_t> hashBuf,
             llvm::ArrayRef<uint8_t> data,
             std::function<void(uint8_t *dest, ArrayRef<uint8_t> arr)> hashFn) {
   std::vector<ArrayRef<uint8_t>> chunks = split(data, 1024 * 1024);
-  std::vector<uint8_t> hashes(chunks.size() * hashBuf.size());
+  const size_t hashesSize = chunks.size() * hashBuf.size();
+  std::unique_ptr<uint8_t[]> hashes(new uint8_t[hashesSize]);
 
   // Compute hash values.
-  parallelForEachN(0, chunks.size(), [&](size_t i) {
-    hashFn(hashes.data() + i * hashBuf.size(), chunks[i]);
+  parallelFor(0, chunks.size(), [&](size_t i) {
+    hashFn(hashes.get() + i * hashBuf.size(), chunks[i]);
   });
 
   // Write to the final output buffer.
-  hashFn(hashBuf.data(), hashes);
+  hashFn(hashBuf.data(), ArrayRef(hashes.get(), hashesSize));
 }
 
 template <class ELFT> void Writer<ELFT>::writeBuildId() {
@@ -3075,34 +2978,41 @@ template <class ELFT> void Writer<ELFT>::writeBuildId() {
 
   // Compute a hash of all sections of the output file.
   size_t hashSize = mainPart->buildId->hashSize;
-  std::vector<uint8_t> buildId(hashSize);
-  llvm::ArrayRef<uint8_t> buf{Out::bufferStart, size_t(fileSize)};
-
+  std::unique_ptr<uint8_t[]> buildId(new uint8_t[hashSize]);
+  MutableArrayRef<uint8_t> output(buildId.get(), hashSize);
+  llvm::ArrayRef<uint8_t> input{Out::bufferStart, size_t(fileSize)};
+
+  // Fedora introduced build ID as "approximation of true uniqueness across all
+  // binaries that might be used by overlapping sets of people". It does not
+  // need some security goals that some hash algorithms strive to provide, e.g.
+  // (second-)preimage and collision resistance. In practice people use 'md5'
+  // and 'sha1' just for different lengths. Implement them with the more
+  // efficient BLAKE3.
   switch (config->buildId) {
   case BuildIdKind::Fast:
-    computeHash(buildId, buf, [](uint8_t *dest, ArrayRef<uint8_t> arr) {
+    computeHash(output, input, [](uint8_t *dest, ArrayRef<uint8_t> arr) {
       write64le(dest, xxHash64(arr));
     });
     break;
   case BuildIdKind::Md5:
-    computeHash(buildId, buf, [&](uint8_t *dest, ArrayRef<uint8_t> arr) {
-      memcpy(dest, MD5::hash(arr).data(), hashSize);
+    computeHash(output, input, [&](uint8_t *dest, ArrayRef<uint8_t> arr) {
+      memcpy(dest, BLAKE3::hash<16>(arr).data(), hashSize);
     });
     break;
   case BuildIdKind::Sha1:
-    computeHash(buildId, buf, [&](uint8_t *dest, ArrayRef<uint8_t> arr) {
-      memcpy(dest, SHA1::hash(arr).data(), hashSize);
+    computeHash(output, input, [&](uint8_t *dest, ArrayRef<uint8_t> arr) {
+      memcpy(dest, BLAKE3::hash<20>(arr).data(), hashSize);
     });
     break;
   case BuildIdKind::Uuid:
-    if (auto ec = llvm::getRandomBytes(buildId.data(), hashSize))
+    if (auto ec = llvm::getRandomBytes(buildId.get(), hashSize))
       error("entropy source failure: " + ec.message());
     break;
   default:
     llvm_unreachable("unknown BuildIdKind");
   }
   for (Partition &part : partitions)
-    part.buildId->writeBuildId(buildId);
+    part.buildId->writeBuildId(output);
 }
 
 template void elf::createSyntheticSections<ELF32LE>();
index c2d96ad..0790f13 100644 (file)
 #define LLD_ELF_WRITER_H
 
 #include "Config.h"
-#include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include <cstdint>
-#include <memory>
 
-namespace lld {
-namespace elf {
+namespace lld::elf {
 class InputFile;
 class OutputSection;
-class InputSectionBase;
 void copySectionsIntoPartitions();
 template <class ELFT> void createSyntheticSections();
-void combineEhSections();
 template <class ELFT> void writeResult();
 
 // This describes a program header entry.
@@ -51,7 +46,6 @@ struct PhdrEntry {
 };
 
 void addReservedSymbols();
-llvm::StringRef getOutputSectionName(const InputSectionBase *s);
 
 template <class ELFT> uint32_t calcMipsEFlags();
 
@@ -61,7 +55,6 @@ uint8_t getMipsFpAbiFlag(uint8_t oldFlag, uint8_t newFlag,
 bool isMipsN32Abi(const InputFile *f);
 bool isMicroMips();
 bool isMipsR6();
-} // namespace elf
-} // namespace lld
+} // namespace lld::elf
 
 #endif
diff --git a/gnu/llvm/lld/docs/AtomLLD.rst b/gnu/llvm/lld/docs/AtomLLD.rst
deleted file mode 100644 (file)
index 2766094..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-ATOM-based lld
-==============
-
-Note: this document discuss Mach-O port of LLD. For ELF and COFF,
-see :doc:`index`.
-
-ATOM-based lld is a new set of modular code for creating linker tools.
-Currently it supports Mach-O.
-
-* End-User Features:
-
-  * Compatible with existing linker options
-  * Reads standard Object Files
-  * Writes standard Executable Files
-  * Remove clang's reliance on "the system linker"
-  * Uses the LLVM `"UIUC" BSD-Style license`__.
-
-* Applications:
-
-  * Modular design
-  * Support cross linking
-  * Easy to add new CPU support
-  * Can be built as static tool or library
-
-* Design and Implementation:
-
-  * Extensive unit tests
-  * Internal linker model can be dumped/read to textual format
-  * Additional linking features can be plugged in as "passes"
-  * OS specific and CPU specific code factored out
-
-Why a new linker?
------------------
-
-The fact that clang relies on whatever linker tool you happen to have installed
-means that clang has been very conservative adopting features which require a
-recent linker.
-
-In the same way that the MC layer of LLVM has removed clang's reliance on the
-system assembler tool, the lld project will remove clang's reliance on the
-system linker tool.
-
-
-Contents
---------
-
-.. toctree::
-   :maxdepth: 2
-
-   design
-   getting_started
-   development
-   open_projects
-   sphinx_intro
-
-Indices and tables
-------------------
-
-* :ref:`genindex`
-* :ref:`search`
-
-__ https://llvm.org/docs/DeveloperPolicy.html#license
diff --git a/gnu/llvm/lld/docs/Driver.rst b/gnu/llvm/lld/docs/Driver.rst
deleted file mode 100644 (file)
index 0ac86ff..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-======
-Driver
-======
-
-Note: this document discuss Mach-O port of LLD. For ELF and COFF,
-see :doc:`index`.
-
-.. contents::
-   :local:
-
-Introduction
-============
-
-This document describes the lld driver. The purpose of this document is to
-describe both the motivation and design goals for the driver, as well as details
-of the internal implementation.
-
-Overview
-========
-
-The lld driver is designed to support a number of different command line
-interfaces. The main interfaces we plan to support are binutils' ld, Apple's
-ld, and Microsoft's link.exe.
-
-Flavors
--------
-
-Each of these different interfaces is referred to as a flavor. There is also an
-extra flavor "core" which is used to exercise the core functionality of the
-linker it the test suite.
-
-* gnu
-* darwin
-* link
-* core
-
-Selecting a Flavor
-^^^^^^^^^^^^^^^^^^
-
-There are two different ways to tell lld which flavor to be. They are checked in
-order, so the second overrides the first. The first is to symlink :program:`lld`
-as :program:`lld-{flavor}` or just :program:`{flavor}`. You can also specify
-it as the first command line argument using ``-flavor``::
-
-  $ lld -flavor gnu
-
-There is a shortcut for ``-flavor core`` as ``-core``.
-
-
-Adding an Option to an existing Flavor
-======================================
-
-#. Add the option to the desired :file:`lib/Driver/{flavor}Options.td`.
-
-#. Add to :cpp:class:`lld::FlavorLinkingContext` a getter and setter method
-   for the option.
-
-#. Modify :cpp:func:`lld::FlavorDriver::parse` in :file:
-   `lib/Driver/{Flavor}Driver.cpp` to call the targetInfo setter
-   for the option.
-
-#. Modify {Flavor}Reader and {Flavor}Writer to use the new targetInfo option.
-
-
-Adding a Flavor
-===============
-
-#. Add an entry for the flavor in :file:`include/lld/Common/Driver.h` to
-   :cpp:class:`lld::UniversalDriver::Flavor`.
-
-#. Add an entry in :file:`lib/Driver/UniversalDriver.cpp` to
-   :cpp:func:`lld::Driver::strToFlavor` and
-   :cpp:func:`lld::UniversalDriver::link`.
-   This allows the flavor to be selected via symlink and `-flavor`.
-
-#. Add a tablegen file called :file:`lib/Driver/{flavor}Options.td` that
-   describes the options. If the options are a superset of another driver, that
-   driver's td file can simply be included. The :file:`{flavor}Options.td` file
-   must also be added to :file:`lib/Driver/CMakeLists.txt`.
-
-#. Add a ``{flavor}Driver`` as a subclass of :cpp:class:`lld::Driver`
-   in :file:`lib/Driver/{flavor}Driver.cpp`.
diff --git a/gnu/llvm/lld/docs/Readers.rst b/gnu/llvm/lld/docs/Readers.rst
deleted file mode 100644 (file)
index eae1717..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-.. _Readers:
-
-Developing lld Readers
-======================
-
-Note: this document discuss Mach-O port of LLD. For ELF and COFF,
-see :doc:`index`.
-
-Introduction
-------------
-
-The purpose of a "Reader" is to take an object file in a particular format
-and create an `lld::File`:cpp:class: (which is a graph of Atoms)
-representing the object file.  A Reader inherits from
-`lld::Reader`:cpp:class: which lives in
-:file:`include/lld/Core/Reader.h` and
-:file:`lib/Core/Reader.cpp`.
-
-The Reader infrastructure for an object format ``Foo`` requires the
-following pieces in order to fit into lld:
-
-:file:`include/lld/ReaderWriter/ReaderFoo.h`
-
-   .. cpp:class:: ReaderOptionsFoo : public ReaderOptions
-
-      This Options class is the only way to configure how the Reader will
-      parse any file into an `lld::Reader`:cpp:class: object.  This class
-      should be declared in the `lld`:cpp:class: namespace.
-
-   .. cpp:function:: Reader *createReaderFoo(ReaderOptionsFoo &reader)
-
-      This factory function configures and create the Reader. This function
-      should be declared in the `lld`:cpp:class: namespace.
-
-:file:`lib/ReaderWriter/Foo/ReaderFoo.cpp`
-
-   .. cpp:class:: ReaderFoo : public Reader
-
-      This is the concrete Reader class which can be called to parse
-      object files. It should be declared in an anonymous namespace or
-      if there is shared code with the `lld::WriterFoo`:cpp:class: you
-      can make a nested namespace (e.g. `lld::foo`:cpp:class:).
-
-You may have noticed that :cpp:class:`ReaderFoo` is not declared in the
-``.h`` file. An important design aspect of lld is that all Readers are
-created *only* through an object-format-specific
-:cpp:func:`createReaderFoo` factory function. The creation of the Reader is
-parametrized through a :cpp:class:`ReaderOptionsFoo` class. This options
-class is the one-and-only way to control how the Reader operates when
-parsing an input file into an Atom graph. For instance, you may want the
-Reader to only accept certain architectures. The options class can be
-instantiated from command line options or be programmatically configured.
-
-Where to start
---------------
-
-The lld project already has a skeleton of source code for Readers for
-``ELF``, ``PECOFF``, ``MachO``, and lld's native ``YAML`` graph format.
-If your file format is a variant of one of those, you should modify the
-existing Reader to support your variant. This is done by customizing the Options
-class for the Reader and making appropriate changes to the ``.cpp`` file to
-interpret those options and act accordingly.
-
-If your object file format is not a variant of any existing Reader, you'll need
-to create a new Reader subclass with the organization described above.
-
-Readers are factories
----------------------
-
-The linker will usually only instantiate your Reader once.  That one Reader will
-have its loadFile() method called many times with different input files.
-To support multithreaded linking, the Reader may be parsing multiple input
-files in parallel. Therefore, there should be no parsing state in you Reader
-object.  Any parsing state should be in ivars of your File subclass or in
-some temporary object.
-
-The key function to implement in a reader is::
-
-  virtual error_code loadFile(LinkerInput &input,
-                              std::vector<std::unique_ptr<File>> &result);
-
-It takes a memory buffer (which contains the contents of the object file
-being read) and returns an instantiated lld::File object which is
-a collection of Atoms. The result is a vector of File pointers (instead of
-simple a File pointer) because some file formats allow multiple object
-"files" to be encoded in one file system file.
-
-
-Memory Ownership
-----------------
-
-Atoms are always owned by their File object. During core linking when Atoms
-are coalesced or stripped away, core linking does not delete them.
-Core linking just removes those unused Atoms from its internal list.
-The destructor of a File object is responsible for deleting all Atoms it
-owns, and if ownership of the MemoryBuffer was passed to it, the File
-destructor needs to delete that too.
-
-Making Atoms
-------------
-
-The internal model of lld is purely Atom based.  But most object files do not
-have an explicit concept of Atoms, instead most have "sections". The way
-to think of this is that a section is just a list of Atoms with common
-attributes.
-
-The first step in parsing section-based object files is to cleave each
-section into a list of Atoms. The technique may vary by section type. For
-code sections (e.g. .text), there are usually symbols at the start of each
-function. Those symbol addresses are the points at which the section is
-cleaved into discrete Atoms.  Some file formats (like ELF) also include the
-length of each symbol in the symbol table. Otherwise, the length of each
-Atom is calculated to run to the start of the next symbol or the end of the
-section.
-
-Other sections types can be implicitly cleaved. For instance c-string literals
-or unwind info (e.g. .eh_frame) can be cleaved by having the Reader look at
-the content of the section.  It is important to cleave sections into Atoms
-to remove false dependencies. For instance the .eh_frame section often
-has no symbols, but contains "pointers" to the functions for which it
-has unwind info.  If the .eh_frame section was not cleaved (but left as one
-big Atom), there would always be a reference (from the eh_frame Atom) to
-each function.  So the linker would be unable to coalesce or dead stripped
-away the function atoms.
-
-The lld Atom model also requires that a reference to an undefined symbol be
-modeled as a Reference to an UndefinedAtom. So the Reader also needs to
-create an UndefinedAtom for each undefined symbol in the object file.
-
-Once all Atoms have been created, the second step is to create References
-(recall that Atoms are "nodes" and References are "edges"). Most References
-are created by looking at the "relocation records" in the object file. If
-a function contains a call to "malloc", there is usually a relocation record
-specifying the address in the section and the symbol table index. Your
-Reader will need to convert the address to an Atom and offset and the symbol
-table index into a target Atom. If "malloc" is not defined in the object file,
-the target Atom of the Reference will be an UndefinedAtom.
-
-
-Performance
------------
-Once you have the above working to parse an object file into Atoms and
-References, you'll want to look at performance.  Some techniques that can
-help performance are:
-
-* Use llvm::BumpPtrAllocator or pre-allocate one big vector<Reference> and then
-  just have each atom point to its subrange of References in that vector.
-  This can be faster that allocating each Reference as separate object.
-* Pre-scan the symbol table and determine how many atoms are in each section
-  then allocate space for all the Atom objects at once.
-* Don't copy symbol names or section content to each Atom, instead use
-  StringRef and ArrayRef in each Atom to point to its name and content in the
-  MemoryBuffer.
-
-
-Testing
--------
-
-We are still working on infrastructure to test Readers. The issue is that
-you don't want to check in binary files to the test suite. And the tools
-for creating your object file from assembly source may not be available on
-every OS.
-
-We are investigating a way to use YAML to describe the section, symbols,
-and content of a file. Then have some code which will write out an object
-file from that YAML description.
-
-Once that is in place, you can write test cases that contain section/symbols
-YAML and is run through the linker to produce Atom/References based YAML which
-is then run through FileCheck to verify the Atoms and References are as
-expected.
-
-
-
diff --git a/gnu/llvm/lld/docs/design.rst b/gnu/llvm/lld/docs/design.rst
deleted file mode 100644 (file)
index 20d8fe7..0000000
+++ /dev/null
@@ -1,421 +0,0 @@
-.. _design:
-
-Linker Design
-=============
-
-Note: this document discuss Mach-O port of LLD. For ELF and COFF,
-see :doc:`index`.
-
-Introduction
-------------
-
-lld is a new generation of linker.  It is not "section" based like traditional
-linkers which mostly just interlace sections from multiple object files into the
-output file.  Instead, lld is based on "Atoms".  Traditional section based
-linking work well for simple linking, but their model makes advanced linking
-features difficult to implement.  Features like dead code stripping, reordering
-functions for locality, and C++ coalescing require the linker to work at a finer
-grain.
-
-An atom is an indivisible chunk of code or data.  An atom has a set of
-attributes, such as: name, scope, content-type, alignment, etc.  An atom also
-has a list of References.  A Reference contains: a kind, an optional offset, an
-optional addend, and an optional target atom.
-
-The Atom model allows the linker to use standard graph theory models for linking
-data structures.  Each atom is a node, and each Reference is an edge.  The
-feature of dead code stripping is implemented by following edges to mark all
-live atoms, and then delete the non-live atoms.
-
-
-Atom Model
-----------
-
-An atom is an indivisible chunk of code or data.  Typically each user written
-function or global variable is an atom.  In addition, the compiler may emit
-other atoms, such as for literal c-strings or floating point constants, or for
-runtime data structures like dwarf unwind info or pointers to initializers.
-
-A simple "hello world" object file would be modeled like this:
-
-.. image:: hello.png
-
-There are three atoms: main, a proxy for printf, and an anonymous atom
-containing the c-string literal "hello world".  The Atom "main" has two
-references. One is the call site for the call to printf, and the other is a
-reference for the instruction that loads the address of the c-string literal.
-
-There are only four different types of atoms:
-
-       * DefinedAtom
-               95% of all atoms.  This is a chunk of code or data
-
-       * UndefinedAtom
-          This is a place holder in object files for a reference to some atom
-          outside the translation unit.During core linking it is usually replaced
-          by (coalesced into) another Atom.
-
-       * SharedLibraryAtom
-               If a required symbol name turns out to be defined in a dynamic shared
-               library (and not some object file).  A SharedLibraryAtom is the
-               placeholder Atom used to represent that fact.
-
-               It is similar to an UndefinedAtom, but it also tracks information
-               about the associated shared library.
-
-       * AbsoluteAtom
-               This is for embedded support where some stuff is implemented in ROM at
-               some fixed address.  This atom has no content.  It is just an address
-               that the Writer needs to fix up any references to point to.
-
-
-File Model
-----------
-
-The linker views the input files as basically containers of Atoms and
-References, and just a few attributes of their own.  The linker works with three
-kinds of files: object files, static libraries, and dynamic shared libraries.
-Each kind of file has reader object which presents the file in the model
-expected by the linker.
-
-Object File
-~~~~~~~~~~~
-
-An object file is just a container of atoms.  When linking an object file, a
-reader is instantiated which parses the object file and instantiates a set of
-atoms representing all content in the .o file.  The linker adds all those atoms
-to a master graph.
-
-Static Library (Archive)
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-This is the traditional unix static archive which is just a collection of object
-files with a "table of contents". When linking with a static library, by default
-nothing is added to the master graph of atoms. Instead, if after merging all
-atoms from object files into a master graph, if any "undefined" atoms are left
-remaining in the master graph, the linker reads the table of contents for each
-static library to see if any have the needed definitions. If so, the set of
-atoms from the specified object file in the static library is added to the
-master graph of atoms.
-
-Dynamic Library (Shared Object)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Dynamic libraries are different than object files and static libraries in that
-they don't directly add any content.  Their purpose is to check at build time
-that the remaining undefined references can be resolved at runtime, and provide
-a list of dynamic libraries (SO_NEEDED) that will be needed at runtime.  The way
-this is modeled in the linker is that a dynamic library contributes no atoms to
-the initial graph of atoms.  Instead, (like static libraries) if there are
-"undefined" atoms in the master graph of all atoms, then each dynamic library is
-checked to see if exports the required symbol. If so, a "shared library" atom is
-instantiated by the by the reader which the linker uses to replace the
-"undefined" atom.
-
-Linking Steps
--------------
-
-Through the use of abstract Atoms, the core of linking is architecture
-independent and file format independent.  All command line parsing is factored
-out into a separate "options" abstraction which enables the linker to be driven
-with different command line sets.
-
-The overall steps in linking are:
-
-  #. Command line processing
-
-  #. Parsing input files
-
-  #. Resolving
-
-  #. Passes/Optimizations
-
-  #. Generate output file
-
-The Resolving and Passes steps are done purely on the master graph of atoms, so
-they have no notion of file formats such as mach-o or ELF.
-
-
-Input Files
-~~~~~~~~~~~
-
-Existing developer tools using different file formats for object files.
-A goal of lld is to be file format independent.  This is done
-through a plug-in model for reading object files. The lld::Reader is the base
-class for all object file readers.  A Reader follows the factory method pattern.
-A Reader instantiates an lld::File object (which is a graph of Atoms) from a
-given object file (on disk or in-memory).
-
-Every Reader subclass defines its own "options" class (for instance the mach-o
-Reader defines the class ReaderOptionsMachO).  This options class is the
-one-and-only way to control how the Reader operates when parsing an input file
-into an Atom graph.  For instance, you may want the Reader to only accept
-certain architectures.  The options class can be instantiated from command
-line options, or it can be subclassed and the ivars programmatically set.
-
-Resolving
-~~~~~~~~~
-
-The resolving step takes all the atoms' graphs from each object file and
-combines them into one master object graph.  Unfortunately, it is not as simple
-as appending the atom list from each file into one big list.  There are many
-cases where atoms need to be coalesced.  That is, two or more atoms need to be
-coalesced into one atom.  This is necessary to support: C language "tentative
-definitions", C++ weak symbols for templates and inlines defined in headers,
-replacing undefined atoms with actual definition atoms, and for merging copies
-of constants like c-strings and floating point constants.
-
-The linker support coalescing by-name and by-content. By-name is used for
-tentative definitions and weak symbols.  By-content is used for constant data
-that can be merged.
-
-The resolving process maintains some global linking "state", including a "symbol
-table" which is a map from llvm::StringRef to lld::Atom*.  With these data
-structures, the linker iterates all atoms in all input files. For each atom, it
-checks if the atom is named and has a global or hidden scope.  If so, the atom
-is added to the symbol table map.  If there already is a matching atom in that
-table, that means the current atom needs to be coalesced with the found atom, or
-it is a multiple definition error.
-
-When all initial input file atoms have been processed by the resolver, a scan is
-made to see if there are any undefined atoms in the graph.  If there are, the
-linker scans all libraries (both static and dynamic) looking for definitions to
-replace the undefined atoms.  It is an error if any undefined atoms are left
-remaining.
-
-Dead code stripping (if requested) is done at the end of resolving.  The linker
-does a simple mark-and-sweep. It starts with "root" atoms (like "main" in a main
-executable) and follows each references and marks each Atom that it visits as
-"live".  When done, all atoms not marked "live" are removed.
-
-The result of the Resolving phase is the creation of an lld::File object.  The
-goal is that the lld::File model is **the** internal representation
-throughout the linker. The file readers parse (mach-o, ELF, COFF) into an
-lld::File.  The file writers (mach-o, ELF, COFF) taken an lld::File and produce
-their file kind, and every Pass only operates on an lld::File.  This is not only
-a simpler, consistent model, but it enables the state of the linker to be dumped
-at any point in the link for testing purposes.
-
-
-Passes
-~~~~~~
-
-The Passes step is an open ended set of routines that each get a change to
-modify or enhance the current lld::File object. Some example Passes are:
-
-  * stub (PLT) generation
-
-  * GOT instantiation
-
-  * order_file optimization
-
-  * branch island generation
-
-  * branch shim generation
-
-  * Objective-C optimizations (Darwin specific)
-
-  * TLV instantiation (Darwin specific)
-
-  * DTrace probe processing (Darwin specific)
-
-  * compact unwind encoding (Darwin specific)
-
-
-Some of these passes are specific to Darwin's runtime environments.  But many of
-the passes are applicable to any OS (such as generating branch island for out of
-range branch instructions).
-
-The general structure of a pass is to iterate through the atoms in the current
-lld::File object, inspecting each atom and doing something.  For instance, the
-stub pass, looks for call sites to shared library atoms (e.g. call to printf).
-It then instantiates a "stub" atom (PLT entry) and a "lazy pointer" atom for
-each proxy atom needed, and these new atoms are added to the current lld::File
-object.  Next, all the noted call sites to shared library atoms have their
-References altered to point to the stub atom instead of the shared library atom.
-
-
-Generate Output File
-~~~~~~~~~~~~~~~~~~~~
-
-Once the passes are done, the output file writer is given current lld::File
-object.  The writer's job is to create the executable content file wrapper and
-place the content of the atoms into it.
-
-lld uses a plug-in model for writing output files. All concrete writers (e.g.
-ELF, mach-o, etc) are subclasses of the lld::Writer class.
-
-Unlike the Reader class which has just one method to instantiate an lld::File,
-the Writer class has multiple methods.  The crucial method is to generate the
-output file, but there are also methods which allow the Writer to contribute
-Atoms to the resolver and specify passes to run.
-
-An example of contributing
-atoms is that if the Writer knows a main executable is being linked and such
-an executable requires a specially named entry point (e.g. "_main"), the Writer
-can add an UndefinedAtom with that special name to the resolver.  This will
-cause the resolver to issue an error if that symbol is not defined.
-
-Sometimes a Writer supports lazily created symbols, such as names for the start
-of sections. To support this, the Writer can create a File object which vends
-no initial atoms, but does lazily supply atoms by name as needed.
-
-Every Writer subclass defines its own "options" class (for instance the mach-o
-Writer defines the class WriterOptionsMachO).  This options class is the
-one-and-only way to control how the Writer operates when producing an output
-file from an Atom graph.  For instance, you may want the Writer to optimize
-the output for certain OS versions, or strip local symbols, etc. The options
-class can be instantiated from command line options, or it can be subclassed
-and the ivars programmatically set.
-
-
-lld::File representations
--------------------------
-
-Just as LLVM has three representations of its IR model, lld has two
-representations of its File/Atom/Reference model:
-
- * In memory, abstract C++ classes (lld::Atom, lld::Reference, and lld::File).
-
- * textual (in YAML)
-
-
-Textual representations in YAML
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-In designing a textual format we want something easy for humans to read and easy
-for the linker to parse.  Since an atom has lots of attributes most of which are
-usually just the default, we should define default values for every attribute so
-that those can be omitted from the text representation.  Here is the atoms for a
-simple hello world program expressed in YAML::
-
-  target-triple:   x86_64-apple-darwin11
-
-  atoms:
-      - name:    _main
-        scope:   global
-        type:    code
-        content: [ 55, 48, 89, e5, 48, 8d, 3d, 00, 00, 00, 00, 30, c0, e8, 00, 00,
-                   00, 00, 31, c0, 5d, c3 ]
-        fixups:
-        - offset: 07
-          kind:   pcrel32
-          target: 2
-        - offset: 0E
-          kind:   call32
-          target: _fprintf
-
-      - type:    c-string
-        content: [ 73, 5A, 00 ]
-
-  ...
-
-The biggest use for the textual format will be writing test cases.  Writing test
-cases in C is problematic because the compiler may vary its output over time for
-its own optimization reasons which my inadvertently disable or break the linker
-feature trying to be tested. By writing test cases in the linkers own textual
-format, we can exactly specify every attribute of every atom and thus target
-specific linker logic.
-
-The textual/YAML format follows the ReaderWriter patterns used in lld. The lld
-library comes with the classes: ReaderYAML and WriterYAML.
-
-
-Testing
--------
-
-The lld project contains a test suite which is being built up as new code is
-added to lld.  All new lld functionality should have a tests added to the test
-suite.  The test suite is `lit <https://llvm.org/cmds/lit.html/>`_ driven.  Each
-test is a text file with comments telling lit how to run the test and check the
-result To facilitate testing, the lld project builds a tool called lld-core.
-This tool reads a YAML file (default from stdin), parses it into one or more
-lld::File objects in memory and then feeds those lld::File objects to the
-resolver phase.
-
-
-Resolver testing
-~~~~~~~~~~~~~~~~
-
-Basic testing is the "core linking" or resolving phase.  That is where the
-linker merges object files.  All test cases are written in YAML.  One feature of
-YAML is that it allows multiple "documents" to be encoding in one YAML stream.
-That means one text file can appear to the linker as multiple .o files - the
-normal case for the linker.
-
-Here is a simple example of a core linking test case. It checks that an
-undefined atom from one file will be replaced by a definition from another
-file::
-
-  # RUN: lld-core %s | FileCheck %s
-
-  #
-  # Test that undefined atoms are replaced with defined atoms.
-  #
-
-  ---
-  atoms:
-      - name:              foo
-        definition:        undefined
-  ---
-  atoms:
-      - name:              foo
-        scope:             global
-        type:              code
-  ...
-
-  # CHECK:       name:       foo
-  # CHECK:       scope:      global
-  # CHECK:       type:       code
-  # CHECK-NOT:   name:       foo
-  # CHECK:       ...
-
-
-Passes testing
-~~~~~~~~~~~~~~
-
-Since Passes just operate on an lld::File object, the lld-core tool has the
-option to run a particular pass (after resolving).  Thus, you can write a YAML
-test case with carefully crafted input to exercise areas of a Pass and the check
-the resulting lld::File object as represented in YAML.
-
-
-Design Issues
--------------
-
-There are a number of open issues in the design of lld.  The plan is to wait and
-make these design decisions when we need to.
-
-
-Debug Info
-~~~~~~~~~~
-
-Currently, the lld model says nothing about debug info.  But the most popular
-debug format is DWARF and there is some impedance mismatch with the lld model
-and DWARF.  In lld there are just Atoms and only Atoms that need to be in a
-special section at runtime have an associated section.  Also, Atoms do not have
-addresses.  The way DWARF is spec'ed different parts of DWARF are supposed to go
-into specially named sections and the DWARF references function code by address.
-
-CPU and OS specific functionality
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Currently, lld has an abstract "Platform" that deals with any CPU or OS specific
-differences in linking.  We just keep adding virtual methods to the base
-Platform class as we find linking areas that might need customization.  At some
-point we'll need to structure this better.
-
-
-File Attributes
-~~~~~~~~~~~~~~~
-
-Currently, lld::File just has a path and a way to iterate its atoms. We will
-need to add more attributes on a File.  For example, some equivalent to the
-target triple.  There is also a number of cached or computed attributes that
-could make various Passes more efficient.  For instance, on Darwin there are a
-number of Objective-C optimizations that can be done by a Pass.  But it would
-improve the plain C case if the Objective-C optimization Pass did not have to
-scan all atoms looking for any Objective-C data structures.  This could be done
-if the lld::File object had an attribute that said if the file had any
-Objective-C data in it. The Resolving phase would then be required to "merge"
-that attribute as object files are added.
diff --git a/gnu/llvm/lld/docs/development.rst b/gnu/llvm/lld/docs/development.rst
deleted file mode 100644 (file)
index 81b826f..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-.. _development:
-
-Development
-===========
-
-Note: this document discuss Mach-O port of LLD. For ELF and COFF,
-see :doc:`index`.
-
-lld is developed as part of the `LLVM <https://llvm.org>`_ project.
-
-Creating a Reader
------------------
-
-See the :ref:`Creating a Reader <Readers>` guide.
-
-
-Modifying the Driver
---------------------
-
-See :doc:`Driver`.
-
-
-Debugging
----------
-
-You can run lld with ``-mllvm -debug`` command line options to enable debugging
-printouts. If you want to enable debug information for some specific pass, you
-can run it with ``-mllvm '-debug-only=<pass>'``, where pass is a name used in
-the ``DEBUG_WITH_TYPE()`` macro.
-
-
-
-Documentation
--------------
-
-The project documentation is written in reStructuredText and generated using the
-`Sphinx <http://sphinx.pocoo.org/>`_ documentation generator. For more
-information on writing documentation for the project, see the
-:ref:`sphinx_intro`.
-
-.. toctree::
-   :hidden:
-
-   Readers
-   Driver
diff --git a/gnu/llvm/lld/docs/getting_started.rst b/gnu/llvm/lld/docs/getting_started.rst
deleted file mode 100644 (file)
index 506cb24..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-.. _getting_started:
-
-Getting Started: Building and Running lld
-=========================================
-
-This page gives you the shortest path to checking out and building lld. If you
-run into problems, please file bugs in the `LLVM Bugzilla`__
-
-__ https://bugs.llvm.org/
-
-Building lld
-------------
-
-On Unix-like Systems
-~~~~~~~~~~~~~~~~~~~~
-
-1. Get the required tools.
-
-  * `CMake 2.8`_\+.
-  * make (or any build system CMake supports).
-  * `Clang 3.1`_\+ or GCC 4.7+ (C++11 support is required).
-
-    * If using Clang, you will also need `libc++`_.
-  * `Python 2.4`_\+ (not 3.x) for running tests.
-
-.. _CMake 2.8: http://www.cmake.org/cmake/resources/software.html
-.. _Clang 3.1: http://clang.llvm.org/
-.. _libc++: http://libcxx.llvm.org/
-.. _Python 2.4: http://python.org/download/
-
-2. Check out LLVM and subprojects (including lld)::
-
-     $ git clone https://github.com/llvm/llvm-project.git
-
-4. Build LLVM and lld::
-
-     $ cd llvm-project
-     $ mkdir build && cd build
-     $ cmake -G "Unix Makefiles" -DLLVM_ENABLE_PROJECTS=lld ../llvm
-     $ make
-
-  * If you want to build with clang and it is not the default compiler or
-    it is installed in an alternate location, you'll need to tell the cmake tool
-    the location of the C and C++ compiler via CMAKE_C_COMPILER and
-    CMAKE_CXX_COMPILER. For example::
-
-        $ cmake -DCMAKE_CXX_COMPILER=/path/to/clang++ -DCMAKE_C_COMPILER=/path/to/clang ...
-
-5. Test::
-
-     $ make check-lld
-
-Using Visual Studio
-~~~~~~~~~~~~~~~~~~~
-
-#. Get the required tools.
-
-  * `CMake 2.8`_\+.
-  * `Visual Studio 12 (2013) or later`_ (required for C++11 support)
-  * `Python 2.4`_\+ (not 3.x) for running tests.
-
-.. _CMake 2.8: http://www.cmake.org/cmake/resources/software.html
-.. _Visual Studio 12 (2013) or later: http://www.microsoft.com/visualstudio/11/en-us
-.. _Python 2.4: http://python.org/download/
-
-#. Check out LLVM as above.
-
-#. Generate Visual Studio project files::
-
-     $ cd llvm-project/build (out of source build required)
-     $ cmake -G "Visual Studio 11" -DLLVM_ENABLE_PROJECTS=lld ../llvm
-
-#. Build
-
-  * Open LLVM.sln in Visual Studio.
-  * Build the ``ALL_BUILD`` target.
-
-#. Test
-
-  * Build the ``lld-test`` target.
-
-More Information
-~~~~~~~~~~~~~~~~
-
-For more information on using CMake see the `LLVM CMake guide`_.
-
-.. _LLVM CMake guide: https://llvm.org/docs/CMake.html
index 51acf14..b4b2327 100644 (file)
@@ -130,20 +130,26 @@ Alias for
 .Fl -color-diagnostics Ns = Ns Cm auto .
 .It Fl -compress-debug-sections Ns = Ns Ar value
 Compress DWARF debug sections.
-.Ar value
+.Cm value
 may be
-.Cm none
-or
-.Cm zlib .
+.Pp
+.Bl -tag -width 2n -compact
+.It Cm none
+No compression.
+.It Cm zlib
 The default compression level is 1 (fastest) as the debug info usually
-compresses well at that level, but if you want to compress it more,
+compresses well at that level. If you want to compress it more,
 you can specify
 .Fl O2
 to set the compression level to 6.
+.It Cm zstd
+The compression level is 5.
+.El
+.Pp
 .It Fl -cref
-Output cross reference table.
-.It Fl -define-common , Fl d
-Assign space to common symbols.
+Output cross reference table. If
+.Fl Map
+is specified, print to the map file.
 .It Fl -defsym Ns = Ns Ar symbol Ns = Ns Ar expression
 Define a symbol alias.
 .Ar expression
@@ -167,10 +173,9 @@ Specify the dynamic linker to be used for a dynamically linked executable.
 This is recorded in an ELF segment of type
 .Dv PT_INTERP .
 .It Fl -dynamic-list Ns = Ns Ar file
-Read a list of dynamic symbols from
-.Ar file .
-(executable) Put matched non-local defined symbols to the dynamic symbol table.
-(shared object) References to matched non-local STV_DEFAULT symbols shouldn't be bound to definitions within the shared object. Implies
+Similar to
+.Cm --export-dynamic-symbol-list .
+When creating a shared object, implies
 .Cm -Bsymbolic
 but does not set DF_SYMBOLIC
 .It Fl -EB
@@ -227,6 +232,12 @@ Put symbols in the dynamic symbol table.
 .Cm -Bsymbolic-functions
 or
 .Cm --dynamic-list
+.It Fl -export-dynamic-symbol-list Ns = Ns Ar file
+Read a list of dynamic symbol patterns from
+.Ar file .
+Apply
+.Cm --export-dynamic-symbol
+on each pattern.
 .It Fl -fatal-warnings
 Treat warnings as errors.
 .It Fl -filter Ns = Ns Ar value , Fl F Ar value
@@ -321,8 +332,6 @@ Always set
 for shared libraries.
 .It Fl -no-color-diagnostics
 Do not use colors in diagnostics.
-.It Fl -no-define-common
-Do not assign space to common symbols.
 .It Fl -no-demangle
 Do not demangle symbol names.
 .It Fl -no-dynamic-linker
@@ -342,15 +351,18 @@ Page align sections.
 .It Fl -no-omagic
 Do not set the text data sections to be writable, page align sections.
 .It Fl -no-relax
-Disable target-specific relaxations. This is currently a no-op.
+Disable target-specific relaxations. For x86-64 this disables R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX GOT optimization.
 .It Fl -no-rosegment
 Do not put read-only non-executable sections in their own segment.
-.It Fl -no-undefined-version
-Report version scripts that refer undefined symbols.
+.It Fl -undefined-version
+Do not report version scripts that refer to undefined symbols.
 .It Fl -no-undefined
 Report unresolved symbols even if the linker is creating a shared library.
 .It Fl -no-warn-symbol-ordering
 Do not warn about problems with the symbol ordering file or call graph profile.
+.It Fl -no-warnings , Fl w
+Suppress warnings and cancel
+.Cm --fatal-warnings.
 .It Fl -no-whole-archive
 Restores the default behavior of loading archive members.
 .It Fl -no-pie , Fl -no-pic-executable
@@ -451,6 +463,20 @@ is specified, use SHT_ANDROID_RELR instead of SHT_RELR.
 Always generate position independent thunks.
 .It Fl -pie , Fl -pic-executable
 Create a position independent executable.
+.It Fl -power10-stubs Ns = Ns Cm mode
+Whether to use Power10 instructions in call stubs for R_PPC64_REL24_NOTOC and TOC/NOTOC interworking.
+.Ar mode
+may be:
+.Pp
+.Bl -tag -width 2n -compact
+.It Cm yes
+(default) Use.
+.It Cm auto
+Currently the same as yes.
+.It Cm no
+Don't use.
+.El
+
 .It Fl -print-gc-sections
 List removed unused sections.
 .It Fl -print-icf-sections
@@ -467,7 +493,7 @@ Save the current state of
 and
 .Fl -whole-archive.
 .It Fl -pop-state
-Undo the effect of
+Restore the states saved by
 .Fl -push-state.
 .It Fl -relocatable , Fl r
 Create relocatable object file.
@@ -616,10 +642,10 @@ Creates a separate output section for every orphan input section.
 Determine how to handle unresolved symbols.
 .It Fl -use-android-relr-tags
 Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*.
-.It Fl v
+.It Fl v , Fl V
 Display the version number and proceed with linking if object files are
 specified.
-.It Fl V , Fl -version
+.It Fl -version
 Display the version number and exit.
 .It Fl -verbose
 Verbose mode.
@@ -655,6 +681,8 @@ linkers, and may be removed in the future.
 Report unresolved symbols as warnings.
 .It Fl -whole-archive
 Force load of all members in a static library.
+.It Fl -why-extract Ns = Ns Ar file
+Print to a file about why archive members are extracted.
 .It Fl -wrap Ns = Ns Ar symbol
 Redirect
 .Ar symbol
@@ -681,6 +709,16 @@ Stack permissions are recorded in the
 .Dv PT_GNU_STACK
 segment.
 .Pp
+.It Cm bti-report Ns = Ns Ar [none|warning|error]
+Specify how to report the missing GNU_PROPERTY_AARCH64_FEATURE_1_BTI property.
+.Cm none
+is the default, linker will not report the missing property otherwise will be reported as a warning or an error.
+.Pp
+.It Cm cet-report Ns = Ns Ar [none|warning|error]
+Specify how to report the missing GNU_PROPERTY_X86_FEATURE_1_IBT or GNU_PROPERTY_X86_FEATURE_1_SHSTK properties.
+.Cm none
+is the default, linker will not report the missing property otherwise will be reported as a warning or an error.
+.Pp
 .It Cm force-bti
 Force enable AArch64 BTI instruction in PLT, warn if Input ELF file does not have GNU_PROPERTY_AARCH64_FEATURE_1_BTI property.
 .Pp
@@ -780,6 +818,12 @@ processing.
 .It Cm pac-plt
 AArch64 only, use pointer authentication in PLT.
 .Pp
+.It Cm pack-relative-relocs
+Similar to
+.Cm -pack-dyn-relocs=relr
+, but synthesizes the GLIBC_ABI_DT_RELR version dependency if there is a GLIBC_2.* version dependency.
+glibc ld.so rejects loading a dynamically linked object without the GLIBC_ABI_DT_RELR version dependency.
+.Pp
 .It Cm rel
 Use REL format for dynamic relocations.
 .Pp
diff --git a/gnu/llvm/lld/docs/open_projects.rst b/gnu/llvm/lld/docs/open_projects.rst
deleted file mode 100644 (file)
index 36edca4..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-.. _open_projects:
-
-Open Projects
-=============
-
-Documentation TODOs
-~~~~~~~~~~~~~~~~~~~
-
-.. todolist::
diff --git a/gnu/llvm/lld/docs/sphinx_intro.rst b/gnu/llvm/lld/docs/sphinx_intro.rst
deleted file mode 100644 (file)
index b671cdc..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-.. _sphinx_intro:
-
-Sphinx Introduction for LLVM Developers
-=======================================
-
-This document is intended as a short and simple introduction to the Sphinx
-documentation generation system for LLVM developers.
-
-Quickstart
-----------
-
-To get started writing documentation, you will need to:
-
- 1. Have the Sphinx tools :ref:`installed <installing_sphinx>`.
-
- 2. Understand how to :ref:`build the documentation
-    <building_the_documentation>`.
-
- 3. Start :ref:`writing documentation <writing_documentation>`!
-
-.. _installing_sphinx:
-
-Installing Sphinx
-~~~~~~~~~~~~~~~~~
-
-You should be able to install Sphinx using the standard Python package
-installation tool ``easy_install``, as follows::
-
-  $ sudo easy_install sphinx
-  Searching for sphinx
-  Reading http://pypi.python.org/simple/sphinx/
-  Reading http://sphinx.pocoo.org/
-  Best match: Sphinx 1.1.3
-  ... more lines here ..
-
-If you do not have root access (or otherwise want to avoid installing Sphinx in
-system directories) see the section on :ref:`installing_sphinx_in_a_venv` .
-
-If you do not have the ``easy_install`` tool on your system, you should be able
-to install it using:
-
-  Linux
-    Use your distribution's standard package management tool to install it,
-    i.e., ``apt-get install easy_install`` or ``yum install easy_install``.
-
-  macOS
-    All modern macOS systems come with ``easy_install`` as part of the base
-    system.
-
-  Windows
-    See the `setuptools <http://pypi.python.org/pypi/setuptools>`_ package web
-    page for instructions.
-
-
-.. _building_the_documentation:
-
-Building the documentation
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-In order to build the documentation need to add ``-DLLVM_ENABLE_SPHINX=ON`` to
-your ``cmake`` command.  Once you do this you can build the docs using
-``docs-lld-html`` build (``ninja`` or ``make``) target.
-
-That build target will invoke ``sphinx-build`` with the appropriate options for
-the project, and generate the HTML documentation in a ``tools/lld/docs/html``
-subdirectory.
-
-.. _writing_documentation:
-
-Writing documentation
-~~~~~~~~~~~~~~~~~~~~~
-
-The documentation itself is written in the reStructuredText (ReST) format, and
-Sphinx defines additional tags to support features like cross-referencing.
-
-The ReST format itself is organized around documents mostly being readable
-plaintext documents. You should generally be able to write new documentation
-easily just by following the style of the existing documentation.
-
-If you want to understand the formatting of the documents more, the best place
-to start is Sphinx's own `ReST Primer <http://sphinx.pocoo.org/rest.html>`_.
-
-
-Learning More
--------------
-
-If you want to learn more about the Sphinx system, the best place to start is
-the Sphinx documentation itself, available `here
-<http://sphinx.pocoo.org/contents.html>`_.
-
-
-.. _installing_sphinx_in_a_venv:
-
-Installing Sphinx in a Virtual Environment
-------------------------------------------
-
-Most Python developers prefer to work with tools inside a *virtualenv* (virtual
-environment) instance, which functions as an application sandbox. This avoids
-polluting your system installation with different packages used by various
-projects (and ensures that dependencies for different packages don't conflict
-with one another). Of course, you need to first have the virtualenv software
-itself which generally would be installed at the system level::
-
-  $ sudo easy_install virtualenv
-
-but after that you no longer need to install additional packages in the system
-directories.
-
-Once you have the *virtualenv* tool itself installed, you can create a
-virtualenv for Sphinx using::
-
-  $ virtualenv ~/my-sphinx-install
-  New python executable in /Users/dummy/my-sphinx-install/bin/python
-  Installing setuptools............done.
-  Installing pip...............done.
-
-  $ ~/my-sphinx-install/bin/easy_install sphinx
-  ... install messages here ...
-
-and from now on you can "activate" the *virtualenv* using::
-
-  $ source ~/my-sphinx-install/bin/activate
-
-which will change your PATH to ensure the sphinx-build tool from inside the
-virtual environment will be used. See the `virtualenv website
-<http://www.virtualenv.org/en/latest/index.html>`_ for more information on using
-virtual environments.
diff --git a/gnu/llvm/lld/include/lld/Core/AbsoluteAtom.h b/gnu/llvm/lld/include/lld/Core/AbsoluteAtom.h
deleted file mode 100644 (file)
index 5214b41..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-//===- Core/AbsoluteAtom.h - An absolute Atom -----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_ABSOLUTE_ATOM_H
-#define LLD_CORE_ABSOLUTE_ATOM_H
-
-#include "lld/Core/Atom.h"
-
-namespace lld {
-
-/// An AbsoluteAtom has no content.
-/// It exists to represent content at fixed addresses in memory.
-class AbsoluteAtom : public Atom {
-public:
-
-  virtual uint64_t value() const = 0;
-
-  /// scope - The visibility of this atom to other atoms.  C static functions
-  /// have scope scopeTranslationUnit.  Regular C functions have scope
-  /// scopeGlobal.  Functions compiled with visibility=hidden have scope
-  /// scopeLinkageUnit so they can be see by other atoms being linked but not
-  /// by the OS loader.
-  virtual Scope scope() const = 0;
-
-  static bool classof(const Atom *a) {
-    return a->definition() == definitionAbsolute;
-  }
-
-  static bool classof(const AbsoluteAtom *) { return true; }
-
-protected:
-  AbsoluteAtom() : Atom(definitionAbsolute) {}
-};
-
-} // namespace lld
-
-#endif // LLD_CORE_ABSOLUTE_ATOM_H
diff --git a/gnu/llvm/lld/include/lld/Core/ArchiveLibraryFile.h b/gnu/llvm/lld/include/lld/Core/ArchiveLibraryFile.h
deleted file mode 100644 (file)
index 0abef40..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-//===- Core/ArchiveLibraryFile.h - Models static library ------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_ARCHIVE_LIBRARY_FILE_H
-#define LLD_CORE_ARCHIVE_LIBRARY_FILE_H
-
-#include "lld/Core/File.h"
-#include <set>
-
-namespace lld {
-
-///
-/// The ArchiveLibraryFile subclass of File is used to represent unix
-/// static library archives.  These libraries provide no atoms to the
-/// initial set of atoms linked.  Instead, when the Resolver will query
-/// ArchiveLibraryFile instances for specific symbols names using the
-/// find() method.  If the archive contains an object file which has a
-/// DefinedAtom whose scope is not translationUnit, then that entire
-/// object file File is returned.
-///
-class ArchiveLibraryFile : public File {
-public:
-  static bool classof(const File *f) {
-    return f->kind() == kindArchiveLibrary;
-  }
-
-  /// Check if any member of the archive contains an Atom with the
-  /// specified name and return the File object for that member, or nullptr.
-  virtual File *find(StringRef name) = 0;
-
-  virtual std::error_code
-  parseAllMembers(std::vector<std::unique_ptr<File>> &result) = 0;
-
-protected:
-  /// only subclasses of ArchiveLibraryFile can be instantiated
-  ArchiveLibraryFile(StringRef path) : File(path, kindArchiveLibrary) {}
-};
-
-} // namespace lld
-
-#endif // LLD_CORE_ARCHIVE_LIBRARY_FILE_H
diff --git a/gnu/llvm/lld/include/lld/Core/Atom.h b/gnu/llvm/lld/include/lld/Core/Atom.h
deleted file mode 100644 (file)
index d89792d..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-//===- Core/Atom.h - A node in linking graph --------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_ATOM_H
-#define LLD_CORE_ATOM_H
-
-#include "lld/Common/LLVM.h"
-#include "llvm/ADT/StringRef.h"
-
-namespace lld {
-
-class File;
-
-template<typename T>
-class OwningAtomPtr;
-
-///
-/// The linker has a Graph Theory model of linking. An object file is seen
-/// as a set of Atoms with References to other Atoms.  Each Atom is a node
-/// and each Reference is an edge. An Atom can be a DefinedAtom which has
-/// content or a UndefinedAtom which is a placeholder and represents an
-/// undefined symbol (extern declaration).
-///
-class Atom {
-  template<typename T> friend class OwningAtomPtr;
-
-public:
-  /// Whether this atom is defined or a proxy for an undefined symbol
-  enum Definition {
-    definitionRegular,      ///< Normal C/C++ function or global variable.
-    definitionAbsolute,     ///< Asm-only (foo = 10). Not tied to any content.
-    definitionUndefined,    ///< Only in .o files to model reference to undef.
-    definitionSharedLibrary ///< Only in shared libraries to model export.
-  };
-
-  /// The scope in which this atom is accessible to other atoms.
-  enum Scope {
-    scopeTranslationUnit,  ///< Accessible only to atoms in the same translation
-                           ///  unit (e.g. a C static).
-    scopeLinkageUnit,      ///< Accessible to atoms being linked but not visible
-                           ///  to runtime loader (e.g. visibility=hidden).
-    scopeGlobal            ///< Accessible to all atoms and visible to runtime
-                           ///  loader (e.g. visibility=default).
-  };
-
-  /// file - returns the File that produced/owns this Atom
-  virtual const File& file() const = 0;
-
-  /// name - The name of the atom. For a function atom, it is the (mangled)
-  /// name of the function.
-  virtual StringRef name() const = 0;
-
-  /// definition - Whether this atom is a definition or represents an undefined
-  /// symbol.
-  Definition definition() const { return _definition; }
-
-  static bool classof(const Atom *a) { return true; }
-
-protected:
-  /// Atom is an abstract base class.  Only subclasses can access constructor.
-  explicit Atom(Definition def) : _definition(def) {}
-
-  /// The memory for Atom objects is always managed by the owning File
-  /// object.  Therefore, no one but the owning File object should call
-  /// delete on an Atom.  In fact, some File objects may bulk allocate
-  /// an array of Atoms, so they cannot be individually deleted by anyone.
-  virtual ~Atom() = default;
-
-private:
-  Definition _definition;
-};
-
-/// Class which owns an atom pointer and runs the atom destructor when the
-/// owning pointer goes out of scope.
-template<typename T>
-class OwningAtomPtr {
-private:
-  OwningAtomPtr(const OwningAtomPtr &) = delete;
-  void operator=(const OwningAtomPtr &) = delete;
-
-public:
-  OwningAtomPtr() = default;
-  OwningAtomPtr(T *atom) : atom(atom) { }
-
-  ~OwningAtomPtr() {
-    if (atom)
-      runDestructor(atom);
-  }
-
-  void runDestructor(Atom *atom) {
-    atom->~Atom();
-  }
-
-  OwningAtomPtr(OwningAtomPtr &&ptr) : atom(ptr.atom) {
-    ptr.atom = nullptr;
-  }
-
-  void operator=(OwningAtomPtr&& ptr) {
-    if (atom)
-      runDestructor(atom);
-    atom = ptr.atom;
-    ptr.atom = nullptr;
-  }
-
-  T *const &get() const {
-    return atom;
-  }
-
-  T *&get() {
-    return atom;
-  }
-
-  T *release() {
-    auto *v = atom;
-    atom = nullptr;
-    return v;
-  }
-
-private:
-  T *atom = nullptr;
-};
-
-} // end namespace lld
-
-#endif // LLD_CORE_ATOM_H
diff --git a/gnu/llvm/lld/include/lld/Core/DefinedAtom.h b/gnu/llvm/lld/include/lld/Core/DefinedAtom.h
deleted file mode 100644 (file)
index 4b1de7f..0000000
+++ /dev/null
@@ -1,373 +0,0 @@
-//===- Core/DefinedAtom.h - An Atom with content --------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_DEFINED_ATOM_H
-#define LLD_CORE_DEFINED_ATOM_H
-
-#include "lld/Common/LLVM.h"
-#include "lld/Core/Atom.h"
-#include "lld/Core/Reference.h"
-#include "llvm/Support/ErrorHandling.h"
-
-namespace lld {
-class File;
-
-/// The fundamental unit of linking.
-///
-/// A C function or global variable is an atom.  An atom has content and
-/// attributes. The content of a function atom is the instructions that
-/// implement the function.  The content of a global variable atom is its
-/// initial bytes.
-///
-/// Here are some example attribute sets for common atoms. If a particular
-/// attribute is not listed, the default values are:  definition=regular,
-/// sectionChoice=basedOnContent, scope=translationUnit, merge=no,
-/// deadStrip=normal, interposable=no
-///
-///  C function:  void foo() {} <br>
-///    name=foo, type=code, perm=r_x, scope=global
-///
-///  C static function:  staic void func() {} <br>
-///    name=func, type=code, perm=r_x
-///
-///  C global variable:  int count = 1; <br>
-///    name=count, type=data, perm=rw_, scope=global
-///
-///  C tentative definition:  int bar; <br>
-///    name=bar, type=zerofill, perm=rw_, scope=global,
-///    merge=asTentative, interposable=yesAndRuntimeWeak
-///
-///  Uninitialized C static variable:  static int stuff; <br>
-///    name=stuff, type=zerofill, perm=rw_
-///
-///  Weak C function:  __attribute__((weak)) void foo() {} <br>
-///    name=foo, type=code, perm=r_x, scope=global, merge=asWeak
-///
-///  Hidden C function:  __attribute__((visibility("hidden"))) void foo() {}<br>
-///    name=foo, type=code, perm=r_x, scope=linkageUnit
-///
-///  No-dead-strip function:  __attribute__((used)) void foo() {} <br>
-///    name=foo, type=code, perm=r_x, scope=global, deadStrip=never
-///
-///  Non-inlined C++ inline method:  inline void Foo::doit() {} <br>
-///    name=_ZN3Foo4doitEv, type=code, perm=r_x, scope=global,
-///    mergeDupes=asWeak
-///
-///  Non-inlined C++ inline method whose address is taken:
-///     inline void Foo::doit() {} <br>
-///    name=_ZN3Foo4doitEv, type=code, perm=r_x, scope=global,
-///    mergeDupes=asAddressedWeak
-///
-///  literal c-string:  "hello" <br>
-///    name="" type=cstring, perm=r__, scope=linkageUnit
-///
-///  literal double:  1.234 <br>
-///    name="" type=literal8, perm=r__, scope=linkageUnit
-///
-///  constant:  { 1,2,3 } <br>
-///    name="" type=constant, perm=r__, scope=linkageUnit
-///
-///  Pointer to initializer function:  <br>
-///    name="" type=initializer, perm=rw_l,
-///    sectionChoice=customRequired
-///
-///  C function place in custom section:  __attribute__((section("__foo")))
-///                                       void foo() {} <br>
-///    name=foo, type=code, perm=r_x, scope=global,
-///    sectionChoice=customRequired, customSectionName=__foo
-///
-class DefinedAtom : public Atom {
-public:
-  enum Interposable {
-    interposeNo,            // linker can directly bind uses of this atom
-    interposeYes,           // linker must indirect (through GOT) uses
-    interposeYesAndRuntimeWeak // must indirect and mark symbol weak in final
-                               // linked image
-  };
-
-  enum Merge {
-    mergeNo,                // Another atom with same name is error
-    mergeAsTentative,       // Is ANSI C tentative definition, can be coalesced
-    mergeAsWeak,            // Is C++ inline definition that was not inlined,
-                            // but address was not taken, so atom can be hidden
-                            // by linker
-    mergeAsWeakAndAddressUsed, // Is C++ definition inline definition whose
-                               // address was taken.
-    mergeSameNameAndSize,   // Another atom with different size is error
-    mergeByLargestSection,  // Choose an atom whose section is the largest.
-    mergeByContent,         // Merge with other constants with same content.
-  };
-
-  enum ContentType {
-    typeUnknown,            // for use with definitionUndefined
-    typeMachHeader,         // atom representing mach_header [Darwin]
-    typeCode,               // executable code
-    typeResolver,           // function which returns address of target
-    typeBranchIsland,       // linker created for large binaries
-    typeBranchShim,         // linker created to switch thumb mode
-    typeStub,               // linker created for calling external function
-    typeStubHelper,         // linker created for initial stub binding
-    typeConstant,           // a read-only constant
-    typeCString,            // a zero terminated UTF8 C string
-    typeUTF16String,        // a zero terminated UTF16 string
-    typeCFI,                // a FDE or CIE from dwarf unwind info
-    typeLSDA,               // extra unwinding info
-    typeLiteral4,           // a four-btye read-only constant
-    typeLiteral8,           // an eight-btye read-only constant
-    typeLiteral16,          // a sixteen-btye read-only constant
-    typeData,               // read-write data
-    typeDataFast,           // allow data to be quickly accessed
-    typeZeroFill,           // zero-fill data
-    typeZeroFillFast,       // allow zero-fill data to be quicky accessed
-    typeConstData,          // read-only data after dynamic linker is done
-    typeObjC1Class,         // ObjC1 class [Darwin]
-    typeLazyPointer,        // pointer through which a stub jumps
-    typeLazyDylibPointer,   // pointer through which a stub jumps [Darwin]
-    typeNonLazyPointer,     // pointer to external symbol
-    typeCFString,           // NS/CFString object [Darwin]
-    typeGOT,                // pointer to external symbol
-    typeInitializerPtr,     // pointer to initializer function
-    typeTerminatorPtr,      // pointer to terminator function
-    typeCStringPtr,         // pointer to UTF8 C string [Darwin]
-    typeObjCClassPtr,       // pointer to ObjC class [Darwin]
-    typeObjC2CategoryList,  // pointers to ObjC category [Darwin]
-    typeObjCImageInfo,      // pointer to ObjC class [Darwin]
-    typeObjCMethodList,     // pointer to ObjC method list [Darwin]
-    typeDTraceDOF,          // runtime data for Dtrace [Darwin]
-    typeInterposingTuples,  // tuples of interposing info for dyld [Darwin]
-    typeTempLTO,            // temporary atom for bitcode reader
-    typeCompactUnwindInfo,  // runtime data for unwinder [Darwin]
-    typeProcessedUnwindInfo,// compressed compact unwind info [Darwin]
-    typeThunkTLV,           // thunk used to access a TLV [Darwin]
-    typeTLVInitialData,     // initial data for a TLV [Darwin]
-    typeTLVInitialZeroFill, // TLV initial zero fill data [Darwin]
-    typeTLVInitializerPtr,  // pointer to thread local initializer [Darwin]
-    typeDSOHandle,          // atom representing DSO handle [Darwin]
-    typeSectCreate,         // Created via the -sectcreate option [Darwin]
-  };
-
-  // Permission bits for atoms and segments. The order of these values are
-  // important, because the layout pass may sort atoms by permission if other
-  // attributes are the same.
-  enum ContentPermissions {
-    perm___  = 0,           // mapped as unaccessible
-    permR__  = 8,           // mapped read-only
-    permRW_  = 8 + 2,       // mapped readable and writable
-    permRW_L = 8 + 2 + 1,   // initially mapped r/w, then made read-only
-                            // loader writable
-    permR_X  = 8 + 4,       // mapped readable and executable
-    permRWX  = 8 + 2 + 4,   // mapped readable and writable and executable
-    permUnknown = 16        // unknown or invalid permissions
-  };
-
-  enum SectionChoice {
-    sectionBasedOnContent,  // linker infers final section based on content
-    sectionCustomPreferred, // linker may place in specific section
-    sectionCustomRequired   // linker must place in specific section
-  };
-
-  enum DeadStripKind {
-    deadStripNormal,        // linker may dead strip this atom
-    deadStripNever,         // linker must never dead strip this atom
-    deadStripAlways         // linker must remove this atom if unused
-  };
-
-  enum DynamicExport {
-    /// The linker may or may not export this atom dynamically depending
-    ///   on the output type and other context of the link.
-    dynamicExportNormal,
-    /// The linker will always export this atom dynamically.
-    dynamicExportAlways,
-  };
-
-  // Attributes describe a code model used by the atom.
-  enum CodeModel {
-    codeNA,           // no specific code model
-    // MIPS code models
-    codeMipsPIC,      // PIC function in a PIC / non-PIC mixed file
-    codeMipsMicro,    // microMIPS instruction encoding
-    codeMipsMicroPIC, // microMIPS instruction encoding + PIC
-    codeMips16,       // MIPS-16 instruction encoding
-    // ARM code models
-    codeARMThumb,     // ARM Thumb instruction set
-    codeARM_a,        // $a-like mapping symbol (for ARM code)
-    codeARM_d,        // $d-like mapping symbol (for data)
-    codeARM_t,        // $t-like mapping symbol (for Thumb code)
-  };
-
-  struct Alignment {
-    Alignment(int v, int m = 0) : value(v), modulus(m) {}
-
-    uint16_t value;
-    uint16_t modulus;
-
-    bool operator==(const Alignment &rhs) const {
-      return (value == rhs.value) && (modulus == rhs.modulus);
-    }
-  };
-
-  /// returns a value for the order of this Atom within its file.
-  ///
-  /// This is used by the linker to order the layout of Atoms so that the
-  /// resulting image is stable and reproducible.
-  virtual uint64_t ordinal() const = 0;
-
-  /// the number of bytes of space this atom's content will occupy in the
-  /// final linked image.
-  ///
-  /// For a function atom, it is the number of bytes of code in the function.
-  virtual uint64_t size() const = 0;
-
-  /// The size of the section from which the atom is instantiated.
-  ///
-  /// Merge::mergeByLargestSection is defined in terms of section size
-  /// and not in terms of atom size, so we need this function separate
-  /// from size().
-  virtual uint64_t sectionSize() const { return 0; }
-
-  /// The visibility of this atom to other atoms.
-  ///
-  /// C static functions have scope scopeTranslationUnit.  Regular C functions
-  /// have scope scopeGlobal.  Functions compiled with visibility=hidden have
-  /// scope scopeLinkageUnit so they can be see by other atoms being linked but
-  /// not by the OS loader.
-  virtual Scope scope() const = 0;
-
-  /// Whether the linker should use direct or indirect access to this
-  /// atom.
-  virtual Interposable interposable() const = 0;
-
-  /// how the linker should handle if multiple atoms have the same name.
-  virtual Merge merge() const = 0;
-
-  /// The type of this atom, such as code or data.
-  virtual ContentType contentType() const = 0;
-
-  /// The alignment constraints on how this atom must be laid out in the
-  /// final linked image (e.g. 16-byte aligned).
-  virtual Alignment alignment() const = 0;
-
-  /// Whether this atom must be in a specially named section in the final
-  /// linked image, or if the linker can infer the section based on the
-  /// contentType().
-  virtual SectionChoice sectionChoice() const = 0;
-
-  /// If sectionChoice() != sectionBasedOnContent, then this return the
-  /// name of the section the atom should be placed into.
-  virtual StringRef customSectionName() const = 0;
-
-  /// constraints on whether the linker may dead strip away this atom.
-  virtual DeadStripKind deadStrip() const = 0;
-
-  /// Under which conditions should this atom be dynamically exported.
-  virtual DynamicExport dynamicExport() const {
-    return dynamicExportNormal;
-  }
-
-  /// Code model used by the atom.
-  virtual CodeModel codeModel() const { return codeNA; }
-
-  /// Returns the OS memory protections required for this atom's content
-  /// at runtime.
-  ///
-  /// A function atom is R_X, a global variable is RW_, and a read-only constant
-  /// is R__.
-  virtual ContentPermissions permissions() const;
-
-  /// returns a reference to the raw (unrelocated) bytes of this Atom's
-  /// content.
-  virtual ArrayRef<uint8_t> rawContent() const = 0;
-
-  /// This class abstracts iterating over the sequence of References
-  /// in an Atom.  Concrete instances of DefinedAtom must implement
-  /// the derefIterator() and incrementIterator() methods.
-  class reference_iterator {
-  public:
-    reference_iterator(const DefinedAtom &a, const void *it)
-      : _atom(a), _it(it) { }
-
-    const Reference *operator*() const {
-      return _atom.derefIterator(_it);
-    }
-
-    const Reference *operator->() const {
-      return _atom.derefIterator(_it);
-    }
-
-    bool operator==(const reference_iterator &other) const {
-      return _it == other._it;
-    }
-
-    bool operator!=(const reference_iterator &other) const {
-      return !(*this == other);
-    }
-
-    reference_iterator &operator++() {
-      _atom.incrementIterator(_it);
-      return *this;
-    }
-  private:
-    const DefinedAtom &_atom;
-    const void *_it;
-  };
-
-  /// Returns an iterator to the beginning of this Atom's References.
-  virtual reference_iterator begin() const = 0;
-
-  /// Returns an iterator to the end of this Atom's References.
-  virtual reference_iterator end() const = 0;
-
-  /// Adds a reference to this atom.
-  virtual void addReference(Reference::KindNamespace ns,
-                            Reference::KindArch arch,
-                            Reference::KindValue kindValue, uint64_t off,
-                            const Atom *target, Reference::Addend a) {
-    llvm_unreachable("Subclass does not permit adding references");
-  }
-
-  static bool classof(const Atom *a) {
-    return a->definition() == definitionRegular;
-  }
-
-  /// Utility for deriving permissions from content type
-  static ContentPermissions permissions(ContentType type);
-
-  /// Utility function to check if the atom occupies file space
-  bool occupiesDiskSpace() const {
-    ContentType atomContentType = contentType();
-    return !(atomContentType == DefinedAtom::typeZeroFill ||
-             atomContentType == DefinedAtom::typeZeroFillFast ||
-             atomContentType == DefinedAtom::typeTLVInitialZeroFill);
-  }
-
-  /// Utility function to check if relocations in this atom to other defined
-  /// atoms can be implicitly generated, and so we don't need to explicitly
-  /// emit those relocations.
-  bool relocsToDefinedCanBeImplicit() const {
-    ContentType atomContentType = contentType();
-    return atomContentType == typeCFI;
-  }
-
-protected:
-  // DefinedAtom is an abstract base class. Only subclasses can access
-  // constructor.
-  DefinedAtom() : Atom(definitionRegular) { }
-
-  ~DefinedAtom() override = default;
-
-  /// Returns a pointer to the Reference object that the abstract
-  /// iterator "points" to.
-  virtual const Reference *derefIterator(const void *iter) const = 0;
-
-  /// Adjusts the abstract iterator to "point" to the next Reference
-  /// object for this Atom.
-  virtual void incrementIterator(const void *&iter) const = 0;
-};
-} // end namespace lld
-
-#endif
diff --git a/gnu/llvm/lld/include/lld/Core/Error.h b/gnu/llvm/lld/include/lld/Core/Error.h
deleted file mode 100644 (file)
index 5e12a00..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-//===- Error.h - system_error extensions for lld ----------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This declares a new error_category for the lld library.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_ERROR_H
-#define LLD_CORE_ERROR_H
-
-#include "lld/Common/LLVM.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/Error.h"
-#include <system_error>
-
-namespace lld {
-
-const std::error_category &YamlReaderCategory();
-
-enum class YamlReaderError {
-  unknown_keyword,
-  illegal_value
-};
-
-inline std::error_code make_error_code(YamlReaderError e) {
-  return std::error_code(static_cast<int>(e), YamlReaderCategory());
-}
-
-/// Creates an error_code object that has associated with it an arbitrary
-/// error message.  The value() of the error_code will always be non-zero
-/// but its value is meaningless. The message() will be (a copy of) the
-/// supplied error string.
-/// Note:  Once ErrorOr<> is updated to work with errors other than error_code,
-/// this can be updated to return some other kind of error.
-std::error_code make_dynamic_error_code(StringRef msg);
-
-/// Generic error.
-///
-/// For errors that don't require their own specific sub-error (most errors)
-/// this class can be used to describe the error via a string message.
-class GenericError : public llvm::ErrorInfo<GenericError> {
-public:
-  static char ID;
-  GenericError(Twine Msg);
-  const std::string &getMessage() const { return Msg; }
-  void log(llvm::raw_ostream &OS) const override;
-
-  std::error_code convertToErrorCode() const override {
-    return make_dynamic_error_code(getMessage());
-  }
-
-private:
-  std::string Msg;
-};
-
-} // end namespace lld
-
-namespace std {
-template <> struct is_error_code_enum<lld::YamlReaderError> : std::true_type {};
-}
-
-#endif
diff --git a/gnu/llvm/lld/include/lld/Core/File.h b/gnu/llvm/lld/include/lld/Core/File.h
deleted file mode 100644 (file)
index bb4ca9c..0000000
+++ /dev/null
@@ -1,276 +0,0 @@
-//===- Core/File.h - A Container of Atoms ---------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_FILE_H
-#define LLD_CORE_FILE_H
-
-#include "lld/Core/AbsoluteAtom.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/SharedLibraryAtom.h"
-#include "lld/Core/UndefinedAtom.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <functional>
-#include <memory>
-#include <mutex>
-#include <vector>
-
-namespace lld {
-
-class LinkingContext;
-
-/// Every Atom is owned by some File. A common scenario is for a single
-/// object file (.o) to be parsed by some reader and produce a single
-/// File object that represents the content of that object file.
-///
-/// To iterate through the Atoms in a File there are four methods that
-/// return collections.  For instance to iterate through all the DefinedAtoms
-/// in a File object use:
-///      for (const DefinedAtoms *atom : file->defined()) {
-///      }
-///
-/// The Atom objects in a File are owned by the File object.  The Atom objects
-/// are destroyed when the File object is destroyed.
-class File {
-public:
-  virtual ~File();
-
-  /// Kinds of files that are supported.
-  enum Kind {
-    kindErrorObject,          ///< a error object file (.o)
-    kindNormalizedObject,     ///< a normalized file (.o)
-    kindMachObject,           ///< a MachO object file (.o)
-    kindCEntryObject,         ///< a file for CEntries
-    kindHeaderObject,         ///< a file for file headers
-    kindEntryObject,          ///< a file for the entry
-    kindUndefinedSymsObject,  ///< a file for undefined symbols
-    kindStubHelperObject,     ///< a file for stub helpers
-    kindResolverMergedObject, ///< the resolver merged file.
-    kindSectCreateObject,     ///< a sect create object file (.o)
-    kindSharedLibrary,        ///< shared library (.so)
-    kindArchiveLibrary        ///< archive (.a)
-  };
-
-  /// Returns file kind.  Need for dyn_cast<> on File objects.
-  Kind kind() const {
-    return _kind;
-  }
-
-  /// This returns the path to the file which was used to create this object
-  /// (e.g. "/tmp/foo.o"). If the file is a member of an archive file, the
-  /// returned string includes the archive file name.
-  StringRef path() const {
-    if (_archivePath.empty())
-      return _path;
-    if (_archiveMemberPath.empty())
-      _archiveMemberPath = (_archivePath + "(" + _path + ")").str();
-    return _archiveMemberPath;
-  }
-
-  /// Returns the path of the archive file name if this file is instantiated
-  /// from an archive file. Otherwise returns the empty string.
-  StringRef archivePath() const { return _archivePath; }
-  void setArchivePath(StringRef path) { _archivePath = std::string(path); }
-
-  /// Returns the path name of this file. It doesn't include archive file name.
-  StringRef memberPath() const { return _path; }
-
-  /// Returns the command line order of the file.
-  uint64_t ordinal() const {
-    assert(_ordinal != UINT64_MAX);
-    return _ordinal;
-  }
-
-  /// Returns true/false depending on whether an ordinal has been set.
-  bool hasOrdinal() const { return (_ordinal != UINT64_MAX); }
-
-  /// Sets the command line order of the file.
-  void setOrdinal(uint64_t ordinal) const { _ordinal = ordinal; }
-
-  /// Returns the ordinal for the next atom to be defined in this file.
-  uint64_t getNextAtomOrdinalAndIncrement() const {
-    return _nextAtomOrdinal++;
-  }
-
-  /// For allocating any objects owned by this File.
-  llvm::BumpPtrAllocator &allocator() const {
-    return _allocator;
-  }
-
-  /// The type of atom mutable container.
-  template <typename T> using AtomVector = std::vector<OwningAtomPtr<T>>;
-
-  /// The range type for the atoms.
-  template <typename T> class AtomRange {
-  public:
-    AtomRange(AtomVector<T> &v) : _v(v) {}
-    AtomRange(const AtomVector<T> &v) : _v(const_cast<AtomVector<T> &>(v)) {}
-
-    using ConstDerefFn = const T* (*)(const OwningAtomPtr<T>&);
-    using DerefFn = T* (*)(OwningAtomPtr<T>&);
-
-    typedef llvm::mapped_iterator<typename AtomVector<T>::const_iterator,
-                                  ConstDerefFn> ConstItTy;
-    typedef llvm::mapped_iterator<typename AtomVector<T>::iterator,
-                                  DerefFn> ItTy;
-
-    static const T* DerefConst(const OwningAtomPtr<T> &p) {
-      return p.get();
-    }
-
-    static T* Deref(OwningAtomPtr<T> &p) {
-      return p.get();
-    }
-
-    ConstItTy begin() const {
-      return ConstItTy(_v.begin(), ConstDerefFn(DerefConst));
-    }
-    ConstItTy end() const {
-      return ConstItTy(_v.end(), ConstDerefFn(DerefConst));
-    }
-
-    ItTy begin() {
-      return ItTy(_v.begin(), DerefFn(Deref));
-    }
-    ItTy end() {
-      return ItTy(_v.end(), DerefFn(Deref));
-    }
-
-    llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() {
-      return llvm::make_range(_v.begin(), _v.end());
-    }
-
-    llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() const {
-      return llvm::make_range(_v.begin(), _v.end());
-    }
-
-    bool empty() const {
-      return _v.empty();
-    }
-
-    size_t size() const {
-      return _v.size();
-    }
-
-    const OwningAtomPtr<T> &operator[](size_t idx) const {
-      return _v[idx];
-    }
-
-    OwningAtomPtr<T> &operator[](size_t idx) {
-      return _v[idx];
-    }
-
-  private:
-    AtomVector<T> &_v;
-  };
-
-  /// Must be implemented to return the AtomVector object for
-  /// all DefinedAtoms in this File.
-  virtual const AtomRange<DefinedAtom> defined() const = 0;
-
-  /// Must be implemented to return the AtomVector object for
-  /// all UndefinedAtomw in this File.
-  virtual const AtomRange<UndefinedAtom> undefined() const = 0;
-
-  /// Must be implemented to return the AtomVector object for
-  /// all SharedLibraryAtoms in this File.
-  virtual const AtomRange<SharedLibraryAtom> sharedLibrary() const = 0;
-
-  /// Must be implemented to return the AtomVector object for
-  /// all AbsoluteAtoms in this File.
-  virtual const AtomRange<AbsoluteAtom> absolute() const = 0;
-
-  /// Drop all of the atoms owned by this file.  This will result in all of
-  /// the atoms running their destructors.
-  /// This is required because atoms may be allocated on a BumpPtrAllocator
-  /// of a different file.  We need to destruct all atoms before any files.
-  virtual void clearAtoms() = 0;
-
-  /// If a file is parsed using a different method than doParse(),
-  /// one must use this method to set the last error status, so that
-  /// doParse will not be called twice. Only YAML reader uses this
-  /// (because YAML reader does not read blobs but structured data).
-  void setLastError(std::error_code err) { _lastError = err; }
-
-  std::error_code parse();
-
-  // Usually each file owns a std::unique_ptr<MemoryBuffer>.
-  // However, there's one special case. If a file is an archive file,
-  // the archive file and its children all shares the same memory buffer.
-  // This method is used by the ArchiveFile to give its children
-  // co-ownership of the buffer.
-  void setSharedMemoryBuffer(std::shared_ptr<MemoryBuffer> mb) {
-    _sharedMemoryBuffer = mb;
-  }
-
-protected:
-  /// only subclasses of File can be instantiated
-  File(StringRef p, Kind kind)
-    : _path(p), _kind(kind), _ordinal(UINT64_MAX),
-      _nextAtomOrdinal(0) {}
-
-  /// Subclasses should override this method to parse the
-  /// memory buffer passed to this file's constructor.
-  virtual std::error_code doParse() { return std::error_code(); }
-
-  static AtomVector<DefinedAtom> _noDefinedAtoms;
-  static AtomVector<UndefinedAtom> _noUndefinedAtoms;
-  static AtomVector<SharedLibraryAtom> _noSharedLibraryAtoms;
-  static AtomVector<AbsoluteAtom> _noAbsoluteAtoms;
-  mutable llvm::BumpPtrAllocator _allocator;
-
-private:
-  StringRef _path;
-  std::string _archivePath;
-  mutable std::string _archiveMemberPath;
-  Kind              _kind;
-  mutable uint64_t  _ordinal;
-  mutable uint64_t _nextAtomOrdinal;
-  std::shared_ptr<MemoryBuffer> _sharedMemoryBuffer;
-  llvm::Optional<std::error_code> _lastError;
-  std::mutex _parseMutex;
-};
-
-/// An ErrorFile represents a file that doesn't exist.
-/// If you try to parse a file which doesn't exist, an instance of this
-/// class will be returned. That's parse method always returns an error.
-/// This is useful to delay erroring on non-existent files, so that we
-/// can do unit testing a driver using non-existing file paths.
-class ErrorFile : public File {
-public:
-  ErrorFile(StringRef path, std::error_code ec)
-      : File(path, kindErrorObject), _ec(ec) {}
-
-  std::error_code doParse() override { return _ec; }
-
-  const AtomRange<DefinedAtom> defined() const override {
-    llvm_unreachable("internal error");
-  }
-  const AtomRange<UndefinedAtom> undefined() const override {
-    llvm_unreachable("internal error");
-  }
-  const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
-    llvm_unreachable("internal error");
-  }
-  const AtomRange<AbsoluteAtom> absolute() const override {
-    llvm_unreachable("internal error");
-  }
-
-  void clearAtoms() override {
-  }
-
-private:
-  std::error_code _ec;
-};
-
-} // end namespace lld
-
-#endif
diff --git a/gnu/llvm/lld/include/lld/Core/Instrumentation.h b/gnu/llvm/lld/include/lld/Core/Instrumentation.h
deleted file mode 100644 (file)
index e0b1145..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-//===- include/Core/Instrumentation.h - Instrumentation API ---------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// Provide an Instrumentation API that optionally uses VTune interfaces.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_INSTRUMENTATION_H
-#define LLD_CORE_INSTRUMENTATION_H
-
-#include "llvm/Support/Compiler.h"
-#include <utility>
-
-#ifdef LLD_HAS_VTUNE
-# include <ittnotify.h>
-#endif
-
-namespace lld {
-#ifdef LLD_HAS_VTUNE
-/// A unique global scope for instrumentation data.
-///
-/// Domains last for the lifetime of the application and cannot be destroyed.
-/// Multiple Domains created with the same name represent the same domain.
-class Domain {
-  __itt_domain *_domain;
-
-public:
-  explicit Domain(const char *name) : _domain(__itt_domain_createA(name)) {}
-
-  operator __itt_domain *() const { return _domain; }
-  __itt_domain *operator->() const { return _domain; }
-};
-
-/// A global reference to a string constant.
-///
-/// These are uniqued by the ITT runtime and cannot be deleted. They are not
-/// specific to a domain.
-///
-/// Prefer reusing a single StringHandle over passing a ntbs when the same
-/// string will be used often.
-class StringHandle {
-  __itt_string_handle *_handle;
-
-public:
-  StringHandle(const char *name) : _handle(__itt_string_handle_createA(name)) {}
-
-  operator __itt_string_handle *() const { return _handle; }
-};
-
-/// A task on a single thread. Nests within other tasks.
-///
-/// Each thread has its own task stack and tasks nest recursively on that stack.
-/// A task cannot transfer threads.
-///
-/// SBRM is used to ensure task starts and ends are balanced. The lifetime of
-/// a task is either the lifetime of this object, or until end is called.
-class ScopedTask {
-  __itt_domain *_domain;
-
-  ScopedTask(const ScopedTask &) = delete;
-  ScopedTask &operator=(const ScopedTask &) = delete;
-
-public:
-  /// Create a task in Domain \p d named \p s.
-  ScopedTask(const Domain &d, const StringHandle &s) : _domain(d) {
-    __itt_task_begin(d, __itt_null, __itt_null, s);
-  }
-
-  ScopedTask(ScopedTask &&other) {
-    *this = std::move(other);
-  }
-
-  ScopedTask &operator=(ScopedTask &&other) {
-    _domain = other._domain;
-    other._domain = nullptr;
-    return *this;
-  }
-
-  /// Prematurely end this task.
-  void end() {
-    if (_domain)
-      __itt_task_end(_domain);
-    _domain = nullptr;
-  }
-
-  ~ScopedTask() { end(); }
-};
-
-/// A specific point in time. Allows metadata to be associated.
-class Marker {
-public:
-  Marker(const Domain &d, const StringHandle &s) {
-    __itt_marker(d, __itt_null, s, __itt_scope_global);
-  }
-};
-#else
-class Domain {
-public:
-  Domain(const char *name) {}
-};
-
-class StringHandle {
-public:
-  StringHandle(const char *name) {}
-};
-
-class ScopedTask {
-public:
-  ScopedTask(const Domain &d, const StringHandle &s) {}
-  void end() {}
-};
-
-class Marker {
-public:
-  Marker(const Domain &d, const StringHandle &s) {}
-};
-#endif
-
-inline const Domain &getDefaultDomain() {
-  static Domain domain("org.llvm.lld");
-  return domain;
-}
-} // end namespace lld.
-
-#endif
diff --git a/gnu/llvm/lld/include/lld/Core/LinkingContext.h b/gnu/llvm/lld/include/lld/Core/LinkingContext.h
deleted file mode 100644 (file)
index e090ff9..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-//===- lld/Core/LinkingContext.h - Linker Target Info Interface -*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_LINKING_CONTEXT_H
-#define LLD_CORE_LINKING_CONTEXT_H
-
-#include "lld/Core/Node.h"
-#include "lld/Core/Reader.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Error.h"
-#include <cassert>
-#include <cstdint>
-#include <memory>
-#include <string>
-#include <vector>
-
-namespace lld {
-
-class PassManager;
-class File;
-class Writer;
-class Node;
-class SharedLibraryFile;
-
-/// The LinkingContext class encapsulates "what and how" to link.
-///
-/// The base class LinkingContext contains the options needed by core linking.
-/// Subclasses of LinkingContext have additional options needed by specific
-/// Writers.
-class LinkingContext {
-public:
-  virtual ~LinkingContext();
-
-  /// \name Methods needed by core linking
-  /// @{
-
-  /// Name of symbol linker should use as "entry point" to program,
-  /// usually "main" or "start".
-  virtual StringRef entrySymbolName() const { return _entrySymbolName; }
-
-  /// Whether core linking should remove Atoms not reachable by following
-  /// References from the entry point Atom or from all global scope Atoms
-  /// if globalsAreDeadStripRoots() is true.
-  bool deadStrip() const { return _deadStrip; }
-
-  /// Only used if deadStrip() returns true.  Means all global scope Atoms
-  /// should be marked live (along with all Atoms they reference).  Usually
-  /// this method returns false for main executables, but true for dynamic
-  /// shared libraries.
-  bool globalsAreDeadStripRoots() const { return _globalsAreDeadStripRoots; }
-
-  /// Only used if deadStrip() returns true.  This method returns the names
-  /// of DefinedAtoms that should be marked live (along with all Atoms they
-  /// reference). Only Atoms with scope scopeLinkageUnit or scopeGlobal can
-  /// be kept live using this method.
-  ArrayRef<StringRef> deadStripRoots() const {
-    return _deadStripRoots;
-  }
-
-  /// Add the given symbol name to the dead strip root set. Only used if
-  /// deadStrip() returns true.
-  void addDeadStripRoot(StringRef symbolName) {
-    assert(!symbolName.empty() && "Empty symbol cannot be a dead strip root");
-    _deadStripRoots.push_back(symbolName);
-  }
-
-  /// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a
-  /// SharedLibraryAtom for the link to be successful.  This method controls
-  /// whether core linking prints out a list of remaining UndefinedAtoms.
-  ///
-  /// \todo This should be a method core linking calls with a list of the
-  /// UndefinedAtoms so that different drivers can format the error message
-  /// as needed.
-  bool printRemainingUndefines() const { return _printRemainingUndefines; }
-
-  /// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a
-  /// SharedLibraryAtom for the link to be successful.  This method controls
-  /// whether core linking considers remaining undefines to be an error.
-  bool allowRemainingUndefines() const { return _allowRemainingUndefines; }
-
-  /// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a
-  /// SharedLibraryAtom for the link to be successful.  This method controls
-  /// whether core linking considers remaining undefines from the shared library
-  /// to be an error.
-  bool allowShlibUndefines() const { return _allowShlibUndefines; }
-
-  /// If true, core linking will write the path to each input file to stdout
-  /// (i.e. llvm::outs()) as it is used.  This is used to implement the -t
-  /// linker option.
-  ///
-  /// \todo This should be a method core linking calls so that drivers can
-  /// format the line as needed.
-  bool logInputFiles() const { return _logInputFiles; }
-
-  /// Parts of LLVM use global variables which are bound to command line
-  /// options (see llvm::cl::Options). This method returns "command line"
-  /// options which are used to configure LLVM's command line settings.
-  /// For instance the -debug-only XXX option can be used to dynamically
-  /// trace different parts of LLVM and lld.
-  ArrayRef<const char *> llvmOptions() const { return _llvmOptions; }
-
-  /// \name Methods used by Drivers to configure TargetInfo
-  /// @{
-  void setOutputPath(StringRef str) { _outputPath = str; }
-
-  // Set the entry symbol name. You may also need to call addDeadStripRoot() for
-  // the symbol if your platform supports dead-stripping, so that the symbol
-  // will not be removed from the output.
-  void setEntrySymbolName(StringRef name) {
-    _entrySymbolName = name;
-  }
-
-  void setDeadStripping(bool enable) { _deadStrip = enable; }
-  void setGlobalsAreDeadStripRoots(bool v) { _globalsAreDeadStripRoots = v; }
-
-  void setPrintRemainingUndefines(bool print) {
-    _printRemainingUndefines = print;
-  }
-
-  void setAllowRemainingUndefines(bool allow) {
-    _allowRemainingUndefines = allow;
-  }
-
-  void setAllowShlibUndefines(bool allow) { _allowShlibUndefines = allow; }
-  void setLogInputFiles(bool log) { _logInputFiles = log; }
-
-  void appendLLVMOption(const char *opt) { _llvmOptions.push_back(opt); }
-
-  std::vector<std::unique_ptr<Node>> &getNodes() { return _nodes; }
-  const std::vector<std::unique_ptr<Node>> &getNodes() const { return _nodes; }
-
-  /// This method adds undefined symbols specified by the -u option to the to
-  /// the list of undefined symbols known to the linker. This option essentially
-  /// forces an undefined symbol to be created. You may also need to call
-  /// addDeadStripRoot() for the symbol if your platform supports dead
-  /// stripping, so that the symbol will not be removed from the output.
-  void addInitialUndefinedSymbol(StringRef symbolName) {
-    _initialUndefinedSymbols.push_back(symbolName);
-  }
-
-  /// Iterators for symbols that appear on the command line.
-  typedef std::vector<StringRef> StringRefVector;
-  typedef StringRefVector::iterator StringRefVectorIter;
-  typedef StringRefVector::const_iterator StringRefVectorConstIter;
-
-  /// Create linker internal files containing atoms for the linker to include
-  /// during link. Flavors can override this function in their LinkingContext
-  /// to add more internal files. These internal files are positioned before
-  /// the actual input files.
-  virtual void createInternalFiles(std::vector<std::unique_ptr<File>> &) const;
-
-  /// Return the list of undefined symbols that are specified in the
-  /// linker command line, using the -u option.
-  ArrayRef<StringRef> initialUndefinedSymbols() const {
-    return _initialUndefinedSymbols;
-  }
-
-  /// After all set* methods are called, the Driver calls this method
-  /// to validate that there are no missing options or invalid combinations
-  /// of options.  If there is a problem, a description of the problem
-  /// is written to the global error handler.
-  ///
-  /// \returns true if there is an error with the current settings.
-  bool validate();
-
-  /// Formats symbol name for use in error messages.
-  virtual std::string demangle(StringRef symbolName) const = 0;
-
-  /// @}
-  /// \name Methods used by Driver::link()
-  /// @{
-
-  /// Returns the file system path to which the linked output should be written.
-  ///
-  /// \todo To support in-memory linking, we need an abstraction that allows
-  /// the linker to write to an in-memory buffer.
-  StringRef outputPath() const { return _outputPath; }
-
-  /// Accessor for Register object embedded in LinkingContext.
-  const Registry &registry() const { return _registry; }
-  Registry &registry() { return _registry; }
-
-  /// This method is called by core linking to give the Writer a chance
-  /// to add file format specific "files" to set of files to be linked. This is
-  /// how file format specific atoms can be added to the link.
-  virtual void createImplicitFiles(std::vector<std::unique_ptr<File>> &) = 0;
-
-  /// This method is called by core linking to build the list of Passes to be
-  /// run on the merged/linked graph of all input files.
-  virtual void addPasses(PassManager &pm) = 0;
-
-  /// Calls through to the writeFile() method on the specified Writer.
-  ///
-  /// \param linkedFile This is the merged/linked graph of all input file Atoms.
-  virtual llvm::Error writeFile(const File &linkedFile) const;
-
-  /// Return the next ordinal and Increment it.
-  virtual uint64_t getNextOrdinalAndIncrement() const { return _nextOrdinal++; }
-
-  // This function is called just before the Resolver kicks in.
-  // Derived classes may use it to change the list of input files.
-  virtual void finalizeInputFiles() = 0;
-
-  /// Callback invoked for each file the Resolver decides we are going to load.
-  /// This can be used to update context state based on the file, and emit
-  /// errors for any differences between the context state and a loaded file.
-  /// For example, we can error if we try to load a file which is a different
-  /// arch from that being linked.
-  virtual llvm::Error handleLoadedFile(File &file) = 0;
-
-  /// @}
-protected:
-  LinkingContext(); // Must be subclassed
-
-  /// Abstract method to lazily instantiate the Writer.
-  virtual Writer &writer() const = 0;
-
-  /// Method to create an internal file for the entry symbol
-  virtual std::unique_ptr<File> createEntrySymbolFile() const;
-  std::unique_ptr<File> createEntrySymbolFile(StringRef filename) const;
-
-  /// Method to create an internal file for an undefined symbol
-  virtual std::unique_ptr<File> createUndefinedSymbolFile() const;
-  std::unique_ptr<File> createUndefinedSymbolFile(StringRef filename) const;
-
-  StringRef _outputPath;
-  StringRef _entrySymbolName;
-  bool _deadStrip = false;
-  bool _globalsAreDeadStripRoots = false;
-  bool _printRemainingUndefines = true;
-  bool _allowRemainingUndefines = false;
-  bool _logInputFiles = false;
-  bool _allowShlibUndefines = false;
-  std::vector<StringRef> _deadStripRoots;
-  std::vector<const char *> _llvmOptions;
-  StringRefVector _initialUndefinedSymbols;
-  std::vector<std::unique_ptr<Node>> _nodes;
-  mutable llvm::BumpPtrAllocator _allocator;
-  mutable uint64_t _nextOrdinal = 0;
-  Registry _registry;
-
-private:
-  /// Validate the subclass bits. Only called by validate.
-  virtual bool validateImpl() = 0;
-};
-
-} // end namespace lld
-
-#endif // LLD_CORE_LINKING_CONTEXT_H
diff --git a/gnu/llvm/lld/include/lld/Core/Node.h b/gnu/llvm/lld/include/lld/Core/Node.h
deleted file mode 100644 (file)
index a224793..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-//===- lld/Core/Node.h - Input file class -----------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-///
-/// The classes in this file represents inputs to the linker.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_NODE_H
-#define LLD_CORE_NODE_H
-
-#include "lld/Core/File.h"
-#include <algorithm>
-#include <memory>
-
-namespace lld {
-
-// A Node represents a FileNode or other type of Node. In the latter case,
-// the node contains meta information about the input file list.
-// Currently only GroupEnd node is defined as a meta node.
-class Node {
-public:
-  enum class Kind { File, GroupEnd };
-
-  explicit Node(Kind type) : _kind(type) {}
-  virtual ~Node() = default;
-
-  virtual Kind kind() const { return _kind; }
-
-private:
-  Kind _kind;
-};
-
-// This is a marker for --end-group. getSize() returns the number of
-// files between the corresponding --start-group and this marker.
-class GroupEnd : public Node {
-public:
-  explicit GroupEnd(int size) : Node(Kind::GroupEnd), _size(size) {}
-
-  int getSize() const { return _size; }
-
-  static bool classof(const Node *a) {
-    return a->kind() == Kind::GroupEnd;
-  }
-
-private:
-  int _size;
-};
-
-// A container of File.
-class FileNode : public Node {
-public:
-  explicit FileNode(std::unique_ptr<File> f)
-      : Node(Node::Kind::File), _file(std::move(f)) {}
-
-  static bool classof(const Node *a) {
-    return a->kind() == Node::Kind::File;
-  }
-
-  File *getFile() { return _file.get(); }
-
-protected:
-  std::unique_ptr<File> _file;
-};
-
-} // end namespace lld
-
-#endif // LLD_CORE_NODE_H
diff --git a/gnu/llvm/lld/include/lld/Core/Pass.h b/gnu/llvm/lld/include/lld/Core/Pass.h
deleted file mode 100644 (file)
index 57d5a40..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-//===------ Core/Pass.h - Base class for linker passes ----------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_PASS_H
-#define LLD_CORE_PASS_H
-
-#include "llvm/Support/Error.h"
-
-namespace lld {
-
-class SimpleFile;
-
-/// Once the core linking is done (which resolves references, coalesces atoms
-/// and produces a complete Atom graph), the linker runs a series of passes
-/// on the Atom graph. The graph is modeled as a File, which means the pass
-/// has access to all the atoms and to File level attributes. Each pass does
-/// a particular transformation to the Atom graph or to the File attributes.
-///
-/// This is the abstract base class for all passes.  A Pass does its
-/// actual work in it perform() method.  It can iterator over Atoms in the
-/// graph using the *begin()/*end() atom iterator of the File.  It can add
-/// new Atoms to the graph using the File's addAtom() method.
-class Pass {
-public:
-  virtual ~Pass() = default;
-
-  /// Do the actual work of the Pass.
-  virtual llvm::Error perform(SimpleFile &mergedFile) = 0;
-
-protected:
-  // Only subclassess can be instantiated.
-  Pass() = default;
-};
-
-} // end namespace lld
-
-#endif // LLD_CORE_PASS_H
diff --git a/gnu/llvm/lld/include/lld/Core/PassManager.h b/gnu/llvm/lld/include/lld/Core/PassManager.h
deleted file mode 100644 (file)
index 02499d0..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-//===- lld/Core/PassManager.h - Manage linker passes ----------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_PASS_MANAGER_H
-#define LLD_CORE_PASS_MANAGER_H
-
-#include "lld/Common/LLVM.h"
-#include "lld/Core/Pass.h"
-#include "llvm/Support/Error.h"
-#include <memory>
-#include <vector>
-
-namespace lld {
-class SimpleFile;
-class Pass;
-
-/// Owns and runs a collection of passes.
-///
-/// This class is currently just a container for passes and a way to run them.
-///
-/// In the future this should handle timing pass runs, running parallel passes,
-/// and validate/satisfy pass dependencies.
-class PassManager {
-public:
-  void add(std::unique_ptr<Pass> pass) {
-    _passes.push_back(std::move(pass));
-  }
-
-  llvm::Error runOnFile(SimpleFile &file) {
-    for (std::unique_ptr<Pass> &pass : _passes)
-      if (llvm::Error EC = pass->perform(file))
-        return EC;
-    return llvm::Error::success();
-  }
-
-private:
-  /// Passes in the order they should run.
-  std::vector<std::unique_ptr<Pass>> _passes;
-};
-} // end namespace lld
-
-#endif
diff --git a/gnu/llvm/lld/include/lld/Core/Reader.h b/gnu/llvm/lld/include/lld/Core/Reader.h
deleted file mode 100644 (file)
index a2d7912..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-//===- lld/Core/Reader.h - Abstract File Format Reading Interface ---------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_READER_H
-#define LLD_CORE_READER_H
-
-#include "lld/Common/LLVM.h"
-#include "lld/Core/Reference.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/BinaryFormat/Magic.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include <memory>
-#include <vector>
-
-namespace llvm {
-namespace yaml {
-class IO;
-} // end namespace yaml
-} // end namespace llvm
-
-namespace lld {
-
-class File;
-class LinkingContext;
-class MachOLinkingContext;
-
-/// An abstract class for reading object files, library files, and
-/// executable files.
-///
-/// Each file format (e.g. mach-o, etc) has a concrete subclass of Reader.
-class Reader {
-public:
-  virtual ~Reader() = default;
-
-  /// Sniffs the file to determine if this Reader can parse it.
-  /// The method is called with:
-  /// 1) the file_magic enumeration returned by identify_magic()
-  /// 2) the whole file content buffer if the above is not enough.
-  virtual bool canParse(llvm::file_magic magic, MemoryBufferRef mb) const = 0;
-
-  /// Parse a supplied buffer (already filled with the contents of a
-  /// file) and create a File object.
-  /// The resulting File object takes ownership of the MemoryBuffer.
-  virtual ErrorOr<std::unique_ptr<File>>
-  loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &) const = 0;
-};
-
-/// An abstract class for handling alternate yaml representations
-/// of object files.
-///
-/// The YAML syntax allows "tags" which are used to specify the type of
-/// the YAML node.  In lld, top level YAML documents can be in many YAML
-/// representations (e.g mach-o encoded as yaml, etc).  A tag is used to
-/// specify which representation is used in the following YAML document.
-/// To work, there must be a YamlIOTaggedDocumentHandler registered that
-/// handles each tag type.
-class YamlIOTaggedDocumentHandler {
-public:
-  virtual ~YamlIOTaggedDocumentHandler();
-
-  /// This method is called on each registered YamlIOTaggedDocumentHandler
-  /// until one returns true.  If the subclass handles tag type !xyz, then
-  /// this method should call io.mapTag("!xzy") to see if that is the current
-  /// document type, and if so, process the rest of the document using
-  /// YAML I/O, then convert the result into an lld::File* and return it.
-  virtual bool handledDocTag(llvm::yaml::IO &io, const lld::File *&f) const = 0;
-};
-
-/// A registry to hold the list of currently registered Readers and
-/// tables which map Reference kind values to strings.
-/// The linker does not directly invoke Readers.  Instead, it registers
-/// Readers based on it configuration and command line options, then calls
-/// the Registry object to parse files.
-class Registry {
-public:
-  Registry();
-
-  /// Walk the list of registered Readers and find one that can parse the
-  /// supplied file and parse it.
-  ErrorOr<std::unique_ptr<File>>
-  loadFile(std::unique_ptr<MemoryBuffer> mb) const;
-
-  /// Walk the list of registered kind tables to convert a Reference Kind
-  /// name to a value.
-  bool referenceKindFromString(StringRef inputStr, Reference::KindNamespace &ns,
-                               Reference::KindArch &a,
-                               Reference::KindValue &value) const;
-
-  /// Walk the list of registered kind tables to convert a Reference Kind
-  /// value to a string.
-  bool referenceKindToString(Reference::KindNamespace ns, Reference::KindArch a,
-                             Reference::KindValue value, StringRef &) const;
-
-  /// Walk the list of registered tag handlers and have the one that handles
-  /// the current document type process the yaml into an lld::File*.
-  bool handleTaggedDoc(llvm::yaml::IO &io, const lld::File *&file) const;
-
-  // These methods are called to dynamically add support for various file
-  // formats. The methods are also implemented in the appropriate lib*.a
-  // library, so that the code for handling a format is only linked in, if this
-  // method is used.  Any options that a Reader might need must be passed
-  // as parameters to the addSupport*() method.
-  void addSupportArchives(bool logLoading);
-  void addSupportYamlFiles();
-  void addSupportMachOObjects(MachOLinkingContext &);
-
-  /// To convert between kind values and names, the registry walks the list
-  /// of registered kind tables. Each table is a zero terminated array of
-  /// KindStrings elements.
-  struct KindStrings {
-    Reference::KindValue  value;
-    StringRef             name;
-  };
-
-  /// A Reference Kind value is a tuple of <namespace, arch, value>.  All
-  /// entries in a conversion table have the same <namespace, arch>.  The
-  /// array then contains the value/name pairs.
-  void addKindTable(Reference::KindNamespace ns, Reference::KindArch arch,
-                    const KindStrings array[]);
-
-private:
-  struct KindEntry {
-    Reference::KindNamespace  ns;
-    Reference::KindArch       arch;
-    const KindStrings        *array;
-  };
-
-  void add(std::unique_ptr<Reader>);
-  void add(std::unique_ptr<YamlIOTaggedDocumentHandler>);
-
-  std::vector<std::unique_ptr<Reader>>                       _readers;
-  std::vector<std::unique_ptr<YamlIOTaggedDocumentHandler>>  _yamlHandlers;
-  std::vector<KindEntry>                                     _kindEntries;
-};
-
-// Utilities for building a KindString table.  For instance:
-//   static const Registry::KindStrings table[] = {
-//      LLD_KIND_STRING_ENTRY(R_VAX_ADDR16),
-//      LLD_KIND_STRING_ENTRY(R_VAX_DATA16),
-//      LLD_KIND_STRING_END
-//   };
-#define LLD_KIND_STRING_ENTRY(name) { name, #name }
-#define LLD_KIND_STRING_END         { 0,    "" }
-
-} // end namespace lld
-
-#endif // LLD_CORE_READER_H
diff --git a/gnu/llvm/lld/include/lld/Core/Reference.h b/gnu/llvm/lld/include/lld/Core/Reference.h
deleted file mode 100644 (file)
index b104f84..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-//===- Core/References.h - A Reference to Another Atom ----------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_REFERENCES_H
-#define LLD_CORE_REFERENCES_H
-
-#include <cstdint>
-
-namespace lld {
-
-class Atom;
-
-///
-/// The linker has a Graph Theory model of linking. An object file is seen
-/// as a set of Atoms with References to other Atoms.  Each Atom is a node
-/// and each Reference is an edge.
-///
-/// For example if a function contains a call site to "malloc" 40 bytes into
-/// the Atom, then the function Atom will have a Reference of: offsetInAtom=40,
-/// kind=callsite, target=malloc, addend=0.
-///
-/// Besides supporting traditional "relocations", references are also used
-/// forcing layout (one atom must follow another), marking data-in-code
-/// (jump tables or ARM constants), etc.
-///
-/// The "kind" of a reference is a tuple of <namespace, arch, value>.  This
-/// enable us to re-use existing relocation types definded for various
-/// file formats and architectures.
-///
-/// References and atoms form a directed graph. The dead-stripping pass
-/// traverses them starting from dead-strip root atoms to garbage collect
-/// unreachable ones.
-///
-/// References of any kind are considered as directed edges. In addition to
-/// that, references of some kind is considered as bidirected edges.
-class Reference {
-public:
-  /// Which universe defines the kindValue().
-  enum class KindNamespace {
-    all     = 0,
-    testing = 1,
-    mach_o  = 2,
-  };
-
-  KindNamespace kindNamespace() const { return (KindNamespace)_kindNamespace; }
-  void setKindNamespace(KindNamespace ns) { _kindNamespace = (uint8_t)ns; }
-
-  // Which architecture the kind value is for.
-  enum class KindArch { all, AArch64, ARM, x86, x86_64};
-
-  KindArch kindArch() const { return (KindArch)_kindArch; }
-  void setKindArch(KindArch a) { _kindArch = (uint8_t)a; }
-
-  typedef uint16_t KindValue;
-
-  KindValue kindValue() const { return _kindValue; }
-
-  /// setKindValue() is needed because during linking, some optimizations may
-  /// change the codegen and hence the reference kind.
-  void setKindValue(KindValue value) {
-    _kindValue = value;
-  }
-
-  /// KindValues used with KindNamespace::all and KindArch::all.
-  enum {
-    // kindLayoutAfter is treated as a bidirected edge by the dead-stripping
-    // pass.
-    kindLayoutAfter = 1,
-    kindAssociate,
-  };
-
-  // A value to be added to the value of a target
-  typedef int64_t Addend;
-
-  /// If the reference is a fixup in the Atom, then this returns the
-  /// byte offset into the Atom's content to do the fix up.
-  virtual uint64_t offsetInAtom() const = 0;
-
-  /// Returns the atom this reference refers to.
-  virtual const Atom *target() const = 0;
-
-  /// During linking, the linker may merge graphs which coalesces some nodes
-  /// (i.e. Atoms).  To switch the target of a reference, this method is called.
-  virtual void setTarget(const Atom *) = 0;
-
-  /// Some relocations require a symbol and a value (e.g. foo + 4).
-  virtual Addend addend() const = 0;
-
-  /// During linking, some optimizations may change addend value.
-  virtual void setAddend(Addend) = 0;
-
-  /// Returns target specific attributes of the reference.
-  virtual uint32_t tag() const { return 0; }
-
-protected:
-  /// Reference is an abstract base class.  Only subclasses can use constructor.
-  Reference(KindNamespace ns, KindArch a, KindValue value)
-      : _kindValue(value), _kindNamespace((uint8_t)ns), _kindArch((uint8_t)a) {}
-
-  /// The memory for Reference objects is always managed by the owning File
-  /// object.  Therefore, no one but the owning File object should call
-  /// delete on a Reference.  In fact, some File objects may bulk allocate
-  /// an array of References, so they cannot be individually deleted by anyone.
-  virtual ~Reference() = default;
-
-  KindValue  _kindValue;
-  uint8_t    _kindNamespace;
-  uint8_t    _kindArch;
-};
-
-} // end namespace lld
-
-#endif // LLD_CORE_REFERENCES_H
diff --git a/gnu/llvm/lld/include/lld/Core/Resolver.h b/gnu/llvm/lld/include/lld/Core/Resolver.h
deleted file mode 100644 (file)
index 9ab2195..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-//===- Core/Resolver.h - Resolves Atom References -------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_RESOLVER_H
-#define LLD_CORE_RESOLVER_H
-
-#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/File.h"
-#include "lld/Core/SharedLibraryFile.h"
-#include "lld/Core/Simple.h"
-#include "lld/Core/SymbolTable.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/Support/ErrorOr.h"
-#include <set>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
-namespace lld {
-
-class Atom;
-class LinkingContext;
-
-/// The Resolver is responsible for merging all input object files
-/// and producing a merged graph.
-class Resolver {
-public:
-  Resolver(LinkingContext &ctx) : _ctx(ctx), _result(new MergedFile()) {}
-
-  // InputFiles::Handler methods
-  void doDefinedAtom(OwningAtomPtr<DefinedAtom> atom);
-  bool doUndefinedAtom(OwningAtomPtr<UndefinedAtom> atom);
-  void doSharedLibraryAtom(OwningAtomPtr<SharedLibraryAtom> atom);
-  void doAbsoluteAtom(OwningAtomPtr<AbsoluteAtom> atom);
-
-  // Handle files, this adds atoms from the current file thats
-  // being processed by the resolver
-  llvm::Expected<bool> handleFile(File &);
-
-  // Handle an archive library file.
-  llvm::Expected<bool> handleArchiveFile(File &);
-
-  // Handle a shared library file.
-  llvm::Error handleSharedLibrary(File &);
-
-  /// do work of merging and resolving and return list
-  bool resolve();
-
-  std::unique_ptr<SimpleFile> resultFile() { return std::move(_result); }
-
-private:
-  typedef std::function<llvm::Expected<bool>(StringRef)> UndefCallback;
-
-  bool undefinesAdded(int begin, int end);
-  File *getFile(int &index);
-
-  /// The main function that iterates over the files to resolve
-  bool resolveUndefines();
-  void updateReferences();
-  void deadStripOptimize();
-  bool checkUndefines();
-  void removeCoalescedAwayAtoms();
-  llvm::Expected<bool> forEachUndefines(File &file, UndefCallback callback);
-
-  void markLive(const Atom *atom);
-
-  class MergedFile : public SimpleFile {
-  public:
-    MergedFile() : SimpleFile("<linker-internal>", kindResolverMergedObject) {}
-    void addAtoms(llvm::MutableArrayRef<OwningAtomPtr<Atom>> atoms);
-  };
-
-  LinkingContext &_ctx;
-  SymbolTable _symbolTable;
-  std::vector<OwningAtomPtr<Atom>>     _atoms;
-  std::set<const Atom *>        _deadStripRoots;
-  llvm::DenseSet<const Atom *>  _liveAtoms;
-  llvm::DenseSet<const Atom *>  _deadAtoms;
-  std::unique_ptr<MergedFile>   _result;
-  std::unordered_multimap<const Atom *, const Atom *> _reverseRef;
-
-  // --start-group and --end-group
-  std::vector<File *> _files;
-  std::map<File *, bool> _newUndefinesAdded;
-
-  // List of undefined symbols.
-  std::vector<StringRef> _undefines;
-
-  // Start position in _undefines for each archive/shared library file.
-  // Symbols from index 0 to the start position are already searched before.
-  // Searching them again would never succeed. When we look for undefined
-  // symbols from an archive/shared library file, start from its start
-  // position to save time.
-  std::map<File *, size_t> _undefineIndex;
-};
-
-} // namespace lld
-
-#endif // LLD_CORE_RESOLVER_H
diff --git a/gnu/llvm/lld/include/lld/Core/SharedLibraryAtom.h b/gnu/llvm/lld/include/lld/Core/SharedLibraryAtom.h
deleted file mode 100644 (file)
index 171d154..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-//===- Core/SharedLibraryAtom.h - A Shared Library Atom -------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_SHARED_LIBRARY_ATOM_H
-#define LLD_CORE_SHARED_LIBRARY_ATOM_H
-
-#include "lld/Core/Atom.h"
-
-namespace lld {
-
-/// A SharedLibraryAtom has no content.
-/// It exists to represent a symbol which will be bound at runtime.
-class SharedLibraryAtom : public Atom {
-public:
-  enum class Type : uint32_t {
-    Unknown,
-    Code,
-    Data,
-  };
-
-  /// Returns shared library name used to load it at runtime.
-  /// On Darwin it is the LC_DYLIB_LOAD dylib name.
-  virtual StringRef loadName() const = 0;
-
-  /// Returns if shared library symbol can be missing at runtime and if
-  /// so the loader should silently resolve address of symbol to be nullptr.
-  virtual bool canBeNullAtRuntime() const = 0;
-
-  virtual Type type() const = 0;
-
-  virtual uint64_t size() const = 0;
-
-  static bool classof(const Atom *a) {
-    return a->definition() == definitionSharedLibrary;
-  }
-
-  static inline bool classof(const SharedLibraryAtom *) { return true; }
-
-protected:
-  SharedLibraryAtom() : Atom(definitionSharedLibrary) {}
-
-  ~SharedLibraryAtom() override = default;
-};
-
-} // namespace lld
-
-#endif // LLD_CORE_SHARED_LIBRARY_ATOM_H
diff --git a/gnu/llvm/lld/include/lld/Core/SharedLibraryFile.h b/gnu/llvm/lld/include/lld/Core/SharedLibraryFile.h
deleted file mode 100644 (file)
index 846d1f2..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-//===- Core/SharedLibraryFile.h - Models shared libraries as Atoms --------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_SHARED_LIBRARY_FILE_H
-#define LLD_CORE_SHARED_LIBRARY_FILE_H
-
-#include "lld/Core/File.h"
-
-namespace lld {
-
-///
-/// The SharedLibraryFile subclass of File is used to represent dynamic
-/// shared libraries being linked against.
-///
-class SharedLibraryFile : public File {
-public:
-  static bool classof(const File *f) {
-    return f->kind() == kindSharedLibrary;
-  }
-
-  /// Check if the shared library exports a symbol with the specified name.
-  /// If so, return a SharedLibraryAtom which represents that exported
-  /// symbol.  Otherwise return nullptr.
-  virtual OwningAtomPtr<SharedLibraryAtom> exports(StringRef name) const = 0;
-
-  // Returns the install name.
-  virtual StringRef getDSOName() const = 0;
-
-  const AtomRange<DefinedAtom> defined() const override {
-    return _definedAtoms;
-  }
-
-  const AtomRange<UndefinedAtom> undefined() const override {
-    return _undefinedAtoms;
-  }
-
-  const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
-    return _sharedLibraryAtoms;
-  }
-
-  const AtomRange<AbsoluteAtom> absolute() const override {
-    return _absoluteAtoms;
-  }
-
-  void clearAtoms() override {
-    _definedAtoms.clear();
-    _undefinedAtoms.clear();
-    _sharedLibraryAtoms.clear();
-    _absoluteAtoms.clear();
-  }
-
-protected:
-  /// only subclasses of SharedLibraryFile can be instantiated
-  explicit SharedLibraryFile(StringRef path) : File(path, kindSharedLibrary) {}
-
-  AtomVector<DefinedAtom> _definedAtoms;
-  AtomVector<UndefinedAtom> _undefinedAtoms;
-  AtomVector<SharedLibraryAtom> _sharedLibraryAtoms;
-  AtomVector<AbsoluteAtom> _absoluteAtoms;
-};
-
-} // namespace lld
-
-#endif // LLD_CORE_SHARED_LIBRARY_FILE_H
diff --git a/gnu/llvm/lld/include/lld/Core/Simple.h b/gnu/llvm/lld/include/lld/Core/Simple.h
deleted file mode 100644 (file)
index f211beb..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-//===- lld/Core/Simple.h - Simple implementations of Atom and File --------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// Provide simple implementations for Atoms and File.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_SIMPLE_H
-#define LLD_CORE_SIMPLE_H
-
-#include "lld/Core/AbsoluteAtom.h"
-#include "lld/Core/Atom.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/SharedLibraryAtom.h"
-#include "lld/Core/UndefinedAtom.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/ilist.h"
-#include "llvm/ADT/ilist_node.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <algorithm>
-#include <cassert>
-#include <cstdint>
-#include <functional>
-
-namespace lld {
-
-class SimpleFile : public File {
-public:
-  SimpleFile(StringRef path, File::Kind kind)
-    : File(path, kind) {}
-
-  ~SimpleFile() override {
-    _defined.clear();
-    _undefined.clear();
-    _shared.clear();
-    _absolute.clear();
-  }
-
-  void addAtom(DefinedAtom &a) {
-    _defined.push_back(OwningAtomPtr<DefinedAtom>(&a));
-  }
-  void addAtom(UndefinedAtom &a) {
-    _undefined.push_back(OwningAtomPtr<UndefinedAtom>(&a));
-  }
-  void addAtom(SharedLibraryAtom &a) {
-    _shared.push_back(OwningAtomPtr<SharedLibraryAtom>(&a));
-  }
-  void addAtom(AbsoluteAtom &a) {
-    _absolute.push_back(OwningAtomPtr<AbsoluteAtom>(&a));
-  }
-
-  void addAtom(const Atom &atom) {
-    if (auto *p = dyn_cast<DefinedAtom>(&atom)) {
-      addAtom(const_cast<DefinedAtom &>(*p));
-    } else if (auto *p = dyn_cast<UndefinedAtom>(&atom)) {
-      addAtom(const_cast<UndefinedAtom &>(*p));
-    } else if (auto *p = dyn_cast<SharedLibraryAtom>(&atom)) {
-      addAtom(const_cast<SharedLibraryAtom &>(*p));
-    } else if (auto *p = dyn_cast<AbsoluteAtom>(&atom)) {
-      addAtom(const_cast<AbsoluteAtom &>(*p));
-    } else {
-      llvm_unreachable("atom has unknown definition kind");
-    }
-  }
-
-  void removeDefinedAtomsIf(std::function<bool(const DefinedAtom *)> pred) {
-    auto &atoms = _defined;
-    auto newEnd = std::remove_if(atoms.begin(), atoms.end(),
-                                 [&pred](OwningAtomPtr<DefinedAtom> &p) {
-                                   return pred(p.get());
-                                 });
-    atoms.erase(newEnd, atoms.end());
-  }
-
-  const AtomRange<DefinedAtom> defined() const override { return _defined; }
-
-  const AtomRange<UndefinedAtom> undefined() const override {
-    return _undefined;
-  }
-
-  const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
-    return _shared;
-  }
-
-  const AtomRange<AbsoluteAtom> absolute() const override {
-    return _absolute;
-  }
-
-  void clearAtoms() override {
-    _defined.clear();
-    _undefined.clear();
-    _shared.clear();
-    _absolute.clear();
-  }
-
-private:
-  AtomVector<DefinedAtom> _defined;
-  AtomVector<UndefinedAtom> _undefined;
-  AtomVector<SharedLibraryAtom> _shared;
-  AtomVector<AbsoluteAtom> _absolute;
-};
-
-class SimpleReference : public Reference,
-                        public llvm::ilist_node<SimpleReference> {
-public:
-  SimpleReference(Reference::KindNamespace ns, Reference::KindArch arch,
-                  Reference::KindValue value, uint64_t off, const Atom *t,
-                  Reference::Addend a)
-      : Reference(ns, arch, value), _target(t), _offsetInAtom(off), _addend(a) {
-  }
-  SimpleReference()
-      : Reference(Reference::KindNamespace::all, Reference::KindArch::all, 0),
-        _target(nullptr), _offsetInAtom(0), _addend(0) {}
-
-  uint64_t offsetInAtom() const override { return _offsetInAtom; }
-
-  const Atom *target() const override {
-    assert(_target);
-    return _target;
-  }
-
-  Addend addend() const override { return _addend; }
-  void setAddend(Addend a) override { _addend = a; }
-  void setTarget(const Atom *newAtom) override { _target = newAtom; }
-
-private:
-  const Atom *_target;
-  uint64_t _offsetInAtom;
-  Addend _addend;
-};
-
-class SimpleDefinedAtom : public DefinedAtom {
-public:
-  explicit SimpleDefinedAtom(const File &f)
-      : _file(f), _ordinal(f.getNextAtomOrdinalAndIncrement()) {}
-
-  ~SimpleDefinedAtom() override {
-    _references.clearAndLeakNodesUnsafely();
-  }
-
-  const File &file() const override { return _file; }
-
-  StringRef name() const override { return StringRef(); }
-
-  uint64_t ordinal() const override { return _ordinal; }
-
-  Scope scope() const override { return DefinedAtom::scopeLinkageUnit; }
-
-  Interposable interposable() const override {
-    return DefinedAtom::interposeNo;
-  }
-
-  Merge merge() const override { return DefinedAtom::mergeNo; }
-
-  Alignment alignment() const override { return 1; }
-
-  SectionChoice sectionChoice() const override {
-    return DefinedAtom::sectionBasedOnContent;
-  }
-
-  StringRef customSectionName() const override { return StringRef(); }
-  DeadStripKind deadStrip() const override {
-    return DefinedAtom::deadStripNormal;
-  }
-
-  DefinedAtom::reference_iterator begin() const override {
-    const void *it =
-        reinterpret_cast<const void *>(_references.begin().getNodePtr());
-    return reference_iterator(*this, it);
-  }
-
-  DefinedAtom::reference_iterator end() const override {
-    const void *it =
-        reinterpret_cast<const void *>(_references.end().getNodePtr());
-    return reference_iterator(*this, it);
-  }
-
-  const Reference *derefIterator(const void *it) const override {
-    return &*RefList::const_iterator(
-        *reinterpret_cast<const llvm::ilist_node<SimpleReference> *>(it));
-  }
-
-  void incrementIterator(const void *&it) const override {
-    RefList::const_iterator ref(
-        *reinterpret_cast<const llvm::ilist_node<SimpleReference> *>(it));
-    it = reinterpret_cast<const void *>(std::next(ref).getNodePtr());
-  }
-
-  void addReference(Reference::KindNamespace ns,
-                    Reference::KindArch arch,
-                    Reference::KindValue kindValue, uint64_t off,
-                    const Atom *target, Reference::Addend a) override {
-    assert(target && "trying to create reference to nothing");
-    auto node = new (_file.allocator())
-        SimpleReference(ns, arch, kindValue, off, target, a);
-    _references.push_back(node);
-  }
-
-  /// Sort references in a canonical order (by offset, then by kind).
-  void sortReferences() const {
-    // Cannot sort a linked  list, so move elements into a temporary vector,
-    // sort the vector, then reconstruct the list.
-    llvm::SmallVector<SimpleReference *, 16> elements;
-    for (SimpleReference &node : _references) {
-      elements.push_back(&node);
-    }
-    std::sort(elements.begin(), elements.end(),
-        [] (const SimpleReference *lhs, const SimpleReference *rhs) -> bool {
-          uint64_t lhsOffset = lhs->offsetInAtom();
-          uint64_t rhsOffset = rhs->offsetInAtom();
-          if (rhsOffset != lhsOffset)
-            return (lhsOffset < rhsOffset);
-          if (rhs->kindNamespace() != lhs->kindNamespace())
-            return (lhs->kindNamespace() < rhs->kindNamespace());
-          if (rhs->kindArch() != lhs->kindArch())
-            return (lhs->kindArch() < rhs->kindArch());
-          return (lhs->kindValue() < rhs->kindValue());
-        });
-    _references.clearAndLeakNodesUnsafely();
-    for (SimpleReference *node : elements) {
-      _references.push_back(node);
-    }
-  }
-
-  void setOrdinal(uint64_t ord) { _ordinal = ord; }
-
-private:
-  typedef llvm::ilist<SimpleReference> RefList;
-
-  const File &_file;
-  uint64_t _ordinal;
-  mutable RefList _references;
-};
-
-class SimpleUndefinedAtom : public UndefinedAtom {
-public:
-  SimpleUndefinedAtom(const File &f, StringRef name) : _file(f), _name(name) {
-    assert(!name.empty() && "UndefinedAtoms must have a name");
-  }
-
-  ~SimpleUndefinedAtom() override = default;
-
-  /// file - returns the File that produced/owns this Atom
-  const File &file() const override { return _file; }
-
-  /// name - The name of the atom. For a function atom, it is the (mangled)
-  /// name of the function.
-  StringRef name() const override { return _name; }
-
-  CanBeNull canBeNull() const override { return UndefinedAtom::canBeNullNever; }
-
-private:
-  const File &_file;
-  StringRef _name;
-};
-
-} // end namespace lld
-
-#endif // LLD_CORE_SIMPLE_H
diff --git a/gnu/llvm/lld/include/lld/Core/SymbolTable.h b/gnu/llvm/lld/include/lld/Core/SymbolTable.h
deleted file mode 100644 (file)
index c7502a4..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-//===- Core/SymbolTable.h - Main Symbol Table -----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_SYMBOL_TABLE_H
-#define LLD_CORE_SYMBOL_TABLE_H
-
-#include "lld/Common/LLVM.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/Support/DJB.h"
-#include <cstring>
-#include <map>
-#include <vector>
-
-namespace lld {
-
-class AbsoluteAtom;
-class Atom;
-class DefinedAtom;
-class LinkingContext;
-class ResolverOptions;
-class SharedLibraryAtom;
-class UndefinedAtom;
-
-/// The SymbolTable class is responsible for coalescing atoms.
-///
-/// All atoms coalescable by-name or by-content should be added.
-/// The method replacement() can be used to find the replacement atom
-/// if an atom has been coalesced away.
-class SymbolTable {
-public:
-  /// add atom to symbol table
-  bool add(const DefinedAtom &);
-
-  /// add atom to symbol table
-  bool add(const UndefinedAtom &);
-
-  /// add atom to symbol table
-  bool add(const SharedLibraryAtom &);
-
-  /// add atom to symbol table
-  bool add(const AbsoluteAtom &);
-
-  /// returns atom in symbol table for specified name (or nullptr)
-  const Atom *findByName(StringRef sym);
-
-  /// returns vector of remaining UndefinedAtoms
-  std::vector<const UndefinedAtom *> undefines();
-
-  /// if atom has been coalesced away, return replacement, else return atom
-  const Atom *replacement(const Atom *);
-
-  /// if atom has been coalesced away, return true
-  bool isCoalescedAway(const Atom *);
-
-private:
-  typedef llvm::DenseMap<const Atom *, const Atom *> AtomToAtom;
-
-  struct StringRefMappingInfo {
-    static StringRef getEmptyKey() { return StringRef(); }
-    static StringRef getTombstoneKey() { return StringRef(" ", 1); }
-    static unsigned getHashValue(StringRef const val) {
-      return llvm::djbHash(val, 0);
-    }
-    static bool isEqual(StringRef const lhs, StringRef const rhs) {
-      return lhs.equals(rhs);
-    }
-  };
-  typedef llvm::DenseMap<StringRef, const Atom *,
-                                           StringRefMappingInfo> NameToAtom;
-
-  struct AtomMappingInfo {
-    static const DefinedAtom * getEmptyKey() { return nullptr; }
-    static const DefinedAtom * getTombstoneKey() { return (DefinedAtom*)(-1); }
-    static unsigned getHashValue(const DefinedAtom * const Val);
-    static bool isEqual(const DefinedAtom * const LHS,
-                        const DefinedAtom * const RHS);
-  };
-  typedef llvm::DenseSet<const DefinedAtom*, AtomMappingInfo> AtomContentSet;
-
-  bool addByName(const Atom &);
-  bool addByContent(const DefinedAtom &);
-
-  AtomToAtom _replacedAtoms;
-  NameToAtom _nameTable;
-  AtomContentSet _contentTable;
-};
-
-} // namespace lld
-
-#endif // LLD_CORE_SYMBOL_TABLE_H
diff --git a/gnu/llvm/lld/include/lld/Core/UndefinedAtom.h b/gnu/llvm/lld/include/lld/Core/UndefinedAtom.h
deleted file mode 100644 (file)
index 31cb9f8..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-//===- Core/UndefinedAtom.h - An Undefined Atom ---------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_UNDEFINED_ATOM_H
-#define LLD_CORE_UNDEFINED_ATOM_H
-
-#include "lld/Core/Atom.h"
-
-namespace lld {
-
-/// An UndefinedAtom has no content.
-/// It exists as a placeholder for a future atom.
-class UndefinedAtom : public Atom {
-public:
-  /// Whether this undefined symbol needs to be resolved,
-  /// or whether it can just evaluate to nullptr.
-  /// This concept is often called "weak", but that term
-  /// is overloaded to mean other things too.
-  enum CanBeNull {
-    /// Normal symbols must be resolved at build time
-    canBeNullNever,
-
-    /// This symbol can be missing at runtime and will evaluate to nullptr.
-    /// That is, the static linker still must find a definition (usually
-    /// is some shared library), but at runtime, the dynamic loader
-    /// will allow the symbol to be missing and resolved to nullptr.
-    ///
-    /// On Darwin this is generated using a function prototype with
-    /// __attribute__((weak_import)).
-    /// On linux this is generated using a function prototype with
-    ///  __attribute__((weak)).
-    /// On Windows this feature is not supported.
-    canBeNullAtRuntime,
-
-    /// This symbol can be missing at build time.
-    /// That is, the static linker will not error if a definition for
-    /// this symbol is not found at build time. Instead, the linker
-    /// will build an executable that lets the dynamic loader find the
-    /// symbol at runtime.
-    /// This feature is not supported on Darwin nor Windows.
-    /// On linux this is generated using a function prototype with
-    ///  __attribute__((weak)).
-    canBeNullAtBuildtime
-  };
-
-  virtual CanBeNull canBeNull() const = 0;
-
-  static bool classof(const Atom *a) {
-    return a->definition() == definitionUndefined;
-  }
-
-  static bool classof(const UndefinedAtom *) { return true; }
-
-protected:
-  UndefinedAtom() : Atom(definitionUndefined) {}
-
-  ~UndefinedAtom() override = default;
-};
-
-} // namespace lld
-
-#endif // LLD_CORE_UNDEFINED_ATOM_H
diff --git a/gnu/llvm/lld/include/lld/Core/Writer.h b/gnu/llvm/lld/include/lld/Core/Writer.h
deleted file mode 100644 (file)
index 0de5fca..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-//===- lld/Core/Writer.h - Abstract File Format Interface -----------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_WRITER_H
-#define LLD_CORE_WRITER_H
-
-#include "lld/Common/LLVM.h"
-#include "llvm/Support/Error.h"
-#include <memory>
-#include <vector>
-
-namespace lld {
-class File;
-class LinkingContext;
-class MachOLinkingContext;
-
-/// The Writer is an abstract class for writing object files, shared
-/// library files, and executable files.  Each file format (e.g. mach-o, etc)
-/// has a concrete subclass of Writer.
-class Writer {
-public:
-  virtual ~Writer();
-
-  /// Write a file from the supplied File object
-  virtual llvm::Error writeFile(const File &linkedFile, StringRef path) = 0;
-
-  /// This method is called by Core Linking to give the Writer a chance
-  /// to add file format specific "files" to set of files to be linked. This is
-  /// how file format specific atoms can be added to the link.
-  virtual void createImplicitFiles(std::vector<std::unique_ptr<File>> &) {}
-
-protected:
-  // only concrete subclasses can be instantiated
-  Writer();
-};
-
-std::unique_ptr<Writer> createWriterMachO(const MachOLinkingContext &);
-std::unique_ptr<Writer> createWriterYAML(const LinkingContext &);
-} // end namespace lld
-
-#endif
diff --git a/gnu/llvm/lld/include/lld/ReaderWriter/MachOLinkingContext.h b/gnu/llvm/lld/include/lld/ReaderWriter/MachOLinkingContext.h
deleted file mode 100644 (file)
index 974f323..0000000
+++ /dev/null
@@ -1,505 +0,0 @@
-//===- lld/ReaderWriter/MachOLinkingContext.h -----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_LINKING_CONTEXT_H
-#define LLD_READER_WRITER_MACHO_LINKING_CONTEXT_H
-
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Reader.h"
-#include "lld/Core/Writer.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <set>
-
-using llvm::MachO::HeaderFileType;
-
-namespace lld {
-
-namespace mach_o {
-class ArchHandler;
-class MachODylibFile;
-class MachOFile;
-class SectCreateFile;
-}
-
-class MachOLinkingContext : public LinkingContext {
-public:
-  MachOLinkingContext();
-  ~MachOLinkingContext() override;
-
-  enum Arch {
-    arch_unknown,
-    arch_ppc,
-    arch_x86,
-    arch_x86_64,
-    arch_armv6,
-    arch_armv7,
-    arch_armv7s,
-    arch_arm64,
-  };
-
-  enum class OS {
-    unknown,
-    macOSX,
-    iOS,
-    iOS_simulator
-  };
-
-  enum class ExportMode {
-    globals,    // Default, all global symbols exported.
-    exported,   // -exported_symbol[s_list], only listed symbols exported.
-    unexported  // -unexported_symbol[s_list], no listed symbol exported.
-  };
-
-  enum class DebugInfoMode {
-    addDebugMap,    // Default
-    noDebugMap      // -S option
-  };
-
-  enum class UndefinedMode {
-    error,
-    warning,
-    suppress,
-    dynamicLookup
-  };
-
-  enum ObjCConstraint {
-    objc_unknown = 0,
-    objc_supports_gc = 2,
-    objc_gc_only = 4,
-    // Image optimized by dyld = 8
-    // GC compaction = 16
-    objc_retainReleaseForSimulator = 32,
-    objc_retainRelease
-  };
-
-  /// Initializes the context to sane default values given the specified output
-  /// file type, arch, os, and minimum os version.  This should be called before
-  /// other setXXX() methods.
-  void configure(HeaderFileType type, Arch arch, OS os, uint32_t minOSVersion,
-                 bool exportDynamicSymbols);
-
-  void addPasses(PassManager &pm) override;
-  bool validateImpl() override;
-  std::string demangle(StringRef symbolName) const override;
-
-  void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
-
-  /// Creates a new file which is owned by the context.  Returns a pointer to
-  /// the new file.
-  template <class T, class... Args>
-  typename std::enable_if<!std::is_array<T>::value, T *>::type
-  make_file(Args &&... args) const {
-    auto file = std::unique_ptr<T>(new T(std::forward<Args>(args)...));
-    auto *filePtr = file.get();
-    auto *ctx = const_cast<MachOLinkingContext *>(this);
-    ctx->getNodes().push_back(std::make_unique<FileNode>(std::move(file)));
-    return filePtr;
-  }
-
-  uint32_t getCPUType() const;
-  uint32_t getCPUSubType() const;
-
-  bool addEntryPointLoadCommand() const;
-  bool addUnixThreadLoadCommand() const;
-  bool outputTypeHasEntry() const;
-  bool is64Bit() const;
-
-  virtual uint64_t pageZeroSize() const { return _pageZeroSize; }
-  virtual uint64_t pageSize() const { return _pageSize; }
-
-  mach_o::ArchHandler &archHandler() const;
-
-  HeaderFileType outputMachOType() const { return _outputMachOType; }
-
-  Arch arch() const { return _arch; }
-  StringRef archName() const { return nameFromArch(_arch); }
-  OS os() const { return _os; }
-
-  ExportMode exportMode() const { return _exportMode; }
-  void setExportMode(ExportMode mode) { _exportMode = mode; }
-  void addExportSymbol(StringRef sym);
-  bool exportRestrictMode() const { return _exportMode != ExportMode::globals; }
-  bool exportSymbolNamed(StringRef sym) const;
-
-  DebugInfoMode debugInfoMode() const { return _debugInfoMode; }
-  void setDebugInfoMode(DebugInfoMode mode) {
-    _debugInfoMode = mode;
-  }
-
-  void appendOrderedSymbol(StringRef symbol, StringRef filename);
-
-  bool keepPrivateExterns() const { return _keepPrivateExterns; }
-  void setKeepPrivateExterns(bool v) { _keepPrivateExterns = v; }
-  bool demangleSymbols() const { return _demangle; }
-  void setDemangleSymbols(bool d) { _demangle = d; }
-  bool mergeObjCCategories() const { return _mergeObjCCategories; }
-  void setMergeObjCCategories(bool v) { _mergeObjCCategories = v; }
-  /// Create file at specified path which will contain a binary encoding
-  /// of all input and output file paths.
-  std::error_code createDependencyFile(StringRef path);
-  void addInputFileDependency(StringRef path) const;
-  void addInputFileNotFound(StringRef path) const;
-  void addOutputFileDependency(StringRef path) const;
-
-  bool minOS(StringRef mac, StringRef iOS) const;
-  void setDoNothing(bool value) { _doNothing = value; }
-  bool doNothing() const { return _doNothing; }
-  bool printAtoms() const { return _printAtoms; }
-  bool testingFileUsage() const { return _testingFileUsage; }
-  const StringRefVector &searchDirs() const { return _searchDirs; }
-  const StringRefVector &frameworkDirs() const { return _frameworkDirs; }
-  void setSysLibRoots(const StringRefVector &paths);
-  const StringRefVector &sysLibRoots() const { return _syslibRoots; }
-  bool PIE() const { return _pie; }
-  void setPIE(bool pie) { _pie = pie; }
-  bool generateVersionLoadCommand() const {
-    return _generateVersionLoadCommand;
-  }
-  void setGenerateVersionLoadCommand(bool v) {
-    _generateVersionLoadCommand = v;
-  }
-
-  bool generateFunctionStartsLoadCommand() const {
-    return _generateFunctionStartsLoadCommand;
-  }
-  void setGenerateFunctionStartsLoadCommand(bool v) {
-    _generateFunctionStartsLoadCommand = v;
-  }
-
-  bool generateDataInCodeLoadCommand() const {
-    return _generateDataInCodeLoadCommand;
-  }
-  void setGenerateDataInCodeLoadCommand(bool v) {
-    _generateDataInCodeLoadCommand = v;
-  }
-
-  uint64_t stackSize() const { return _stackSize; }
-  void setStackSize(uint64_t stackSize) { _stackSize = stackSize; }
-
-  uint64_t baseAddress() const { return _baseAddress; }
-  void setBaseAddress(uint64_t baseAddress) { _baseAddress = baseAddress; }
-
-  ObjCConstraint objcConstraint() const { return _objcConstraint; }
-
-  uint32_t osMinVersion() const { return _osMinVersion; }
-
-  uint32_t sdkVersion() const { return _sdkVersion; }
-  void setSdkVersion(uint64_t v) { _sdkVersion = v; }
-
-  uint64_t sourceVersion() const { return _sourceVersion; }
-  void setSourceVersion(uint64_t v) { _sourceVersion = v; }
-
-  uint32_t swiftVersion() const { return _swiftVersion; }
-
-  /// Checks whether a given path on the filesystem exists.
-  ///
-  /// When running in -test_file_usage mode, this method consults an
-  /// internally maintained list of files that exist (provided by -path_exists)
-  /// instead of the actual filesystem.
-  bool pathExists(StringRef path) const;
-
-  /// Like pathExists() but only used on files - not directories.
-  bool fileExists(StringRef path) const;
-
-  /// Adds any library search paths derived from the given base, possibly
-  /// modified by -syslibroots.
-  ///
-  /// The set of paths added consists of approximately all syslibroot-prepended
-  /// versions of libPath that exist, or the original libPath if there are none
-  /// for whatever reason. With various edge-cases for compatibility.
-  void addModifiedSearchDir(StringRef libPath, bool isSystemPath = false);
-
-  /// Determine whether -lFoo can be resolve within the given path, and
-  /// return the filename if so.
-  ///
-  /// The -lFoo option is documented to search for libFoo.dylib and libFoo.a in
-  /// that order, unless Foo ends in ".o", in which case only the exact file
-  /// matches (e.g. -lfoo.o would only find foo.o).
-  llvm::Optional<StringRef> searchDirForLibrary(StringRef path,
-                                                StringRef libName) const;
-
-  /// Iterates through all search path entries looking for libName (as
-  /// specified by -lFoo).
-  llvm::Optional<StringRef> searchLibrary(StringRef libName) const;
-
-  /// Add a framework search path.  Internally, this method may be prepended
-  /// the path with syslibroot.
-  void addFrameworkSearchDir(StringRef fwPath, bool isSystemPath = false);
-
-  /// Iterates through all framework directories looking for
-  /// Foo.framework/Foo (when fwName = "Foo").
-  llvm::Optional<StringRef> findPathForFramework(StringRef fwName) const;
-
-  /// The dylib's binary compatibility version, in the raw uint32 format.
-  ///
-  /// When building a dynamic library, this is the compatibility version that
-  /// gets embedded into the result. Other Mach-O binaries that link against
-  /// this library will store the compatibility version in its load command. At
-  /// runtime, the loader will verify that the binary is compatible with the
-  /// installed dynamic library.
-  uint32_t compatibilityVersion() const { return _compatibilityVersion; }
-
-  /// The dylib's current version, in the raw uint32 format.
-  ///
-  /// When building a dynamic library, this is the current version that gets
-  /// embedded into the result. Other Mach-O binaries that link against
-  /// this library will store the compatibility version in its load command.
-  uint32_t currentVersion() const { return _currentVersion; }
-
-  /// The dylib's install name.
-  ///
-  /// Binaries that link against the dylib will embed this path into the dylib
-  /// load command. When loading the binaries at runtime, this is the location
-  /// on disk that the loader will look for the dylib.
-  StringRef installName() const { return _installName; }
-
-  /// Whether or not the dylib has side effects during initialization.
-  ///
-  /// Dylibs marked as being dead strippable provide the guarantee that loading
-  /// the dylib has no side effects, allowing the linker to strip out the dylib
-  /// when linking a binary that does not use any of its symbols.
-  bool deadStrippableDylib() const { return _deadStrippableDylib; }
-
-  /// Whether or not to use flat namespace.
-  ///
-  /// MachO usually uses a two-level namespace, where each external symbol
-  /// referenced by the target is associated with the dylib that will provide
-  /// the symbol's definition at runtime. Using flat namespace overrides this
-  /// behavior: the linker searches all dylibs on the command line and all
-  /// dylibs those original dylibs depend on, but does not record which dylib
-  /// an external symbol came from. At runtime dyld again searches all images
-  /// and uses the first definition it finds. In addition, any undefines in
-  /// loaded flat_namespace dylibs must be resolvable at build time.
-  bool useFlatNamespace() const { return _flatNamespace; }
-
-  /// How to handle undefined symbols.
-  ///
-  /// Options are:
-  ///  * error: Report an error and terminate linking.
-  ///  * warning: Report a warning, but continue linking.
-  ///  * suppress: Ignore and continue linking.
-  ///  * dynamic_lookup: For use with -twolevel namespace: Records source dylibs
-  ///    for symbols that are defined in a linked dylib at static link time.
-  ///    Undefined symbols are handled by searching all loaded images at
-  ///    runtime.
-  UndefinedMode undefinedMode() const { return _undefinedMode; }
-
-  /// The path to the executable that will load the bundle at runtime.
-  ///
-  /// When building a Mach-O bundle, this executable will be examined if there
-  /// are undefined symbols after the main link phase. It is expected that this
-  /// binary will be loading the bundle at runtime and will provide the symbols
-  /// at that point.
-  StringRef bundleLoader() const { return _bundleLoader; }
-
-  void setCompatibilityVersion(uint32_t vers) { _compatibilityVersion = vers; }
-  void setCurrentVersion(uint32_t vers) { _currentVersion = vers; }
-  void setInstallName(StringRef name) { _installName = name; }
-  void setDeadStrippableDylib(bool deadStrippable) {
-    _deadStrippableDylib = deadStrippable;
-  }
-  void setUseFlatNamespace(bool flatNamespace) {
-    _flatNamespace = flatNamespace;
-  }
-
-  void setUndefinedMode(UndefinedMode undefinedMode) {
-    _undefinedMode = undefinedMode;
-  }
-
-  void setBundleLoader(StringRef loader) { _bundleLoader = loader; }
-  void setPrintAtoms(bool value=true) { _printAtoms = value; }
-  void setTestingFileUsage(bool value = true) {
-    _testingFileUsage = value;
-  }
-  void addExistingPathForDebug(StringRef path) {
-    _existingPaths.insert(path);
-  }
-
-  void addRpath(StringRef rpath);
-  const StringRefVector &rpaths() const { return _rpaths; }
-
-  /// Add section alignment constraint on final layout.
-  void addSectionAlignment(StringRef seg, StringRef sect, uint16_t align);
-
-  /// Add a section based on a command-line sectcreate option.
-  void addSectCreateSection(StringRef seg, StringRef sect,
-                            std::unique_ptr<MemoryBuffer> content);
-
-  /// Returns true if specified section had alignment constraints.
-  bool sectionAligned(StringRef seg, StringRef sect, uint16_t &align) const;
-
-  StringRef dyldPath() const { return "/usr/lib/dyld"; }
-
-  /// Stub creation Pass should be run.
-  bool needsStubsPass() const;
-
-  // GOT creation Pass should be run.
-  bool needsGOTPass() const;
-
-  /// Pass to add TLV sections.
-  bool needsTLVPass() const;
-
-  /// Pass to transform __compact_unwind into __unwind_info should be run.
-  bool needsCompactUnwindPass() const;
-
-  /// Pass to add shims switching between thumb and arm mode.
-  bool needsShimPass() const;
-
-  /// Pass to add objc image info and optimized objc data.
-  bool needsObjCPass() const;
-
-  /// Magic symbol name stubs will need to help lazy bind.
-  StringRef binderSymbolName() const;
-
-  /// Used to keep track of direct and indirect dylibs.
-  void registerDylib(mach_o::MachODylibFile *dylib, bool upward) const;
-
-  // Reads a file from disk to memory. Returns only a needed chunk
-  // if a fat binary.
-  ErrorOr<std::unique_ptr<MemoryBuffer>> getMemoryBuffer(StringRef path);
-
-  /// Used to find indirect dylibs. Instantiates a MachODylibFile if one
-  /// has not already been made for the requested dylib.  Uses -L and -F
-  /// search paths to allow indirect dylibs to be overridden.
-  mach_o::MachODylibFile* findIndirectDylib(StringRef path);
-
-  uint32_t dylibCurrentVersion(StringRef installName) const;
-
-  uint32_t dylibCompatVersion(StringRef installName) const;
-
-  ArrayRef<mach_o::MachODylibFile*> allDylibs() const {
-    return _allDylibs;
-  }
-
-  /// Creates a copy (owned by this MachOLinkingContext) of a string.
-  StringRef copy(StringRef str) { return str.copy(_allocator); }
-
-  /// If the memoryBuffer is a fat file with a slice for the current arch,
-  /// this method will return the offset and size of that slice.
-  bool sliceFromFatFile(MemoryBufferRef mb, uint32_t &offset, uint32_t &size);
-
-  /// Returns if a command line option specified dylib is an upward link.
-  bool isUpwardDylib(StringRef installName) const;
-
-  static bool isThinObjectFile(StringRef path, Arch &arch);
-  static Arch archFromCpuType(uint32_t cputype, uint32_t cpusubtype);
-  static Arch archFromName(StringRef archName);
-  static StringRef nameFromArch(Arch arch);
-  static uint32_t cpuTypeFromArch(Arch arch);
-  static uint32_t cpuSubtypeFromArch(Arch arch);
-  static bool is64Bit(Arch arch);
-  static bool isHostEndian(Arch arch);
-  static bool isBigEndian(Arch arch);
-
-  /// Construct 32-bit value from string "X.Y.Z" where
-  /// bits are xxxx.yy.zz.  Largest number is 65535.255.255
-  static bool parsePackedVersion(StringRef str, uint32_t &result);
-
-  /// Construct 64-bit value from string "A.B.C.D.E" where
-  /// bits are aaaa.bb.cc.dd.ee.  Largest number is 16777215.1023.1023.1023.1023
-  static bool parsePackedVersion(StringRef str, uint64_t &result);
-
-  void finalizeInputFiles() override;
-
-  llvm::Error handleLoadedFile(File &file) override;
-
-  bool customAtomOrderer(const DefinedAtom *left, const DefinedAtom *right,
-                         bool &leftBeforeRight) const;
-
-  /// Return the 'flat namespace' file. This is the file that supplies
-  /// atoms for otherwise undefined symbols when the -flat_namespace or
-  /// -undefined dynamic_lookup options are used.
-  File* flatNamespaceFile() const { return _flatNamespaceFile; }
-
-private:
-  Writer &writer() const override;
-  mach_o::MachODylibFile* loadIndirectDylib(StringRef path);
-  struct ArchInfo {
-    StringRef                 archName;
-    MachOLinkingContext::Arch arch;
-    bool                      littleEndian;
-    uint32_t                  cputype;
-    uint32_t                  cpusubtype;
-  };
-
-  struct SectionAlign {
-    StringRef segmentName;
-    StringRef sectionName;
-    uint16_t  align;
-  };
-
-  struct OrderFileNode {
-    StringRef fileFilter;
-    unsigned  order;
-  };
-
-  static bool findOrderOrdinal(const std::vector<OrderFileNode> &nodes,
-                             const DefinedAtom *atom, unsigned &ordinal);
-
-  static ArchInfo _s_archInfos[];
-
-  std::set<StringRef> _existingPaths; // For testing only.
-  StringRefVector _searchDirs;
-  StringRefVector _syslibRoots;
-  StringRefVector _frameworkDirs;
-  HeaderFileType _outputMachOType = llvm::MachO::MH_EXECUTE;
-  bool _outputMachOTypeStatic = false; // Disambiguate static vs dynamic prog
-  bool _doNothing = false;             // for -help and -v which just print info
-  bool _pie = false;
-  Arch _arch = arch_unknown;
-  OS _os = OS::macOSX;
-  uint32_t _osMinVersion = 0;
-  uint32_t _sdkVersion = 0;
-  uint64_t _sourceVersion = 0;
-  uint64_t _pageZeroSize = 0;
-  uint64_t _pageSize = 4096;
-  uint64_t _baseAddress = 0;
-  uint64_t _stackSize = 0;
-  uint32_t _compatibilityVersion = 0;
-  uint32_t _currentVersion = 0;
-  ObjCConstraint _objcConstraint = objc_unknown;
-  uint32_t _swiftVersion = 0;
-  StringRef _installName;
-  StringRefVector _rpaths;
-  bool _flatNamespace = false;
-  UndefinedMode _undefinedMode = UndefinedMode::error;
-  bool _deadStrippableDylib = false;
-  bool _printAtoms = false;
-  bool _testingFileUsage = false;
-  bool _keepPrivateExterns = false;
-  bool _demangle = false;
-  bool _mergeObjCCategories = true;
-  bool _generateVersionLoadCommand = false;
-  bool _generateFunctionStartsLoadCommand = false;
-  bool _generateDataInCodeLoadCommand = false;
-  StringRef _bundleLoader;
-  mutable std::unique_ptr<mach_o::ArchHandler> _archHandler;
-  mutable std::unique_ptr<Writer> _writer;
-  std::vector<SectionAlign> _sectAligns;
-  mutable llvm::StringMap<mach_o::MachODylibFile*> _pathToDylibMap;
-  mutable std::vector<mach_o::MachODylibFile*> _allDylibs;
-  mutable std::set<mach_o::MachODylibFile*> _upwardDylibs;
-  mutable std::vector<std::unique_ptr<File>> _indirectDylibs;
-  mutable std::mutex _dylibsMutex;
-  ExportMode _exportMode = ExportMode::globals;
-  llvm::StringSet<> _exportedSymbols;
-  DebugInfoMode _debugInfoMode = DebugInfoMode::addDebugMap;
-  std::unique_ptr<llvm::raw_fd_ostream> _dependencyInfo;
-  llvm::StringMap<std::vector<OrderFileNode>> _orderFiles;
-  unsigned _orderFileEntries = 0;
-  File *_flatNamespaceFile = nullptr;
-  mach_o::SectCreateFile *_sectCreateFile = nullptr;
-};
-
-} // end namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_LINKING_CONTEXT_H
diff --git a/gnu/llvm/lld/include/lld/ReaderWriter/YamlContext.h b/gnu/llvm/lld/include/lld/ReaderWriter/YamlContext.h
deleted file mode 100644 (file)
index dc133e3..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-//===- lld/ReaderWriter/YamlContext.h - object used in YAML I/O context ---===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_YAML_CONTEXT_H
-#define LLD_READER_WRITER_YAML_CONTEXT_H
-
-#include "lld/Common/LLVM.h"
-#include <functional>
-#include <memory>
-#include <vector>
-
-namespace lld {
-class File;
-class LinkingContext;
-class Registry;
-namespace mach_o {
-namespace normalized {
-struct NormalizedFile;
-}
-}
-
-using lld::mach_o::normalized::NormalizedFile;
-
-/// When YAML I/O is used in lld, the yaml context always holds a YamlContext
-/// object.  We need to support hetergenous yaml documents which each require
-/// different context info.  This struct supports all clients.
-struct YamlContext {
-  const LinkingContext *_ctx = nullptr;
-  const Registry *_registry = nullptr;
-  File *_file = nullptr;
-  NormalizedFile *_normalizeMachOFile = nullptr;
-  StringRef _path;
-};
-
-} // end namespace lld
-
-#endif // LLD_READER_WRITER_YAML_CONTEXT_H
diff --git a/gnu/llvm/lld/lib/CMakeLists.txt b/gnu/llvm/lld/lib/CMakeLists.txt
deleted file mode 100644 (file)
index 8884efc..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-add_subdirectory(Core)
-add_subdirectory(Driver)
-add_subdirectory(ReaderWriter)
diff --git a/gnu/llvm/lld/lib/Core/CMakeLists.txt b/gnu/llvm/lld/lib/Core/CMakeLists.txt
deleted file mode 100644 (file)
index d5e5075..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-add_lld_library(lldCore
-  DefinedAtom.cpp
-  Error.cpp
-  File.cpp
-  LinkingContext.cpp
-  Reader.cpp
-  Resolver.cpp
-  SymbolTable.cpp
-  Writer.cpp
-
-  ADDITIONAL_HEADER_DIRS
-  ${LLD_INCLUDE_DIR}/lld/Core
-
-  LINK_COMPONENTS
-    BinaryFormat
-    MC
-    Support
-
-  LINK_LIBS
-  ${LLVM_PTHREAD_LIB}
-
-  DEPENDS
-  intrinsics_gen
-  )
diff --git a/gnu/llvm/lld/lib/Core/DefinedAtom.cpp b/gnu/llvm/lld/lib/Core/DefinedAtom.cpp
deleted file mode 100644 (file)
index 3c1eece..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-//===- DefinedAtom.cpp ------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/ErrorHandling.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-
-namespace lld {
-
-DefinedAtom::ContentPermissions DefinedAtom::permissions() const {
-  // By default base permissions on content type.
-  return permissions(this->contentType());
-}
-
-// Utility function for deriving permissions from content type
-DefinedAtom::ContentPermissions DefinedAtom::permissions(ContentType type) {
-  switch (type) {
-  case typeCode:
-  case typeResolver:
-  case typeBranchIsland:
-  case typeBranchShim:
-  case typeStub:
-  case typeStubHelper:
-  case typeMachHeader:
-    return permR_X;
-
-  case typeConstant:
-  case typeCString:
-  case typeUTF16String:
-  case typeCFI:
-  case typeLSDA:
-  case typeLiteral4:
-  case typeLiteral8:
-  case typeLiteral16:
-  case typeDTraceDOF:
-  case typeCompactUnwindInfo:
-  case typeProcessedUnwindInfo:
-  case typeObjCImageInfo:
-  case typeObjCMethodList:
-    return permR__;
-
-  case typeData:
-  case typeDataFast:
-  case typeZeroFill:
-  case typeZeroFillFast:
-  case typeObjC1Class:
-  case typeLazyPointer:
-  case typeLazyDylibPointer:
-  case typeNonLazyPointer:
-  case typeThunkTLV:
-    return permRW_;
-
-  case typeGOT:
-  case typeConstData:
-  case typeCFString:
-  case typeInitializerPtr:
-  case typeTerminatorPtr:
-  case typeCStringPtr:
-  case typeObjCClassPtr:
-  case typeObjC2CategoryList:
-  case typeInterposingTuples:
-  case typeTLVInitialData:
-  case typeTLVInitialZeroFill:
-  case typeTLVInitializerPtr:
-    return permRW_L;
-
-  case typeUnknown:
-  case typeTempLTO:
-  case typeSectCreate:
-  case typeDSOHandle:
-    return permUnknown;
-  }
-  llvm_unreachable("unknown content type");
-}
-
-} // namespace
diff --git a/gnu/llvm/lld/lib/Core/Error.cpp b/gnu/llvm/lld/lib/Core/Error.cpp
deleted file mode 100644 (file)
index a4f4b1b..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-//===- Error.cpp - system_error extensions for lld --------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/Error.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <mutex>
-#include <string>
-#include <vector>
-
-using namespace lld;
-
-namespace {
-class _YamlReaderErrorCategory : public std::error_category {
-public:
-  const char* name() const noexcept override {
-    return "lld.yaml.reader";
-  }
-
-  std::string message(int ev) const override {
-    switch (static_cast<YamlReaderError>(ev)) {
-    case YamlReaderError::unknown_keyword:
-      return "Unknown keyword found in yaml file";
-    case YamlReaderError::illegal_value:
-      return "Bad value found in yaml file";
-    }
-    llvm_unreachable("An enumerator of YamlReaderError does not have a "
-                     "message defined.");
-  }
-};
-} // end anonymous namespace
-
-const std::error_category &lld::YamlReaderCategory() {
-  static _YamlReaderErrorCategory o;
-  return o;
-}
-
-namespace lld {
-
-/// Temporary class to enable make_dynamic_error_code() until
-/// llvm::ErrorOr<> is updated to work with error encapsulations
-/// other than error_code.
-class dynamic_error_category : public std::error_category {
-public:
-  ~dynamic_error_category() override = default;
-
-  const char *name() const noexcept override {
-    return "lld.dynamic_error";
-  }
-
-  std::string message(int ev) const override {
-    assert(ev >= 0);
-    assert(ev < (int)_messages.size());
-    // The value is an index into the string vector.
-    return _messages[ev];
-  }
-
-  int add(std::string msg) {
-    std::lock_guard<std::recursive_mutex> lock(_mutex);
-    // Value zero is always the success value.
-    if (_messages.empty())
-      _messages.push_back("Success");
-    _messages.push_back(msg);
-    // Return the index of the string just appended.
-    return _messages.size() - 1;
-  }
-
-private:
-  std::vector<std::string> _messages;
-  std::recursive_mutex _mutex;
-};
-
-static dynamic_error_category categorySingleton;
-
-std::error_code make_dynamic_error_code(StringRef msg) {
-  return std::error_code(categorySingleton.add(std::string(msg)),
-                         categorySingleton);
-}
-
-char GenericError::ID = 0;
-
-GenericError::GenericError(Twine Msg) : Msg(Msg.str()) { }
-
-void GenericError::log(raw_ostream &OS) const {
-  OS << Msg;
-}
-
-} // namespace lld
diff --git a/gnu/llvm/lld/lib/Core/File.cpp b/gnu/llvm/lld/lib/Core/File.cpp
deleted file mode 100644 (file)
index ce33923..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-//===- Core/File.cpp - A Container of Atoms -------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/File.h"
-#include <mutex>
-
-namespace lld {
-
-File::~File() = default;
-
-File::AtomVector<DefinedAtom> File::_noDefinedAtoms;
-File::AtomVector<UndefinedAtom> File::_noUndefinedAtoms;
-File::AtomVector<SharedLibraryAtom> File::_noSharedLibraryAtoms;
-File::AtomVector<AbsoluteAtom> File::_noAbsoluteAtoms;
-
-std::error_code File::parse() {
-  std::lock_guard<std::mutex> lock(_parseMutex);
-  if (!_lastError.hasValue())
-    _lastError = doParse();
-  return _lastError.getValue();
-}
-
-} // end namespace lld
diff --git a/gnu/llvm/lld/lib/Core/LinkingContext.cpp b/gnu/llvm/lld/lib/Core/LinkingContext.cpp
deleted file mode 100644 (file)
index 911ae60..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-//===- lib/Core/LinkingContext.cpp - Linker Context Object Interface ------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Node.h"
-#include "lld/Core/Simple.h"
-#include "lld/Core/Writer.h"
-#include <algorithm>
-
-namespace lld {
-
-LinkingContext::LinkingContext() = default;
-
-LinkingContext::~LinkingContext() = default;
-
-bool LinkingContext::validate() {
-  return validateImpl();
-}
-
-llvm::Error LinkingContext::writeFile(const File &linkedFile) const {
-  return this->writer().writeFile(linkedFile, _outputPath);
-}
-
-std::unique_ptr<File> LinkingContext::createEntrySymbolFile() const {
-  return createEntrySymbolFile("<command line option -e>");
-}
-
-std::unique_ptr<File>
-LinkingContext::createEntrySymbolFile(StringRef filename) const {
-  if (entrySymbolName().empty())
-    return nullptr;
-  std::unique_ptr<SimpleFile> entryFile(new SimpleFile(filename,
-                                                       File::kindEntryObject));
-  entryFile->addAtom(
-      *(new (_allocator) SimpleUndefinedAtom(*entryFile, entrySymbolName())));
-  return std::move(entryFile);
-}
-
-std::unique_ptr<File> LinkingContext::createUndefinedSymbolFile() const {
-  return createUndefinedSymbolFile("<command line option -u or --defsym>");
-}
-
-std::unique_ptr<File>
-LinkingContext::createUndefinedSymbolFile(StringRef filename) const {
-  if (_initialUndefinedSymbols.empty())
-    return nullptr;
-  std::unique_ptr<SimpleFile> undefinedSymFile(
-    new SimpleFile(filename, File::kindUndefinedSymsObject));
-  for (StringRef undefSym : _initialUndefinedSymbols)
-    undefinedSymFile->addAtom(*(new (_allocator) SimpleUndefinedAtom(
-                                   *undefinedSymFile, undefSym)));
-  return std::move(undefinedSymFile);
-}
-
-void LinkingContext::createInternalFiles(
-    std::vector<std::unique_ptr<File>> &result) const {
-  if (std::unique_ptr<File> file = createEntrySymbolFile())
-    result.push_back(std::move(file));
-  if (std::unique_ptr<File> file = createUndefinedSymbolFile())
-    result.push_back(std::move(file));
-}
-
-} // end namespace lld
diff --git a/gnu/llvm/lld/lib/Core/Reader.cpp b/gnu/llvm/lld/lib/Core/Reader.cpp
deleted file mode 100644 (file)
index 3592d87..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-//===- lib/Core/Reader.cpp ------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/Reader.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reference.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/BinaryFormat/Magic.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include <algorithm>
-#include <memory>
-
-using llvm::file_magic;
-using llvm::identify_magic;
-
-namespace lld {
-
-YamlIOTaggedDocumentHandler::~YamlIOTaggedDocumentHandler() = default;
-
-void Registry::add(std::unique_ptr<Reader> reader) {
-  _readers.push_back(std::move(reader));
-}
-
-void Registry::add(std::unique_ptr<YamlIOTaggedDocumentHandler> handler) {
-  _yamlHandlers.push_back(std::move(handler));
-}
-
-ErrorOr<std::unique_ptr<File>>
-Registry::loadFile(std::unique_ptr<MemoryBuffer> mb) const {
-  // Get file magic.
-  StringRef content(mb->getBufferStart(), mb->getBufferSize());
-  file_magic fileType = identify_magic(content);
-
-  // Ask each registered reader if it can handle this file type or extension.
-  for (const std::unique_ptr<Reader> &reader : _readers) {
-    if (!reader->canParse(fileType, mb->getMemBufferRef()))
-      continue;
-    return reader->loadFile(std::move(mb), *this);
-  }
-
-  // No Reader could parse this file.
-  return make_error_code(llvm::errc::executable_format_error);
-}
-
-static const Registry::KindStrings kindStrings[] = {
-    {Reference::kindLayoutAfter, "layout-after"},
-    {Reference::kindAssociate, "associate"},
-    LLD_KIND_STRING_END};
-
-Registry::Registry() {
-  addKindTable(Reference::KindNamespace::all, Reference::KindArch::all,
-               kindStrings);
-}
-
-bool Registry::handleTaggedDoc(llvm::yaml::IO &io,
-                               const lld::File *&file) const {
-  for (const std::unique_ptr<YamlIOTaggedDocumentHandler> &h : _yamlHandlers)
-    if (h->handledDocTag(io, file))
-      return true;
-  return false;
-}
-
-void Registry::addKindTable(Reference::KindNamespace ns,
-                            Reference::KindArch arch,
-                            const KindStrings array[]) {
-  KindEntry entry = { ns, arch, array };
-  _kindEntries.push_back(entry);
-}
-
-bool Registry::referenceKindFromString(StringRef inputStr,
-                                       Reference::KindNamespace &ns,
-                                       Reference::KindArch &arch,
-                                       Reference::KindValue &value) const {
-  for (const KindEntry &entry : _kindEntries) {
-    for (const KindStrings *pair = entry.array; !pair->name.empty(); ++pair) {
-      if (!inputStr.equals(pair->name))
-        continue;
-      ns = entry.ns;
-      arch = entry.arch;
-      value = pair->value;
-      return true;
-    }
-  }
-  return false;
-}
-
-bool Registry::referenceKindToString(Reference::KindNamespace ns,
-                                     Reference::KindArch arch,
-                                     Reference::KindValue value,
-                                     StringRef &str) const {
-  for (const KindEntry &entry : _kindEntries) {
-    if (entry.ns != ns)
-      continue;
-    if (entry.arch != arch)
-      continue;
-    for (const KindStrings *pair = entry.array; !pair->name.empty(); ++pair) {
-      if (pair->value != value)
-        continue;
-      str = pair->name;
-      return true;
-    }
-  }
-  return false;
-}
-
-} // end namespace lld
diff --git a/gnu/llvm/lld/lib/Core/Resolver.cpp b/gnu/llvm/lld/lib/Core/Resolver.cpp
deleted file mode 100644 (file)
index 17a4605..0000000
+++ /dev/null
@@ -1,503 +0,0 @@
-//===- Core/Resolver.cpp - Resolves Atom References -----------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/Resolver.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/Atom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Instrumentation.h"
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/SharedLibraryFile.h"
-#include "lld/Core/SymbolTable.h"
-#include "lld/Core/UndefinedAtom.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <utility>
-#include <vector>
-
-namespace lld {
-
-llvm::Expected<bool> Resolver::handleFile(File &file) {
-  if (auto ec = _ctx.handleLoadedFile(file))
-    return std::move(ec);
-  bool undefAdded = false;
-  for (auto &atom : file.defined().owning_ptrs())
-    doDefinedAtom(std::move(atom));
-  for (auto &atom : file.undefined().owning_ptrs()) {
-    if (doUndefinedAtom(std::move(atom)))
-      undefAdded = true;
-  }
-  for (auto &atom : file.sharedLibrary().owning_ptrs())
-    doSharedLibraryAtom(std::move(atom));
-  for (auto &atom : file.absolute().owning_ptrs())
-    doAbsoluteAtom(std::move(atom));
-  return undefAdded;
-}
-
-llvm::Expected<bool> Resolver::forEachUndefines(File &file,
-                                                UndefCallback callback) {
-  size_t i = _undefineIndex[&file];
-  bool undefAdded = false;
-  do {
-    for (; i < _undefines.size(); ++i) {
-      StringRef undefName = _undefines[i];
-      if (undefName.empty())
-        continue;
-      const Atom *atom = _symbolTable.findByName(undefName);
-      if (!isa<UndefinedAtom>(atom) || _symbolTable.isCoalescedAway(atom)) {
-        // The symbol was resolved by some other file. Cache the result.
-        _undefines[i] = "";
-        continue;
-      }
-      auto undefAddedOrError = callback(undefName);
-      if (auto ec = undefAddedOrError.takeError())
-        return std::move(ec);
-      undefAdded |= undefAddedOrError.get();
-    }
-  } while (i < _undefines.size());
-  _undefineIndex[&file] = i;
-  return undefAdded;
-}
-
-llvm::Expected<bool> Resolver::handleArchiveFile(File &file) {
-  ArchiveLibraryFile *archiveFile = cast<ArchiveLibraryFile>(&file);
-  return forEachUndefines(file,
-                          [&](StringRef undefName) -> llvm::Expected<bool> {
-    if (File *member = archiveFile->find(undefName)) {
-      member->setOrdinal(_ctx.getNextOrdinalAndIncrement());
-      return handleFile(*member);
-    }
-    return false;
-  });
-}
-
-llvm::Error Resolver::handleSharedLibrary(File &file) {
-  // Add all the atoms from the shared library
-  SharedLibraryFile *sharedLibrary = cast<SharedLibraryFile>(&file);
-  auto undefAddedOrError = handleFile(*sharedLibrary);
-  if (auto ec = undefAddedOrError.takeError())
-    return ec;
-  undefAddedOrError =
-      forEachUndefines(file, [&](StringRef undefName) -> llvm::Expected<bool> {
-        auto atom = sharedLibrary->exports(undefName);
-        if (atom.get())
-          doSharedLibraryAtom(std::move(atom));
-        return false;
-      });
-
-  if (auto ec = undefAddedOrError.takeError())
-    return ec;
-  return llvm::Error::success();
-}
-
-bool Resolver::doUndefinedAtom(OwningAtomPtr<UndefinedAtom> atom) {
-  DEBUG_WITH_TYPE("resolver", llvm::dbgs()
-                    << "       UndefinedAtom: "
-                    << llvm::format("0x%09lX", atom.get())
-                    << ", name=" << atom.get()->name() << "\n");
-
-  // tell symbol table
-  bool newUndefAdded = _symbolTable.add(*atom.get());
-  if (newUndefAdded)
-    _undefines.push_back(atom.get()->name());
-
-  // add to list of known atoms
-  _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
-
-  return newUndefAdded;
-}
-
-// Called on each atom when a file is added. Returns true if a given
-// atom is added to the symbol table.
-void Resolver::doDefinedAtom(OwningAtomPtr<DefinedAtom> atom) {
-  DEBUG_WITH_TYPE("resolver", llvm::dbgs()
-                    << "         DefinedAtom: "
-                    << llvm::format("0x%09lX", atom.get())
-                    << ", file=#"
-                    << atom.get()->file().ordinal()
-                    << ", atom=#"
-                    << atom.get()->ordinal()
-                    << ", name="
-                    << atom.get()->name()
-                    << ", type="
-                    << atom.get()->contentType()
-                    << "\n");
-
-  // An atom that should never be dead-stripped is a dead-strip root.
-  if (_ctx.deadStrip() &&
-      atom.get()->deadStrip() == DefinedAtom::deadStripNever) {
-    _deadStripRoots.insert(atom.get());
-  }
-
-  // add to list of known atoms
-  _symbolTable.add(*atom.get());
-  _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
-}
-
-void Resolver::doSharedLibraryAtom(OwningAtomPtr<SharedLibraryAtom> atom) {
-  DEBUG_WITH_TYPE("resolver", llvm::dbgs()
-                    << "   SharedLibraryAtom: "
-                    << llvm::format("0x%09lX", atom.get())
-                    << ", name="
-                    << atom.get()->name()
-                    << "\n");
-
-  // tell symbol table
-  _symbolTable.add(*atom.get());
-
-  // add to list of known atoms
-  _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
-}
-
-void Resolver::doAbsoluteAtom(OwningAtomPtr<AbsoluteAtom> atom) {
-  DEBUG_WITH_TYPE("resolver", llvm::dbgs()
-                    << "       AbsoluteAtom: "
-                    << llvm::format("0x%09lX", atom.get())
-                    << ", name="
-                    << atom.get()->name()
-                    << "\n");
-
-  // tell symbol table
-  if (atom.get()->scope() != Atom::scopeTranslationUnit)
-    _symbolTable.add(*atom.get());
-
-  // add to list of known atoms
-  _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
-}
-
-// Returns true if at least one of N previous files has created an
-// undefined symbol.
-bool Resolver::undefinesAdded(int begin, int end) {
-  std::vector<std::unique_ptr<Node>> &inputs = _ctx.getNodes();
-  for (int i = begin; i < end; ++i)
-    if (FileNode *node = dyn_cast<FileNode>(inputs[i].get()))
-      if (_newUndefinesAdded[node->getFile()])
-        return true;
-  return false;
-}
-
-File *Resolver::getFile(int &index) {
-  std::vector<std::unique_ptr<Node>> &inputs = _ctx.getNodes();
-  if ((size_t)index >= inputs.size())
-    return nullptr;
-  if (GroupEnd *group = dyn_cast<GroupEnd>(inputs[index].get())) {
-    // We are at the end of the current group. If one or more new
-    // undefined atom has been added in the last groupSize files, we
-    // reiterate over the files.
-    int size = group->getSize();
-    if (undefinesAdded(index - size, index)) {
-      index -= size;
-      return getFile(index);
-    }
-    ++index;
-    return getFile(index);
-  }
-  return cast<FileNode>(inputs[index++].get())->getFile();
-}
-
-// Keep adding atoms until _ctx.getNextFile() returns an error. This
-// function is where undefined atoms are resolved.
-bool Resolver::resolveUndefines() {
-  DEBUG_WITH_TYPE("resolver",
-                  llvm::dbgs() << "******** Resolving undefines:\n");
-  ScopedTask task(getDefaultDomain(), "resolveUndefines");
-  int index = 0;
-  std::set<File *> seen;
-  for (;;) {
-    bool undefAdded = false;
-    DEBUG_WITH_TYPE("resolver",
-                    llvm::dbgs() << "Loading file #" << index << "\n");
-    File *file = getFile(index);
-    if (!file)
-      return true;
-    if (std::error_code ec = file->parse()) {
-      llvm::errs() << "Cannot open " + file->path() << ": " << ec.message()
-                   << "\n";
-      return false;
-    }
-    DEBUG_WITH_TYPE("resolver",
-                    llvm::dbgs() << "Loaded file: " << file->path() << "\n");
-    switch (file->kind()) {
-    case File::kindErrorObject:
-    case File::kindNormalizedObject:
-    case File::kindMachObject:
-    case File::kindCEntryObject:
-    case File::kindHeaderObject:
-    case File::kindEntryObject:
-    case File::kindUndefinedSymsObject:
-    case File::kindStubHelperObject:
-    case File::kindResolverMergedObject:
-    case File::kindSectCreateObject: {
-      // The same file may be visited more than once if the file is
-      // in --start-group and --end-group. Only library files should
-      // be processed more than once.
-      if (seen.count(file))
-        break;
-      seen.insert(file);
-      assert(!file->hasOrdinal());
-      file->setOrdinal(_ctx.getNextOrdinalAndIncrement());
-      auto undefAddedOrError = handleFile(*file);
-      if (auto EC = undefAddedOrError.takeError()) {
-        // FIXME: This should be passed to logAllUnhandledErrors but it needs
-        // to be passed a Twine instead of a string.
-        llvm::errs() << "Error in " + file->path() << ": ";
-        logAllUnhandledErrors(std::move(EC), llvm::errs(), std::string());
-        return false;
-      }
-      undefAdded = undefAddedOrError.get();
-      break;
-    }
-    case File::kindArchiveLibrary: {
-      if (!file->hasOrdinal())
-        file->setOrdinal(_ctx.getNextOrdinalAndIncrement());
-      auto undefAddedOrError = handleArchiveFile(*file);
-      if (auto EC = undefAddedOrError.takeError()) {
-        // FIXME: This should be passed to logAllUnhandledErrors but it needs
-        // to be passed a Twine instead of a string.
-        llvm::errs() << "Error in " + file->path() << ": ";
-        logAllUnhandledErrors(std::move(EC), llvm::errs(), std::string());
-        return false;
-      }
-      undefAdded = undefAddedOrError.get();
-      break;
-    }
-    case File::kindSharedLibrary:
-      if (!file->hasOrdinal())
-        file->setOrdinal(_ctx.getNextOrdinalAndIncrement());
-      if (auto EC = handleSharedLibrary(*file)) {
-        // FIXME: This should be passed to logAllUnhandledErrors but it needs
-        // to be passed a Twine instead of a string.
-        llvm::errs() << "Error in " + file->path() << ": ";
-        logAllUnhandledErrors(std::move(EC), llvm::errs(), std::string());
-        return false;
-      }
-      break;
-    }
-    _newUndefinesAdded[file] = undefAdded;
-  }
-}
-
-// switch all references to undefined or coalesced away atoms
-// to the new defined atom
-void Resolver::updateReferences() {
-  DEBUG_WITH_TYPE("resolver",
-                  llvm::dbgs() << "******** Updating references:\n");
-  ScopedTask task(getDefaultDomain(), "updateReferences");
-  for (const OwningAtomPtr<Atom> &atom : _atoms) {
-    if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom.get())) {
-      for (const Reference *ref : *defAtom) {
-        // A reference of type kindAssociate shouldn't be updated.
-        // Instead, an atom having such reference will be removed
-        // if the target atom is coalesced away, so that they will
-        // go away as a group.
-        if (ref->kindNamespace() == lld::Reference::KindNamespace::all &&
-            ref->kindValue() == lld::Reference::kindAssociate) {
-          if (_symbolTable.isCoalescedAway(atom.get()))
-            _deadAtoms.insert(ref->target());
-          continue;
-        }
-        const Atom *newTarget = _symbolTable.replacement(ref->target());
-        const_cast<Reference *>(ref)->setTarget(newTarget);
-      }
-    }
-  }
-}
-
-// For dead code stripping, recursively mark atoms "live"
-void Resolver::markLive(const Atom *atom) {
-  // Mark the atom is live. If it's already marked live, then stop recursion.
-  auto exists = _liveAtoms.insert(atom);
-  if (!exists.second)
-    return;
-
-  // Mark all atoms it references as live
-  if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom)) {
-    for (const Reference *ref : *defAtom)
-      markLive(ref->target());
-    for (auto &p : llvm::make_range(_reverseRef.equal_range(defAtom))) {
-      const Atom *target = p.second;
-      markLive(target);
-    }
-  }
-}
-
-static bool isBackref(const Reference *ref) {
-  if (ref->kindNamespace() != lld::Reference::KindNamespace::all)
-    return false;
-  return (ref->kindValue() == lld::Reference::kindLayoutAfter);
-}
-
-// remove all atoms not actually used
-void Resolver::deadStripOptimize() {
-  DEBUG_WITH_TYPE("resolver",
-                  llvm::dbgs() << "******** Dead stripping unused atoms:\n");
-  ScopedTask task(getDefaultDomain(), "deadStripOptimize");
-  // only do this optimization with -dead_strip
-  if (!_ctx.deadStrip())
-    return;
-
-  // Some type of references prevent referring atoms to be dead-striped.
-  // Make a reverse map of such references before traversing the graph.
-  // While traversing the list of atoms, mark AbsoluteAtoms as live
-  // in order to avoid reclaim.
-  for (const OwningAtomPtr<Atom> &atom : _atoms) {
-    if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom.get()))
-      for (const Reference *ref : *defAtom)
-        if (isBackref(ref))
-          _reverseRef.insert(std::make_pair(ref->target(), atom.get()));
-    if (const AbsoluteAtom *absAtom = dyn_cast<AbsoluteAtom>(atom.get()))
-      markLive(absAtom);
-  }
-
-  // By default, shared libraries are built with all globals as dead strip roots
-  if (_ctx.globalsAreDeadStripRoots())
-    for (const OwningAtomPtr<Atom> &atom : _atoms)
-      if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom.get()))
-        if (defAtom->scope() == DefinedAtom::scopeGlobal)
-          _deadStripRoots.insert(defAtom);
-
-  // Or, use list of names that are dead strip roots.
-  for (const StringRef &name : _ctx.deadStripRoots()) {
-    const Atom *symAtom = _symbolTable.findByName(name);
-    assert(symAtom);
-    _deadStripRoots.insert(symAtom);
-  }
-
-  // mark all roots as live, and recursively all atoms they reference
-  for (const Atom *dsrAtom : _deadStripRoots)
-    markLive(dsrAtom);
-
-  // now remove all non-live atoms from _atoms
-  _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(),
-                              [&](OwningAtomPtr<Atom> &a) {
-                 return _liveAtoms.count(a.get()) == 0;
-               }),
-               _atoms.end());
-}
-
-// error out if some undefines remain
-bool Resolver::checkUndefines() {
-  DEBUG_WITH_TYPE("resolver",
-                  llvm::dbgs() << "******** Checking for undefines:\n");
-
-  // build vector of remaining undefined symbols
-  std::vector<const UndefinedAtom *> undefinedAtoms = _symbolTable.undefines();
-  if (_ctx.deadStrip()) {
-    // When dead code stripping, we don't care if dead atoms are undefined.
-    undefinedAtoms.erase(
-        std::remove_if(undefinedAtoms.begin(), undefinedAtoms.end(),
-                       [&](const Atom *a) { return _liveAtoms.count(a) == 0; }),
-        undefinedAtoms.end());
-  }
-
-  if (undefinedAtoms.empty())
-    return false;
-
-  // Warn about unresolved symbols.
-  bool foundUndefines = false;
-  for (const UndefinedAtom *undef : undefinedAtoms) {
-    // Skip over a weak symbol.
-    if (undef->canBeNull() != UndefinedAtom::canBeNullNever)
-      continue;
-
-    // If this is a library and undefined symbols are allowed on the
-    // target platform, skip over it.
-    if (isa<SharedLibraryFile>(undef->file()) && _ctx.allowShlibUndefines())
-      continue;
-
-    // If the undefine is coalesced away, skip over it.
-    if (_symbolTable.isCoalescedAway(undef))
-      continue;
-
-    // Seems like this symbol is undefined. Warn that.
-    foundUndefines = true;
-    if (_ctx.printRemainingUndefines()) {
-      llvm::errs() << "Undefined symbol: " << undef->file().path() << ": "
-                   << _ctx.demangle(undef->name()) << "\n";
-    }
-  }
-  if (!foundUndefines)
-    return false;
-  if (_ctx.printRemainingUndefines())
-    llvm::errs() << "symbol(s) not found\n";
-  return true;
-}
-
-// Remove from _atoms all coalesced away atoms.
-void Resolver::removeCoalescedAwayAtoms() {
-  DEBUG_WITH_TYPE("resolver",
-                  llvm::dbgs() << "******** Removing coalesced away atoms:\n");
-  ScopedTask task(getDefaultDomain(), "removeCoalescedAwayAtoms");
-  _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(),
-                              [&](OwningAtomPtr<Atom> &a) {
-                 return _symbolTable.isCoalescedAway(a.get()) ||
-                        _deadAtoms.count(a.get());
-               }),
-               _atoms.end());
-}
-
-bool Resolver::resolve() {
-  DEBUG_WITH_TYPE("resolver",
-                  llvm::dbgs() << "******** Resolving atom references:\n");
-  if (!resolveUndefines())
-    return false;
-  updateReferences();
-  deadStripOptimize();
-  if (checkUndefines()) {
-    DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Found undefines... ");
-    if (!_ctx.allowRemainingUndefines()) {
-      DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "which we don't allow\n");
-      return false;
-    }
-    DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "which we are ok with\n");
-  }
-  removeCoalescedAwayAtoms();
-  _result->addAtoms(_atoms);
-  DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "******** Finished resolver\n");
-  return true;
-}
-
-void Resolver::MergedFile::addAtoms(
-                              llvm::MutableArrayRef<OwningAtomPtr<Atom>> all) {
-  ScopedTask task(getDefaultDomain(), "addAtoms");
-  DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Resolver final atom list:\n");
-
-  for (OwningAtomPtr<Atom> &atom : all) {
-#ifndef NDEBUG
-    if (auto *definedAtom = dyn_cast<DefinedAtom>(atom.get())) {
-      DEBUG_WITH_TYPE("resolver", llvm::dbgs()
-                      << llvm::format("    0x%09lX", definedAtom)
-                      << ", file=#"
-                      << definedAtom->file().ordinal()
-                      << ", atom=#"
-                      << definedAtom->ordinal()
-                      << ", name="
-                      << definedAtom->name()
-                      << ", type="
-                      << definedAtom->contentType()
-                      << "\n");
-    } else {
-      DEBUG_WITH_TYPE("resolver", llvm::dbgs()
-                      << llvm::format("    0x%09lX", atom.get())
-                      << ", name="
-                      << atom.get()->name()
-                      << "\n");
-    }
-#endif
-    addAtom(*atom.release());
-  }
-}
-
-} // namespace lld
diff --git a/gnu/llvm/lld/lib/Core/SymbolTable.cpp b/gnu/llvm/lld/lib/Core/SymbolTable.cpp
deleted file mode 100644 (file)
index 3ce9555..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-//===- Core/SymbolTable.cpp - Main Symbol Table ---------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/SymbolTable.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/AbsoluteAtom.h"
-#include "lld/Core/Atom.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Resolver.h"
-#include "lld/Core/SharedLibraryAtom.h"
-#include "lld/Core/UndefinedAtom.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMapInfo.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <cstdlib>
-#include <vector>
-
-namespace lld {
-bool SymbolTable::add(const UndefinedAtom &atom) { return addByName(atom); }
-
-bool SymbolTable::add(const SharedLibraryAtom &atom) { return addByName(atom); }
-
-bool SymbolTable::add(const AbsoluteAtom &atom) { return addByName(atom); }
-
-bool SymbolTable::add(const DefinedAtom &atom) {
-  if (!atom.name().empty() &&
-      atom.scope() != DefinedAtom::scopeTranslationUnit) {
-    // Named atoms cannot be merged by content.
-    assert(atom.merge() != DefinedAtom::mergeByContent);
-    // Track named atoms that are not scoped to file (static).
-    return addByName(atom);
-  }
-  if (atom.merge() == DefinedAtom::mergeByContent) {
-    // Named atoms cannot be merged by content.
-    assert(atom.name().empty());
-    // Currently only read-only constants can be merged.
-    if (atom.permissions() == DefinedAtom::permR__)
-      return addByContent(atom);
-    // TODO: support mergeByContent of data atoms by comparing content & fixups.
-  }
-  return false;
-}
-
-enum NameCollisionResolution {
-  NCR_First,
-  NCR_Second,
-  NCR_DupDef,
-  NCR_DupUndef,
-  NCR_DupShLib,
-  NCR_Error
-};
-
-static NameCollisionResolution cases[4][4] = {
-  //regular     absolute    undef      sharedLib
-  {
-    // first is regular
-    NCR_DupDef, NCR_Error,   NCR_First, NCR_First
-  },
-  {
-    // first is absolute
-    NCR_Error,  NCR_Error,  NCR_First, NCR_First
-  },
-  {
-    // first is undef
-    NCR_Second, NCR_Second, NCR_DupUndef, NCR_Second
-  },
-  {
-    // first is sharedLib
-    NCR_Second, NCR_Second, NCR_First, NCR_DupShLib
-  }
-};
-
-static NameCollisionResolution collide(Atom::Definition first,
-                                       Atom::Definition second) {
-  return cases[first][second];
-}
-
-enum MergeResolution {
-  MCR_First,
-  MCR_Second,
-  MCR_Largest,
-  MCR_SameSize,
-  MCR_Error
-};
-
-static MergeResolution mergeCases[][6] = {
-  // no          tentative      weak          weakAddress   sameNameAndSize largest
-  {MCR_Error,    MCR_First,     MCR_First,    MCR_First,    MCR_SameSize,   MCR_Largest},  // no
-  {MCR_Second,   MCR_Largest,   MCR_Second,   MCR_Second,   MCR_SameSize,   MCR_Largest},  // tentative
-  {MCR_Second,   MCR_First,     MCR_First,    MCR_Second,   MCR_SameSize,   MCR_Largest},  // weak
-  {MCR_Second,   MCR_First,     MCR_First,    MCR_First,    MCR_SameSize,   MCR_Largest},  // weakAddress
-  {MCR_SameSize, MCR_SameSize,  MCR_SameSize, MCR_SameSize, MCR_SameSize,   MCR_SameSize}, // sameSize
-  {MCR_Largest,  MCR_Largest,   MCR_Largest,  MCR_Largest,  MCR_SameSize,   MCR_Largest},  // largest
-};
-
-static MergeResolution mergeSelect(DefinedAtom::Merge first,
-                                   DefinedAtom::Merge second) {
-  assert(first != DefinedAtom::mergeByContent);
-  assert(second != DefinedAtom::mergeByContent);
-  return mergeCases[first][second];
-}
-
-bool SymbolTable::addByName(const Atom &newAtom) {
-  StringRef name = newAtom.name();
-  assert(!name.empty());
-  const Atom *existing = findByName(name);
-  if (existing == nullptr) {
-    // Name is not in symbol table yet, add it associate with this atom.
-    _nameTable[name] = &newAtom;
-    return true;
-  }
-
-  // Do nothing if the same object is added more than once.
-  if (existing == &newAtom)
-    return false;
-
-  // Name is already in symbol table and associated with another atom.
-  bool useNew = true;
-  switch (collide(existing->definition(), newAtom.definition())) {
-  case NCR_First:
-    useNew = false;
-    break;
-  case NCR_Second:
-    useNew = true;
-    break;
-  case NCR_DupDef: {
-    const auto *existingDef = cast<DefinedAtom>(existing);
-    const auto *newDef = cast<DefinedAtom>(&newAtom);
-    switch (mergeSelect(existingDef->merge(), newDef->merge())) {
-    case MCR_First:
-      useNew = false;
-      break;
-    case MCR_Second:
-      useNew = true;
-      break;
-    case MCR_Largest: {
-      uint64_t existingSize = existingDef->sectionSize();
-      uint64_t newSize = newDef->sectionSize();
-      useNew = (newSize >= existingSize);
-      break;
-    }
-    case MCR_SameSize: {
-      uint64_t existingSize = existingDef->sectionSize();
-      uint64_t newSize = newDef->sectionSize();
-      if (existingSize == newSize) {
-        useNew = true;
-        break;
-      }
-      llvm::errs() << "Size mismatch: " << existing->name() << " ("
-                   << existingSize << ") " << newAtom.name() << " (" << newSize
-                   << ")\n";
-      LLVM_FALLTHROUGH;
-    }
-    case MCR_Error:
-      llvm::errs() << "Duplicate symbols: " << existing->name() << ":"
-                   << existing->file().path() << " and " << newAtom.name()
-                   << ":" << newAtom.file().path() << "\n";
-      llvm::report_fatal_error("duplicate symbol error");
-      break;
-    }
-    break;
-  }
-  case NCR_DupUndef: {
-    const UndefinedAtom* existingUndef = cast<UndefinedAtom>(existing);
-    const UndefinedAtom* newUndef = cast<UndefinedAtom>(&newAtom);
-
-    bool sameCanBeNull = (existingUndef->canBeNull() == newUndef->canBeNull());
-    if (sameCanBeNull)
-      useNew = false;
-    else
-      useNew = (newUndef->canBeNull() < existingUndef->canBeNull());
-    break;
-  }
-  case NCR_DupShLib: {
-    useNew = false;
-    break;
-  }
-  case NCR_Error:
-    llvm::errs() << "SymbolTable: error while merging " << name << "\n";
-    llvm::report_fatal_error("duplicate symbol error");
-    break;
-  }
-
-  if (useNew) {
-    // Update name table to use new atom.
-    _nameTable[name] = &newAtom;
-    // Add existing atom to replacement table.
-    _replacedAtoms[existing] = &newAtom;
-  } else {
-    // New atom is not being used.  Add it to replacement table.
-    _replacedAtoms[&newAtom] = existing;
-  }
-  return false;
-}
-
-unsigned SymbolTable::AtomMappingInfo::getHashValue(const DefinedAtom *atom) {
-  auto content = atom->rawContent();
-  return llvm::hash_combine(atom->size(),
-                            atom->contentType(),
-                            llvm::hash_combine_range(content.begin(),
-                                                     content.end()));
-}
-
-bool SymbolTable::AtomMappingInfo::isEqual(const DefinedAtom * const l,
-                                           const DefinedAtom * const r) {
-  if (l == r)
-    return true;
-  if (l == getEmptyKey() || r == getEmptyKey())
-    return false;
-  if (l == getTombstoneKey() || r == getTombstoneKey())
-    return false;
-  if (l->contentType() != r->contentType())
-    return false;
-  if (l->size() != r->size())
-    return false;
-  if (l->sectionChoice() != r->sectionChoice())
-    return false;
-  if (l->sectionChoice() == DefinedAtom::sectionCustomRequired) {
-    if (!l->customSectionName().equals(r->customSectionName()))
-      return false;
-  }
-  ArrayRef<uint8_t> lc = l->rawContent();
-  ArrayRef<uint8_t> rc = r->rawContent();
-  return memcmp(lc.data(), rc.data(), lc.size()) == 0;
-}
-
-bool SymbolTable::addByContent(const DefinedAtom &newAtom) {
-  AtomContentSet::iterator pos = _contentTable.find(&newAtom);
-  if (pos == _contentTable.end()) {
-    _contentTable.insert(&newAtom);
-    return true;
-  }
-  const Atom* existing = *pos;
-  // New atom is not being used.  Add it to replacement table.
-  _replacedAtoms[&newAtom] = existing;
-  return false;
-}
-
-const Atom *SymbolTable::findByName(StringRef sym) {
-  NameToAtom::iterator pos = _nameTable.find(sym);
-  if (pos == _nameTable.end())
-    return nullptr;
-  return pos->second;
-}
-
-const Atom *SymbolTable::replacement(const Atom *atom) {
-  // Find the replacement for a given atom. Atoms in _replacedAtoms
-  // may be chained, so find the last one.
-  for (;;) {
-    AtomToAtom::iterator pos = _replacedAtoms.find(atom);
-    if (pos == _replacedAtoms.end())
-      return atom;
-    atom = pos->second;
-  }
-}
-
-bool SymbolTable::isCoalescedAway(const Atom *atom) {
-  return _replacedAtoms.count(atom) > 0;
-}
-
-std::vector<const UndefinedAtom *> SymbolTable::undefines() {
-  std::vector<const UndefinedAtom *> ret;
-  for (auto it : _nameTable) {
-    const Atom *atom = it.second;
-    assert(atom != nullptr);
-    if (const auto *undef = dyn_cast<const UndefinedAtom>(atom))
-      if (_replacedAtoms.count(undef) == 0)
-        ret.push_back(undef);
-  }
-  return ret;
-}
-
-} // namespace lld
diff --git a/gnu/llvm/lld/lib/Core/Writer.cpp b/gnu/llvm/lld/lib/Core/Writer.cpp
deleted file mode 100644 (file)
index 12788b1..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-//===- lib/Core/Writer.cpp ------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/Writer.h"
-
-namespace lld {
-
-Writer::Writer() = default;
-
-Writer::~Writer() = default;
-
-} // end namespace lld
diff --git a/gnu/llvm/lld/lib/Driver/CMakeLists.txt b/gnu/llvm/lld/lib/Driver/CMakeLists.txt
deleted file mode 100644 (file)
index ff67c28..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-set(LLVM_TARGET_DEFINITIONS DarwinLdOptions.td)
-tablegen(LLVM DarwinLdOptions.inc -gen-opt-parser-defs)
-add_public_tablegen_target(DriverOptionsTableGen)
-
-add_lld_library(lldDriver
-  DarwinLdDriver.cpp
-
-  ADDITIONAL_HEADER_DIRS
-  ${LLD_INCLUDE_DIR}/lld/Driver
-
-  LINK_COMPONENTS
-    Option
-    Support
-
-  LINK_LIBS
-    lldCommon
-    lldCore
-    lldMachO
-    lldReaderWriter
-    lldYAML
-  )
-
-add_dependencies(lldDriver DriverOptionsTableGen)
diff --git a/gnu/llvm/lld/lib/Driver/DarwinLdDriver.cpp b/gnu/llvm/lld/lib/Driver/DarwinLdDriver.cpp
deleted file mode 100644 (file)
index 21d1257..0000000
+++ /dev/null
@@ -1,1229 +0,0 @@
-//===- lib/Driver/DarwinLdDriver.cpp --------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-///
-/// Concrete instance of the Driver for darwin's ld.
-///
-//===----------------------------------------------------------------------===//
-
-#include "lld/Common/Args.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/Error.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Instrumentation.h"
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Node.h"
-#include "lld/Core/PassManager.h"
-#include "lld/Core/Resolver.h"
-#include "lld/Core/SharedLibraryFile.h"
-#include "lld/Core/Simple.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Option/Arg.h"
-#include "llvm/Option/ArgList.h"
-#include "llvm/Option/OptTable.h"
-#include "llvm/Option/Option.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cstdint>
-#include <memory>
-#include <string>
-#include <system_error>
-#include <utility>
-#include <vector>
-
-using namespace lld;
-
-namespace {
-
-// Create enum with OPT_xxx values for each option in DarwinLdOptions.td
-enum {
-  OPT_INVALID = 0,
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELP, META, VALUES)                                             \
-  OPT_##ID,
-#include "DarwinLdOptions.inc"
-#undef OPTION
-};
-
-// Create prefix string literals used in DarwinLdOptions.td
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
-#include "DarwinLdOptions.inc"
-#undef PREFIX
-
-// Create table mapping all options defined in DarwinLdOptions.td
-static const llvm::opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {PREFIX,      NAME,      HELPTEXT,                                           \
-   METAVAR,     OPT_##ID,  llvm::opt::Option::KIND##Class,                     \
-   PARAM,       FLAGS,     OPT_##GROUP,                                        \
-   OPT_##ALIAS, ALIASARGS, VALUES},
-#include "DarwinLdOptions.inc"
-#undef OPTION
-};
-
-// Create OptTable class for parsing actual command line arguments
-class DarwinLdOptTable : public llvm::opt::OptTable {
-public:
-  DarwinLdOptTable() : OptTable(InfoTable) {}
-};
-
-static std::vector<std::unique_ptr<File>>
-makeErrorFile(StringRef path, std::error_code ec) {
-  std::vector<std::unique_ptr<File>> result;
-  result.push_back(std::make_unique<ErrorFile>(path, ec));
-  return result;
-}
-
-static std::vector<std::unique_ptr<File>>
-parseMemberFiles(std::unique_ptr<File> file) {
-  std::vector<std::unique_ptr<File>> members;
-  if (auto *archive = dyn_cast<ArchiveLibraryFile>(file.get())) {
-    if (std::error_code ec = archive->parseAllMembers(members))
-      return makeErrorFile(file->path(), ec);
-  } else {
-    members.push_back(std::move(file));
-  }
-  return members;
-}
-
-std::vector<std::unique_ptr<File>> loadFile(MachOLinkingContext &ctx,
-                                            StringRef path, bool wholeArchive,
-                                            bool upwardDylib) {
-  if (ctx.logInputFiles())
-    message(path);
-
-  ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr = ctx.getMemoryBuffer(path);
-  if (std::error_code ec = mbOrErr.getError())
-    return makeErrorFile(path, ec);
-  ErrorOr<std::unique_ptr<File>> fileOrErr =
-      ctx.registry().loadFile(std::move(mbOrErr.get()));
-  if (std::error_code ec = fileOrErr.getError())
-    return makeErrorFile(path, ec);
-  std::unique_ptr<File> &file = fileOrErr.get();
-
-  // If file is a dylib, inform LinkingContext about it.
-  if (SharedLibraryFile *shl = dyn_cast<SharedLibraryFile>(file.get())) {
-    if (std::error_code ec = shl->parse())
-      return makeErrorFile(path, ec);
-    ctx.registerDylib(reinterpret_cast<mach_o::MachODylibFile *>(shl),
-                      upwardDylib);
-  }
-  if (wholeArchive)
-    return parseMemberFiles(std::move(file));
-  std::vector<std::unique_ptr<File>> files;
-  files.push_back(std::move(file));
-  return files;
-}
-
-} // end anonymous namespace
-
-// Test may be running on Windows. Canonicalize the path
-// separator to '/' to get consistent outputs for tests.
-static std::string canonicalizePath(StringRef path) {
-  char sep = llvm::sys::path::get_separator().front();
-  if (sep != '/') {
-    std::string fixedPath = std::string(path);
-    std::replace(fixedPath.begin(), fixedPath.end(), sep, '/');
-    return fixedPath;
-  } else {
-    return std::string(path);
-  }
-}
-
-static void addFile(StringRef path, MachOLinkingContext &ctx,
-                    bool loadWholeArchive, bool upwardDylib) {
-  std::vector<std::unique_ptr<File>> files =
-      loadFile(ctx, path, loadWholeArchive, upwardDylib);
-  for (std::unique_ptr<File> &file : files)
-    ctx.getNodes().push_back(std::make_unique<FileNode>(std::move(file)));
-}
-
-// Export lists are one symbol per line.  Blank lines are ignored.
-// Trailing comments start with #.
-static std::error_code parseExportsList(StringRef exportFilePath,
-                                        MachOLinkingContext &ctx) {
-  // Map in export list file.
-  ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
-                                   MemoryBuffer::getFileOrSTDIN(exportFilePath);
-  if (std::error_code ec = mb.getError())
-    return ec;
-  ctx.addInputFileDependency(exportFilePath);
-  StringRef buffer = mb->get()->getBuffer();
-  while (!buffer.empty()) {
-    // Split off each line in the file.
-    std::pair<StringRef, StringRef> lineAndRest = buffer.split('\n');
-    StringRef line = lineAndRest.first;
-    // Ignore trailing # comments.
-    std::pair<StringRef, StringRef> symAndComment = line.split('#');
-    StringRef sym = symAndComment.first.trim();
-    if (!sym.empty())
-      ctx.addExportSymbol(sym);
-    buffer = lineAndRest.second;
-  }
-  return std::error_code();
-}
-
-/// Order files are one symbol per line. Blank lines are ignored.
-/// Trailing comments start with #. Symbol names can be prefixed with an
-/// architecture name and/or .o leaf name.  Examples:
-///     _foo
-///     bar.o:_bar
-///     libfrob.a(bar.o):_bar
-///     x86_64:_foo64
-static std::error_code parseOrderFile(StringRef orderFilePath,
-                                      MachOLinkingContext &ctx) {
-  // Map in order file.
-  ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
-                                   MemoryBuffer::getFileOrSTDIN(orderFilePath);
-  if (std::error_code ec = mb.getError())
-    return ec;
-  ctx.addInputFileDependency(orderFilePath);
-  StringRef buffer = mb->get()->getBuffer();
-  while (!buffer.empty()) {
-    // Split off each line in the file.
-    std::pair<StringRef, StringRef> lineAndRest = buffer.split('\n');
-    StringRef line = lineAndRest.first;
-    buffer = lineAndRest.second;
-    // Ignore trailing # comments.
-    std::pair<StringRef, StringRef> symAndComment = line.split('#');
-    if (symAndComment.first.empty())
-      continue;
-    StringRef sym = symAndComment.first.trim();
-    if (sym.empty())
-      continue;
-    // Check for prefix.
-    StringRef prefix;
-    std::pair<StringRef, StringRef> prefixAndSym = sym.split(':');
-    if (!prefixAndSym.second.empty()) {
-      sym = prefixAndSym.second;
-      prefix = prefixAndSym.first;
-      if (!prefix.endswith(".o") && !prefix.endswith(".o)")) {
-        // If arch name prefix does not match arch being linked, ignore symbol.
-        if (!ctx.archName().equals(prefix))
-          continue;
-        prefix = "";
-      }
-    } else
-     sym = prefixAndSym.first;
-    if (!sym.empty()) {
-      ctx.appendOrderedSymbol(sym, prefix);
-      // llvm::errs() << sym << ", prefix=" << prefix << "\n";
-    }
-  }
-  return std::error_code();
-}
-
-//
-// There are two variants of the  -filelist option:
-//
-//   -filelist <path>
-// In this variant, the path is to a text file which contains one file path
-// per line.  There are no comments or trimming of whitespace.
-//
-//   -fileList <path>,<dir>
-// In this variant, the path is to a text file which contains a partial path
-// per line. The <dir> prefix is prepended to each partial path.
-//
-static llvm::Error loadFileList(StringRef fileListPath,
-                                MachOLinkingContext &ctx, bool forceLoad) {
-  // If there is a comma, split off <dir>.
-  std::pair<StringRef, StringRef> opt = fileListPath.split(',');
-  StringRef filePath = opt.first;
-  StringRef dirName = opt.second;
-  ctx.addInputFileDependency(filePath);
-  // Map in file list file.
-  ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
-                                        MemoryBuffer::getFileOrSTDIN(filePath);
-  if (std::error_code ec = mb.getError())
-    return llvm::errorCodeToError(ec);
-  StringRef buffer = mb->get()->getBuffer();
-  while (!buffer.empty()) {
-    // Split off each line in the file.
-    std::pair<StringRef, StringRef> lineAndRest = buffer.split('\n');
-    StringRef line = lineAndRest.first;
-    StringRef path;
-    if (!dirName.empty()) {
-      // If there is a <dir> then prepend dir to each line.
-      SmallString<256> fullPath;
-      fullPath.assign(dirName);
-      llvm::sys::path::append(fullPath, Twine(line));
-      path = ctx.copy(fullPath.str());
-    } else {
-      // No <dir> use whole line as input file path.
-      path = ctx.copy(line);
-    }
-    if (!ctx.pathExists(path)) {
-      return llvm::make_error<GenericError>(Twine("File not found '")
-                                            + path
-                                            + "'");
-    }
-    if (ctx.testingFileUsage()) {
-      message("Found filelist entry " + canonicalizePath(path));
-    }
-    addFile(path, ctx, forceLoad, false);
-    buffer = lineAndRest.second;
-  }
-  return llvm::Error::success();
-}
-
-/// Parse number assuming it is base 16, but allow 0x prefix.
-static bool parseNumberBase16(StringRef numStr, uint64_t &baseAddress) {
-  if (numStr.startswith_insensitive("0x"))
-    numStr = numStr.drop_front(2);
-  return numStr.getAsInteger(16, baseAddress);
-}
-
-static void parseLLVMOptions(const LinkingContext &ctx) {
-  // Honor -mllvm
-  if (!ctx.llvmOptions().empty()) {
-    unsigned numArgs = ctx.llvmOptions().size();
-    auto **args = new const char *[numArgs + 2];
-    args[0] = "lld (LLVM option parsing)";
-    for (unsigned i = 0; i != numArgs; ++i)
-      args[i + 1] = ctx.llvmOptions()[i];
-    args[numArgs + 1] = nullptr;
-    llvm::cl::ResetAllOptionOccurrences();
-    llvm::cl::ParseCommandLineOptions(numArgs + 1, args);
-  }
-}
-
-namespace lld {
-namespace mach_o {
-
-bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx) {
-  // Parse command line options using DarwinLdOptions.td
-  DarwinLdOptTable table;
-  unsigned missingIndex;
-  unsigned missingCount;
-  llvm::opt::InputArgList parsedArgs =
-      table.ParseArgs(args.slice(1), missingIndex, missingCount);
-  if (missingCount) {
-    error("missing arg value for '" +
-          Twine(parsedArgs.getArgString(missingIndex)) + "' expected " +
-          Twine(missingCount) + " argument(s).");
-    return false;
-  }
-
-  for (auto unknownArg : parsedArgs.filtered(OPT_UNKNOWN)) {
-    warn("ignoring unknown argument: " +
-         Twine(unknownArg->getAsString(parsedArgs)));
-  }
-
-  errorHandler().verbose = parsedArgs.hasArg(OPT_v);
-  errorHandler().errorLimit = args::getInteger(parsedArgs, OPT_error_limit, 20);
-
-  // Figure out output kind ( -dylib, -r, -bundle, -preload, or -static )
-  llvm::MachO::HeaderFileType fileType = llvm::MachO::MH_EXECUTE;
-  bool isStaticExecutable = false;
-  if (llvm::opt::Arg *kind = parsedArgs.getLastArg(
-          OPT_dylib, OPT_relocatable, OPT_bundle, OPT_static, OPT_preload)) {
-    switch (kind->getOption().getID()) {
-    case OPT_dylib:
-      fileType = llvm::MachO::MH_DYLIB;
-      break;
-    case OPT_relocatable:
-      fileType = llvm::MachO::MH_OBJECT;
-      break;
-    case OPT_bundle:
-      fileType = llvm::MachO::MH_BUNDLE;
-      break;
-    case OPT_static:
-      fileType = llvm::MachO::MH_EXECUTE;
-      isStaticExecutable = true;
-      break;
-    case OPT_preload:
-      fileType = llvm::MachO::MH_PRELOAD;
-      break;
-    }
-  }
-
-  // Handle -arch xxx
-  MachOLinkingContext::Arch arch = MachOLinkingContext::arch_unknown;
-  if (llvm::opt::Arg *archStr = parsedArgs.getLastArg(OPT_arch)) {
-    arch = MachOLinkingContext::archFromName(archStr->getValue());
-    if (arch == MachOLinkingContext::arch_unknown) {
-      error("unknown arch named '" + Twine(archStr->getValue()) + "'");
-      return false;
-    }
-  }
-  // If no -arch specified, scan input files to find first non-fat .o file.
-  if (arch == MachOLinkingContext::arch_unknown) {
-    for (auto &inFile : parsedArgs.filtered(OPT_INPUT)) {
-      // This is expensive because it opens and maps the file.  But that is
-      // ok because no -arch is rare.
-      if (MachOLinkingContext::isThinObjectFile(inFile->getValue(), arch))
-        break;
-    }
-    if (arch == MachOLinkingContext::arch_unknown &&
-        !parsedArgs.getLastArg(OPT_test_file_usage)) {
-      // If no -arch and no options at all, print usage message.
-      if (parsedArgs.size() == 0) {
-        table.printHelp(llvm::outs(),
-                        (std::string(args[0]) + " [options] file...").c_str(),
-                        "LLVM Linker", false);
-      } else {
-        error("-arch not specified and could not be inferred");
-      }
-      return false;
-    }
-  }
-
-  // Handle -macosx_version_min or -ios_version_min
-  MachOLinkingContext::OS os = MachOLinkingContext::OS::unknown;
-  uint32_t minOSVersion = 0;
-  if (llvm::opt::Arg *minOS =
-          parsedArgs.getLastArg(OPT_macosx_version_min, OPT_ios_version_min,
-                                OPT_ios_simulator_version_min)) {
-    switch (minOS->getOption().getID()) {
-    case OPT_macosx_version_min:
-      os = MachOLinkingContext::OS::macOSX;
-      if (MachOLinkingContext::parsePackedVersion(minOS->getValue(),
-                                                  minOSVersion)) {
-        error("malformed macosx_version_min value");
-        return false;
-      }
-      break;
-    case OPT_ios_version_min:
-      os = MachOLinkingContext::OS::iOS;
-      if (MachOLinkingContext::parsePackedVersion(minOS->getValue(),
-                                                  minOSVersion)) {
-        error("malformed ios_version_min value");
-        return false;
-      }
-      break;
-    case OPT_ios_simulator_version_min:
-      os = MachOLinkingContext::OS::iOS_simulator;
-      if (MachOLinkingContext::parsePackedVersion(minOS->getValue(),
-                                                  minOSVersion)) {
-        error("malformed ios_simulator_version_min value");
-        return false;
-      }
-      break;
-    }
-  } else {
-    // No min-os version on command line, check environment variables
-  }
-
-  // Handle export_dynamic
-  // FIXME: Should we warn when this applies to something other than a static
-  // executable or dylib?  Those are the only cases where this has an effect.
-  // Note, this has to come before ctx.configure() so that we get the correct
-  // value for _globalsAreDeadStripRoots.
-  bool exportDynamicSymbols = parsedArgs.hasArg(OPT_export_dynamic);
-
-  // Now that there's enough information parsed in, let the linking context
-  // set up default values.
-  ctx.configure(fileType, arch, os, minOSVersion, exportDynamicSymbols);
-
-  // Handle -e xxx
-  if (llvm::opt::Arg *entry = parsedArgs.getLastArg(OPT_entry))
-    ctx.setEntrySymbolName(entry->getValue());
-
-  // Handle -o xxx
-  if (llvm::opt::Arg *outpath = parsedArgs.getLastArg(OPT_output))
-    ctx.setOutputPath(outpath->getValue());
-  else
-    ctx.setOutputPath("a.out");
-
-  // Handle -image_base XXX and -seg1addr XXXX
-  if (llvm::opt::Arg *imageBase = parsedArgs.getLastArg(OPT_image_base)) {
-    uint64_t baseAddress;
-    if (parseNumberBase16(imageBase->getValue(), baseAddress)) {
-      error("image_base expects a hex number");
-      return false;
-    } else if (baseAddress < ctx.pageZeroSize()) {
-      error("image_base overlaps with __PAGEZERO");
-      return false;
-    } else if (baseAddress % ctx.pageSize()) {
-      error("image_base must be a multiple of page size (0x" +
-            llvm::utohexstr(ctx.pageSize()) + ")");
-      return false;
-    }
-
-    ctx.setBaseAddress(baseAddress);
-  }
-
-  // Handle -dead_strip
-  if (parsedArgs.getLastArg(OPT_dead_strip))
-    ctx.setDeadStripping(true);
-
-  bool globalWholeArchive = false;
-  // Handle -all_load
-  if (parsedArgs.getLastArg(OPT_all_load))
-    globalWholeArchive = true;
-
-  // Handle -install_name
-  if (llvm::opt::Arg *installName = parsedArgs.getLastArg(OPT_install_name))
-    ctx.setInstallName(installName->getValue());
-  else
-    ctx.setInstallName(ctx.outputPath());
-
-  // Handle -mark_dead_strippable_dylib
-  if (parsedArgs.getLastArg(OPT_mark_dead_strippable_dylib))
-    ctx.setDeadStrippableDylib(true);
-
-  // Handle -compatibility_version and -current_version
-  if (llvm::opt::Arg *vers = parsedArgs.getLastArg(OPT_compatibility_version)) {
-    if (ctx.outputMachOType() != llvm::MachO::MH_DYLIB) {
-      error("-compatibility_version can only be used with -dylib");
-      return false;
-    }
-    uint32_t parsedVers;
-    if (MachOLinkingContext::parsePackedVersion(vers->getValue(), parsedVers)) {
-      error("-compatibility_version value is malformed");
-      return false;
-    }
-    ctx.setCompatibilityVersion(parsedVers);
-  }
-
-  if (llvm::opt::Arg *vers = parsedArgs.getLastArg(OPT_current_version)) {
-    if (ctx.outputMachOType() != llvm::MachO::MH_DYLIB) {
-      error("-current_version can only be used with -dylib");
-      return false;
-    }
-    uint32_t parsedVers;
-    if (MachOLinkingContext::parsePackedVersion(vers->getValue(), parsedVers)) {
-      error("-current_version value is malformed");
-      return false;
-    }
-    ctx.setCurrentVersion(parsedVers);
-  }
-
-  // Handle -bundle_loader
-  if (llvm::opt::Arg *loader = parsedArgs.getLastArg(OPT_bundle_loader))
-    ctx.setBundleLoader(loader->getValue());
-
-  // Handle -sectalign segname sectname align
-  for (auto &alignArg : parsedArgs.filtered(OPT_sectalign)) {
-    const char* segName   = alignArg->getValue(0);
-    const char* sectName  = alignArg->getValue(1);
-    const char* alignStr  = alignArg->getValue(2);
-    if ((alignStr[0] == '0') && (alignStr[1] == 'x'))
-      alignStr += 2;
-    unsigned long long alignValue;
-    if (llvm::getAsUnsignedInteger(alignStr, 16, alignValue)) {
-      error("-sectalign alignment value '" + Twine(alignStr) +
-            "' not a valid number");
-      return false;
-    }
-    uint16_t align = 1 << llvm::countTrailingZeros(alignValue);
-    if (!llvm::isPowerOf2_64(alignValue)) {
-      std::string Msg;
-      llvm::raw_string_ostream OS(Msg);
-      OS << "alignment for '-sectalign " << segName << " " << sectName
-         << llvm::format(" 0x%llX", alignValue)
-         << "' is not a power of two, using " << llvm::format("0x%08X", align);
-      OS.flush();
-      warn(Msg);
-    }
-    ctx.addSectionAlignment(segName, sectName, align);
-  }
-
-  // Handle -mllvm
-  for (auto &llvmArg : parsedArgs.filtered(OPT_mllvm)) {
-    ctx.appendLLVMOption(llvmArg->getValue());
-  }
-
-  // Handle -print_atoms
-  if (parsedArgs.getLastArg(OPT_print_atoms))
-    ctx.setPrintAtoms();
-
-  // Handle -t (trace) option.
-  if (parsedArgs.getLastArg(OPT_t))
-    ctx.setLogInputFiles(true);
-
-  // Handle -demangle option.
-  if (parsedArgs.getLastArg(OPT_demangle))
-    ctx.setDemangleSymbols(true);
-
-  // Handle -keep_private_externs
-  if (parsedArgs.getLastArg(OPT_keep_private_externs)) {
-    ctx.setKeepPrivateExterns(true);
-    if (ctx.outputMachOType() != llvm::MachO::MH_OBJECT)
-      warn("-keep_private_externs only used in -r mode");
-  }
-
-  // Handle -dependency_info <path> used by Xcode.
-  if (llvm::opt::Arg *depInfo = parsedArgs.getLastArg(OPT_dependency_info))
-    if (std::error_code ec = ctx.createDependencyFile(depInfo->getValue()))
-      warn(ec.message() + ", processing '-dependency_info " +
-           depInfo->getValue());
-
-  // In -test_file_usage mode, we'll be given an explicit list of paths that
-  // exist. We'll also be expected to print out information about how we located
-  // libraries and so on that the user specified, but not to actually do any
-  // linking.
-  if (parsedArgs.getLastArg(OPT_test_file_usage)) {
-    ctx.setTestingFileUsage();
-
-    // With paths existing by fiat, linking is not going to end well.
-    ctx.setDoNothing(true);
-
-    // Only bother looking for an existence override if we're going to use it.
-    for (auto existingPath : parsedArgs.filtered(OPT_path_exists)) {
-      ctx.addExistingPathForDebug(existingPath->getValue());
-    }
-  }
-
-  // Register possible input file parsers.
-  if (!ctx.doNothing()) {
-    ctx.registry().addSupportMachOObjects(ctx);
-    ctx.registry().addSupportArchives(ctx.logInputFiles());
-    ctx.registry().addSupportYamlFiles();
-  }
-
-  // Now construct the set of library search directories, following ld64's
-  // baroque set of accumulated hacks. Mostly, the algorithm constructs
-  //     { syslibroots } x { libpaths }
-  //
-  // Unfortunately, there are numerous exceptions:
-  //   1. Only absolute paths get modified by syslibroot options.
-  //   2. If there is just 1 -syslibroot, system paths not found in it are
-  //      skipped.
-  //   3. If the last -syslibroot is "/", all of them are ignored entirely.
-  //   4. If { syslibroots } x path ==  {}, the original path is kept.
-  std::vector<StringRef> sysLibRoots;
-  for (auto syslibRoot : parsedArgs.filtered(OPT_syslibroot)) {
-    sysLibRoots.push_back(syslibRoot->getValue());
-  }
-  if (!sysLibRoots.empty()) {
-    // Ignore all if last -syslibroot is "/".
-    if (sysLibRoots.back() != "/")
-      ctx.setSysLibRoots(sysLibRoots);
-  }
-
-  // Paths specified with -L come first, and are not considered system paths for
-  // the case where there is precisely 1 -syslibroot.
-  for (auto libPath : parsedArgs.filtered(OPT_L)) {
-    ctx.addModifiedSearchDir(libPath->getValue());
-  }
-
-  // Process -F directories (where to look for frameworks).
-  for (auto fwPath : parsedArgs.filtered(OPT_F)) {
-    ctx.addFrameworkSearchDir(fwPath->getValue());
-  }
-
-  // -Z suppresses the standard search paths.
-  if (!parsedArgs.hasArg(OPT_Z)) {
-    ctx.addModifiedSearchDir("/usr/lib", true);
-    ctx.addModifiedSearchDir("/usr/local/lib", true);
-    ctx.addFrameworkSearchDir("/Library/Frameworks", true);
-    ctx.addFrameworkSearchDir("/System/Library/Frameworks", true);
-  }
-
-  // Now that we've constructed the final set of search paths, print out those
-  // search paths in verbose mode.
-  if (errorHandler().verbose) {
-    message("Library search paths:");
-    for (auto path : ctx.searchDirs()) {
-      message("    " + path);
-    }
-    message("Framework search paths:");
-    for (auto path : ctx.frameworkDirs()) {
-      message("    " + path);
-    }
-  }
-
-  // Handle -exported_symbols_list <file>
-  for (auto expFile : parsedArgs.filtered(OPT_exported_symbols_list)) {
-    if (ctx.exportMode() == MachOLinkingContext::ExportMode::unexported) {
-      error("-exported_symbols_list cannot be combined with "
-            "-unexported_symbol[s_list]");
-      return false;
-    }
-    ctx.setExportMode(MachOLinkingContext::ExportMode::exported);
-    if (std::error_code ec = parseExportsList(expFile->getValue(), ctx)) {
-      error(ec.message() + ", processing '-exported_symbols_list " +
-            expFile->getValue());
-      return false;
-    }
-  }
-
-  // Handle -exported_symbol <symbol>
-  for (auto symbol : parsedArgs.filtered(OPT_exported_symbol)) {
-    if (ctx.exportMode() == MachOLinkingContext::ExportMode::unexported) {
-      error("-exported_symbol cannot be combined with "
-            "-unexported_symbol[s_list]");
-      return false;
-    }
-    ctx.setExportMode(MachOLinkingContext::ExportMode::exported);
-    ctx.addExportSymbol(symbol->getValue());
-  }
-
-  // Handle -unexported_symbols_list <file>
-  for (auto expFile : parsedArgs.filtered(OPT_unexported_symbols_list)) {
-    if (ctx.exportMode() == MachOLinkingContext::ExportMode::exported) {
-      error("-unexported_symbols_list cannot be combined with "
-            "-exported_symbol[s_list]");
-      return false;
-    }
-    ctx.setExportMode(MachOLinkingContext::ExportMode::unexported);
-    if (std::error_code ec = parseExportsList(expFile->getValue(), ctx)) {
-      error(ec.message() + ", processing '-unexported_symbols_list " +
-            expFile->getValue());
-      return false;
-    }
-  }
-
-  // Handle -unexported_symbol <symbol>
-  for (auto symbol : parsedArgs.filtered(OPT_unexported_symbol)) {
-    if (ctx.exportMode() == MachOLinkingContext::ExportMode::exported) {
-      error("-unexported_symbol cannot be combined with "
-            "-exported_symbol[s_list]");
-      return false;
-    }
-    ctx.setExportMode(MachOLinkingContext::ExportMode::unexported);
-    ctx.addExportSymbol(symbol->getValue());
-  }
-
-  // Handle obosolete -multi_module and -single_module
-  if (llvm::opt::Arg *mod =
-          parsedArgs.getLastArg(OPT_multi_module, OPT_single_module)) {
-    if (mod->getOption().getID() == OPT_multi_module)
-      warn("-multi_module is obsolete and being ignored");
-    else if (ctx.outputMachOType() != llvm::MachO::MH_DYLIB)
-      warn("-single_module being ignored. It is only for use when producing a "
-           "dylib");
-  }
-
-  // Handle obsolete ObjC options: -objc_gc_compaction, -objc_gc, -objc_gc_only
-  if (parsedArgs.getLastArg(OPT_objc_gc_compaction)) {
-    error("-objc_gc_compaction is not supported");
-    return false;
-  }
-
-  if (parsedArgs.getLastArg(OPT_objc_gc)) {
-    error("-objc_gc is not supported");
-    return false;
-  }
-
-  if (parsedArgs.getLastArg(OPT_objc_gc_only)) {
-    error("-objc_gc_only is not supported");
-    return false;
-  }
-
-  // Handle -pie or -no_pie
-  if (llvm::opt::Arg *pie = parsedArgs.getLastArg(OPT_pie, OPT_no_pie)) {
-    switch (ctx.outputMachOType()) {
-    case llvm::MachO::MH_EXECUTE:
-      switch (ctx.os()) {
-      case MachOLinkingContext::OS::macOSX:
-        if ((minOSVersion < 0x000A0500) &&
-            (pie->getOption().getID() == OPT_pie)) {
-          error("-pie can only be used when targeting Mac OS X 10.5 or later");
-          return false;
-        }
-        break;
-      case MachOLinkingContext::OS::iOS:
-        if ((minOSVersion < 0x00040200) &&
-            (pie->getOption().getID() == OPT_pie)) {
-          error("-pie can only be used when targeting iOS 4.2 or later");
-          return false;
-        }
-        break;
-      case MachOLinkingContext::OS::iOS_simulator:
-        if (pie->getOption().getID() == OPT_no_pie) {
-          error("iOS simulator programs must be built PIE");
-          return false;
-        }
-        break;
-      case MachOLinkingContext::OS::unknown:
-        break;
-      }
-      ctx.setPIE(pie->getOption().getID() == OPT_pie);
-      break;
-    case llvm::MachO::MH_PRELOAD:
-      break;
-    case llvm::MachO::MH_DYLIB:
-    case llvm::MachO::MH_BUNDLE:
-      warn(pie->getSpelling() +
-           " being ignored. It is only used when linking main executables");
-      break;
-    default:
-      error(pie->getSpelling() +
-            " can only used when linking main executables");
-      return false;
-    }
-  }
-
-  // Handle -version_load_command or -no_version_load_command
-  {
-    bool flagOn = false;
-    bool flagOff = false;
-    if (auto *arg = parsedArgs.getLastArg(OPT_version_load_command,
-                                          OPT_no_version_load_command)) {
-      flagOn = arg->getOption().getID() == OPT_version_load_command;
-      flagOff = arg->getOption().getID() == OPT_no_version_load_command;
-    }
-
-    // default to adding version load command for dynamic code,
-    // static code must opt-in
-    switch (ctx.outputMachOType()) {
-      case llvm::MachO::MH_OBJECT:
-        ctx.setGenerateVersionLoadCommand(false);
-        break;
-      case llvm::MachO::MH_EXECUTE:
-        // dynamic executables default to generating a version load command,
-        // while static executables only generate it if required.
-        if (isStaticExecutable) {
-          if (flagOn)
-            ctx.setGenerateVersionLoadCommand(true);
-        } else {
-          if (!flagOff)
-            ctx.setGenerateVersionLoadCommand(true);
-        }
-        break;
-      case llvm::MachO::MH_PRELOAD:
-      case llvm::MachO::MH_KEXT_BUNDLE:
-        if (flagOn)
-          ctx.setGenerateVersionLoadCommand(true);
-        break;
-      case llvm::MachO::MH_DYLINKER:
-      case llvm::MachO::MH_DYLIB:
-      case llvm::MachO::MH_BUNDLE:
-        if (!flagOff)
-          ctx.setGenerateVersionLoadCommand(true);
-        break;
-      case llvm::MachO::MH_FVMLIB:
-      case llvm::MachO::MH_DYLDLINK:
-      case llvm::MachO::MH_DYLIB_STUB:
-      case llvm::MachO::MH_DSYM:
-        // We don't generate load commands for these file types, even if
-        // forced on.
-        break;
-    }
-  }
-
-  // Handle -function_starts or -no_function_starts
-  {
-    bool flagOn = false;
-    bool flagOff = false;
-    if (auto *arg = parsedArgs.getLastArg(OPT_function_starts,
-                                          OPT_no_function_starts)) {
-      flagOn = arg->getOption().getID() == OPT_function_starts;
-      flagOff = arg->getOption().getID() == OPT_no_function_starts;
-    }
-
-    // default to adding functions start for dynamic code, static code must
-    // opt-in
-    switch (ctx.outputMachOType()) {
-      case llvm::MachO::MH_OBJECT:
-        ctx.setGenerateFunctionStartsLoadCommand(false);
-        break;
-      case llvm::MachO::MH_EXECUTE:
-        // dynamic executables default to generating a version load command,
-        // while static executables only generate it if required.
-        if (isStaticExecutable) {
-          if (flagOn)
-            ctx.setGenerateFunctionStartsLoadCommand(true);
-        } else {
-          if (!flagOff)
-            ctx.setGenerateFunctionStartsLoadCommand(true);
-        }
-        break;
-      case llvm::MachO::MH_PRELOAD:
-      case llvm::MachO::MH_KEXT_BUNDLE:
-        if (flagOn)
-          ctx.setGenerateFunctionStartsLoadCommand(true);
-        break;
-      case llvm::MachO::MH_DYLINKER:
-      case llvm::MachO::MH_DYLIB:
-      case llvm::MachO::MH_BUNDLE:
-        if (!flagOff)
-          ctx.setGenerateFunctionStartsLoadCommand(true);
-        break;
-      case llvm::MachO::MH_FVMLIB:
-      case llvm::MachO::MH_DYLDLINK:
-      case llvm::MachO::MH_DYLIB_STUB:
-      case llvm::MachO::MH_DSYM:
-        // We don't generate load commands for these file types, even if
-        // forced on.
-        break;
-    }
-  }
-
-  // Handle -data_in_code_info or -no_data_in_code_info
-  {
-    bool flagOn = false;
-    bool flagOff = false;
-    if (auto *arg = parsedArgs.getLastArg(OPT_data_in_code_info,
-                                          OPT_no_data_in_code_info)) {
-      flagOn = arg->getOption().getID() == OPT_data_in_code_info;
-      flagOff = arg->getOption().getID() == OPT_no_data_in_code_info;
-    }
-
-    // default to adding data in code for dynamic code, static code must
-    // opt-in
-    switch (ctx.outputMachOType()) {
-      case llvm::MachO::MH_OBJECT:
-        if (!flagOff)
-          ctx.setGenerateDataInCodeLoadCommand(true);
-        break;
-      case llvm::MachO::MH_EXECUTE:
-        // dynamic executables default to generating a version load command,
-        // while static executables only generate it if required.
-        if (isStaticExecutable) {
-          if (flagOn)
-            ctx.setGenerateDataInCodeLoadCommand(true);
-        } else {
-          if (!flagOff)
-            ctx.setGenerateDataInCodeLoadCommand(true);
-        }
-        break;
-      case llvm::MachO::MH_PRELOAD:
-      case llvm::MachO::MH_KEXT_BUNDLE:
-        if (flagOn)
-          ctx.setGenerateDataInCodeLoadCommand(true);
-        break;
-      case llvm::MachO::MH_DYLINKER:
-      case llvm::MachO::MH_DYLIB:
-      case llvm::MachO::MH_BUNDLE:
-        if (!flagOff)
-          ctx.setGenerateDataInCodeLoadCommand(true);
-        break;
-      case llvm::MachO::MH_FVMLIB:
-      case llvm::MachO::MH_DYLDLINK:
-      case llvm::MachO::MH_DYLIB_STUB:
-      case llvm::MachO::MH_DSYM:
-        // We don't generate load commands for these file types, even if
-        // forced on.
-        break;
-    }
-  }
-
-  // Handle sdk_version
-  if (llvm::opt::Arg *arg = parsedArgs.getLastArg(OPT_sdk_version)) {
-    uint32_t sdkVersion = 0;
-    if (MachOLinkingContext::parsePackedVersion(arg->getValue(),
-                                                sdkVersion)) {
-      error("malformed sdkVersion value");
-      return false;
-    }
-    ctx.setSdkVersion(sdkVersion);
-  } else if (ctx.generateVersionLoadCommand()) {
-    // If we don't have an sdk version, but were going to emit a load command
-    // with min_version, then we need to give a warning as we have no sdk
-    // version to put in that command.
-    // FIXME: We need to decide whether to make this an error.
-    warn("-sdk_version is required when emitting min version load command.  "
-         "Setting sdk version to match provided min version");
-    ctx.setSdkVersion(ctx.osMinVersion());
-  }
-
-  // Handle source_version
-  if (llvm::opt::Arg *arg = parsedArgs.getLastArg(OPT_source_version)) {
-    uint64_t version = 0;
-    if (MachOLinkingContext::parsePackedVersion(arg->getValue(),
-                                                version)) {
-      error("malformed source_version value");
-      return false;
-    }
-    ctx.setSourceVersion(version);
-  }
-
-  // Handle stack_size
-  if (llvm::opt::Arg *stackSize = parsedArgs.getLastArg(OPT_stack_size)) {
-    uint64_t stackSizeVal;
-    if (parseNumberBase16(stackSize->getValue(), stackSizeVal)) {
-      error("stack_size expects a hex number");
-      return false;
-    }
-    if ((stackSizeVal % ctx.pageSize()) != 0) {
-      error("stack_size must be a multiple of page size (0x" +
-            llvm::utohexstr(ctx.pageSize()) + ")");
-      return false;
-    }
-
-    ctx.setStackSize(stackSizeVal);
-  }
-
-  // Handle debug info handling options: -S
-  if (parsedArgs.hasArg(OPT_S))
-    ctx.setDebugInfoMode(MachOLinkingContext::DebugInfoMode::noDebugMap);
-
-  // Handle -order_file <file>
-  for (auto orderFile : parsedArgs.filtered(OPT_order_file)) {
-    if (std::error_code ec = parseOrderFile(orderFile->getValue(), ctx)) {
-      error(ec.message() + ", processing '-order_file " + orderFile->getValue()
-            + "'");
-      return false;
-    }
-  }
-
-  // Handle -flat_namespace.
-  if (llvm::opt::Arg *ns =
-          parsedArgs.getLastArg(OPT_flat_namespace, OPT_twolevel_namespace)) {
-    if (ns->getOption().getID() == OPT_flat_namespace)
-      ctx.setUseFlatNamespace(true);
-  }
-
-  // Handle -undefined
-  if (llvm::opt::Arg *undef = parsedArgs.getLastArg(OPT_undefined)) {
-    MachOLinkingContext::UndefinedMode UndefMode;
-    if (StringRef(undef->getValue()).equals("error"))
-      UndefMode = MachOLinkingContext::UndefinedMode::error;
-    else if (StringRef(undef->getValue()).equals("warning"))
-      UndefMode = MachOLinkingContext::UndefinedMode::warning;
-    else if (StringRef(undef->getValue()).equals("suppress"))
-      UndefMode = MachOLinkingContext::UndefinedMode::suppress;
-    else if (StringRef(undef->getValue()).equals("dynamic_lookup"))
-      UndefMode = MachOLinkingContext::UndefinedMode::dynamicLookup;
-    else {
-      error("invalid option to -undefined [ warning | error | suppress | "
-            "dynamic_lookup ]");
-      return false;
-    }
-
-    if (ctx.useFlatNamespace()) {
-      // If we're using -flat_namespace then 'warning', 'suppress' and
-      // 'dynamic_lookup' are all equivalent, so map them to 'suppress'.
-      if (UndefMode != MachOLinkingContext::UndefinedMode::error)
-        UndefMode = MachOLinkingContext::UndefinedMode::suppress;
-    } else {
-      // If we're using -twolevel_namespace then 'warning' and 'suppress' are
-      // illegal. Emit a diagnostic if they've been (mis)used.
-      if (UndefMode == MachOLinkingContext::UndefinedMode::warning ||
-          UndefMode == MachOLinkingContext::UndefinedMode::suppress) {
-        error("can't use -undefined warning or suppress with "
-              "-twolevel_namespace");
-        return false;
-      }
-    }
-
-    ctx.setUndefinedMode(UndefMode);
-  }
-
-  // Handle -no_objc_category_merging.
-  if (parsedArgs.getLastArg(OPT_no_objc_category_merging))
-    ctx.setMergeObjCCategories(false);
-
-  // Handle -rpath <path>
-  if (parsedArgs.hasArg(OPT_rpath)) {
-    switch (ctx.outputMachOType()) {
-      case llvm::MachO::MH_EXECUTE:
-      case llvm::MachO::MH_DYLIB:
-      case llvm::MachO::MH_BUNDLE:
-        if (!ctx.minOS("10.5", "2.0")) {
-          if (ctx.os() == MachOLinkingContext::OS::macOSX)
-            error("-rpath can only be used when targeting OS X 10.5 or later");
-          else
-            error("-rpath can only be used when targeting iOS 2.0 or later");
-          return false;
-        }
-        break;
-      default:
-        error("-rpath can only be used when creating a dynamic final linked "
-              "image");
-        return false;
-    }
-
-    for (auto rPath : parsedArgs.filtered(OPT_rpath)) {
-      ctx.addRpath(rPath->getValue());
-    }
-  }
-
-  // Parse the LLVM options before we process files in case the file handling
-  // makes use of things like LLVM_DEBUG().
-  parseLLVMOptions(ctx);
-
-  // Handle input files and sectcreate.
-  for (auto &arg : parsedArgs) {
-    bool upward;
-    llvm::Optional<StringRef> resolvedPath;
-    switch (arg->getOption().getID()) {
-    default:
-      continue;
-    case OPT_INPUT:
-      addFile(arg->getValue(), ctx, globalWholeArchive, false);
-      break;
-    case OPT_upward_library:
-      addFile(arg->getValue(), ctx, false, true);
-      break;
-    case OPT_force_load:
-      addFile(arg->getValue(), ctx, true, false);
-      break;
-    case OPT_l:
-    case OPT_upward_l:
-      upward = (arg->getOption().getID() == OPT_upward_l);
-      resolvedPath = ctx.searchLibrary(arg->getValue());
-      if (!resolvedPath) {
-        error("Unable to find library for " + arg->getSpelling() +
-              arg->getValue());
-        return false;
-      } else if (ctx.testingFileUsage()) {
-        message(Twine("Found ") + (upward ? "upward " : " ") + "library " +
-                canonicalizePath(resolvedPath.getValue()));
-      }
-      addFile(resolvedPath.getValue(), ctx, globalWholeArchive, upward);
-      break;
-    case OPT_framework:
-    case OPT_upward_framework:
-      upward = (arg->getOption().getID() == OPT_upward_framework);
-      resolvedPath = ctx.findPathForFramework(arg->getValue());
-      if (!resolvedPath) {
-        error("Unable to find framework for " + arg->getSpelling() + " " +
-              arg->getValue());
-        return false;
-      } else if (ctx.testingFileUsage()) {
-        message(Twine("Found ") + (upward ? "upward " : " ") + "framework " +
-                canonicalizePath(resolvedPath.getValue()));
-      }
-      addFile(resolvedPath.getValue(), ctx, globalWholeArchive, upward);
-      break;
-    case OPT_filelist:
-      if (auto ec = loadFileList(arg->getValue(), ctx, globalWholeArchive)) {
-        handleAllErrors(std::move(ec), [&](const llvm::ErrorInfoBase &EI) {
-          error(EI.message() + ", processing '-filelist " + arg->getValue());
-        });
-        return false;
-      }
-      break;
-    case OPT_sectcreate: {
-        const char* seg  = arg->getValue(0);
-        const char* sect = arg->getValue(1);
-        const char* fileName = arg->getValue(2);
-
-        ErrorOr<std::unique_ptr<MemoryBuffer>> contentOrErr =
-          MemoryBuffer::getFile(fileName);
-
-        if (!contentOrErr) {
-          error("can't open -sectcreate file " + Twine(fileName));
-          return false;
-        }
-
-        ctx.addSectCreateSection(seg, sect, std::move(*contentOrErr));
-      }
-      break;
-    }
-  }
-
-  if (ctx.getNodes().empty()) {
-    error("No input files");
-    return false;
-  }
-
-  // Validate the combination of options used.
-  return ctx.validate();
-}
-
-static void createFiles(MachOLinkingContext &ctx, bool Implicit) {
-  std::vector<std::unique_ptr<File>> Files;
-  if (Implicit)
-    ctx.createImplicitFiles(Files);
-  else
-    ctx.createInternalFiles(Files);
-  for (auto i = Files.rbegin(), e = Files.rend(); i != e; ++i) {
-    auto &members = ctx.getNodes();
-    members.insert(members.begin(), std::make_unique<FileNode>(std::move(*i)));
-  }
-}
-
-/// This is where the link is actually performed.
-bool link(llvm::ArrayRef<const char *> args, bool CanExitEarly,
-          raw_ostream &StdoutOS, raw_ostream &StderrOS) {
-  lld::stdoutOS = &StdoutOS;
-  lld::stderrOS = &StderrOS;
-
-  errorHandler().logName = args::getFilenameWithoutExe(args[0]);
-  errorHandler().errorLimitExceededMsg =
-      "too many errors emitted, stopping now (use "
-      "'-error-limit 0' to see all errors)";
-  errorHandler().exitEarly = CanExitEarly;
-  StderrOS.enable_colors(StderrOS.has_colors());
-
-  MachOLinkingContext ctx;
-  if (!parse(args, ctx))
-    return false;
-  if (ctx.doNothing())
-    return true;
-  if (ctx.getNodes().empty())
-    return false;
-
-  for (std::unique_ptr<Node> &ie : ctx.getNodes())
-    if (FileNode *node = dyn_cast<FileNode>(ie.get()))
-      node->getFile()->parse();
-
-  createFiles(ctx, false /* Implicit */);
-
-  // Give target a chance to add files
-  createFiles(ctx, true /* Implicit */);
-
-  // Give target a chance to postprocess input files.
-  // Mach-O uses this chance to move all object files before library files.
-  ctx.finalizeInputFiles();
-
-  // Do core linking.
-  ScopedTask resolveTask(getDefaultDomain(), "Resolve");
-  Resolver resolver(ctx);
-  if (!resolver.resolve())
-    return false;
-  SimpleFile *merged = nullptr;
-  {
-    std::unique_ptr<SimpleFile> mergedFile = resolver.resultFile();
-    merged = mergedFile.get();
-    auto &members = ctx.getNodes();
-    members.insert(members.begin(),
-                   std::make_unique<FileNode>(std::move(mergedFile)));
-  }
-  resolveTask.end();
-
-  // Run passes on linked atoms.
-  ScopedTask passTask(getDefaultDomain(), "Passes");
-  PassManager pm;
-  ctx.addPasses(pm);
-  if (auto ec = pm.runOnFile(*merged)) {
-    // FIXME: This should be passed to logAllUnhandledErrors but it needs
-    // to be passed a Twine instead of a string.
-    lld::errs() << "Failed to run passes on file '" << ctx.outputPath()
-                << "': ";
-    logAllUnhandledErrors(std::move(ec), lld::errs(), std::string());
-    return false;
-  }
-
-  passTask.end();
-
-  // Give linked atoms to Writer to generate output file.
-  ScopedTask writeTask(getDefaultDomain(), "Write");
-  if (auto ec = ctx.writeFile(*merged)) {
-    // FIXME: This should be passed to logAllUnhandledErrors but it needs
-    // to be passed a Twine instead of a string.
-    lld::errs() << "Failed to write file '" << ctx.outputPath() << "': ";
-    logAllUnhandledErrors(std::move(ec), lld::errs(), std::string());
-    return false;
-  }
-
-  // Call exit() if we can to avoid calling destructors.
-  if (CanExitEarly)
-    exitLld(errorCount() ? 1 : 0);
-
-
-  return true;
-}
-
-} // end namespace mach_o
-} // end namespace lld
diff --git a/gnu/llvm/lld/lib/Driver/DarwinLdOptions.td b/gnu/llvm/lld/lib/Driver/DarwinLdOptions.td
deleted file mode 100644 (file)
index 3bbde8b..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-include "llvm/Option/OptParser.td"
-
-
-// output kinds
-def grp_kind : OptionGroup<"outs">, HelpText<"OUTPUT KIND">;
-def relocatable : Flag<["-"], "r">,
-     HelpText<"Create relocatable object file">, Group<grp_kind>;
-def static : Flag<["-"], "static">,
-     HelpText<"Create static executable">, Group<grp_kind>;
-def dynamic : Flag<["-"], "dynamic">,
-     HelpText<"Create dynamic executable (default)">,Group<grp_kind>;
-def dylib : Flag<["-"], "dylib">,
-     HelpText<"Create dynamic library">, Group<grp_kind>;
-def bundle : Flag<["-"], "bundle">,
-     HelpText<"Create dynamic bundle">, Group<grp_kind>;
-def execute : Flag<["-"], "execute">,
-     HelpText<"Create main executable (default)">, Group<grp_kind>;
-def preload : Flag<["-"], "preload">,
-     HelpText<"Create binary for use with embedded systems">, Group<grp_kind>;
-
-// optimizations
-def grp_opts : OptionGroup<"opts">, HelpText<"OPTIMIZATIONS">;
-def dead_strip : Flag<["-"], "dead_strip">,
-     HelpText<"Remove unreference code and data">, Group<grp_opts>;
-def macosx_version_min : Separate<["-"], "macosx_version_min">,
-     MetaVarName<"<version>">,
-     HelpText<"Minimum Mac OS X version">, Group<grp_opts>;
-def ios_version_min : Separate<["-"], "ios_version_min">,
-     MetaVarName<"<version>">,
-     HelpText<"Minimum iOS version">, Group<grp_opts>;
-def iphoneos_version_min : Separate<["-"], "iphoneos_version_min">,
-     Alias<ios_version_min>;
-def ios_simulator_version_min : Separate<["-"], "ios_simulator_version_min">,
-     MetaVarName<"<version>">,
-     HelpText<"Minimum iOS simulator version">, Group<grp_opts>;
-def sdk_version : Separate<["-"], "sdk_version">,
-     MetaVarName<"<version>">,
-     HelpText<"SDK version">, Group<grp_opts>;
-def source_version : Separate<["-"], "source_version">,
-     MetaVarName<"<version>">,
-     HelpText<"Source version">, Group<grp_opts>;
-def version_load_command : Flag<["-"], "version_load_command">,
-     HelpText<"Force generation of a version load command">, Group<grp_opts>;
-def no_version_load_command : Flag<["-"], "no_version_load_command">,
-     HelpText<"Disable generation of a version load command">, Group<grp_opts>;
-def function_starts : Flag<["-"], "function_starts">,
-     HelpText<"Force generation of a function starts load command">,
-     Group<grp_opts>;
-def no_function_starts : Flag<["-"], "no_function_starts">,
-     HelpText<"Disable generation of a function starts load command">,
-     Group<grp_opts>;
-def data_in_code_info : Flag<["-"], "data_in_code_info">,
-     HelpText<"Force generation of a data in code load command">,
-     Group<grp_opts>;
-def no_data_in_code_info : Flag<["-"], "no_data_in_code_info">,
-     HelpText<"Disable generation of a data in code load command">,
-     Group<grp_opts>;
-def mllvm : Separate<["-"], "mllvm">,
-     MetaVarName<"<option>">,
-     HelpText<"Options to pass to LLVM during LTO">, Group<grp_opts>;
-def exported_symbols_list : Separate<["-"], "exported_symbols_list">,
-     MetaVarName<"<file-path>">,
-     HelpText<"Restricts which symbols will be exported">, Group<grp_opts>;
-def exported_symbol : Separate<["-"], "exported_symbol">,
-     MetaVarName<"<symbol>">,
-     HelpText<"Restricts which symbols will be exported">, Group<grp_opts>;
-def unexported_symbols_list : Separate<["-"], "unexported_symbols_list">,
-     MetaVarName<"<file-path>">,
-     HelpText<"Lists symbols that should not be exported">, Group<grp_opts>;
-def unexported_symbol : Separate<["-"], "unexported_symbol">,
-     MetaVarName<"<symbol>">,
-     HelpText<"A symbol which should not be exported">, Group<grp_opts>;
-def keep_private_externs : Flag<["-"], "keep_private_externs">,
-     HelpText<"Private extern (hidden) symbols should not be transformed "
-              "into local symbols">, Group<grp_opts>;
-def order_file : Separate<["-"], "order_file">,
-     MetaVarName<"<file-path>">,
-     HelpText<"re-order and move specified symbols to start of their section">,
-     Group<grp_opts>;
-def flat_namespace : Flag<["-"], "flat_namespace">,
-     HelpText<"Resolves symbols in any (transitively) linked dynamic libraries. "
-              "Source libraries are not recorded: dyld will re-search all "
-              "images at runtime and use the first definition found.">,
-     Group<grp_opts>;
-def twolevel_namespace : Flag<["-"], "twolevel_namespace">,
-     HelpText<"Resolves symbols in listed libraries only. Source libraries are "
-              "recorded in the symbol table.">,
-     Group<grp_opts>;
-def undefined : Separate<["-"], "undefined">,
-                MetaVarName<"<undefined>">,
-                HelpText<"Determines how undefined symbols are handled.">,
-                Group<grp_opts>;
-def no_objc_category_merging : Flag<["-"], "no_objc_category_merging">,
-     HelpText<"Disables the optimisation which merges Objective-C categories "
-              "on a class in to the class itself.">,
-     Group<grp_opts>;
-
-// main executable options
-def grp_main : OptionGroup<"opts">, HelpText<"MAIN EXECUTABLE OPTIONS">;
-def entry : Separate<["-"], "e">,
-     MetaVarName<"<entry-name>">,
-     HelpText<"entry symbol name">,Group<grp_main>;
-def pie : Flag<["-"], "pie">,
-     HelpText<"Create Position Independent Executable (for ASLR)">,
-     Group<grp_main>;
-def no_pie : Flag<["-"], "no_pie">,
-     HelpText<"Do not create Position Independent Executable">,
-     Group<grp_main>;
-def stack_size : Separate<["-"], "stack_size">,
-     HelpText<"Specifies the maximum stack size for the main thread in a program. "
-              "Must be a page-size multiple. (default=8Mb)">,
-     Group<grp_main>;
-def export_dynamic : Flag<["-"], "export_dynamic">,
-     HelpText<"Preserves all global symbols in main executables during LTO">,
-     Group<grp_main>;
-
-// dylib executable options
-def grp_dylib : OptionGroup<"opts">, HelpText<"DYLIB EXECUTABLE OPTIONS">;
-def install_name : Separate<["-"], "install_name">,
-     MetaVarName<"<path>">,
-     HelpText<"The dylib's install name">, Group<grp_dylib>;
-def mark_dead_strippable_dylib : Flag<["-"], "mark_dead_strippable_dylib">,
-     HelpText<"Marks the dylib as having no side effects during initialization">,
-     Group<grp_dylib>;
-def compatibility_version : Separate<["-"], "compatibility_version">,
-     MetaVarName<"<version>">,
-     HelpText<"The dylib's compatibility version">, Group<grp_dylib>;
-def current_version : Separate<["-"], "current_version">,
-     MetaVarName<"<version>">,
-     HelpText<"The dylib's current version">, Group<grp_dylib>;
-
-// dylib executable options - compatibility aliases
-def dylib_install_name : Separate<["-"], "dylib_install_name">,
-     Alias<install_name>;
-def dylib_compatibility_version : Separate<["-"], "dylib_compatibility_version">,
-     MetaVarName<"<version>">, Alias<compatibility_version>;
-def dylib_current_version : Separate<["-"], "dylib_current_version">,
-     MetaVarName<"<version>">, Alias<current_version>;
-
-// bundle executable options
-def grp_bundle : OptionGroup<"opts">, HelpText<"BUNDLE EXECUTABLE OPTIONS">;
-def bundle_loader : Separate<["-"], "bundle_loader">,
-     MetaVarName<"<path>">,
-     HelpText<"The executable that will be loading this Mach-O bundle">,
-     Group<grp_bundle>;
-
-// library options
-def grp_libs : OptionGroup<"libs">, HelpText<"LIBRARY OPTIONS">;
-def L : JoinedOrSeparate<["-"], "L">,
-     MetaVarName<"<dir>">,
-     HelpText<"Add directory to library search path">, Group<grp_libs>;
-def F : JoinedOrSeparate<["-"], "F">,
-     MetaVarName<"<dir>">,
-     HelpText<"Add directory to framework search path">, Group<grp_libs>;
-def Z : Flag<["-"], "Z">,
-     HelpText<"Do not search standard directories for libraries or frameworks">;
-def all_load : Flag<["-"], "all_load">,
-     HelpText<"Forces all members of all static libraries to be loaded">,
-     Group<grp_libs>;
-def force_load : Separate<["-"], "force_load">,
-     MetaVarName<"<library-path>">,
-     HelpText<"Forces all members of specified static libraries to be loaded">,
-     Group<grp_libs>;
-def syslibroot : Separate<["-"], "syslibroot">, MetaVarName<"<dir>">,
-     HelpText<"Add path to SDK to all absolute library search paths">,
-     Group<grp_libs>;
-
-// Input options
-def l : Joined<["-"], "l">,
-     MetaVarName<"<libname>">,
-     HelpText<"Base name of library searched for in -L directories">;
-def upward_l : Joined<["-"], "upward-l">,
-     MetaVarName<"<libname>">,
-     HelpText<"Base name of upward library searched for in -L directories">;
-def framework : Separate<["-"], "framework">,
-     MetaVarName<"<name>">,
-     HelpText<"Base name of framework searched for in -F directories">;
-def upward_framework : Separate<["-"], "upward_framework">,
-     MetaVarName<"<name>">,
-     HelpText<"Base name of upward framework searched for in -F directories">;
-def upward_library : Separate<["-"], "upward_library">,
-     MetaVarName<"<path>">,
-     HelpText<"path to upward dylib to link with">;
-def filelist : Separate<["-"], "filelist">,
-     MetaVarName<"<path>">,
-     HelpText<"file containing paths to input files">;
-
-
-// test case options
-def print_atoms : Flag<["-"], "print_atoms">,
-     HelpText<"Emit output as yaml atoms">;
-def test_file_usage : Flag<["-"], "test_file_usage">,
-     HelpText<"Only files specified by -file_exists are considered to exist. "
-              "Print which files would be used">;
-def path_exists : Separate<["-"], "path_exists">,
-     MetaVarName<"<path>">,
-     HelpText<"Used with -test_file_usage to declare a path">;
-
-
-// general options
-def output : Separate<["-"], "o">,
-     MetaVarName<"<path>">,
-     HelpText<"Output file path">;
-def arch : Separate<["-"], "arch">,
-     MetaVarName<"<arch-name>">,
-     HelpText<"Architecture to link">;
-def sectalign : MultiArg<["-"], "sectalign", 3>,
-     MetaVarName<"<segname> <sectname> <alignment>">,
-     HelpText<"Alignment for segment/section">;
-def sectcreate : MultiArg<["-"], "sectcreate", 3>,
-     MetaVarName<"<segname> <sectname> <file>">,
-     HelpText<"Create section <segname>/<sectname> from contents of <file>">;
-def image_base : Separate<["-"], "image_base">;
-def seg1addr : Separate<["-"], "seg1addr">, Alias<image_base>;
-def demangle : Flag<["-"], "demangle">,
-     HelpText<"Demangles symbol names in errors and warnings">;
-def dependency_info : Separate<["-"], "dependency_info">,
-     MetaVarName<"<file>">,
-     HelpText<"Write binary list of files used during link">;
-def S : Flag<["-"], "S">,
-     HelpText<"Remove debug information (STABS or DWARF) from the output file">;
-def rpath : Separate<["-"], "rpath">,
-     MetaVarName<"<path>">,
-     HelpText<"Add path to the runpath search path list for image being created">;
-
-def t : Flag<["-"], "t">,
-     HelpText<"Print the names of the input files as ld processes them">;
-def v : Flag<["-"], "v">,
-     HelpText<"Print linker information">;
-def error_limit : Separate<["-", "--"], "error-limit">,
-     MetaVarName<"<number>">,
-     HelpText<"Maximum number of errors to emit before stopping (0 = no limit)">;
-
-// Ignored options
-def lto_library : Separate<["-"], "lto_library">,
-    MetaVarName<"<path>">,
-    HelpText<"Ignored for compatibility with other linkers">;
-
-// Obsolete options
-def grp_obsolete : OptionGroup<"obsolete">, HelpText<"OBSOLETE OPTIONS">;
-def single_module : Flag<["-"], "single_module">,
-     HelpText<"Default for dylibs">, Group<grp_obsolete>;
-def multi_module : Flag<["-"], "multi_module">,
-     HelpText<"Unsupported way to build dylibs">, Group<grp_obsolete>;
-def objc_gc_compaction : Flag<["-"], "objc_gc_compaction">,
-     HelpText<"Unsupported ObjC GC option">, Group<grp_obsolete>;
-def objc_gc : Flag<["-"], "objc_gc">,
-     HelpText<"Unsupported ObjC GC option">, Group<grp_obsolete>;
-def objc_gc_only : Flag<["-"], "objc_gc_only">,
-     HelpText<"Unsupported ObjC GC option">, Group<grp_obsolete>;
diff --git a/gnu/llvm/lld/lib/ReaderWriter/CMakeLists.txt b/gnu/llvm/lld/lib/ReaderWriter/CMakeLists.txt
deleted file mode 100644 (file)
index bedb836..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-add_subdirectory(MachO)
-add_subdirectory(YAML)
-
-if (MSVC)
-  add_definitions(-wd4062) # Suppress 'warning C4062: Enumerator has no associated handler in a switch statement.'
-endif()
-
-add_lld_library(lldReaderWriter
-  FileArchive.cpp
-
-  ADDITIONAL_HEADER_DIRS
-  ${LLD_INCLUDE_DIR}/lld/ReaderWriter
-
-  LINK_COMPONENTS
-    Object
-    Support
-
-  LINK_LIBS
-    lldCore
-  )
diff --git a/gnu/llvm/lld/lib/ReaderWriter/FileArchive.cpp b/gnu/llvm/lld/lib/ReaderWriter/FileArchive.cpp
deleted file mode 100644 (file)
index 98f4d06..0000000
+++ /dev/null
@@ -1,227 +0,0 @@
-//===- lib/ReaderWriter/FileArchive.cpp -----------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Common/LLVM.h"
-#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reader.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/BinaryFormat/Magic.h"
-#include "llvm/Object/Archive.h"
-#include "llvm/Object/Error.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <memory>
-#include <set>
-#include <string>
-#include <system_error>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-using llvm::object::Archive;
-using llvm::file_magic;
-using llvm::identify_magic;
-
-namespace lld {
-
-namespace {
-
-/// The FileArchive class represents an Archive Library file
-class FileArchive : public lld::ArchiveLibraryFile {
-public:
-  FileArchive(std::unique_ptr<MemoryBuffer> mb, const Registry &reg,
-              StringRef path, bool logLoading)
-      : ArchiveLibraryFile(path), _mb(std::shared_ptr<MemoryBuffer>(mb.release())),
-        _registry(reg), _logLoading(logLoading) {}
-
-  /// Check if any member of the archive contains an Atom with the
-  /// specified name and return the File object for that member, or nullptr.
-  File *find(StringRef name) override {
-    auto member = _symbolMemberMap.find(name);
-    if (member == _symbolMemberMap.end())
-      return nullptr;
-    Archive::Child c = member->second;
-
-    // Don't return a member already returned
-    Expected<StringRef> buf = c.getBuffer();
-    if (!buf) {
-      // TODO: Actually report errors helpfully.
-      consumeError(buf.takeError());
-      return nullptr;
-    }
-    const char *memberStart = buf->data();
-    if (_membersInstantiated.count(memberStart))
-      return nullptr;
-    _membersInstantiated.insert(memberStart);
-
-    std::unique_ptr<File> result;
-    if (instantiateMember(c, result))
-      return nullptr;
-
-    File *file = result.get();
-    _filesReturned.push_back(std::move(result));
-
-    // Give up the file pointer. It was stored and will be destroyed with destruction of FileArchive
-    return file;
-  }
-
-  /// parse each member
-  std::error_code
-  parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
-    if (std::error_code ec = parse())
-      return ec;
-    llvm::Error err = llvm::Error::success();
-    for (auto mf = _archive->child_begin(err), me = _archive->child_end();
-         mf != me; ++mf) {
-      std::unique_ptr<File> file;
-      if (std::error_code ec = instantiateMember(*mf, file)) {
-        // err is Success (or we wouldn't be in the loop body) but we can't
-        // return without testing or consuming it.
-        consumeError(std::move(err));
-        return ec;
-      }
-      result.push_back(std::move(file));
-    }
-    if (err)
-      return errorToErrorCode(std::move(err));
-    return std::error_code();
-  }
-
-  const AtomRange<DefinedAtom> defined() const override {
-    return _noDefinedAtoms;
-  }
-
-  const AtomRange<UndefinedAtom> undefined() const override {
-    return _noUndefinedAtoms;
-  }
-
-  const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
-    return _noSharedLibraryAtoms;
-  }
-
-  const AtomRange<AbsoluteAtom> absolute() const override {
-    return _noAbsoluteAtoms;
-  }
-
-  void clearAtoms() override {
-    _noDefinedAtoms.clear();
-    _noUndefinedAtoms.clear();
-    _noSharedLibraryAtoms.clear();
-    _noAbsoluteAtoms.clear();
-  }
-
-protected:
-  std::error_code doParse() override {
-    // Make Archive object which will be owned by FileArchive object.
-    llvm::Error Err = llvm::Error::success();
-    _archive.reset(new Archive(_mb->getMemBufferRef(), Err));
-    if (Err)
-      return errorToErrorCode(std::move(Err));
-    std::error_code ec;
-    if ((ec = buildTableOfContents()))
-      return ec;
-    return std::error_code();
-  }
-
-private:
-  std::error_code instantiateMember(Archive::Child member,
-                                    std::unique_ptr<File> &result) const {
-    Expected<llvm::MemoryBufferRef> mbOrErr = member.getMemoryBufferRef();
-    if (!mbOrErr)
-      return errorToErrorCode(mbOrErr.takeError());
-    llvm::MemoryBufferRef mb = mbOrErr.get();
-    std::string memberPath = (_archive->getFileName() + "("
-                           + mb.getBufferIdentifier() + ")").str();
-
-    if (_logLoading)
-      llvm::errs() << memberPath << "\n";
-
-    std::unique_ptr<MemoryBuffer> memberMB(MemoryBuffer::getMemBuffer(
-        mb.getBuffer(), mb.getBufferIdentifier(), false));
-
-    ErrorOr<std::unique_ptr<File>> fileOrErr =
-        _registry.loadFile(std::move(memberMB));
-    if (std::error_code ec = fileOrErr.getError())
-      return ec;
-    result = std::move(fileOrErr.get());
-    if (std::error_code ec = result->parse())
-      return ec;
-    result->setArchivePath(_archive->getFileName());
-
-    // The memory buffer is co-owned by the archive file and the children,
-    // so that the bufffer is deallocated when all the members are destructed.
-    result->setSharedMemoryBuffer(_mb);
-    return std::error_code();
-  }
-
-  std::error_code buildTableOfContents() {
-    DEBUG_WITH_TYPE("FileArchive", llvm::dbgs()
-                                       << "Table of contents for archive '"
-                                       << _archive->getFileName() << "':\n");
-    for (const Archive::Symbol &sym : _archive->symbols()) {
-      StringRef name = sym.getName();
-      Expected<Archive::Child> memberOrErr = sym.getMember();
-      if (!memberOrErr)
-        return errorToErrorCode(memberOrErr.takeError());
-      Archive::Child member = memberOrErr.get();
-      DEBUG_WITH_TYPE("FileArchive",
-                      llvm::dbgs()
-                          << llvm::format("0x%08llX ",
-                                          member.getBuffer()->data())
-                          << "'" << name << "'\n");
-      _symbolMemberMap.insert(std::make_pair(name, member));
-    }
-    return std::error_code();
-  }
-
-  typedef std::unordered_map<StringRef, Archive::Child> MemberMap;
-  typedef std::set<const char *> InstantiatedSet;
-
-  std::shared_ptr<MemoryBuffer> _mb;
-  const Registry &_registry;
-  std::unique_ptr<Archive> _archive;
-  MemberMap _symbolMemberMap;
-  InstantiatedSet _membersInstantiated;
-  bool _logLoading;
-  std::vector<std::unique_ptr<MemoryBuffer>> _memberBuffers;
-  std::vector<std::unique_ptr<File>> _filesReturned;
-};
-
-class ArchiveReader : public Reader {
-public:
-  ArchiveReader(bool logLoading) : _logLoading(logLoading) {}
-
-  bool canParse(file_magic magic, MemoryBufferRef) const override {
-    return magic == file_magic::archive;
-  }
-
-  ErrorOr<std::unique_ptr<File>> loadFile(std::unique_ptr<MemoryBuffer> mb,
-                                          const Registry &reg) const override {
-    StringRef path = mb->getBufferIdentifier();
-    std::unique_ptr<File> ret =
-        std::make_unique<FileArchive>(std::move(mb), reg, path, _logLoading);
-    return std::move(ret);
-  }
-
-private:
-  bool _logLoading;
-};
-
-} // anonymous namespace
-
-void Registry::addSupportArchives(bool logLoading) {
-  add(std::unique_ptr<Reader>(new ArchiveReader(logLoading)));
-}
-
-} // namespace lld
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/ArchHandler.cpp b/gnu/llvm/lld/lib/ReaderWriter/MachO/ArchHandler.cpp
deleted file mode 100644 (file)
index c101f3b..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-//===- lib/FileFormat/MachO/ArchHandler.cpp -------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-
-#include "ArchHandler.h"
-#include "Atoms.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Support/ErrorHandling.h"
-
-using namespace llvm::MachO;
-using namespace lld::mach_o::normalized;
-
-namespace lld {
-namespace mach_o {
-
-
-ArchHandler::ArchHandler() {
-}
-
-ArchHandler::~ArchHandler() {
-}
-
-std::unique_ptr<mach_o::ArchHandler> ArchHandler::create(
-                                               MachOLinkingContext::Arch arch) {
-  switch (arch) {
-  case MachOLinkingContext::arch_x86_64:
-    return create_x86_64();
-  case MachOLinkingContext::arch_x86:
-    return create_x86();
-  case MachOLinkingContext::arch_armv6:
-  case MachOLinkingContext::arch_armv7:
-  case MachOLinkingContext::arch_armv7s:
-    return create_arm();
-  case MachOLinkingContext::arch_arm64:
-    return create_arm64();
-  default:
-    llvm_unreachable("Unknown arch");
-  }
-}
-
-
-bool ArchHandler::isLazyPointer(const Reference &ref) {
-  // A lazy bind entry is needed for a lazy pointer.
-  const StubInfo &info = stubInfo();
-  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
-    return false;
-  if (ref.kindArch() != info.lazyPointerReferenceToFinal.arch)
-    return false;
-  return (ref.kindValue() == info.lazyPointerReferenceToFinal.kind);
-}
-
-
-ArchHandler::RelocPattern ArchHandler::relocPattern(const Relocation &reloc) {
-  assert((reloc.type & 0xFFF0) == 0);
-  uint16_t result = reloc.type;
-  if (reloc.scattered)
-    result |= rScattered;
-  if (reloc.pcRel)
-    result |= rPcRel;
-  if (reloc.isExtern)
-    result |= rExtern;
-  switch(reloc.length) {
-  case 0:
-    break;
-  case 1:
-    result |= rLength2;
-    break;
-  case 2:
-    result |= rLength4;
-    break;
-  case 3:
-    result |= rLength8;
-    break;
-  default:
-    llvm_unreachable("bad r_length");
-  }
-  return result;
-}
-
-normalized::Relocation
-ArchHandler::relocFromPattern(ArchHandler::RelocPattern pattern) {
-  normalized::Relocation result;
-  result.offset    = 0;
-  result.scattered = (pattern & rScattered);
-  result.type     = (RelocationInfoType)(pattern & 0xF);
-  result.pcRel    = (pattern & rPcRel);
-  result.isExtern = (pattern & rExtern);
-  result.value    = 0;
-  result.symbol    = 0;
-  switch (pattern & 0x300) {
-  case rLength1:
-    result.length = 0;
-    break;
-  case rLength2:
-    result.length = 1;
-    break;
-  case rLength4:
-    result.length = 2;
-    break;
-  case rLength8:
-    result.length = 3;
-    break;
-  }
-  return result;
-}
-
-void ArchHandler::appendReloc(normalized::Relocations &relocs, uint32_t offset,
-                              uint32_t symbol, uint32_t value,
-                              RelocPattern pattern) {
-  normalized::Relocation reloc = relocFromPattern(pattern);
-  reloc.offset = offset;
-  reloc.symbol = symbol;
-  reloc.value  = value;
-  relocs.push_back(reloc);
-}
-
-
-int16_t ArchHandler::readS16(const uint8_t *addr, bool isBig) {
-    return read16(addr, isBig);
-}
-
-int32_t ArchHandler::readS32(const uint8_t *addr, bool isBig) {
-  return read32(addr, isBig);
-}
-
-uint32_t ArchHandler::readU32(const uint8_t *addr, bool isBig) {
-  return read32(addr, isBig);
-}
-
-  int64_t ArchHandler::readS64(const uint8_t *addr, bool isBig) {
-  return read64(addr, isBig);
-}
-
-bool ArchHandler::isDwarfCIE(bool isBig, const DefinedAtom *atom) {
-  assert(atom->contentType() == DefinedAtom::typeCFI);
-  if (atom->rawContent().size() < sizeof(uint32_t))
-    return false;
-  uint32_t size = read32(atom->rawContent().data(), isBig);
-
-  uint32_t idOffset = sizeof(uint32_t);
-  if (size == 0xffffffffU)
-    idOffset += sizeof(uint64_t);
-
-  return read32(atom->rawContent().data() + idOffset, isBig) == 0;
-}
-
-const Atom *ArchHandler::fdeTargetFunction(const DefinedAtom *fde) {
-  for (auto ref : *fde) {
-    if (ref->kindNamespace() == Reference::KindNamespace::mach_o &&
-        ref->kindValue() == unwindRefToFunctionKind()) {
-      assert(ref->kindArch() == kindArch() && "unexpected Reference arch");
-      return ref->target();
-    }
-  }
-
-  return nullptr;
-}
-
-} // namespace mach_o
-} // namespace lld
-
-
-
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/ArchHandler.h b/gnu/llvm/lld/lib/ReaderWriter/MachO/ArchHandler.h
deleted file mode 100644 (file)
index 83646c0..0000000
+++ /dev/null
@@ -1,322 +0,0 @@
-//===- lib/FileFormat/MachO/ArchHandler.h ---------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_ARCH_HANDLER_H
-#define LLD_READER_WRITER_MACHO_ARCH_HANDLER_H
-
-#include "Atoms.h"
-#include "File.h"
-#include "MachONormalizedFile.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/Error.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/Simple.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/Triple.h"
-
-namespace lld {
-namespace mach_o {
-
-///
-/// The ArchHandler class handles all architecture specific aspects of
-/// mach-o linking.
-///
-class ArchHandler {
-public:
-  virtual ~ArchHandler();
-
-  /// There is no public interface to subclasses of ArchHandler, so this
-  /// is the only way to instantiate an ArchHandler.
-  static std::unique_ptr<ArchHandler> create(MachOLinkingContext::Arch arch);
-
-  /// Get (arch specific) kind strings used by Registry.
-  virtual const Registry::KindStrings *kindStrings() = 0;
-
-  /// Convert mach-o Arch to Reference::KindArch.
-  virtual Reference::KindArch kindArch() = 0;
-
-  /// Used by StubPass to update References to shared library functions
-  /// to be references to a stub.
-  virtual bool isCallSite(const Reference &) = 0;
-
-  /// Used by GOTPass to locate GOT References
-  virtual bool isGOTAccess(const Reference &, bool &canBypassGOT) {
-    return false;
-  }
-
-  /// Used by TLVPass to locate TLV References.
-  virtual bool isTLVAccess(const Reference &) const { return false; }
-
-  /// Used by the TLVPass to update TLV References.
-  virtual void updateReferenceToTLV(const Reference *) {}
-
-  /// Used by ShimPass to insert shims in branches that switch mode.
-  virtual bool isNonCallBranch(const Reference &) = 0;
-
-  /// Used by GOTPass to update GOT References
-  virtual void updateReferenceToGOT(const Reference *, bool targetIsNowGOT) {}
-
-  /// Does this architecture make use of __unwind_info sections for exception
-  /// handling? If so, it will need a separate pass to create them.
-  virtual bool needsCompactUnwind() = 0;
-
-  /// Returns the kind of reference to use to synthesize a 32-bit image-offset
-  /// value, used in the __unwind_info section.
-  virtual Reference::KindValue imageOffsetKind() = 0;
-
-  /// Returns the kind of reference to use to synthesize a 32-bit image-offset
-  /// indirect value. Used for personality functions in the __unwind_info
-  /// section.
-  virtual Reference::KindValue imageOffsetKindIndirect() = 0;
-
-  /// Architecture specific compact unwind type that signals __eh_frame should
-  /// actually be used.
-  virtual uint32_t dwarfCompactUnwindType() = 0;
-
-  /// Reference from an __eh_frame CIE atom to its personality function it's
-  /// describing. Usually pointer-sized and PC-relative, but differs in whether
-  /// it needs to be in relocatable objects.
-  virtual Reference::KindValue unwindRefToPersonalityFunctionKind() = 0;
-
-  /// Reference from an __eh_frame FDE to the CIE it's based on.
-  virtual Reference::KindValue unwindRefToCIEKind() = 0;
-
-  /// Reference from an __eh_frame FDE atom to the function it's
-  /// describing. Usually pointer-sized and PC-relative, but differs in whether
-  /// it needs to be in relocatable objects.
-  virtual Reference::KindValue unwindRefToFunctionKind() = 0;
-
-  /// Reference from an __unwind_info entry of dwarfCompactUnwindType to the
-  /// required __eh_frame entry. On current architectures, the low 24 bits
-  /// represent the offset of the function's FDE entry from the start of
-  /// __eh_frame.
-  virtual Reference::KindValue unwindRefToEhFrameKind() = 0;
-
-  /// Returns a pointer sized reference kind.  On 64-bit targets this will
-  /// likely be something like pointer64, and pointer32 on 32-bit targets.
-  virtual Reference::KindValue pointerKind() = 0;
-
-  virtual const Atom *fdeTargetFunction(const DefinedAtom *fde);
-
-  /// Used by normalizedFromAtoms() to know where to generated rebasing and
-  /// binding info in final executables.
-  virtual bool isPointer(const Reference &) = 0;
-
-  /// Used by normalizedFromAtoms() to know where to generated lazy binding
-  /// info in final executables.
-  virtual bool isLazyPointer(const Reference &);
-
-  /// Reference from an __stub_helper entry to the required offset of the
-  /// lazy bind commands.
-  virtual Reference::KindValue lazyImmediateLocationKind() = 0;
-
-  /// Returns true if the specified relocation is paired to the next relocation.
-  virtual bool isPairedReloc(const normalized::Relocation &) = 0;
-
-  /// Prototype for a helper function.  Given a sectionIndex and address,
-  /// finds the atom and offset with that atom of that address.
-  typedef std::function<llvm::Error (uint32_t sectionIndex, uint64_t addr,
-                        const lld::Atom **, Reference::Addend *)>
-                        FindAtomBySectionAndAddress;
-
-  /// Prototype for a helper function.  Given a symbolIndex, finds the atom
-  /// representing that symbol.
-  typedef std::function<llvm::Error (uint32_t symbolIndex,
-                        const lld::Atom **)> FindAtomBySymbolIndex;
-
-  /// Analyzes a relocation from a .o file and returns the info
-  /// (kind, target, addend) needed to instantiate a Reference.
-  /// Two helper functions are passed as parameters to find the target atom
-  /// given a symbol index or address.
-  virtual llvm::Error
-          getReferenceInfo(const normalized::Relocation &reloc,
-                           const DefinedAtom *inAtom,
-                           uint32_t offsetInAtom,
-                           uint64_t fixupAddress, bool isBigEndian,
-                           FindAtomBySectionAndAddress atomFromAddress,
-                           FindAtomBySymbolIndex atomFromSymbolIndex,
-                           Reference::KindValue *kind,
-                           const lld::Atom **target,
-                           Reference::Addend *addend) = 0;
-
-  /// Analyzes a pair of relocations from a .o file and returns the info
-  /// (kind, target, addend) needed to instantiate a Reference.
-  /// Two helper functions are passed as parameters to find the target atom
-  /// given a symbol index or address.
-  virtual llvm::Error
-      getPairReferenceInfo(const normalized::Relocation &reloc1,
-                           const normalized::Relocation &reloc2,
-                           const DefinedAtom *inAtom,
-                           uint32_t offsetInAtom,
-                           uint64_t fixupAddress, bool isBig, bool scatterable,
-                           FindAtomBySectionAndAddress atomFromAddress,
-                           FindAtomBySymbolIndex atomFromSymbolIndex,
-                           Reference::KindValue *kind,
-                           const lld::Atom **target,
-                           Reference::Addend *addend) = 0;
-
-  /// Prototype for a helper function.  Given an atom, finds the symbol table
-  /// index for it in the output file.
-  typedef std::function<uint32_t (const Atom &atom)> FindSymbolIndexForAtom;
-
-  /// Prototype for a helper function.  Given an atom, finds the index
-  /// of the section that will contain the atom.
-  typedef std::function<uint32_t (const Atom &atom)> FindSectionIndexForAtom;
-
-  /// Prototype for a helper function.  Given an atom, finds the address
-  /// assigned to it in the output file.
-  typedef std::function<uint64_t (const Atom &atom)> FindAddressForAtom;
-
-  /// Some architectures require local symbols on anonymous atoms.
-  virtual bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) {
-    return false;
-  }
-
-  /// Copy raw content then apply all fixup References on an Atom.
-  virtual void generateAtomContent(const DefinedAtom &atom, bool relocatable,
-                                   FindAddressForAtom findAddress,
-                                   FindAddressForAtom findSectionAddress,
-                                   uint64_t imageBaseAddress,
-                          llvm::MutableArrayRef<uint8_t> atomContentBuffer) = 0;
-
-  /// Used in -r mode to convert a Reference to a mach-o relocation.
-  virtual void appendSectionRelocations(const DefinedAtom &atom,
-                                        uint64_t atomSectionOffset,
-                                        const Reference &ref,
-                                        FindSymbolIndexForAtom,
-                                        FindSectionIndexForAtom,
-                                        FindAddressForAtom,
-                                        normalized::Relocations&) = 0;
-
-  /// Add arch-specific References.
-  virtual void addAdditionalReferences(MachODefinedAtom &atom) { }
-
-  // Add Reference for data-in-code marker.
-  virtual void addDataInCodeReference(MachODefinedAtom &atom, uint32_t atomOff,
-                                      uint16_t length, uint16_t kind) { }
-
-  /// Returns true if the specificed Reference value marks the start or end
-  /// of a data-in-code range in an atom.
-  virtual bool isDataInCodeTransition(Reference::KindValue refKind) {
-    return false;
-  }
-
-  /// Returns the Reference value for a Reference that marks that start of
-  /// a data-in-code range.
-  virtual Reference::KindValue dataInCodeTransitionStart(
-                                                const MachODefinedAtom &atom) {
-    return 0;
-  }
-
-  /// Returns the Reference value for a Reference that marks that end of
-  /// a data-in-code range.
-  virtual Reference::KindValue dataInCodeTransitionEnd(
-                                                const MachODefinedAtom &atom) {
-    return 0;
-  }
-
-  /// Only relevant for 32-bit arm archs.
-  virtual bool isThumbFunction(const DefinedAtom &atom) { return false; }
-
-  /// Only relevant for 32-bit arm archs.
-  virtual const DefinedAtom *createShim(MachOFile &file, bool thumbToArm,
-                                        const DefinedAtom &) {
-    llvm_unreachable("shims only support on arm");
-  }
-
-  /// Does a given unwind-cfi atom represent a CIE (as opposed to an FDE).
-  static bool isDwarfCIE(bool isBig, const DefinedAtom *atom);
-
-  struct ReferenceInfo {
-    Reference::KindArch arch;
-    uint16_t            kind;
-    uint32_t            offset;
-    int32_t             addend;
-  };
-
-  struct OptionalRefInfo {
-    bool                used;
-    uint16_t            kind;
-    uint32_t            offset;
-    int32_t             addend;
-  };
-
-  /// Table of architecture specific information for creating stubs.
-  struct StubInfo {
-    const char*     binderSymbolName;
-    ReferenceInfo   lazyPointerReferenceToHelper;
-    ReferenceInfo   lazyPointerReferenceToFinal;
-    ReferenceInfo   nonLazyPointerReferenceToBinder;
-    uint8_t         codeAlignment;
-
-    uint32_t        stubSize;
-    uint8_t         stubBytes[16];
-    ReferenceInfo   stubReferenceToLP;
-    OptionalRefInfo optStubReferenceToLP;
-
-    uint32_t        stubHelperSize;
-    uint8_t         stubHelperBytes[16];
-    ReferenceInfo   stubHelperReferenceToImm;
-    ReferenceInfo   stubHelperReferenceToHelperCommon;
-
-    DefinedAtom::ContentType stubHelperImageCacheContentType;
-
-    uint32_t        stubHelperCommonSize;
-    uint8_t         stubHelperCommonAlignment;
-    uint8_t         stubHelperCommonBytes[36];
-    ReferenceInfo   stubHelperCommonReferenceToCache;
-    OptionalRefInfo optStubHelperCommonReferenceToCache;
-    ReferenceInfo   stubHelperCommonReferenceToBinder;
-    OptionalRefInfo optStubHelperCommonReferenceToBinder;
-  };
-
-  virtual const StubInfo &stubInfo() = 0;
-
-protected:
-  ArchHandler();
-
-  static std::unique_ptr<mach_o::ArchHandler> create_x86_64();
-  static std::unique_ptr<mach_o::ArchHandler> create_x86();
-  static std::unique_ptr<mach_o::ArchHandler> create_arm();
-  static std::unique_ptr<mach_o::ArchHandler> create_arm64();
-
-  // Handy way to pack mach-o r_type and other bit fields into one 16-bit value.
-  typedef uint16_t RelocPattern;
-  enum {
-    rScattered = 0x8000,
-    rPcRel     = 0x4000,
-    rExtern    = 0x2000,
-    rLength1   = 0x0000,
-    rLength2   = 0x0100,
-    rLength4   = 0x0200,
-    rLength8   = 0x0300,
-    rLenArmLo  = rLength1,
-    rLenArmHi  = rLength2,
-    rLenThmbLo = rLength4,
-    rLenThmbHi = rLength8
-  };
-  /// Extract RelocPattern from normalized mach-o relocation.
-  static RelocPattern relocPattern(const normalized::Relocation &reloc);
-  /// Create normalized Relocation initialized from pattern.
-  static normalized::Relocation relocFromPattern(RelocPattern pattern);
-  /// One liner to add a relocation.
-  static void appendReloc(normalized::Relocations &relocs, uint32_t offset,
-                          uint32_t symbol, uint32_t value,
-                          RelocPattern pattern);
-
-
-  static int16_t  readS16(const uint8_t *addr, bool isBig);
-  static int32_t  readS32(const uint8_t *addr, bool isBig);
-  static uint32_t readU32(const uint8_t *addr, bool isBig);
-  static int64_t  readS64(const uint8_t *addr, bool isBig);
-};
-
-} // namespace mach_o
-} // namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_ARCH_HANDLER_H
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp b/gnu/llvm/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
deleted file mode 100644 (file)
index 06c98ac..0000000
+++ /dev/null
@@ -1,1522 +0,0 @@
-//===- lib/FileFormat/MachO/ArchHandler_arm.cpp ---------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "Atoms.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorHandling.h"
-
-using namespace llvm::MachO;
-using namespace lld::mach_o::normalized;
-
-namespace lld {
-namespace mach_o {
-
-using llvm::support::ulittle32_t;
-using llvm::support::little32_t;
-
-
-class ArchHandler_arm : public ArchHandler {
-public:
-  ArchHandler_arm() = default;
-  ~ArchHandler_arm() override = default;
-
-  const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
-
-  Reference::KindArch kindArch() override { return Reference::KindArch::ARM; }
-
-  const ArchHandler::StubInfo &stubInfo() override;
-  bool isCallSite(const Reference &) override;
-  bool isPointer(const Reference &) override;
-  bool isPairedReloc(const normalized::Relocation &) override;
-  bool isNonCallBranch(const Reference &) override;
-
-  bool needsCompactUnwind() override {
-    return false;
-  }
-  Reference::KindValue imageOffsetKind() override {
-    return invalid;
-  }
-  Reference::KindValue imageOffsetKindIndirect() override {
-    return invalid;
-  }
-
-  Reference::KindValue unwindRefToPersonalityFunctionKind() override {
-    return invalid;
-  }
-
-  Reference::KindValue unwindRefToCIEKind() override {
-    return invalid;
-  }
-
-  Reference::KindValue unwindRefToFunctionKind() override {
-    return invalid;
-  }
-
-  Reference::KindValue unwindRefToEhFrameKind() override {
-    return invalid;
-  }
-
-  Reference::KindValue lazyImmediateLocationKind() override {
-    return lazyImmediateLocation;
-  }
-
-  Reference::KindValue pointerKind() override {
-    return invalid;
-  }
-
-  uint32_t dwarfCompactUnwindType() override {
-    // FIXME
-    return -1;
-  }
-
-  llvm::Error getReferenceInfo(const normalized::Relocation &reloc,
-                               const DefinedAtom *inAtom,
-                               uint32_t offsetInAtom,
-                               uint64_t fixupAddress, bool swap,
-                               FindAtomBySectionAndAddress atomFromAddress,
-                               FindAtomBySymbolIndex atomFromSymbolIndex,
-                               Reference::KindValue *kind,
-                               const lld::Atom **target,
-                               Reference::Addend *addend) override;
-  llvm::Error
-      getPairReferenceInfo(const normalized::Relocation &reloc1,
-                           const normalized::Relocation &reloc2,
-                           const DefinedAtom *inAtom,
-                           uint32_t offsetInAtom,
-                           uint64_t fixupAddress, bool swap, bool scatterable,
-                           FindAtomBySectionAndAddress atomFromAddress,
-                           FindAtomBySymbolIndex atomFromSymbolIndex,
-                           Reference::KindValue *kind,
-                           const lld::Atom **target,
-                           Reference::Addend *addend) override;
-
-  void generateAtomContent(const DefinedAtom &atom, bool relocatable,
-                           FindAddressForAtom findAddress,
-                           FindAddressForAtom findSectionAddress,
-                           uint64_t imageBaseAddress,
-                           llvm::MutableArrayRef<uint8_t> atomContentBuffer) override;
-
-  void appendSectionRelocations(const DefinedAtom &atom,
-                                uint64_t atomSectionOffset,
-                                const Reference &ref,
-                                FindSymbolIndexForAtom,
-                                FindSectionIndexForAtom,
-                                FindAddressForAtom,
-                                normalized::Relocations &) override;
-
-  void addAdditionalReferences(MachODefinedAtom &atom) override;
-
-  bool isDataInCodeTransition(Reference::KindValue refKind) override {
-    switch (refKind) {
-    case modeThumbCode:
-    case modeArmCode:
-    case modeData:
-      return true;
-    default:
-      return false;
-      break;
-    }
-  }
-
-  Reference::KindValue dataInCodeTransitionStart(
-                                        const MachODefinedAtom &atom) override {
-    return modeData;
-  }
-
-  Reference::KindValue dataInCodeTransitionEnd(
-                                        const MachODefinedAtom &atom) override {
-    return atom.isThumb() ? modeThumbCode : modeArmCode;
-  }
-
-  bool isThumbFunction(const DefinedAtom &atom) override;
-  const DefinedAtom *createShim(MachOFile &file, bool thumbToArm,
-                                const DefinedAtom &) override;
-
-private:
-  friend class Thumb2ToArmShimAtom;
-  friend class ArmToThumbShimAtom;
-
-  static const Registry::KindStrings _sKindStrings[];
-  static const StubInfo              _sStubInfoArmPIC;
-
-  enum ArmKind : Reference::KindValue {
-    invalid,               /// for error condition
-
-    modeThumbCode,         /// Content starting at this offset is thumb.
-    modeArmCode,           /// Content starting at this offset is arm.
-    modeData,              /// Content starting at this offset is data.
-
-    // Kinds found in mach-o .o files:
-    thumb_bl22,            /// ex: bl _foo
-    thumb_b22,             /// ex: b _foo
-    thumb_movw,            /// ex: movw        r1, :lower16:_foo
-    thumb_movt,            /// ex: movt        r1, :lower16:_foo
-    thumb_movw_funcRel,    /// ex: movw        r1, :lower16:(_foo-(L1+4))
-    thumb_movt_funcRel,    /// ex: movt r1, :upper16:(_foo-(L1+4))
-    arm_bl24,              /// ex: bl _foo
-    arm_b24,               /// ex: b _foo
-    arm_movw,              /// ex: movw        r1, :lower16:_foo
-    arm_movt,              /// ex: movt        r1, :lower16:_foo
-    arm_movw_funcRel,      /// ex: movw        r1, :lower16:(_foo-(L1+4))
-    arm_movt_funcRel,      /// ex: movt r1, :upper16:(_foo-(L1+4))
-    pointer32,             /// ex: .long _foo
-    delta32,               /// ex: .long _foo - .
-
-    // Kinds introduced by Passes:
-    lazyPointer,           /// Location contains a lazy pointer.
-    lazyImmediateLocation, /// Location contains immediate value used in stub.
-  };
-
-  // Utility functions for inspecting/updating instructions.
-  static bool isThumbMovw(uint32_t instruction);
-  static bool isThumbMovt(uint32_t instruction);
-  static bool isArmMovw(uint32_t instruction);
-  static bool isArmMovt(uint32_t instruction);
-  static int32_t getDisplacementFromThumbBranch(uint32_t instruction, uint32_t);
-  static int32_t getDisplacementFromArmBranch(uint32_t instruction);
-  static uint16_t getWordFromThumbMov(uint32_t instruction);
-  static uint16_t getWordFromArmMov(uint32_t instruction);
-  static uint32_t clearThumbBit(uint32_t value, const Atom *target);
-  static uint32_t setDisplacementInArmBranch(uint32_t instr, int32_t disp,
-                                             bool targetIsThumb);
-  static uint32_t setDisplacementInThumbBranch(uint32_t instr, uint32_t ia,
-                                               int32_t disp, bool targetThumb);
-  static uint32_t setWordFromThumbMov(uint32_t instruction, uint16_t word);
-  static uint32_t setWordFromArmMov(uint32_t instruction, uint16_t word);
-
-  StringRef stubName(const DefinedAtom &);
-  bool useExternalRelocationTo(const Atom &target);
-
-  void applyFixupFinal(const Reference &ref, uint8_t *location,
-                       uint64_t fixupAddress, uint64_t targetAddress,
-                       uint64_t inAtomAddress, bool &thumbMode,
-                       bool targetIsThumb);
-
-  void applyFixupRelocatable(const Reference &ref, uint8_t *location,
-                             uint64_t fixupAddress,
-                             uint64_t targetAddress,
-                             uint64_t inAtomAddress, bool &thumbMode,
-                             bool targetIsThumb);
-};
-
-//===----------------------------------------------------------------------===//
-//  ArchHandler_arm
-//===----------------------------------------------------------------------===//
-
-const Registry::KindStrings ArchHandler_arm::_sKindStrings[] = {
-  LLD_KIND_STRING_ENTRY(invalid),
-  LLD_KIND_STRING_ENTRY(modeThumbCode),
-  LLD_KIND_STRING_ENTRY(modeArmCode),
-  LLD_KIND_STRING_ENTRY(modeData),
-  LLD_KIND_STRING_ENTRY(thumb_bl22),
-  LLD_KIND_STRING_ENTRY(thumb_b22),
-  LLD_KIND_STRING_ENTRY(thumb_movw),
-  LLD_KIND_STRING_ENTRY(thumb_movt),
-  LLD_KIND_STRING_ENTRY(thumb_movw_funcRel),
-  LLD_KIND_STRING_ENTRY(thumb_movt_funcRel),
-  LLD_KIND_STRING_ENTRY(arm_bl24),
-  LLD_KIND_STRING_ENTRY(arm_b24),
-  LLD_KIND_STRING_ENTRY(arm_movw),
-  LLD_KIND_STRING_ENTRY(arm_movt),
-  LLD_KIND_STRING_ENTRY(arm_movw_funcRel),
-  LLD_KIND_STRING_ENTRY(arm_movt_funcRel),
-  LLD_KIND_STRING_ENTRY(pointer32),
-  LLD_KIND_STRING_ENTRY(delta32),
-  LLD_KIND_STRING_ENTRY(lazyPointer),
-  LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
-  LLD_KIND_STRING_END
-};
-
-const ArchHandler::StubInfo ArchHandler_arm::_sStubInfoArmPIC = {
-  "dyld_stub_binder",
-
-  // References in lazy pointer
-  { Reference::KindArch::ARM, pointer32, 0, 0 },
-  { Reference::KindArch::ARM, lazyPointer, 0, 0 },
-
-  // GOT pointer to dyld_stub_binder
-  { Reference::KindArch::ARM, pointer32, 0, 0 },
-
-  // arm code alignment 2^2
-  2,
-
-  // Stub size and code
-  16,
-  { 0x04, 0xC0, 0x9F, 0xE5,       //   ldr ip, pc + 12
-    0x0C, 0xC0, 0x8F, 0xE0,       //  add ip, pc, ip
-    0x00, 0xF0, 0x9C, 0xE5,       //   ldr pc, [ip]
-    0x00, 0x00, 0x00, 0x00 },     //   .long L_foo$lazy_ptr - (L1$scv + 8)
-  { Reference::KindArch::ARM, delta32, 12, 0 },
-  { false, 0, 0, 0 },
-
-  // Stub Helper size and code
-  12,
-  { 0x00, 0xC0, 0x9F, 0xE5,       // ldr   ip, [pc, #0]
-    0x00, 0x00, 0x00, 0xEA,       // b      _helperhelper
-    0x00, 0x00, 0x00, 0x00 },     // .long  lazy-info-offset
-  { Reference::KindArch::ARM, lazyImmediateLocation, 8, 0 },
-  { Reference::KindArch::ARM, arm_b24, 4, 0 },
-
-  // Stub helper image cache content type
-  DefinedAtom::typeGOT,
-
-  // Stub Helper-Common size and code
-  36,
-  // Stub helper alignment
-  2,
-       { // push lazy-info-offset
-    0x04, 0xC0, 0x2D, 0xE5,       // str ip, [sp, #-4]!
-               // push address of dyld_mageLoaderCache
-    0x10, 0xC0, 0x9F, 0xE5,       // ldr       ip, L1
-    0x0C, 0xC0, 0x8F, 0xE0,       // add       ip, pc, ip
-    0x04, 0xC0, 0x2D, 0xE5,       // str ip, [sp, #-4]!
-               // jump through dyld_stub_binder
-    0x08, 0xC0, 0x9F, 0xE5,       // ldr       ip, L2
-    0x0C, 0xC0, 0x8F, 0xE0,       // add       ip, pc, ip
-    0x00, 0xF0, 0x9C, 0xE5,       // ldr       pc, [ip]
-    0x00, 0x00, 0x00, 0x00,       // L1: .long fFastStubGOTAtom - (helper+16)
-    0x00, 0x00, 0x00, 0x00 },     // L2: .long dyld_stub_binder - (helper+28)
-  { Reference::KindArch::ARM, delta32, 28, 0xC },
-  { false, 0, 0, 0 },
-  { Reference::KindArch::ARM, delta32, 32, 0x04 },
-  { false, 0, 0, 0 }
-};
-
-const ArchHandler::StubInfo &ArchHandler_arm::stubInfo() {
-  // If multiple kinds of stubs are supported, select which StubInfo here.
-  return _sStubInfoArmPIC;
-}
-
-bool ArchHandler_arm::isCallSite(const Reference &ref) {
-  switch (ref.kindValue()) {
-  case thumb_b22:
-  case thumb_bl22:
-  case arm_b24:
-  case arm_bl24:
-    return true;
-  default:
-    return false;
-  }
-}
-
-bool ArchHandler_arm::isPointer(const Reference &ref) {
-  return (ref.kindValue() == pointer32);
-}
-
-bool ArchHandler_arm::isNonCallBranch(const Reference &ref) {
-  switch (ref.kindValue()) {
-  case thumb_b22:
-  case arm_b24:
-    return true;
-  default:
-    return false;
-  }
-}
-
-bool ArchHandler_arm::isPairedReloc(const Relocation &reloc) {
-  switch (reloc.type) {
-  case ARM_RELOC_SECTDIFF:
-  case ARM_RELOC_LOCAL_SECTDIFF:
-  case ARM_RELOC_HALF_SECTDIFF:
-  case ARM_RELOC_HALF:
-    return true;
-  default:
-    return false;
-  }
-}
-
-/// Trace references from stub atom to lazy pointer to target and get its name.
-StringRef ArchHandler_arm::stubName(const DefinedAtom &stubAtom) {
-  assert(stubAtom.contentType() == DefinedAtom::typeStub);
-  for (const Reference *ref : stubAtom) {
-    if (const DefinedAtom* lp = dyn_cast<DefinedAtom>(ref->target())) {
-      if (lp->contentType() != DefinedAtom::typeLazyPointer)
-        continue;
-      for (const Reference *ref2 : *lp) {
-        if (ref2->kindValue() != lazyPointer)
-          continue;
-        return ref2->target()->name();
-      }
-    }
-  }
-  return "stub";
-}
-
-/// Extract displacement from an ARM b/bl/blx instruction.
-int32_t ArchHandler_arm::getDisplacementFromArmBranch(uint32_t instruction) {
-  // Sign-extend imm24
-  int32_t displacement = (instruction & 0x00FFFFFF) << 2;
-  if ((displacement & 0x02000000) != 0)
-    displacement |= 0xFC000000;
-  // If this is BLX and H bit set, add 2.
-  if ((instruction & 0xFF000000) == 0xFB000000)
-    displacement += 2;
-  return displacement;
-}
-
-/// Update an ARM b/bl/blx instruction, switching bl <-> blx as needed.
-uint32_t ArchHandler_arm::setDisplacementInArmBranch(uint32_t instruction,
-                                                     int32_t displacement,
-                                                     bool targetIsThumb) {
-  assert((displacement <= 33554428) && (displacement > (-33554432))
-                                              && "arm branch out of range");
-  bool is_blx = ((instruction & 0xF0000000) == 0xF0000000);
-  uint32_t newInstruction = (instruction & 0xFF000000);
-  uint32_t h = 0;
-  if (targetIsThumb) {
-    // Force use of BLX.
-    newInstruction = 0xFA000000;
-    if (!is_blx) {
-      assert(((instruction & 0xF0000000) == 0xE0000000)
-                                                   && "no conditional arm blx");
-      assert(((instruction & 0xFF000000) == 0xEB000000)
-                                             && "no arm pc-rel BX instruction");
-    }
-    if (displacement & 2)
-      h = 1;
-  }
-  else {
-    // Force use of B/BL.
-    if (is_blx)
-      newInstruction = 0xEB000000;
-  }
-  newInstruction |= (h << 24) | ((displacement >> 2) & 0x00FFFFFF);
-  return newInstruction;
-}
-
-/// Extract displacement from a thumb b/bl/blx instruction.
-int32_t ArchHandler_arm::getDisplacementFromThumbBranch(uint32_t instruction,
-                                                        uint32_t instrAddr) {
-  bool is_blx = ((instruction & 0xD000F800) == 0xC000F000);
-  uint32_t s = (instruction >> 10) & 0x1;
-  uint32_t j1 = (instruction >> 29) & 0x1;
-  uint32_t j2 = (instruction >> 27) & 0x1;
-  uint32_t imm10 = instruction & 0x3FF;
-  uint32_t imm11 = (instruction >> 16) & 0x7FF;
-  uint32_t i1 = (j1 == s);
-  uint32_t i2 = (j2 == s);
-  uint32_t dis =
-      (s << 24) | (i1 << 23) | (i2 << 22) | (imm10 << 12) | (imm11 << 1);
-  int32_t sdis = dis;
-  int32_t result = s ? (sdis | 0xFE000000) : sdis;
-  if (is_blx && (instrAddr & 0x2)) {
-    // The thumb blx instruction always has low bit of imm11 as zero.  The way
-    // a 2-byte aligned blx can branch to a 4-byte aligned ARM target is that
-    // the blx instruction always 4-byte aligns the pc before adding the
-    // displacement from the blx.  We must emulate that when decoding this.
-    result -= 2;
-  }
-  return result;
-}
-
-/// Update a thumb b/bl/blx instruction, switching bl <-> blx as needed.
-uint32_t ArchHandler_arm::setDisplacementInThumbBranch(uint32_t instruction,
-                                                       uint32_t instrAddr,
-                                                       int32_t displacement,
-                                                       bool targetIsThumb) {
-  assert((displacement <= 16777214) && (displacement > (-16777216))
-                                              && "thumb branch out of range");
-       bool is_bl = ((instruction & 0xD000F800) == 0xD000F000);
-       bool is_blx = ((instruction & 0xD000F800) == 0xC000F000);
-       bool is_b = ((instruction & 0xD000F800) == 0x9000F000);
-  uint32_t newInstruction = (instruction & 0xD000F800);
-  if (is_bl || is_blx) {
-    if (targetIsThumb) {
-      newInstruction = 0xD000F000; // Use bl
-    } else {
-      newInstruction = 0xC000F000; // Use blx
-      // See note in getDisplacementFromThumbBranch() about blx.
-      if (instrAddr & 0x2)
-        displacement += 2;
-    }
-  } else if (is_b) {
-    assert(targetIsThumb && "no pc-rel thumb branch instruction that "
-                             "switches to arm mode");
-  }
-  else {
-    llvm_unreachable("thumb branch22 reloc on a non-branch instruction");
-  }
-  uint32_t s = (uint32_t)(displacement >> 24) & 0x1;
-  uint32_t i1 = (uint32_t)(displacement >> 23) & 0x1;
-  uint32_t i2 = (uint32_t)(displacement >> 22) & 0x1;
-  uint32_t imm10 = (uint32_t)(displacement >> 12) & 0x3FF;
-  uint32_t imm11 = (uint32_t)(displacement >> 1) & 0x7FF;
-  uint32_t j1 = (i1 == s);
-  uint32_t j2 = (i2 == s);
-  uint32_t nextDisp = (j1 << 13) | (j2 << 11) | imm11;
-  uint32_t firstDisp = (s << 10) | imm10;
-  newInstruction |= (nextDisp << 16) | firstDisp;
-  return newInstruction;
-}
-
-bool ArchHandler_arm::isThumbMovw(uint32_t instruction) {
-  return (instruction & 0x8000FBF0) == 0x0000F240;
-}
-
-bool ArchHandler_arm::isThumbMovt(uint32_t instruction) {
-  return (instruction & 0x8000FBF0) == 0x0000F2C0;
-}
-
-bool ArchHandler_arm::isArmMovw(uint32_t instruction) {
-  return (instruction & 0x0FF00000) == 0x03000000;
-}
-
-bool ArchHandler_arm::isArmMovt(uint32_t instruction) {
-  return (instruction & 0x0FF00000) == 0x03400000;
-}
-
-uint16_t ArchHandler_arm::getWordFromThumbMov(uint32_t instruction) {
-  assert(isThumbMovw(instruction) || isThumbMovt(instruction));
-  uint32_t i = ((instruction & 0x00000400) >> 10);
-  uint32_t imm4 = (instruction & 0x0000000F);
-  uint32_t imm3 = ((instruction & 0x70000000) >> 28);
-  uint32_t imm8 = ((instruction & 0x00FF0000) >> 16);
-  return (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
-}
-
-uint16_t ArchHandler_arm::getWordFromArmMov(uint32_t instruction) {
-  assert(isArmMovw(instruction) || isArmMovt(instruction));
-  uint32_t imm4 = ((instruction & 0x000F0000) >> 16);
-  uint32_t imm12 = (instruction & 0x00000FFF);
-  return (imm4 << 12) | imm12;
-}
-
-uint32_t ArchHandler_arm::setWordFromThumbMov(uint32_t instr, uint16_t word) {
-  assert(isThumbMovw(instr) || isThumbMovt(instr));
-  uint32_t imm4 = (word & 0xF000) >> 12;
-  uint32_t i =    (word & 0x0800) >> 11;
-  uint32_t imm3 = (word & 0x0700) >> 8;
-  uint32_t imm8 =  word & 0x00FF;
-       return (instr & 0x8F00FBF0) | imm4 | (i << 10) | (imm3 << 28) | (imm8 << 16);
-}
-
-uint32_t ArchHandler_arm::setWordFromArmMov(uint32_t instr, uint16_t word) {
-  assert(isArmMovw(instr) || isArmMovt(instr));
-  uint32_t imm4 = (word & 0xF000) >> 12;
-  uint32_t imm12 = word & 0x0FFF;
-  return (instr & 0xFFF0F000) | (imm4 << 16) | imm12;
-}
-
-uint32_t ArchHandler_arm::clearThumbBit(uint32_t value, const Atom *target) {
-  // The assembler often adds one to the address of a thumb function.
-  // We need to undo that so it does not look like an addend.
-  if (value & 1) {
-    if (isa<DefinedAtom>(target)) {
-      const MachODefinedAtom *machoTarget =
-          reinterpret_cast<const MachODefinedAtom *>(target);
-      if (machoTarget->isThumb())
-        value &= -2; // mask off thumb-bit
-    }
-  }
-  return value;
-}
-
-llvm::Error ArchHandler_arm::getReferenceInfo(
-    const Relocation &reloc, const DefinedAtom *inAtom, uint32_t offsetInAtom,
-    uint64_t fixupAddress, bool isBig,
-    FindAtomBySectionAndAddress atomFromAddress,
-    FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind,
-    const lld::Atom **target, Reference::Addend *addend) {
-  const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
-  uint64_t targetAddress;
-  uint32_t instruction = *(const ulittle32_t *)fixupContent;
-  int32_t displacement;
-  switch (relocPattern(reloc)) {
-  case ARM_THUMB_RELOC_BR22 | rPcRel | rExtern | rLength4:
-    // ex: bl _foo (and _foo is undefined)
-    if ((instruction & 0xD000F800) == 0x9000F000)
-      *kind = thumb_b22;
-    else
-      *kind = thumb_bl22;
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    // Instruction contains branch to addend.
-    displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
-    *addend = fixupAddress + 4 + displacement;
-    return llvm::Error::success();
-  case ARM_THUMB_RELOC_BR22 | rPcRel | rLength4:
-    // ex: bl _foo (and _foo is defined)
-    if ((instruction & 0xD000F800) == 0x9000F000)
-      *kind = thumb_b22;
-    else
-      *kind = thumb_bl22;
-    displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
-    targetAddress = fixupAddress + 4 + displacement;
-    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
-  case ARM_THUMB_RELOC_BR22 | rScattered | rPcRel | rLength4:
-    // ex: bl _foo+4 (and _foo is defined)
-    if ((instruction & 0xD000F800) == 0x9000F000)
-      *kind = thumb_b22;
-    else
-      *kind = thumb_bl22;
-    displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
-    targetAddress = fixupAddress + 4 + displacement;
-    if (auto ec = atomFromAddress(0, reloc.value, target, addend))
-      return ec;
-    // reloc.value is target atom's address.  Instruction contains branch
-    // to atom+addend.
-    *addend += (targetAddress - reloc.value);
-    return llvm::Error::success();
-  case ARM_RELOC_BR24 | rPcRel | rExtern | rLength4:
-    // ex: bl _foo (and _foo is undefined)
-    if (((instruction & 0x0F000000) == 0x0A000000)
-        && ((instruction & 0xF0000000) != 0xF0000000))
-      *kind = arm_b24;
-    else
-      *kind = arm_bl24;
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    // Instruction contains branch to addend.
-    displacement = getDisplacementFromArmBranch(instruction);
-    *addend = fixupAddress + 8 + displacement;
-    return llvm::Error::success();
-  case ARM_RELOC_BR24 | rPcRel | rLength4:
-    // ex: bl _foo (and _foo is defined)
-    if (((instruction & 0x0F000000) == 0x0A000000)
-        && ((instruction & 0xF0000000) != 0xF0000000))
-      *kind = arm_b24;
-    else
-      *kind = arm_bl24;
-    displacement = getDisplacementFromArmBranch(instruction);
-    targetAddress = fixupAddress + 8 + displacement;
-    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
-  case ARM_RELOC_BR24 | rScattered | rPcRel | rLength4:
-    // ex: bl _foo+4 (and _foo is defined)
-    if (((instruction & 0x0F000000) == 0x0A000000)
-        && ((instruction & 0xF0000000) != 0xF0000000))
-      *kind = arm_b24;
-    else
-      *kind = arm_bl24;
-    displacement = getDisplacementFromArmBranch(instruction);
-    targetAddress = fixupAddress + 8 + displacement;
-    if (auto ec = atomFromAddress(0, reloc.value, target, addend))
-      return ec;
-    // reloc.value is target atom's address.  Instruction contains branch
-    // to atom+addend.
-    *addend += (targetAddress - reloc.value);
-    return llvm::Error::success();
-  case ARM_RELOC_VANILLA | rExtern | rLength4:
-    // ex: .long _foo (and _foo is undefined)
-    *kind = pointer32;
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    *addend = instruction;
-    return llvm::Error::success();
-  case ARM_RELOC_VANILLA | rLength4:
-    // ex: .long _foo (and _foo is defined)
-    *kind = pointer32;
-    if (auto ec = atomFromAddress(reloc.symbol, instruction, target, addend))
-      return ec;
-    *addend = clearThumbBit((uint32_t) * addend, *target);
-    return llvm::Error::success();
-  case ARM_RELOC_VANILLA | rScattered | rLength4:
-    // ex: .long _foo+a (and _foo is defined)
-    *kind = pointer32;
-    if (auto ec = atomFromAddress(0, reloc.value, target, addend))
-      return ec;
-    *addend += (clearThumbBit(instruction, *target) - reloc.value);
-    return llvm::Error::success();
-  default:
-    return llvm::make_error<GenericError>("unsupported arm relocation type");
-  }
-  return llvm::Error::success();
-}
-
-llvm::Error
-ArchHandler_arm::getPairReferenceInfo(const normalized::Relocation &reloc1,
-                                     const normalized::Relocation &reloc2,
-                                     const DefinedAtom *inAtom,
-                                     uint32_t offsetInAtom,
-                                     uint64_t fixupAddress, bool isBig,
-                                     bool scatterable,
-                                     FindAtomBySectionAndAddress atomFromAddr,
-                                     FindAtomBySymbolIndex atomFromSymbolIndex,
-                                     Reference::KindValue *kind,
-                                     const lld::Atom **target,
-                                     Reference::Addend *addend) {
-  bool pointerDiff = false;
-  bool funcRel;
-  bool top;
-  bool thumbReloc;
-  switch(relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
-  case ((ARM_RELOC_HALF_SECTDIFF  | rScattered | rLenThmbLo) << 16 |
-         ARM_RELOC_PAIR           | rScattered | rLenThmbLo):
-    // ex: movw        r1, :lower16:(_x-L1) [thumb mode]
-    *kind = thumb_movw_funcRel;
-    funcRel = true;
-    top = false;
-    thumbReloc = true;
-    break;
-  case ((ARM_RELOC_HALF_SECTDIFF  | rScattered | rLenThmbHi) << 16 |
-         ARM_RELOC_PAIR           | rScattered | rLenThmbHi):
-    // ex: movt        r1, :upper16:(_x-L1) [thumb mode]
-    *kind = thumb_movt_funcRel;
-    funcRel = true;
-    top = true;
-    thumbReloc = true;
-    break;
-  case ((ARM_RELOC_HALF_SECTDIFF  | rScattered | rLenArmLo) << 16 |
-         ARM_RELOC_PAIR           | rScattered | rLenArmLo):
-    // ex: movw        r1, :lower16:(_x-L1) [arm mode]
-    *kind = arm_movw_funcRel;
-    funcRel = true;
-    top = false;
-    thumbReloc = false;
-    break;
-  case ((ARM_RELOC_HALF_SECTDIFF  | rScattered | rLenArmHi) << 16 |
-         ARM_RELOC_PAIR           | rScattered | rLenArmHi):
-    // ex: movt        r1, :upper16:(_x-L1) [arm mode]
-    *kind = arm_movt_funcRel;
-    funcRel = true;
-    top = true;
-    thumbReloc = false;
-    break;
-  case ((ARM_RELOC_HALF     | rLenThmbLo) << 16 |
-         ARM_RELOC_PAIR     | rLenThmbLo):
-    // ex: movw        r1, :lower16:_x [thumb mode]
-    *kind = thumb_movw;
-    funcRel = false;
-    top = false;
-    thumbReloc = true;
-    break;
-  case ((ARM_RELOC_HALF     | rLenThmbHi) << 16 |
-         ARM_RELOC_PAIR     | rLenThmbHi):
-    // ex: movt        r1, :upper16:_x [thumb mode]
-    *kind = thumb_movt;
-    funcRel = false;
-    top = true;
-    thumbReloc = true;
-    break;
-  case ((ARM_RELOC_HALF     | rLenArmLo) << 16 |
-         ARM_RELOC_PAIR     | rLenArmLo):
-    // ex: movw        r1, :lower16:_x [arm mode]
-    *kind = arm_movw;
-    funcRel = false;
-    top = false;
-    thumbReloc = false;
-    break;
-  case ((ARM_RELOC_HALF     | rLenArmHi) << 16 |
-         ARM_RELOC_PAIR     | rLenArmHi):
-    // ex: movt        r1, :upper16:_x [arm mode]
-    *kind = arm_movt;
-    funcRel = false;
-    top = true;
-    thumbReloc = false;
-    break;
-  case ((ARM_RELOC_HALF | rScattered  | rLenThmbLo) << 16 |
-         ARM_RELOC_PAIR               | rLenThmbLo):
-    // ex: movw        r1, :lower16:_x+a [thumb mode]
-    *kind = thumb_movw;
-    funcRel = false;
-    top = false;
-    thumbReloc = true;
-    break;
-  case ((ARM_RELOC_HALF | rScattered  | rLenThmbHi) << 16 |
-         ARM_RELOC_PAIR               | rLenThmbHi):
-    // ex: movt        r1, :upper16:_x+a [thumb mode]
-    *kind = thumb_movt;
-    funcRel = false;
-    top = true;
-    thumbReloc = true;
-    break;
-  case ((ARM_RELOC_HALF | rScattered  | rLenArmLo) << 16 |
-         ARM_RELOC_PAIR               | rLenArmLo):
-    // ex: movw        r1, :lower16:_x+a [arm mode]
-    *kind = arm_movw;
-    funcRel = false;
-    top = false;
-    thumbReloc = false;
-    break;
-  case ((ARM_RELOC_HALF | rScattered  | rLenArmHi) << 16 |
-         ARM_RELOC_PAIR               | rLenArmHi):
-    // ex: movt        r1, :upper16:_x+a [arm mode]
-    *kind = arm_movt;
-    funcRel = false;
-    top = true;
-    thumbReloc = false;
-    break;
-  case ((ARM_RELOC_HALF | rExtern   | rLenThmbLo) << 16 |
-         ARM_RELOC_PAIR             | rLenThmbLo):
-    // ex: movw        r1, :lower16:_undef [thumb mode]
-    *kind = thumb_movw;
-    funcRel = false;
-    top = false;
-    thumbReloc = true;
-    break;
-  case ((ARM_RELOC_HALF | rExtern   | rLenThmbHi) << 16 |
-         ARM_RELOC_PAIR             | rLenThmbHi):
-    // ex: movt        r1, :upper16:_undef [thumb mode]
-    *kind = thumb_movt;
-    funcRel = false;
-    top = true;
-    thumbReloc = true;
-    break;
-  case ((ARM_RELOC_HALF | rExtern   | rLenArmLo) << 16 |
-         ARM_RELOC_PAIR             | rLenArmLo):
-    // ex: movw        r1, :lower16:_undef [arm mode]
-    *kind = arm_movw;
-    funcRel = false;
-    top = false;
-    thumbReloc = false;
-    break;
-  case ((ARM_RELOC_HALF | rExtern   | rLenArmHi) << 16 |
-         ARM_RELOC_PAIR             | rLenArmHi):
-    // ex: movt        r1, :upper16:_undef [arm mode]
-    *kind = arm_movt;
-    funcRel = false;
-    top = true;
-    thumbReloc = false;
-    break;
-  case ((ARM_RELOC_SECTDIFF       | rScattered | rLength4) << 16 |
-         ARM_RELOC_PAIR           | rScattered | rLength4):
-  case ((ARM_RELOC_LOCAL_SECTDIFF | rScattered | rLength4) << 16 |
-         ARM_RELOC_PAIR           | rScattered | rLength4):
-    // ex: .long _foo - .
-    pointerDiff = true;
-    break;
-  default:
-    return llvm::make_error<GenericError>("unsupported arm relocation pair");
-  }
-  const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
-  uint32_t instruction = *(const ulittle32_t *)fixupContent;
-  uint32_t value;
-  uint32_t fromAddress;
-  uint32_t toAddress;
-  uint16_t instruction16;
-  uint16_t other16;
-  const lld::Atom *fromTarget;
-  Reference::Addend offsetInTo;
-  Reference::Addend offsetInFrom;
-  if (pointerDiff) {
-    toAddress = reloc1.value;
-    fromAddress = reloc2.value;
-    if (auto ec = atomFromAddr(0, toAddress, target, &offsetInTo))
-      return ec;
-    if (auto ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom))
-      return ec;
-    if (scatterable && (fromTarget != inAtom))
-      return llvm::make_error<GenericError>(
-          "SECTDIFF relocation where subtrahend label is not in atom");
-    *kind = delta32;
-    value = clearThumbBit(instruction, *target);
-    *addend = (int32_t)(value - (toAddress - fixupAddress));
-  } else if (funcRel) {
-    toAddress = reloc1.value;
-    fromAddress = reloc2.value;
-    if (auto ec = atomFromAddr(0, toAddress, target, &offsetInTo))
-      return ec;
-    if (auto ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom))
-      return ec;
-    if (fromTarget != inAtom)
-      return llvm::make_error<GenericError>("ARM_RELOC_HALF_SECTDIFF relocation"
-                                     " where subtrahend label is not in atom");
-    other16 = (reloc2.offset & 0xFFFF);
-    if (thumbReloc) {
-      if (top) {
-        if (!isThumbMovt(instruction))
-          return llvm::make_error<GenericError>("expected movt instruction");
-      }
-      else {
-        if (!isThumbMovw(instruction))
-          return llvm::make_error<GenericError>("expected movw instruction");
-      }
-      instruction16 = getWordFromThumbMov(instruction);
-    }
-    else {
-      if (top) {
-        if (!isArmMovt(instruction))
-          return llvm::make_error<GenericError>("expected movt instruction");
-      }
-      else {
-        if (!isArmMovw(instruction))
-          return llvm::make_error<GenericError>("expected movw instruction");
-      }
-      instruction16 = getWordFromArmMov(instruction);
-    }
-    if (top)
-      value = (instruction16 << 16) | other16;
-    else
-      value = (other16 << 16) | instruction16;
-    value = clearThumbBit(value, *target);
-    int64_t ta = (int64_t) value - (toAddress - fromAddress);
-    *addend = ta - offsetInFrom;
-    return llvm::Error::success();
-  } else {
-    uint32_t sectIndex;
-    if (thumbReloc) {
-      if (top) {
-        if (!isThumbMovt(instruction))
-          return llvm::make_error<GenericError>("expected movt instruction");
-      }
-      else {
-        if (!isThumbMovw(instruction))
-          return llvm::make_error<GenericError>("expected movw instruction");
-      }
-      instruction16 = getWordFromThumbMov(instruction);
-    }
-    else {
-      if (top) {
-        if (!isArmMovt(instruction))
-          return llvm::make_error<GenericError>("expected movt instruction");
-      }
-      else {
-        if (!isArmMovw(instruction))
-          return llvm::make_error<GenericError>("expected movw instruction");
-      }
-      instruction16 = getWordFromArmMov(instruction);
-    }
-    other16 = (reloc2.offset & 0xFFFF);
-    if (top)
-      value = (instruction16 << 16) | other16;
-    else
-      value = (other16 << 16) | instruction16;
-    if (reloc1.isExtern) {
-      if (auto ec = atomFromSymbolIndex(reloc1.symbol, target))
-        return ec;
-      *addend = value;
-    } else {
-      if (reloc1.scattered) {
-        toAddress = reloc1.value;
-        sectIndex = 0;
-      } else {
-        toAddress = value;
-        sectIndex = reloc1.symbol;
-      }
-      if (auto ec = atomFromAddr(sectIndex, toAddress, target, &offsetInTo))
-        return ec;
-      *addend = value - toAddress;
-    }
-  }
-
-  return llvm::Error::success();
-}
-
-void ArchHandler_arm::applyFixupFinal(const Reference &ref, uint8_t *loc,
-                                      uint64_t fixupAddress,
-                                      uint64_t targetAddress,
-                                      uint64_t inAtomAddress,
-                                      bool &thumbMode, bool targetIsThumb) {
-  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
-    return;
-  assert(ref.kindArch() == Reference::KindArch::ARM);
-  ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
-  int32_t displacement;
-  uint16_t value16;
-  uint32_t value32;
-  switch (static_cast<ArmKind>(ref.kindValue())) {
-  case modeThumbCode:
-    thumbMode = true;
-    break;
-  case modeArmCode:
-    thumbMode = false;
-    break;
-  case modeData:
-    break;
-  case thumb_b22:
-  case thumb_bl22:
-    assert(thumbMode);
-    displacement = (targetAddress - (fixupAddress + 4)) + ref.addend();
-    value32 = setDisplacementInThumbBranch(*loc32, fixupAddress,
-                                           displacement, targetIsThumb);
-    *loc32 = value32;
-    break;
-  case thumb_movw:
-    assert(thumbMode);
-    value16 = (targetAddress + ref.addend()) & 0xFFFF;
-    if (targetIsThumb)
-      value16 |= 1;
-    *loc32 = setWordFromThumbMov(*loc32, value16);
-    break;
-  case thumb_movt:
-    assert(thumbMode);
-    value16 = (targetAddress + ref.addend()) >> 16;
-    *loc32 = setWordFromThumbMov(*loc32, value16);
-    break;
-  case thumb_movw_funcRel:
-    assert(thumbMode);
-    value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
-    if (targetIsThumb)
-      value16 |= 1;
-    *loc32 = setWordFromThumbMov(*loc32, value16);
-    break;
-  case thumb_movt_funcRel:
-    assert(thumbMode);
-    value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
-    *loc32 = setWordFromThumbMov(*loc32, value16);
-    break;
-  case arm_b24:
-  case arm_bl24:
-   assert(!thumbMode);
-    displacement = (targetAddress - (fixupAddress + 8)) + ref.addend();
-    value32 = setDisplacementInArmBranch(*loc32, displacement, targetIsThumb);
-    *loc32 = value32;
-    break;
-  case arm_movw:
-    assert(!thumbMode);
-    value16 = (targetAddress + ref.addend()) & 0xFFFF;
-    if (targetIsThumb)
-      value16 |= 1;
-    *loc32 = setWordFromArmMov(*loc32, value16);
-    break;
-  case arm_movt:
-    assert(!thumbMode);
-    value16 = (targetAddress + ref.addend()) >> 16;
-    *loc32 = setWordFromArmMov(*loc32, value16);
-    break;
-  case arm_movw_funcRel:
-    assert(!thumbMode);
-    value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
-    if (targetIsThumb)
-      value16 |= 1;
-    *loc32 = setWordFromArmMov(*loc32, value16);
-    break;
-  case arm_movt_funcRel:
-    assert(!thumbMode);
-    value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
-    *loc32 = setWordFromArmMov(*loc32, value16);
-    break;
-  case pointer32:
-    if (targetIsThumb)
-      *loc32 = targetAddress + ref.addend() + 1;
-    else
-      *loc32 = targetAddress + ref.addend();
-    break;
-  case delta32:
-    if (targetIsThumb)
-      *loc32 = targetAddress - fixupAddress + ref.addend() + 1;
-    else
-      *loc32 = targetAddress - fixupAddress + ref.addend();
-    break;
-  case lazyPointer:
-    // do nothing
-    break;
-  case lazyImmediateLocation:
-    *loc32 = ref.addend();
-    break;
-  case invalid:
-    llvm_unreachable("invalid ARM Reference Kind");
-    break;
-  }
-}
-
-void ArchHandler_arm::generateAtomContent(const DefinedAtom &atom,
-                                          bool relocatable,
-                                          FindAddressForAtom findAddress,
-                                          FindAddressForAtom findSectionAddress,
-                                          uint64_t imageBaseAddress,
-                            llvm::MutableArrayRef<uint8_t> atomContentBuffer) {
-  // Copy raw bytes.
-  std::copy(atom.rawContent().begin(), atom.rawContent().end(),
-            atomContentBuffer.begin());
-  // Apply fix-ups.
-  bool thumbMode = false;
-  for (const Reference *ref : atom) {
-    uint32_t offset = ref->offsetInAtom();
-    const Atom *target = ref->target();
-    uint64_t targetAddress = 0;
-    bool targetIsThumb = false;
-    if (const DefinedAtom *defTarg = dyn_cast<DefinedAtom>(target)) {
-      targetAddress = findAddress(*target);
-      targetIsThumb = isThumbFunction(*defTarg);
-    }
-    uint64_t atomAddress = findAddress(atom);
-    uint64_t fixupAddress = atomAddress + offset;
-    if (relocatable) {
-      applyFixupRelocatable(*ref, &atomContentBuffer[offset], fixupAddress,
-                            targetAddress, atomAddress, thumbMode,
-                            targetIsThumb);
-    } else {
-      applyFixupFinal(*ref, &atomContentBuffer[offset], fixupAddress,
-                      targetAddress, atomAddress, thumbMode, targetIsThumb);
-    }
-  }
-}
-
-bool ArchHandler_arm::useExternalRelocationTo(const Atom &target) {
-  // Undefined symbols are referenced via external relocations.
-  if (isa<UndefinedAtom>(&target))
-    return true;
-  if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(&target)) {
-     switch (defAtom->merge()) {
-     case DefinedAtom::mergeAsTentative:
-       // Tentative definitions are referenced via external relocations.
-       return true;
-     case DefinedAtom::mergeAsWeak:
-     case DefinedAtom::mergeAsWeakAndAddressUsed:
-       // Global weak-defs are referenced via external relocations.
-       return (defAtom->scope() == DefinedAtom::scopeGlobal);
-     default:
-       break;
-    }
-  }
-  // Everything else is reference via an internal relocation.
-  return false;
-}
-
-void ArchHandler_arm::applyFixupRelocatable(const Reference &ref, uint8_t *loc,
-                                            uint64_t fixupAddress,
-                                            uint64_t targetAddress,
-                                            uint64_t inAtomAddress,
-                                            bool &thumbMode,
-                                            bool targetIsThumb) {
-  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
-    return;
-  assert(ref.kindArch() == Reference::KindArch::ARM);
-  bool useExternalReloc = useExternalRelocationTo(*ref.target());
-  ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
-  int32_t displacement;
-  uint16_t value16;
-  uint32_t value32;
-  bool targetIsUndef = isa<UndefinedAtom>(ref.target());
-  switch (static_cast<ArmKind>(ref.kindValue())) {
-  case modeThumbCode:
-    thumbMode = true;
-    break;
-  case modeArmCode:
-    thumbMode = false;
-    break;
-  case modeData:
-    break;
-  case thumb_b22:
-  case thumb_bl22:
-    assert(thumbMode);
-    if (useExternalReloc)
-      displacement = (ref.addend() - (fixupAddress + 4));
-    else
-      displacement = (targetAddress - (fixupAddress + 4)) + ref.addend();
-    value32 = setDisplacementInThumbBranch(*loc32, fixupAddress,
-                                           displacement,
-                                           targetIsUndef || targetIsThumb);
-    *loc32 = value32;
-    break;
-  case thumb_movw:
-    assert(thumbMode);
-    if (useExternalReloc)
-      value16 = ref.addend() & 0xFFFF;
-    else
-      value16 = (targetAddress + ref.addend()) & 0xFFFF;
-    *loc32 = setWordFromThumbMov(*loc32, value16);
-    break;
-  case thumb_movt:
-    assert(thumbMode);
-    if (useExternalReloc)
-      value16 = ref.addend() >> 16;
-    else
-      value16 = (targetAddress + ref.addend()) >> 16;
-    *loc32 = setWordFromThumbMov(*loc32, value16);
-    break;
-  case thumb_movw_funcRel:
-    assert(thumbMode);
-    value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
-    *loc32 = setWordFromThumbMov(*loc32, value16);
-    break;
-  case thumb_movt_funcRel:
-    assert(thumbMode);
-    value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
-    *loc32 = setWordFromThumbMov(*loc32, value16);
-    break;
-  case arm_b24:
-  case arm_bl24:
-    assert(!thumbMode);
-    if (useExternalReloc)
-      displacement = (ref.addend() - (fixupAddress + 8));
-    else
-      displacement = (targetAddress - (fixupAddress + 8)) + ref.addend();
-    value32 = setDisplacementInArmBranch(*loc32, displacement,
-                                         targetIsThumb);
-    *loc32 = value32;
-    break;
-  case arm_movw:
-    assert(!thumbMode);
-    if (useExternalReloc)
-      value16 = ref.addend() & 0xFFFF;
-    else
-      value16 = (targetAddress + ref.addend()) & 0xFFFF;
-    *loc32 = setWordFromArmMov(*loc32, value16);
-    break;
-  case arm_movt:
-    assert(!thumbMode);
-    if (useExternalReloc)
-      value16 = ref.addend() >> 16;
-    else
-      value16 = (targetAddress + ref.addend()) >> 16;
-    *loc32 = setWordFromArmMov(*loc32, value16);
-    break;
-  case arm_movw_funcRel:
-    assert(!thumbMode);
-    value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
-    *loc32 = setWordFromArmMov(*loc32, value16);
-    break;
-  case arm_movt_funcRel:
-    assert(!thumbMode);
-    value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
-    *loc32 = setWordFromArmMov(*loc32, value16);
-    break;
-  case pointer32:
-    *loc32 = targetAddress + ref.addend();
-    break;
-  case delta32:
-    *loc32 = targetAddress - fixupAddress + ref.addend();
-    break;
-  case lazyPointer:
-  case lazyImmediateLocation:
-    // do nothing
-    break;
-  case invalid:
-    llvm_unreachable("invalid ARM Reference Kind");
-    break;
-  }
-}
-
-void ArchHandler_arm::appendSectionRelocations(
-                                   const DefinedAtom &atom,
-                                   uint64_t atomSectionOffset,
-                                   const Reference &ref,
-                                   FindSymbolIndexForAtom symbolIndexForAtom,
-                                   FindSectionIndexForAtom sectionIndexForAtom,
-                                   FindAddressForAtom addressForAtom,
-                                   normalized::Relocations &relocs) {
-  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
-    return;
-  assert(ref.kindArch() == Reference::KindArch::ARM);
-  uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom();
-  bool useExternalReloc = useExternalRelocationTo(*ref.target());
-  uint32_t targetAtomAddress;
-  uint32_t fromAtomAddress;
-  uint16_t other16;
-  switch (static_cast<ArmKind>(ref.kindValue())) {
-  case modeThumbCode:
-  case modeArmCode:
-  case modeData:
-    // Do nothing.
-    break;
-  case thumb_b22:
-  case thumb_bl22:
-    if (useExternalReloc) {
-      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  ARM_THUMB_RELOC_BR22 | rExtern    | rPcRel | rLength4);
-    } else {
-      if (ref.addend() != 0)
-        appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
-                  ARM_THUMB_RELOC_BR22 | rScattered | rPcRel | rLength4);
-      else
-        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
-                  ARM_THUMB_RELOC_BR22 |              rPcRel | rLength4);
-    }
-    break;
-  case thumb_movw:
-    if (useExternalReloc) {
-      other16 = ref.addend() >> 16;
-      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  ARM_RELOC_HALF | rExtern    | rLenThmbLo);
-      appendReloc(relocs, other16, 0, 0,
-                  ARM_RELOC_PAIR              | rLenThmbLo);
-    } else {
-      targetAtomAddress = addressForAtom(*ref.target());
-      if (ref.addend() != 0) {
-        other16 = (targetAtomAddress + ref.addend()) >> 16;
-        appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
-                  ARM_RELOC_HALF | rScattered | rLenThmbLo);
-        appendReloc(relocs, other16, 0, 0,
-                  ARM_RELOC_PAIR              | rLenThmbLo);
-      } else {
-        other16 = (targetAtomAddress + ref.addend()) >> 16;
-        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
-                  ARM_RELOC_HALF              | rLenThmbLo);
-        appendReloc(relocs, other16, 0, 0,
-                  ARM_RELOC_PAIR              | rLenThmbLo);
-      }
-    }
-    break;
-  case thumb_movt:
-    if (useExternalReloc) {
-      other16 = ref.addend() & 0xFFFF;
-      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  ARM_RELOC_HALF | rExtern    | rLenThmbHi);
-      appendReloc(relocs, other16, 0, 0,
-                  ARM_RELOC_PAIR              | rLenThmbHi);
-    } else {
-      targetAtomAddress = addressForAtom(*ref.target());
-      if (ref.addend() != 0) {
-        other16 = (targetAtomAddress + ref.addend()) & 0xFFFF;
-        appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
-                    ARM_RELOC_HALF | rScattered | rLenThmbHi);
-        appendReloc(relocs, other16, 0, 0,
-                    ARM_RELOC_PAIR              | rLenThmbHi);
-      } else {
-        other16 = (targetAtomAddress + ref.addend()) & 0xFFFF;
-        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
-                    ARM_RELOC_HALF              | rLenThmbHi);
-        appendReloc(relocs, other16, 0, 0,
-                    ARM_RELOC_PAIR              | rLenThmbHi);
-      }
-    }
-    break;
-  case thumb_movw_funcRel:
-    fromAtomAddress = addressForAtom(atom);
-    targetAtomAddress = addressForAtom(*ref.target());
-    other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) >> 16;
-    appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
-                ARM_RELOC_HALF_SECTDIFF | rScattered | rLenThmbLo);
-    appendReloc(relocs, other16, 0, fromAtomAddress,
-                ARM_RELOC_PAIR          | rScattered | rLenThmbLo);
-    break;
-  case thumb_movt_funcRel:
-    fromAtomAddress = addressForAtom(atom);
-    targetAtomAddress = addressForAtom(*ref.target());
-    other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) & 0xFFFF;
-    appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
-                ARM_RELOC_HALF_SECTDIFF | rScattered | rLenThmbHi);
-    appendReloc(relocs, other16, 0, fromAtomAddress,
-                ARM_RELOC_PAIR          | rScattered | rLenThmbHi);
-    break;
-  case arm_b24:
-  case arm_bl24:
-    if (useExternalReloc) {
-      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  ARM_RELOC_BR24 | rExtern    | rPcRel | rLength4);
-    } else {
-      if (ref.addend() != 0)
-        appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
-                  ARM_RELOC_BR24 | rScattered | rPcRel | rLength4);
-      else
-        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
-                  ARM_RELOC_BR24 |              rPcRel | rLength4);
-    }
-    break;
-  case arm_movw:
-    if (useExternalReloc) {
-      other16 = ref.addend() >> 16;
-      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  ARM_RELOC_HALF | rExtern    | rLenArmLo);
-      appendReloc(relocs, other16, 0, 0,
-                  ARM_RELOC_PAIR              | rLenArmLo);
-    } else {
-      targetAtomAddress = addressForAtom(*ref.target());
-      if (ref.addend() != 0) {
-        other16 = (targetAtomAddress + ref.addend()) >> 16;
-        appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
-                  ARM_RELOC_HALF | rScattered | rLenArmLo);
-        appendReloc(relocs, other16, 0, 0,
-                  ARM_RELOC_PAIR              | rLenArmLo);
-      } else {
-        other16 = (targetAtomAddress + ref.addend()) >> 16;
-        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
-                  ARM_RELOC_HALF              | rLenArmLo);
-        appendReloc(relocs, other16, 0, 0,
-                  ARM_RELOC_PAIR              | rLenArmLo);
-      }
-    }
-    break;
-  case arm_movt:
-    if (useExternalReloc) {
-      other16 = ref.addend() & 0xFFFF;
-      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  ARM_RELOC_HALF | rExtern    | rLenArmHi);
-      appendReloc(relocs, other16, 0, 0,
-                  ARM_RELOC_PAIR              | rLenArmHi);
-    } else {
-      targetAtomAddress = addressForAtom(*ref.target());
-      if (ref.addend() != 0) {
-        other16 = (targetAtomAddress + ref.addend()) & 0xFFFF;
-        appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
-                  ARM_RELOC_HALF | rScattered | rLenArmHi);
-        appendReloc(relocs, other16, 0, 0,
-                  ARM_RELOC_PAIR              | rLenArmHi);
-      } else {
-        other16 = (targetAtomAddress + ref.addend()) & 0xFFFF;
-        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
-                  ARM_RELOC_HALF              | rLenArmHi);
-        appendReloc(relocs, other16, 0, 0,
-                  ARM_RELOC_PAIR              | rLenArmHi);
-      }
-    }
-    break;
-  case arm_movw_funcRel:
-    fromAtomAddress = addressForAtom(atom);
-    targetAtomAddress = addressForAtom(*ref.target());
-    other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) >> 16;
-    appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
-                ARM_RELOC_HALF_SECTDIFF | rScattered | rLenArmLo);
-    appendReloc(relocs, other16, 0, fromAtomAddress,
-                ARM_RELOC_PAIR          | rScattered | rLenArmLo);
-    break;
-  case arm_movt_funcRel:
-    fromAtomAddress = addressForAtom(atom);
-    targetAtomAddress = addressForAtom(*ref.target());
-    other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) & 0xFFFF;
-    appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
-                ARM_RELOC_HALF_SECTDIFF | rScattered | rLenArmHi);
-    appendReloc(relocs, other16, 0, fromAtomAddress,
-                ARM_RELOC_PAIR          | rScattered | rLenArmHi);
-    break;
-  case pointer32:
-    if (useExternalReloc) {
-      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()),  0,
-                ARM_RELOC_VANILLA |    rExtern     |  rLength4);
-    }
-    else {
-      if (ref.addend() != 0)
-        appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
-                ARM_RELOC_VANILLA |    rScattered  |  rLength4);
-      else
-        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
-                ARM_RELOC_VANILLA |                   rLength4);
-    }
-    break;
-  case delta32:
-    appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
-              ARM_RELOC_SECTDIFF  |  rScattered    | rLength4);
-    appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) +
-                                                           ref.offsetInAtom(),
-              ARM_RELOC_PAIR      |  rScattered    | rLength4);
-    break;
-  case lazyPointer:
-  case lazyImmediateLocation:
-    // do nothing
-    break;
-  case invalid:
-    llvm_unreachable("invalid ARM Reference Kind");
-    break;
-  }
-}
-
-void ArchHandler_arm::addAdditionalReferences(MachODefinedAtom &atom) {
-  if (atom.isThumb()) {
-    atom.addReference(Reference::KindNamespace::mach_o,
-                      Reference::KindArch::ARM, modeThumbCode, 0, &atom, 0);
-  }
-}
-
-bool ArchHandler_arm::isThumbFunction(const DefinedAtom &atom) {
-  for (const Reference *ref : atom) {
-    if (ref->offsetInAtom() != 0)
-      return false;
-    if (ref->kindNamespace() != Reference::KindNamespace::mach_o)
-      continue;
-    assert(ref->kindArch() == Reference::KindArch::ARM);
-    if (ref->kindValue() == modeThumbCode)
-      return true;
-  }
-  return false;
-}
-
-class Thumb2ToArmShimAtom : public SimpleDefinedAtom {
-public:
-  Thumb2ToArmShimAtom(MachOFile &file, StringRef targetName,
-                      const DefinedAtom &target)
-      : SimpleDefinedAtom(file) {
-    addReference(Reference::KindNamespace::mach_o, Reference::KindArch::ARM,
-                 ArchHandler_arm::modeThumbCode, 0, this, 0);
-    addReference(Reference::KindNamespace::mach_o, Reference::KindArch::ARM,
-                 ArchHandler_arm::delta32, 8, &target, 0);
-    std::string name = std::string(targetName) + "$shim";
-    StringRef tmp(name);
-    _name = tmp.copy(file.allocator());
-  }
-
-  ~Thumb2ToArmShimAtom() override = default;
-
-  StringRef name() const override {
-    return _name;
-  }
-
-  ContentType contentType() const override {
-    return DefinedAtom::typeCode;
-  }
-
-  Alignment alignment() const override { return 4; }
-
-  uint64_t size() const override {
-    return 12;
-  }
-
-  ContentPermissions permissions() const override {
-    return DefinedAtom::permR_X;
-  }
-
-  ArrayRef<uint8_t> rawContent() const override {
-    static const uint8_t bytes[] =
-    { 0xDF, 0xF8, 0x04, 0xC0,       //  ldr ip, pc + 4
-      0xFF, 0x44,                   //  add ip, pc, ip
-      0x60, 0x47,                   //  ldr pc, [ip]
-      0x00, 0x00, 0x00, 0x00 };     //  .long target - this
-    assert(sizeof(bytes) == size());
-    return llvm::makeArrayRef(bytes, sizeof(bytes));
-  }
-private:
-  StringRef _name;
-};
-
-class ArmToThumbShimAtom : public SimpleDefinedAtom {
-public:
-  ArmToThumbShimAtom(MachOFile &file, StringRef targetName,
-                     const DefinedAtom &target)
-      : SimpleDefinedAtom(file) {
-    addReference(Reference::KindNamespace::mach_o, Reference::KindArch::ARM,
-                 ArchHandler_arm::delta32, 12, &target, 0);
-    std::string name = std::string(targetName) + "$shim";
-    StringRef tmp(name);
-    _name = tmp.copy(file.allocator());
-  }
-
-  ~ArmToThumbShimAtom() override = default;
-
-  StringRef name() const override {
-    return _name;
-  }
-
-  ContentType contentType() const override {
-    return DefinedAtom::typeCode;
-  }
-
-  Alignment alignment() const override { return 4; }
-
-  uint64_t size() const override {
-    return 16;
-  }
-
-  ContentPermissions permissions() const override {
-    return DefinedAtom::permR_X;
-  }
-
-  ArrayRef<uint8_t> rawContent() const override {
-    static const uint8_t bytes[] =
-    { 0x04, 0xC0, 0x9F, 0xE5,       //  ldr ip, pc + 4
-      0x0C, 0xC0, 0x8F, 0xE0,       //  add ip, pc, ip
-      0x1C, 0xFF, 0x2F, 0xE1,       //  ldr pc, [ip]
-      0x00, 0x00, 0x00, 0x00 };     //  .long target - this
-    assert(sizeof(bytes) == size());
-    return llvm::makeArrayRef(bytes, sizeof(bytes));
-  }
-private:
-  StringRef _name;
-};
-
-const DefinedAtom *ArchHandler_arm::createShim(MachOFile &file,
-                                               bool thumbToArm,
-                                               const DefinedAtom &target) {
-  bool isStub = (target.contentType() == DefinedAtom::typeStub);
-  StringRef targetName = isStub ? stubName(target) : target.name();
-  if (thumbToArm)
-    return new (file.allocator()) Thumb2ToArmShimAtom(file, targetName, target);
-  else
-    return new (file.allocator()) ArmToThumbShimAtom(file, targetName, target);
-}
-
-std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_arm() {
-  return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_arm());
-}
-
-} // namespace mach_o
-} // namespace lld
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp b/gnu/llvm/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
deleted file mode 100644 (file)
index bee081a..0000000
+++ /dev/null
@@ -1,897 +0,0 @@
-//===- lib/FileFormat/MachO/ArchHandler_arm64.cpp -------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "Atoms.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Format.h"
-
-using namespace llvm::MachO;
-using namespace lld::mach_o::normalized;
-
-namespace lld {
-namespace mach_o {
-
-using llvm::support::ulittle32_t;
-using llvm::support::ulittle64_t;
-
-using llvm::support::little32_t;
-using llvm::support::little64_t;
-
-class ArchHandler_arm64 : public ArchHandler {
-public:
-  ArchHandler_arm64() = default;
-  ~ArchHandler_arm64() override = default;
-
-  const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
-
-  Reference::KindArch kindArch() override {
-    return Reference::KindArch::AArch64;
-  }
-
-  /// Used by GOTPass to locate GOT References
-  bool isGOTAccess(const Reference &ref, bool &canBypassGOT) override {
-    if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
-      return false;
-    assert(ref.kindArch() == Reference::KindArch::AArch64);
-    switch (ref.kindValue()) {
-    case gotPage21:
-    case gotOffset12:
-      canBypassGOT = true;
-      return true;
-    case delta32ToGOT:
-    case unwindCIEToPersonalityFunction:
-    case imageOffsetGot:
-      canBypassGOT = false;
-      return true;
-    default:
-      return false;
-    }
-  }
-
-  /// Used by GOTPass to update GOT References.
-  void updateReferenceToGOT(const Reference *ref, bool targetNowGOT) override {
-    // If GOT slot was instantiated, transform:
-    //   gotPage21/gotOffset12 -> page21/offset12scale8
-    // If GOT slot optimized away, transform:
-    //   gotPage21/gotOffset12 -> page21/addOffset12
-    assert(ref->kindNamespace() == Reference::KindNamespace::mach_o);
-    assert(ref->kindArch() == Reference::KindArch::AArch64);
-    switch (ref->kindValue()) {
-    case gotPage21:
-      const_cast<Reference *>(ref)->setKindValue(page21);
-      break;
-    case gotOffset12:
-      const_cast<Reference *>(ref)->setKindValue(targetNowGOT ?
-                                                 offset12scale8 : addOffset12);
-      break;
-    case delta32ToGOT:
-      const_cast<Reference *>(ref)->setKindValue(delta32);
-      break;
-    case imageOffsetGot:
-      const_cast<Reference *>(ref)->setKindValue(imageOffset);
-      break;
-    default:
-      llvm_unreachable("Not a GOT reference");
-    }
-  }
-
-  const StubInfo &stubInfo() override { return _sStubInfo; }
-
-  bool isCallSite(const Reference &) override;
-  bool isNonCallBranch(const Reference &) override {
-    return false;
-  }
-
-  bool isPointer(const Reference &) override;
-  bool isPairedReloc(const normalized::Relocation &) override;
-
-  bool needsCompactUnwind() override {
-    return true;
-  }
-  Reference::KindValue imageOffsetKind() override {
-    return imageOffset;
-  }
-  Reference::KindValue imageOffsetKindIndirect() override {
-    return imageOffsetGot;
-  }
-
-  Reference::KindValue unwindRefToPersonalityFunctionKind() override {
-    return unwindCIEToPersonalityFunction;
-  }
-
-  Reference::KindValue unwindRefToCIEKind() override {
-    return negDelta32;
-  }
-
-  Reference::KindValue unwindRefToFunctionKind() override {
-    return unwindFDEToFunction;
-  }
-
-  Reference::KindValue unwindRefToEhFrameKind() override {
-    return unwindInfoToEhFrame;
-  }
-
-  Reference::KindValue pointerKind() override {
-    return pointer64;
-  }
-
-  Reference::KindValue lazyImmediateLocationKind() override {
-    return lazyImmediateLocation;
-  }
-
-  uint32_t dwarfCompactUnwindType() override {
-    return 0x03000000;
-  }
-
-  llvm::Error getReferenceInfo(const normalized::Relocation &reloc,
-                               const DefinedAtom *inAtom,
-                               uint32_t offsetInAtom,
-                               uint64_t fixupAddress, bool isBig,
-                               FindAtomBySectionAndAddress atomFromAddress,
-                               FindAtomBySymbolIndex atomFromSymbolIndex,
-                               Reference::KindValue *kind,
-                               const lld::Atom **target,
-                               Reference::Addend *addend) override;
-  llvm::Error
-      getPairReferenceInfo(const normalized::Relocation &reloc1,
-                           const normalized::Relocation &reloc2,
-                           const DefinedAtom *inAtom,
-                           uint32_t offsetInAtom,
-                           uint64_t fixupAddress, bool isBig, bool scatterable,
-                           FindAtomBySectionAndAddress atomFromAddress,
-                           FindAtomBySymbolIndex atomFromSymbolIndex,
-                           Reference::KindValue *kind,
-                           const lld::Atom **target,
-                           Reference::Addend *addend) override;
-
-  bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) override {
-    return (atom->contentType() == DefinedAtom::typeCString);
-  }
-
-  void generateAtomContent(const DefinedAtom &atom, bool relocatable,
-                           FindAddressForAtom findAddress,
-                           FindAddressForAtom findSectionAddress,
-                           uint64_t imageBaseAddress,
-                    llvm::MutableArrayRef<uint8_t> atomContentBuffer) override;
-
-  void appendSectionRelocations(const DefinedAtom &atom,
-                                uint64_t atomSectionOffset,
-                                const Reference &ref,
-                                FindSymbolIndexForAtom symbolIndexForAtom,
-                                FindSectionIndexForAtom sectionIndexForAtom,
-                                FindAddressForAtom addressForAtom,
-                                normalized::Relocations &relocs) override;
-
-private:
-  static const Registry::KindStrings _sKindStrings[];
-  static const StubInfo _sStubInfo;
-
-  enum Arm64Kind : Reference::KindValue {
-    invalid,               /// for error condition
-
-    // Kinds found in mach-o .o files:
-    branch26,              /// ex: bl   _foo
-    page21,                /// ex: adrp x1, _foo@PAGE
-    offset12,              /// ex: ldrb w0, [x1, _foo@PAGEOFF]
-    offset12scale2,        /// ex: ldrs w0, [x1, _foo@PAGEOFF]
-    offset12scale4,        /// ex: ldr  w0, [x1, _foo@PAGEOFF]
-    offset12scale8,        /// ex: ldr  x0, [x1, _foo@PAGEOFF]
-    offset12scale16,       /// ex: ldr  q0, [x1, _foo@PAGEOFF]
-    gotPage21,             /// ex: adrp x1, _foo@GOTPAGE
-    gotOffset12,           /// ex: ldr  w0, [x1, _foo@GOTPAGEOFF]
-    tlvPage21,             /// ex: adrp x1, _foo@TLVPAGE
-    tlvOffset12,           /// ex: ldr  w0, [x1, _foo@TLVPAGEOFF]
-
-    pointer64,             /// ex: .quad _foo
-    delta64,               /// ex: .quad _foo - .
-    delta32,               /// ex: .long _foo - .
-    negDelta32,            /// ex: .long . - _foo
-    pointer64ToGOT,        /// ex: .quad _foo@GOT
-    delta32ToGOT,          /// ex: .long _foo@GOT - .
-
-    // Kinds introduced by Passes:
-    addOffset12,           /// Location contains LDR to change into ADD.
-    lazyPointer,           /// Location contains a lazy pointer.
-    lazyImmediateLocation, /// Location contains immediate value used in stub.
-    imageOffset,           /// Location contains offset of atom in final image
-    imageOffsetGot,        /// Location contains offset of GOT entry for atom in
-                           /// final image (typically personality function).
-    unwindCIEToPersonalityFunction,   /// Nearly delta32ToGOT, but cannot be
-                           /// rematerialized in relocatable object
-                           /// (yay for implicit contracts!).
-    unwindFDEToFunction,   /// Nearly delta64, but cannot be rematerialized in
-                           /// relocatable object (yay for implicit contracts!).
-    unwindInfoToEhFrame,   /// Fix low 24 bits of compact unwind encoding to
-                           /// refer to __eh_frame entry.
-  };
-
-  void applyFixupFinal(const Reference &ref, uint8_t *location,
-                       uint64_t fixupAddress, uint64_t targetAddress,
-                       uint64_t inAtomAddress, uint64_t imageBaseAddress,
-                       FindAddressForAtom findSectionAddress);
-
-  void applyFixupRelocatable(const Reference &ref, uint8_t *location,
-                             uint64_t fixupAddress, uint64_t targetAddress,
-                             uint64_t inAtomAddress, bool targetUnnamed);
-
-  // Utility functions for inspecting/updating instructions.
-  static uint32_t setDisplacementInBranch26(uint32_t instr, int32_t disp);
-  static uint32_t setDisplacementInADRP(uint32_t instr, int64_t disp);
-  static Arm64Kind offset12KindFromInstruction(uint32_t instr);
-  static uint32_t setImm12(uint32_t instr, uint32_t offset);
-};
-
-const Registry::KindStrings ArchHandler_arm64::_sKindStrings[] = {
-  LLD_KIND_STRING_ENTRY(invalid),
-  LLD_KIND_STRING_ENTRY(branch26),
-  LLD_KIND_STRING_ENTRY(page21),
-  LLD_KIND_STRING_ENTRY(offset12),
-  LLD_KIND_STRING_ENTRY(offset12scale2),
-  LLD_KIND_STRING_ENTRY(offset12scale4),
-  LLD_KIND_STRING_ENTRY(offset12scale8),
-  LLD_KIND_STRING_ENTRY(offset12scale16),
-  LLD_KIND_STRING_ENTRY(gotPage21),
-  LLD_KIND_STRING_ENTRY(gotOffset12),
-  LLD_KIND_STRING_ENTRY(tlvPage21),
-  LLD_KIND_STRING_ENTRY(tlvOffset12),
-  LLD_KIND_STRING_ENTRY(pointer64),
-  LLD_KIND_STRING_ENTRY(delta64),
-  LLD_KIND_STRING_ENTRY(delta32),
-  LLD_KIND_STRING_ENTRY(negDelta32),
-  LLD_KIND_STRING_ENTRY(pointer64ToGOT),
-  LLD_KIND_STRING_ENTRY(delta32ToGOT),
-
-  LLD_KIND_STRING_ENTRY(addOffset12),
-  LLD_KIND_STRING_ENTRY(lazyPointer),
-  LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
-  LLD_KIND_STRING_ENTRY(imageOffset),
-  LLD_KIND_STRING_ENTRY(imageOffsetGot),
-  LLD_KIND_STRING_ENTRY(unwindCIEToPersonalityFunction),
-  LLD_KIND_STRING_ENTRY(unwindFDEToFunction),
-  LLD_KIND_STRING_ENTRY(unwindInfoToEhFrame),
-
-  LLD_KIND_STRING_END
-};
-
-const ArchHandler::StubInfo ArchHandler_arm64::_sStubInfo = {
-  "dyld_stub_binder",
-
-  // Lazy pointer references
-  { Reference::KindArch::AArch64, pointer64, 0, 0 },
-  { Reference::KindArch::AArch64, lazyPointer, 0, 0 },
-
-  // GOT pointer to dyld_stub_binder
-  { Reference::KindArch::AArch64, pointer64, 0, 0 },
-
-  // arm64 code alignment 2^1
-  1,
-
-  // Stub size and code
-  12,
-  { 0x10, 0x00, 0x00, 0x90,   // ADRP  X16, lazy_pointer@page
-    0x10, 0x02, 0x40, 0xF9,   // LDR   X16, [X16, lazy_pointer@pageoff]
-    0x00, 0x02, 0x1F, 0xD6 }, // BR    X16
-  { Reference::KindArch::AArch64, page21, 0, 0 },
-  { true,                         offset12scale8, 4, 0 },
-
-  // Stub Helper size and code
-  12,
-  { 0x50, 0x00, 0x00, 0x18,   //      LDR   W16, L0
-    0x00, 0x00, 0x00, 0x14,   //      LDR   B  helperhelper
-    0x00, 0x00, 0x00, 0x00 }, // L0: .long 0
-  { Reference::KindArch::AArch64, lazyImmediateLocation, 8, 0 },
-  { Reference::KindArch::AArch64, branch26, 4, 0 },
-
-  // Stub helper image cache content type
-  DefinedAtom::typeGOT,
-
-  // Stub Helper-Common size and code
-  24,
-  // Stub helper alignment
-  2,
-  { 0x11, 0x00, 0x00, 0x90,   //  ADRP  X17, dyld_ImageLoaderCache@page
-    0x31, 0x02, 0x00, 0x91,   //  ADD   X17, X17, dyld_ImageLoaderCache@pageoff
-    0xF0, 0x47, 0xBF, 0xA9,   //  STP   X16/X17, [SP, #-16]!
-    0x10, 0x00, 0x00, 0x90,   //  ADRP  X16, _fast_lazy_bind@page
-    0x10, 0x02, 0x40, 0xF9,   //  LDR   X16, [X16,_fast_lazy_bind@pageoff]
-    0x00, 0x02, 0x1F, 0xD6 }, //  BR    X16
-  { Reference::KindArch::AArch64, page21,   0, 0 },
-  { true,                         offset12, 4, 0 },
-  { Reference::KindArch::AArch64, page21,   12, 0 },
-  { true,                         offset12scale8, 16, 0 }
-};
-
-bool ArchHandler_arm64::isCallSite(const Reference &ref) {
-  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
-    return false;
-  assert(ref.kindArch() == Reference::KindArch::AArch64);
-  return (ref.kindValue() == branch26);
-}
-
-bool ArchHandler_arm64::isPointer(const Reference &ref) {
-  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
-    return false;
-  assert(ref.kindArch() == Reference::KindArch::AArch64);
-  Reference::KindValue kind = ref.kindValue();
-  return (kind == pointer64);
-}
-
-bool ArchHandler_arm64::isPairedReloc(const Relocation &r) {
-  return ((r.type == ARM64_RELOC_ADDEND) || (r.type == ARM64_RELOC_SUBTRACTOR));
-}
-
-uint32_t ArchHandler_arm64::setDisplacementInBranch26(uint32_t instr,
-                                                      int32_t displacement) {
-  assert((displacement <= 134217727) && (displacement > (-134217728)) &&
-         "arm64 branch out of range");
-  return (instr & 0xFC000000) | ((uint32_t)(displacement >> 2) & 0x03FFFFFF);
-}
-
-uint32_t ArchHandler_arm64::setDisplacementInADRP(uint32_t instruction,
-                                                  int64_t displacement) {
-  assert((displacement <= 0x100000000LL) && (displacement > (-0x100000000LL)) &&
-         "arm64 ADRP out of range");
-  assert(((instruction & 0x9F000000) == 0x90000000) &&
-         "reloc not on ADRP instruction");
-  uint32_t immhi = (displacement >> 9) & (0x00FFFFE0);
-  uint32_t immlo = (displacement << 17) & (0x60000000);
-  return (instruction & 0x9F00001F) | immlo | immhi;
-}
-
-ArchHandler_arm64::Arm64Kind
-ArchHandler_arm64::offset12KindFromInstruction(uint32_t instruction) {
-  if (instruction & 0x08000000) {
-    switch ((instruction >> 30) & 0x3) {
-    case 0:
-      if ((instruction & 0x04800000) == 0x04800000)
-        return offset12scale16;
-      return offset12;
-    case 1:
-      return offset12scale2;
-    case 2:
-      return offset12scale4;
-    case 3:
-      return offset12scale8;
-    }
-  }
-  return offset12;
-}
-
-uint32_t ArchHandler_arm64::setImm12(uint32_t instruction, uint32_t offset) {
-  assert(((offset & 0xFFFFF000) == 0) && "imm12 offset out of range");
-  uint32_t imm12 = offset << 10;
-  return (instruction & 0xFFC003FF) | imm12;
-}
-
-llvm::Error ArchHandler_arm64::getReferenceInfo(
-    const Relocation &reloc, const DefinedAtom *inAtom, uint32_t offsetInAtom,
-    uint64_t fixupAddress, bool isBig,
-    FindAtomBySectionAndAddress atomFromAddress,
-    FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind,
-    const lld::Atom **target, Reference::Addend *addend) {
-  const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
-  switch (relocPattern(reloc)) {
-  case ARM64_RELOC_BRANCH26           | rPcRel | rExtern | rLength4:
-    // ex: bl _foo
-    *kind = branch26;
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    *addend = 0;
-    return llvm::Error::success();
-  case ARM64_RELOC_PAGE21             | rPcRel | rExtern | rLength4:
-    // ex: adrp x1, _foo@PAGE
-    *kind = page21;
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    *addend = 0;
-    return llvm::Error::success();
-  case ARM64_RELOC_PAGEOFF12                   | rExtern | rLength4:
-    // ex: ldr x0, [x1, _foo@PAGEOFF]
-    *kind = offset12KindFromInstruction(*(const little32_t *)fixupContent);
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    *addend = 0;
-    return llvm::Error::success();
-  case ARM64_RELOC_GOT_LOAD_PAGE21    | rPcRel | rExtern | rLength4:
-    // ex: adrp x1, _foo@GOTPAGE
-    *kind = gotPage21;
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    *addend = 0;
-    return llvm::Error::success();
-  case ARM64_RELOC_GOT_LOAD_PAGEOFF12          | rExtern | rLength4:
-    // ex: ldr x0, [x1, _foo@GOTPAGEOFF]
-    *kind = gotOffset12;
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    *addend = 0;
-    return llvm::Error::success();
-  case ARM64_RELOC_TLVP_LOAD_PAGE21   | rPcRel | rExtern | rLength4:
-    // ex: adrp x1, _foo@TLVPAGE
-    *kind = tlvPage21;
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    *addend = 0;
-    return llvm::Error::success();
-  case ARM64_RELOC_TLVP_LOAD_PAGEOFF12         | rExtern | rLength4:
-    // ex: ldr x0, [x1, _foo@TLVPAGEOFF]
-    *kind = tlvOffset12;
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    *addend = 0;
-    return llvm::Error::success();
-  case ARM64_RELOC_UNSIGNED                    | rExtern | rLength8:
-    // ex: .quad _foo + N
-    *kind = pointer64;
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    *addend = *(const little64_t *)fixupContent;
-    return llvm::Error::success();
-  case ARM64_RELOC_UNSIGNED                              | rLength8:
-     // ex: .quad Lfoo + N
-     *kind = pointer64;
-     return atomFromAddress(reloc.symbol, *(const little64_t *)fixupContent,
-                            target, addend);
-  case ARM64_RELOC_POINTER_TO_GOT              | rExtern | rLength8:
-    // ex: .quad _foo@GOT
-    *kind = pointer64ToGOT;
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    *addend = 0;
-    return llvm::Error::success();
-  case ARM64_RELOC_POINTER_TO_GOT     | rPcRel | rExtern | rLength4:
-    // ex: .long _foo@GOT - .
-
-    // If we are in an .eh_frame section, then the kind of the relocation should
-    // not be delta32ToGOT.  It may instead be unwindCIEToPersonalityFunction.
-    if (inAtom->contentType() == DefinedAtom::typeCFI)
-      *kind = unwindCIEToPersonalityFunction;
-    else
-      *kind = delta32ToGOT;
-
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    *addend = 0;
-    return llvm::Error::success();
-  default:
-    return llvm::make_error<GenericError>("unsupported arm64 relocation type");
-  }
-}
-
-llvm::Error ArchHandler_arm64::getPairReferenceInfo(
-    const normalized::Relocation &reloc1, const normalized::Relocation &reloc2,
-    const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress,
-    bool swap, bool scatterable, FindAtomBySectionAndAddress atomFromAddress,
-    FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind,
-    const lld::Atom **target, Reference::Addend *addend) {
-  const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
-  switch (relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
-  case ((ARM64_RELOC_ADDEND                                | rLength4) << 16 |
-         ARM64_RELOC_BRANCH26           | rPcRel | rExtern | rLength4):
-    // ex: bl _foo+8
-    *kind = branch26;
-    if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
-      return ec;
-    *addend = reloc1.symbol;
-    return llvm::Error::success();
-  case ((ARM64_RELOC_ADDEND                                | rLength4) << 16 |
-         ARM64_RELOC_PAGE21             | rPcRel | rExtern | rLength4):
-    // ex: adrp x1, _foo@PAGE
-    *kind = page21;
-    if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
-      return ec;
-    *addend = reloc1.symbol;
-    return llvm::Error::success();
-  case ((ARM64_RELOC_ADDEND                                | rLength4) << 16 |
-         ARM64_RELOC_PAGEOFF12                   | rExtern | rLength4): {
-    // ex: ldr w0, [x1, _foo@PAGEOFF]
-    uint32_t cont32 = (int32_t)*(const little32_t *)fixupContent;
-    *kind = offset12KindFromInstruction(cont32);
-    if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
-      return ec;
-    *addend = reloc1.symbol;
-    return llvm::Error::success();
-  }
-  case ((ARM64_RELOC_SUBTRACTOR                  | rExtern | rLength8) << 16 |
-         ARM64_RELOC_UNSIGNED                    | rExtern | rLength8):
-    // ex: .quad _foo - .
-    if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
-      return ec;
-
-    // If we are in an .eh_frame section, then the kind of the relocation should
-    // not be delta64.  It may instead be unwindFDEToFunction.
-    if (inAtom->contentType() == DefinedAtom::typeCFI)
-      *kind = unwindFDEToFunction;
-    else
-      *kind = delta64;
-
-    // The offsets of the 2 relocations must match
-    if (reloc1.offset != reloc2.offset)
-      return llvm::make_error<GenericError>(
-                                    "paired relocs must have the same offset");
-    *addend = (int64_t)*(const little64_t *)fixupContent + offsetInAtom;
-    return llvm::Error::success();
-  case ((ARM64_RELOC_SUBTRACTOR                  | rExtern | rLength4) << 16 |
-         ARM64_RELOC_UNSIGNED                    | rExtern | rLength4):
-    // ex: .quad _foo - .
-    *kind = delta32;
-    if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
-      return ec;
-    *addend = (int32_t)*(const little32_t *)fixupContent + offsetInAtom;
-    return llvm::Error::success();
-  default:
-    return llvm::make_error<GenericError>("unsupported arm64 relocation pair");
-  }
-}
-
-void ArchHandler_arm64::generateAtomContent(
-    const DefinedAtom &atom, bool relocatable, FindAddressForAtom findAddress,
-    FindAddressForAtom findSectionAddress, uint64_t imageBaseAddress,
-    llvm::MutableArrayRef<uint8_t> atomContentBuffer) {
-  // Copy raw bytes.
-  std::copy(atom.rawContent().begin(), atom.rawContent().end(),
-            atomContentBuffer.begin());
-  // Apply fix-ups.
-#ifndef NDEBUG
-  if (atom.begin() != atom.end()) {
-    DEBUG_WITH_TYPE("atom-content", llvm::dbgs()
-                    << "Applying fixups to atom:\n"
-                    << "   address="
-                    << llvm::format("    0x%09lX", &atom)
-                    << ", file=#"
-                    << atom.file().ordinal()
-                    << ", atom=#"
-                    << atom.ordinal()
-                    << ", name="
-                    << atom.name()
-                    << ", type="
-                    << atom.contentType()
-                    << "\n");
-  }
-#endif
-  for (const Reference *ref : atom) {
-    uint32_t offset = ref->offsetInAtom();
-    const Atom *target = ref->target();
-    bool targetUnnamed = target->name().empty();
-    uint64_t targetAddress = 0;
-    if (isa<DefinedAtom>(target))
-      targetAddress = findAddress(*target);
-    uint64_t atomAddress = findAddress(atom);
-    uint64_t fixupAddress = atomAddress + offset;
-    if (relocatable) {
-      applyFixupRelocatable(*ref, &atomContentBuffer[offset], fixupAddress,
-                            targetAddress, atomAddress, targetUnnamed);
-    } else {
-      applyFixupFinal(*ref, &atomContentBuffer[offset], fixupAddress,
-                      targetAddress, atomAddress, imageBaseAddress,
-                      findSectionAddress);
-    }
-  }
-}
-
-void ArchHandler_arm64::applyFixupFinal(const Reference &ref, uint8_t *loc,
-                                        uint64_t fixupAddress,
-                                        uint64_t targetAddress,
-                                        uint64_t inAtomAddress,
-                                        uint64_t imageBaseAddress,
-                                        FindAddressForAtom findSectionAddress) {
-  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
-    return;
-  assert(ref.kindArch() == Reference::KindArch::AArch64);
-  ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
-  ulittle64_t *loc64 = reinterpret_cast<ulittle64_t *>(loc);
-  int32_t displacement;
-  uint32_t instruction;
-  uint32_t value32;
-  uint32_t value64;
-  switch (static_cast<Arm64Kind>(ref.kindValue())) {
-  case branch26:
-    displacement = (targetAddress - fixupAddress) + ref.addend();
-    *loc32 = setDisplacementInBranch26(*loc32, displacement);
-    return;
-  case page21:
-  case gotPage21:
-  case tlvPage21:
-    displacement =
-        ((targetAddress + ref.addend()) & (-4096)) - (fixupAddress & (-4096));
-    *loc32 = setDisplacementInADRP(*loc32, displacement);
-    return;
-  case offset12:
-  case gotOffset12:
-  case tlvOffset12:
-    displacement = (targetAddress + ref.addend()) & 0x00000FFF;
-    *loc32 = setImm12(*loc32, displacement);
-    return;
-  case offset12scale2:
-    displacement = (targetAddress + ref.addend()) & 0x00000FFF;
-    assert(((displacement & 0x1) == 0) &&
-           "scaled imm12 not accessing 2-byte aligneds");
-    *loc32 = setImm12(*loc32, displacement >> 1);
-    return;
-  case offset12scale4:
-    displacement = (targetAddress + ref.addend()) & 0x00000FFF;
-    assert(((displacement & 0x3) == 0) &&
-           "scaled imm12 not accessing 4-byte aligned");
-    *loc32 = setImm12(*loc32, displacement >> 2);
-    return;
-  case offset12scale8:
-    displacement = (targetAddress + ref.addend()) & 0x00000FFF;
-    assert(((displacement & 0x7) == 0) &&
-           "scaled imm12 not accessing 8-byte aligned");
-    *loc32 = setImm12(*loc32, displacement >> 3);
-    return;
-  case offset12scale16:
-    displacement = (targetAddress + ref.addend()) & 0x00000FFF;
-    assert(((displacement & 0xF) == 0) &&
-           "scaled imm12 not accessing 16-byte aligned");
-    *loc32 = setImm12(*loc32, displacement >> 4);
-    return;
-  case addOffset12:
-    instruction = *loc32;
-    assert(((instruction & 0xFFC00000) == 0xF9400000) &&
-           "GOT reloc is not an LDR instruction");
-    displacement = (targetAddress + ref.addend()) & 0x00000FFF;
-    value32 = 0x91000000 | (instruction & 0x000003FF);
-    instruction = setImm12(value32, displacement);
-    *loc32 = instruction;
-    return;
-  case pointer64:
-  case pointer64ToGOT:
-    *loc64 = targetAddress + ref.addend();
-    return;
-  case delta64:
-  case unwindFDEToFunction:
-    *loc64 = (targetAddress - fixupAddress) + ref.addend();
-    return;
-  case delta32:
-  case delta32ToGOT:
-  case unwindCIEToPersonalityFunction:
-    *loc32 = (targetAddress - fixupAddress) + ref.addend();
-    return;
-  case negDelta32:
-    *loc32 = fixupAddress - targetAddress + ref.addend();
-    return;
-  case lazyPointer:
-    // Do nothing
-    return;
-  case lazyImmediateLocation:
-    *loc32 = ref.addend();
-    return;
-  case imageOffset:
-    *loc32 = (targetAddress - imageBaseAddress) + ref.addend();
-    return;
-  case imageOffsetGot:
-    llvm_unreachable("imageOffsetGot should have been changed to imageOffset");
-    break;
-  case unwindInfoToEhFrame:
-    value64 = targetAddress - findSectionAddress(*ref.target()) + ref.addend();
-    assert(value64 < 0xffffffU && "offset in __eh_frame too large");
-    *loc32 = (*loc32 & 0xff000000U) | value64;
-    return;
-  case invalid:
-    // Fall into llvm_unreachable().
-    break;
-  }
-  llvm_unreachable("invalid arm64 Reference Kind");
-}
-
-void ArchHandler_arm64::applyFixupRelocatable(const Reference &ref,
-                                              uint8_t *loc,
-                                              uint64_t fixupAddress,
-                                              uint64_t targetAddress,
-                                              uint64_t inAtomAddress,
-                                              bool targetUnnamed) {
-  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
-    return;
-  assert(ref.kindArch() == Reference::KindArch::AArch64);
-  ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
-  ulittle64_t *loc64 = reinterpret_cast<ulittle64_t *>(loc);
-  switch (static_cast<Arm64Kind>(ref.kindValue())) {
-  case branch26:
-    *loc32 = setDisplacementInBranch26(*loc32, 0);
-    return;
-  case page21:
-  case gotPage21:
-  case tlvPage21:
-    *loc32 = setDisplacementInADRP(*loc32, 0);
-    return;
-  case offset12:
-  case offset12scale2:
-  case offset12scale4:
-  case offset12scale8:
-  case offset12scale16:
-  case gotOffset12:
-  case tlvOffset12:
-    *loc32 = setImm12(*loc32, 0);
-    return;
-  case pointer64:
-    if (targetUnnamed)
-      *loc64 = targetAddress + ref.addend();
-    else
-      *loc64 = ref.addend();
-    return;
-  case delta64:
-    *loc64 = ref.addend() + inAtomAddress - fixupAddress;
-    return;
-  case unwindFDEToFunction:
-    // We don't emit unwindFDEToFunction in -r mode as they are implicitly
-    // generated from the data in the __eh_frame section.  So here we need
-    // to use the targetAddress so that we can generate the full relocation
-    // when we parse again later.
-    *loc64 = targetAddress - fixupAddress;
-    return;
-  case delta32:
-    *loc32 = ref.addend() + inAtomAddress - fixupAddress;
-    return;
-  case negDelta32:
-    // We don't emit negDelta32 in -r mode as they are implicitly
-    // generated from the data in the __eh_frame section.  So here we need
-    // to use the targetAddress so that we can generate the full relocation
-    // when we parse again later.
-    *loc32 = fixupAddress - targetAddress + ref.addend();
-    return;
-  case pointer64ToGOT:
-    *loc64 = 0;
-    return;
-  case delta32ToGOT:
-    *loc32 = inAtomAddress - fixupAddress;
-    return;
-  case unwindCIEToPersonalityFunction:
-    // We don't emit unwindCIEToPersonalityFunction in -r mode as they are
-    // implicitly generated from the data in the __eh_frame section.  So here we
-    // need to use the targetAddress so that we can generate the full relocation
-    // when we parse again later.
-    *loc32 = targetAddress - fixupAddress;
-    return;
-  case addOffset12:
-    llvm_unreachable("lazy reference kind implies GOT pass was run");
-  case lazyPointer:
-  case lazyImmediateLocation:
-    llvm_unreachable("lazy reference kind implies Stubs pass was run");
-  case imageOffset:
-  case imageOffsetGot:
-  case unwindInfoToEhFrame:
-    llvm_unreachable("fixup implies __unwind_info");
-    return;
-  case invalid:
-    // Fall into llvm_unreachable().
-    break;
-  }
-  llvm_unreachable("unknown arm64 Reference Kind");
-}
-
-void ArchHandler_arm64::appendSectionRelocations(
-    const DefinedAtom &atom, uint64_t atomSectionOffset, const Reference &ref,
-    FindSymbolIndexForAtom symbolIndexForAtom,
-    FindSectionIndexForAtom sectionIndexForAtom,
-    FindAddressForAtom addressForAtom, normalized::Relocations &relocs) {
-  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
-    return;
-  assert(ref.kindArch() == Reference::KindArch::AArch64);
-  uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom();
-  switch (static_cast<Arm64Kind>(ref.kindValue())) {
-  case branch26:
-    if (ref.addend()) {
-      appendReloc(relocs, sectionOffset, ref.addend(), 0,
-                  ARM64_RELOC_ADDEND | rLength4);
-      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  ARM64_RELOC_BRANCH26 | rPcRel | rExtern | rLength4);
-     } else {
-      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  ARM64_RELOC_BRANCH26 | rPcRel | rExtern | rLength4);
-    }
-    return;
-  case page21:
-    if (ref.addend()) {
-      appendReloc(relocs, sectionOffset, ref.addend(), 0,
-                  ARM64_RELOC_ADDEND | rLength4);
-      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  ARM64_RELOC_PAGE21 | rPcRel | rExtern | rLength4);
-     } else {
-      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  ARM64_RELOC_PAGE21 | rPcRel | rExtern | rLength4);
-    }
-    return;
-  case offset12:
-  case offset12scale2:
-  case offset12scale4:
-  case offset12scale8:
-  case offset12scale16:
-    if (ref.addend()) {
-      appendReloc(relocs, sectionOffset, ref.addend(), 0,
-                  ARM64_RELOC_ADDEND | rLength4);
-      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  ARM64_RELOC_PAGEOFF12  | rExtern | rLength4);
-     } else {
-      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  ARM64_RELOC_PAGEOFF12 | rExtern | rLength4);
-    }
-    return;
-  case gotPage21:
-    assert(ref.addend() == 0);
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  ARM64_RELOC_GOT_LOAD_PAGE21 | rPcRel | rExtern | rLength4);
-    return;
-  case gotOffset12:
-    assert(ref.addend() == 0);
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  ARM64_RELOC_GOT_LOAD_PAGEOFF12 | rExtern | rLength4);
-    return;
-  case tlvPage21:
-    assert(ref.addend() == 0);
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  ARM64_RELOC_TLVP_LOAD_PAGE21 | rPcRel | rExtern | rLength4);
-    return;
-  case tlvOffset12:
-    assert(ref.addend() == 0);
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  ARM64_RELOC_TLVP_LOAD_PAGEOFF12 | rExtern | rLength4);
-    return;
-  case pointer64:
-    if (ref.target()->name().empty())
-      appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
-                  ARM64_RELOC_UNSIGNED           | rLength8);
-    else
-      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  ARM64_RELOC_UNSIGNED | rExtern | rLength8);
-    return;
-  case delta64:
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
-                ARM64_RELOC_SUBTRACTOR | rExtern | rLength8);
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                ARM64_RELOC_UNSIGNED  | rExtern | rLength8);
-    return;
-  case delta32:
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
-                ARM64_RELOC_SUBTRACTOR | rExtern | rLength4 );
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                ARM64_RELOC_UNSIGNED   | rExtern | rLength4 );
-    return;
-  case pointer64ToGOT:
-    assert(ref.addend() == 0);
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  ARM64_RELOC_POINTER_TO_GOT | rExtern | rLength8);
-    return;
-  case delta32ToGOT:
-    assert(ref.addend() == 0);
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  ARM64_RELOC_POINTER_TO_GOT | rPcRel | rExtern | rLength4);
-    return;
-  case addOffset12:
-    llvm_unreachable("lazy reference kind implies GOT pass was run");
-  case lazyPointer:
-  case lazyImmediateLocation:
-    llvm_unreachable("lazy reference kind implies Stubs pass was run");
-  case imageOffset:
-  case imageOffsetGot:
-    llvm_unreachable("deltas from mach_header can only be in final images");
-  case unwindCIEToPersonalityFunction:
-  case unwindFDEToFunction:
-  case unwindInfoToEhFrame:
-  case negDelta32:
-    // Do nothing.
-    return;
-  case invalid:
-    // Fall into llvm_unreachable().
-    break;
-  }
-  llvm_unreachable("unknown arm64 Reference Kind");
-}
-
-std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_arm64() {
-  return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_arm64());
-}
-
-} // namespace mach_o
-} // namespace lld
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp b/gnu/llvm/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
deleted file mode 100644 (file)
index 6ea8e8c..0000000
+++ /dev/null
@@ -1,643 +0,0 @@
-//===- lib/FileFormat/MachO/ArchHandler_x86.cpp ---------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "Atoms.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorHandling.h"
-
-using namespace llvm::MachO;
-using namespace lld::mach_o::normalized;
-
-namespace lld {
-namespace mach_o {
-
-using llvm::support::ulittle16_t;
-using llvm::support::ulittle32_t;
-
-using llvm::support::little16_t;
-using llvm::support::little32_t;
-
-class ArchHandler_x86 : public ArchHandler {
-public:
-  ArchHandler_x86() = default;
-  ~ArchHandler_x86() override = default;
-
-  const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
-
-  Reference::KindArch kindArch() override { return Reference::KindArch::x86; }
-
-  const StubInfo &stubInfo() override { return _sStubInfo; }
-  bool isCallSite(const Reference &) override;
-  bool isNonCallBranch(const Reference &) override {
-    return false;
-  }
-
-  bool isPointer(const Reference &) override;
-  bool isPairedReloc(const normalized::Relocation &) override;
-
-  bool needsCompactUnwind() override {
-    return false;
-  }
-
-  Reference::KindValue imageOffsetKind() override {
-    return invalid;
-  }
-
-  Reference::KindValue imageOffsetKindIndirect() override {
-    return invalid;
-  }
-
-  Reference::KindValue unwindRefToPersonalityFunctionKind() override {
-    return invalid;
-  }
-
-  Reference::KindValue unwindRefToCIEKind() override {
-    return negDelta32;
-  }
-
-  Reference::KindValue unwindRefToFunctionKind() override{
-    return delta32;
-  }
-
-  Reference::KindValue lazyImmediateLocationKind() override {
-    return lazyImmediateLocation;
-  }
-
-  Reference::KindValue unwindRefToEhFrameKind() override {
-    return invalid;
-  }
-
-  Reference::KindValue pointerKind() override {
-    return invalid;
-  }
-
-  uint32_t dwarfCompactUnwindType() override {
-    return 0x04000000U;
-  }
-
-  llvm::Error getReferenceInfo(const normalized::Relocation &reloc,
-                               const DefinedAtom *inAtom,
-                               uint32_t offsetInAtom,
-                               uint64_t fixupAddress, bool swap,
-                               FindAtomBySectionAndAddress atomFromAddress,
-                               FindAtomBySymbolIndex atomFromSymbolIndex,
-                               Reference::KindValue *kind,
-                               const lld::Atom **target,
-                               Reference::Addend *addend) override;
-  llvm::Error
-      getPairReferenceInfo(const normalized::Relocation &reloc1,
-                           const normalized::Relocation &reloc2,
-                           const DefinedAtom *inAtom,
-                           uint32_t offsetInAtom,
-                           uint64_t fixupAddress, bool swap, bool scatterable,
-                           FindAtomBySectionAndAddress atomFromAddress,
-                           FindAtomBySymbolIndex atomFromSymbolIndex,
-                           Reference::KindValue *kind,
-                           const lld::Atom **target,
-                           Reference::Addend *addend) override;
-
-  void generateAtomContent(const DefinedAtom &atom, bool relocatable,
-                           FindAddressForAtom findAddress,
-                           FindAddressForAtom findSectionAddress,
-                           uint64_t imageBaseAddress,
-                    llvm::MutableArrayRef<uint8_t> atomContentBuffer) override;
-
-  void appendSectionRelocations(const DefinedAtom &atom,
-                                uint64_t atomSectionOffset,
-                                const Reference &ref,
-                                FindSymbolIndexForAtom symbolIndexForAtom,
-                                FindSectionIndexForAtom sectionIndexForAtom,
-                                FindAddressForAtom addressForAtom,
-                                normalized::Relocations &relocs) override;
-
-  bool isDataInCodeTransition(Reference::KindValue refKind) override {
-    return refKind == modeCode || refKind == modeData;
-  }
-
-  Reference::KindValue dataInCodeTransitionStart(
-                                        const MachODefinedAtom &atom) override {
-    return modeData;
-  }
-
-  Reference::KindValue dataInCodeTransitionEnd(
-                                        const MachODefinedAtom &atom) override {
-    return modeCode;
-  }
-
-private:
-  static const Registry::KindStrings _sKindStrings[];
-  static const StubInfo              _sStubInfo;
-
-  enum X86Kind : Reference::KindValue {
-    invalid,               /// for error condition
-
-    modeCode,              /// Content starting at this offset is code.
-    modeData,              /// Content starting at this offset is data.
-
-    // Kinds found in mach-o .o files:
-    branch32,              /// ex: call _foo
-    branch16,              /// ex: callw _foo
-    abs32,                 /// ex: movl _foo, %eax
-    funcRel32,             /// ex: movl _foo-L1(%eax), %eax
-    pointer32,             /// ex: .long _foo
-    delta32,               /// ex: .long _foo - .
-    negDelta32,            /// ex: .long . - _foo
-
-    // Kinds introduced by Passes:
-    lazyPointer,           /// Location contains a lazy pointer.
-    lazyImmediateLocation, /// Location contains immediate value used in stub.
-  };
-
-  static bool useExternalRelocationTo(const Atom &target);
-
-  void applyFixupFinal(const Reference &ref, uint8_t *location,
-                       uint64_t fixupAddress, uint64_t targetAddress,
-                       uint64_t inAtomAddress);
-
-  void applyFixupRelocatable(const Reference &ref, uint8_t *location,
-                             uint64_t fixupAddress,
-                             uint64_t targetAddress,
-                             uint64_t inAtomAddress);
-};
-
-//===----------------------------------------------------------------------===//
-//  ArchHandler_x86
-//===----------------------------------------------------------------------===//
-
-const Registry::KindStrings ArchHandler_x86::_sKindStrings[] = {
-  LLD_KIND_STRING_ENTRY(invalid),
-  LLD_KIND_STRING_ENTRY(modeCode),
-  LLD_KIND_STRING_ENTRY(modeData),
-  LLD_KIND_STRING_ENTRY(branch32),
-  LLD_KIND_STRING_ENTRY(branch16),
-  LLD_KIND_STRING_ENTRY(abs32),
-  LLD_KIND_STRING_ENTRY(funcRel32),
-  LLD_KIND_STRING_ENTRY(pointer32),
-  LLD_KIND_STRING_ENTRY(delta32),
-  LLD_KIND_STRING_ENTRY(negDelta32),
-  LLD_KIND_STRING_ENTRY(lazyPointer),
-  LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
-  LLD_KIND_STRING_END
-};
-
-const ArchHandler::StubInfo ArchHandler_x86::_sStubInfo = {
-  "dyld_stub_binder",
-
-  // Lazy pointer references
-  { Reference::KindArch::x86, pointer32, 0, 0 },
-  { Reference::KindArch::x86, lazyPointer, 0, 0 },
-
-  // GOT pointer to dyld_stub_binder
-  { Reference::KindArch::x86, pointer32, 0, 0 },
-
-  // x86 code alignment
-  1,
-
-  // Stub size and code
-  6,
-  { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 },       // jmp *lazyPointer
-  { Reference::KindArch::x86, abs32, 2, 0 },
-  { false, 0, 0, 0 },
-
-  // Stub Helper size and code
-  10,
-  { 0x68, 0x00, 0x00, 0x00, 0x00,               // pushl $lazy-info-offset
-    0xE9, 0x00, 0x00, 0x00, 0x00 },             // jmp helperhelper
-  { Reference::KindArch::x86, lazyImmediateLocation, 1, 0 },
-  { Reference::KindArch::x86, branch32, 6, 0 },
-
-  // Stub helper image cache content type
-  DefinedAtom::typeNonLazyPointer,
-
-  // Stub Helper-Common size and code
-  12,
-  // Stub helper alignment
-  2,
-  { 0x68, 0x00, 0x00, 0x00, 0x00,               // pushl $dyld_ImageLoaderCache
-    0xFF, 0x25, 0x00, 0x00, 0x00, 0x00,         // jmp *_fast_lazy_bind
-    0x90 },                                     // nop
-  { Reference::KindArch::x86, abs32, 1, 0 },
-  { false, 0, 0, 0 },
-  { Reference::KindArch::x86, abs32, 7, 0 },
-  { false, 0, 0, 0 }
-};
-
-bool ArchHandler_x86::isCallSite(const Reference &ref) {
-  return (ref.kindValue() == branch32);
-}
-
-bool ArchHandler_x86::isPointer(const Reference &ref) {
-  return (ref.kindValue() == pointer32);
-}
-
-bool ArchHandler_x86::isPairedReloc(const Relocation &reloc) {
-  if (!reloc.scattered)
-    return false;
-  return (reloc.type == GENERIC_RELOC_LOCAL_SECTDIFF) ||
-         (reloc.type == GENERIC_RELOC_SECTDIFF);
-}
-
-llvm::Error
-ArchHandler_x86::getReferenceInfo(const Relocation &reloc,
-                                  const DefinedAtom *inAtom,
-                                  uint32_t offsetInAtom,
-                                  uint64_t fixupAddress, bool swap,
-                                  FindAtomBySectionAndAddress atomFromAddress,
-                                  FindAtomBySymbolIndex atomFromSymbolIndex,
-                                  Reference::KindValue *kind,
-                                  const lld::Atom **target,
-                                  Reference::Addend *addend) {
-  DefinedAtom::ContentPermissions perms;
-  const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
-  uint64_t targetAddress;
-  switch (relocPattern(reloc)) {
-  case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength4:
-    // ex: call _foo (and _foo undefined)
-    *kind = branch32;
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    *addend = fixupAddress + 4 + (int32_t)*(const little32_t *)fixupContent;
-    break;
-  case GENERIC_RELOC_VANILLA | rPcRel | rLength4:
-    // ex: call _foo (and _foo defined)
-    *kind = branch32;
-    targetAddress =
-        fixupAddress + 4 + (int32_t) * (const little32_t *)fixupContent;
-    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
-    break;
-  case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength4:
-    // ex: call _foo+n (and _foo defined)
-    *kind = branch32;
-    targetAddress =
-        fixupAddress + 4 + (int32_t) * (const little32_t *)fixupContent;
-    if (auto ec = atomFromAddress(0, reloc.value, target, addend))
-      return ec;
-    *addend = targetAddress - reloc.value;
-    break;
-  case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength2:
-    // ex: callw _foo (and _foo undefined)
-    *kind = branch16;
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    *addend = fixupAddress + 2 + (int16_t)*(const little16_t *)fixupContent;
-    break;
-  case GENERIC_RELOC_VANILLA | rPcRel | rLength2:
-    // ex: callw _foo (and _foo defined)
-    *kind = branch16;
-    targetAddress =
-        fixupAddress + 2 + (int16_t) * (const little16_t *)fixupContent;
-    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
-    break;
-  case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength2:
-    // ex: callw _foo+n (and _foo defined)
-    *kind = branch16;
-    targetAddress =
-        fixupAddress + 2 + (int16_t) * (const little16_t *)fixupContent;
-    if (auto ec = atomFromAddress(0, reloc.value, target, addend))
-      return ec;
-    *addend = targetAddress - reloc.value;
-    break;
-  case GENERIC_RELOC_VANILLA | rExtern | rLength4:
-    // ex: movl        _foo, %eax   (and _foo undefined)
-    // ex: .long _foo        (and _foo undefined)
-    perms = inAtom->permissions();
-    *kind =
-        ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32
-                                                                 : pointer32;
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    *addend = *(const ulittle32_t *)fixupContent;
-    break;
-  case GENERIC_RELOC_VANILLA | rLength4:
-    // ex: movl        _foo, %eax   (and _foo defined)
-    // ex: .long _foo        (and _foo defined)
-    perms = inAtom->permissions();
-    *kind =
-        ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32
-                                                                 : pointer32;
-    targetAddress = *(const ulittle32_t *)fixupContent;
-    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
-    break;
-  case GENERIC_RELOC_VANILLA | rScattered | rLength4:
-    // ex: .long _foo+n      (and _foo defined)
-    perms = inAtom->permissions();
-    *kind =
-        ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32
-                                                                 : pointer32;
-    if (auto ec = atomFromAddress(0, reloc.value, target, addend))
-      return ec;
-    *addend = *(const ulittle32_t *)fixupContent - reloc.value;
-    break;
-  default:
-    return llvm::make_error<GenericError>("unsupported i386 relocation type");
-  }
-  return llvm::Error::success();
-}
-
-llvm::Error
-ArchHandler_x86::getPairReferenceInfo(const normalized::Relocation &reloc1,
-                                      const normalized::Relocation &reloc2,
-                                      const DefinedAtom *inAtom,
-                                      uint32_t offsetInAtom,
-                                      uint64_t fixupAddress, bool swap,
-                                      bool scatterable,
-                                      FindAtomBySectionAndAddress atomFromAddr,
-                                      FindAtomBySymbolIndex atomFromSymbolIndex,
-                                      Reference::KindValue *kind,
-                                      const lld::Atom **target,
-                                      Reference::Addend *addend) {
-  const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
-  DefinedAtom::ContentPermissions perms = inAtom->permissions();
-  uint32_t fromAddress;
-  uint32_t toAddress;
-  uint32_t value;
-  const lld::Atom *fromTarget;
-  Reference::Addend offsetInTo;
-  Reference::Addend offsetInFrom;
-  switch (relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
-  case ((GENERIC_RELOC_SECTDIFF | rScattered | rLength4) << 16 |
-         GENERIC_RELOC_PAIR | rScattered | rLength4):
-  case ((GENERIC_RELOC_LOCAL_SECTDIFF | rScattered | rLength4) << 16 |
-         GENERIC_RELOC_PAIR | rScattered | rLength4):
-    toAddress = reloc1.value;
-    fromAddress = reloc2.value;
-    value = *(const little32_t *)fixupContent;
-    if (auto ec = atomFromAddr(0, toAddress, target, &offsetInTo))
-      return ec;
-    if (auto ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom))
-      return ec;
-    if (fromTarget != inAtom) {
-      if (*target != inAtom)
-        return llvm::make_error<GenericError>(
-            "SECTDIFF relocation where neither target is in atom");
-      *kind = negDelta32;
-      *addend = toAddress - value - fromAddress;
-      *target = fromTarget;
-    } else {
-      if ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) {
-        // SECTDIFF relocations are used in i386 codegen where the function
-        // prolog does a CALL to the next instruction which POPs the return
-        // address into EBX which becomes the pic-base register.  The POP
-        // instruction is label the used for the subtrahend in expressions.
-        // The funcRel32 kind represents the 32-bit delta to some symbol from
-        // the start of the function (atom) containing the funcRel32.
-        *kind = funcRel32;
-        uint32_t ta = fromAddress + value - toAddress;
-        *addend = ta - offsetInFrom;
-      } else {
-        *kind = delta32;
-        *addend = fromAddress + value - toAddress;
-      }
-    }
-    return llvm::Error::success();
-    break;
-  default:
-    return llvm::make_error<GenericError>("unsupported i386 relocation type");
-  }
-}
-
-void ArchHandler_x86::generateAtomContent(const DefinedAtom &atom,
-                                          bool relocatable,
-                                          FindAddressForAtom findAddress,
-                                          FindAddressForAtom findSectionAddress,
-                                          uint64_t imageBaseAddress,
-                            llvm::MutableArrayRef<uint8_t> atomContentBuffer) {
-  // Copy raw bytes.
-  std::copy(atom.rawContent().begin(), atom.rawContent().end(),
-            atomContentBuffer.begin());
-  // Apply fix-ups.
-  for (const Reference *ref : atom) {
-    uint32_t offset = ref->offsetInAtom();
-    const Atom *target = ref->target();
-    uint64_t targetAddress = 0;
-    if (isa<DefinedAtom>(target))
-      targetAddress = findAddress(*target);
-    uint64_t atomAddress = findAddress(atom);
-    uint64_t fixupAddress = atomAddress + offset;
-    if (relocatable) {
-      applyFixupRelocatable(*ref, &atomContentBuffer[offset],
-                                        fixupAddress, targetAddress,
-                                        atomAddress);
-    } else {
-      applyFixupFinal(*ref, &atomContentBuffer[offset],
-                                  fixupAddress, targetAddress,
-                                  atomAddress);
-    }
-  }
-}
-
-void ArchHandler_x86::applyFixupFinal(const Reference &ref, uint8_t *loc,
-                                      uint64_t fixupAddress,
-                                      uint64_t targetAddress,
-                                      uint64_t inAtomAddress) {
-  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
-    return;
-  assert(ref.kindArch() == Reference::KindArch::x86);
-  ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
-  switch (static_cast<X86Kind>(ref.kindValue())) {
-  case branch32:
-    *loc32 = (targetAddress - (fixupAddress + 4)) + ref.addend();
-    break;
-  case branch16:
-    *loc32 = (targetAddress - (fixupAddress + 2)) + ref.addend();
-    break;
-  case pointer32:
-  case abs32:
-    *loc32 = targetAddress + ref.addend();
-    break;
-  case funcRel32:
-    *loc32 = targetAddress - inAtomAddress + ref.addend();
-    break;
-  case delta32:
-    *loc32 = targetAddress - fixupAddress + ref.addend();
-    break;
-  case negDelta32:
-    *loc32 = fixupAddress - targetAddress + ref.addend();
-    break;
-  case modeCode:
-  case modeData:
-  case lazyPointer:
-    // do nothing
-    break;
-  case lazyImmediateLocation:
-    *loc32 = ref.addend();
-    break;
-  case invalid:
-    llvm_unreachable("invalid x86 Reference Kind");
-    break;
-  }
-}
-
-void ArchHandler_x86::applyFixupRelocatable(const Reference &ref,
-                                               uint8_t *loc,
-                                               uint64_t fixupAddress,
-                                               uint64_t targetAddress,
-                                               uint64_t inAtomAddress) {
-  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
-    return;
-  assert(ref.kindArch() == Reference::KindArch::x86);
-  bool useExternalReloc = useExternalRelocationTo(*ref.target());
-  ulittle16_t *loc16 = reinterpret_cast<ulittle16_t *>(loc);
-  ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
-  switch (static_cast<X86Kind>(ref.kindValue())) {
-  case branch32:
-    if (useExternalReloc)
-      *loc32 = ref.addend() - (fixupAddress + 4);
-    else
-      *loc32  =(targetAddress - (fixupAddress+4)) + ref.addend();
-    break;
-  case branch16:
-    if (useExternalReloc)
-      *loc16 = ref.addend() - (fixupAddress + 2);
-    else
-      *loc16 = (targetAddress - (fixupAddress+2)) + ref.addend();
-    break;
-  case pointer32:
-  case abs32:
-    *loc32 = targetAddress + ref.addend();
-    break;
-  case funcRel32:
-    *loc32 = targetAddress - inAtomAddress + ref.addend(); // FIXME
-    break;
-  case delta32:
-    *loc32 = targetAddress - fixupAddress + ref.addend();
-    break;
-  case negDelta32:
-    *loc32 = fixupAddress - targetAddress + ref.addend();
-    break;
-  case modeCode:
-  case modeData:
-  case lazyPointer:
-  case lazyImmediateLocation:
-    // do nothing
-    break;
-  case invalid:
-    llvm_unreachable("invalid x86 Reference Kind");
-    break;
-  }
-}
-
-bool ArchHandler_x86::useExternalRelocationTo(const Atom &target) {
-  // Undefined symbols are referenced via external relocations.
-  if (isa<UndefinedAtom>(&target))
-    return true;
-  if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(&target)) {
-     switch (defAtom->merge()) {
-     case DefinedAtom::mergeAsTentative:
-       // Tentative definitions are referenced via external relocations.
-       return true;
-     case DefinedAtom::mergeAsWeak:
-     case DefinedAtom::mergeAsWeakAndAddressUsed:
-       // Global weak-defs are referenced via external relocations.
-       return (defAtom->scope() == DefinedAtom::scopeGlobal);
-     default:
-       break;
-    }
-  }
-  // Everything else is reference via an internal relocation.
-  return false;
-}
-
-void ArchHandler_x86::appendSectionRelocations(
-                                   const DefinedAtom &atom,
-                                   uint64_t atomSectionOffset,
-                                   const Reference &ref,
-                                   FindSymbolIndexForAtom symbolIndexForAtom,
-                                   FindSectionIndexForAtom sectionIndexForAtom,
-                                   FindAddressForAtom addressForAtom,
-                                   normalized::Relocations &relocs) {
-  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
-    return;
-  assert(ref.kindArch() == Reference::KindArch::x86);
-  uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom();
-  bool useExternalReloc = useExternalRelocationTo(*ref.target());
-  switch (static_cast<X86Kind>(ref.kindValue())) {
-  case modeCode:
-  case modeData:
-    break;
-  case branch32:
-    if (useExternalReloc) {
-      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  GENERIC_RELOC_VANILLA | rExtern    | rPcRel | rLength4);
-    } else {
-      if (ref.addend() != 0)
-        appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
-                  GENERIC_RELOC_VANILLA | rScattered | rPcRel |  rLength4);
-      else
-        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
-                  GENERIC_RELOC_VANILLA |              rPcRel | rLength4);
-    }
-    break;
-  case branch16:
-    if (useExternalReloc) {
-      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                  GENERIC_RELOC_VANILLA | rExtern    | rPcRel | rLength2);
-    } else {
-      if (ref.addend() != 0)
-        appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
-                  GENERIC_RELOC_VANILLA | rScattered | rPcRel |  rLength2);
-      else
-        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
-                  GENERIC_RELOC_VANILLA |              rPcRel | rLength2);
-    }
-    break;
-  case pointer32:
-  case abs32:
-    if (useExternalReloc)
-      appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()),  0,
-                GENERIC_RELOC_VANILLA |    rExtern     |  rLength4);
-    else {
-      if (ref.addend() != 0)
-        appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
-                GENERIC_RELOC_VANILLA |    rScattered  |  rLength4);
-      else
-        appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
-                GENERIC_RELOC_VANILLA |                   rLength4);
-    }
-    break;
-  case funcRel32:
-    appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
-              GENERIC_RELOC_SECTDIFF |  rScattered    | rLength4);
-    appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) - ref.addend(),
-              GENERIC_RELOC_PAIR     |  rScattered    | rLength4);
-    break;
-  case delta32:
-    appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
-              GENERIC_RELOC_SECTDIFF |  rScattered    | rLength4);
-    appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) +
-                                                           ref.offsetInAtom(),
-              GENERIC_RELOC_PAIR     |  rScattered    | rLength4);
-    break;
-  case negDelta32:
-    appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) +
-                                                           ref.offsetInAtom(),
-              GENERIC_RELOC_SECTDIFF |  rScattered    | rLength4);
-    appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
-              GENERIC_RELOC_PAIR     |  rScattered    | rLength4);
-    break;
-  case lazyPointer:
-  case lazyImmediateLocation:
-    llvm_unreachable("lazy reference kind implies Stubs pass was run");
-    break;
-  case invalid:
-    llvm_unreachable("unknown x86 Reference Kind");
-    break;
-  }
-}
-
-std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_x86() {
-  return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_x86());
-}
-
-} // namespace mach_o
-} // namespace lld
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp b/gnu/llvm/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
deleted file mode 100644 (file)
index 6874070..0000000
+++ /dev/null
@@ -1,899 +0,0 @@
-//===- lib/FileFormat/MachO/ArchHandler_x86_64.cpp ------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "Atoms.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorHandling.h"
-
-using namespace llvm::MachO;
-using namespace lld::mach_o::normalized;
-
-namespace lld {
-namespace mach_o {
-
-using llvm::support::ulittle32_t;
-using llvm::support::ulittle64_t;
-
-using llvm::support::little32_t;
-using llvm::support::little64_t;
-
-class ArchHandler_x86_64 : public ArchHandler {
-public:
-  ArchHandler_x86_64() = default;
-  ~ArchHandler_x86_64() override = default;
-
-  const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
-
-  Reference::KindArch kindArch() override {
-    return Reference::KindArch::x86_64;
-  }
-
-  /// Used by GOTPass to locate GOT References
-  bool isGOTAccess(const Reference &ref, bool &canBypassGOT) override {
-    if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
-      return false;
-    assert(ref.kindArch() == Reference::KindArch::x86_64);
-    switch (ref.kindValue()) {
-    case ripRel32GotLoad:
-      canBypassGOT = true;
-      return true;
-    case ripRel32Got:
-      canBypassGOT = false;
-      return true;
-    case imageOffsetGot:
-      canBypassGOT = false;
-      return true;
-    default:
-      return false;
-    }
-  }
-
-  bool isTLVAccess(const Reference &ref) const override {
-    assert(ref.kindNamespace() == Reference::KindNamespace::mach_o);
-    assert(ref.kindArch() == Reference::KindArch::x86_64);
-    return ref.kindValue() == ripRel32Tlv;
-  }
-
-  void updateReferenceToTLV(const Reference *ref) override {
-    assert(ref->kindNamespace() == Reference::KindNamespace::mach_o);
-    assert(ref->kindArch() == Reference::KindArch::x86_64);
-    assert(ref->kindValue() == ripRel32Tlv);
-    const_cast<Reference*>(ref)->setKindValue(ripRel32);
-  }
-
-  /// Used by GOTPass to update GOT References
-  void updateReferenceToGOT(const Reference *ref, bool targetNowGOT) override {
-    assert(ref->kindNamespace() == Reference::KindNamespace::mach_o);
-    assert(ref->kindArch() == Reference::KindArch::x86_64);
-
-    switch (ref->kindValue()) {
-    case ripRel32Got:
-      assert(targetNowGOT && "target must be GOT");
-      LLVM_FALLTHROUGH;
-    case ripRel32GotLoad:
-      const_cast<Reference *>(ref)
-        ->setKindValue(targetNowGOT ? ripRel32 : ripRel32GotLoadNowLea);
-      break;
-    case imageOffsetGot:
-      const_cast<Reference *>(ref)->setKindValue(imageOffset);
-      break;
-    default:
-      llvm_unreachable("unknown GOT reference kind");
-    }
-  }
-
-  bool needsCompactUnwind() override {
-    return true;
-  }
-
-  Reference::KindValue imageOffsetKind() override {
-    return imageOffset;
-  }
-
-  Reference::KindValue imageOffsetKindIndirect() override {
-    return imageOffsetGot;
-  }
-
-  Reference::KindValue unwindRefToPersonalityFunctionKind() override {
-    return ripRel32Got;
-  }
-
-  Reference::KindValue unwindRefToCIEKind() override {
-    return negDelta32;
-  }
-
-  Reference::KindValue unwindRefToFunctionKind() override{
-    return unwindFDEToFunction;
-  }
-
-  Reference::KindValue lazyImmediateLocationKind() override {
-    return lazyImmediateLocation;
-  }
-
-  Reference::KindValue unwindRefToEhFrameKind() override {
-    return unwindInfoToEhFrame;
-  }
-
-  Reference::KindValue pointerKind() override {
-    return pointer64;
-  }
-
-  uint32_t dwarfCompactUnwindType() override {
-    return 0x04000000U;
-  }
-
-  const StubInfo &stubInfo() override { return _sStubInfo; }
-
-  bool isNonCallBranch(const Reference &) override {
-    return false;
-  }
-
-  bool isCallSite(const Reference &) override;
-  bool isPointer(const Reference &) override;
-  bool isPairedReloc(const normalized::Relocation &) override;
-
-  llvm::Error getReferenceInfo(const normalized::Relocation &reloc,
-                               const DefinedAtom *inAtom,
-                               uint32_t offsetInAtom,
-                               uint64_t fixupAddress, bool swap,
-                               FindAtomBySectionAndAddress atomFromAddress,
-                               FindAtomBySymbolIndex atomFromSymbolIndex,
-                               Reference::KindValue *kind,
-                               const lld::Atom **target,
-                               Reference::Addend *addend) override;
-  llvm::Error
-      getPairReferenceInfo(const normalized::Relocation &reloc1,
-                           const normalized::Relocation &reloc2,
-                           const DefinedAtom *inAtom,
-                           uint32_t offsetInAtom,
-                           uint64_t fixupAddress, bool swap, bool scatterable,
-                           FindAtomBySectionAndAddress atomFromAddress,
-                           FindAtomBySymbolIndex atomFromSymbolIndex,
-                           Reference::KindValue *kind,
-                           const lld::Atom **target,
-                           Reference::Addend *addend) override;
-
-  bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) override {
-    return (atom->contentType() == DefinedAtom::typeCString);
-  }
-
-  void generateAtomContent(const DefinedAtom &atom, bool relocatable,
-                           FindAddressForAtom findAddress,
-                           FindAddressForAtom findSectionAddress,
-                           uint64_t imageBase,
-                    llvm::MutableArrayRef<uint8_t> atomContentBuffer) override;
-
-  void appendSectionRelocations(const DefinedAtom &atom,
-                                uint64_t atomSectionOffset,
-                                const Reference &ref,
-                                FindSymbolIndexForAtom symbolIndexForAtom,
-                                FindSectionIndexForAtom sectionIndexForAtom,
-                                FindAddressForAtom addressForAtom,
-                                normalized::Relocations &relocs) override;
-
-  bool isDataInCodeTransition(Reference::KindValue refKind) override {
-    return refKind == modeCode || refKind == modeData;
-  }
-
-  Reference::KindValue dataInCodeTransitionStart(
-                                        const MachODefinedAtom &atom) override {
-    return modeData;
-  }
-
-  Reference::KindValue dataInCodeTransitionEnd(
-                                        const MachODefinedAtom &atom) override {
-    return modeCode;
-  }
-
-private:
-  static const Registry::KindStrings _sKindStrings[];
-  static const StubInfo              _sStubInfo;
-
-  enum X86_64Kind: Reference::KindValue {
-    invalid,               /// for error condition
-
-    modeCode,              /// Content starting at this offset is code.
-    modeData,              /// Content starting at this offset is data.
-
-    // Kinds found in mach-o .o files:
-    branch32,              /// ex: call _foo
-    ripRel32,              /// ex: movq _foo(%rip), %rax
-    ripRel32Minus1,        /// ex: movb $0x12, _foo(%rip)
-    ripRel32Minus2,        /// ex: movw $0x1234, _foo(%rip)
-    ripRel32Minus4,        /// ex: movl $0x12345678, _foo(%rip)
-    ripRel32Anon,          /// ex: movq L1(%rip), %rax
-    ripRel32Minus1Anon,    /// ex: movb $0x12, L1(%rip)
-    ripRel32Minus2Anon,    /// ex: movw $0x1234, L1(%rip)
-    ripRel32Minus4Anon,    /// ex: movw $0x12345678, L1(%rip)
-    ripRel32GotLoad,       /// ex: movq  _foo@GOTPCREL(%rip), %rax
-    ripRel32Got,           /// ex: pushq _foo@GOTPCREL(%rip)
-    ripRel32Tlv,           /// ex: movq  _foo@TLVP(%rip), %rdi
-    pointer64,             /// ex: .quad _foo
-    pointer64Anon,         /// ex: .quad L1
-    delta64,               /// ex: .quad _foo - .
-    delta32,               /// ex: .long _foo - .
-    delta64Anon,           /// ex: .quad L1 - .
-    delta32Anon,           /// ex: .long L1 - .
-    negDelta64,            /// ex: .quad . - _foo
-    negDelta32,            /// ex: .long . - _foo
-
-    // Kinds introduced by Passes:
-    ripRel32GotLoadNowLea, /// Target of GOT load is in linkage unit so
-                           ///  "movq  _foo@GOTPCREL(%rip), %rax" can be changed
-                           /// to "leaq _foo(%rip), %rax
-    lazyPointer,           /// Location contains a lazy pointer.
-    lazyImmediateLocation, /// Location contains immediate value used in stub.
-
-    imageOffset,           /// Location contains offset of atom in final image
-    imageOffsetGot,        /// Location contains offset of GOT entry for atom in
-                           /// final image (typically personality function).
-    unwindFDEToFunction,   /// Nearly delta64, but cannot be rematerialized in
-                           /// relocatable object (yay for implicit contracts!).
-    unwindInfoToEhFrame,   /// Fix low 24 bits of compact unwind encoding to
-                           /// refer to __eh_frame entry.
-    tlvInitSectionOffset   /// Location contains offset tlv init-value atom
-                           /// within the __thread_data section.
-  };
-
-  Reference::KindValue kindFromReloc(const normalized::Relocation &reloc);
-
-  void applyFixupFinal(const Reference &ref, uint8_t *location,
-                       uint64_t fixupAddress, uint64_t targetAddress,
-                       uint64_t inAtomAddress, uint64_t imageBaseAddress,
-                       FindAddressForAtom findSectionAddress);
-
-  void applyFixupRelocatable(const Reference &ref, uint8_t *location,
-                             uint64_t fixupAddress,
-                             uint64_t targetAddress,
-                             uint64_t inAtomAddress);
-};
-
-const Registry::KindStrings ArchHandler_x86_64::_sKindStrings[] = {
-  LLD_KIND_STRING_ENTRY(invalid),
-  LLD_KIND_STRING_ENTRY(modeCode),
-  LLD_KIND_STRING_ENTRY(modeData),
-  LLD_KIND_STRING_ENTRY(branch32),
-  LLD_KIND_STRING_ENTRY(ripRel32),
-  LLD_KIND_STRING_ENTRY(ripRel32Minus1),
-  LLD_KIND_STRING_ENTRY(ripRel32Minus2),
-  LLD_KIND_STRING_ENTRY(ripRel32Minus4),
-  LLD_KIND_STRING_ENTRY(ripRel32Anon),
-  LLD_KIND_STRING_ENTRY(ripRel32Minus1Anon),
-  LLD_KIND_STRING_ENTRY(ripRel32Minus2Anon),
-  LLD_KIND_STRING_ENTRY(ripRel32Minus4Anon),
-  LLD_KIND_STRING_ENTRY(ripRel32GotLoad),
-  LLD_KIND_STRING_ENTRY(ripRel32GotLoadNowLea),
-  LLD_KIND_STRING_ENTRY(ripRel32Got),
-  LLD_KIND_STRING_ENTRY(ripRel32Tlv),
-  LLD_KIND_STRING_ENTRY(lazyPointer),
-  LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
-  LLD_KIND_STRING_ENTRY(pointer64),
-  LLD_KIND_STRING_ENTRY(pointer64Anon),
-  LLD_KIND_STRING_ENTRY(delta32),
-  LLD_KIND_STRING_ENTRY(delta64),
-  LLD_KIND_STRING_ENTRY(delta32Anon),
-  LLD_KIND_STRING_ENTRY(delta64Anon),
-  LLD_KIND_STRING_ENTRY(negDelta64),
-  LLD_KIND_STRING_ENTRY(negDelta32),
-  LLD_KIND_STRING_ENTRY(imageOffset),
-  LLD_KIND_STRING_ENTRY(imageOffsetGot),
-  LLD_KIND_STRING_ENTRY(unwindFDEToFunction),
-  LLD_KIND_STRING_ENTRY(unwindInfoToEhFrame),
-  LLD_KIND_STRING_ENTRY(tlvInitSectionOffset),
-  LLD_KIND_STRING_END
-};
-
-const ArchHandler::StubInfo ArchHandler_x86_64::_sStubInfo = {
-  "dyld_stub_binder",
-
-  // Lazy pointer references
-  { Reference::KindArch::x86_64, pointer64, 0, 0 },
-  { Reference::KindArch::x86_64, lazyPointer, 0, 0 },
-
-  // GOT pointer to dyld_stub_binder
-  { Reference::KindArch::x86_64, pointer64, 0, 0 },
-
-  // x86_64 code alignment 2^1
-  1,
-
-  // Stub size and code
-  6,
-  { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 },       // jmp *lazyPointer
-  { Reference::KindArch::x86_64, ripRel32, 2, 0 },
-  { false, 0, 0, 0 },
-
-  // Stub Helper size and code
-  10,
-  { 0x68, 0x00, 0x00, 0x00, 0x00,               // pushq $lazy-info-offset
-    0xE9, 0x00, 0x00, 0x00, 0x00 },             // jmp helperhelper
-  { Reference::KindArch::x86_64, lazyImmediateLocation, 1, 0 },
-  { Reference::KindArch::x86_64, branch32, 6, 0 },
-
-  // Stub helper image cache content type
-  DefinedAtom::typeNonLazyPointer,
-
-  // Stub Helper-Common size and code
-  16,
-  // Stub helper alignment
-  2,
-  { 0x4C, 0x8D, 0x1D, 0x00, 0x00, 0x00, 0x00,   // leaq cache(%rip),%r11
-    0x41, 0x53,                                 // push %r11
-    0xFF, 0x25, 0x00, 0x00, 0x00, 0x00,         // jmp *binder(%rip)
-    0x90 },                                     // nop
-  { Reference::KindArch::x86_64, ripRel32, 3, 0 },
-  { false, 0, 0, 0 },
-  { Reference::KindArch::x86_64, ripRel32, 11, 0 },
-  { false, 0, 0, 0 }
-
-};
-
-bool ArchHandler_x86_64::isCallSite(const Reference &ref) {
-  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
-    return false;
-  assert(ref.kindArch() == Reference::KindArch::x86_64);
-  return (ref.kindValue() == branch32);
-}
-
-bool ArchHandler_x86_64::isPointer(const Reference &ref) {
-  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
-    return false;
-  assert(ref.kindArch() == Reference::KindArch::x86_64);
-  Reference::KindValue kind = ref.kindValue();
-  return (kind == pointer64 || kind == pointer64Anon);
-}
-
-bool ArchHandler_x86_64::isPairedReloc(const Relocation &reloc) {
-  return (reloc.type == X86_64_RELOC_SUBTRACTOR);
-}
-
-Reference::KindValue
-ArchHandler_x86_64::kindFromReloc(const Relocation &reloc) {
-  switch(relocPattern(reloc)) {
-  case X86_64_RELOC_BRANCH   | rPcRel | rExtern | rLength4:
-    return branch32;
-  case X86_64_RELOC_SIGNED   | rPcRel | rExtern | rLength4:
-    return ripRel32;
-  case X86_64_RELOC_SIGNED   | rPcRel |           rLength4:
-    return ripRel32Anon;
-  case X86_64_RELOC_SIGNED_1 | rPcRel | rExtern | rLength4:
-    return ripRel32Minus1;
-  case X86_64_RELOC_SIGNED_1 | rPcRel |           rLength4:
-    return ripRel32Minus1Anon;
-  case X86_64_RELOC_SIGNED_2 | rPcRel | rExtern | rLength4:
-    return ripRel32Minus2;
-  case X86_64_RELOC_SIGNED_2 | rPcRel |           rLength4:
-    return ripRel32Minus2Anon;
-  case X86_64_RELOC_SIGNED_4 | rPcRel | rExtern | rLength4:
-    return ripRel32Minus4;
-  case X86_64_RELOC_SIGNED_4 | rPcRel |           rLength4:
-    return ripRel32Minus4Anon;
-  case X86_64_RELOC_GOT_LOAD | rPcRel | rExtern | rLength4:
-    return ripRel32GotLoad;
-  case X86_64_RELOC_GOT      | rPcRel | rExtern | rLength4:
-    return ripRel32Got;
-  case X86_64_RELOC_TLV      | rPcRel | rExtern | rLength4:
-    return ripRel32Tlv;
-  case X86_64_RELOC_UNSIGNED          | rExtern | rLength8:
-    return pointer64;
-  case X86_64_RELOC_UNSIGNED                    | rLength8:
-    return pointer64Anon;
-  default:
-    return invalid;
-  }
-}
-
-llvm::Error
-ArchHandler_x86_64::getReferenceInfo(const Relocation &reloc,
-                                    const DefinedAtom *inAtom,
-                                    uint32_t offsetInAtom,
-                                    uint64_t fixupAddress, bool swap,
-                                    FindAtomBySectionAndAddress atomFromAddress,
-                                    FindAtomBySymbolIndex atomFromSymbolIndex,
-                                    Reference::KindValue *kind,
-                                    const lld::Atom **target,
-                                    Reference::Addend *addend) {
-  *kind = kindFromReloc(reloc);
-  if (*kind == invalid)
-    return llvm::make_error<GenericError>("unknown type");
-  const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
-  uint64_t targetAddress;
-  switch (*kind) {
-  case branch32:
-  case ripRel32:
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    *addend = *(const little32_t *)fixupContent;
-    return llvm::Error::success();
-  case ripRel32Minus1:
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    *addend = (int32_t)*(const little32_t *)fixupContent + 1;
-    return llvm::Error::success();
-  case ripRel32Minus2:
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    *addend = (int32_t)*(const little32_t *)fixupContent + 2;
-    return llvm::Error::success();
-  case ripRel32Minus4:
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    *addend = (int32_t)*(const little32_t *)fixupContent + 4;
-    return llvm::Error::success();
-  case ripRel32Anon:
-    targetAddress = fixupAddress + 4 + *(const little32_t *)fixupContent;
-    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
-  case ripRel32Minus1Anon:
-    targetAddress = fixupAddress + 5 + *(const little32_t *)fixupContent;
-    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
-  case ripRel32Minus2Anon:
-    targetAddress = fixupAddress + 6 + *(const little32_t *)fixupContent;
-    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
-  case ripRel32Minus4Anon:
-    targetAddress = fixupAddress + 8 + *(const little32_t *)fixupContent;
-    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
-  case ripRel32GotLoad:
-  case ripRel32Got:
-  case ripRel32Tlv:
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    *addend = *(const little32_t *)fixupContent;
-    return llvm::Error::success();
-  case tlvInitSectionOffset:
-  case pointer64:
-    if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
-      return ec;
-    // If this is the 3rd pointer of a tlv-thunk (i.e. the pointer to the TLV's
-    // initial value) we need to handle it specially.
-    if (inAtom->contentType() == DefinedAtom::typeThunkTLV &&
-        offsetInAtom == 16) {
-      *kind = tlvInitSectionOffset;
-      assert(*addend == 0 && "TLV-init has non-zero addend?");
-    } else
-      *addend = *(const little64_t *)fixupContent;
-    return llvm::Error::success();
-  case pointer64Anon:
-    targetAddress = *(const little64_t *)fixupContent;
-    return atomFromAddress(reloc.symbol, targetAddress, target, addend);
-  default:
-    llvm_unreachable("bad reloc kind");
-  }
-}
-
-llvm::Error
-ArchHandler_x86_64::getPairReferenceInfo(const normalized::Relocation &reloc1,
-                                   const normalized::Relocation &reloc2,
-                                   const DefinedAtom *inAtom,
-                                   uint32_t offsetInAtom,
-                                   uint64_t fixupAddress, bool swap,
-                                   bool scatterable,
-                                   FindAtomBySectionAndAddress atomFromAddress,
-                                   FindAtomBySymbolIndex atomFromSymbolIndex,
-                                   Reference::KindValue *kind,
-                                   const lld::Atom **target,
-                                   Reference::Addend *addend) {
-  const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
-  uint64_t targetAddress;
-  const lld::Atom *fromTarget;
-  if (auto ec = atomFromSymbolIndex(reloc1.symbol, &fromTarget))
-    return ec;
-
-  switch(relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
-  case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
-        X86_64_RELOC_UNSIGNED    | rExtern | rLength8): {
-    if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
-      return ec;
-    uint64_t encodedAddend = (int64_t)*(const little64_t *)fixupContent;
-    if (inAtom == fromTarget) {
-      if (inAtom->contentType() == DefinedAtom::typeCFI)
-        *kind = unwindFDEToFunction;
-      else
-        *kind = delta64;
-      *addend = encodedAddend + offsetInAtom;
-    } else if (inAtom == *target) {
-      *kind = negDelta64;
-      *addend = encodedAddend - offsetInAtom;
-      *target = fromTarget;
-    } else
-      return llvm::make_error<GenericError>("Invalid pointer diff");
-    return llvm::Error::success();
-  }
-  case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
-        X86_64_RELOC_UNSIGNED    | rExtern | rLength4): {
-    if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
-      return ec;
-    uint32_t encodedAddend = (int32_t)*(const little32_t *)fixupContent;
-    if (inAtom == fromTarget) {
-      *kind = delta32;
-      *addend = encodedAddend + offsetInAtom;
-    } else if (inAtom == *target) {
-      *kind = negDelta32;
-      *addend = encodedAddend - offsetInAtom;
-      *target = fromTarget;
-    } else
-      return llvm::make_error<GenericError>("Invalid pointer diff");
-    return llvm::Error::success();
-  }
-  case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
-        X86_64_RELOC_UNSIGNED              | rLength8):
-    if (fromTarget != inAtom)
-      return llvm::make_error<GenericError>("pointer diff not in base atom");
-    *kind = delta64Anon;
-    targetAddress = offsetInAtom + (int64_t)*(const little64_t *)fixupContent;
-    return atomFromAddress(reloc2.symbol, targetAddress, target, addend);
-  case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
-        X86_64_RELOC_UNSIGNED              | rLength4):
-    if (fromTarget != inAtom)
-      return llvm::make_error<GenericError>("pointer diff not in base atom");
-    *kind = delta32Anon;
-    targetAddress = offsetInAtom + (int32_t)*(const little32_t *)fixupContent;
-    return atomFromAddress(reloc2.symbol, targetAddress, target, addend);
-  default:
-    return llvm::make_error<GenericError>("unknown pair");
-  }
-}
-
-void ArchHandler_x86_64::generateAtomContent(
-    const DefinedAtom &atom, bool relocatable, FindAddressForAtom findAddress,
-    FindAddressForAtom findSectionAddress, uint64_t imageBaseAddress,
-    llvm::MutableArrayRef<uint8_t> atomContentBuffer) {
-  // Copy raw bytes.
-  std::copy(atom.rawContent().begin(), atom.rawContent().end(),
-            atomContentBuffer.begin());
-  // Apply fix-ups.
-  for (const Reference *ref : atom) {
-    uint32_t offset = ref->offsetInAtom();
-    const Atom *target = ref->target();
-    uint64_t targetAddress = 0;
-    if (isa<DefinedAtom>(target))
-      targetAddress = findAddress(*target);
-    uint64_t atomAddress = findAddress(atom);
-    uint64_t fixupAddress = atomAddress + offset;
-    if (relocatable) {
-      applyFixupRelocatable(*ref, &atomContentBuffer[offset],
-                                        fixupAddress, targetAddress,
-                                        atomAddress);
-    } else {
-      applyFixupFinal(*ref, &atomContentBuffer[offset],
-                      fixupAddress, targetAddress,
-                      atomAddress, imageBaseAddress, findSectionAddress);
-    }
-  }
-}
-
-void ArchHandler_x86_64::applyFixupFinal(
-    const Reference &ref, uint8_t *loc, uint64_t fixupAddress,
-    uint64_t targetAddress, uint64_t inAtomAddress, uint64_t imageBaseAddress,
-    FindAddressForAtom findSectionAddress) {
-  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
-    return;
-  assert(ref.kindArch() == Reference::KindArch::x86_64);
-  ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
-  ulittle64_t *loc64 = reinterpret_cast<ulittle64_t *>(loc);
-  switch (static_cast<X86_64Kind>(ref.kindValue())) {
-  case branch32:
-  case ripRel32:
-  case ripRel32Anon:
-  case ripRel32Got:
-  case ripRel32GotLoad:
-  case ripRel32Tlv:
-    *loc32 = targetAddress - (fixupAddress + 4) + ref.addend();
-    return;
-  case pointer64:
-  case pointer64Anon:
-    *loc64 = targetAddress + ref.addend();
-    return;
-  case tlvInitSectionOffset:
-    *loc64 = targetAddress - findSectionAddress(*ref.target()) + ref.addend();
-    return;
-  case ripRel32Minus1:
-  case ripRel32Minus1Anon:
-    *loc32 = targetAddress - (fixupAddress + 5) + ref.addend();
-    return;
-  case ripRel32Minus2:
-  case ripRel32Minus2Anon:
-    *loc32 = targetAddress - (fixupAddress + 6) + ref.addend();
-    return;
-  case ripRel32Minus4:
-  case ripRel32Minus4Anon:
-    *loc32 = targetAddress - (fixupAddress + 8) + ref.addend();
-    return;
-  case delta32:
-  case delta32Anon:
-    *loc32 = targetAddress - fixupAddress + ref.addend();
-    return;
-  case delta64:
-  case delta64Anon:
-  case unwindFDEToFunction:
-    *loc64 = targetAddress - fixupAddress + ref.addend();
-    return;
-  case ripRel32GotLoadNowLea:
-    // Change MOVQ to LEA
-    assert(loc[-2] == 0x8B);
-    loc[-2] = 0x8D;
-    *loc32 = targetAddress - (fixupAddress + 4) + ref.addend();
-    return;
-  case negDelta64:
-    *loc64 = fixupAddress - targetAddress + ref.addend();
-    return;
-  case negDelta32:
-    *loc32 = fixupAddress - targetAddress + ref.addend();
-    return;
-  case modeCode:
-  case modeData:
-  case lazyPointer:
-    // Do nothing
-    return;
-  case lazyImmediateLocation:
-    *loc32 = ref.addend();
-    return;
-  case imageOffset:
-  case imageOffsetGot:
-    *loc32 = (targetAddress - imageBaseAddress) + ref.addend();
-    return;
-  case unwindInfoToEhFrame: {
-    uint64_t val = targetAddress - findSectionAddress(*ref.target()) + ref.addend();
-    assert(val < 0xffffffU && "offset in __eh_frame too large");
-    *loc32 = (*loc32 & 0xff000000U) | val;
-    return;
-  }
-  case invalid:
-    // Fall into llvm_unreachable().
-    break;
-  }
-  llvm_unreachable("invalid x86_64 Reference Kind");
-}
-
-void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref,
-                                               uint8_t *loc,
-                                               uint64_t fixupAddress,
-                                               uint64_t targetAddress,
-                                               uint64_t inAtomAddress)  {
-  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
-    return;
-  assert(ref.kindArch() == Reference::KindArch::x86_64);
-  ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
-  ulittle64_t *loc64 = reinterpret_cast<ulittle64_t *>(loc);
-  switch (static_cast<X86_64Kind>(ref.kindValue())) {
-  case branch32:
-  case ripRel32:
-  case ripRel32Got:
-  case ripRel32GotLoad:
-  case ripRel32Tlv:
-    *loc32 = ref.addend();
-    return;
-  case ripRel32Anon:
-    *loc32 = (targetAddress - (fixupAddress + 4)) + ref.addend();
-    return;
-  case tlvInitSectionOffset:
-  case pointer64:
-    *loc64 = ref.addend();
-    return;
-  case pointer64Anon:
-    *loc64 = targetAddress + ref.addend();
-    return;
-  case ripRel32Minus1:
-    *loc32 = ref.addend() - 1;
-    return;
-  case ripRel32Minus1Anon:
-    *loc32 = (targetAddress - (fixupAddress + 5)) + ref.addend();
-    return;
-  case ripRel32Minus2:
-    *loc32 = ref.addend() - 2;
-    return;
-  case ripRel32Minus2Anon:
-    *loc32 = (targetAddress - (fixupAddress + 6)) + ref.addend();
-    return;
-  case ripRel32Minus4:
-    *loc32 = ref.addend() - 4;
-    return;
-  case ripRel32Minus4Anon:
-    *loc32 = (targetAddress - (fixupAddress + 8)) + ref.addend();
-    return;
-  case delta32:
-    *loc32 = ref.addend() + inAtomAddress - fixupAddress;
-    return;
-  case delta32Anon:
-    // The value we write here should be the delta to the target
-    // after taking in to account the difference from the fixup back to the
-    // last defined label
-    // ie, if we have:
-    // _base: ...
-    // Lfixup: .quad Ltarget - .
-    // ...
-    // Ltarget:
-    //
-    // Then we want to encode the value (Ltarget + addend) - (LFixup - _base)
-    *loc32 = (targetAddress + ref.addend()) - (fixupAddress - inAtomAddress);
-    return;
-  case delta64:
-    *loc64 = ref.addend() + inAtomAddress - fixupAddress;
-    return;
-  case delta64Anon:
-    // The value we write here should be the delta to the target
-    // after taking in to account the difference from the fixup back to the
-    // last defined label
-    // ie, if we have:
-    // _base: ...
-    // Lfixup: .quad Ltarget - .
-    // ...
-    // Ltarget:
-    //
-    // Then we want to encode the value (Ltarget + addend) - (LFixup - _base)
-    *loc64 = (targetAddress + ref.addend()) - (fixupAddress - inAtomAddress);
-    return;
-  case negDelta64:
-    *loc64 = ref.addend() + fixupAddress - inAtomAddress;
-    return;
-  case negDelta32:
-    *loc32 = ref.addend() + fixupAddress - inAtomAddress;
-    return;
-  case ripRel32GotLoadNowLea:
-    llvm_unreachable("ripRel32GotLoadNowLea implies GOT pass was run");
-    return;
-  case lazyPointer:
-  case lazyImmediateLocation:
-    llvm_unreachable("lazy reference kind implies Stubs pass was run");
-    return;
-  case imageOffset:
-  case imageOffsetGot:
-  case unwindInfoToEhFrame:
-    llvm_unreachable("fixup implies __unwind_info");
-    return;
-  case modeCode:
-  case modeData:
-  case unwindFDEToFunction:
-    // Do nothing for now
-    return;
-  case invalid:
-    // Fall into llvm_unreachable().
-    break;
-  }
-  llvm_unreachable("unknown x86_64 Reference Kind");
-}
-
-void ArchHandler_x86_64::appendSectionRelocations(
-                                   const DefinedAtom &atom,
-                                   uint64_t atomSectionOffset,
-                                   const Reference &ref,
-                                   FindSymbolIndexForAtom symbolIndexForAtom,
-                                   FindSectionIndexForAtom sectionIndexForAtom,
-                                   FindAddressForAtom addressForAtom,
-                                   normalized::Relocations &relocs) {
-  if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
-    return;
-  assert(ref.kindArch() == Reference::KindArch::x86_64);
-  uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom();
-  switch (static_cast<X86_64Kind>(ref.kindValue())) {
-  case modeCode:
-  case modeData:
-    return;
-  case branch32:
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_BRANCH | rPcRel | rExtern | rLength4);
-    return;
-  case ripRel32:
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_SIGNED | rPcRel | rExtern | rLength4 );
-    return;
-  case ripRel32Anon:
-    appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_SIGNED | rPcRel           | rLength4 );
-    return;
-  case ripRel32Got:
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_GOT | rPcRel | rExtern | rLength4 );
-    return;
-  case ripRel32GotLoad:
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_GOT_LOAD | rPcRel | rExtern | rLength4 );
-    return;
-  case ripRel32Tlv:
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_TLV | rPcRel | rExtern | rLength4 );
-    return;
-  case tlvInitSectionOffset:
-  case pointer64:
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_UNSIGNED  | rExtern | rLength8);
-    return;
-  case pointer64Anon:
-    appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_UNSIGNED | rLength8);
-    return;
-  case ripRel32Minus1:
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_SIGNED_1 | rPcRel | rExtern | rLength4 );
-    return;
-  case ripRel32Minus1Anon:
-    appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_SIGNED_1 | rPcRel           | rLength4 );
-    return;
-  case ripRel32Minus2:
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_SIGNED_2 | rPcRel | rExtern | rLength4 );
-    return;
-  case ripRel32Minus2Anon:
-    appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_SIGNED_2 | rPcRel           | rLength4 );
-    return;
-  case ripRel32Minus4:
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_SIGNED_4 | rPcRel | rExtern | rLength4 );
-    return;
-  case ripRel32Minus4Anon:
-    appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_SIGNED_4 | rPcRel           | rLength4 );
-    return;
-  case delta32:
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
-                X86_64_RELOC_SUBTRACTOR | rExtern | rLength4 );
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_UNSIGNED   | rExtern | rLength4 );
-    return;
-  case delta32Anon:
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
-                X86_64_RELOC_SUBTRACTOR | rExtern | rLength4 );
-    appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_UNSIGNED             | rLength4 );
-    return;
-  case delta64:
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
-                X86_64_RELOC_SUBTRACTOR | rExtern | rLength8 );
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_UNSIGNED   | rExtern | rLength8 );
-    return;
-  case delta64Anon:
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
-                X86_64_RELOC_SUBTRACTOR | rExtern | rLength8 );
-    appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_UNSIGNED             | rLength8 );
-    return;
-  case unwindFDEToFunction:
-  case unwindInfoToEhFrame:
-    return;
-  case negDelta32:
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_SUBTRACTOR | rExtern | rLength4 );
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
-                X86_64_RELOC_UNSIGNED   | rExtern | rLength4 );
-    return;
-  case negDelta64:
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
-                X86_64_RELOC_SUBTRACTOR | rExtern | rLength8 );
-    appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
-                X86_64_RELOC_UNSIGNED   | rExtern | rLength8 );
-    return;
-  case ripRel32GotLoadNowLea:
-    llvm_unreachable("ripRel32GotLoadNowLea implies GOT pass was run");
-    return;
-  case lazyPointer:
-  case lazyImmediateLocation:
-    llvm_unreachable("lazy reference kind implies Stubs pass was run");
-    return;
-  case imageOffset:
-  case imageOffsetGot:
-    llvm_unreachable("__unwind_info references should have been resolved");
-    return;
-  case invalid:
-    // Fall into llvm_unreachable().
-    break;
-  }
-  llvm_unreachable("unknown x86_64 Reference Kind");
-}
-
-std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_x86_64() {
-  return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_x86_64());
-}
-
-} // namespace mach_o
-} // namespace lld
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/Atoms.h b/gnu/llvm/lld/lib/ReaderWriter/MachO/Atoms.h
deleted file mode 100644 (file)
index c61aaa8..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-//===- lib/ReaderWriter/MachO/Atoms.h ---------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_ATOMS_H
-#define LLD_READER_WRITER_MACHO_ATOMS_H
-
-#include "lld/Core/Atom.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/SharedLibraryAtom.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include <cstdint>
-#include <string>
-
-namespace lld {
-
-class File;
-
-namespace mach_o {
-
-class MachODefinedAtom : public SimpleDefinedAtom {
-public:
-  MachODefinedAtom(const File &f, const StringRef name, Scope scope,
-                   ContentType type, Merge merge, bool thumb, bool noDeadStrip,
-                   const ArrayRef<uint8_t> content, Alignment align)
-      : SimpleDefinedAtom(f), _name(name), _content(content),
-        _align(align), _contentType(type), _scope(scope), _merge(merge),
-        _thumb(thumb), _noDeadStrip(noDeadStrip) {}
-
-  // Constructor for zero-fill content
-  MachODefinedAtom(const File &f, const StringRef name, Scope scope,
-                   ContentType type, uint64_t size, bool noDeadStrip,
-                   Alignment align)
-      : SimpleDefinedAtom(f), _name(name),
-        _content(ArrayRef<uint8_t>(nullptr, size)), _align(align),
-        _contentType(type), _scope(scope), _merge(mergeNo), _thumb(false),
-        _noDeadStrip(noDeadStrip) {}
-
-  ~MachODefinedAtom() override = default;
-
-  uint64_t size() const override { return _content.size(); }
-
-  ContentType contentType() const override { return _contentType; }
-
-  Alignment alignment() const override { return _align; }
-
-  StringRef name() const override { return _name; }
-
-  Scope scope() const override { return _scope; }
-
-  Merge merge() const override { return _merge; }
-
-  DeadStripKind deadStrip() const override {
-    if (_contentType == DefinedAtom::typeInitializerPtr)
-      return deadStripNever;
-    if (_contentType == DefinedAtom::typeTerminatorPtr)
-      return deadStripNever;
-    if (_noDeadStrip)
-      return deadStripNever;
-    return deadStripNormal;
-  }
-
-  ArrayRef<uint8_t> rawContent() const override {
-    // Note: Zerofill atoms have a content pointer which is null.
-    return _content;
-  }
-
-  bool isThumb() const { return _thumb; }
-
-private:
-  const StringRef _name;
-  const ArrayRef<uint8_t> _content;
-  const DefinedAtom::Alignment _align;
-  const ContentType _contentType;
-  const Scope _scope;
-  const Merge _merge;
-  const bool _thumb;
-  const bool _noDeadStrip;
-};
-
-class MachODefinedCustomSectionAtom : public MachODefinedAtom {
-public:
-  MachODefinedCustomSectionAtom(const File &f, const StringRef name,
-                                Scope scope, ContentType type, Merge merge,
-                                bool thumb, bool noDeadStrip,
-                                const ArrayRef<uint8_t> content,
-                                StringRef sectionName, Alignment align)
-      : MachODefinedAtom(f, name, scope, type, merge, thumb, noDeadStrip,
-                         content, align),
-        _sectionName(sectionName) {}
-
-  ~MachODefinedCustomSectionAtom() override = default;
-
-  SectionChoice sectionChoice() const override {
-    return DefinedAtom::sectionCustomRequired;
-  }
-
-  StringRef customSectionName() const override {
-    return _sectionName;
-  }
-private:
-  StringRef _sectionName;
-};
-
-class MachOTentativeDefAtom : public SimpleDefinedAtom {
-public:
-  MachOTentativeDefAtom(const File &f, const StringRef name, Scope scope,
-                        uint64_t size, DefinedAtom::Alignment align)
-      : SimpleDefinedAtom(f), _name(std::string(name)), _scope(scope),
-        _size(size), _align(align) {}
-
-  ~MachOTentativeDefAtom() override = default;
-
-  uint64_t size() const override { return _size; }
-
-  Merge merge() const override { return DefinedAtom::mergeAsTentative; }
-
-  ContentType contentType() const override { return DefinedAtom::typeZeroFill; }
-
-  Alignment alignment() const override { return _align; }
-
-  StringRef name() const override { return _name; }
-
-  Scope scope() const override { return _scope; }
-
-  ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
-
-private:
-  const std::string _name;
-  const Scope _scope;
-  const uint64_t _size;
-  const DefinedAtom::Alignment _align;
-};
-
-class MachOSharedLibraryAtom : public SharedLibraryAtom {
-public:
-  MachOSharedLibraryAtom(const File &file, StringRef name,
-                         StringRef dylibInstallName, bool weakDef)
-      : SharedLibraryAtom(), _file(file), _name(name),
-        _dylibInstallName(dylibInstallName) {}
-  ~MachOSharedLibraryAtom() override = default;
-
-  StringRef loadName() const override { return _dylibInstallName; }
-
-  bool canBeNullAtRuntime() const override {
-    // FIXME: this may actually be changeable. For now, all symbols are strongly
-    // defined though.
-    return false;
-  }
-
-  const File &file() const override { return _file; }
-
-  StringRef name() const override { return _name; }
-
-  Type type() const override {
-    // Unused in MachO (I think).
-    return Type::Unknown;
-  }
-
-  uint64_t size() const override {
-    // Unused in MachO (I think)
-    return 0;
-  }
-
-private:
-  const File &_file;
-  StringRef _name;
-  StringRef _dylibInstallName;
-};
-
-} // end namespace mach_o
-} // end namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_ATOMS_H
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/CMakeLists.txt b/gnu/llvm/lld/lib/ReaderWriter/MachO/CMakeLists.txt
deleted file mode 100644 (file)
index bdbfbee..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-add_lld_library(lldMachO
-  ArchHandler.cpp
-  ArchHandler_arm.cpp
-  ArchHandler_arm64.cpp
-  ArchHandler_x86.cpp
-  ArchHandler_x86_64.cpp
-  CompactUnwindPass.cpp
-  GOTPass.cpp
-  LayoutPass.cpp
-  MachOLinkingContext.cpp
-  MachONormalizedFileBinaryReader.cpp
-  MachONormalizedFileBinaryWriter.cpp
-  MachONormalizedFileFromAtoms.cpp
-  MachONormalizedFileToAtoms.cpp
-  MachONormalizedFileYAML.cpp
-  ObjCPass.cpp
-  ShimPass.cpp
-  StubsPass.cpp
-  TLVPass.cpp
-  WriterMachO.cpp
-
-  LINK_COMPONENTS
-    DebugInfoDWARF
-    Demangle
-    Object
-    Support
-    TextAPI
-
-  LINK_LIBS
-    lldCommon
-    lldCore
-    lldYAML
-    ${LLVM_PTHREAD_LIB}
-  )
-
-include_directories(.)
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp b/gnu/llvm/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
deleted file mode 100644 (file)
index f3636fe..0000000
+++ /dev/null
@@ -1,580 +0,0 @@
-//===- lib/ReaderWriter/MachO/CompactUnwindPass.cpp -------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file A pass to convert MachO's __compact_unwind sections into the final
-/// __unwind_info format used during runtime. See
-/// mach-o/compact_unwind_encoding.h for more details on the formats involved.
-///
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "File.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "MachOPasses.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Format.h"
-
-#define DEBUG_TYPE "macho-compact-unwind"
-
-namespace lld {
-namespace mach_o {
-
-namespace {
-struct CompactUnwindEntry {
-  const Atom *rangeStart;
-  const Atom *personalityFunction;
-  const Atom *lsdaLocation;
-  const Atom *ehFrame;
-
-  uint32_t rangeLength;
-
-  // There are 3 types of compact unwind entry, distinguished by the encoding
-  // value: 0 indicates a function with no unwind info;
-  // _archHandler.dwarfCompactUnwindType() indicates that the entry defers to
-  // __eh_frame, and that the ehFrame entry will be valid; any other value is a
-  // real compact unwind entry -- personalityFunction will be set and
-  // lsdaLocation may be.
-  uint32_t encoding;
-
-  CompactUnwindEntry(const DefinedAtom *function)
-      : rangeStart(function), personalityFunction(nullptr),
-        lsdaLocation(nullptr), ehFrame(nullptr), rangeLength(function->size()),
-        encoding(0) {}
-
-  CompactUnwindEntry()
-      : rangeStart(nullptr), personalityFunction(nullptr),
-        lsdaLocation(nullptr), ehFrame(nullptr), rangeLength(0), encoding(0) {}
-};
-
-struct UnwindInfoPage {
-  ArrayRef<CompactUnwindEntry> entries;
-};
-}
-
-class UnwindInfoAtom : public SimpleDefinedAtom {
-public:
-  UnwindInfoAtom(ArchHandler &archHandler, const File &file, bool isBig,
-                 std::vector<const Atom *> &personalities,
-                 std::vector<uint32_t> &commonEncodings,
-                 std::vector<UnwindInfoPage> &pages, uint32_t numLSDAs)
-      : SimpleDefinedAtom(file), _archHandler(archHandler),
-        _commonEncodingsOffset(7 * sizeof(uint32_t)),
-        _personalityArrayOffset(_commonEncodingsOffset +
-                                commonEncodings.size() * sizeof(uint32_t)),
-        _topLevelIndexOffset(_personalityArrayOffset +
-                             personalities.size() * sizeof(uint32_t)),
-        _lsdaIndexOffset(_topLevelIndexOffset +
-                         3 * (pages.size() + 1) * sizeof(uint32_t)),
-        _firstPageOffset(_lsdaIndexOffset + 2 * numLSDAs * sizeof(uint32_t)),
-        _isBig(isBig) {
-
-    addHeader(commonEncodings.size(), personalities.size(), pages.size());
-    addCommonEncodings(commonEncodings);
-    addPersonalityFunctions(personalities);
-    addTopLevelIndexes(pages);
-    addLSDAIndexes(pages, numLSDAs);
-    addSecondLevelPages(pages);
-  }
-
-  ~UnwindInfoAtom() override = default;
-
-  ContentType contentType() const override {
-    return DefinedAtom::typeProcessedUnwindInfo;
-  }
-
-  Alignment alignment() const override { return 4; }
-
-  uint64_t size() const override { return _contents.size(); }
-
-  ContentPermissions permissions() const override {
-    return DefinedAtom::permR__;
-  }
-
-  ArrayRef<uint8_t> rawContent() const override { return _contents; }
-
-  void addHeader(uint32_t numCommon, uint32_t numPersonalities,
-                 uint32_t numPages) {
-    using normalized::write32;
-
-    uint32_t headerSize = 7 * sizeof(uint32_t);
-    _contents.resize(headerSize);
-
-    uint8_t *headerEntries = _contents.data();
-    // version
-    write32(headerEntries, 1, _isBig);
-    // commonEncodingsArraySectionOffset
-    write32(headerEntries + sizeof(uint32_t), _commonEncodingsOffset, _isBig);
-    // commonEncodingsArrayCount
-    write32(headerEntries + 2 * sizeof(uint32_t), numCommon, _isBig);
-    // personalityArraySectionOffset
-    write32(headerEntries + 3 * sizeof(uint32_t), _personalityArrayOffset,
-            _isBig);
-    // personalityArrayCount
-    write32(headerEntries + 4 * sizeof(uint32_t), numPersonalities, _isBig);
-    // indexSectionOffset
-    write32(headerEntries + 5 * sizeof(uint32_t), _topLevelIndexOffset, _isBig);
-    // indexCount
-    write32(headerEntries + 6 * sizeof(uint32_t), numPages + 1, _isBig);
-  }
-
-  /// Add the list of common encodings to the section; this is simply an array
-  /// of uint32_t compact values. Size has already been specified in the header.
-  void addCommonEncodings(std::vector<uint32_t> &commonEncodings) {
-    using normalized::write32;
-
-    _contents.resize(_commonEncodingsOffset +
-                     commonEncodings.size() * sizeof(uint32_t));
-    uint8_t *commonEncodingsArea =
-        reinterpret_cast<uint8_t *>(_contents.data() + _commonEncodingsOffset);
-
-    for (uint32_t encoding : commonEncodings) {
-      write32(commonEncodingsArea, encoding, _isBig);
-      commonEncodingsArea += sizeof(uint32_t);
-    }
-  }
-
-  void addPersonalityFunctions(std::vector<const Atom *> personalities) {
-    _contents.resize(_personalityArrayOffset +
-                     personalities.size() * sizeof(uint32_t));
-
-    for (unsigned i = 0; i < personalities.size(); ++i)
-      addImageReferenceIndirect(_personalityArrayOffset + i * sizeof(uint32_t),
-                                personalities[i]);
-  }
-
-  void addTopLevelIndexes(std::vector<UnwindInfoPage> &pages) {
-    using normalized::write32;
-
-    uint32_t numIndexes = pages.size() + 1;
-    _contents.resize(_topLevelIndexOffset + numIndexes * 3 * sizeof(uint32_t));
-
-    uint32_t pageLoc = _firstPageOffset;
-
-    // The most difficult job here is calculating the LSDAs; everything else
-    // follows fairly naturally, but we can't state where the first
-    uint8_t *indexData = &_contents[_topLevelIndexOffset];
-    uint32_t numLSDAs = 0;
-    for (unsigned i = 0; i < pages.size(); ++i) {
-      // functionOffset
-      addImageReference(_topLevelIndexOffset + 3 * i * sizeof(uint32_t),
-                        pages[i].entries[0].rangeStart);
-      // secondLevelPagesSectionOffset
-      write32(indexData + (3 * i + 1) * sizeof(uint32_t), pageLoc, _isBig);
-      write32(indexData + (3 * i + 2) * sizeof(uint32_t),
-              _lsdaIndexOffset + numLSDAs * 2 * sizeof(uint32_t), _isBig);
-
-      for (auto &entry : pages[i].entries)
-        if (entry.lsdaLocation)
-          ++numLSDAs;
-    }
-
-    // Finally, write out the final sentinel index
-    auto &finalEntry = pages[pages.size() - 1].entries.back();
-    addImageReference(_topLevelIndexOffset +
-                          3 * pages.size() * sizeof(uint32_t),
-                      finalEntry.rangeStart, finalEntry.rangeLength);
-    // secondLevelPagesSectionOffset => 0
-    write32(indexData + (3 * pages.size() + 2) * sizeof(uint32_t),
-            _lsdaIndexOffset + numLSDAs * 2 * sizeof(uint32_t), _isBig);
-  }
-
-  void addLSDAIndexes(std::vector<UnwindInfoPage> &pages, uint32_t numLSDAs) {
-    _contents.resize(_lsdaIndexOffset + numLSDAs * 2 * sizeof(uint32_t));
-
-    uint32_t curOffset = _lsdaIndexOffset;
-    for (auto &page : pages) {
-      for (auto &entry : page.entries) {
-        if (!entry.lsdaLocation)
-          continue;
-
-        addImageReference(curOffset, entry.rangeStart);
-        addImageReference(curOffset + sizeof(uint32_t), entry.lsdaLocation);
-        curOffset += 2 * sizeof(uint32_t);
-      }
-    }
-  }
-
-  void addSecondLevelPages(std::vector<UnwindInfoPage> &pages) {
-    for (auto &page : pages) {
-      addRegularSecondLevelPage(page);
-    }
-  }
-
-  void addRegularSecondLevelPage(const UnwindInfoPage &page) {
-    uint32_t curPageOffset = _contents.size();
-    const int16_t headerSize = sizeof(uint32_t) + 2 * sizeof(uint16_t);
-    uint32_t curPageSize =
-        headerSize + 2 * page.entries.size() * sizeof(uint32_t);
-    _contents.resize(curPageOffset + curPageSize);
-
-    using normalized::write32;
-    using normalized::write16;
-    // 2 => regular page
-    write32(&_contents[curPageOffset], 2, _isBig);
-    // offset of 1st entry
-    write16(&_contents[curPageOffset + 4], headerSize, _isBig);
-    write16(&_contents[curPageOffset + 6], page.entries.size(), _isBig);
-
-    uint32_t pagePos = curPageOffset + headerSize;
-    for (auto &entry : page.entries) {
-      addImageReference(pagePos, entry.rangeStart);
-
-      write32(_contents.data() + pagePos + sizeof(uint32_t), entry.encoding,
-              _isBig);
-      if ((entry.encoding & 0x0f000000U) ==
-          _archHandler.dwarfCompactUnwindType())
-        addEhFrameReference(pagePos + sizeof(uint32_t), entry.ehFrame);
-
-      pagePos += 2 * sizeof(uint32_t);
-    }
-  }
-
-  void addEhFrameReference(uint32_t offset, const Atom *dest,
-                           Reference::Addend addend = 0) {
-    addReference(Reference::KindNamespace::mach_o, _archHandler.kindArch(),
-                 _archHandler.unwindRefToEhFrameKind(), offset, dest, addend);
-  }
-
-  void addImageReference(uint32_t offset, const Atom *dest,
-                         Reference::Addend addend = 0) {
-    addReference(Reference::KindNamespace::mach_o, _archHandler.kindArch(),
-                 _archHandler.imageOffsetKind(), offset, dest, addend);
-  }
-
-  void addImageReferenceIndirect(uint32_t offset, const Atom *dest) {
-    addReference(Reference::KindNamespace::mach_o, _archHandler.kindArch(),
-                 _archHandler.imageOffsetKindIndirect(), offset, dest, 0);
-  }
-
-private:
-  mach_o::ArchHandler &_archHandler;
-  std::vector<uint8_t> _contents;
-  uint32_t _commonEncodingsOffset;
-  uint32_t _personalityArrayOffset;
-  uint32_t _topLevelIndexOffset;
-  uint32_t _lsdaIndexOffset;
-  uint32_t _firstPageOffset;
-  bool _isBig;
-};
-
-/// Pass for instantiating and optimizing GOT slots.
-///
-class CompactUnwindPass : public Pass {
-public:
-  CompactUnwindPass(const MachOLinkingContext &context)
-      : _ctx(context), _archHandler(_ctx.archHandler()),
-        _file(*_ctx.make_file<MachOFile>("<mach-o Compact Unwind Pass>")),
-        _isBig(MachOLinkingContext::isBigEndian(_ctx.arch())) {
-    _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
-  }
-
-private:
-  llvm::Error perform(SimpleFile &mergedFile) override {
-    LLVM_DEBUG(llvm::dbgs() << "MachO Compact Unwind pass\n");
-
-    std::map<const Atom *, CompactUnwindEntry> unwindLocs;
-    std::map<const Atom *, const Atom *> dwarfFrames;
-    std::vector<const Atom *> personalities;
-    uint32_t numLSDAs = 0;
-
-    // First collect all __compact_unwind and __eh_frame entries, addressable by
-    // the function referred to.
-    collectCompactUnwindEntries(mergedFile, unwindLocs, personalities,
-                                numLSDAs);
-
-    collectDwarfFrameEntries(mergedFile, dwarfFrames);
-
-    // Skip rest of pass if no unwind info.
-    if (unwindLocs.empty() && dwarfFrames.empty())
-      return llvm::Error::success();
-
-    // FIXME: if there are more than 4 personality functions then we need to
-    // defer to DWARF info for the ones we don't put in the list. They should
-    // also probably be sorted by frequency.
-    assert(personalities.size() <= 4);
-
-    // TODO: Find common encodings for use by compressed pages.
-    std::vector<uint32_t> commonEncodings;
-
-    // Now sort the entries by final address and fixup the compact encoding to
-    // its final form (i.e. set personality function bits & create DWARF
-    // references where needed).
-    std::vector<CompactUnwindEntry> unwindInfos = createUnwindInfoEntries(
-        mergedFile, unwindLocs, personalities, dwarfFrames);
-
-    // Remove any unused eh-frame atoms.
-    pruneUnusedEHFrames(mergedFile, unwindInfos, unwindLocs, dwarfFrames);
-
-    // Finally, we can start creating pages based on these entries.
-
-    LLVM_DEBUG(llvm::dbgs() << "  Splitting entries into pages\n");
-    // FIXME: we split the entries into pages naively: lots of 4k pages followed
-    // by a small one. ld64 tried to minimize space and align them to real 4k
-    // boundaries. That might be worth doing, or perhaps we could perform some
-    // minor balancing for expected number of lookups.
-    std::vector<UnwindInfoPage> pages;
-    auto remainingInfos = llvm::makeArrayRef(unwindInfos);
-    do {
-      pages.push_back(UnwindInfoPage());
-
-      // FIXME: we only create regular pages at the moment. These can hold up to
-      // 1021 entries according to the documentation.
-      unsigned entriesInPage = std::min(1021U, (unsigned)remainingInfos.size());
-
-      pages.back().entries = remainingInfos.slice(0, entriesInPage);
-      remainingInfos = remainingInfos.slice(entriesInPage);
-
-      LLVM_DEBUG(llvm::dbgs()
-                 << "    Page from "
-                 << pages.back().entries[0].rangeStart->name() << " to "
-                 << pages.back().entries.back().rangeStart->name() << " + "
-                 << llvm::format("0x%x",
-                                 pages.back().entries.back().rangeLength)
-                 << " has " << entriesInPage << " entries\n");
-    } while (!remainingInfos.empty());
-
-    auto *unwind = new (_file.allocator())
-        UnwindInfoAtom(_archHandler, _file, _isBig, personalities,
-                       commonEncodings, pages, numLSDAs);
-    mergedFile.addAtom(*unwind);
-
-    // Finally, remove all __compact_unwind atoms now that we've processed them.
-    mergedFile.removeDefinedAtomsIf([](const DefinedAtom *atom) {
-      return atom->contentType() == DefinedAtom::typeCompactUnwindInfo;
-    });
-
-    return llvm::Error::success();
-  }
-
-  void collectCompactUnwindEntries(
-      const SimpleFile &mergedFile,
-      std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
-      std::vector<const Atom *> &personalities, uint32_t &numLSDAs) {
-    LLVM_DEBUG(llvm::dbgs() << "  Collecting __compact_unwind entries\n");
-
-    for (const DefinedAtom *atom : mergedFile.defined()) {
-      if (atom->contentType() != DefinedAtom::typeCompactUnwindInfo)
-        continue;
-
-      auto unwindEntry = extractCompactUnwindEntry(atom);
-      unwindLocs.insert(std::make_pair(unwindEntry.rangeStart, unwindEntry));
-
-      LLVM_DEBUG(llvm::dbgs() << "    Entry for "
-                              << unwindEntry.rangeStart->name() << ", encoding="
-                              << llvm::format("0x%08x", unwindEntry.encoding));
-      if (unwindEntry.personalityFunction)
-        LLVM_DEBUG(llvm::dbgs()
-                   << ", personality="
-                   << unwindEntry.personalityFunction->name()
-                   << ", lsdaLoc=" << unwindEntry.lsdaLocation->name());
-      LLVM_DEBUG(llvm::dbgs() << '\n');
-
-      // Count number of LSDAs we see, since we need to know how big the index
-      // will be while laying out the section.
-      if (unwindEntry.lsdaLocation)
-        ++numLSDAs;
-
-      // Gather the personality functions now, so that they're in deterministic
-      // order (derived from the DefinedAtom order).
-      if (unwindEntry.personalityFunction &&
-          !llvm::count(personalities, unwindEntry.personalityFunction))
-        personalities.push_back(unwindEntry.personalityFunction);
-    }
-  }
-
-  CompactUnwindEntry extractCompactUnwindEntry(const DefinedAtom *atom) {
-    CompactUnwindEntry entry;
-
-    for (const Reference *ref : *atom) {
-      switch (ref->offsetInAtom()) {
-      case 0:
-        // FIXME: there could legitimately be functions with multiple encoding
-        // entries. However, nothing produces them at the moment.
-        assert(ref->addend() == 0 && "unexpected offset into function");
-        entry.rangeStart = ref->target();
-        break;
-      case 0x10:
-        assert(ref->addend() == 0 && "unexpected offset into personality fn");
-        entry.personalityFunction = ref->target();
-        break;
-      case 0x18:
-        assert(ref->addend() == 0 && "unexpected offset into LSDA atom");
-        entry.lsdaLocation = ref->target();
-        break;
-      }
-    }
-
-    if (atom->rawContent().size() < 4 * sizeof(uint32_t))
-      return entry;
-
-    using normalized::read32;
-    entry.rangeLength =
-        read32(atom->rawContent().data() + 2 * sizeof(uint32_t), _isBig);
-    entry.encoding =
-        read32(atom->rawContent().data() + 3 * sizeof(uint32_t), _isBig);
-    return entry;
-  }
-
-  void
-  collectDwarfFrameEntries(const SimpleFile &mergedFile,
-                           std::map<const Atom *, const Atom *> &dwarfFrames) {
-    for (const DefinedAtom *ehFrameAtom : mergedFile.defined()) {
-      if (ehFrameAtom->contentType() != DefinedAtom::typeCFI)
-        continue;
-      if (ArchHandler::isDwarfCIE(_isBig, ehFrameAtom))
-        continue;
-
-      if (const Atom *function = _archHandler.fdeTargetFunction(ehFrameAtom))
-        dwarfFrames[function] = ehFrameAtom;
-    }
-  }
-
-  /// Every atom defined in __TEXT,__text needs an entry in the final
-  /// __unwind_info section (in order). These comes from two sources:
-  ///   + Input __compact_unwind sections where possible (after adding the
-  ///      personality function offset which is only known now).
-  ///   + A synthesised reference to __eh_frame if there's no __compact_unwind
-  ///     or too many personality functions to be accommodated.
-  std::vector<CompactUnwindEntry> createUnwindInfoEntries(
-      const SimpleFile &mergedFile,
-      const std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
-      const std::vector<const Atom *> &personalities,
-      const std::map<const Atom *, const Atom *> &dwarfFrames) {
-    std::vector<CompactUnwindEntry> unwindInfos;
-
-    LLVM_DEBUG(llvm::dbgs() << "  Creating __unwind_info entries\n");
-    // The final order in the __unwind_info section must be derived from the
-    // order of typeCode atoms, since that's how they'll be put into the object
-    // file eventually (yuck!).
-    for (const DefinedAtom *atom : mergedFile.defined()) {
-      if (atom->contentType() != DefinedAtom::typeCode)
-        continue;
-
-      unwindInfos.push_back(finalizeUnwindInfoEntryForAtom(
-          atom, unwindLocs, personalities, dwarfFrames));
-
-      LLVM_DEBUG(llvm::dbgs()
-                 << "    Entry for " << atom->name() << ", final encoding="
-                 << llvm::format("0x%08x", unwindInfos.back().encoding)
-                 << '\n');
-    }
-
-    return unwindInfos;
-  }
-
-  /// Remove unused EH frames.
-  ///
-  /// An EH frame is considered unused if there is a corresponding compact
-  /// unwind atom that doesn't require the EH frame.
-  void pruneUnusedEHFrames(
-                   SimpleFile &mergedFile,
-                   const std::vector<CompactUnwindEntry> &unwindInfos,
-                   const std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
-                   const std::map<const Atom *, const Atom *> &dwarfFrames) {
-
-    // Worklist of all 'used' FDEs.
-    std::vector<const DefinedAtom *> usedDwarfWorklist;
-
-    // We have to check two conditions when building the worklist:
-    // (1) EH frames used by compact unwind entries.
-    for (auto &entry : unwindInfos)
-      if (entry.ehFrame)
-        usedDwarfWorklist.push_back(cast<DefinedAtom>(entry.ehFrame));
-
-    // (2) EH frames that reference functions with no corresponding compact
-    //     unwind info.
-    for (auto &entry : dwarfFrames)
-      if (!unwindLocs.count(entry.first))
-        usedDwarfWorklist.push_back(cast<DefinedAtom>(entry.second));
-
-    // Add all transitively referenced CFI atoms by processing the worklist.
-    std::set<const Atom *> usedDwarfFrames;
-    while (!usedDwarfWorklist.empty()) {
-      const DefinedAtom *cfiAtom = usedDwarfWorklist.back();
-      usedDwarfWorklist.pop_back();
-      usedDwarfFrames.insert(cfiAtom);
-      for (const auto *ref : *cfiAtom) {
-        const DefinedAtom *cfiTarget = dyn_cast<DefinedAtom>(ref->target());
-        if (cfiTarget->contentType() == DefinedAtom::typeCFI)
-          usedDwarfWorklist.push_back(cfiTarget);
-      }
-    }
-
-    // Finally, delete all unreferenced CFI atoms.
-    mergedFile.removeDefinedAtomsIf([&](const DefinedAtom *atom) {
-      if ((atom->contentType() == DefinedAtom::typeCFI) &&
-          !usedDwarfFrames.count(atom))
-        return true;
-      return false;
-    });
-  }
-
-  CompactUnwindEntry finalizeUnwindInfoEntryForAtom(
-      const DefinedAtom *function,
-      const std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
-      const std::vector<const Atom *> &personalities,
-      const std::map<const Atom *, const Atom *> &dwarfFrames) {
-    auto unwindLoc = unwindLocs.find(function);
-
-    CompactUnwindEntry entry;
-    if (unwindLoc == unwindLocs.end()) {
-      // Default entry has correct encoding (0 => no unwind), but we need to
-      // synthesise the function.
-      entry.rangeStart = function;
-      entry.rangeLength = function->size();
-    } else
-      entry = unwindLoc->second;
-
-
-    // If there's no __compact_unwind entry, or it explicitly says to use
-    // __eh_frame, we need to try and fill in the correct DWARF atom.
-    if (entry.encoding == _archHandler.dwarfCompactUnwindType() ||
-        entry.encoding == 0) {
-      auto dwarfFrame = dwarfFrames.find(function);
-      if (dwarfFrame != dwarfFrames.end()) {
-        entry.encoding = _archHandler.dwarfCompactUnwindType();
-        entry.ehFrame = dwarfFrame->second;
-      }
-    }
-
-    auto personality = llvm::find(personalities, entry.personalityFunction);
-    uint32_t personalityIdx = personality == personalities.end()
-                                  ? 0
-                                  : personality - personalities.begin() + 1;
-
-    // FIXME: We should also use DWARF when there isn't enough room for the
-    // personality function in the compact encoding.
-    assert(personalityIdx < 4 && "too many personality functions");
-
-    entry.encoding |= personalityIdx << 28;
-
-    if (entry.lsdaLocation)
-      entry.encoding |= 1U << 30;
-
-    return entry;
-  }
-
-  const MachOLinkingContext &_ctx;
-  mach_o::ArchHandler &_archHandler;
-  MachOFile &_file;
-  bool _isBig;
-};
-
-void addCompactUnwindPass(PassManager &pm, const MachOLinkingContext &ctx) {
-  assert(ctx.needsCompactUnwindPass());
-  pm.add(std::make_unique<CompactUnwindPass>(ctx));
-}
-
-} // end namespace mach_o
-} // end namespace lld
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/DebugInfo.h b/gnu/llvm/lld/lib/ReaderWriter/MachO/DebugInfo.h
deleted file mode 100644 (file)
index 591dd1e..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-//===- lib/ReaderWriter/MachO/File.h ----------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_DEBUGINFO_H
-#define LLD_READER_WRITER_MACHO_DEBUGINFO_H
-
-#include "lld/Core/Atom.h"
-#include <vector>
-
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/raw_ostream.h"
-
-
-namespace lld {
-namespace mach_o {
-
-class DebugInfo {
-public:
-  enum class Kind {
-    Dwarf,
-    Stabs
-  };
-
-  Kind kind() const { return _kind; }
-
-  void setAllocator(std::unique_ptr<llvm::BumpPtrAllocator> allocator) {
-    _allocator = std::move(allocator);
-  }
-
-protected:
-  DebugInfo(Kind kind) : _kind(kind) {}
-
-private:
-  std::unique_ptr<llvm::BumpPtrAllocator> _allocator;
-  Kind _kind;
-};
-
-struct TranslationUnitSource {
-  StringRef name;
-  StringRef path;
-};
-
-class DwarfDebugInfo : public DebugInfo {
-public:
-  DwarfDebugInfo(TranslationUnitSource tu)
-    : DebugInfo(Kind::Dwarf), _tu(std::move(tu)) {}
-
-  static inline bool classof(const DebugInfo *di) {
-    return di->kind() == Kind::Dwarf;
-  }
-
-  const TranslationUnitSource &translationUnitSource() const { return _tu; }
-
-private:
-  TranslationUnitSource _tu;
-};
-
-struct Stab {
-  Stab(const Atom* atom, uint8_t type, uint8_t other, uint16_t desc,
-       uint32_t value, StringRef str)
-    : atom(atom), type(type), other(other), desc(desc), value(value),
-      str(str) {}
-
-  const class Atom*   atom;
-  uint8_t             type;
-  uint8_t             other;
-  uint16_t            desc;
-  uint32_t            value;
-  StringRef           str;
-};
-
-inline raw_ostream& operator<<(raw_ostream &os, Stab &s) {
-  os << "Stab -- atom: " << llvm::format("%p", s.atom) << ", type: " << (uint32_t)s.type
-     << ", other: " << (uint32_t)s.other << ", desc: " << s.desc << ", value: " << s.value
-     << ", str: '" << s.str << "'";
-  return os;
-}
-
-class StabsDebugInfo : public DebugInfo {
-public:
-
-  typedef std::vector<Stab> StabsList;
-
-  StabsDebugInfo(StabsList stabs)
-    : DebugInfo(Kind::Stabs), _stabs(std::move(stabs)) {}
-
-  static inline bool classof(const DebugInfo *di) {
-    return di->kind() == Kind::Stabs;
-  }
-
-  const StabsList& stabs() const { return _stabs; }
-
-public:
-  StabsList _stabs;
-};
-
-} // end namespace mach_o
-} // end namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_DEBUGINFO_H
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/ExecutableAtoms.h b/gnu/llvm/lld/lib/ReaderWriter/MachO/ExecutableAtoms.h
deleted file mode 100644 (file)
index ce94be4..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-//===- lib/ReaderWriter/MachO/ExecutableAtoms.h ---------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
-#define LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
-
-#include "Atoms.h"
-#include "File.h"
-
-#include "llvm/BinaryFormat/MachO.h"
-
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/Simple.h"
-#include "lld/Core/UndefinedAtom.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-
-namespace lld {
-namespace mach_o {
-
-
-//
-// CEntryFile adds an UndefinedAtom for "_main" so that the Resolving
-// phase will fail if "_main" is undefined.
-//
-class CEntryFile : public SimpleFile {
-public:
-  CEntryFile(const MachOLinkingContext &context)
-      : SimpleFile("C entry", kindCEntryObject),
-       _undefMain(*this, context.entrySymbolName()) {
-    this->addAtom(_undefMain);
-  }
-
-private:
-  SimpleUndefinedAtom   _undefMain;
-};
-
-
-//
-// StubHelperFile adds an UndefinedAtom for "dyld_stub_binder" so that
-// the Resolveing phase will fail if "dyld_stub_binder" is undefined.
-//
-class StubHelperFile : public SimpleFile {
-public:
-  StubHelperFile(const MachOLinkingContext &context)
-      : SimpleFile("stub runtime", kindStubHelperObject),
-        _undefBinder(*this, context.binderSymbolName()) {
-    this->addAtom(_undefBinder);
-  }
-
-private:
-  SimpleUndefinedAtom   _undefBinder;
-};
-
-
-//
-// MachHeaderAliasFile lazily instantiates the magic symbols that mark the start
-// of the mach_header for final linked images.
-//
-class MachHeaderAliasFile : public SimpleFile {
-public:
-  MachHeaderAliasFile(const MachOLinkingContext &context)
-    : SimpleFile("mach_header symbols", kindHeaderObject) {
-    StringRef machHeaderSymbolName;
-    DefinedAtom::Scope symbolScope = DefinedAtom::scopeLinkageUnit;
-    StringRef dsoHandleName;
-    switch (context.outputMachOType()) {
-    case llvm::MachO::MH_OBJECT:
-      machHeaderSymbolName = "__mh_object_header";
-      break;
-    case llvm::MachO::MH_EXECUTE:
-      machHeaderSymbolName = "__mh_execute_header";
-      symbolScope = DefinedAtom::scopeGlobal;
-      dsoHandleName = "___dso_handle";
-      break;
-    case llvm::MachO::MH_FVMLIB:
-      llvm_unreachable("no mach_header symbol for file type");
-    case llvm::MachO::MH_CORE:
-      llvm_unreachable("no mach_header symbol for file type");
-    case llvm::MachO::MH_PRELOAD:
-      llvm_unreachable("no mach_header symbol for file type");
-    case llvm::MachO::MH_DYLIB:
-      machHeaderSymbolName = "__mh_dylib_header";
-      dsoHandleName = "___dso_handle";
-      break;
-    case llvm::MachO::MH_DYLINKER:
-      machHeaderSymbolName = "__mh_dylinker_header";
-      dsoHandleName = "___dso_handle";
-      break;
-    case llvm::MachO::MH_BUNDLE:
-      machHeaderSymbolName = "__mh_bundle_header";
-      dsoHandleName = "___dso_handle";
-      break;
-    case llvm::MachO::MH_DYLIB_STUB:
-      llvm_unreachable("no mach_header symbol for file type");
-    case llvm::MachO::MH_DSYM:
-      llvm_unreachable("no mach_header symbol for file type");
-    case llvm::MachO::MH_KEXT_BUNDLE:
-      dsoHandleName = "___dso_handle";
-      break;
-    }
-    if (!machHeaderSymbolName.empty())
-      _definedAtoms.push_back(new (allocator()) MachODefinedAtom(
-          *this, machHeaderSymbolName, symbolScope,
-          DefinedAtom::typeMachHeader, DefinedAtom::mergeNo, false,
-          true /* noDeadStrip */,
-          ArrayRef<uint8_t>(), DefinedAtom::Alignment(4096)));
-
-    if (!dsoHandleName.empty())
-      _definedAtoms.push_back(new (allocator()) MachODefinedAtom(
-          *this, dsoHandleName, DefinedAtom::scopeLinkageUnit,
-          DefinedAtom::typeDSOHandle, DefinedAtom::mergeNo, false,
-          true /* noDeadStrip */,
-          ArrayRef<uint8_t>(), DefinedAtom::Alignment(1)));
-  }
-
-  const AtomRange<DefinedAtom> defined() const override {
-    return _definedAtoms;
-  }
-  const AtomRange<UndefinedAtom> undefined() const override {
-    return _noUndefinedAtoms;
-  }
-
-  const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
-    return _noSharedLibraryAtoms;
-  }
-
-  const AtomRange<AbsoluteAtom> absolute() const override {
-    return _noAbsoluteAtoms;
-  }
-
-  void clearAtoms() override {
-    _definedAtoms.clear();
-    _noUndefinedAtoms.clear();
-    _noSharedLibraryAtoms.clear();
-    _noAbsoluteAtoms.clear();
-  }
-
-
-private:
-  mutable AtomVector<DefinedAtom> _definedAtoms;
-};
-
-} // namespace mach_o
-} // namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/File.h b/gnu/llvm/lld/lib/ReaderWriter/MachO/File.h
deleted file mode 100644 (file)
index 7783296..0000000
+++ /dev/null
@@ -1,467 +0,0 @@
-//===- lib/ReaderWriter/MachO/File.h ----------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_FILE_H
-#define LLD_READER_WRITER_MACHO_FILE_H
-
-#include "Atoms.h"
-#include "DebugInfo.h"
-#include "MachONormalizedFile.h"
-#include "lld/Core/SharedLibraryFile.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/Support/Format.h"
-#include "llvm/TextAPI/InterfaceFile.h"
-#include "llvm/TextAPI/TextAPIReader.h"
-#include <unordered_map>
-
-namespace lld {
-namespace mach_o {
-
-using lld::mach_o::normalized::Section;
-
-class MachOFile : public SimpleFile {
-public:
-
-  /// Real file constructor - for on-disk files.
-  MachOFile(std::unique_ptr<MemoryBuffer> mb, MachOLinkingContext *ctx)
-    : SimpleFile(mb->getBufferIdentifier(), File::kindMachObject),
-      _mb(std::move(mb)), _ctx(ctx) {}
-
-  /// Dummy file constructor - for virtual files.
-  MachOFile(StringRef path)
-    : SimpleFile(path, File::kindMachObject) {}
-
-  void addDefinedAtom(StringRef name, Atom::Scope scope,
-                      DefinedAtom::ContentType type, DefinedAtom::Merge merge,
-                      uint64_t sectionOffset, uint64_t contentSize, bool thumb,
-                      bool noDeadStrip, bool copyRefs,
-                      const Section *inSection) {
-    assert(sectionOffset+contentSize <= inSection->content.size());
-    ArrayRef<uint8_t> content = inSection->content.slice(sectionOffset,
-                                                        contentSize);
-    if (copyRefs) {
-      // Make a copy of the atom's name and content that is owned by this file.
-      name = name.copy(allocator());
-      content = content.copy(allocator());
-    }
-    DefinedAtom::Alignment align(
-        inSection->alignment,
-        sectionOffset % inSection->alignment);
-    auto *atom =
-        new (allocator()) MachODefinedAtom(*this, name, scope, type, merge,
-                                           thumb, noDeadStrip, content, align);
-    addAtomForSection(inSection, atom, sectionOffset);
-  }
-
-  void addDefinedAtomInCustomSection(StringRef name, Atom::Scope scope,
-                      DefinedAtom::ContentType type, DefinedAtom::Merge merge,
-                      bool thumb, bool noDeadStrip, uint64_t sectionOffset,
-                      uint64_t contentSize, StringRef sectionName,
-                      bool copyRefs, const Section *inSection) {
-    assert(sectionOffset+contentSize <= inSection->content.size());
-    ArrayRef<uint8_t> content = inSection->content.slice(sectionOffset,
-                                                        contentSize);
-   if (copyRefs) {
-      // Make a copy of the atom's name and content that is owned by this file.
-      name = name.copy(allocator());
-      content = content.copy(allocator());
-      sectionName = sectionName.copy(allocator());
-    }
-    DefinedAtom::Alignment align(
-        inSection->alignment,
-        sectionOffset % inSection->alignment);
-    auto *atom =
-        new (allocator()) MachODefinedCustomSectionAtom(*this, name, scope, type,
-                                                        merge, thumb,
-                                                        noDeadStrip, content,
-                                                        sectionName, align);
-    addAtomForSection(inSection, atom, sectionOffset);
-  }
-
-  void addZeroFillDefinedAtom(StringRef name, Atom::Scope scope,
-                              uint64_t sectionOffset, uint64_t size,
-                              bool noDeadStrip, bool copyRefs,
-                              const Section *inSection) {
-    if (copyRefs) {
-      // Make a copy of the atom's name and content that is owned by this file.
-      name = name.copy(allocator());
-    }
-    DefinedAtom::Alignment align(
-        inSection->alignment,
-        sectionOffset % inSection->alignment);
-
-    DefinedAtom::ContentType type = DefinedAtom::typeUnknown;
-    switch (inSection->type) {
-    case llvm::MachO::S_ZEROFILL:
-      type = DefinedAtom::typeZeroFill;
-      break;
-    case llvm::MachO::S_THREAD_LOCAL_ZEROFILL:
-      type = DefinedAtom::typeTLVInitialZeroFill;
-      break;
-    default:
-      llvm_unreachable("Unrecognized zero-fill section");
-    }
-
-    auto *atom =
-        new (allocator()) MachODefinedAtom(*this, name, scope, type, size,
-                                           noDeadStrip, align);
-    addAtomForSection(inSection, atom, sectionOffset);
-  }
-
-  void addUndefinedAtom(StringRef name, bool copyRefs) {
-    if (copyRefs) {
-      // Make a copy of the atom's name that is owned by this file.
-      name = name.copy(allocator());
-    }
-    auto *atom = new (allocator()) SimpleUndefinedAtom(*this, name);
-    addAtom(*atom);
-    _undefAtoms[name] = atom;
-  }
-
-  void addTentativeDefAtom(StringRef name, Atom::Scope scope, uint64_t size,
-                           DefinedAtom::Alignment align, bool copyRefs) {
-    if (copyRefs) {
-      // Make a copy of the atom's name that is owned by this file.
-      name = name.copy(allocator());
-    }
-    auto *atom =
-        new (allocator()) MachOTentativeDefAtom(*this, name, scope, size, align);
-    addAtom(*atom);
-    _undefAtoms[name] = atom;
-  }
-
-  /// Search this file for the atom from 'section' that covers
-  /// 'offsetInSect'.  Returns nullptr is no atom found.
-  MachODefinedAtom *findAtomCoveringAddress(const Section &section,
-                                            uint64_t offsetInSect,
-                                            uint32_t *foundOffsetAtom=nullptr) {
-    const auto &pos = _sectionAtoms.find(&section);
-    if (pos == _sectionAtoms.end())
-      return nullptr;
-    const auto &vec = pos->second;
-    assert(offsetInSect < section.content.size());
-    // Vector of atoms for section are already sorted, so do binary search.
-    const auto &atomPos = std::lower_bound(vec.begin(), vec.end(), offsetInSect,
-        [offsetInSect](const SectionOffsetAndAtom &ao,
-                       uint64_t targetAddr) -> bool {
-          // Each atom has a start offset of its slice of the
-          // section's content. This compare function must return true
-          // iff the atom's range is before the offset being searched for.
-          uint64_t atomsEndOffset = ao.offset+ao.atom->rawContent().size();
-          return (atomsEndOffset <= offsetInSect);
-        });
-    if (atomPos == vec.end())
-      return nullptr;
-    if (foundOffsetAtom)
-      *foundOffsetAtom = offsetInSect - atomPos->offset;
-    return atomPos->atom;
-  }
-
-  /// Searches this file for an UndefinedAtom named 'name'. Returns
-  /// nullptr is no such atom found.
-  const lld::Atom *findUndefAtom(StringRef name) {
-    auto pos = _undefAtoms.find(name);
-    if (pos == _undefAtoms.end())
-      return nullptr;
-    return pos->second;
-  }
-
-  typedef std::function<void (MachODefinedAtom* atom)> DefinedAtomVisitor;
-
-  void eachDefinedAtom(DefinedAtomVisitor vistor) {
-    for (auto &sectAndAtoms : _sectionAtoms) {
-      for (auto &offAndAtom : sectAndAtoms.second) {
-        vistor(offAndAtom.atom);
-      }
-    }
-  }
-
-  typedef std::function<void(MachODefinedAtom *atom, uint64_t offset)>
-      SectionAtomVisitor;
-
-  void eachAtomInSection(const Section &section, SectionAtomVisitor visitor) {
-    auto pos = _sectionAtoms.find(&section);
-    if (pos == _sectionAtoms.end())
-      return;
-    auto vec = pos->second;
-
-    for (auto &offAndAtom : vec)
-      visitor(offAndAtom.atom, offAndAtom.offset);
-  }
-
-  MachOLinkingContext::Arch arch() const { return _arch; }
-  void setArch(MachOLinkingContext::Arch arch) { _arch = arch; }
-
-  MachOLinkingContext::OS OS() const { return _os; }
-  void setOS(MachOLinkingContext::OS os) { _os = os; }
-
-  MachOLinkingContext::ObjCConstraint objcConstraint() const {
-    return _objcConstraint;
-  }
-  void setObjcConstraint(MachOLinkingContext::ObjCConstraint v) {
-    _objcConstraint = v;
-  }
-
-  uint32_t minVersion() const { return _minVersion; }
-  void setMinVersion(uint32_t v) { _minVersion = v; }
-
-  LoadCommandType minVersionLoadCommandKind() const {
-    return _minVersionLoadCommandKind;
-  }
-  void setMinVersionLoadCommandKind(LoadCommandType v) {
-    _minVersionLoadCommandKind = v;
-  }
-
-  uint32_t swiftVersion() const { return _swiftVersion; }
-  void setSwiftVersion(uint32_t v) { _swiftVersion = v; }
-
-  bool subsectionsViaSymbols() const {
-    return _flags & llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
-  }
-  void setFlags(normalized::FileFlags v) { _flags = v; }
-
-  /// Methods for support type inquiry through isa, cast, and dyn_cast:
-  static inline bool classof(const File *F) {
-    return F->kind() == File::kindMachObject;
-  }
-
-  void setDebugInfo(std::unique_ptr<DebugInfo> debugInfo) {
-    _debugInfo = std::move(debugInfo);
-  }
-
-  DebugInfo* debugInfo() const { return _debugInfo.get(); }
-  std::unique_ptr<DebugInfo> takeDebugInfo() { return std::move(_debugInfo); }
-
-protected:
-  std::error_code doParse() override {
-    // Convert binary file to normalized mach-o.
-    auto normFile = normalized::readBinary(_mb, _ctx->arch());
-    if (auto ec = normFile.takeError())
-      return llvm::errorToErrorCode(std::move(ec));
-    // Convert normalized mach-o to atoms.
-    if (auto ec = normalized::normalizedObjectToAtoms(this, **normFile, false))
-      return llvm::errorToErrorCode(std::move(ec));
-    return std::error_code();
-  }
-
-private:
-  struct SectionOffsetAndAtom { uint64_t offset;  MachODefinedAtom *atom; };
-
-  void addAtomForSection(const Section *inSection, MachODefinedAtom* atom,
-                         uint64_t sectionOffset) {
-    SectionOffsetAndAtom offAndAtom;
-    offAndAtom.offset = sectionOffset;
-    offAndAtom.atom   = atom;
-     _sectionAtoms[inSection].push_back(offAndAtom);
-    addAtom(*atom);
-  }
-
-  typedef llvm::DenseMap<const normalized::Section *,
-                         std::vector<SectionOffsetAndAtom>>  SectionToAtoms;
-  typedef llvm::StringMap<const lld::Atom *> NameToAtom;
-
-  std::unique_ptr<MemoryBuffer> _mb;
-  MachOLinkingContext          *_ctx;
-  SectionToAtoms                _sectionAtoms;
-  NameToAtom                     _undefAtoms;
-  MachOLinkingContext::Arch      _arch = MachOLinkingContext::arch_unknown;
-  MachOLinkingContext::OS        _os = MachOLinkingContext::OS::unknown;
-  uint32_t                       _minVersion = 0;
-  LoadCommandType               _minVersionLoadCommandKind = (LoadCommandType)0;
-  MachOLinkingContext::ObjCConstraint _objcConstraint =
-      MachOLinkingContext::objc_unknown;
-  uint32_t                       _swiftVersion = 0;
-  normalized::FileFlags        _flags = llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
-  std::unique_ptr<DebugInfo>   _debugInfo;
-};
-
-class MachODylibFile : public SharedLibraryFile {
-public:
-  MachODylibFile(std::unique_ptr<MemoryBuffer> mb, MachOLinkingContext *ctx)
-      : SharedLibraryFile(mb->getBufferIdentifier()),
-        _mb(std::move(mb)), _ctx(ctx) {}
-
-  MachODylibFile(StringRef path) : SharedLibraryFile(path) {}
-
-  OwningAtomPtr<SharedLibraryAtom> exports(StringRef name) const override {
-    // Pass down _installName so that if this requested symbol
-    // is re-exported through this dylib, the SharedLibraryAtom's loadName()
-    // is this dylib installName and not the implementation dylib's.
-    // NOTE: isData is not needed for dylibs (it matters for static libs).
-    return exports(name, _installName);
-  }
-
-  /// Adds symbol name that this dylib exports. The corresponding
-  /// SharedLibraryAtom is created lazily (since most symbols are not used).
-  void addExportedSymbol(StringRef name, bool weakDef, bool copyRefs) {
-    if (copyRefs) {
-      name = name.copy(allocator());
-    }
-    AtomAndFlags info(weakDef);
-    _nameToAtom[name] = info;
-  }
-
-  void addReExportedDylib(StringRef dylibPath) {
-    _reExportedDylibs.emplace_back(dylibPath);
-  }
-
-  StringRef installName() const { return _installName; }
-  uint32_t currentVersion() { return _currentVersion; }
-  uint32_t compatVersion() { return _compatVersion; }
-
-  void setInstallName(StringRef name) { _installName = name; }
-  void setCompatVersion(uint32_t version) { _compatVersion = version; }
-  void setCurrentVersion(uint32_t version) { _currentVersion = version; }
-
-  typedef std::function<MachODylibFile *(StringRef)> FindDylib;
-
-  void loadReExportedDylibs(FindDylib find) {
-    for (ReExportedDylib &entry : _reExportedDylibs) {
-      if (!entry.file)
-        entry.file = find(entry.path);
-    }
-  }
-
-  StringRef getDSOName() const override { return _installName; }
-
-  std::error_code doParse() override {
-    // Convert binary file to normalized mach-o.
-    auto normFile = normalized::readBinary(_mb, _ctx->arch());
-    if (auto ec = normFile.takeError())
-      return llvm::errorToErrorCode(std::move(ec));
-    // Convert normalized mach-o to atoms.
-    if (auto ec = normalized::normalizedDylibToAtoms(this, **normFile, false))
-      return llvm::errorToErrorCode(std::move(ec));
-    return std::error_code();
-  }
-
-protected:
-  OwningAtomPtr<SharedLibraryAtom> exports(StringRef name,
-                                   StringRef installName) const {
-    // First, check if requested symbol is directly implemented by this dylib.
-    auto entry = _nameToAtom.find(name);
-    if (entry != _nameToAtom.end()) {
-      // FIXME: Make this map a set and only used in assert builds.
-      // Note, its safe to assert here as the resolver is the only client of
-      // this API and it only requests exports for undefined symbols.
-      // If we return from here we are no longer undefined so we should never
-      // get here again.
-      assert(!entry->second.atom && "Duplicate shared library export");
-      bool weakDef = entry->second.weakDef;
-      auto *atom = new (allocator()) MachOSharedLibraryAtom(*this, name,
-                                                            installName,
-                                                            weakDef);
-      entry->second.atom = atom;
-      return atom;
-    }
-
-    // Next, check if symbol is implemented in some re-exported dylib.
-    for (const ReExportedDylib &dylib : _reExportedDylibs) {
-      assert(dylib.file);
-      auto atom = dylib.file->exports(name, installName);
-      if (atom.get())
-        return atom;
-    }
-
-    // Symbol not exported or re-exported by this dylib.
-    return nullptr;
-  }
-
-  struct ReExportedDylib {
-    ReExportedDylib(StringRef p) : path(p), file(nullptr) { }
-    ReExportedDylib(StringRef p, MachODylibFile *file) : path(p), file(file) { }
-    StringRef       path;
-    MachODylibFile *file;
-  };
-
-  struct AtomAndFlags {
-    AtomAndFlags() : atom(nullptr), weakDef(false) { }
-    AtomAndFlags(bool weak) : atom(nullptr), weakDef(weak) { }
-    const SharedLibraryAtom  *atom;
-    bool                      weakDef;
-  };
-
-  std::unique_ptr<MemoryBuffer>              _mb;
-  MachOLinkingContext                       *_ctx;
-  StringRef                                  _installName;
-  uint32_t                                   _currentVersion;
-  uint32_t                                   _compatVersion;
-  std::vector<ReExportedDylib>               _reExportedDylibs;
-  mutable std::unordered_map<StringRef, AtomAndFlags> _nameToAtom;
-};
-
-class TAPIFile : public MachODylibFile {
-public:
-
-  TAPIFile(std::unique_ptr<MemoryBuffer> mb, MachOLinkingContext *ctx)
-      : MachODylibFile(std::move(mb), ctx) {}
-
-  std::error_code doParse() override {
-
-    llvm::Expected<std::unique_ptr<llvm::MachO::InterfaceFile>> result =
-        llvm::MachO::TextAPIReader::get(*_mb);
-    if (!result)
-      return std::make_error_code(std::errc::invalid_argument);
-
-    std::unique_ptr<llvm::MachO::InterfaceFile> interface{std::move(*result)};
-    return loadFromInterface(*interface);
-  }
-
-private:
-  std::error_code loadFromInterface(llvm::MachO::InterfaceFile &interface) {
-    llvm::MachO::Architecture arch;
-    switch(_ctx->arch()) {
-    case MachOLinkingContext::arch_x86:
-      arch = llvm::MachO::AK_i386;
-      break;
-    case MachOLinkingContext::arch_x86_64:
-      arch = llvm::MachO::AK_x86_64;
-      break;
-    case MachOLinkingContext::arch_arm64:
-      arch = llvm::MachO::AK_arm64;
-      break;
-    default:
-      return std::make_error_code(std::errc::invalid_argument);
-    }
-
-    setInstallName(interface.getInstallName().copy(allocator()));
-    // TODO(compnerd) filter out symbols based on the target platform
-    for (const auto symbol : interface.symbols())
-      if (symbol->getArchitectures().has(arch))
-        addExportedSymbol(symbol->getName(), symbol->isWeakDefined(), true);
-
-    for (const llvm::MachO::InterfaceFileRef &reexport :
-         interface.reexportedLibraries())
-      addReExportedDylib(reexport.getInstallName().copy(allocator()));
-
-    for (const auto& document : interface.documents()) {
-      for (auto& reexport : _reExportedDylibs) {
-        if (reexport.path != document->getInstallName())
-          continue;
-        assert(!reexport.file);
-        _ownedFiles.push_back(std::make_unique<TAPIFile>(
-            MemoryBuffer::getMemBuffer("", _mb->getBufferIdentifier()), _ctx));
-        reexport.file = _ownedFiles.back().get();
-        std::error_code err = _ownedFiles.back()->loadFromInterface(*document);
-        if (err)
-          return err;
-      }
-    }
-
-    return std::error_code();
-  }
-
-  std::vector<std::unique_ptr<TAPIFile>> _ownedFiles;
-};
-
-} // end namespace mach_o
-} // end namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_FILE_H
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/FlatNamespaceFile.h b/gnu/llvm/lld/lib/ReaderWriter/MachO/FlatNamespaceFile.h
deleted file mode 100644 (file)
index 1885eff..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-//===- lib/ReaderWriter/MachO/FlatNamespaceFile.h -------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_FLAT_NAMESPACE_FILE_H
-#define LLD_READER_WRITER_MACHO_FLAT_NAMESPACE_FILE_H
-
-#include "Atoms.h"
-#include "lld/Core/SharedLibraryFile.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/Support/Debug.h"
-
-namespace lld {
-namespace mach_o {
-
-//
-// A FlateNamespaceFile instance may be added as a resolution source of last
-// resort, depending on how -flat_namespace and -undefined are set.
-//
-class FlatNamespaceFile : public SharedLibraryFile {
-public:
-  FlatNamespaceFile(const MachOLinkingContext &context)
-    : SharedLibraryFile("flat namespace") { }
-
-  OwningAtomPtr<SharedLibraryAtom> exports(StringRef name) const override {
-    return new (allocator()) MachOSharedLibraryAtom(*this, name, getDSOName(),
-                                                    false);
-  }
-
-  StringRef getDSOName() const override { return "flat-namespace"; }
-
-  const AtomRange<DefinedAtom> defined() const override {
-    return _noDefinedAtoms;
-  }
-  const AtomRange<UndefinedAtom> undefined() const override {
-    return _noUndefinedAtoms;
-  }
-
-  const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
-    return _noSharedLibraryAtoms;
-  }
-
-  const AtomRange<AbsoluteAtom> absolute() const override {
-    return _noAbsoluteAtoms;
-  }
-
-  void clearAtoms() override {
-    _noDefinedAtoms.clear();
-    _noUndefinedAtoms.clear();
-    _noSharedLibraryAtoms.clear();
-    _noAbsoluteAtoms.clear();
-  }
-};
-
-} // namespace mach_o
-} // namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_FLAT_NAMESPACE_FILE_H
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/GOTPass.cpp b/gnu/llvm/lld/lib/ReaderWriter/MachO/GOTPass.cpp
deleted file mode 100644 (file)
index 10e611c..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-//===- lib/ReaderWriter/MachO/GOTPass.cpp -----------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// This linker pass transforms all GOT kind references to real references.
-/// That is, in assembly you can write something like:
-///     movq foo@GOTPCREL(%rip), %rax
-/// which means you want to load a pointer to "foo" out of the GOT (global
-/// Offsets Table). In the object file, the Atom containing this instruction
-/// has a Reference whose target is an Atom named "foo" and the Reference
-/// kind is a GOT load.  The linker needs to instantiate a pointer sized
-/// GOT entry.  This is done be creating a GOT Atom to represent that pointer
-/// sized data in this pass, and altering the Atom graph so the Reference now
-/// points to the GOT Atom entry (corresponding to "foo") and changing the
-/// Reference Kind to reflect it is now pointing to a GOT entry (rather
-/// then needing a GOT entry).
-///
-/// There is one optimization the linker can do here.  If the target of the GOT
-/// is in the same linkage unit and does not need to be interposable, and
-/// the GOT use is just a load (not some other operation), this pass can
-/// transform that load into an LEA (add).  This optimizes away one memory load
-/// which at runtime that could stall the pipeline.  This optimization only
-/// works for architectures in which a (GOT) load instruction can be change to
-/// an LEA instruction that is the same size.  The method isGOTAccess() should
-/// only return true for "canBypassGOT" if this optimization is supported.
-///
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "File.h"
-#include "MachOPasses.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/STLExtras.h"
-
-namespace lld {
-namespace mach_o {
-
-//
-//  GOT Entry Atom created by the GOT pass.
-//
-class GOTEntryAtom : public SimpleDefinedAtom {
-public:
-  GOTEntryAtom(const File &file, bool is64, StringRef name)
-    : SimpleDefinedAtom(file), _is64(is64), _name(name) { }
-
-  ~GOTEntryAtom() override = default;
-
-  ContentType contentType() const override {
-    return DefinedAtom::typeGOT;
-  }
-
-  Alignment alignment() const override {
-    return _is64 ? 8 : 4;
-  }
-
-  uint64_t size() const override {
-    return _is64 ? 8 : 4;
-  }
-
-  ContentPermissions permissions() const override {
-    return DefinedAtom::permRW_;
-  }
-
-  ArrayRef<uint8_t> rawContent() const override {
-    static const uint8_t zeros[] =
-        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-    return llvm::makeArrayRef(zeros, size());
-  }
-
-  StringRef slotName() const {
-    return _name;
-  }
-
-private:
-  const bool _is64;
-  StringRef _name;
-};
-
-/// Pass for instantiating and optimizing GOT slots.
-///
-class GOTPass : public Pass {
-public:
-  GOTPass(const MachOLinkingContext &context)
-      : _ctx(context), _archHandler(_ctx.archHandler()),
-        _file(*_ctx.make_file<MachOFile>("<mach-o GOT Pass>")) {
-    _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
-  }
-
-private:
-  llvm::Error perform(SimpleFile &mergedFile) override {
-    // Scan all references in all atoms.
-    for (const DefinedAtom *atom : mergedFile.defined()) {
-      for (const Reference *ref : *atom) {
-        // Look at instructions accessing the GOT.
-        bool canBypassGOT;
-        if (!_archHandler.isGOTAccess(*ref, canBypassGOT))
-          continue;
-        const Atom *target = ref->target();
-        assert(target != nullptr);
-
-        if (!shouldReplaceTargetWithGOTAtom(target, canBypassGOT)) {
-          // Update reference kind to reflect that target is a direct access.
-          _archHandler.updateReferenceToGOT(ref, false);
-        } else {
-          // Replace the target with a reference to a GOT entry.
-          const DefinedAtom *gotEntry = makeGOTEntry(target);
-          const_cast<Reference *>(ref)->setTarget(gotEntry);
-          // Update reference kind to reflect that target is now a GOT entry.
-          _archHandler.updateReferenceToGOT(ref, true);
-        }
-      }
-    }
-
-    // Sort and add all created GOT Atoms to master file
-    std::vector<const GOTEntryAtom *> entries;
-    entries.reserve(_targetToGOT.size());
-    for (auto &it : _targetToGOT)
-      entries.push_back(it.second);
-    std::sort(entries.begin(), entries.end(),
-              [](const GOTEntryAtom *left, const GOTEntryAtom *right) {
-      return (left->slotName().compare(right->slotName()) < 0);
-    });
-    for (const GOTEntryAtom *slot : entries)
-      mergedFile.addAtom(*slot);
-
-    return llvm::Error::success();
-  }
-
-  bool shouldReplaceTargetWithGOTAtom(const Atom *target, bool canBypassGOT) {
-    // Accesses to shared library symbols must go through GOT.
-    if (isa<SharedLibraryAtom>(target))
-      return true;
-    // Accesses to interposable symbols in same linkage unit must also go
-    // through GOT.
-    const DefinedAtom *defTarget = dyn_cast<DefinedAtom>(target);
-    if (defTarget != nullptr &&
-        defTarget->interposable() != DefinedAtom::interposeNo) {
-      assert(defTarget->scope() != DefinedAtom::scopeTranslationUnit);
-      return true;
-    }
-    // Target does not require indirection.  So, if instruction allows GOT to be
-    // by-passed, do that optimization and don't create GOT entry.
-    return !canBypassGOT;
-  }
-
-  const DefinedAtom *makeGOTEntry(const Atom *target) {
-    auto pos = _targetToGOT.find(target);
-    if (pos == _targetToGOT.end()) {
-      auto *gotEntry = new (_file.allocator())
-          GOTEntryAtom(_file, _ctx.is64Bit(), target->name());
-      _targetToGOT[target] = gotEntry;
-      const ArchHandler::ReferenceInfo &nlInfo = _archHandler.stubInfo().
-                                                nonLazyPointerReferenceToBinder;
-      gotEntry->addReference(Reference::KindNamespace::mach_o, nlInfo.arch,
-                             nlInfo.kind, 0, target, 0);
-      return gotEntry;
-    }
-    return pos->second;
-  }
-
-  const MachOLinkingContext &_ctx;
-  mach_o::ArchHandler                             &_archHandler;
-  MachOFile                                       &_file;
-  llvm::DenseMap<const Atom*, const GOTEntryAtom*> _targetToGOT;
-};
-
-void addGOTPass(PassManager &pm, const MachOLinkingContext &ctx) {
-  assert(ctx.needsGOTPass());
-  pm.add(std::make_unique<GOTPass>(ctx));
-}
-
-} // end namespace mach_o
-} // end namespace lld
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/LayoutPass.cpp b/gnu/llvm/lld/lib/ReaderWriter/MachO/LayoutPass.cpp
deleted file mode 100644 (file)
index e92fdf1..0000000
+++ /dev/null
@@ -1,490 +0,0 @@
-//===-- ReaderWriter/MachO/LayoutPass.cpp - Layout atoms ------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "LayoutPass.h"
-#include "lld/Core/Instrumentation.h"
-#include "lld/Core/PassManager.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Parallel.h"
-#include <algorithm>
-#include <set>
-#include <utility>
-
-using namespace lld;
-
-#define DEBUG_TYPE "LayoutPass"
-
-namespace lld {
-namespace mach_o {
-
-static bool compareAtoms(const LayoutPass::SortKey &,
-                         const LayoutPass::SortKey &,
-                         LayoutPass::SortOverride customSorter);
-
-#ifndef NDEBUG
-// Return "reason (leftval, rightval)"
-static std::string formatReason(StringRef reason, int leftVal, int rightVal) {
-  return (Twine(reason) + " (" + Twine(leftVal) + ", " + Twine(rightVal) + ")")
-      .str();
-}
-
-// Less-than relationship of two atoms must be transitive, which is, if a < b
-// and b < c, a < c must be true. This function checks the transitivity by
-// checking the sort results.
-static void checkTransitivity(std::vector<LayoutPass::SortKey> &vec,
-                              LayoutPass::SortOverride customSorter) {
-  for (auto i = vec.begin(), e = vec.end(); (i + 1) != e; ++i) {
-    for (auto j = i + 1; j != e; ++j) {
-      assert(compareAtoms(*i, *j, customSorter));
-      assert(!compareAtoms(*j, *i, customSorter));
-    }
-  }
-}
-
-// Helper functions to check follow-on graph.
-typedef llvm::DenseMap<const DefinedAtom *, const DefinedAtom *> AtomToAtomT;
-
-static std::string atomToDebugString(const Atom *atom) {
-  const DefinedAtom *definedAtom = dyn_cast<DefinedAtom>(atom);
-  std::string str;
-  llvm::raw_string_ostream s(str);
-  if (definedAtom->name().empty())
-    s << "<anonymous " << definedAtom << ">";
-  else
-    s << definedAtom->name();
-  s << " in ";
-  if (definedAtom->customSectionName().empty())
-    s << "<anonymous>";
-  else
-    s << definedAtom->customSectionName();
-  s.flush();
-  return str;
-}
-
-static void showCycleDetectedError(const Registry &registry,
-                                   AtomToAtomT &followOnNexts,
-                                   const DefinedAtom *atom) {
-  const DefinedAtom *start = atom;
-  llvm::dbgs() << "There's a cycle in a follow-on chain!\n";
-  do {
-    llvm::dbgs() << "  " << atomToDebugString(atom) << "\n";
-    for (const Reference *ref : *atom) {
-      StringRef kindValStr;
-      if (!registry.referenceKindToString(ref->kindNamespace(), ref->kindArch(),
-                                          ref->kindValue(), kindValStr)) {
-        kindValStr = "<unknown>";
-      }
-      llvm::dbgs() << "    " << kindValStr
-                   << ": " << atomToDebugString(ref->target()) << "\n";
-    }
-    atom = followOnNexts[atom];
-  } while (atom != start);
-  llvm::report_fatal_error("Cycle detected");
-}
-
-/// Exit if there's a cycle in a followon chain reachable from the
-/// given root atom. Uses the tortoise and hare algorithm to detect a
-/// cycle.
-static void checkNoCycleInFollowonChain(const Registry &registry,
-                                        AtomToAtomT &followOnNexts,
-                                        const DefinedAtom *root) {
-  const DefinedAtom *tortoise = root;
-  const DefinedAtom *hare = followOnNexts[root];
-  while (true) {
-    if (!tortoise || !hare)
-      return;
-    if (tortoise == hare)
-      showCycleDetectedError(registry, followOnNexts, tortoise);
-    tortoise = followOnNexts[tortoise];
-    hare = followOnNexts[followOnNexts[hare]];
-  }
-}
-
-static void checkReachabilityFromRoot(AtomToAtomT &followOnRoots,
-                                      const DefinedAtom *atom) {
-  if (!atom) return;
-  auto i = followOnRoots.find(atom);
-  if (i == followOnRoots.end()) {
-    llvm_unreachable(((Twine("Atom <") + atomToDebugString(atom) +
-                       "> has no follow-on root!"))
-                         .str()
-                         .c_str());
-  }
-  const DefinedAtom *ap = i->second;
-  while (true) {
-    const DefinedAtom *next = followOnRoots[ap];
-    if (!next) {
-      llvm_unreachable((Twine("Atom <" + atomToDebugString(atom) +
-                              "> is not reachable from its root!"))
-                           .str()
-                           .c_str());
-    }
-    if (next == ap)
-      return;
-    ap = next;
-  }
-}
-
-static void printDefinedAtoms(const File::AtomRange<DefinedAtom> &atomRange) {
-  for (const DefinedAtom *atom : atomRange) {
-    llvm::dbgs() << "  file=" << atom->file().path()
-                 << ", name=" << atom->name()
-                 << ", size=" << atom->size()
-                 << ", type=" << atom->contentType()
-                 << ", ordinal=" << atom->ordinal()
-                 << "\n";
-  }
-}
-
-/// Verify that the followon chain is sane. Should not be called in
-/// release binary.
-void LayoutPass::checkFollowonChain(const File::AtomRange<DefinedAtom> &range) {
-  ScopedTask task(getDefaultDomain(), "LayoutPass::checkFollowonChain");
-
-  // Verify that there's no cycle in follow-on chain.
-  std::set<const DefinedAtom *> roots;
-  for (const auto &ai : _followOnRoots)
-    roots.insert(ai.second);
-  for (const DefinedAtom *root : roots)
-    checkNoCycleInFollowonChain(_registry, _followOnNexts, root);
-
-  // Verify that all the atoms in followOnNexts have references to
-  // their roots.
-  for (const auto &ai : _followOnNexts) {
-    checkReachabilityFromRoot(_followOnRoots, ai.first);
-    checkReachabilityFromRoot(_followOnRoots, ai.second);
-  }
-}
-#endif // #ifndef NDEBUG
-
-/// The function compares atoms by sorting atoms in the following order
-/// a) Sorts atoms by their ordinal overrides (layout-after/ingroup)
-/// b) Sorts atoms by their permissions
-/// c) Sorts atoms by their content
-/// d) Sorts atoms by custom sorter
-/// e) Sorts atoms on how they appear using File Ordinality
-/// f) Sorts atoms on how they appear within the File
-static bool compareAtomsSub(const LayoutPass::SortKey &lc,
-                            const LayoutPass::SortKey &rc,
-                            LayoutPass::SortOverride customSorter,
-                            std::string &reason) {
-  const DefinedAtom *left = lc._atom.get();
-  const DefinedAtom *right = rc._atom.get();
-  if (left == right) {
-    reason = "same";
-    return false;
-  }
-
-  // Find the root of the chain if it is a part of a follow-on chain.
-  const DefinedAtom *leftRoot = lc._root;
-  const DefinedAtom *rightRoot = rc._root;
-
-  // Sort atoms by their ordinal overrides only if they fall in the same
-  // chain.
-  if (leftRoot == rightRoot) {
-    LLVM_DEBUG(reason = formatReason("override", lc._override, rc._override));
-    return lc._override < rc._override;
-  }
-
-  // Sort same permissions together.
-  DefinedAtom::ContentPermissions leftPerms = leftRoot->permissions();
-  DefinedAtom::ContentPermissions rightPerms = rightRoot->permissions();
-
-  if (leftPerms != rightPerms) {
-    LLVM_DEBUG(
-        reason = formatReason("contentPerms", (int)leftPerms, (int)rightPerms));
-    return leftPerms < rightPerms;
-  }
-
-  // Sort same content types together.
-  DefinedAtom::ContentType leftType = leftRoot->contentType();
-  DefinedAtom::ContentType rightType = rightRoot->contentType();
-
-  if (leftType != rightType) {
-    LLVM_DEBUG(reason =
-                   formatReason("contentType", (int)leftType, (int)rightType));
-    return leftType < rightType;
-  }
-
-  // Use custom sorter if supplied.
-  if (customSorter) {
-    bool leftBeforeRight;
-    if (customSorter(leftRoot, rightRoot, leftBeforeRight))
-      return leftBeforeRight;
-  }
-
-  // Sort by .o order.
-  const File *leftFile = &leftRoot->file();
-  const File *rightFile = &rightRoot->file();
-
-  if (leftFile != rightFile) {
-    LLVM_DEBUG(reason = formatReason(".o order", (int)leftFile->ordinal(),
-                                     (int)rightFile->ordinal()));
-    return leftFile->ordinal() < rightFile->ordinal();
-  }
-
-  // Sort by atom order with .o file.
-  uint64_t leftOrdinal = leftRoot->ordinal();
-  uint64_t rightOrdinal = rightRoot->ordinal();
-
-  if (leftOrdinal != rightOrdinal) {
-    LLVM_DEBUG(reason = formatReason("ordinal", (int)leftRoot->ordinal(),
-                                     (int)rightRoot->ordinal()));
-    return leftOrdinal < rightOrdinal;
-  }
-
-  llvm::errs() << "Unordered: <" << left->name() << "> <" << right->name()
-               << ">\n";
-  llvm_unreachable("Atoms with Same Ordinal!");
-}
-
-static bool compareAtoms(const LayoutPass::SortKey &lc,
-                         const LayoutPass::SortKey &rc,
-                         LayoutPass::SortOverride customSorter) {
-  std::string reason;
-  bool result = compareAtomsSub(lc, rc, customSorter, reason);
-  LLVM_DEBUG({
-    StringRef comp = result ? "<" : ">=";
-    llvm::dbgs() << "Layout: '" << lc._atom.get()->name()
-                 << "' " << comp << " '"
-                 << rc._atom.get()->name() << "' (" << reason << ")\n";
-  });
-  return result;
-}
-
-LayoutPass::LayoutPass(const Registry &registry, SortOverride sorter)
-    : _registry(registry), _customSorter(std::move(sorter)) {}
-
-// Returns the atom immediately followed by the given atom in the followon
-// chain.
-const DefinedAtom *LayoutPass::findAtomFollowedBy(
-    const DefinedAtom *targetAtom) {
-  // Start from the beginning of the chain and follow the chain until
-  // we find the targetChain.
-  const DefinedAtom *atom = _followOnRoots[targetAtom];
-  while (true) {
-    const DefinedAtom *prevAtom = atom;
-    AtomToAtomT::iterator targetFollowOnAtomsIter = _followOnNexts.find(atom);
-    // The target atom must be in the chain of its root.
-    assert(targetFollowOnAtomsIter != _followOnNexts.end());
-    atom = targetFollowOnAtomsIter->second;
-    if (atom == targetAtom)
-      return prevAtom;
-  }
-}
-
-// Check if all the atoms followed by the given target atom are of size zero.
-// When this method is called, an atom being added is not of size zero and
-// will be added to the head of the followon chain. All the atoms between the
-// atom and the targetAtom (specified by layout-after) need to be of size zero
-// in this case. Otherwise the desired layout is impossible.
-bool LayoutPass::checkAllPrevAtomsZeroSize(const DefinedAtom *targetAtom) {
-  const DefinedAtom *atom = _followOnRoots[targetAtom];
-  while (true) {
-    if (atom == targetAtom)
-      return true;
-    if (atom->size() != 0)
-      // TODO: print warning that an impossible layout is being desired by the
-      // user.
-      return false;
-    AtomToAtomT::iterator targetFollowOnAtomsIter = _followOnNexts.find(atom);
-    // The target atom must be in the chain of its root.
-    assert(targetFollowOnAtomsIter != _followOnNexts.end());
-    atom = targetFollowOnAtomsIter->second;
-  }
-}
-
-// Set the root of all atoms in targetAtom's chain to the given root.
-void LayoutPass::setChainRoot(const DefinedAtom *targetAtom,
-                              const DefinedAtom *root) {
-  // Walk through the followon chain and override each node's root.
-  while (true) {
-    _followOnRoots[targetAtom] = root;
-    AtomToAtomT::iterator targetFollowOnAtomsIter =
-        _followOnNexts.find(targetAtom);
-    if (targetFollowOnAtomsIter == _followOnNexts.end())
-      return;
-    targetAtom = targetFollowOnAtomsIter->second;
-  }
-}
-
-/// This pass builds the followon tables described by two DenseMaps
-/// followOnRoots and followonNexts.
-/// The followOnRoots map contains a mapping of a DefinedAtom to its root
-/// The followOnNexts map contains a mapping of what DefinedAtom follows the
-/// current Atom
-/// The algorithm follows a very simple approach
-/// a) If the atom is first seen, then make that as the root atom
-/// b) The targetAtom which this Atom contains, has the root thats set to the
-///    root of the current atom
-/// c) If the targetAtom is part of a different tree and the root of the
-///    targetAtom is itself, Chain all the atoms that are contained in the tree
-///    to the current Tree
-/// d) If the targetAtom is part of a different chain and the root of the
-///    targetAtom until the targetAtom has all atoms of size 0, then chain the
-///    targetAtoms and its tree to the current chain
-void LayoutPass::buildFollowOnTable(const File::AtomRange<DefinedAtom> &range) {
-  ScopedTask task(getDefaultDomain(), "LayoutPass::buildFollowOnTable");
-  // Set the initial size of the followon and the followonNext hash to the
-  // number of atoms that we have.
-  _followOnRoots.reserve(range.size());
-  _followOnNexts.reserve(range.size());
-  for (const DefinedAtom *ai : range) {
-    for (const Reference *r : *ai) {
-      if (r->kindNamespace() != lld::Reference::KindNamespace::all ||
-          r->kindValue() != lld::Reference::kindLayoutAfter)
-        continue;
-      const DefinedAtom *targetAtom = dyn_cast<DefinedAtom>(r->target());
-      _followOnNexts[ai] = targetAtom;
-
-      // If we find a followon for the first time, let's make that atom as the
-      // root atom.
-      if (_followOnRoots.count(ai) == 0)
-        _followOnRoots[ai] = ai;
-
-      auto iter = _followOnRoots.find(targetAtom);
-      if (iter == _followOnRoots.end()) {
-        // If the targetAtom is not a root of any chain, let's make the root of
-        // the targetAtom to the root of the current chain.
-
-        // The expression m[i] = m[j] where m is a DenseMap and i != j is not
-        // safe. m[j] returns a reference, which would be invalidated when a
-        // rehashing occurs. If rehashing occurs to make room for m[i], m[j]
-        // becomes invalid, and that invalid reference would be used as the RHS
-        // value of the expression.
-        // Copy the value to workaround.
-        const DefinedAtom *tmp = _followOnRoots[ai];
-        _followOnRoots[targetAtom] = tmp;
-        continue;
-      }
-      if (iter->second == targetAtom) {
-        // If the targetAtom is the root of a chain, the chain becomes part of
-        // the current chain. Rewrite the subchain's root to the current
-        // chain's root.
-        setChainRoot(targetAtom, _followOnRoots[ai]);
-        continue;
-      }
-      // The targetAtom is already a part of a chain. If the current atom is
-      // of size zero, we can insert it in the middle of the chain just
-      // before the target atom, while not breaking other atom's followon
-      // relationships. If it's not, we can only insert the current atom at
-      // the beginning of the chain. All the atoms followed by the target
-      // atom must be of size zero in that case to satisfy the followon
-      // relationships.
-      size_t currentAtomSize = ai->size();
-      if (currentAtomSize == 0) {
-        const DefinedAtom *targetPrevAtom = findAtomFollowedBy(targetAtom);
-        _followOnNexts[targetPrevAtom] = ai;
-        const DefinedAtom *tmp = _followOnRoots[targetPrevAtom];
-        _followOnRoots[ai] = tmp;
-        continue;
-      }
-      if (!checkAllPrevAtomsZeroSize(targetAtom))
-        break;
-      _followOnNexts[ai] = _followOnRoots[targetAtom];
-      setChainRoot(_followOnRoots[targetAtom], _followOnRoots[ai]);
-    }
-  }
-}
-
-/// Build an ordinal override map by traversing the followon chain, and
-/// assigning ordinals to each atom, if the atoms have their ordinals
-/// already assigned skip the atom and move to the next. This is the
-/// main map thats used to sort the atoms while comparing two atoms together
-void
-LayoutPass::buildOrdinalOverrideMap(const File::AtomRange<DefinedAtom> &range) {
-  ScopedTask task(getDefaultDomain(), "LayoutPass::buildOrdinalOverrideMap");
-  uint64_t index = 0;
-  for (const DefinedAtom *ai : range) {
-    const DefinedAtom *atom = ai;
-    if (_ordinalOverrideMap.find(atom) != _ordinalOverrideMap.end())
-      continue;
-    AtomToAtomT::iterator start = _followOnRoots.find(atom);
-    if (start == _followOnRoots.end())
-      continue;
-    for (const DefinedAtom *nextAtom = start->second; nextAtom;
-         nextAtom = _followOnNexts[nextAtom]) {
-      AtomToOrdinalT::iterator pos = _ordinalOverrideMap.find(nextAtom);
-      if (pos == _ordinalOverrideMap.end())
-        _ordinalOverrideMap[nextAtom] = index++;
-    }
-  }
-}
-
-std::vector<LayoutPass::SortKey>
-LayoutPass::decorate(File::AtomRange<DefinedAtom> &atomRange) const {
-  std::vector<SortKey> ret;
-  for (OwningAtomPtr<DefinedAtom> &atom : atomRange.owning_ptrs()) {
-    auto ri = _followOnRoots.find(atom.get());
-    auto oi = _ordinalOverrideMap.find(atom.get());
-    const auto *root = (ri == _followOnRoots.end()) ? atom.get() : ri->second;
-    uint64_t override = (oi == _ordinalOverrideMap.end()) ? 0 : oi->second;
-    ret.push_back(SortKey(std::move(atom), root, override));
-  }
-  return ret;
-}
-
-void LayoutPass::undecorate(File::AtomRange<DefinedAtom> &atomRange,
-                            std::vector<SortKey> &keys) const {
-  size_t i = 0;
-  for (SortKey &k : keys)
-    atomRange[i++] = std::move(k._atom);
-}
-
-/// Perform the actual pass
-llvm::Error LayoutPass::perform(SimpleFile &mergedFile) {
-  LLVM_DEBUG(llvm::dbgs() << "******** Laying out atoms:\n");
-  // sort the atoms
-  ScopedTask task(getDefaultDomain(), "LayoutPass");
-  File::AtomRange<DefinedAtom> atomRange = mergedFile.defined();
-
-  // Build follow on tables
-  buildFollowOnTable(atomRange);
-
-  // Check the structure of followon graph if running in debug mode.
-  LLVM_DEBUG(checkFollowonChain(atomRange));
-
-  // Build override maps
-  buildOrdinalOverrideMap(atomRange);
-
-  LLVM_DEBUG({
-    llvm::dbgs() << "unsorted atoms:\n";
-    printDefinedAtoms(atomRange);
-  });
-
-  std::vector<LayoutPass::SortKey> vec = decorate(atomRange);
-  llvm::parallelSort(
-      vec,
-      [&](const LayoutPass::SortKey &l, const LayoutPass::SortKey &r) -> bool {
-        return compareAtoms(l, r, _customSorter);
-      });
-  LLVM_DEBUG(checkTransitivity(vec, _customSorter));
-  undecorate(atomRange, vec);
-
-  LLVM_DEBUG({
-    llvm::dbgs() << "sorted atoms:\n";
-    printDefinedAtoms(atomRange);
-  });
-
-  LLVM_DEBUG(llvm::dbgs() << "******** Finished laying out atoms\n");
-  return llvm::Error::success();
-}
-
-void addLayoutPass(PassManager &pm, const MachOLinkingContext &ctx) {
-  pm.add(std::make_unique<LayoutPass>(
-      ctx.registry(), [&](const DefinedAtom * left, const DefinedAtom * right,
-                          bool & leftBeforeRight) ->bool {
-    return ctx.customAtomOrderer(left, right, leftBeforeRight);
-  }));
-}
-
-} // namespace mach_o
-} // namespace lld
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/LayoutPass.h b/gnu/llvm/lld/lib/ReaderWriter/MachO/LayoutPass.h
deleted file mode 100644 (file)
index 904e16b..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-//===------ lib/ReaderWriter/MachO/LayoutPass.h - Handles Layout of atoms -===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_LAYOUT_PASS_H
-#define LLD_READER_WRITER_MACHO_LAYOUT_PASS_H
-
-#include "lld/Core/File.h"
-#include "lld/Core/Pass.h"
-#include "lld/Core/Reader.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/DenseMap.h"
-#include <map>
-#include <string>
-#include <vector>
-
-namespace lld {
-class DefinedAtom;
-class SimpleFile;
-
-namespace mach_o {
-
-/// This linker pass does the layout of the atoms. The pass is done after the
-/// order their .o files were found on the command line, then by order of the
-/// atoms (address) in the .o file.  But some atoms have a preferred location
-/// in their section (such as pinned to the start or end of the section), so
-/// the sort must take that into account too.
-class LayoutPass : public Pass {
-public:
-  struct SortKey {
-    SortKey(OwningAtomPtr<DefinedAtom> &&atom,
-            const DefinedAtom *root, uint64_t override)
-    : _atom(std::move(atom)), _root(root), _override(override) {}
-    OwningAtomPtr<DefinedAtom> _atom;
-    const DefinedAtom *_root;
-    uint64_t _override;
-
-    // Note, these are only here to appease MSVC bots which didn't like
-    // the same methods being implemented/deleted in OwningAtomPtr.
-    SortKey(SortKey &&key) : _atom(std::move(key._atom)), _root(key._root),
-                             _override(key._override) {
-      key._root = nullptr;
-    }
-
-    SortKey &operator=(SortKey &&key) {
-      _atom = std::move(key._atom);
-      _root = key._root;
-      key._root = nullptr;
-      _override = key._override;
-      return *this;
-    }
-
-  private:
-    SortKey(const SortKey &) = delete;
-    void operator=(const SortKey&) = delete;
-  };
-
-  typedef std::function<bool (const DefinedAtom *left, const DefinedAtom *right,
-                              bool &leftBeforeRight)> SortOverride;
-
-  LayoutPass(const Registry &registry, SortOverride sorter);
-
-  /// Sorts atoms in mergedFile by content type then by command line order.
-  llvm::Error perform(SimpleFile &mergedFile) override;
-
-  ~LayoutPass() override = default;
-
-private:
-  // Build the followOn atoms chain as specified by the kindLayoutAfter
-  // reference type
-  void buildFollowOnTable(const File::AtomRange<DefinedAtom> &range);
-
-  // Build a map of Atoms to ordinals for sorting the atoms
-  void buildOrdinalOverrideMap(const File::AtomRange<DefinedAtom> &range);
-
-  const Registry &_registry;
-  SortOverride _customSorter;
-
-  typedef llvm::DenseMap<const DefinedAtom *, const DefinedAtom *> AtomToAtomT;
-  typedef llvm::DenseMap<const DefinedAtom *, uint64_t> AtomToOrdinalT;
-
-  // A map to be used to sort atoms. It represents the order of atoms in the
-  // result; if Atom X is mapped to atom Y in this map, X will be located
-  // immediately before Y in the output file. Y might be mapped to another
-  // atom, constructing a follow-on chain. An atom cannot be mapped to more
-  // than one atom unless all but one atom are of size zero.
-  AtomToAtomT _followOnNexts;
-
-  // A map to be used to sort atoms. It's a map from an atom to its root of
-  // follow-on chain. A root atom is mapped to itself. If an atom is not in
-  // _followOnNexts, the atom is not in this map, and vice versa.
-  AtomToAtomT _followOnRoots;
-
-  AtomToOrdinalT _ordinalOverrideMap;
-
-  // Helper methods for buildFollowOnTable().
-  const DefinedAtom *findAtomFollowedBy(const DefinedAtom *targetAtom);
-  bool checkAllPrevAtomsZeroSize(const DefinedAtom *targetAtom);
-
-  void setChainRoot(const DefinedAtom *targetAtom, const DefinedAtom *root);
-
-  std::vector<SortKey> decorate(File::AtomRange<DefinedAtom> &atomRange) const;
-
-  void undecorate(File::AtomRange<DefinedAtom> &atomRange,
-                  std::vector<SortKey> &keys) const;
-
-  // Check if the follow-on graph is a correct structure. For debugging only.
-  void checkFollowonChain(const File::AtomRange<DefinedAtom> &range);
-};
-
-} // namespace mach_o
-} // namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_LAYOUT_PASS_H
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp b/gnu/llvm/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
deleted file mode 100644 (file)
index acd919e..0000000
+++ /dev/null
@@ -1,1104 +0,0 @@
-//===- lib/ReaderWriter/MachO/MachOLinkingContext.cpp ---------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Common/ErrorHandler.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "ArchHandler.h"
-#include "File.h"
-#include "FlatNamespaceFile.h"
-#include "MachONormalizedFile.h"
-#include "MachOPasses.h"
-#include "SectCreateFile.h"
-#include "lld/Common/Driver.h"
-#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/PassManager.h"
-#include "lld/Core/Reader.h"
-#include "lld/Core/Writer.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Demangle/Demangle.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/Path.h"
-#include <algorithm>
-
-using lld::mach_o::ArchHandler;
-using lld::mach_o::MachOFile;
-using lld::mach_o::MachODylibFile;
-using namespace llvm::MachO;
-
-namespace lld {
-
-bool MachOLinkingContext::parsePackedVersion(StringRef str, uint32_t &result) {
-  result = 0;
-
-  if (str.empty())
-    return false;
-
-  SmallVector<StringRef, 3> parts;
-  llvm::SplitString(str, parts, ".");
-
-  unsigned long long num;
-  if (llvm::getAsUnsignedInteger(parts[0], 10, num))
-    return true;
-  if (num > 65535)
-    return true;
-  result = num << 16;
-
-  if (parts.size() > 1) {
-    if (llvm::getAsUnsignedInteger(parts[1], 10, num))
-      return true;
-    if (num > 255)
-      return true;
-    result |= (num << 8);
-  }
-
-  if (parts.size() > 2) {
-    if (llvm::getAsUnsignedInteger(parts[2], 10, num))
-      return true;
-    if (num > 255)
-      return true;
-    result |= num;
-  }
-
-  return false;
-}
-
-bool MachOLinkingContext::parsePackedVersion(StringRef str, uint64_t &result) {
-  result = 0;
-
-  if (str.empty())
-    return false;
-
-  SmallVector<StringRef, 5> parts;
-  llvm::SplitString(str, parts, ".");
-
-  unsigned long long num;
-  if (llvm::getAsUnsignedInteger(parts[0], 10, num))
-    return true;
-  if (num > 0xFFFFFF)
-    return true;
-  result = num << 40;
-
-  unsigned Shift = 30;
-  for (StringRef str : llvm::makeArrayRef(parts).slice(1)) {
-    if (llvm::getAsUnsignedInteger(str, 10, num))
-      return true;
-    if (num > 0x3FF)
-      return true;
-    result |= (num << Shift);
-    Shift -= 10;
-  }
-
-  return false;
-}
-
-MachOLinkingContext::ArchInfo MachOLinkingContext::_s_archInfos[] = {
-  { "x86_64", arch_x86_64, true,  CPU_TYPE_X86_64,  CPU_SUBTYPE_X86_64_ALL },
-  { "i386",   arch_x86,    true,  CPU_TYPE_I386,    CPU_SUBTYPE_X86_ALL },
-  { "ppc",    arch_ppc,    false, CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL },
-  { "armv6",  arch_armv6,  true,  CPU_TYPE_ARM,     CPU_SUBTYPE_ARM_V6 },
-  { "armv7",  arch_armv7,  true,  CPU_TYPE_ARM,     CPU_SUBTYPE_ARM_V7 },
-  { "armv7s", arch_armv7s, true,  CPU_TYPE_ARM,     CPU_SUBTYPE_ARM_V7S },
-  { "arm64",  arch_arm64,  true,  CPU_TYPE_ARM64,   CPU_SUBTYPE_ARM64_ALL },
-  { "",       arch_unknown,false, 0,                0 }
-};
-
-MachOLinkingContext::Arch
-MachOLinkingContext::archFromCpuType(uint32_t cputype, uint32_t cpusubtype) {
-  for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
-    if ((info->cputype == cputype) && (info->cpusubtype == cpusubtype))
-      return info->arch;
-  }
-  return arch_unknown;
-}
-
-MachOLinkingContext::Arch
-MachOLinkingContext::archFromName(StringRef archName) {
-  for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
-    if (info->archName.equals(archName))
-      return info->arch;
-  }
-  return arch_unknown;
-}
-
-StringRef MachOLinkingContext::nameFromArch(Arch arch) {
-  for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
-    if (info->arch == arch)
-      return info->archName;
-  }
-  return "<unknown>";
-}
-
-uint32_t MachOLinkingContext::cpuTypeFromArch(Arch arch) {
-  assert(arch != arch_unknown);
-  for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
-    if (info->arch == arch)
-      return info->cputype;
-  }
-  llvm_unreachable("Unknown arch type");
-}
-
-uint32_t MachOLinkingContext::cpuSubtypeFromArch(Arch arch) {
-  assert(arch != arch_unknown);
-  for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
-    if (info->arch == arch)
-      return info->cpusubtype;
-  }
-  llvm_unreachable("Unknown arch type");
-}
-
-bool MachOLinkingContext::isThinObjectFile(StringRef path, Arch &arch) {
-  return mach_o::normalized::isThinObjectFile(path, arch);
-}
-
-bool MachOLinkingContext::sliceFromFatFile(MemoryBufferRef mb, uint32_t &offset,
-                                           uint32_t &size) {
-  return mach_o::normalized::sliceFromFatFile(mb, _arch, offset, size);
-}
-
-MachOLinkingContext::MachOLinkingContext() {}
-
-MachOLinkingContext::~MachOLinkingContext() {
-  // Atoms are allocated on BumpPtrAllocator's on File's.
-  // As we transfer atoms from one file to another, we need to clear all of the
-  // atoms before we remove any of the BumpPtrAllocator's.
-  auto &nodes = getNodes();
-  for (unsigned i = 0, e = nodes.size(); i != e; ++i) {
-    FileNode *node = dyn_cast<FileNode>(nodes[i].get());
-    if (!node)
-      continue;
-    File *file = node->getFile();
-    file->clearAtoms();
-  }
-}
-
-void MachOLinkingContext::configure(HeaderFileType type, Arch arch, OS os,
-                                    uint32_t minOSVersion,
-                                    bool exportDynamicSymbols) {
-  _outputMachOType = type;
-  _arch = arch;
-  _os = os;
-  _osMinVersion = minOSVersion;
-
-  // If min OS not specified on command line, use reasonable defaults.
-  // Note that we only do sensible defaults when emitting something other than
-  // object and preload.
-  if (_outputMachOType != llvm::MachO::MH_OBJECT &&
-      _outputMachOType != llvm::MachO::MH_PRELOAD) {
-    if (minOSVersion == 0) {
-      switch (_arch) {
-      case arch_x86_64:
-      case arch_x86:
-        parsePackedVersion("10.8", _osMinVersion);
-        _os = MachOLinkingContext::OS::macOSX;
-        break;
-      case arch_armv6:
-      case arch_armv7:
-      case arch_armv7s:
-      case arch_arm64:
-        parsePackedVersion("7.0", _osMinVersion);
-        _os = MachOLinkingContext::OS::iOS;
-        break;
-      default:
-        break;
-      }
-    }
-  }
-
-  switch (_outputMachOType) {
-  case llvm::MachO::MH_EXECUTE:
-    // If targeting newer OS, use _main
-    if (minOS("10.8", "6.0")) {
-      _entrySymbolName = "_main";
-    } else {
-      // If targeting older OS, use start (in crt1.o)
-      _entrySymbolName = "start";
-    }
-
-    // __PAGEZERO defaults to 4GB on 64-bit (except for PP64 which lld does not
-    // support) and 4KB on 32-bit.
-    if (is64Bit(_arch)) {
-      _pageZeroSize = 0x100000000;
-    } else {
-      _pageZeroSize = 0x1000;
-    }
-
-    // Initial base address is __PAGEZERO size.
-    _baseAddress = _pageZeroSize;
-
-    // Make PIE by default when targetting newer OSs.
-    switch (os) {
-      case OS::macOSX:
-        if (minOSVersion >= 0x000A0700) // MacOSX 10.7
-          _pie = true;
-        break;
-      case OS::iOS:
-        if (minOSVersion >= 0x00040300) // iOS 4.3
-          _pie = true;
-       break;
-       case OS::iOS_simulator:
-        _pie = true;
-       break;
-       case OS::unknown:
-       break;
-    }
-    setGlobalsAreDeadStripRoots(exportDynamicSymbols);
-    break;
-  case llvm::MachO::MH_DYLIB:
-    setGlobalsAreDeadStripRoots(exportDynamicSymbols);
-    break;
-  case llvm::MachO::MH_BUNDLE:
-    break;
-  case llvm::MachO::MH_OBJECT:
-    _printRemainingUndefines = false;
-    _allowRemainingUndefines = true;
-    break;
-  default:
-    break;
-  }
-
-  // Set default segment page sizes based on arch.
-  if (arch == arch_arm64)
-    _pageSize = 4*4096;
-}
-
-uint32_t MachOLinkingContext::getCPUType() const {
-  return cpuTypeFromArch(_arch);
-}
-
-uint32_t MachOLinkingContext::getCPUSubType() const {
-  return cpuSubtypeFromArch(_arch);
-}
-
-bool MachOLinkingContext::is64Bit(Arch arch) {
-  for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
-    if (info->arch == arch) {
-      return (info->cputype & CPU_ARCH_ABI64);
-    }
-  }
-  // unknown archs are not 64-bit.
-  return false;
-}
-
-bool MachOLinkingContext::isHostEndian(Arch arch) {
-  assert(arch != arch_unknown);
-  for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
-    if (info->arch == arch) {
-      return (info->littleEndian == llvm::sys::IsLittleEndianHost);
-    }
-  }
-  llvm_unreachable("Unknown arch type");
-}
-
-bool MachOLinkingContext::isBigEndian(Arch arch) {
-  assert(arch != arch_unknown);
-  for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
-    if (info->arch == arch) {
-      return ! info->littleEndian;
-    }
-  }
-  llvm_unreachable("Unknown arch type");
-}
-
-bool MachOLinkingContext::is64Bit() const {
-  return is64Bit(_arch);
-}
-
-bool MachOLinkingContext::outputTypeHasEntry() const {
-  switch (_outputMachOType) {
-  case MH_EXECUTE:
-  case MH_DYLINKER:
-  case MH_PRELOAD:
-    return true;
-  default:
-    return false;
-  }
-}
-
-bool MachOLinkingContext::needsStubsPass() const {
-  switch (_outputMachOType) {
-  case MH_EXECUTE:
-    return !_outputMachOTypeStatic;
-  case MH_DYLIB:
-  case MH_BUNDLE:
-    return true;
-  default:
-    return false;
-  }
-}
-
-bool MachOLinkingContext::needsGOTPass() const {
-  // GOT pass not used in -r mode.
-  if (_outputMachOType == MH_OBJECT)
-    return false;
-  // Only some arches use GOT pass.
-  switch (_arch) {
-    case arch_x86_64:
-    case arch_arm64:
-      return true;
-    default:
-      return false;
-  }
-}
-
-bool MachOLinkingContext::needsCompactUnwindPass() const {
-  switch (_outputMachOType) {
-  case MH_EXECUTE:
-  case MH_DYLIB:
-  case MH_BUNDLE:
-    return archHandler().needsCompactUnwind();
-  default:
-    return false;
-  }
-}
-
-bool MachOLinkingContext::needsObjCPass() const {
-  // ObjC pass is only needed if any of the inputs were ObjC.
-  return _objcConstraint != objc_unknown;
-}
-
-bool MachOLinkingContext::needsShimPass() const {
-  // Shim pass only used in final executables.
-  if (_outputMachOType == MH_OBJECT)
-    return false;
-  // Only 32-bit arm arches use Shim pass.
-  switch (_arch) {
-  case arch_armv6:
-  case arch_armv7:
-  case arch_armv7s:
-    return true;
-  default:
-    return false;
-  }
-}
-
-bool MachOLinkingContext::needsTLVPass() const {
-  switch (_outputMachOType) {
-  case MH_BUNDLE:
-  case MH_EXECUTE:
-  case MH_DYLIB:
-    return true;
-  default:
-    return false;
-  }
-}
-
-StringRef MachOLinkingContext::binderSymbolName() const {
-  return archHandler().stubInfo().binderSymbolName;
-}
-
-bool MachOLinkingContext::minOS(StringRef mac, StringRef iOS) const {
-  uint32_t parsedVersion;
-  switch (_os) {
-  case OS::macOSX:
-    if (parsePackedVersion(mac, parsedVersion))
-      return false;
-    return _osMinVersion >= parsedVersion;
-  case OS::iOS:
-  case OS::iOS_simulator:
-    if (parsePackedVersion(iOS, parsedVersion))
-      return false;
-    return _osMinVersion >= parsedVersion;
-  case OS::unknown:
-    // If we don't know the target, then assume that we don't meet the min OS.
-    // This matches the ld64 behaviour
-    return false;
-  }
-  llvm_unreachable("invalid OS enum");
-}
-
-bool MachOLinkingContext::addEntryPointLoadCommand() const {
-  if ((_outputMachOType == MH_EXECUTE) && !_outputMachOTypeStatic) {
-    return minOS("10.8", "6.0");
-  }
-  return false;
-}
-
-bool MachOLinkingContext::addUnixThreadLoadCommand() const {
-  switch (_outputMachOType) {
-  case MH_EXECUTE:
-    if (_outputMachOTypeStatic)
-      return true;
-    else
-      return !minOS("10.8", "6.0");
-    break;
-  case MH_DYLINKER:
-  case MH_PRELOAD:
-    return true;
-  default:
-    return false;
-  }
-}
-
-bool MachOLinkingContext::pathExists(StringRef path) const {
-  if (!_testingFileUsage)
-    return llvm::sys::fs::exists(path.str());
-
-  // Otherwise, we're in test mode: only files explicitly provided on the
-  // command-line exist.
-  std::string key = path.str();
-  std::replace(key.begin(), key.end(), '\\', '/');
-  return _existingPaths.find(key) != _existingPaths.end();
-}
-
-bool MachOLinkingContext::fileExists(StringRef path) const {
-  bool found = pathExists(path);
-  // Log search misses.
-  if (!found)
-    addInputFileNotFound(path);
-
-  // When testing, file is never opened, so logging is done here.
-  if (_testingFileUsage && found)
-    addInputFileDependency(path);
-
-  return found;
-}
-
-void MachOLinkingContext::setSysLibRoots(const StringRefVector &paths) {
-  _syslibRoots = paths;
-}
-
-void MachOLinkingContext::addRpath(StringRef rpath) {
-  _rpaths.push_back(rpath);
-}
-
-void MachOLinkingContext::addModifiedSearchDir(StringRef libPath,
-                                               bool isSystemPath) {
-  bool addedModifiedPath = false;
-
-  // -syslibroot only applies to absolute paths.
-  if (libPath.startswith("/")) {
-    for (auto syslibRoot : _syslibRoots) {
-      SmallString<256> path(syslibRoot);
-      llvm::sys::path::append(path, libPath);
-      if (pathExists(path)) {
-        _searchDirs.push_back(path.str().copy(_allocator));
-        addedModifiedPath = true;
-      }
-    }
-  }
-
-  if (addedModifiedPath)
-    return;
-
-  // Finally, if only one -syslibroot is given, system paths which aren't in it
-  // get suppressed.
-  if (_syslibRoots.size() != 1 || !isSystemPath) {
-    if (pathExists(libPath)) {
-      _searchDirs.push_back(libPath);
-    }
-  }
-}
-
-void MachOLinkingContext::addFrameworkSearchDir(StringRef fwPath,
-                                                bool isSystemPath) {
-  bool pathAdded = false;
-
-  // -syslibroot only used with to absolute framework search paths.
-  if (fwPath.startswith("/")) {
-    for (auto syslibRoot : _syslibRoots) {
-      SmallString<256> path(syslibRoot);
-      llvm::sys::path::append(path, fwPath);
-      if (pathExists(path)) {
-        _frameworkDirs.push_back(path.str().copy(_allocator));
-        pathAdded = true;
-      }
-    }
-  }
-  // If fwPath found in any -syslibroot, then done.
-  if (pathAdded)
-    return;
-
-  // If only one -syslibroot, system paths not in that SDK are suppressed.
-  if (isSystemPath && (_syslibRoots.size() == 1))
-    return;
-
-  // Only use raw fwPath if that directory exists.
-  if (pathExists(fwPath))
-    _frameworkDirs.push_back(fwPath);
-}
-
-llvm::Optional<StringRef>
-MachOLinkingContext::searchDirForLibrary(StringRef path,
-                                         StringRef libName) const {
-  SmallString<256> fullPath;
-  if (libName.endswith(".o")) {
-    // A request ending in .o is special: just search for the file directly.
-    fullPath.assign(path);
-    llvm::sys::path::append(fullPath, libName);
-    if (fileExists(fullPath))
-      return fullPath.str().copy(_allocator);
-    return llvm::None;
-  }
-
-  // Search for stub library
-  fullPath.assign(path);
-  llvm::sys::path::append(fullPath, Twine("lib") + libName + ".tbd");
-  if (fileExists(fullPath))
-    return fullPath.str().copy(_allocator);
-
-  // Search for dynamic library
-  fullPath.assign(path);
-  llvm::sys::path::append(fullPath, Twine("lib") + libName + ".dylib");
-  if (fileExists(fullPath))
-    return fullPath.str().copy(_allocator);
-
-  // If not, try for a static library
-  fullPath.assign(path);
-  llvm::sys::path::append(fullPath, Twine("lib") + libName + ".a");
-  if (fileExists(fullPath))
-    return fullPath.str().copy(_allocator);
-
-  return llvm::None;
-}
-
-llvm::Optional<StringRef>
-MachOLinkingContext::searchLibrary(StringRef libName) const {
-  SmallString<256> path;
-  for (StringRef dir : searchDirs()) {
-    llvm::Optional<StringRef> searchDir = searchDirForLibrary(dir, libName);
-    if (searchDir)
-      return searchDir;
-  }
-
-  return llvm::None;
-}
-
-llvm::Optional<StringRef>
-MachOLinkingContext::findPathForFramework(StringRef fwName) const{
-  SmallString<256> fullPath;
-  for (StringRef dir : frameworkDirs()) {
-    fullPath.assign(dir);
-    llvm::sys::path::append(fullPath, Twine(fwName) + ".framework", fwName);
-    if (fileExists(fullPath))
-      return fullPath.str().copy(_allocator);
-  }
-
-  return llvm::None;
-}
-
-bool MachOLinkingContext::validateImpl() {
-  // TODO: if -arch not specified, look at arch of first .o file.
-
-  if (_currentVersion && _outputMachOType != MH_DYLIB) {
-    error("-current_version can only be used with dylibs");
-    return false;
-  }
-
-  if (_compatibilityVersion && _outputMachOType != MH_DYLIB) {
-    error("-compatibility_version can only be used with dylibs");
-    return false;
-  }
-
-  if (_deadStrippableDylib && _outputMachOType != MH_DYLIB) {
-    error("-mark_dead_strippable_dylib can only be used with dylibs");
-    return false;
-  }
-
-  if (!_bundleLoader.empty() && outputMachOType() != MH_BUNDLE) {
-    error("-bundle_loader can only be used with Mach-O bundles");
-    return false;
-  }
-
-  // If -exported_symbols_list used, all exported symbols must be defined.
-  if (_exportMode == ExportMode::exported) {
-    for (const auto &symbol : _exportedSymbols)
-      addInitialUndefinedSymbol(symbol.getKey());
-  }
-
-  // If -dead_strip, set up initial live symbols.
-  if (deadStrip()) {
-    // Entry point is live.
-    if (outputTypeHasEntry())
-      addDeadStripRoot(entrySymbolName());
-    // Lazy binding helper is live.
-    if (needsStubsPass())
-      addDeadStripRoot(binderSymbolName());
-    // If using -exported_symbols_list, make all exported symbols live.
-    if (_exportMode == ExportMode::exported) {
-      setGlobalsAreDeadStripRoots(false);
-      for (const auto &symbol : _exportedSymbols)
-        addDeadStripRoot(symbol.getKey());
-    }
-  }
-
-  addOutputFileDependency(outputPath());
-
-  return true;
-}
-
-void MachOLinkingContext::addPasses(PassManager &pm) {
-  // objc pass should be before layout pass.  Otherwise test cases may contain
-  // no atoms which confuses the layout pass.
-  if (needsObjCPass())
-    mach_o::addObjCPass(pm, *this);
-  mach_o::addLayoutPass(pm, *this);
-  if (needsStubsPass())
-    mach_o::addStubsPass(pm, *this);
-  if (needsCompactUnwindPass())
-    mach_o::addCompactUnwindPass(pm, *this);
-  if (needsGOTPass())
-    mach_o::addGOTPass(pm, *this);
-  if (needsTLVPass())
-    mach_o::addTLVPass(pm, *this);
-  if (needsShimPass())
-    mach_o::addShimPass(pm, *this); // Shim pass must run after stubs pass.
-}
-
-Writer &MachOLinkingContext::writer() const {
-  if (!_writer)
-    _writer = createWriterMachO(*this);
-  return *_writer;
-}
-
-ErrorOr<std::unique_ptr<MemoryBuffer>>
-MachOLinkingContext::getMemoryBuffer(StringRef path) {
-  addInputFileDependency(path);
-
-  ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr =
-    MemoryBuffer::getFileOrSTDIN(path);
-  if (std::error_code ec = mbOrErr.getError())
-    return ec;
-  std::unique_ptr<MemoryBuffer> mb = std::move(mbOrErr.get());
-
-  // If buffer contains a fat file, find required arch in fat buffer
-  // and switch buffer to point to just that required slice.
-  uint32_t offset;
-  uint32_t size;
-  if (sliceFromFatFile(mb->getMemBufferRef(), offset, size))
-    return MemoryBuffer::getFileSlice(path, size, offset);
-  return std::move(mb);
-}
-
-MachODylibFile* MachOLinkingContext::loadIndirectDylib(StringRef path) {
-  ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr = getMemoryBuffer(path);
-  if (mbOrErr.getError())
-    return nullptr;
-
-  ErrorOr<std::unique_ptr<File>> fileOrErr =
-      registry().loadFile(std::move(mbOrErr.get()));
-  if (!fileOrErr)
-    return nullptr;
-  std::unique_ptr<File> &file = fileOrErr.get();
-  file->parse();
-  MachODylibFile *result = reinterpret_cast<MachODylibFile *>(file.get());
-  // Node object now owned by _indirectDylibs vector.
-  _indirectDylibs.push_back(std::move(file));
-  return result;
-}
-
-MachODylibFile* MachOLinkingContext::findIndirectDylib(StringRef path) {
-  // See if already loaded.
-  auto pos = _pathToDylibMap.find(path);
-  if (pos != _pathToDylibMap.end())
-    return pos->second;
-
-  // Search -L paths if of the form "libXXX.dylib"
-  std::pair<StringRef, StringRef> split = path.rsplit('/');
-  StringRef leafName = split.second;
-  if (leafName.startswith("lib") && leafName.endswith(".dylib")) {
-    // FIXME: Need to enhance searchLibrary() to only look for .dylib
-    auto libPath = searchLibrary(leafName);
-    if (libPath)
-      return loadIndirectDylib(libPath.getValue());
-  }
-
-  // Try full path with sysroot.
-  for (StringRef sysPath : _syslibRoots) {
-    SmallString<256> fullPath;
-    fullPath.assign(sysPath);
-    llvm::sys::path::append(fullPath, path);
-    if (pathExists(fullPath))
-      return loadIndirectDylib(fullPath);
-  }
-
-  // Try full path.
-  if (pathExists(path)) {
-    return loadIndirectDylib(path);
-  }
-
-  return nullptr;
-}
-
-uint32_t MachOLinkingContext::dylibCurrentVersion(StringRef installName) const {
-  auto pos = _pathToDylibMap.find(installName);
-  if (pos != _pathToDylibMap.end())
-    return pos->second->currentVersion();
-  else
-    return 0x10000; // 1.0
-}
-
-uint32_t MachOLinkingContext::dylibCompatVersion(StringRef installName) const {
-  auto pos = _pathToDylibMap.find(installName);
-  if (pos != _pathToDylibMap.end())
-    return pos->second->compatVersion();
-  else
-    return 0x10000; // 1.0
-}
-
-void MachOLinkingContext::createImplicitFiles(
-                            std::vector<std::unique_ptr<File> > &result) {
-  // Add indirect dylibs by asking each linked dylib to add its indirects.
-  // Iterate until no more dylibs get loaded.
-  size_t dylibCount = 0;
-  while (dylibCount != _allDylibs.size()) {
-    dylibCount = _allDylibs.size();
-    for (MachODylibFile *dylib : _allDylibs) {
-      dylib->loadReExportedDylibs([this] (StringRef path) -> MachODylibFile* {
-                                  return findIndirectDylib(path); });
-    }
-  }
-
-  // Let writer add output type specific extras.
-  writer().createImplicitFiles(result);
-
-  // If undefinedMode is != error, add a FlatNamespaceFile instance. This will
-  // provide a SharedLibraryAtom for symbols that aren't defined elsewhere.
-  if (undefinedMode() != UndefinedMode::error) {
-    result.emplace_back(new mach_o::FlatNamespaceFile(*this));
-    _flatNamespaceFile = result.back().get();
-  }
-}
-
-void MachOLinkingContext::registerDylib(MachODylibFile *dylib,
-                                        bool upward) const {
-  std::lock_guard<std::mutex> lock(_dylibsMutex);
-
-  if (!llvm::count(_allDylibs, dylib))
-    _allDylibs.push_back(dylib);
-  _pathToDylibMap[dylib->installName()] = dylib;
-  // If path is different than install name, register path too.
-  if (!dylib->path().equals(dylib->installName()))
-    _pathToDylibMap[dylib->path()] = dylib;
-  if (upward)
-    _upwardDylibs.insert(dylib);
-}
-
-bool MachOLinkingContext::isUpwardDylib(StringRef installName) const {
-  for (MachODylibFile *dylib : _upwardDylibs) {
-    if (dylib->installName().equals(installName))
-      return true;
-  }
-  return false;
-}
-
-ArchHandler &MachOLinkingContext::archHandler() const {
-  if (!_archHandler)
-    _archHandler = ArchHandler::create(_arch);
-  return *_archHandler;
-}
-
-void MachOLinkingContext::addSectionAlignment(StringRef seg, StringRef sect,
-                                              uint16_t align) {
-  SectionAlign entry = { seg, sect, align };
-  _sectAligns.push_back(entry);
-}
-
-void MachOLinkingContext::addSectCreateSection(
-                                        StringRef seg, StringRef sect,
-                                        std::unique_ptr<MemoryBuffer> content) {
-
-  if (!_sectCreateFile) {
-    auto sectCreateFile = std::make_unique<mach_o::SectCreateFile>();
-    _sectCreateFile = sectCreateFile.get();
-    getNodes().push_back(std::make_unique<FileNode>(std::move(sectCreateFile)));
-  }
-
-  assert(_sectCreateFile && "sectcreate file does not exist.");
-  _sectCreateFile->addSection(seg, sect, std::move(content));
-}
-
-bool MachOLinkingContext::sectionAligned(StringRef seg, StringRef sect,
-                                         uint16_t &align) const {
-  for (const SectionAlign &entry : _sectAligns) {
-    if (seg.equals(entry.segmentName) && sect.equals(entry.sectionName)) {
-      align = entry.align;
-      return true;
-    }
-  }
-  return false;
-}
-
-void MachOLinkingContext::addExportSymbol(StringRef sym) {
-  // Support old crufty export lists with bogus entries.
-  if (sym.endswith(".eh") || sym.startswith(".objc_category_name_")) {
-    llvm::errs() << "warning: ignoring " << sym << " in export list\n";
-    return;
-  }
-  // Only i386 MacOSX uses old ABI, so don't change those.
-  if ((_os != OS::macOSX) || (_arch != arch_x86)) {
-    // ObjC has two different ABIs.  Be nice and allow one export list work for
-    // both ABIs by renaming symbols.
-    if (sym.startswith(".objc_class_name_")) {
-      std::string abi2className("_OBJC_CLASS_$_");
-      abi2className += sym.substr(17);
-      _exportedSymbols.insert(copy(abi2className));
-      std::string abi2metaclassName("_OBJC_METACLASS_$_");
-      abi2metaclassName += sym.substr(17);
-      _exportedSymbols.insert(copy(abi2metaclassName));
-      return;
-    }
-  }
-
-  // FIXME: Support wildcards.
-  _exportedSymbols.insert(sym);
-}
-
-bool MachOLinkingContext::exportSymbolNamed(StringRef sym) const {
-  switch (_exportMode) {
-  case ExportMode::globals:
-    llvm_unreachable("exportSymbolNamed() should not be called in this mode");
-    break;
-  case ExportMode::exported:
-    return _exportedSymbols.count(sym);
-  case ExportMode::unexported:
-    return !_exportedSymbols.count(sym);
-  }
-  llvm_unreachable("_exportMode unknown enum value");
-}
-
-std::string MachOLinkingContext::demangle(StringRef symbolName) const {
-  // Only try to demangle symbols if -demangle on command line
-  if (!demangleSymbols())
-    return std::string(symbolName);
-
-  // Only try to demangle symbols that look like C++ symbols
-  if (!symbolName.startswith("__Z"))
-    return std::string(symbolName);
-
-  SmallString<256> symBuff;
-  StringRef nullTermSym = Twine(symbolName).toNullTerminatedStringRef(symBuff);
-  // Mach-O has extra leading underscore that needs to be removed.
-  const char *cstr = nullTermSym.data() + 1;
-  int status;
-  char *demangled = llvm::itaniumDemangle(cstr, nullptr, nullptr, &status);
-  if (demangled) {
-    std::string result(demangled);
-    // __cxa_demangle() always uses a malloc'ed buffer to return the result.
-    free(demangled);
-    return result;
-  }
-
-  return std::string(symbolName);
-}
-
-static void addDependencyInfoHelper(llvm::raw_fd_ostream *DepInfo,
-                                    char Opcode, StringRef Path) {
-  if (!DepInfo)
-    return;
-
-  *DepInfo << Opcode;
-  *DepInfo << Path;
-  *DepInfo << '\0';
-}
-
-std::error_code MachOLinkingContext::createDependencyFile(StringRef path) {
-  std::error_code ec;
-  _dependencyInfo = std::unique_ptr<llvm::raw_fd_ostream>(
-      new llvm::raw_fd_ostream(path, ec, llvm::sys::fs::OF_None));
-  if (ec) {
-    _dependencyInfo.reset();
-    return ec;
-  }
-
-  addDependencyInfoHelper(_dependencyInfo.get(), 0x00, "lld" /*FIXME*/);
-  return std::error_code();
-}
-
-void MachOLinkingContext::addInputFileDependency(StringRef path) const {
-  addDependencyInfoHelper(_dependencyInfo.get(), 0x10, path);
-}
-
-void MachOLinkingContext::addInputFileNotFound(StringRef path) const {
-  addDependencyInfoHelper(_dependencyInfo.get(), 0x11, path);
-}
-
-void MachOLinkingContext::addOutputFileDependency(StringRef path) const {
-  addDependencyInfoHelper(_dependencyInfo.get(), 0x40, path);
-}
-
-void MachOLinkingContext::appendOrderedSymbol(StringRef symbol,
-                                              StringRef filename) {
-  // To support sorting static functions which may have the same name in
-  // multiple .o files, _orderFiles maps the symbol name to a vector
-  // of OrderFileNode each of which can specify a file prefix.
-  OrderFileNode info;
-  if (!filename.empty())
-    info.fileFilter = copy(filename);
-  info.order = _orderFileEntries++;
-  _orderFiles[symbol].push_back(info);
-}
-
-bool
-MachOLinkingContext::findOrderOrdinal(const std::vector<OrderFileNode> &nodes,
-                                      const DefinedAtom *atom,
-                                      unsigned &ordinal) {
-  const File *objFile = &atom->file();
-  assert(objFile);
-  StringRef objName = objFile->path();
-  std::pair<StringRef, StringRef> dirAndLeaf = objName.rsplit('/');
-  if (!dirAndLeaf.second.empty())
-    objName = dirAndLeaf.second;
-  for (const OrderFileNode &info : nodes) {
-    if (info.fileFilter.empty()) {
-      // Have unprefixed symbol name in order file that matches this atom.
-      ordinal = info.order;
-      return true;
-    }
-    if (info.fileFilter.equals(objName)) {
-      // Have prefixed symbol name in order file that matches atom's path.
-      ordinal = info.order;
-      return true;
-    }
-  }
-  return false;
-}
-
-bool MachOLinkingContext::customAtomOrderer(const DefinedAtom *left,
-                                            const DefinedAtom *right,
-                                            bool &leftBeforeRight) const {
-  // No custom sorting if no order file entries.
-  if (!_orderFileEntries)
-    return false;
-
-  // Order files can only order named atoms.
-  StringRef leftName = left->name();
-  StringRef rightName = right->name();
-  if (leftName.empty() || rightName.empty())
-    return false;
-
-  // If neither is in order file list, no custom sorter.
-  auto leftPos = _orderFiles.find(leftName);
-  auto rightPos = _orderFiles.find(rightName);
-  bool leftIsOrdered = (leftPos != _orderFiles.end());
-  bool rightIsOrdered = (rightPos != _orderFiles.end());
-  if (!leftIsOrdered && !rightIsOrdered)
-    return false;
-
-  // There could be multiple symbols with same name but different file prefixes.
-  unsigned leftOrder;
-  unsigned rightOrder;
-  bool foundLeft =
-      leftIsOrdered && findOrderOrdinal(leftPos->getValue(), left, leftOrder);
-  bool foundRight = rightIsOrdered &&
-                    findOrderOrdinal(rightPos->getValue(), right, rightOrder);
-  if (!foundLeft && !foundRight)
-    return false;
-
-  // If only one is in order file list, ordered one goes first.
-  if (foundLeft != foundRight)
-    leftBeforeRight = foundLeft;
-  else
-    leftBeforeRight = (leftOrder < rightOrder);
-
-  return true;
-}
-
-static bool isLibrary(const std::unique_ptr<Node> &elem) {
-  if (FileNode *node = dyn_cast<FileNode>(const_cast<Node *>(elem.get()))) {
-    File *file = node->getFile();
-    return isa<SharedLibraryFile>(file) || isa<ArchiveLibraryFile>(file);
-  }
-  return false;
-}
-
-// The darwin linker processes input files in two phases.  The first phase
-// links in all object (.o) files in command line order. The second phase
-// links in libraries in command line order.
-// In this function we reorder the input files so that all the object files
-// comes before any library file. We also make a group for the library files
-// so that the Resolver will reiterate over the libraries as long as we find
-// new undefines from libraries.
-void MachOLinkingContext::finalizeInputFiles() {
-  std::vector<std::unique_ptr<Node>> &elements = getNodes();
-  llvm::stable_sort(elements, [](const std::unique_ptr<Node> &a,
-                                 const std::unique_ptr<Node> &b) {
-    return !isLibrary(a) && isLibrary(b);
-  });
-  size_t numLibs = std::count_if(elements.begin(), elements.end(), isLibrary);
-  elements.push_back(std::make_unique<GroupEnd>(numLibs));
-}
-
-llvm::Error MachOLinkingContext::handleLoadedFile(File &file) {
-  auto *machoFile = dyn_cast<MachOFile>(&file);
-  if (!machoFile)
-    return llvm::Error::success();
-
-  // Check that the arch of the context matches that of the file.
-  // Also set the arch of the context if it didn't have one.
-  if (_arch == arch_unknown) {
-    _arch = machoFile->arch();
-  } else if (machoFile->arch() != arch_unknown && machoFile->arch() != _arch) {
-    // Archs are different.
-    return llvm::make_error<GenericError>(file.path() +
-                  Twine(" cannot be linked due to incompatible architecture"));
-  }
-
-  // Check that the OS of the context matches that of the file.
-  // Also set the OS of the context if it didn't have one.
-  if (_os == OS::unknown) {
-    _os = machoFile->OS();
-  } else if (machoFile->OS() != OS::unknown && machoFile->OS() != _os) {
-    // OSes are different.
-    return llvm::make_error<GenericError>(file.path() +
-              Twine(" cannot be linked due to incompatible operating systems"));
-  }
-
-  // Check that if the objc info exists, that it is compatible with the target
-  // OS.
-  switch (machoFile->objcConstraint()) {
-    case objc_unknown:
-      // The file is not compiled with objc, so skip the checks.
-      break;
-    case objc_gc_only:
-    case objc_supports_gc:
-      llvm_unreachable("GC support should already have thrown an error");
-    case objc_retainReleaseForSimulator:
-      // The file is built with simulator objc, so make sure that the context
-      // is also building with simulator support.
-      if (_os != OS::iOS_simulator)
-        return llvm::make_error<GenericError>(file.path() +
-          Twine(" cannot be linked.  It contains ObjC built for the simulator"
-                " while we are linking a non-simulator target"));
-      assert((_objcConstraint == objc_unknown ||
-              _objcConstraint == objc_retainReleaseForSimulator) &&
-             "Must be linking with retain/release for the simulator");
-      _objcConstraint = objc_retainReleaseForSimulator;
-      break;
-    case objc_retainRelease:
-      // The file is built without simulator objc, so make sure that the
-      // context is also building without simulator support.
-      if (_os == OS::iOS_simulator)
-        return llvm::make_error<GenericError>(file.path() +
-          Twine(" cannot be linked.  It contains ObjC built for a non-simulator"
-                " target while we are linking a simulator target"));
-      assert((_objcConstraint == objc_unknown ||
-              _objcConstraint == objc_retainRelease) &&
-             "Must be linking with retain/release for a non-simulator target");
-      _objcConstraint = objc_retainRelease;
-      break;
-  }
-
-  // Check that the swift version of the context matches that of the file.
-  // Also set the swift version of the context if it didn't have one.
-  if (!_swiftVersion) {
-    _swiftVersion = machoFile->swiftVersion();
-  } else if (machoFile->swiftVersion() &&
-             machoFile->swiftVersion() != _swiftVersion) {
-    // Swift versions are different.
-    return llvm::make_error<GenericError>("different swift versions");
-  }
-
-  return llvm::Error::success();
-}
-
-} // end namespace lld
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h b/gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h
deleted file mode 100644 (file)
index 3ef2949..0000000
+++ /dev/null
@@ -1,336 +0,0 @@
-//===- lib/ReaderWriter/MachO/MachONormalizedFile.h -----------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-///
-/// \file These data structures comprise the "normalized" view of
-/// mach-o object files. The normalized view is an in-memory only data structure
-/// which is always in native endianness and pointer size.
-///
-/// The normalized view easily converts to and from YAML using YAML I/O.
-///
-/// The normalized view converts to and from binary mach-o object files using
-/// the writeBinary() and readBinary() functions.
-///
-/// The normalized view converts to and from lld::Atoms using the
-/// normalizedToAtoms() and normalizedFromAtoms().
-///
-/// Overall, the conversion paths available look like:
-///
-///                 +---------------+
-///                 | binary mach-o |
-///                 +---------------+
-///                        ^
-///                        |
-///                        v
-///                  +------------+         +------+
-///                  | normalized |   <->   | yaml |
-///                  +------------+         +------+
-///                        ^
-///                        |
-///                        v
-///                    +-------+
-///                    | Atoms |
-///                    +-------+
-///
-
-#ifndef LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
-#define LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
-
-#include "DebugInfo.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/Error.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/YAMLTraits.h"
-
-using llvm::BumpPtrAllocator;
-using llvm::yaml::Hex64;
-using llvm::yaml::Hex32;
-using llvm::yaml::Hex16;
-using llvm::yaml::Hex8;
-using llvm::yaml::SequenceTraits;
-using llvm::MachO::HeaderFileType;
-using llvm::MachO::BindType;
-using llvm::MachO::RebaseType;
-using llvm::MachO::NListType;
-using llvm::MachO::RelocationInfoType;
-using llvm::MachO::SectionType;
-using llvm::MachO::LoadCommandType;
-using llvm::MachO::ExportSymbolKind;
-using llvm::MachO::DataRegionType;
-
-namespace lld {
-namespace mach_o {
-namespace normalized {
-
-
-/// The real mach-o relocation record is 8-bytes on disk and is
-/// encoded in one of two different bit-field patterns.  This
-/// normalized form has the union of all possible fields.
-struct Relocation {
-  Relocation() : offset(0), scattered(false),
-                 type(llvm::MachO::GENERIC_RELOC_VANILLA),
-                 length(0), pcRel(false), isExtern(false), value(0),
-                 symbol(0) { }
-
-  Hex32               offset;
-  bool                scattered;
-  RelocationInfoType  type;
-  uint8_t             length;
-  bool                pcRel;
-  bool                isExtern;
-  Hex32               value;
-  uint32_t            symbol;
-};
-
-/// A typedef so that YAML I/O can treat this vector as a sequence.
-typedef std::vector<Relocation> Relocations;
-
-/// A typedef so that YAML I/O can process the raw bytes in a section.
-typedef std::vector<Hex8> ContentBytes;
-
-/// A typedef so that YAML I/O can treat indirect symbols as a flow sequence.
-typedef std::vector<uint32_t> IndirectSymbols;
-
-/// A typedef so that YAML I/O can encode/decode section attributes.
-LLVM_YAML_STRONG_TYPEDEF(uint32_t, SectionAttr)
-
-/// A typedef so that YAML I/O can encode/decode section alignment.
-LLVM_YAML_STRONG_TYPEDEF(uint16_t, SectionAlignment)
-
-/// Mach-O has a 32-bit and 64-bit section record.  This normalized form
-/// can support either kind.
-struct Section {
-  Section() : type(llvm::MachO::S_REGULAR),
-              attributes(0), alignment(1), address(0) { }
-
-  StringRef       segmentName;
-  StringRef       sectionName;
-  SectionType     type;
-  SectionAttr     attributes;
-  SectionAlignment        alignment;
-  Hex64           address;
-  ArrayRef<uint8_t> content;
-  Relocations     relocations;
-  IndirectSymbols indirectSymbols;
-};
-
-
-/// A typedef so that YAML I/O can encode/decode the scope bits of an nlist.
-LLVM_YAML_STRONG_TYPEDEF(uint8_t, SymbolScope)
-
-/// A typedef so that YAML I/O can encode/decode the desc bits of an nlist.
-LLVM_YAML_STRONG_TYPEDEF(uint16_t, SymbolDesc)
-
-/// Mach-O has a 32-bit and 64-bit symbol table entry (nlist), and the symbol
-/// type and scope and mixed in the same n_type field.  This normalized form
-/// works for any pointer size and separates out the type and scope.
-struct Symbol {
-  Symbol() : type(llvm::MachO::N_UNDF), scope(0), sect(0), desc(0), value(0) { }
-
-  StringRef     name;
-  NListType     type;
-  SymbolScope   scope;
-  uint8_t       sect;
-  SymbolDesc    desc;
-  Hex64         value;
-};
-
-/// Check whether the given section type indicates a zero-filled section.
-// FIXME: Utility functions of this kind should probably be moved into
-//        llvm/Support.
-inline bool isZeroFillSection(SectionType T) {
-  return (T == llvm::MachO::S_ZEROFILL ||
-          T == llvm::MachO::S_THREAD_LOCAL_ZEROFILL);
-}
-
-/// A typedef so that YAML I/O can (de/en)code the protection bits of a segment.
-LLVM_YAML_STRONG_TYPEDEF(uint32_t, VMProtect)
-
-/// A typedef to hold verions X.Y.X packed into 32-bit xxxx.yy.zz
-LLVM_YAML_STRONG_TYPEDEF(uint32_t, PackedVersion)
-
-/// Segments are only used in normalized final linked images (not in relocatable
-/// object files). They specify how a range of the file is loaded.
-struct Segment {
-  StringRef     name;
-  Hex64         address;
-  Hex64         size;
-  VMProtect     init_access;
-  VMProtect     max_access;
-};
-
-/// Only used in normalized final linked images to specify on which dylibs
-/// it depends.
-struct DependentDylib {
-  StringRef       path;
-  LoadCommandType kind;
-  PackedVersion   compatVersion;
-  PackedVersion   currentVersion;
-};
-
-/// A normalized rebasing entry.  Only used in normalized final linked images.
-struct RebaseLocation {
-  Hex32         segOffset;
-  uint8_t       segIndex;
-  RebaseType    kind;
-};
-
-/// A normalized binding entry.  Only used in normalized final linked images.
-struct BindLocation {
-  Hex32           segOffset;
-  uint8_t         segIndex;
-  BindType        kind;
-  bool            canBeNull;
-  int             ordinal;
-  StringRef       symbolName;
-  Hex64           addend;
-};
-
-/// A typedef so that YAML I/O can encode/decode export flags.
-LLVM_YAML_STRONG_TYPEDEF(uint32_t, ExportFlags)
-
-/// A normalized export entry.  Only used in normalized final linked images.
-struct Export {
-  StringRef         name;
-  Hex64             offset;
-  ExportSymbolKind  kind;
-  ExportFlags       flags;
-  Hex32             otherOffset;
-  StringRef         otherName;
-};
-
-/// A normalized data-in-code entry.
-struct DataInCode {
-  Hex32           offset;
-  Hex16           length;
-  DataRegionType  kind;
-};
-
-/// A typedef so that YAML I/O can encode/decode mach_header.flags.
-LLVM_YAML_STRONG_TYPEDEF(uint32_t, FileFlags)
-
-///
-struct NormalizedFile {
-  MachOLinkingContext::Arch   arch = MachOLinkingContext::arch_unknown;
-  HeaderFileType              fileType = llvm::MachO::MH_OBJECT;
-  FileFlags                   flags = 0;
-  std::vector<Segment>        segments; // Not used in object files.
-  std::vector<Section>        sections;
-
-  // Symbols sorted by kind.
-  std::vector<Symbol>         localSymbols;
-  std::vector<Symbol>         globalSymbols;
-  std::vector<Symbol>         undefinedSymbols;
-  std::vector<Symbol>         stabsSymbols;
-
-  // Maps to load commands with no LINKEDIT content (final linked images only).
-  std::vector<DependentDylib> dependentDylibs;
-  StringRef                   installName;        // dylibs only
-  PackedVersion               compatVersion = 0;  // dylibs only
-  PackedVersion               currentVersion = 0; // dylibs only
-  bool                        hasUUID = false;
-  bool                        hasMinVersionLoadCommand = false;
-  bool                        generateDataInCodeLoadCommand = false;
-  std::vector<StringRef>      rpaths;
-  Hex64                       entryAddress = 0;
-  Hex64                       stackSize = 0;
-  MachOLinkingContext::OS     os = MachOLinkingContext::OS::unknown;
-  Hex64                       sourceVersion = 0;
-  PackedVersion               minOSverson = 0;
-  PackedVersion               sdkVersion = 0;
-  LoadCommandType             minOSVersionKind = (LoadCommandType)0;
-
-  // Maps to load commands with LINKEDIT content (final linked images only).
-  Hex32                       pageSize = 0;
-  std::vector<RebaseLocation> rebasingInfo;
-  std::vector<BindLocation>   bindingInfo;
-  std::vector<BindLocation>   weakBindingInfo;
-  std::vector<BindLocation>   lazyBindingInfo;
-  std::vector<Export>         exportInfo;
-  std::vector<uint8_t>        functionStarts;
-  std::vector<DataInCode>     dataInCode;
-
-  // TODO:
-  // code-signature
-  // split-seg-info
-  // function-starts
-
-  // For any allocations in this struct which need to be owned by this struct.
-  BumpPtrAllocator            ownedAllocations;
-};
-
-/// Tests if a file is a non-fat mach-o object file.
-bool isThinObjectFile(StringRef path, MachOLinkingContext::Arch &arch);
-
-/// If the buffer is a fat file with the request arch, then this function
-/// returns true with 'offset' and 'size' set to location of the arch slice
-/// within the buffer.  Otherwise returns false;
-bool sliceFromFatFile(MemoryBufferRef mb, MachOLinkingContext::Arch arch,
-                      uint32_t &offset, uint32_t &size);
-
-/// Reads a mach-o file and produces an in-memory normalized view.
-llvm::Expected<std::unique_ptr<NormalizedFile>>
-readBinary(std::unique_ptr<MemoryBuffer> &mb,
-           const MachOLinkingContext::Arch arch);
-
-/// Takes in-memory normalized view and writes a mach-o object file.
-llvm::Error writeBinary(const NormalizedFile &file, StringRef path);
-
-size_t headerAndLoadCommandsSize(const NormalizedFile &file,
-                                 bool includeFunctionStarts);
-
-
-/// Parses a yaml encoded mach-o file to produce an in-memory normalized view.
-llvm::Expected<std::unique_ptr<NormalizedFile>>
-readYaml(std::unique_ptr<MemoryBuffer> &mb);
-
-/// Writes a yaml encoded mach-o files given an in-memory normalized view.
-std::error_code writeYaml(const NormalizedFile &file, raw_ostream &out);
-
-llvm::Error
-normalizedObjectToAtoms(MachOFile *file,
-                        const NormalizedFile &normalizedFile,
-                        bool copyRefs);
-
-llvm::Error
-normalizedDylibToAtoms(MachODylibFile *file,
-                       const NormalizedFile &normalizedFile,
-                       bool copyRefs);
-
-/// Takes in-memory normalized dylib or object and parses it into lld::File
-llvm::Expected<std::unique_ptr<lld::File>>
-normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
-                  bool copyRefs);
-
-/// Takes atoms and generates a normalized macho-o view.
-llvm::Expected<std::unique_ptr<NormalizedFile>>
-normalizedFromAtoms(const lld::File &atomFile, const MachOLinkingContext &ctxt);
-
-
-} // namespace normalized
-
-/// Class for interfacing mach-o yaml files into generic yaml parsing
-class MachOYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
-public:
-  MachOYamlIOTaggedDocumentHandler(MachOLinkingContext::Arch arch)
-    : _arch(arch) { }
-  bool handledDocTag(llvm::yaml::IO &io, const lld::File *&file) const override;
-private:
-  const MachOLinkingContext::Arch _arch;
-};
-
-} // namespace mach_o
-} // namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp b/gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
deleted file mode 100644 (file)
index 87601ca..0000000
+++ /dev/null
@@ -1,614 +0,0 @@
-//===- lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp ---------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-///
-/// \file For mach-o object files, this implementation converts from
-/// mach-o on-disk binary format to in-memory normalized mach-o.
-///
-///                 +---------------+
-///                 | binary mach-o |
-///                 +---------------+
-///                        |
-///                        |
-///                        v
-///                  +------------+
-///                  | normalized |
-///                  +------------+
-
-#include "ArchHandler.h"
-#include "MachONormalizedFile.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/Error.h"
-#include "lld/Core/SharedLibraryFile.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/BinaryFormat/Magic.h"
-#include "llvm/Object/MachO.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <functional>
-#include <system_error>
-
-using namespace llvm::MachO;
-using llvm::object::ExportEntry;
-using llvm::file_magic;
-using llvm::object::MachOObjectFile;
-
-namespace lld {
-namespace mach_o {
-namespace normalized {
-
-// Utility to call a lambda expression on each load command.
-static llvm::Error forEachLoadCommand(
-    StringRef lcRange, unsigned lcCount, bool isBig, bool is64,
-    std::function<bool(uint32_t cmd, uint32_t size, const char *lc)> func) {
-  const char* p = lcRange.begin();
-  for (unsigned i=0; i < lcCount; ++i) {
-    const load_command *lc = reinterpret_cast<const load_command*>(p);
-    load_command lcCopy;
-    const load_command *slc = lc;
-    if (isBig != llvm::sys::IsBigEndianHost) {
-      memcpy(&lcCopy, lc, sizeof(load_command));
-      swapStruct(lcCopy);
-      slc = &lcCopy;
-    }
-    if ( (p + slc->cmdsize) > lcRange.end() )
-      return llvm::make_error<GenericError>("Load command exceeds range");
-
-    if (func(slc->cmd, slc->cmdsize, p))
-      return llvm::Error::success();
-
-    p += slc->cmdsize;
-  }
-
-  return llvm::Error::success();
-}
-
-static std::error_code appendRelocations(Relocations &relocs, StringRef buffer,
-                                         bool bigEndian,
-                                         uint32_t reloff, uint32_t nreloc) {
-  if ((reloff + nreloc*8) > buffer.size())
-    return make_error_code(llvm::errc::executable_format_error);
-  const any_relocation_info* relocsArray =
-            reinterpret_cast<const any_relocation_info*>(buffer.begin()+reloff);
-
-  for(uint32_t i=0; i < nreloc; ++i) {
-    relocs.push_back(unpackRelocation(relocsArray[i], bigEndian));
-  }
-  return std::error_code();
-}
-
-static std::error_code
-appendIndirectSymbols(IndirectSymbols &isyms, StringRef buffer, bool isBig,
-                      uint32_t istOffset, uint32_t istCount,
-                      uint32_t startIndex, uint32_t count) {
-  if ((istOffset + istCount*4) > buffer.size())
-    return make_error_code(llvm::errc::executable_format_error);
-  if (startIndex+count  > istCount)
-    return make_error_code(llvm::errc::executable_format_error);
-  const uint8_t *indirectSymbolArray = (const uint8_t *)buffer.data();
-
-  for(uint32_t i=0; i < count; ++i) {
-    isyms.push_back(read32(
-        indirectSymbolArray + (startIndex + i) * sizeof(uint32_t), isBig));
-  }
-  return std::error_code();
-}
-
-
-template <typename T> static T readBigEndian(T t) {
-  if (llvm::sys::IsLittleEndianHost)
-    llvm::sys::swapByteOrder(t);
-  return t;
-}
-
-
-static bool isMachOHeader(const mach_header *mh, bool &is64, bool &isBig) {
-  switch (read32(&mh->magic, false)) {
-  case llvm::MachO::MH_MAGIC:
-    is64 = false;
-    isBig = false;
-    return true;
-  case llvm::MachO::MH_MAGIC_64:
-    is64 = true;
-    isBig = false;
-    return true;
-  case llvm::MachO::MH_CIGAM:
-    is64 = false;
-    isBig = true;
-    return true;
-  case llvm::MachO::MH_CIGAM_64:
-    is64 = true;
-    isBig = true;
-    return true;
-  default:
-    return false;
-  }
-}
-
-
-bool isThinObjectFile(StringRef path, MachOLinkingContext::Arch &arch) {
-  // Try opening and mapping file at path.
-  ErrorOr<std::unique_ptr<MemoryBuffer>> b = MemoryBuffer::getFileOrSTDIN(path);
-  if (b.getError())
-    return false;
-
-  // If file length < 32 it is too small to be mach-o object file.
-  StringRef fileBuffer = b->get()->getBuffer();
-  if (fileBuffer.size() < 32)
-    return false;
-
-  // If file buffer does not start with MH_MAGIC (and variants), not obj file.
-  const mach_header *mh = reinterpret_cast<const mach_header *>(
-                                                            fileBuffer.begin());
-  bool is64, isBig;
-  if (!isMachOHeader(mh, is64, isBig))
-    return false;
-
-  // If not MH_OBJECT, not object file.
-  if (read32(&mh->filetype, isBig) != MH_OBJECT)
-    return false;
-
-  // Lookup up arch from cpu/subtype pair.
-  arch = MachOLinkingContext::archFromCpuType(
-      read32(&mh->cputype, isBig),
-      read32(&mh->cpusubtype, isBig));
-  return true;
-}
-
-bool sliceFromFatFile(MemoryBufferRef mb, MachOLinkingContext::Arch arch,
-                      uint32_t &offset, uint32_t &size) {
-  const char *start = mb.getBufferStart();
-  const llvm::MachO::fat_header *fh =
-      reinterpret_cast<const llvm::MachO::fat_header *>(start);
-  if (readBigEndian(fh->magic) != llvm::MachO::FAT_MAGIC)
-    return false;
-  uint32_t nfat_arch = readBigEndian(fh->nfat_arch);
-  const fat_arch *fstart =
-      reinterpret_cast<const fat_arch *>(start + sizeof(fat_header));
-  const fat_arch *fend =
-      reinterpret_cast<const fat_arch *>(start + sizeof(fat_header) +
-                                         sizeof(fat_arch) * nfat_arch);
-  const uint32_t reqCpuType = MachOLinkingContext::cpuTypeFromArch(arch);
-  const uint32_t reqCpuSubtype = MachOLinkingContext::cpuSubtypeFromArch(arch);
-  for (const fat_arch *fa = fstart; fa < fend; ++fa) {
-    if ((readBigEndian(fa->cputype) == reqCpuType) &&
-        (readBigEndian(fa->cpusubtype) == reqCpuSubtype)) {
-      offset = readBigEndian(fa->offset);
-      size = readBigEndian(fa->size);
-      if ((offset + size) > mb.getBufferSize())
-        return false;
-      return true;
-    }
-  }
-  return false;
-}
-
-/// Reads a mach-o file and produces an in-memory normalized view.
-llvm::Expected<std::unique_ptr<NormalizedFile>>
-readBinary(std::unique_ptr<MemoryBuffer> &mb,
-           const MachOLinkingContext::Arch arch) {
-  // Make empty NormalizedFile.
-  std::unique_ptr<NormalizedFile> f(new NormalizedFile());
-
-  const char *start = mb->getBufferStart();
-  size_t objSize = mb->getBufferSize();
-  const mach_header *mh = reinterpret_cast<const mach_header *>(start);
-
-  uint32_t sliceOffset;
-  uint32_t sliceSize;
-  if (sliceFromFatFile(mb->getMemBufferRef(), arch, sliceOffset, sliceSize)) {
-    start = &start[sliceOffset];
-    objSize = sliceSize;
-    mh = reinterpret_cast<const mach_header *>(start);
-  }
-
-  // Determine endianness and pointer size for mach-o file.
-  bool is64, isBig;
-  if (!isMachOHeader(mh, is64, isBig))
-    return llvm::make_error<GenericError>("File is not a mach-o");
-
-  // Endian swap header, if needed.
-  mach_header headerCopy;
-  const mach_header *smh = mh;
-  if (isBig != llvm::sys::IsBigEndianHost) {
-    memcpy(&headerCopy, mh, sizeof(mach_header));
-    swapStruct(headerCopy);
-    smh = &headerCopy;
-  }
-
-  // Validate head and load commands fit in buffer.
-  const uint32_t lcCount = smh->ncmds;
-  const char *lcStart =
-      start + (is64 ? sizeof(mach_header_64) : sizeof(mach_header));
-  StringRef lcRange(lcStart, smh->sizeofcmds);
-  if (lcRange.end() > (start + objSize))
-    return llvm::make_error<GenericError>("Load commands exceed file size");
-
-  // Get architecture from mach_header.
-  f->arch = MachOLinkingContext::archFromCpuType(smh->cputype, smh->cpusubtype);
-  if (f->arch != arch) {
-    return llvm::make_error<GenericError>(
-                                  Twine("file is wrong architecture. Expected "
-                                  "(" + MachOLinkingContext::nameFromArch(arch)
-                                  + ") found ("
-                                  + MachOLinkingContext::nameFromArch(f->arch)
-                                  + ")" ));
-  }
-  // Copy file type and flags
-  f->fileType = HeaderFileType(smh->filetype);
-  f->flags = smh->flags;
-
-
-  // Pre-scan load commands looking for indirect symbol table.
-  uint32_t indirectSymbolTableOffset = 0;
-  uint32_t indirectSymbolTableCount = 0;
-  auto ec = forEachLoadCommand(lcRange, lcCount, isBig, is64,
-                               [&](uint32_t cmd, uint32_t size,
-                                   const char *lc) -> bool {
-    if (cmd == LC_DYSYMTAB) {
-      const dysymtab_command *d = reinterpret_cast<const dysymtab_command*>(lc);
-      indirectSymbolTableOffset = read32(&d->indirectsymoff, isBig);
-      indirectSymbolTableCount = read32(&d->nindirectsyms, isBig);
-      return true;
-    }
-    return false;
-  });
-  if (ec)
-    return std::move(ec);
-
-  // Walk load commands looking for segments/sections and the symbol table.
-  const data_in_code_entry *dataInCode = nullptr;
-  const dyld_info_command *dyldInfo = nullptr;
-  uint32_t dataInCodeSize = 0;
-  ec = forEachLoadCommand(lcRange, lcCount, isBig, is64,
-                    [&] (uint32_t cmd, uint32_t size, const char* lc) -> bool {
-    switch(cmd) {
-    case LC_SEGMENT_64:
-      if (is64) {
-        const segment_command_64 *seg =
-                              reinterpret_cast<const segment_command_64*>(lc);
-        const unsigned sectionCount = read32(&seg->nsects, isBig);
-        const section_64 *sects = reinterpret_cast<const section_64*>
-                                  (lc + sizeof(segment_command_64));
-        const unsigned lcSize = sizeof(segment_command_64)
-                                              + sectionCount*sizeof(section_64);
-        // Verify sections don't extend beyond end of segment load command.
-        if (lcSize > size)
-          return true;
-        for (unsigned i=0; i < sectionCount; ++i) {
-          const section_64 *sect = &sects[i];
-          Section section;
-          section.segmentName = getString16(sect->segname);
-          section.sectionName = getString16(sect->sectname);
-          section.type = (SectionType)(read32(&sect->flags, isBig) &
-                                       SECTION_TYPE);
-          section.attributes  = read32(&sect->flags, isBig) & SECTION_ATTRIBUTES;
-          section.alignment   = 1 << read32(&sect->align, isBig);
-          section.address     = read64(&sect->addr, isBig);
-          const uint8_t *content =
-            (const uint8_t *)start + read32(&sect->offset, isBig);
-          size_t contentSize = read64(&sect->size, isBig);
-          // Note: this assign() is copying the content bytes.  Ideally,
-          // we can use a custom allocator for vector to avoid the copy.
-          section.content = llvm::makeArrayRef(content, contentSize);
-          appendRelocations(section.relocations, mb->getBuffer(), isBig,
-                            read32(&sect->reloff, isBig),
-                            read32(&sect->nreloc, isBig));
-          if (section.type == S_NON_LAZY_SYMBOL_POINTERS) {
-            appendIndirectSymbols(section.indirectSymbols, mb->getBuffer(),
-                                  isBig,
-                                  indirectSymbolTableOffset,
-                                  indirectSymbolTableCount,
-                                  read32(&sect->reserved1, isBig),
-                                  contentSize/4);
-          }
-          f->sections.push_back(section);
-        }
-      }
-      break;
-    case LC_SEGMENT:
-      if (!is64) {
-        const segment_command *seg =
-                              reinterpret_cast<const segment_command*>(lc);
-        const unsigned sectionCount = read32(&seg->nsects, isBig);
-        const section *sects = reinterpret_cast<const section*>
-                                  (lc + sizeof(segment_command));
-        const unsigned lcSize = sizeof(segment_command)
-                                              + sectionCount*sizeof(section);
-        // Verify sections don't extend beyond end of segment load command.
-        if (lcSize > size)
-          return true;
-        for (unsigned i=0; i < sectionCount; ++i) {
-          const section *sect = &sects[i];
-          Section section;
-          section.segmentName = getString16(sect->segname);
-          section.sectionName = getString16(sect->sectname);
-          section.type = (SectionType)(read32(&sect->flags, isBig) &
-                                       SECTION_TYPE);
-          section.attributes =
-              read32((const uint8_t *)&sect->flags, isBig) & SECTION_ATTRIBUTES;
-          section.alignment   = 1 << read32(&sect->align, isBig);
-          section.address     = read32(&sect->addr, isBig);
-          const uint8_t *content =
-            (const uint8_t *)start + read32(&sect->offset, isBig);
-          size_t contentSize = read32(&sect->size, isBig);
-          // Note: this assign() is copying the content bytes.  Ideally,
-          // we can use a custom allocator for vector to avoid the copy.
-          section.content = llvm::makeArrayRef(content, contentSize);
-          appendRelocations(section.relocations, mb->getBuffer(), isBig,
-                            read32(&sect->reloff, isBig),
-                            read32(&sect->nreloc, isBig));
-          if (section.type == S_NON_LAZY_SYMBOL_POINTERS) {
-            appendIndirectSymbols(
-                section.indirectSymbols, mb->getBuffer(), isBig,
-                indirectSymbolTableOffset, indirectSymbolTableCount,
-                read32(&sect->reserved1, isBig), contentSize / 4);
-          }
-          f->sections.push_back(section);
-        }
-      }
-      break;
-    case LC_SYMTAB: {
-      const symtab_command *st = reinterpret_cast<const symtab_command*>(lc);
-      const char *strings = start + read32(&st->stroff, isBig);
-      const uint32_t strSize = read32(&st->strsize, isBig);
-      // Validate string pool and symbol table all in buffer.
-      if (read32((const uint8_t *)&st->stroff, isBig) +
-              read32((const uint8_t *)&st->strsize, isBig) >
-          objSize)
-        return true;
-      if (is64) {
-        const uint32_t symOffset = read32(&st->symoff, isBig);
-        const uint32_t symCount = read32(&st->nsyms, isBig);
-        if ( symOffset+(symCount*sizeof(nlist_64)) > objSize)
-          return true;
-        const nlist_64 *symbols =
-            reinterpret_cast<const nlist_64 *>(start + symOffset);
-        // Convert each nlist_64 to a lld::mach_o::normalized::Symbol.
-        for(uint32_t i=0; i < symCount; ++i) {
-          nlist_64 tempSym;
-          memcpy(&tempSym, &symbols[i], sizeof(nlist_64));
-          const nlist_64 *sin = &tempSym;
-          if (isBig != llvm::sys::IsBigEndianHost)
-            swapStruct(tempSym);
-          Symbol sout;
-          if (sin->n_strx > strSize)
-            return true;
-          sout.name  = &strings[sin->n_strx];
-          sout.type = static_cast<NListType>(sin->n_type & (N_STAB|N_TYPE));
-          sout.scope = (sin->n_type & (N_PEXT|N_EXT));
-          sout.sect  = sin->n_sect;
-          sout.desc  = sin->n_desc;
-          sout.value = sin->n_value;
-          if (sin->n_type & N_STAB)
-            f->stabsSymbols.push_back(sout);
-          else if (sout.type == N_UNDF)
-            f->undefinedSymbols.push_back(sout);
-          else if (sin->n_type & N_EXT)
-            f->globalSymbols.push_back(sout);
-          else
-            f->localSymbols.push_back(sout);
-        }
-      } else {
-        const uint32_t symOffset = read32(&st->symoff, isBig);
-        const uint32_t symCount = read32(&st->nsyms, isBig);
-        if ( symOffset+(symCount*sizeof(nlist)) > objSize)
-          return true;
-        const nlist *symbols =
-            reinterpret_cast<const nlist *>(start + symOffset);
-        // Convert each nlist to a lld::mach_o::normalized::Symbol.
-        for(uint32_t i=0; i < symCount; ++i) {
-          const nlist *sin = &symbols[i];
-          nlist tempSym;
-          if (isBig != llvm::sys::IsBigEndianHost) {
-            tempSym = *sin; swapStruct(tempSym); sin = &tempSym;
-          }
-          Symbol sout;
-          if (sin->n_strx > strSize)
-            return true;
-          sout.name  = &strings[sin->n_strx];
-          sout.type  = (NListType)(sin->n_type & N_TYPE);
-          sout.scope = (sin->n_type & (N_PEXT|N_EXT));
-          sout.sect  = sin->n_sect;
-          sout.desc  = sin->n_desc;
-          sout.value = sin->n_value;
-          if (sout.type == N_UNDF)
-            f->undefinedSymbols.push_back(sout);
-          else if (sout.scope == (SymbolScope)N_EXT)
-            f->globalSymbols.push_back(sout);
-          else if (sin->n_type & N_STAB)
-            f->stabsSymbols.push_back(sout);
-          else
-            f->localSymbols.push_back(sout);
-        }
-      }
-      }
-      break;
-    case LC_ID_DYLIB: {
-      const dylib_command *dl = reinterpret_cast<const dylib_command*>(lc);
-      f->installName = lc + read32(&dl->dylib.name, isBig);
-      f->currentVersion = read32(&dl->dylib.current_version, isBig);
-      f->compatVersion = read32(&dl->dylib.compatibility_version, isBig);
-      }
-      break;
-    case LC_DATA_IN_CODE: {
-      const linkedit_data_command *ldc =
-                            reinterpret_cast<const linkedit_data_command*>(lc);
-      dataInCode = reinterpret_cast<const data_in_code_entry *>(
-          start + read32(&ldc->dataoff, isBig));
-      dataInCodeSize = read32(&ldc->datasize, isBig);
-      }
-      break;
-    case LC_LOAD_DYLIB:
-    case LC_LOAD_WEAK_DYLIB:
-    case LC_REEXPORT_DYLIB:
-    case LC_LOAD_UPWARD_DYLIB: {
-      const dylib_command *dl = reinterpret_cast<const dylib_command*>(lc);
-      DependentDylib entry;
-      entry.path = lc + read32(&dl->dylib.name, isBig);
-      entry.kind = LoadCommandType(cmd);
-      entry.compatVersion = read32(&dl->dylib.compatibility_version, isBig);
-      entry.currentVersion = read32(&dl->dylib.current_version, isBig);
-      f->dependentDylibs.push_back(entry);
-     }
-      break;
-    case LC_RPATH: {
-      const rpath_command *rpc = reinterpret_cast<const rpath_command *>(lc);
-      f->rpaths.push_back(lc + read32(&rpc->path, isBig));
-     }
-      break;
-    case LC_DYLD_INFO:
-    case LC_DYLD_INFO_ONLY:
-      dyldInfo = reinterpret_cast<const dyld_info_command*>(lc);
-      break;
-    case LC_VERSION_MIN_MACOSX:
-    case LC_VERSION_MIN_IPHONEOS:
-    case LC_VERSION_MIN_WATCHOS:
-    case LC_VERSION_MIN_TVOS:
-      // If we are emitting an object file, then we may take the load command
-      // kind from these commands and pass it on to the output
-      // file.
-      f->minOSVersionKind = (LoadCommandType)cmd;
-      break;
-    }
-    return false;
-  });
-  if (ec)
-    return std::move(ec);
-
-  if (dataInCode) {
-    // Convert on-disk data_in_code_entry array to DataInCode vector.
-    for (unsigned i=0; i < dataInCodeSize/sizeof(data_in_code_entry); ++i) {
-      DataInCode entry;
-      entry.offset = read32(&dataInCode[i].offset, isBig);
-      entry.length = read16(&dataInCode[i].length, isBig);
-      entry.kind =
-          (DataRegionType)read16((const uint8_t *)&dataInCode[i].kind, isBig);
-      f->dataInCode.push_back(entry);
-    }
-  }
-
-  if (dyldInfo) {
-    // If any exports, extract and add to normalized exportInfo vector.
-    if (dyldInfo->export_size) {
-      const uint8_t *trieStart = reinterpret_cast<const uint8_t *>(
-          start + read32(&dyldInfo->export_off, isBig));
-      ArrayRef<uint8_t> trie(trieStart, read32(&dyldInfo->export_size, isBig));
-      Error Err = Error::success();
-      for (const ExportEntry &trieExport : MachOObjectFile::exports(Err, trie)) {
-        Export normExport;
-        normExport.name = trieExport.name().copy(f->ownedAllocations);
-        normExport.offset = trieExport.address();
-        normExport.kind = ExportSymbolKind(trieExport.flags() & EXPORT_SYMBOL_FLAGS_KIND_MASK);
-        normExport.flags = trieExport.flags() & ~EXPORT_SYMBOL_FLAGS_KIND_MASK;
-        normExport.otherOffset = trieExport.other();
-        if (!trieExport.otherName().empty())
-          normExport.otherName = trieExport.otherName().copy(f->ownedAllocations);
-        f->exportInfo.push_back(normExport);
-      }
-      if (Err)
-        return std::move(Err);
-    }
-  }
-
-  return std::move(f);
-}
-
-class MachOObjectReader : public Reader {
-public:
-  MachOObjectReader(MachOLinkingContext &ctx) : _ctx(ctx) {}
-
-  bool canParse(file_magic magic, MemoryBufferRef mb) const override {
-    return (magic == file_magic::macho_object && mb.getBufferSize() > 32);
-  }
-
-  ErrorOr<std::unique_ptr<File>>
-  loadFile(std::unique_ptr<MemoryBuffer> mb,
-           const Registry &registry) const override {
-    std::unique_ptr<File> ret =
-      std::make_unique<MachOFile>(std::move(mb), &_ctx);
-    return std::move(ret);
-  }
-
-private:
-  MachOLinkingContext &_ctx;
-};
-
-class MachODylibReader : public Reader {
-public:
-  MachODylibReader(MachOLinkingContext &ctx) : _ctx(ctx) {}
-
-  bool canParse(file_magic magic, MemoryBufferRef mb) const override {
-    switch (magic) {
-    case file_magic::macho_dynamically_linked_shared_lib:
-    case file_magic::macho_dynamically_linked_shared_lib_stub:
-      return mb.getBufferSize() > 32;
-    default:
-      return false;
-    }
-  }
-
-  ErrorOr<std::unique_ptr<File>>
-  loadFile(std::unique_ptr<MemoryBuffer> mb,
-           const Registry &registry) const override {
-    std::unique_ptr<File> ret =
-        std::make_unique<MachODylibFile>(std::move(mb), &_ctx);
-    return std::move(ret);
-  }
-
-private:
-  MachOLinkingContext &_ctx;
-};
-
-class MachOTAPIReader : public Reader {
-public:
-  MachOTAPIReader(MachOLinkingContext &ctx) : _ctx(ctx) {}
-
-  bool canParse(file_magic magic, MemoryBufferRef mb) const override {
-    return magic == file_magic::tapi_file;
-  }
-
-  ErrorOr<std::unique_ptr<File>>
-  loadFile(std::unique_ptr<MemoryBuffer> mb,
-           const Registry &registry) const override {
-    std::unique_ptr<File> ret =
-        std::make_unique<TAPIFile>(std::move(mb), &_ctx);
-    return std::move(ret);
-  }
-
-private:
-  MachOLinkingContext &_ctx;
-};
-
-} // namespace normalized
-} // namespace mach_o
-
-void Registry::addSupportMachOObjects(MachOLinkingContext &ctx) {
-  MachOLinkingContext::Arch arch = ctx.arch();
-  add(std::unique_ptr<Reader>(new mach_o::normalized::MachOObjectReader(ctx)));
-  add(std::unique_ptr<Reader>(new mach_o::normalized::MachODylibReader(ctx)));
-  add(std::unique_ptr<Reader>(new mach_o::normalized::MachOTAPIReader(ctx)));
-  addKindTable(Reference::KindNamespace::mach_o, ctx.archHandler().kindArch(),
-               ctx.archHandler().kindStrings());
-  add(std::unique_ptr<YamlIOTaggedDocumentHandler>(
-                           new mach_o::MachOYamlIOTaggedDocumentHandler(arch)));
-}
-
-
-} // namespace lld
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h b/gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h
deleted file mode 100644 (file)
index aeb04ef..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-//===- lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h ------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H
-#define LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H
-
-#include "MachONormalizedFile.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/Error.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/LEB128.h"
-#include <system_error>
-
-namespace lld {
-namespace mach_o {
-namespace normalized {
-
-class ByteBuffer {
-public:
-  ByteBuffer() : _ostream(_bytes) { }
-
-  void append_byte(uint8_t b) {
-    _ostream << b;
-  }
-  void append_uleb128(uint64_t value) {
-    llvm::encodeULEB128(value, _ostream);
-  }
-  void append_uleb128Fixed(uint64_t value, unsigned byteCount) {
-    unsigned min = llvm::getULEB128Size(value);
-    assert(min <= byteCount);
-    unsigned pad = byteCount - min;
-    llvm::encodeULEB128(value, _ostream, pad);
-  }
-  void append_sleb128(int64_t value) {
-    llvm::encodeSLEB128(value, _ostream);
-  }
-  void append_string(StringRef str) {
-    _ostream << str;
-    append_byte(0);
-  }
-  void align(unsigned alignment) {
-    while ( (_ostream.tell() % alignment) != 0 )
-      append_byte(0);
-  }
-  size_t size() {
-    return _ostream.tell();
-  }
-  const uint8_t *bytes() {
-    return reinterpret_cast<const uint8_t*>(_ostream.str().data());
-  }
-
-private:
-  SmallVector<char, 128>        _bytes;
-  // Stream ivar must be after SmallVector ivar to construct properly.
-  llvm::raw_svector_ostream     _ostream;
-};
-
-using namespace llvm::support::endian;
-using llvm::sys::getSwappedBytes;
-
-template<typename T>
-static inline uint16_t read16(const T *loc, bool isBig) {
-  assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
-  return isBig ? read16be(loc) : read16le(loc);
-}
-
-template<typename T>
-static inline uint32_t read32(const T *loc, bool isBig) {
-  assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
-  return isBig ? read32be(loc) : read32le(loc);
-}
-
-template<typename T>
-static inline uint64_t read64(const T *loc, bool isBig) {
-  assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
-  return isBig ? read64be(loc) : read64le(loc);
-}
-
-inline void write16(uint8_t *loc, uint16_t value, bool isBig) {
-  if (isBig)
-    write16be(loc, value);
-  else
-    write16le(loc, value);
-}
-
-inline void write32(uint8_t *loc, uint32_t value, bool isBig) {
-  if (isBig)
-    write32be(loc, value);
-  else
-    write32le(loc, value);
-}
-
-inline void write64(uint8_t *loc, uint64_t value, bool isBig) {
-  if (isBig)
-    write64be(loc, value);
-  else
-    write64le(loc, value);
-}
-
-inline uint32_t
-bitFieldExtract(uint32_t value, bool isBigEndianBigField, uint8_t firstBit,
-                                                          uint8_t bitCount) {
-  const uint32_t mask = ((1<<bitCount)-1);
-  const uint8_t shift = isBigEndianBigField ? (32-firstBit-bitCount) : firstBit;
-  return (value >> shift) & mask;
-}
-
-inline void
-bitFieldSet(uint32_t &bits, bool isBigEndianBigField, uint32_t newBits,
-                            uint8_t firstBit, uint8_t bitCount) {
-  const uint32_t mask = ((1<<bitCount)-1);
-  assert((newBits & mask) == newBits);
-  const uint8_t shift = isBigEndianBigField ? (32-firstBit-bitCount) : firstBit;
-  bits &= ~(mask << shift);
-  bits |= (newBits << shift);
-}
-
-inline Relocation unpackRelocation(const llvm::MachO::any_relocation_info &r,
-                                   bool isBigEndian) {
-  uint32_t r0 = read32(&r.r_word0, isBigEndian);
-  uint32_t r1 = read32(&r.r_word1, isBigEndian);
-
-  Relocation result;
-  if (r0 & llvm::MachO::R_SCATTERED) {
-    // scattered relocation record always laid out like big endian bit field
-    result.offset     = bitFieldExtract(r0, true, 8, 24);
-    result.scattered  = true;
-    result.type       = (RelocationInfoType)
-                        bitFieldExtract(r0, true, 4, 4);
-    result.length     = bitFieldExtract(r0, true, 2, 2);
-    result.pcRel      = bitFieldExtract(r0, true, 1, 1);
-    result.isExtern   = false;
-    result.value      = r1;
-    result.symbol     = 0;
-  } else {
-    result.offset     = r0;
-    result.scattered  = false;
-    result.type       = (RelocationInfoType)
-                        bitFieldExtract(r1, isBigEndian, 28, 4);
-    result.length     = bitFieldExtract(r1, isBigEndian, 25, 2);
-    result.pcRel      = bitFieldExtract(r1, isBigEndian, 24, 1);
-    result.isExtern   = bitFieldExtract(r1, isBigEndian, 27, 1);
-    result.value      = 0;
-    result.symbol     = bitFieldExtract(r1, isBigEndian, 0, 24);
-  }
-  return result;
-}
-
-
-inline llvm::MachO::any_relocation_info
-packRelocation(const Relocation &r, bool swap, bool isBigEndian) {
-  uint32_t r0 = 0;
-  uint32_t r1 = 0;
-
-  if (r.scattered) {
-    r1 = r.value;
-    bitFieldSet(r0, true, r.offset,    8, 24);
-    bitFieldSet(r0, true, r.type,      4, 4);
-    bitFieldSet(r0, true, r.length,    2, 2);
-    bitFieldSet(r0, true, r.pcRel,     1, 1);
-    bitFieldSet(r0, true, r.scattered, 0, 1); // R_SCATTERED
-  } else {
-    r0 = r.offset;
-    bitFieldSet(r1, isBigEndian, r.type,     28, 4);
-    bitFieldSet(r1, isBigEndian, r.isExtern, 27, 1);
-    bitFieldSet(r1, isBigEndian, r.length,   25, 2);
-    bitFieldSet(r1, isBigEndian, r.pcRel,    24, 1);
-    bitFieldSet(r1, isBigEndian, r.symbol,   0,  24);
-  }
-
-  llvm::MachO::any_relocation_info result;
-  result.r_word0 = swap ? getSwappedBytes(r0) : r0;
-  result.r_word1 = swap ? getSwappedBytes(r1) : r1;
-  return result;
-}
-
-inline StringRef getString16(const char s[16]) {
-  // The StringRef(const char *) constructor passes the const char * to
-  // strlen(), so we can't use this constructor here, because if there is no
-  // null terminator in s, then strlen() will read past the end of the array.
-  return StringRef(s, strnlen(s, 16));
-}
-
-inline void setString16(StringRef str, char s[16]) {
-  memset(s, 0, 16);
-  memcpy(s, str.begin(), (str.size() > 16) ? 16: str.size());
-}
-
-// Implemented in normalizedToAtoms() and used by normalizedFromAtoms() so
-// that the same table can be used to map mach-o sections to and from
-// DefinedAtom::ContentType.
-void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
-                                          StringRef &segmentName,
-                                          StringRef &sectionName,
-                                          SectionType &sectionType,
-                                          SectionAttr &sectionAttrs,
-                                          bool &relocsToDefinedCanBeImplicit);
-
-} // namespace normalized
-} // namespace mach_o
-} // namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp b/gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
deleted file mode 100644 (file)
index 17b45b9..0000000
+++ /dev/null
@@ -1,1560 +0,0 @@
-//===- lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp ---------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-///
-/// \file For mach-o object files, this implementation converts normalized
-/// mach-o in memory to mach-o binary on disk.
-///
-///                 +---------------+
-///                 | binary mach-o |
-///                 +---------------+
-///                        ^
-///                        |
-///                        |
-///                  +------------+
-///                  | normalized |
-///                  +------------+
-
-#include "MachONormalizedFile.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/Error.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/ilist.h"
-#include "llvm/ADT/ilist_node.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <functional>
-#include <list>
-#include <map>
-#include <system_error>
-
-using namespace llvm::MachO;
-
-namespace lld {
-namespace mach_o {
-namespace normalized {
-
-struct TrieNode; // Forward declaration.
-
-struct TrieEdge : public llvm::ilist_node<TrieEdge> {
-  TrieEdge(StringRef s, TrieNode *node) : _subString(s), _child(node) {}
-
-  StringRef          _subString;
-  struct TrieNode   *_child;
-};
-
-} // namespace normalized
-} // namespace mach_o
-} // namespace lld
-
-
-namespace llvm {
-using lld::mach_o::normalized::TrieEdge;
-template <>
-struct ilist_alloc_traits<TrieEdge> : ilist_noalloc_traits<TrieEdge> {};
-} // namespace llvm
-
-
-namespace lld {
-namespace mach_o {
-namespace normalized {
-
-struct TrieNode {
-  typedef llvm::ilist<TrieEdge> TrieEdgeList;
-
-  TrieNode(StringRef s)
-      : _cummulativeString(s), _address(0), _flags(0), _other(0),
-        _trieOffset(0), _hasExportInfo(false) {}
-  ~TrieNode() = default;
-
-  void addSymbol(const Export &entry, BumpPtrAllocator &allocator,
-                 std::vector<TrieNode *> &allNodes);
-
-  void addOrderedNodes(const Export &entry,
-                       std::vector<TrieNode *> &allNodes);
-  bool updateOffset(uint32_t &offset);
-  void appendToByteBuffer(ByteBuffer &out);
-
-private:
-  StringRef                 _cummulativeString;
-  TrieEdgeList              _children;
-  uint64_t                  _address;
-  uint64_t                  _flags;
-  uint64_t                  _other;
-  StringRef                 _importedName;
-  uint32_t                  _trieOffset;
-  bool                      _hasExportInfo;
-  bool                      _ordered = false;
-};
-
-/// Utility class for writing a mach-o binary file given an in-memory
-/// normalized file.
-class MachOFileLayout {
-public:
-  /// All layout computation is done in the constructor.
-  MachOFileLayout(const NormalizedFile &file, bool alwaysIncludeFunctionStarts);
-
-  /// Returns the final file size as computed in the constructor.
-  size_t      size() const;
-
-  // Returns size of the mach_header and load commands.
-  size_t      headerAndLoadCommandsSize() const;
-
-  /// Writes the normalized file as a binary mach-o file to the specified
-  /// path.  This does not have a stream interface because the generated
-  /// file may need the 'x' bit set.
-  llvm::Error writeBinary(StringRef path);
-
-private:
-  uint32_t    loadCommandsSize(uint32_t &count,
-                               bool alwaysIncludeFunctionStarts);
-  void        buildFileOffsets();
-  void        writeMachHeader();
-  llvm::Error writeLoadCommands();
-  void        writeSectionContent();
-  void        writeRelocations();
-  void        writeSymbolTable();
-  void        writeRebaseInfo();
-  void        writeBindingInfo();
-  void        writeLazyBindingInfo();
-  void        writeExportInfo();
-  void        writeFunctionStartsInfo();
-  void        writeDataInCodeInfo();
-  void        writeLinkEditContent();
-  void        buildLinkEditInfo();
-  void        buildRebaseInfo();
-  void        buildBindInfo();
-  void        buildLazyBindInfo();
-  void        buildExportTrie();
-  void        computeFunctionStartsSize();
-  void        computeDataInCodeSize();
-  void        computeSymbolTableSizes();
-  void        buildSectionRelocations();
-  void        appendSymbols(const std::vector<Symbol> &symbols,
-                                      uint32_t &symOffset, uint32_t &strOffset);
-  uint32_t    indirectSymbolIndex(const Section &sect, uint32_t &index);
-  uint32_t    indirectSymbolElementSize(const Section &sect);
-
-  // For use as template parameter to load command methods.
-  struct MachO64Trait {
-    typedef llvm::MachO::segment_command_64 command;
-    typedef llvm::MachO::section_64         section;
-    enum { LC = llvm::MachO::LC_SEGMENT_64 };
-  };
-
-  // For use as template parameter to load command methods.
-  struct MachO32Trait {
-    typedef llvm::MachO::segment_command   command;
-    typedef llvm::MachO::section           section;
-    enum { LC = llvm::MachO::LC_SEGMENT };
-  };
-
-  template <typename T>
-  llvm::Error writeSingleSegmentLoadCommand(uint8_t *&lc);
-  template <typename T> llvm::Error writeSegmentLoadCommands(uint8_t *&lc);
-
-  uint32_t pointerAlign(uint32_t value);
-  static StringRef dyldPath();
-
-  struct SegExtraInfo {
-    uint32_t                    fileOffset;
-    uint32_t                    fileSize;
-    std::vector<const Section*> sections;
-  };
-  typedef std::map<const Segment*, SegExtraInfo> SegMap;
-  struct SectionExtraInfo {
-    uint32_t                    fileOffset;
-  };
-  typedef std::map<const Section*, SectionExtraInfo> SectionMap;
-
-  const NormalizedFile &_file;
-  std::error_code _ec;
-  uint8_t              *_buffer;
-  const bool            _is64;
-  const bool            _swap;
-  const bool            _bigEndianArch;
-  uint64_t              _seg1addr;
-  uint32_t              _startOfLoadCommands;
-  uint32_t              _countOfLoadCommands;
-  uint32_t              _endOfLoadCommands;
-  uint32_t              _startOfRelocations;
-  uint32_t              _startOfFunctionStarts;
-  uint32_t              _startOfDataInCode;
-  uint32_t              _startOfSymbols;
-  uint32_t              _startOfIndirectSymbols;
-  uint32_t              _startOfSymbolStrings;
-  uint32_t              _endOfSymbolStrings;
-  uint32_t              _symbolTableLocalsStartIndex;
-  uint32_t              _symbolTableGlobalsStartIndex;
-  uint32_t              _symbolTableUndefinesStartIndex;
-  uint32_t              _symbolStringPoolSize;
-  uint32_t              _symbolTableSize;
-  uint32_t              _functionStartsSize;
-  uint32_t              _dataInCodeSize;
-  uint32_t              _indirectSymbolTableCount;
-  // Used in object file creation only
-  uint32_t              _startOfSectionsContent;
-  uint32_t              _endOfSectionsContent;
-  // Used in final linked image only
-  uint32_t              _startOfLinkEdit;
-  uint32_t              _startOfRebaseInfo;
-  uint32_t              _endOfRebaseInfo;
-  uint32_t              _startOfBindingInfo;
-  uint32_t              _endOfBindingInfo;
-  uint32_t              _startOfLazyBindingInfo;
-  uint32_t              _endOfLazyBindingInfo;
-  uint32_t              _startOfExportTrie;
-  uint32_t              _endOfExportTrie;
-  uint32_t              _endOfLinkEdit;
-  uint64_t              _addressOfLinkEdit;
-  SegMap                _segInfo;
-  SectionMap            _sectInfo;
-  ByteBuffer            _rebaseInfo;
-  ByteBuffer            _bindingInfo;
-  ByteBuffer            _lazyBindingInfo;
-  ByteBuffer            _weakBindingInfo;
-  ByteBuffer            _exportTrie;
-};
-
-size_t headerAndLoadCommandsSize(const NormalizedFile &file,
-                                 bool includeFunctionStarts) {
-  MachOFileLayout layout(file, includeFunctionStarts);
-  return layout.headerAndLoadCommandsSize();
-}
-
-StringRef MachOFileLayout::dyldPath() {
-  return "/usr/lib/dyld";
-}
-
-uint32_t MachOFileLayout::pointerAlign(uint32_t value) {
-  return llvm::alignTo(value, _is64 ? 8 : 4);
-}
-
-
-size_t MachOFileLayout::headerAndLoadCommandsSize() const {
-  return _endOfLoadCommands;
-}
-
-MachOFileLayout::MachOFileLayout(const NormalizedFile &file,
-                                 bool alwaysIncludeFunctionStarts)
-    : _file(file),
-      _is64(MachOLinkingContext::is64Bit(file.arch)),
-      _swap(!MachOLinkingContext::isHostEndian(file.arch)),
-      _bigEndianArch(MachOLinkingContext::isBigEndian(file.arch)),
-      _seg1addr(INT64_MAX) {
-  _startOfLoadCommands = _is64 ? sizeof(mach_header_64) : sizeof(mach_header);
-  const size_t segCommandBaseSize =
-          (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
-  const size_t sectsSize = (_is64 ? sizeof(section_64) : sizeof(section));
-  if (file.fileType == llvm::MachO::MH_OBJECT) {
-    // object files have just one segment load command containing all sections
-    _endOfLoadCommands = _startOfLoadCommands
-                               + segCommandBaseSize
-                               + file.sections.size() * sectsSize
-                               + sizeof(symtab_command);
-    _countOfLoadCommands = 2;
-    if (file.hasMinVersionLoadCommand) {
-      _endOfLoadCommands += sizeof(version_min_command);
-      _countOfLoadCommands++;
-    }
-    if (!_file.functionStarts.empty() || alwaysIncludeFunctionStarts) {
-      _endOfLoadCommands += sizeof(linkedit_data_command);
-      _countOfLoadCommands++;
-    }
-    if (_file.generateDataInCodeLoadCommand) {
-      _endOfLoadCommands += sizeof(linkedit_data_command);
-      _countOfLoadCommands++;
-    }
-    // Assign file offsets to each section.
-    _startOfSectionsContent = _endOfLoadCommands;
-    unsigned relocCount = 0;
-    uint64_t offset = _startOfSectionsContent;
-    for (const Section &sect : file.sections) {
-      if (isZeroFillSection(sect.type))
-        _sectInfo[&sect].fileOffset = 0;
-      else {
-        offset = llvm::alignTo(offset, sect.alignment);
-        _sectInfo[&sect].fileOffset = offset;
-        offset += sect.content.size();
-      }
-      relocCount += sect.relocations.size();
-    }
-    _endOfSectionsContent = offset;
-
-    computeSymbolTableSizes();
-    computeFunctionStartsSize();
-    computeDataInCodeSize();
-
-    // Align start of relocations.
-    _startOfRelocations = pointerAlign(_endOfSectionsContent);
-    _startOfFunctionStarts = _startOfRelocations + relocCount * 8;
-    _startOfDataInCode = _startOfFunctionStarts + _functionStartsSize;
-    _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
-    // Add Indirect symbol table.
-    _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
-    // Align start of symbol table and symbol strings.
-    _startOfSymbolStrings = _startOfIndirectSymbols
-                  + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
-    _endOfSymbolStrings = _startOfSymbolStrings
-                          + pointerAlign(_symbolStringPoolSize);
-    _endOfLinkEdit = _endOfSymbolStrings;
-    DEBUG_WITH_TYPE("MachOFileLayout",
-                  llvm::dbgs() << "MachOFileLayout()\n"
-      << "  startOfLoadCommands=" << _startOfLoadCommands << "\n"
-      << "  countOfLoadCommands=" << _countOfLoadCommands << "\n"
-      << "  endOfLoadCommands=" << _endOfLoadCommands << "\n"
-      << "  startOfRelocations=" << _startOfRelocations << "\n"
-      << "  startOfSymbols=" << _startOfSymbols << "\n"
-      << "  startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
-      << "  endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
-      << "  startOfSectionsContent=" << _startOfSectionsContent << "\n"
-      << "  endOfSectionsContent=" << _endOfSectionsContent << "\n");
-  } else {
-    // Final linked images have one load command per segment.
-    _endOfLoadCommands = _startOfLoadCommands
-                          + loadCommandsSize(_countOfLoadCommands,
-                                             alwaysIncludeFunctionStarts);
-
-    // Assign section file offsets.
-    buildFileOffsets();
-    buildLinkEditInfo();
-
-    // LINKEDIT of final linked images has in order:
-    // rebase info, binding info, lazy binding info, weak binding info,
-    // data-in-code, symbol table, indirect symbol table, symbol table strings.
-    _startOfRebaseInfo = _startOfLinkEdit;
-    _endOfRebaseInfo = _startOfRebaseInfo + _rebaseInfo.size();
-    _startOfBindingInfo = _endOfRebaseInfo;
-    _endOfBindingInfo = _startOfBindingInfo + _bindingInfo.size();
-    _startOfLazyBindingInfo = _endOfBindingInfo;
-    _endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
-    _startOfExportTrie = _endOfLazyBindingInfo;
-    _endOfExportTrie = _startOfExportTrie + _exportTrie.size();
-    _startOfFunctionStarts = _endOfExportTrie;
-    _startOfDataInCode = _startOfFunctionStarts + _functionStartsSize;
-    _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
-    _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
-    _startOfSymbolStrings = _startOfIndirectSymbols
-                  + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
-    _endOfSymbolStrings = _startOfSymbolStrings
-                          + pointerAlign(_symbolStringPoolSize);
-    _endOfLinkEdit = _endOfSymbolStrings;
-    DEBUG_WITH_TYPE("MachOFileLayout",
-                  llvm::dbgs() << "MachOFileLayout()\n"
-      << "  startOfLoadCommands=" << _startOfLoadCommands << "\n"
-      << "  countOfLoadCommands=" << _countOfLoadCommands << "\n"
-      << "  endOfLoadCommands=" << _endOfLoadCommands << "\n"
-      << "  startOfLinkEdit=" << _startOfLinkEdit << "\n"
-      << "  startOfRebaseInfo=" << _startOfRebaseInfo << "\n"
-      << "  endOfRebaseInfo=" << _endOfRebaseInfo << "\n"
-      << "  startOfBindingInfo=" << _startOfBindingInfo << "\n"
-      << "  endOfBindingInfo=" << _endOfBindingInfo << "\n"
-      << "  startOfLazyBindingInfo=" << _startOfLazyBindingInfo << "\n"
-      << "  endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
-      << "  startOfExportTrie=" << _startOfExportTrie << "\n"
-      << "  endOfExportTrie=" << _endOfExportTrie << "\n"
-      << "  startOfFunctionStarts=" << _startOfFunctionStarts << "\n"
-      << "  startOfDataInCode=" << _startOfDataInCode << "\n"
-      << "  startOfSymbols=" << _startOfSymbols << "\n"
-      << "  startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
-      << "  endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
-      << "  addressOfLinkEdit=" << _addressOfLinkEdit << "\n");
-  }
-}
-
-uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count,
-                                           bool alwaysIncludeFunctionStarts) {
-  uint32_t size = 0;
-  count = 0;
-
-  const size_t segCommandSize =
-          (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
-  const size_t sectionSize = (_is64 ? sizeof(section_64) : sizeof(section));
-
-  // Add LC_SEGMENT for each segment.
-  size += _file.segments.size() * segCommandSize;
-  count += _file.segments.size();
-  // Add section record for each section.
-  size += _file.sections.size() * sectionSize;
-
-  // If creating a dylib, add LC_ID_DYLIB.
-  if (_file.fileType == llvm::MachO::MH_DYLIB) {
-    size += sizeof(dylib_command) + pointerAlign(_file.installName.size() + 1);
-    ++count;
-  }
-
-  // Add LC_DYLD_INFO
-  size += sizeof(dyld_info_command);
-  ++count;
-
-  // Add LC_SYMTAB
-  size += sizeof(symtab_command);
-  ++count;
-
-  // Add LC_DYSYMTAB
-  if (_file.fileType != llvm::MachO::MH_PRELOAD) {
-    size += sizeof(dysymtab_command);
-    ++count;
-  }
-
-  // If main executable add LC_LOAD_DYLINKER
-  if (_file.fileType == llvm::MachO::MH_EXECUTE) {
-    size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1);
-    ++count;
-  }
-
-  // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_WATCHOS,
-  // LC_VERSION_MIN_TVOS
-  if (_file.hasMinVersionLoadCommand) {
-    size += sizeof(version_min_command);
-    ++count;
-  }
-
-  // Add LC_SOURCE_VERSION
-  size += sizeof(source_version_command);
-  ++count;
-
-  // If main executable add LC_MAIN
-  if (_file.fileType == llvm::MachO::MH_EXECUTE) {
-    size += sizeof(entry_point_command);
-    ++count;
-  }
-
-  // Add LC_LOAD_DYLIB for each dependent dylib.
-  for (const DependentDylib &dep : _file.dependentDylibs) {
-    size += sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
-    ++count;
-  }
-
-  // Add LC_RPATH
-  for (const StringRef &path : _file.rpaths) {
-    size += pointerAlign(sizeof(rpath_command) + path.size() + 1);
-    ++count;
-  }
-
-  // Add LC_FUNCTION_STARTS if needed
-  if (!_file.functionStarts.empty() || alwaysIncludeFunctionStarts) {
-    size += sizeof(linkedit_data_command);
-    ++count;
-  }
-
-  // Add LC_DATA_IN_CODE if requested.  Note, we do encode zero length entries.
-  // FIXME: Zero length entries is only to match ld64.  Should we change this?
-  if (_file.generateDataInCodeLoadCommand) {
-    size += sizeof(linkedit_data_command);
-    ++count;
-  }
-
-  return size;
-}
-
-static bool overlaps(const Segment &s1, const Segment &s2) {
-  if (s2.address >= s1.address+s1.size)
-    return false;
-  if (s1.address >= s2.address+s2.size)
-    return false;
-  return true;
-}
-
-static bool overlaps(const Section &s1, const Section &s2) {
-  if (s2.address >= s1.address+s1.content.size())
-    return false;
-  if (s1.address >= s2.address+s2.content.size())
-    return false;
-  return true;
-}
-
-void MachOFileLayout::buildFileOffsets() {
-  // Verify no segments overlap
-  for (const Segment &sg1 : _file.segments) {
-    for (const Segment &sg2 : _file.segments) {
-      if (&sg1 == &sg2)
-        continue;
-      if (overlaps(sg1,sg2)) {
-        _ec = make_error_code(llvm::errc::executable_format_error);
-        return;
-      }
-    }
-  }
-
-  // Verify no sections overlap
-  for (const Section &s1 : _file.sections) {
-    for (const Section &s2 : _file.sections) {
-      if (&s1 == &s2)
-        continue;
-      if (overlaps(s1,s2)) {
-        _ec = make_error_code(llvm::errc::executable_format_error);
-        return;
-      }
-    }
-  }
-
-  // Build side table of extra info about segments and sections.
-  SegExtraInfo t;
-  t.fileOffset = 0;
-  for (const Segment &sg : _file.segments) {
-    _segInfo[&sg] = t;
-  }
-  SectionExtraInfo t2;
-  t2.fileOffset = 0;
-  // Assign sections to segments.
-  for (const Section &s : _file.sections) {
-    _sectInfo[&s] = t2;
-    bool foundSegment = false;
-    for (const Segment &sg : _file.segments) {
-      if (sg.name.equals(s.segmentName)) {
-        if ((s.address >= sg.address)
-                        && (s.address+s.content.size() <= sg.address+sg.size)) {
-          _segInfo[&sg].sections.push_back(&s);
-          foundSegment = true;
-          break;
-        }
-      }
-    }
-    if (!foundSegment) {
-      _ec = make_error_code(llvm::errc::executable_format_error);
-      return;
-    }
-  }
-
-  // Assign file offsets.
-  uint32_t fileOffset = 0;
-  DEBUG_WITH_TYPE("MachOFileLayout",
-                  llvm::dbgs() << "buildFileOffsets()\n");
-  for (const Segment &sg : _file.segments) {
-    _segInfo[&sg].fileOffset = fileOffset;
-    if ((_seg1addr == INT64_MAX) && sg.init_access)
-      _seg1addr = sg.address;
-    DEBUG_WITH_TYPE("MachOFileLayout",
-                  llvm::dbgs() << "  segment=" << sg.name
-                  << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
-
-    uint32_t segFileSize = 0;
-    // A segment that is not zero-fill must use a least one page of disk space.
-    if (sg.init_access)
-      segFileSize = _file.pageSize;
-    for (const Section *s : _segInfo[&sg].sections) {
-      uint32_t sectOffset = s->address - sg.address;
-      uint32_t sectFileSize =
-        isZeroFillSection(s->type) ? 0 : s->content.size();
-      segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
-
-      _sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
-      DEBUG_WITH_TYPE("MachOFileLayout",
-                  llvm::dbgs() << "    section=" << s->sectionName
-                  << ", fileOffset=" << fileOffset << "\n");
-    }
-
-    // round up all segments to page aligned, except __LINKEDIT
-    if (!sg.name.equals("__LINKEDIT")) {
-      _segInfo[&sg].fileSize = llvm::alignTo(segFileSize, _file.pageSize);
-      fileOffset = llvm::alignTo(fileOffset + segFileSize, _file.pageSize);
-    }
-    _addressOfLinkEdit = sg.address + sg.size;
-  }
-  _startOfLinkEdit = fileOffset;
-}
-
-size_t MachOFileLayout::size() const {
-  return _endOfSymbolStrings;
-}
-
-void MachOFileLayout::writeMachHeader() {
-  auto cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
-  // dynamic x86 executables on newer OS version should also set the
-  // CPU_SUBTYPE_LIB64 mask in the CPU subtype.
-  // FIXME: Check that this is a dynamic executable, not a static one.
-  if (_file.fileType == llvm::MachO::MH_EXECUTE &&
-      cpusubtype == CPU_SUBTYPE_X86_64_ALL &&
-      _file.os == MachOLinkingContext::OS::macOSX) {
-    uint32_t version;
-    bool failed = MachOLinkingContext::parsePackedVersion("10.5", version);
-    if (!failed && _file.minOSverson >= version)
-      cpusubtype |= CPU_SUBTYPE_LIB64;
-  }
-
-  mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
-  mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
-  mh->cputype =  MachOLinkingContext::cpuTypeFromArch(_file.arch);
-  mh->cpusubtype = cpusubtype;
-  mh->filetype = _file.fileType;
-  mh->ncmds = _countOfLoadCommands;
-  mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
-  mh->flags = _file.flags;
-  if (_swap)
-    swapStruct(*mh);
-}
-
-uint32_t MachOFileLayout::indirectSymbolIndex(const Section &sect,
-                                                   uint32_t &index) {
-  if (sect.indirectSymbols.empty())
-    return 0;
-  uint32_t result = index;
-  index += sect.indirectSymbols.size();
-  return result;
-}
-
-uint32_t MachOFileLayout::indirectSymbolElementSize(const Section &sect) {
-  if (sect.indirectSymbols.empty())
-    return 0;
-  if (sect.type != S_SYMBOL_STUBS)
-    return 0;
-  return sect.content.size() / sect.indirectSymbols.size();
-}
-
-template <typename T>
-llvm::Error MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
-  typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
-  seg->cmd = T::LC;
-  seg->cmdsize = sizeof(typename T::command)
-                          + _file.sections.size() * sizeof(typename T::section);
-  uint8_t *next = lc + seg->cmdsize;
-  memset(seg->segname, 0, 16);
-  seg->flags = 0;
-  seg->vmaddr = 0;
-  seg->fileoff = _endOfLoadCommands;
-  seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
-  seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
-  seg->nsects = _file.sections.size();
-  if (seg->nsects) {
-    seg->vmsize = _file.sections.back().address
-                + _file.sections.back().content.size();
-    seg->filesize = _sectInfo[&_file.sections.back()].fileOffset +
-                    _file.sections.back().content.size() -
-                    _sectInfo[&_file.sections.front()].fileOffset;
-  }
-  if (_swap)
-    swapStruct(*seg);
-  typename T::section *sout = reinterpret_cast<typename T::section*>
-                                              (lc+sizeof(typename T::command));
-  uint32_t relOffset = _startOfRelocations;
-  uint32_t indirectSymRunningIndex = 0;
-  for (const Section &sin : _file.sections) {
-    setString16(sin.sectionName, sout->sectname);
-    setString16(sin.segmentName, sout->segname);
-    sout->addr = sin.address;
-    sout->size = sin.content.size();
-    sout->offset = _sectInfo[&sin].fileOffset;
-    sout->align = llvm::Log2_32(sin.alignment);
-    sout->reloff = sin.relocations.empty() ? 0 : relOffset;
-    sout->nreloc = sin.relocations.size();
-    sout->flags = sin.type | sin.attributes;
-    sout->reserved1 = indirectSymbolIndex(sin, indirectSymRunningIndex);
-    sout->reserved2 = indirectSymbolElementSize(sin);
-    relOffset += sin.relocations.size() * sizeof(any_relocation_info);
-    if (_swap)
-      swapStruct(*sout);
-    ++sout;
-  }
-  lc = next;
-  return llvm::Error::success();
-}
-
-template <typename T>
-llvm::Error MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
-  uint32_t indirectSymRunningIndex = 0;
-  for (const Segment &seg : _file.segments) {
-    // Link edit has no sections and a custom range of address, so handle it
-    // specially.
-    SegExtraInfo &segInfo = _segInfo[&seg];
-    if (seg.name.equals("__LINKEDIT")) {
-      size_t linkeditSize = _endOfLinkEdit - _startOfLinkEdit;
-      typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
-      cmd->cmd = T::LC;
-      cmd->cmdsize = sizeof(typename T::command);
-      uint8_t *next = lc + cmd->cmdsize;
-      setString16("__LINKEDIT", cmd->segname);
-      cmd->vmaddr   = _addressOfLinkEdit;
-      cmd->vmsize   = llvm::alignTo(linkeditSize, _file.pageSize);
-      cmd->fileoff  = _startOfLinkEdit;
-      cmd->filesize = linkeditSize;
-      cmd->initprot = seg.init_access;
-      cmd->maxprot  = seg.max_access;
-      cmd->nsects   = 0;
-      cmd->flags    = 0;
-      if (_swap)
-        swapStruct(*cmd);
-      lc = next;
-      continue;
-    }
-    // Write segment command with trailing sections.
-    typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
-    cmd->cmd = T::LC;
-    cmd->cmdsize = sizeof(typename T::command)
-                        + segInfo.sections.size() * sizeof(typename T::section);
-    uint8_t *next = lc + cmd->cmdsize;
-    setString16(seg.name, cmd->segname);
-    cmd->vmaddr   = seg.address;
-    cmd->vmsize   = seg.size;
-    cmd->fileoff  = segInfo.fileOffset;
-    cmd->filesize = segInfo.fileSize;
-    cmd->initprot = seg.init_access;
-    cmd->maxprot  = seg.max_access;
-    cmd->nsects   = segInfo.sections.size();
-    cmd->flags    = 0;
-    if (_swap)
-      swapStruct(*cmd);
-    typename T::section *sect = reinterpret_cast<typename T::section*>
-                                               (lc+sizeof(typename T::command));
-    for (const Section *section : segInfo.sections) {
-      setString16(section->sectionName, sect->sectname);
-      setString16(section->segmentName, sect->segname);
-      sect->addr      = section->address;
-      sect->size      = section->content.size();
-      if (isZeroFillSection(section->type))
-        sect->offset  = 0;
-      else
-        sect->offset  = section->address - seg.address + segInfo.fileOffset;
-      sect->align     = llvm::Log2_32(section->alignment);
-      sect->reloff    = 0;
-      sect->nreloc    = 0;
-      sect->flags     = section->type | section->attributes;
-      sect->reserved1 = indirectSymbolIndex(*section, indirectSymRunningIndex);
-      sect->reserved2 = indirectSymbolElementSize(*section);
-      if (_swap)
-        swapStruct(*sect);
-      ++sect;
-    }
-    lc = reinterpret_cast<uint8_t*>(next);
-  }
-  return llvm::Error::success();
-}
-
-static void writeVersionMinLoadCommand(const NormalizedFile &_file,
-                                       bool _swap,
-                                       uint8_t *&lc) {
-  if (!_file.hasMinVersionLoadCommand)
-    return;
-  version_min_command *vm = reinterpret_cast<version_min_command*>(lc);
-  switch (_file.os) {
-    case MachOLinkingContext::OS::unknown:
-      vm->cmd     = _file.minOSVersionKind;
-      vm->cmdsize = sizeof(version_min_command);
-      vm->version = _file.minOSverson;
-      vm->sdk     = 0;
-      break;
-    case MachOLinkingContext::OS::macOSX:
-      vm->cmd     = LC_VERSION_MIN_MACOSX;
-      vm->cmdsize = sizeof(version_min_command);
-      vm->version = _file.minOSverson;
-      vm->sdk     = _file.sdkVersion;
-      break;
-    case MachOLinkingContext::OS::iOS:
-    case MachOLinkingContext::OS::iOS_simulator:
-      vm->cmd     = LC_VERSION_MIN_IPHONEOS;
-      vm->cmdsize = sizeof(version_min_command);
-      vm->version = _file.minOSverson;
-      vm->sdk     = _file.sdkVersion;
-      break;
-  }
-  if (_swap)
-    swapStruct(*vm);
-  lc += sizeof(version_min_command);
-}
-
-llvm::Error MachOFileLayout::writeLoadCommands() {
-  uint8_t *lc = &_buffer[_startOfLoadCommands];
-  if (_file.fileType == llvm::MachO::MH_OBJECT) {
-    // Object files have one unnamed segment which holds all sections.
-    if (_is64) {
-     if (auto ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc))
-       return ec;
-    } else {
-      if (auto ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc))
-        return ec;
-    }
-    // Add LC_SYMTAB with symbol table info
-    symtab_command* st = reinterpret_cast<symtab_command*>(lc);
-    st->cmd     = LC_SYMTAB;
-    st->cmdsize = sizeof(symtab_command);
-    st->symoff  = _startOfSymbols;
-    st->nsyms   = _file.stabsSymbols.size() + _file.localSymbols.size() +
-                  _file.globalSymbols.size() + _file.undefinedSymbols.size();
-    st->stroff  = _startOfSymbolStrings;
-    st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
-    if (_swap)
-      swapStruct(*st);
-    lc += sizeof(symtab_command);
-
-    // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS,
-    // LC_VERSION_MIN_WATCHOS, LC_VERSION_MIN_TVOS
-    writeVersionMinLoadCommand(_file, _swap, lc);
-
-    // Add LC_FUNCTION_STARTS if needed.
-    if (_functionStartsSize != 0) {
-      linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
-      dl->cmd      = LC_FUNCTION_STARTS;
-      dl->cmdsize  = sizeof(linkedit_data_command);
-      dl->dataoff  = _startOfFunctionStarts;
-      dl->datasize = _functionStartsSize;
-      if (_swap)
-        swapStruct(*dl);
-      lc += sizeof(linkedit_data_command);
-    }
-
-    // Add LC_DATA_IN_CODE if requested.
-    if (_file.generateDataInCodeLoadCommand) {
-      linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
-      dl->cmd      = LC_DATA_IN_CODE;
-      dl->cmdsize  = sizeof(linkedit_data_command);
-      dl->dataoff  = _startOfDataInCode;
-      dl->datasize = _dataInCodeSize;
-      if (_swap)
-        swapStruct(*dl);
-      lc += sizeof(linkedit_data_command);
-    }
-  } else {
-    // Final linked images have sections under segments.
-    if (_is64) {
-      if (auto ec = writeSegmentLoadCommands<MachO64Trait>(lc))
-        return ec;
-    } else {
-      if (auto ec = writeSegmentLoadCommands<MachO32Trait>(lc))
-        return ec;
-    }
-
-    // Add LC_ID_DYLIB command for dynamic libraries.
-    if (_file.fileType == llvm::MachO::MH_DYLIB) {
-      dylib_command *dc = reinterpret_cast<dylib_command*>(lc);
-      StringRef path = _file.installName;
-      uint32_t size = sizeof(dylib_command) + pointerAlign(path.size() + 1);
-      dc->cmd                         = LC_ID_DYLIB;
-      dc->cmdsize                     = size;
-      dc->dylib.name                  = sizeof(dylib_command); // offset
-      // needs to be some constant value different than the one in LC_LOAD_DYLIB
-      dc->dylib.timestamp             = 1;
-      dc->dylib.current_version       = _file.currentVersion;
-      dc->dylib.compatibility_version = _file.compatVersion;
-      if (_swap)
-        swapStruct(*dc);
-      memcpy(lc + sizeof(dylib_command), path.begin(), path.size());
-      lc[sizeof(dylib_command) + path.size()] = '\0';
-      lc += size;
-    }
-
-    // Add LC_DYLD_INFO_ONLY.
-    dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc);
-    di->cmd            = LC_DYLD_INFO_ONLY;
-    di->cmdsize        = sizeof(dyld_info_command);
-    di->rebase_off     = _rebaseInfo.size() ? _startOfRebaseInfo : 0;
-    di->rebase_size    = _rebaseInfo.size();
-    di->bind_off       = _bindingInfo.size() ? _startOfBindingInfo : 0;
-    di->bind_size      = _bindingInfo.size();
-    di->weak_bind_off  = 0;
-    di->weak_bind_size = 0;
-    di->lazy_bind_off  = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0;
-    di->lazy_bind_size = _lazyBindingInfo.size();
-    di->export_off     = _exportTrie.size() ? _startOfExportTrie : 0;
-    di->export_size    = _exportTrie.size();
-    if (_swap)
-      swapStruct(*di);
-    lc += sizeof(dyld_info_command);
-
-    // Add LC_SYMTAB with symbol table info.
-    symtab_command* st = reinterpret_cast<symtab_command*>(lc);
-    st->cmd     = LC_SYMTAB;
-    st->cmdsize = sizeof(symtab_command);
-    st->symoff  = _startOfSymbols;
-    st->nsyms   = _file.stabsSymbols.size() + _file.localSymbols.size() +
-                  _file.globalSymbols.size() + _file.undefinedSymbols.size();
-    st->stroff  = _startOfSymbolStrings;
-    st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
-    if (_swap)
-      swapStruct(*st);
-    lc += sizeof(symtab_command);
-
-    // Add LC_DYSYMTAB
-    if (_file.fileType != llvm::MachO::MH_PRELOAD) {
-      dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc);
-      dst->cmd            = LC_DYSYMTAB;
-      dst->cmdsize        = sizeof(dysymtab_command);
-      dst->ilocalsym      = _symbolTableLocalsStartIndex;
-      dst->nlocalsym      = _file.stabsSymbols.size() +
-                            _file.localSymbols.size();
-      dst->iextdefsym     = _symbolTableGlobalsStartIndex;
-      dst->nextdefsym     = _file.globalSymbols.size();
-      dst->iundefsym      = _symbolTableUndefinesStartIndex;
-      dst->nundefsym      = _file.undefinedSymbols.size();
-      dst->tocoff         = 0;
-      dst->ntoc           = 0;
-      dst->modtaboff      = 0;
-      dst->nmodtab        = 0;
-      dst->extrefsymoff   = 0;
-      dst->nextrefsyms    = 0;
-      dst->indirectsymoff = _startOfIndirectSymbols;
-      dst->nindirectsyms  = _indirectSymbolTableCount;
-      dst->extreloff      = 0;
-      dst->nextrel        = 0;
-      dst->locreloff      = 0;
-      dst->nlocrel        = 0;
-      if (_swap)
-        swapStruct(*dst);
-      lc += sizeof(dysymtab_command);
-    }
-
-    // If main executable, add LC_LOAD_DYLINKER
-    if (_file.fileType == llvm::MachO::MH_EXECUTE) {
-      // Build LC_LOAD_DYLINKER load command.
-      uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
-      dylinker_command* dl = reinterpret_cast<dylinker_command*>(lc);
-      dl->cmd              = LC_LOAD_DYLINKER;
-      dl->cmdsize          = size;
-      dl->name             = sizeof(dylinker_command); // offset
-      if (_swap)
-        swapStruct(*dl);
-      memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
-      lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
-      lc += size;
-    }
-
-    // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_WATCHOS,
-    // LC_VERSION_MIN_TVOS
-    writeVersionMinLoadCommand(_file, _swap, lc);
-
-    // Add LC_SOURCE_VERSION
-    {
-      // Note, using a temporary here to appease UB as we may not be aligned
-      // enough for a struct containing a uint64_t when emitting a 32-bit binary
-      source_version_command sv;
-      sv.cmd       = LC_SOURCE_VERSION;
-      sv.cmdsize   = sizeof(source_version_command);
-      sv.version   = _file.sourceVersion;
-      if (_swap)
-        swapStruct(sv);
-      memcpy(lc, &sv, sizeof(source_version_command));
-      lc += sizeof(source_version_command);
-    }
-
-    // If main executable, add LC_MAIN.
-    if (_file.fileType == llvm::MachO::MH_EXECUTE) {
-      // Build LC_MAIN load command.
-      // Note, using a temporary here to appease UB as we may not be aligned
-      // enough for a struct containing a uint64_t when emitting a 32-bit binary
-      entry_point_command ep;
-      ep.cmd       = LC_MAIN;
-      ep.cmdsize   = sizeof(entry_point_command);
-      ep.entryoff  = _file.entryAddress - _seg1addr;
-      ep.stacksize = _file.stackSize;
-      if (_swap)
-        swapStruct(ep);
-      memcpy(lc, &ep, sizeof(entry_point_command));
-      lc += sizeof(entry_point_command);
-    }
-
-    // Add LC_LOAD_DYLIB commands
-    for (const DependentDylib &dep : _file.dependentDylibs) {
-      dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
-      uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
-      dc->cmd                         = dep.kind;
-      dc->cmdsize                     = size;
-      dc->dylib.name                  = sizeof(dylib_command); // offset
-      // needs to be some constant value different than the one in LC_ID_DYLIB
-      dc->dylib.timestamp             = 2;
-      dc->dylib.current_version       = dep.currentVersion;
-      dc->dylib.compatibility_version = dep.compatVersion;
-      if (_swap)
-        swapStruct(*dc);
-      memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size());
-      lc[sizeof(dylib_command)+dep.path.size()] = '\0';
-      lc += size;
-    }
-
-    // Add LC_RPATH
-    for (const StringRef &path : _file.rpaths) {
-      rpath_command *rpc = reinterpret_cast<rpath_command *>(lc);
-      uint32_t size = pointerAlign(sizeof(rpath_command) + path.size() + 1);
-      rpc->cmd                         = LC_RPATH;
-      rpc->cmdsize                     = size;
-      rpc->path                        = sizeof(rpath_command); // offset
-      if (_swap)
-        swapStruct(*rpc);
-      memcpy(lc+sizeof(rpath_command), path.begin(), path.size());
-      lc[sizeof(rpath_command)+path.size()] = '\0';
-      lc += size;
-    }
-
-    // Add LC_FUNCTION_STARTS if needed.
-    if (_functionStartsSize != 0) {
-      linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
-      dl->cmd      = LC_FUNCTION_STARTS;
-      dl->cmdsize  = sizeof(linkedit_data_command);
-      dl->dataoff  = _startOfFunctionStarts;
-      dl->datasize = _functionStartsSize;
-      if (_swap)
-        swapStruct(*dl);
-      lc += sizeof(linkedit_data_command);
-    }
-
-    // Add LC_DATA_IN_CODE if requested.
-    if (_file.generateDataInCodeLoadCommand) {
-      linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
-      dl->cmd      = LC_DATA_IN_CODE;
-      dl->cmdsize  = sizeof(linkedit_data_command);
-      dl->dataoff  = _startOfDataInCode;
-      dl->datasize = _dataInCodeSize;
-      if (_swap)
-        swapStruct(*dl);
-      lc += sizeof(linkedit_data_command);
-    }
-  }
-  assert(lc == &_buffer[_endOfLoadCommands]);
-  return llvm::Error::success();
-}
-
-void MachOFileLayout::writeSectionContent() {
-  for (const Section &s : _file.sections) {
-    // Copy all section content to output buffer.
-    if (isZeroFillSection(s.type))
-      continue;
-    if (s.content.empty())
-      continue;
-    uint32_t offset = _sectInfo[&s].fileOffset;
-    assert(offset >= _endOfLoadCommands);
-    uint8_t *p = &_buffer[offset];
-    memcpy(p, &s.content[0], s.content.size());
-    p += s.content.size();
-  }
-}
-
-void MachOFileLayout::writeRelocations() {
-  uint32_t relOffset = _startOfRelocations;
-  for (Section sect : _file.sections) {
-    for (Relocation r : sect.relocations) {
-      any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
-                                                           &_buffer[relOffset]);
-      *rb = packRelocation(r, _swap, _bigEndianArch);
-      relOffset += sizeof(any_relocation_info);
-    }
-  }
-}
-
-void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
-                                   uint32_t &symOffset, uint32_t &strOffset) {
-  for (const Symbol &sym : symbols) {
-    if (_is64) {
-      nlist_64* nb = reinterpret_cast<nlist_64*>(&_buffer[symOffset]);
-      nb->n_strx = strOffset - _startOfSymbolStrings;
-      nb->n_type = sym.type | sym.scope;
-      nb->n_sect = sym.sect;
-      nb->n_desc = sym.desc;
-      nb->n_value = sym.value;
-      if (_swap)
-        swapStruct(*nb);
-      symOffset += sizeof(nlist_64);
-    } else {
-      nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
-      nb->n_strx = strOffset - _startOfSymbolStrings;
-      nb->n_type = sym.type | sym.scope;
-      nb->n_sect = sym.sect;
-      nb->n_desc = sym.desc;
-      nb->n_value = sym.value;
-      if (_swap)
-        swapStruct(*nb);
-      symOffset += sizeof(nlist);
-    }
-    memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
-    strOffset += sym.name.size();
-    _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
-  }
-}
-
-void MachOFileLayout::writeFunctionStartsInfo() {
-  if (!_functionStartsSize)
-    return;
-  memcpy(&_buffer[_startOfFunctionStarts], _file.functionStarts.data(),
-         _functionStartsSize);
-}
-
-void MachOFileLayout::writeDataInCodeInfo() {
-  uint32_t offset = _startOfDataInCode;
-  for (const DataInCode &entry : _file.dataInCode) {
-    data_in_code_entry *dst = reinterpret_cast<data_in_code_entry*>(
-                                                             &_buffer[offset]);
-    dst->offset = entry.offset;
-    dst->length = entry.length;
-    dst->kind   = entry.kind;
-    if (_swap)
-      swapStruct(*dst);
-    offset += sizeof(data_in_code_entry);
-  }
-}
-
-void MachOFileLayout::writeSymbolTable() {
-  // Write symbol table and symbol strings in parallel.
-  uint32_t symOffset = _startOfSymbols;
-  uint32_t strOffset = _startOfSymbolStrings;
-  // Reserve n_strx offset of zero to mean no name.
-  _buffer[strOffset++] = ' ';
-  _buffer[strOffset++] = '\0';
-  appendSymbols(_file.stabsSymbols, symOffset, strOffset);
-  appendSymbols(_file.localSymbols, symOffset, strOffset);
-  appendSymbols(_file.globalSymbols, symOffset, strOffset);
-  appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
-  // Write indirect symbol table array.
-  uint32_t *indirects = reinterpret_cast<uint32_t*>
-                                            (&_buffer[_startOfIndirectSymbols]);
-  if (_file.fileType == llvm::MachO::MH_OBJECT) {
-    // Object files have sections in same order as input normalized file.
-    for (const Section &section : _file.sections) {
-      for (uint32_t index : section.indirectSymbols) {
-        if (_swap)
-          *indirects++ = llvm::sys::getSwappedBytes(index);
-        else
-          *indirects++ = index;
-      }
-    }
-  } else {
-    // Final linked images must sort sections from normalized file.
-    for (const Segment &seg : _file.segments) {
-      SegExtraInfo &segInfo = _segInfo[&seg];
-      for (const Section *section : segInfo.sections) {
-        for (uint32_t index : section->indirectSymbols) {
-          if (_swap)
-            *indirects++ = llvm::sys::getSwappedBytes(index);
-          else
-            *indirects++ = index;
-        }
-      }
-    }
-  }
-}
-
-void MachOFileLayout::writeRebaseInfo() {
-  memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
-}
-
-void MachOFileLayout::writeBindingInfo() {
-  memcpy(&_buffer[_startOfBindingInfo],
-                                    _bindingInfo.bytes(), _bindingInfo.size());
-}
-
-void MachOFileLayout::writeLazyBindingInfo() {
-  memcpy(&_buffer[_startOfLazyBindingInfo],
-                            _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
-}
-
-void MachOFileLayout::writeExportInfo() {
-  memcpy(&_buffer[_startOfExportTrie], _exportTrie.bytes(), _exportTrie.size());
-}
-
-void MachOFileLayout::buildLinkEditInfo() {
-  buildRebaseInfo();
-  buildBindInfo();
-  buildLazyBindInfo();
-  buildExportTrie();
-  computeSymbolTableSizes();
-  computeFunctionStartsSize();
-  computeDataInCodeSize();
-}
-
-void MachOFileLayout::buildSectionRelocations() {
-
-}
-
-void MachOFileLayout::buildRebaseInfo() {
-  // TODO: compress rebasing info.
-  for (const RebaseLocation& entry : _file.rebasingInfo) {
-    _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
-    _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
-                            | entry.segIndex);
-    _rebaseInfo.append_uleb128(entry.segOffset);
-    _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
-  }
-  _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
-  _rebaseInfo.align(_is64 ? 8 : 4);
-}
-
-void MachOFileLayout::buildBindInfo() {
-  // TODO: compress bind info.
-  uint64_t lastAddend = 0;
-  int lastOrdinal = 0x80000000;
-  StringRef lastSymbolName;
-  BindType lastType = (BindType)0;
-  Hex32 lastSegOffset = ~0U;
-  uint8_t lastSegIndex = (uint8_t)~0U;
-  for (const BindLocation& entry : _file.bindingInfo) {
-    if (entry.ordinal != lastOrdinal) {
-      if (entry.ordinal <= 0)
-        _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
-                                 (entry.ordinal & BIND_IMMEDIATE_MASK));
-      else if (entry.ordinal <= BIND_IMMEDIATE_MASK)
-        _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
-                                 entry.ordinal);
-      else {
-        _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
-        _bindingInfo.append_uleb128(entry.ordinal);
-      }
-      lastOrdinal = entry.ordinal;
-    }
-
-    if (lastSymbolName != entry.symbolName) {
-      _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
-      _bindingInfo.append_string(entry.symbolName);
-      lastSymbolName = entry.symbolName;
-    }
-
-    if (lastType != entry.kind) {
-      _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
-      lastType = entry.kind;
-    }
-
-    if (lastSegIndex != entry.segIndex || lastSegOffset != entry.segOffset) {
-      _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
-                               | entry.segIndex);
-      _bindingInfo.append_uleb128(entry.segOffset);
-      lastSegIndex = entry.segIndex;
-      lastSegOffset = entry.segOffset;
-    }
-    if (entry.addend != lastAddend) {
-      _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
-      _bindingInfo.append_sleb128(entry.addend);
-      lastAddend = entry.addend;
-    }
-    _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
-  }
-  _bindingInfo.append_byte(BIND_OPCODE_DONE);
-  _bindingInfo.align(_is64 ? 8 : 4);
-}
-
-void MachOFileLayout::buildLazyBindInfo() {
-  for (const BindLocation& entry : _file.lazyBindingInfo) {
-    _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
-                            | entry.segIndex);
-    _lazyBindingInfo.append_uleb128(entry.segOffset);
-    if (entry.ordinal <= 0)
-      _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
-                                   (entry.ordinal & BIND_IMMEDIATE_MASK));
-    else if (entry.ordinal <= BIND_IMMEDIATE_MASK)
-      _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
-                                   entry.ordinal);
-    else {
-      _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
-      _lazyBindingInfo.append_uleb128(entry.ordinal);
-    }
-    // FIXME: We need to | the opcode here with flags.
-    _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
-    _lazyBindingInfo.append_string(entry.symbolName);
-    _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
-    _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
-  }
-  _lazyBindingInfo.align(_is64 ? 8 : 4);
-}
-
-void TrieNode::addSymbol(const Export& entry,
-                         BumpPtrAllocator &allocator,
-                         std::vector<TrieNode*> &allNodes) {
-  StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
-  for (TrieEdge &edge : _children) {
-    StringRef edgeStr = edge._subString;
-    if (partialStr.startswith(edgeStr)) {
-      // Already have matching edge, go down that path.
-      edge._child->addSymbol(entry, allocator, allNodes);
-      return;
-    }
-    // See if string has common prefix with existing edge.
-    for (int n=edgeStr.size()-1; n > 0; --n) {
-      if (partialStr.substr(0, n).equals(edgeStr.substr(0, n))) {
-        // Splice in new node:  was A -> C,  now A -> B -> C
-        StringRef bNodeStr = edge._child->_cummulativeString;
-        bNodeStr = bNodeStr.drop_back(edgeStr.size()-n).copy(allocator);
-        auto *bNode = new (allocator) TrieNode(bNodeStr);
-        allNodes.push_back(bNode);
-        TrieNode* cNode = edge._child;
-        StringRef abEdgeStr = edgeStr.substr(0,n).copy(allocator);
-        StringRef bcEdgeStr = edgeStr.substr(n).copy(allocator);
-        DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
-                        << "splice in TrieNode('" << bNodeStr
-                        << "') between edge '"
-                        << abEdgeStr << "' and edge='"
-                        << bcEdgeStr<< "'\n");
-        TrieEdge& abEdge = edge;
-        abEdge._subString = abEdgeStr;
-        abEdge._child = bNode;
-        auto *bcEdge = new (allocator) TrieEdge(bcEdgeStr, cNode);
-        bNode->_children.insert(bNode->_children.end(), bcEdge);
-        bNode->addSymbol(entry, allocator, allNodes);
-        return;
-      }
-    }
-  }
-  if (entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
-    assert(entry.otherOffset != 0);
-  }
-  if (entry.flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
-    assert(entry.otherOffset != 0);
-  }
-  // No commonality with any existing child, make a new edge.
-  auto *newNode = new (allocator) TrieNode(entry.name.copy(allocator));
-  auto *newEdge = new (allocator) TrieEdge(partialStr, newNode);
-  _children.insert(_children.end(), newEdge);
-  DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
-                   << "new TrieNode('" << entry.name << "') with edge '"
-                   << partialStr << "' from node='"
-                   << _cummulativeString << "'\n");
-  newNode->_address = entry.offset;
-  newNode->_flags = entry.flags | entry.kind;
-  newNode->_other = entry.otherOffset;
-  if ((entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) && !entry.otherName.empty())
-    newNode->_importedName = entry.otherName.copy(allocator);
-  newNode->_hasExportInfo = true;
-  allNodes.push_back(newNode);
-}
-
-void TrieNode::addOrderedNodes(const Export& entry,
-                               std::vector<TrieNode*> &orderedNodes) {
-  if (!_ordered) {
-    orderedNodes.push_back(this);
-    _ordered = true;
-  }
-
-  StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
-  for (TrieEdge &edge : _children) {
-    StringRef edgeStr = edge._subString;
-    if (partialStr.startswith(edgeStr)) {
-      // Already have matching edge, go down that path.
-      edge._child->addOrderedNodes(entry, orderedNodes);
-      return;
-    }
-  }
-}
-
-bool TrieNode::updateOffset(uint32_t& offset) {
-  uint32_t nodeSize = 1; // Length when no export info
-  if (_hasExportInfo) {
-    if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
-      nodeSize = llvm::getULEB128Size(_flags);
-      nodeSize += llvm::getULEB128Size(_other); // Other contains ordinal.
-      nodeSize += _importedName.size();
-      ++nodeSize; // Trailing zero in imported name.
-    } else {
-      nodeSize = llvm::getULEB128Size(_flags) + llvm::getULEB128Size(_address);
-      if (_flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
-        nodeSize += llvm::getULEB128Size(_other);
-    }
-    // Overall node size so far is uleb128 of export info + actual export info.
-    nodeSize += llvm::getULEB128Size(nodeSize);
-  }
-  // Compute size of all child edges.
-  ++nodeSize; // Byte for number of children.
-  for (TrieEdge &edge : _children) {
-    nodeSize += edge._subString.size() + 1 // String length.
-              + llvm::getULEB128Size(edge._child->_trieOffset); // Offset len.
-  }
-  // On input, 'offset' is new prefered location for this node.
-  bool result = (_trieOffset != offset);
-  // Store new location in node object for use by parents.
-  _trieOffset = offset;
-  // Update offset for next iteration.
-  offset += nodeSize;
-  // Return true if _trieOffset was changed.
-  return result;
-}
-
-void TrieNode::appendToByteBuffer(ByteBuffer &out) {
-  if (_hasExportInfo) {
-    if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
-      if (!_importedName.empty()) {
-        // nodes with re-export info: size, flags, ordinal, import-name
-        uint32_t nodeSize = llvm::getULEB128Size(_flags)
-                          + llvm::getULEB128Size(_other)
-                          + _importedName.size() + 1;
-        assert(nodeSize < 256);
-        out.append_byte(nodeSize);
-        out.append_uleb128(_flags);
-        out.append_uleb128(_other);
-        out.append_string(_importedName);
-      } else {
-        // nodes without re-export info: size, flags, ordinal, empty-string
-        uint32_t nodeSize = llvm::getULEB128Size(_flags)
-                          + llvm::getULEB128Size(_other) + 1;
-        assert(nodeSize < 256);
-        out.append_byte(nodeSize);
-        out.append_uleb128(_flags);
-        out.append_uleb128(_other);
-        out.append_byte(0);
-      }
-    } else if ( _flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER ) {
-      // Nodes with export info: size, flags, address, other
-      uint32_t nodeSize = llvm::getULEB128Size(_flags)
-                        + llvm::getULEB128Size(_address)
-                        + llvm::getULEB128Size(_other);
-      assert(nodeSize < 256);
-      out.append_byte(nodeSize);
-      out.append_uleb128(_flags);
-      out.append_uleb128(_address);
-      out.append_uleb128(_other);
-    } else {
-      // Nodes with export info: size, flags, address
-      uint32_t nodeSize = llvm::getULEB128Size(_flags)
-                        + llvm::getULEB128Size(_address);
-      assert(nodeSize < 256);
-      out.append_byte(nodeSize);
-      out.append_uleb128(_flags);
-      out.append_uleb128(_address);
-    }
-  } else {
-    // Node with no export info.
-    uint32_t nodeSize = 0;
-    out.append_byte(nodeSize);
-  }
-  // Add number of children.
-  assert(_children.size() < 256);
-  out.append_byte(_children.size());
-  // Append each child edge substring and node offset.
-  for (TrieEdge &edge : _children) {
-    out.append_string(edge._subString);
-    out.append_uleb128(edge._child->_trieOffset);
-  }
-}
-
-void MachOFileLayout::buildExportTrie() {
-  if (_file.exportInfo.empty())
-    return;
-
-  // For all temporary strings and objects used building trie.
-  BumpPtrAllocator allocator;
-
-  // Build trie of all exported symbols.
-  auto *rootNode = new (allocator) TrieNode(StringRef());
-  std::vector<TrieNode*> allNodes;
-  allNodes.reserve(_file.exportInfo.size()*2);
-  allNodes.push_back(rootNode);
-  for (const Export& entry : _file.exportInfo) {
-    rootNode->addSymbol(entry, allocator, allNodes);
-  }
-
-  std::vector<TrieNode*> orderedNodes;
-  orderedNodes.reserve(allNodes.size());
-
-  for (const Export& entry : _file.exportInfo)
-    rootNode->addOrderedNodes(entry, orderedNodes);
-
-  // Assign each node in the vector an offset in the trie stream, iterating
-  // until all uleb128 sizes have stabilized.
-  bool more;
-  do {
-    uint32_t offset = 0;
-    more = false;
-    for (TrieNode* node : orderedNodes) {
-      if (node->updateOffset(offset))
-        more = true;
-    }
-  } while (more);
-
-  // Serialize trie to ByteBuffer.
-  for (TrieNode* node : orderedNodes) {
-    node->appendToByteBuffer(_exportTrie);
-  }
-  _exportTrie.align(_is64 ? 8 : 4);
-}
-
-void MachOFileLayout::computeSymbolTableSizes() {
-  // MachO symbol tables have three ranges: locals, globals, and undefines
-  const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
-  _symbolTableSize = nlistSize * (_file.stabsSymbols.size()
-                                + _file.localSymbols.size()
-                                + _file.globalSymbols.size()
-                                + _file.undefinedSymbols.size());
-  // Always reserve 1-byte for the empty string and 1-byte for its terminator.
-  _symbolStringPoolSize = 2;
-  for (const Symbol &sym : _file.stabsSymbols) {
-    _symbolStringPoolSize += (sym.name.size()+1);
-  }
-  for (const Symbol &sym : _file.localSymbols) {
-    _symbolStringPoolSize += (sym.name.size()+1);
-  }
-  for (const Symbol &sym : _file.globalSymbols) {
-    _symbolStringPoolSize += (sym.name.size()+1);
-  }
-  for (const Symbol &sym : _file.undefinedSymbols) {
-    _symbolStringPoolSize += (sym.name.size()+1);
-  }
-  _symbolTableLocalsStartIndex = 0;
-  _symbolTableGlobalsStartIndex = _file.stabsSymbols.size() +
-                                  _file.localSymbols.size();
-  _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
-                                    + _file.globalSymbols.size();
-
-  _indirectSymbolTableCount = 0;
-  for (const Section &sect : _file.sections) {
-    _indirectSymbolTableCount += sect.indirectSymbols.size();
-  }
-}
-
-void MachOFileLayout::computeFunctionStartsSize() {
-  _functionStartsSize = _file.functionStarts.size();
-}
-
-void MachOFileLayout::computeDataInCodeSize() {
-  _dataInCodeSize = _file.dataInCode.size() * sizeof(data_in_code_entry);
-}
-
-void MachOFileLayout::writeLinkEditContent() {
-  if (_file.fileType == llvm::MachO::MH_OBJECT) {
-    writeRelocations();
-    writeFunctionStartsInfo();
-    writeDataInCodeInfo();
-    writeSymbolTable();
-  } else {
-    writeRebaseInfo();
-    writeBindingInfo();
-    writeLazyBindingInfo();
-    // TODO: add weak binding info
-    writeExportInfo();
-    writeFunctionStartsInfo();
-    writeDataInCodeInfo();
-    writeSymbolTable();
-  }
-}
-
-llvm::Error MachOFileLayout::writeBinary(StringRef path) {
-  // Check for pending error from constructor.
-  if (_ec)
-    return llvm::errorCodeToError(_ec);
-  // Create FileOutputBuffer with calculated size.
-  unsigned flags = 0;
-  if (_file.fileType != llvm::MachO::MH_OBJECT)
-    flags = llvm::FileOutputBuffer::F_executable;
-  Expected<std::unique_ptr<llvm::FileOutputBuffer>> fobOrErr =
-      llvm::FileOutputBuffer::create(path, size(), flags);
-  if (Error E = fobOrErr.takeError())
-    return E;
-  std::unique_ptr<llvm::FileOutputBuffer> &fob = *fobOrErr;
-  // Write content.
-  _buffer = fob->getBufferStart();
-  writeMachHeader();
-  if (auto ec = writeLoadCommands())
-    return ec;
-  writeSectionContent();
-  writeLinkEditContent();
-  if (Error E = fob->commit())
-    return E;
-
-  return llvm::Error::success();
-}
-
-/// Takes in-memory normalized view and writes a mach-o object file.
-llvm::Error writeBinary(const NormalizedFile &file, StringRef path) {
-  MachOFileLayout layout(file, false);
-  return layout.writeBinary(path);
-}
-
-} // namespace normalized
-} // namespace mach_o
-} // namespace lld
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
deleted file mode 100644 (file)
index ddfd176..0000000
+++ /dev/null
@@ -1,1657 +0,0 @@
-//===- lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp ------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-///
-/// \file Converts from in-memory Atoms to in-memory normalized mach-o.
-///
-///                  +------------+
-///                  | normalized |
-///                  +------------+
-///                        ^
-///                        |
-///                        |
-///                    +-------+
-///                    | Atoms |
-///                    +-------+
-
-#include "ArchHandler.h"
-#include "DebugInfo.h"
-#include "MachONormalizedFile.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/Error.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Format.h"
-#include <map>
-#include <system_error>
-#include <unordered_set>
-
-using llvm::StringRef;
-using llvm::isa;
-using namespace llvm::MachO;
-using namespace lld::mach_o::normalized;
-using namespace lld;
-
-namespace {
-
-struct AtomInfo {
-  const DefinedAtom  *atom;
-  uint64_t            offsetInSection;
-};
-
-struct SectionInfo {
-  SectionInfo(StringRef seg, StringRef sect, SectionType type,
-              const MachOLinkingContext &ctxt, uint32_t attr,
-              bool relocsToDefinedCanBeImplicit);
-
-  StringRef                 segmentName;
-  StringRef                 sectionName;
-  SectionType               type;
-  uint32_t                  attributes;
-  uint64_t                  address;
-  uint64_t                  size;
-  uint16_t                  alignment;
-
-  /// If this is set, the any relocs in this section which point to defined
-  /// addresses can be implicitly generated.  This is the case for the
-  /// __eh_frame section where references to the function can be implicit if the
-  /// function is defined.
-  bool                      relocsToDefinedCanBeImplicit;
-
-
-  std::vector<AtomInfo>     atomsAndOffsets;
-  uint32_t                  normalizedSectionIndex;
-  uint32_t                  finalSectionIndex;
-};
-
-SectionInfo::SectionInfo(StringRef sg, StringRef sct, SectionType t,
-                         const MachOLinkingContext &ctxt, uint32_t attrs,
-                         bool relocsToDefinedCanBeImplicit)
- : segmentName(sg), sectionName(sct), type(t), attributes(attrs),
-                 address(0), size(0), alignment(1),
-                 relocsToDefinedCanBeImplicit(relocsToDefinedCanBeImplicit),
-                 normalizedSectionIndex(0), finalSectionIndex(0) {
-  uint16_t align = 1;
-  if (ctxt.sectionAligned(segmentName, sectionName, align)) {
-    alignment = align;
-  }
-}
-
-struct SegmentInfo {
-  SegmentInfo(StringRef name);
-
-  StringRef                  name;
-  uint64_t                   address;
-  uint64_t                   size;
-  uint32_t                   init_access;
-  uint32_t                   max_access;
-  std::vector<SectionInfo*>  sections;
-  uint32_t                   normalizedSegmentIndex;
-};
-
-SegmentInfo::SegmentInfo(StringRef n)
- : name(n), address(0), size(0), init_access(0), max_access(0),
-   normalizedSegmentIndex(0) {
-}
-
-class Util {
-public:
-  Util(const MachOLinkingContext &ctxt)
-      : _ctx(ctxt), _archHandler(ctxt.archHandler()), _entryAtom(nullptr),
-        _hasTLVDescriptors(false), _subsectionsViaSymbols(true) {}
-  ~Util();
-
-  void      processDefinedAtoms(const lld::File &atomFile);
-  void      processAtomAttributes(const DefinedAtom *atom);
-  void      assignAtomToSection(const DefinedAtom *atom);
-  void      organizeSections();
-  void      assignAddressesToSections(const NormalizedFile &file);
-  uint32_t  fileFlags();
-  void      copySegmentInfo(NormalizedFile &file);
-  void      copySectionInfo(NormalizedFile &file);
-  void      updateSectionInfo(NormalizedFile &file);
-  void      buildAtomToAddressMap();
-  llvm::Error synthesizeDebugNotes(NormalizedFile &file);
-  llvm::Error addSymbols(const lld::File &atomFile, NormalizedFile &file);
-  void      addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file);
-  void      addRebaseAndBindingInfo(const lld::File &, NormalizedFile &file);
-  void      addExportInfo(const lld::File &, NormalizedFile &file);
-  void      addSectionRelocs(const lld::File &, NormalizedFile &file);
-  void      addFunctionStarts(const lld::File &, NormalizedFile &file);
-  void      buildDataInCodeArray(const lld::File &, NormalizedFile &file);
-  void      addDependentDylibs(const lld::File &, NormalizedFile &file);
-  void      copyEntryPointAddress(NormalizedFile &file);
-  void      copySectionContent(NormalizedFile &file);
-
-  bool allSourceFilesHaveMinVersions() const {
-    return _allSourceFilesHaveMinVersions;
-  }
-
-  uint32_t minVersion() const {
-    return _minVersion;
-  }
-
-  LoadCommandType minVersionCommandType() const {
-    return _minVersionCommandType;
-  }
-
-private:
-  typedef std::map<DefinedAtom::ContentType, SectionInfo*> TypeToSection;
-  typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
-
-  struct DylibInfo { int ordinal; bool hasWeak; bool hasNonWeak; };
-  typedef llvm::StringMap<DylibInfo> DylibPathToInfo;
-
-  SectionInfo *sectionForAtom(const DefinedAtom*);
-  SectionInfo *getRelocatableSection(DefinedAtom::ContentType type);
-  SectionInfo *getFinalSection(DefinedAtom::ContentType type);
-  void         appendAtom(SectionInfo *sect, const DefinedAtom *atom);
-  SegmentInfo *segmentForName(StringRef segName);
-  void         layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr);
-  void         layoutSectionsInTextSegment(size_t, SegmentInfo *, uint64_t &);
-  void         copySectionContent(SectionInfo *si, ContentBytes &content);
-  uint16_t     descBits(const DefinedAtom* atom);
-  int          dylibOrdinal(const SharedLibraryAtom *sa);
-  void         segIndexForSection(const SectionInfo *sect,
-                             uint8_t &segmentIndex, uint64_t &segmentStartAddr);
-  const Atom  *targetOfLazyPointer(const DefinedAtom *lpAtom);
-  const Atom  *targetOfStub(const DefinedAtom *stubAtom);
-  llvm::Error getSymbolTableRegion(const DefinedAtom* atom,
-                                   bool &inGlobalsRegion,
-                                   SymbolScope &symbolScope);
-  void         appendSection(SectionInfo *si, NormalizedFile &file);
-  uint32_t     sectionIndexForAtom(const Atom *atom);
-  void fixLazyReferenceImm(const DefinedAtom *atom, uint32_t offset,
-                           NormalizedFile &file);
-
-  typedef llvm::DenseMap<const Atom*, uint32_t> AtomToIndex;
-  struct AtomAndIndex { const Atom *atom; uint32_t index; SymbolScope scope; };
-  struct AtomSorter {
-    bool operator()(const AtomAndIndex &left, const AtomAndIndex &right);
-  };
-  struct SegmentSorter {
-    bool operator()(const SegmentInfo *left, const SegmentInfo *right);
-    static unsigned weight(const SegmentInfo *);
-  };
-  struct TextSectionSorter {
-    bool operator()(const SectionInfo *left, const SectionInfo *right);
-    static unsigned weight(const SectionInfo *);
-  };
-
-  const MachOLinkingContext &_ctx;
-  mach_o::ArchHandler          &_archHandler;
-  llvm::BumpPtrAllocator        _allocator;
-  std::vector<SectionInfo*>     _sectionInfos;
-  std::vector<SegmentInfo*>     _segmentInfos;
-  TypeToSection                 _sectionMap;
-  std::vector<SectionInfo*>     _customSections;
-  AtomToAddress                 _atomToAddress;
-  DylibPathToInfo               _dylibInfo;
-  const DefinedAtom            *_entryAtom;
-  AtomToIndex                   _atomToSymbolIndex;
-  std::vector<const Atom *>     _machHeaderAliasAtoms;
-  bool                          _hasTLVDescriptors;
-  bool                          _subsectionsViaSymbols;
-  bool                          _allSourceFilesHaveMinVersions = true;
-  LoadCommandType               _minVersionCommandType = (LoadCommandType)0;
-  uint32_t                      _minVersion = 0;
-  std::vector<lld::mach_o::Stab> _stabs;
-};
-
-Util::~Util() {
-  // The SectionInfo structs are BumpPtr allocated, but atomsAndOffsets needs
-  // to be deleted.
-  for (SectionInfo *si : _sectionInfos) {
-    // clear() destroys vector elements, but does not deallocate.
-    // Instead use swap() to deallocate vector buffer.
-    std::vector<AtomInfo> empty;
-    si->atomsAndOffsets.swap(empty);
-  }
-  // The SegmentInfo structs are BumpPtr allocated, but sections needs
-  // to be deleted.
-  for (SegmentInfo *sgi : _segmentInfos) {
-    std::vector<SectionInfo*> empty2;
-    sgi->sections.swap(empty2);
-  }
-}
-
-SectionInfo *Util::getRelocatableSection(DefinedAtom::ContentType type) {
-  StringRef segmentName;
-  StringRef sectionName;
-  SectionType sectionType;
-  SectionAttr sectionAttrs;
-  bool relocsToDefinedCanBeImplicit;
-
-  // Use same table used by when parsing .o files.
-  relocatableSectionInfoForContentType(type, segmentName, sectionName,
-                                       sectionType, sectionAttrs,
-                                       relocsToDefinedCanBeImplicit);
-  // If we already have a SectionInfo with this name, re-use it.
-  // This can happen if two ContentType map to the same mach-o section.
-  for (auto sect : _sectionMap) {
-    if (sect.second->sectionName.equals(sectionName) &&
-        sect.second->segmentName.equals(segmentName)) {
-      return sect.second;
-    }
-  }
-  // Otherwise allocate new SectionInfo object.
-  auto *sect = new (_allocator)
-      SectionInfo(segmentName, sectionName, sectionType, _ctx, sectionAttrs,
-                  relocsToDefinedCanBeImplicit);
-  _sectionInfos.push_back(sect);
-  _sectionMap[type] = sect;
-  return sect;
-}
-
-#define ENTRY(seg, sect, type, atomType) \
-  {seg, sect, type, DefinedAtom::atomType }
-
-struct MachOFinalSectionFromAtomType {
-  StringRef                 segmentName;
-  StringRef                 sectionName;
-  SectionType               sectionType;
-  DefinedAtom::ContentType  atomType;
-};
-
-const MachOFinalSectionFromAtomType sectsToAtomType[] = {
-  ENTRY("__TEXT", "__text",           S_REGULAR,          typeCode),
-  ENTRY("__TEXT", "__text",           S_REGULAR,          typeMachHeader),
-  ENTRY("__TEXT", "__cstring",        S_CSTRING_LITERALS, typeCString),
-  ENTRY("__TEXT", "__ustring",        S_REGULAR,          typeUTF16String),
-  ENTRY("__TEXT", "__const",          S_REGULAR,          typeConstant),
-  ENTRY("__TEXT", "__const",          S_4BYTE_LITERALS,   typeLiteral4),
-  ENTRY("__TEXT", "__const",          S_8BYTE_LITERALS,   typeLiteral8),
-  ENTRY("__TEXT", "__const",          S_16BYTE_LITERALS,  typeLiteral16),
-  ENTRY("__TEXT", "__stubs",          S_SYMBOL_STUBS,     typeStub),
-  ENTRY("__TEXT", "__stub_helper",    S_REGULAR,          typeStubHelper),
-  ENTRY("__TEXT", "__gcc_except_tab", S_REGULAR,          typeLSDA),
-  ENTRY("__TEXT", "__eh_frame",       S_COALESCED,        typeCFI),
-  ENTRY("__TEXT", "__unwind_info",    S_REGULAR,          typeProcessedUnwindInfo),
-  ENTRY("__DATA", "__data",           S_REGULAR,          typeData),
-  ENTRY("__DATA", "__const",          S_REGULAR,          typeConstData),
-  ENTRY("__DATA", "__cfstring",       S_REGULAR,          typeCFString),
-  ENTRY("__DATA", "__la_symbol_ptr",  S_LAZY_SYMBOL_POINTERS,
-                                                          typeLazyPointer),
-  ENTRY("__DATA", "__mod_init_func",  S_MOD_INIT_FUNC_POINTERS,
-                                                          typeInitializerPtr),
-  ENTRY("__DATA", "__mod_term_func",  S_MOD_TERM_FUNC_POINTERS,
-                                                          typeTerminatorPtr),
-  ENTRY("__DATA", "__got",            S_NON_LAZY_SYMBOL_POINTERS,
-                                                          typeGOT),
-  ENTRY("__DATA", "__nl_symbol_ptr",  S_NON_LAZY_SYMBOL_POINTERS,
-                                                          typeNonLazyPointer),
-  ENTRY("__DATA", "__thread_vars",    S_THREAD_LOCAL_VARIABLES,
-                                                          typeThunkTLV),
-  ENTRY("__DATA", "__thread_data",    S_THREAD_LOCAL_REGULAR,
-                                                          typeTLVInitialData),
-  ENTRY("__DATA", "__thread_ptrs",    S_THREAD_LOCAL_VARIABLE_POINTERS,
-                                                          typeTLVInitializerPtr),
-  ENTRY("__DATA", "__thread_bss",     S_THREAD_LOCAL_ZEROFILL,
-                                                         typeTLVInitialZeroFill),
-  ENTRY("__DATA", "__bss",            S_ZEROFILL,         typeZeroFill),
-  ENTRY("__DATA", "__interposing",    S_INTERPOSING,      typeInterposingTuples),
-};
-#undef ENTRY
-
-SectionInfo *Util::getFinalSection(DefinedAtom::ContentType atomType) {
-  for (auto &p : sectsToAtomType) {
-    if (p.atomType != atomType)
-      continue;
-    SectionAttr sectionAttrs = 0;
-    switch (atomType) {
-    case DefinedAtom::typeMachHeader:
-    case DefinedAtom::typeCode:
-    case DefinedAtom::typeStub:
-    case DefinedAtom::typeStubHelper:
-      sectionAttrs = S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS;
-      break;
-    case DefinedAtom::typeThunkTLV:
-      _hasTLVDescriptors = true;
-      break;
-    default:
-      break;
-    }
-    // If we already have a SectionInfo with this name, re-use it.
-    // This can happen if two ContentType map to the same mach-o section.
-    for (auto sect : _sectionMap) {
-      if (sect.second->sectionName.equals(p.sectionName) &&
-          sect.second->segmentName.equals(p.segmentName)) {
-        return sect.second;
-      }
-    }
-    // Otherwise allocate new SectionInfo object.
-    auto *sect = new (_allocator) SectionInfo(
-        p.segmentName, p.sectionName, p.sectionType, _ctx, sectionAttrs,
-        /* relocsToDefinedCanBeImplicit */ false);
-    _sectionInfos.push_back(sect);
-    _sectionMap[atomType] = sect;
-    return sect;
-  }
-  llvm_unreachable("content type not yet supported");
-}
-
-SectionInfo *Util::sectionForAtom(const DefinedAtom *atom) {
-  if (atom->sectionChoice() == DefinedAtom::sectionBasedOnContent) {
-    // Section for this atom is derived from content type.
-    DefinedAtom::ContentType type = atom->contentType();
-    auto pos = _sectionMap.find(type);
-    if ( pos != _sectionMap.end() )
-      return pos->second;
-    bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
-    return rMode ? getRelocatableSection(type) : getFinalSection(type);
-  } else {
-    // This atom needs to be in a custom section.
-    StringRef customName = atom->customSectionName();
-    // Look to see if we have already allocated the needed custom section.
-    for(SectionInfo *sect : _customSections) {
-      const DefinedAtom *firstAtom = sect->atomsAndOffsets.front().atom;
-      if (firstAtom->customSectionName().equals(customName)) {
-        return sect;
-      }
-    }
-    // Not found, so need to create a new custom section.
-    size_t seperatorIndex = customName.find('/');
-    assert(seperatorIndex != StringRef::npos);
-    StringRef segName = customName.slice(0, seperatorIndex);
-    StringRef sectName = customName.drop_front(seperatorIndex + 1);
-    auto *sect =
-        new (_allocator) SectionInfo(segName, sectName, S_REGULAR, _ctx,
-                                     0, /* relocsToDefinedCanBeImplicit */ false);
-    _customSections.push_back(sect);
-    _sectionInfos.push_back(sect);
-    return sect;
-  }
-}
-
-void Util::appendAtom(SectionInfo *sect, const DefinedAtom *atom) {
-  // Figure out offset for atom in this section given alignment constraints.
-  uint64_t offset = sect->size;
-  DefinedAtom::Alignment atomAlign = atom->alignment();
-  uint64_t align = atomAlign.value;
-  uint64_t requiredModulus = atomAlign.modulus;
-  uint64_t currentModulus = (offset % align);
-  if ( currentModulus != requiredModulus ) {
-    if ( requiredModulus > currentModulus )
-      offset += requiredModulus-currentModulus;
-    else
-      offset += align+requiredModulus-currentModulus;
-  }
-  // Record max alignment of any atom in this section.
-  if (align > sect->alignment)
-    sect->alignment = atomAlign.value;
-  // Assign atom to this section with this offset.
-  AtomInfo ai = {atom, offset};
-  sect->atomsAndOffsets.push_back(ai);
-  // Update section size to include this atom.
-  sect->size = offset + atom->size();
-}
-
-void Util::processDefinedAtoms(const lld::File &atomFile) {
-  for (const DefinedAtom *atom : atomFile.defined()) {
-    processAtomAttributes(atom);
-    assignAtomToSection(atom);
-  }
-}
-
-void Util::processAtomAttributes(const DefinedAtom *atom) {
-  if (auto *machoFile = dyn_cast<mach_o::MachOFile>(&atom->file())) {
-    // If the file doesn't use subsections via symbols, then make sure we don't
-    // add that flag to the final output file if we have a relocatable file.
-    if (!machoFile->subsectionsViaSymbols())
-      _subsectionsViaSymbols = false;
-
-    // All the source files must have min versions for us to output an object
-    // file with a min version.
-    if (auto v = machoFile->minVersion())
-      _minVersion = std::max(_minVersion, v);
-    else
-      _allSourceFilesHaveMinVersions = false;
-
-    // If we don't have a platform load command, but one of the source files
-    // does, then take the one from the file.
-    if (!_minVersionCommandType)
-      if (auto v = machoFile->minVersionLoadCommandKind())
-        _minVersionCommandType = v;
-  }
-}
-
-void Util::assignAtomToSection(const DefinedAtom *atom) {
-  if (atom->contentType() == DefinedAtom::typeMachHeader) {
-    _machHeaderAliasAtoms.push_back(atom);
-    // Assign atom to this section with this offset.
-    AtomInfo ai = {atom, 0};
-    sectionForAtom(atom)->atomsAndOffsets.push_back(ai);
-  } else if (atom->contentType() == DefinedAtom::typeDSOHandle)
-    _machHeaderAliasAtoms.push_back(atom);
-  else
-    appendAtom(sectionForAtom(atom), atom);
-}
-
-SegmentInfo *Util::segmentForName(StringRef segName) {
-  for (SegmentInfo *si : _segmentInfos) {
-    if ( si->name.equals(segName) )
-      return si;
-  }
-  auto *info = new (_allocator) SegmentInfo(segName);
-
-  // Set the initial segment protection.
-  if (segName.equals("__TEXT"))
-    info->init_access = VM_PROT_READ | VM_PROT_EXECUTE;
-  else if (segName.equals("__PAGEZERO"))
-    info->init_access = 0;
-  else if (segName.equals("__LINKEDIT"))
-    info->init_access = VM_PROT_READ;
-  else {
-    // All others default to read-write
-    info->init_access = VM_PROT_READ | VM_PROT_WRITE;
-  }
-
-  // Set max segment protection
-  // Note, its overkill to use a switch statement here, but makes it so much
-  // easier to use switch coverage to catch new cases.
-  switch (_ctx.os()) {
-    case lld::MachOLinkingContext::OS::unknown:
-    case lld::MachOLinkingContext::OS::macOSX:
-    case lld::MachOLinkingContext::OS::iOS_simulator:
-      if (segName.equals("__PAGEZERO")) {
-        info->max_access = 0;
-        break;
-      }
-      // All others default to all
-      info->max_access = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
-      break;
-    case lld::MachOLinkingContext::OS::iOS:
-      // iPhoneOS always uses same protection for max and initial
-      info->max_access = info->init_access;
-      break;
-  }
-  _segmentInfos.push_back(info);
-  return info;
-}
-
-unsigned Util::SegmentSorter::weight(const SegmentInfo *seg) {
- return llvm::StringSwitch<unsigned>(seg->name)
-    .Case("__PAGEZERO",  1)
-    .Case("__TEXT",      2)
-    .Case("__DATA",      3)
-    .Default(100);
-}
-
-bool Util::SegmentSorter::operator()(const SegmentInfo *left,
-                                  const SegmentInfo *right) {
-  return (weight(left) < weight(right));
-}
-
-unsigned Util::TextSectionSorter::weight(const SectionInfo *sect) {
- return llvm::StringSwitch<unsigned>(sect->sectionName)
-    .Case("__text",         1)
-    .Case("__stubs",        2)
-    .Case("__stub_helper",  3)
-    .Case("__const",        4)
-    .Case("__cstring",      5)
-    .Case("__unwind_info",  98)
-    .Case("__eh_frame",     99)
-    .Default(10);
-}
-
-bool Util::TextSectionSorter::operator()(const SectionInfo *left,
-                                         const SectionInfo *right) {
-  return (weight(left) < weight(right));
-}
-
-void Util::organizeSections() {
-  // NOTE!: Keep this in sync with assignAddressesToSections.
-  switch (_ctx.outputMachOType()) {
-    case llvm::MachO::MH_EXECUTE:
-      // Main executables, need a zero-page segment
-      segmentForName("__PAGEZERO");
-      // Fall into next case.
-      LLVM_FALLTHROUGH;
-    case llvm::MachO::MH_DYLIB:
-    case llvm::MachO::MH_BUNDLE:
-      // All dynamic code needs TEXT segment to hold the load commands.
-      segmentForName("__TEXT");
-      break;
-    default:
-      break;
-  }
-  segmentForName("__LINKEDIT");
-
-  // Group sections into segments.
-  for (SectionInfo *si : _sectionInfos) {
-    SegmentInfo *seg = segmentForName(si->segmentName);
-    seg->sections.push_back(si);
-  }
-  // Sort segments.
-  std::sort(_segmentInfos.begin(), _segmentInfos.end(), SegmentSorter());
-
-  // Sort sections within segments.
-  for (SegmentInfo *seg : _segmentInfos) {
-    if (seg->name.equals("__TEXT")) {
-      std::sort(seg->sections.begin(), seg->sections.end(),
-                TextSectionSorter());
-    }
-  }
-
-  // Record final section indexes.
-  uint32_t segmentIndex = 0;
-  uint32_t sectionIndex = 1;
-  for (SegmentInfo *seg : _segmentInfos) {
-    seg->normalizedSegmentIndex = segmentIndex++;
-    for (SectionInfo *sect : seg->sections)
-      sect->finalSectionIndex = sectionIndex++;
-  }
-}
-
-void Util::layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr) {
-  seg->address = addr;
-  for (SectionInfo *sect : seg->sections) {
-    sect->address = llvm::alignTo(addr, sect->alignment);
-    addr = sect->address + sect->size;
-  }
-  seg->size = llvm::alignTo(addr - seg->address, _ctx.pageSize());
-}
-
-// __TEXT segment lays out backwards so padding is at front after load commands.
-void Util::layoutSectionsInTextSegment(size_t hlcSize, SegmentInfo *seg,
-                                                               uint64_t &addr) {
-  seg->address = addr;
-  // Walks sections starting at end to calculate padding for start.
-  int64_t taddr = 0;
-  for (auto it = seg->sections.rbegin(); it != seg->sections.rend(); ++it) {
-    SectionInfo *sect = *it;
-    taddr -= sect->size;
-    taddr = taddr & (0 - sect->alignment);
-  }
-  int64_t padding = taddr - hlcSize;
-  while (padding < 0)
-    padding += _ctx.pageSize();
-  // Start assigning section address starting at padded offset.
-  addr += (padding + hlcSize);
-  for (SectionInfo *sect : seg->sections) {
-    sect->address = llvm::alignTo(addr, sect->alignment);
-    addr = sect->address + sect->size;
-  }
-  seg->size = llvm::alignTo(addr - seg->address, _ctx.pageSize());
-}
-
-void Util::assignAddressesToSections(const NormalizedFile &file) {
-  // NOTE!: Keep this in sync with organizeSections.
-  size_t hlcSize = headerAndLoadCommandsSize(file,
-                                      _ctx.generateFunctionStartsLoadCommand());
-  uint64_t address = 0;
-  for (SegmentInfo *seg : _segmentInfos) {
-    if (seg->name.equals("__PAGEZERO")) {
-      seg->size = _ctx.pageZeroSize();
-      address += seg->size;
-    }
-    else if (seg->name.equals("__TEXT")) {
-      // _ctx.baseAddress()  == 0 implies it was either unspecified or
-      // pageZeroSize is also 0. In either case resetting address is safe.
-      address = _ctx.baseAddress() ? _ctx.baseAddress() : address;
-      layoutSectionsInTextSegment(hlcSize, seg, address);
-    } else
-      layoutSectionsInSegment(seg, address);
-
-    address = llvm::alignTo(address, _ctx.pageSize());
-  }
-  DEBUG_WITH_TYPE("WriterMachO-norm",
-    llvm::dbgs() << "assignAddressesToSections()\n";
-    for (SegmentInfo *sgi : _segmentInfos) {
-      llvm::dbgs()  << "   address=" << llvm::format("0x%08llX", sgi->address)
-                    << ", size="  << llvm::format("0x%08llX", sgi->size)
-                    << ", segment-name='" << sgi->name
-                    << "'\n";
-      for (SectionInfo *si : sgi->sections) {
-        llvm::dbgs()<< "      addr="  << llvm::format("0x%08llX", si->address)
-                    << ", size="  << llvm::format("0x%08llX", si->size)
-                    << ", section-name='" << si->sectionName
-                    << "\n";
-      }
-    }
-  );
-}
-
-void Util::copySegmentInfo(NormalizedFile &file) {
-  for (SegmentInfo *sgi : _segmentInfos) {
-    Segment seg;
-    seg.name    = sgi->name;
-    seg.address = sgi->address;
-    seg.size    = sgi->size;
-    seg.init_access  = sgi->init_access;
-    seg.max_access  = sgi->max_access;
-    file.segments.push_back(seg);
-  }
-}
-
-void Util::appendSection(SectionInfo *si, NormalizedFile &file) {
-   // Add new empty section to end of file.sections.
-  Section temp;
-  file.sections.push_back(std::move(temp));
-  Section* normSect = &file.sections.back();
-  // Copy fields to normalized section.
-  normSect->segmentName   = si->segmentName;
-  normSect->sectionName   = si->sectionName;
-  normSect->type          = si->type;
-  normSect->attributes    = si->attributes;
-  normSect->address       = si->address;
-  normSect->alignment     = si->alignment;
-  // Record where normalized section is.
-  si->normalizedSectionIndex = file.sections.size()-1;
-}
-
-void Util::copySectionContent(NormalizedFile &file) {
-  const bool r = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
-
-  // Utility function for ArchHandler to find address of atom in output file.
-  auto addrForAtom = [&] (const Atom &atom) -> uint64_t {
-    auto pos = _atomToAddress.find(&atom);
-    assert(pos != _atomToAddress.end());
-    return pos->second;
-  };
-
-  auto sectionAddrForAtom = [&] (const Atom &atom) -> uint64_t {
-    for (const SectionInfo *sectInfo : _sectionInfos)
-      for (const AtomInfo &atomInfo : sectInfo->atomsAndOffsets)
-        if (atomInfo.atom == &atom)
-          return sectInfo->address;
-    llvm_unreachable("atom not assigned to section");
-  };
-
-  for (SectionInfo *si : _sectionInfos) {
-    Section *normSect = &file.sections[si->normalizedSectionIndex];
-    if (isZeroFillSection(si->type)) {
-      const uint8_t *empty = nullptr;
-      normSect->content = llvm::makeArrayRef(empty, si->size);
-      continue;
-    }
-    // Copy content from atoms to content buffer for section.
-    llvm::MutableArrayRef<uint8_t> sectionContent;
-    if (si->size) {
-      uint8_t *sectContent = file.ownedAllocations.Allocate<uint8_t>(si->size);
-      sectionContent = llvm::MutableArrayRef<uint8_t>(sectContent, si->size);
-      normSect->content = sectionContent;
-    }
-    for (AtomInfo &ai : si->atomsAndOffsets) {
-      if (!ai.atom->size()) {
-        assert(ai.atom->begin() == ai.atom->end() &&
-               "Cannot have references without content");
-        continue;
-      }
-      auto atomContent = sectionContent.slice(ai.offsetInSection,
-                                              ai.atom->size());
-      _archHandler.generateAtomContent(*ai.atom, r, addrForAtom,
-                                       sectionAddrForAtom, _ctx.baseAddress(),
-                                       atomContent);
-    }
-  }
-}
-
-void Util::copySectionInfo(NormalizedFile &file) {
-  file.sections.reserve(_sectionInfos.size());
-  // Write sections grouped by segment.
-  for (SegmentInfo *sgi : _segmentInfos) {
-    for (SectionInfo *si : sgi->sections) {
-      appendSection(si, file);
-    }
-  }
-}
-
-void Util::updateSectionInfo(NormalizedFile &file) {
-  file.sections.reserve(_sectionInfos.size());
-  // sections grouped by segment.
-  for (SegmentInfo *sgi : _segmentInfos) {
-    Segment *normSeg = &file.segments[sgi->normalizedSegmentIndex];
-    normSeg->address = sgi->address;
-    normSeg->size = sgi->size;
-    for (SectionInfo *si : sgi->sections) {
-      Section *normSect = &file.sections[si->normalizedSectionIndex];
-      normSect->address = si->address;
-    }
-  }
-}
-
-void Util::copyEntryPointAddress(NormalizedFile &nFile) {
-  if (!_entryAtom) {
-    nFile.entryAddress = 0;
-    return;
-  }
-
-  if (_ctx.outputTypeHasEntry()) {
-    if (_archHandler.isThumbFunction(*_entryAtom))
-      nFile.entryAddress = (_atomToAddress[_entryAtom] | 1);
-    else
-      nFile.entryAddress = _atomToAddress[_entryAtom];
-  }
-}
-
-void Util::buildAtomToAddressMap() {
-  DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
-                   << "assign atom addresses:\n");
-  const bool lookForEntry = _ctx.outputTypeHasEntry();
-  for (SectionInfo *sect : _sectionInfos) {
-    for (const AtomInfo &info : sect->atomsAndOffsets) {
-      _atomToAddress[info.atom] = sect->address + info.offsetInSection;
-      if (lookForEntry && (info.atom->contentType() == DefinedAtom::typeCode) &&
-          (info.atom->size() != 0) &&
-          info.atom->name() == _ctx.entrySymbolName()) {
-        _entryAtom = info.atom;
-      }
-      DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
-                      << "   address="
-                      << llvm::format("0x%016X", _atomToAddress[info.atom])
-                      << llvm::format("    0x%09lX", info.atom)
-                      << ", file=#"
-                      << info.atom->file().ordinal()
-                      << ", atom=#"
-                      << info.atom->ordinal()
-                      << ", name="
-                      << info.atom->name()
-                      << ", type="
-                      << info.atom->contentType()
-                      << "\n");
-    }
-  }
-  DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
-                  << "assign header alias atom addresses:\n");
-  for (const Atom *atom : _machHeaderAliasAtoms) {
-    _atomToAddress[atom] = _ctx.baseAddress();
-#ifndef NDEBUG
-    if (auto *definedAtom = dyn_cast<DefinedAtom>(atom)) {
-      DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
-                      << "   address="
-                      << llvm::format("0x%016X", _atomToAddress[atom])
-                      << llvm::format("    0x%09lX", atom)
-                      << ", file=#"
-                      << definedAtom->file().ordinal()
-                      << ", atom=#"
-                      << definedAtom->ordinal()
-                      << ", name="
-                      << definedAtom->name()
-                      << ", type="
-                      << definedAtom->contentType()
-                      << "\n");
-    } else {
-      DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
-                      << "   address="
-                      << llvm::format("0x%016X", _atomToAddress[atom])
-                      << " atom=" << atom
-                      << " name=" << atom->name() << "\n");
-    }
-#endif
-  }
-}
-
-llvm::Error Util::synthesizeDebugNotes(NormalizedFile &file) {
-
-  // Bail out early if we don't need to generate a debug map.
-  if (_ctx.debugInfoMode() == MachOLinkingContext::DebugInfoMode::noDebugMap)
-    return llvm::Error::success();
-
-  std::vector<const DefinedAtom*> atomsNeedingDebugNotes;
-  std::set<const mach_o::MachOFile*> filesWithStabs;
-  bool objFileHasDwarf = false;
-  const File *objFile = nullptr;
-
-  for (SectionInfo *sect : _sectionInfos) {
-    for (const AtomInfo &info : sect->atomsAndOffsets) {
-      if (const DefinedAtom *atom = dyn_cast<DefinedAtom>(info.atom)) {
-
-        // FIXME: No stabs/debug-notes for symbols that wouldn't be in the
-        //        symbol table.
-        // FIXME: No stabs/debug-notes for kernel dtrace probes.
-
-        if (atom->contentType() == DefinedAtom::typeCFI ||
-            atom->contentType() == DefinedAtom::typeCString)
-          continue;
-
-        // Whenever we encounter a new file, update the 'objfileHasDwarf' flag.
-        if (&info.atom->file() != objFile) {
-          objFileHasDwarf = false;
-          if (const mach_o::MachOFile *atomFile =
-              dyn_cast<mach_o::MachOFile>(&info.atom->file())) {
-            if (atomFile->debugInfo()) {
-              if (isa<mach_o::DwarfDebugInfo>(atomFile->debugInfo()))
-                objFileHasDwarf = true;
-              else if (isa<mach_o::StabsDebugInfo>(atomFile->debugInfo()))
-                filesWithStabs.insert(atomFile);
-            }
-          }
-        }
-
-        // If this atom is from a file that needs dwarf, add it to the list.
-        if (objFileHasDwarf)
-          atomsNeedingDebugNotes.push_back(info.atom);
-      }
-    }
-  }
-
-  // Sort atoms needing debug notes by file ordinal, then atom ordinal.
-  std::sort(atomsNeedingDebugNotes.begin(), atomsNeedingDebugNotes.end(),
-            [](const DefinedAtom *lhs, const DefinedAtom *rhs) {
-              if (lhs->file().ordinal() != rhs->file().ordinal())
-                return (lhs->file().ordinal() < rhs->file().ordinal());
-              return (lhs->ordinal() < rhs->ordinal());
-            });
-
-  // FIXME: Handle <rdar://problem/17689030>: Add -add_ast_path option to \
-  //        linker which add N_AST stab entry to output
-  // See OutputFile::synthesizeDebugNotes in ObjectFile.cpp in ld64.
-
-  StringRef oldFileName = "";
-  StringRef oldDirPath = "";
-  bool wroteStartSO = false;
-  std::unordered_set<std::string> seenFiles;
-  for (const DefinedAtom *atom : atomsNeedingDebugNotes) {
-    const auto &atomFile = cast<mach_o::MachOFile>(atom->file());
-    assert(dyn_cast_or_null<lld::mach_o::DwarfDebugInfo>(atomFile.debugInfo())
-           && "file for atom needing debug notes does not contain dwarf");
-    auto &dwarf = cast<lld::mach_o::DwarfDebugInfo>(*atomFile.debugInfo());
-
-    auto &tu = dwarf.translationUnitSource();
-    StringRef newFileName = tu.name;
-    StringRef newDirPath = tu.path;
-
-    // Add an SO whenever the TU source file changes.
-    if (newFileName != oldFileName || newDirPath != oldDirPath) {
-      // Translation unit change, emit ending SO
-      if (oldFileName != "")
-        _stabs.push_back(mach_o::Stab(nullptr, N_SO, 1, 0, 0, ""));
-
-      oldFileName = newFileName;
-      oldDirPath = newDirPath;
-
-      // If newDirPath doesn't end with a '/' we need to add one:
-      if (newDirPath.back() != '/') {
-        char *p =
-          file.ownedAllocations.Allocate<char>(newDirPath.size() + 2);
-        memcpy(p, newDirPath.data(), newDirPath.size());
-        p[newDirPath.size()] = '/';
-        p[newDirPath.size() + 1] = '\0';
-        newDirPath = p;
-      }
-
-      // New translation unit, emit start SOs:
-      _stabs.push_back(mach_o::Stab(nullptr, N_SO, 0, 0, 0, newDirPath));
-      _stabs.push_back(mach_o::Stab(nullptr, N_SO, 0, 0, 0, newFileName));
-
-      // Synthesize OSO for start of file.
-      char *fullPath = nullptr;
-      {
-        SmallString<1024> pathBuf(atomFile.path());
-        if (auto EC = llvm::sys::fs::make_absolute(pathBuf))
-          return llvm::errorCodeToError(EC);
-        fullPath = file.ownedAllocations.Allocate<char>(pathBuf.size() + 1);
-        memcpy(fullPath, pathBuf.c_str(), pathBuf.size() + 1);
-      }
-
-      // Get mod time.
-      uint32_t modTime = 0;
-      llvm::sys::fs::file_status stat;
-      if (!llvm::sys::fs::status(fullPath, stat))
-        if (llvm::sys::fs::exists(stat))
-          modTime = llvm::sys::toTimeT(stat.getLastModificationTime());
-
-      _stabs.push_back(mach_o::Stab(nullptr, N_OSO, _ctx.getCPUSubType(), 1,
-                                    modTime, fullPath));
-      // <rdar://problem/6337329> linker should put cpusubtype in n_sect field
-      // of nlist entry for N_OSO debug note entries.
-      wroteStartSO = true;
-    }
-
-    if (atom->contentType() == DefinedAtom::typeCode) {
-      // Synthesize BNSYM and start FUN stabs.
-      _stabs.push_back(mach_o::Stab(atom, N_BNSYM, 1, 0, 0, ""));
-      _stabs.push_back(mach_o::Stab(atom, N_FUN, 1, 0, 0, atom->name()));
-      // Synthesize any SOL stabs needed
-      // FIXME: add SOL stabs.
-      _stabs.push_back(mach_o::Stab(nullptr, N_FUN, 0, 0,
-                                    atom->rawContent().size(), ""));
-      _stabs.push_back(mach_o::Stab(nullptr, N_ENSYM, 1, 0,
-                                    atom->rawContent().size(), ""));
-    } else {
-      if (atom->scope() == Atom::scopeTranslationUnit)
-        _stabs.push_back(mach_o::Stab(atom, N_STSYM, 1, 0, 0, atom->name()));
-      else
-        _stabs.push_back(mach_o::Stab(nullptr, N_GSYM, 1, 0, 0, atom->name()));
-    }
-  }
-
-  // Emit ending SO if necessary.
-  if (wroteStartSO)
-    _stabs.push_back(mach_o::Stab(nullptr, N_SO, 1, 0, 0, ""));
-
-  // Copy any stabs from .o file.
-  for (const auto *objFile : filesWithStabs) {
-    const auto &stabsList =
-      cast<mach_o::StabsDebugInfo>(objFile->debugInfo())->stabs();
-    for (auto &stab : stabsList) {
-      // FIXME: Drop stabs whose atoms have been dead-stripped.
-      _stabs.push_back(stab);
-    }
-  }
-
-  return llvm::Error::success();
-}
-
-uint16_t Util::descBits(const DefinedAtom* atom) {
-  uint16_t desc = 0;
-  switch (atom->merge()) {
-  case lld::DefinedAtom::mergeNo:
-  case lld::DefinedAtom::mergeAsTentative:
-    break;
-  case lld::DefinedAtom::mergeAsWeak:
-  case lld::DefinedAtom::mergeAsWeakAndAddressUsed:
-    desc |= N_WEAK_DEF;
-    break;
-  case lld::DefinedAtom::mergeSameNameAndSize:
-  case lld::DefinedAtom::mergeByLargestSection:
-  case lld::DefinedAtom::mergeByContent:
-    llvm_unreachable("Unsupported DefinedAtom::merge()");
-    break;
-  }
-  if (atom->contentType() == lld::DefinedAtom::typeResolver)
-    desc |= N_SYMBOL_RESOLVER;
-  if (atom->contentType() == lld::DefinedAtom::typeMachHeader)
-    desc |= REFERENCED_DYNAMICALLY;
-  if (_archHandler.isThumbFunction(*atom))
-    desc |= N_ARM_THUMB_DEF;
-  if (atom->deadStrip() == DefinedAtom::deadStripNever &&
-      _ctx.outputMachOType() == llvm::MachO::MH_OBJECT) {
-    if ((atom->contentType() != DefinedAtom::typeInitializerPtr)
-     && (atom->contentType() != DefinedAtom::typeTerminatorPtr))
-    desc |= N_NO_DEAD_STRIP;
-  }
-  return desc;
-}
-
-bool Util::AtomSorter::operator()(const AtomAndIndex &left,
-                                  const AtomAndIndex &right) {
-  return (left.atom->name().compare(right.atom->name()) < 0);
-}
-
-llvm::Error Util::getSymbolTableRegion(const DefinedAtom* atom,
-                                       bool &inGlobalsRegion,
-                                       SymbolScope &scope) {
-  bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
-  switch (atom->scope()) {
-  case Atom::scopeTranslationUnit:
-    scope = 0;
-    inGlobalsRegion = false;
-    return llvm::Error::success();
-  case Atom::scopeLinkageUnit:
-    if ((_ctx.exportMode() == MachOLinkingContext::ExportMode::exported) &&
-        _ctx.exportSymbolNamed(atom->name())) {
-      return llvm::make_error<GenericError>(
-                          Twine("cannot export hidden symbol ") + atom->name());
-    }
-    if (rMode) {
-      if (_ctx.keepPrivateExterns()) {
-        // -keep_private_externs means keep in globals region as N_PEXT.
-        scope = N_PEXT | N_EXT;
-        inGlobalsRegion = true;
-        return llvm::Error::success();
-      }
-    }
-    // scopeLinkageUnit symbols are no longer global once linked.
-    scope = N_PEXT;
-    inGlobalsRegion = false;
-    return llvm::Error::success();
-  case Atom::scopeGlobal:
-    if (_ctx.exportRestrictMode()) {
-      if (_ctx.exportSymbolNamed(atom->name())) {
-        scope = N_EXT;
-        inGlobalsRegion = true;
-        return llvm::Error::success();
-      } else {
-        scope = N_PEXT;
-        inGlobalsRegion = false;
-        return llvm::Error::success();
-      }
-    } else {
-      scope = N_EXT;
-      inGlobalsRegion = true;
-      return llvm::Error::success();
-    }
-    break;
-  }
-  llvm_unreachable("atom->scope() unknown enum value");
-}
-
-
-
-llvm::Error Util::addSymbols(const lld::File &atomFile,
-                             NormalizedFile &file) {
-  bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
-  // Mach-O symbol table has four regions: stabs, locals, globals, undefs.
-
-  // Add all stabs.
-  for (auto &stab : _stabs) {
-    lld::mach_o::normalized::Symbol sym;
-    sym.type = static_cast<NListType>(stab.type);
-    sym.scope = 0;
-    sym.sect = stab.other;
-    sym.desc = stab.desc;
-    if (stab.atom)
-      sym.value = _atomToAddress[stab.atom];
-    else
-      sym.value = stab.value;
-    sym.name = stab.str;
-    file.stabsSymbols.push_back(sym);
-  }
-
-  // Add all local (non-global) symbols in address order
-  std::vector<AtomAndIndex> globals;
-  globals.reserve(512);
-  for (SectionInfo *sect : _sectionInfos) {
-    for (const AtomInfo &info : sect->atomsAndOffsets) {
-      const DefinedAtom *atom = info.atom;
-      if (!atom->name().empty()) {
-        SymbolScope symbolScope;
-        bool inGlobalsRegion;
-        if (auto ec = getSymbolTableRegion(atom, inGlobalsRegion, symbolScope)){
-          return ec;
-        }
-        if (inGlobalsRegion) {
-          AtomAndIndex ai = { atom, sect->finalSectionIndex, symbolScope };
-          globals.push_back(ai);
-        } else {
-          lld::mach_o::normalized::Symbol sym;
-          sym.name  = atom->name();
-          sym.type  = N_SECT;
-          sym.scope = symbolScope;
-          sym.sect  = sect->finalSectionIndex;
-          sym.desc  = descBits(atom);
-          sym.value = _atomToAddress[atom];
-          _atomToSymbolIndex[atom] = file.localSymbols.size();
-          file.localSymbols.push_back(sym);
-        }
-      } else if (rMode && _archHandler.needsLocalSymbolInRelocatableFile(atom)){
-        // Create 'Lxxx' labels for anonymous atoms if archHandler says so.
-        static unsigned tempNum = 1;
-        char tmpName[16];
-        sprintf(tmpName, "L%04u", tempNum++);
-        StringRef tempRef(tmpName);
-        lld::mach_o::normalized::Symbol sym;
-        sym.name  = tempRef.copy(file.ownedAllocations);
-        sym.type  = N_SECT;
-        sym.scope = 0;
-        sym.sect  = sect->finalSectionIndex;
-        sym.desc  = 0;
-        sym.value = _atomToAddress[atom];
-        _atomToSymbolIndex[atom] = file.localSymbols.size();
-        file.localSymbols.push_back(sym);
-      }
-    }
-  }
-
-  // Sort global symbol alphabetically, then add to symbol table.
-  std::sort(globals.begin(), globals.end(), AtomSorter());
-  const uint32_t globalStartIndex = file.localSymbols.size();
-  for (AtomAndIndex &ai : globals) {
-    lld::mach_o::normalized::Symbol sym;
-    sym.name  = ai.atom->name();
-    sym.type  = N_SECT;
-    sym.scope = ai.scope;
-    sym.sect  = ai.index;
-    sym.desc  = descBits(static_cast<const DefinedAtom*>(ai.atom));
-    sym.value = _atomToAddress[ai.atom];
-    _atomToSymbolIndex[ai.atom] = globalStartIndex + file.globalSymbols.size();
-    file.globalSymbols.push_back(sym);
-  }
-
-  // Sort undefined symbol alphabetically, then add to symbol table.
-  std::vector<AtomAndIndex> undefs;
-  undefs.reserve(128);
-  for (const UndefinedAtom *atom : atomFile.undefined()) {
-    AtomAndIndex ai = { atom, 0, N_EXT };
-    undefs.push_back(ai);
-  }
-  for (const SharedLibraryAtom *atom : atomFile.sharedLibrary()) {
-    AtomAndIndex ai = { atom, 0, N_EXT };
-    undefs.push_back(ai);
-  }
-  std::sort(undefs.begin(), undefs.end(), AtomSorter());
-  const uint32_t start = file.globalSymbols.size() + file.localSymbols.size();
-  for (AtomAndIndex &ai : undefs) {
-    lld::mach_o::normalized::Symbol sym;
-    uint16_t desc = 0;
-    if (!rMode) {
-      uint8_t ordinal = 0;
-      if (!_ctx.useFlatNamespace())
-        ordinal = dylibOrdinal(dyn_cast<SharedLibraryAtom>(ai.atom));
-      llvm::MachO::SET_LIBRARY_ORDINAL(desc, ordinal);
-    }
-    sym.name  = ai.atom->name();
-    sym.type  = N_UNDF;
-    sym.scope = ai.scope;
-    sym.sect  = 0;
-    sym.desc  = desc;
-    sym.value = 0;
-    _atomToSymbolIndex[ai.atom] = file.undefinedSymbols.size() + start;
-    file.undefinedSymbols.push_back(sym);
-  }
-
-  return llvm::Error::success();
-}
-
-const Atom *Util::targetOfLazyPointer(const DefinedAtom *lpAtom) {
-  for (const Reference *ref : *lpAtom) {
-    if (_archHandler.isLazyPointer(*ref)) {
-      return ref->target();
-    }
-  }
-  return nullptr;
-}
-
-const Atom *Util::targetOfStub(const DefinedAtom *stubAtom) {
-  for (const Reference *ref : *stubAtom) {
-    if (const Atom *ta = ref->target()) {
-      if (const DefinedAtom *lpAtom = dyn_cast<DefinedAtom>(ta)) {
-        const Atom *target = targetOfLazyPointer(lpAtom);
-        if (target)
-          return target;
-      }
-    }
-  }
-  return nullptr;
-}
-
-void Util::addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file) {
-  for (SectionInfo *si : _sectionInfos) {
-    Section &normSect = file.sections[si->normalizedSectionIndex];
-    switch (si->type) {
-    case llvm::MachO::S_NON_LAZY_SYMBOL_POINTERS:
-      for (const AtomInfo &info : si->atomsAndOffsets) {
-        bool foundTarget = false;
-        for (const Reference *ref : *info.atom) {
-          const Atom *target = ref->target();
-          if (target) {
-            if (isa<const SharedLibraryAtom>(target)) {
-              uint32_t index = _atomToSymbolIndex[target];
-              normSect.indirectSymbols.push_back(index);
-              foundTarget = true;
-            } else {
-              normSect.indirectSymbols.push_back(
-                                            llvm::MachO::INDIRECT_SYMBOL_LOCAL);
-            }
-          }
-        }
-        if (!foundTarget) {
-          normSect.indirectSymbols.push_back(
-                                             llvm::MachO::INDIRECT_SYMBOL_ABS);
-        }
-      }
-      break;
-    case llvm::MachO::S_LAZY_SYMBOL_POINTERS:
-      for (const AtomInfo &info : si->atomsAndOffsets) {
-        const Atom *target = targetOfLazyPointer(info.atom);
-        if (target) {
-          uint32_t index = _atomToSymbolIndex[target];
-          normSect.indirectSymbols.push_back(index);
-        }
-      }
-      break;
-    case llvm::MachO::S_SYMBOL_STUBS:
-      for (const AtomInfo &info : si->atomsAndOffsets) {
-        const Atom *target = targetOfStub(info.atom);
-        if (target) {
-          uint32_t index = _atomToSymbolIndex[target];
-          normSect.indirectSymbols.push_back(index);
-        }
-      }
-      break;
-    default:
-      break;
-    }
-  }
-}
-
-void Util::addDependentDylibs(const lld::File &atomFile,
-                              NormalizedFile &nFile) {
-  // Scan all imported symbols and build up list of dylibs they are from.
-  int ordinal = 1;
-  for (const auto *dylib : _ctx.allDylibs()) {
-    DylibPathToInfo::iterator pos = _dylibInfo.find(dylib->installName());
-    if (pos == _dylibInfo.end()) {
-      DylibInfo info;
-      bool flatNamespaceAtom = dylib == _ctx.flatNamespaceFile();
-
-      // If we're in -flat_namespace mode (or this atom came from the flat
-      // namespace file under -undefined dynamic_lookup) then use the flat
-      // lookup ordinal.
-      if (flatNamespaceAtom || _ctx.useFlatNamespace())
-        info.ordinal = BIND_SPECIAL_DYLIB_FLAT_LOOKUP;
-      else
-        info.ordinal = ordinal++;
-      info.hasWeak = false;
-      info.hasNonWeak = !info.hasWeak;
-      _dylibInfo[dylib->installName()] = info;
-
-      // Unless this was a flat_namespace atom, record the source dylib.
-      if (!flatNamespaceAtom) {
-        DependentDylib depInfo;
-        depInfo.path = dylib->installName();
-        depInfo.kind = llvm::MachO::LC_LOAD_DYLIB;
-        depInfo.currentVersion = _ctx.dylibCurrentVersion(dylib->path());
-        depInfo.compatVersion = _ctx.dylibCompatVersion(dylib->path());
-        nFile.dependentDylibs.push_back(depInfo);
-      }
-    } else {
-      pos->second.hasWeak = false;
-      pos->second.hasNonWeak = !pos->second.hasWeak;
-    }
-  }
-  // Automatically weak link dylib in which all symbols are weak (canBeNull).
-  for (DependentDylib &dep : nFile.dependentDylibs) {
-    DylibInfo &info = _dylibInfo[dep.path];
-    if (info.hasWeak && !info.hasNonWeak)
-      dep.kind = llvm::MachO::LC_LOAD_WEAK_DYLIB;
-    else if (_ctx.isUpwardDylib(dep.path))
-      dep.kind = llvm::MachO::LC_LOAD_UPWARD_DYLIB;
-  }
-}
-
-int Util::dylibOrdinal(const SharedLibraryAtom *sa) {
-  return _dylibInfo[sa->loadName()].ordinal;
-}
-
-void Util::segIndexForSection(const SectionInfo *sect, uint8_t &segmentIndex,
-                                                  uint64_t &segmentStartAddr) {
-  segmentIndex = 0;
-  for (const SegmentInfo *seg : _segmentInfos) {
-    if ((seg->address <= sect->address)
-      && (seg->address+seg->size >= sect->address+sect->size)) {
-      segmentStartAddr = seg->address;
-      return;
-    }
-    ++segmentIndex;
-  }
-  llvm_unreachable("section not in any segment");
-}
-
-uint32_t Util::sectionIndexForAtom(const Atom *atom) {
-  uint64_t address = _atomToAddress[atom];
-  for (const SectionInfo *si : _sectionInfos) {
-    if ((si->address <= address) && (address < si->address+si->size))
-      return si->finalSectionIndex;
-  }
-  llvm_unreachable("atom not in any section");
-}
-
-void Util::addSectionRelocs(const lld::File &, NormalizedFile &file) {
-  if (_ctx.outputMachOType() != llvm::MachO::MH_OBJECT)
-    return;
-
-  // Utility function for ArchHandler to find symbol index for an atom.
-  auto symIndexForAtom = [&] (const Atom &atom) -> uint32_t {
-    auto pos = _atomToSymbolIndex.find(&atom);
-    assert(pos != _atomToSymbolIndex.end());
-    return pos->second;
-  };
-
-  // Utility function for ArchHandler to find section index for an atom.
-  auto sectIndexForAtom = [&] (const Atom &atom) -> uint32_t {
-    return sectionIndexForAtom(&atom);
-  };
-
-  // Utility function for ArchHandler to find address of atom in output file.
-  auto addressForAtom = [&] (const Atom &atom) -> uint64_t {
-    auto pos = _atomToAddress.find(&atom);
-    assert(pos != _atomToAddress.end());
-    return pos->second;
-  };
-
-  for (SectionInfo *si : _sectionInfos) {
-    Section &normSect = file.sections[si->normalizedSectionIndex];
-    for (const AtomInfo &info : si->atomsAndOffsets) {
-      const DefinedAtom *atom = info.atom;
-      for (const Reference *ref : *atom) {
-        // Skip emitting relocs for sections which are always able to be
-        // implicitly regenerated and where the relocation targets an address
-        // which is defined.
-        if (si->relocsToDefinedCanBeImplicit && isa<DefinedAtom>(ref->target()))
-          continue;
-        _archHandler.appendSectionRelocations(*atom, info.offsetInSection, *ref,
-                                              symIndexForAtom,
-                                              sectIndexForAtom,
-                                              addressForAtom,
-                                              normSect.relocations);
-      }
-    }
-  }
-}
-
-void Util::addFunctionStarts(const lld::File &, NormalizedFile &file) {
-  if (!_ctx.generateFunctionStartsLoadCommand())
-    return;
-  file.functionStarts.reserve(8192);
-  // Delta compress function starts, starting with the mach header symbol.
-  const uint64_t badAddress = ~0ULL;
-  uint64_t addr = badAddress;
-  for (SectionInfo *si : _sectionInfos) {
-    for (const AtomInfo &info : si->atomsAndOffsets) {
-      auto type = info.atom->contentType();
-      if (type == DefinedAtom::typeMachHeader) {
-        addr = _atomToAddress[info.atom];
-        continue;
-      }
-      if (type != DefinedAtom::typeCode)
-        continue;
-      assert(addr != badAddress && "Missing mach header symbol");
-      // Skip atoms which have 0 size.  This is so that LC_FUNCTION_STARTS
-      // can't spill in to the next section.
-      if (!info.atom->size())
-        continue;
-      uint64_t nextAddr = _atomToAddress[info.atom];
-      if (_archHandler.isThumbFunction(*info.atom))
-        nextAddr |= 1;
-      uint64_t delta = nextAddr - addr;
-      if (delta) {
-        ByteBuffer buffer;
-        buffer.append_uleb128(delta);
-        file.functionStarts.insert(file.functionStarts.end(), buffer.bytes(),
-                                   buffer.bytes() + buffer.size());
-      }
-      addr = nextAddr;
-    }
-  }
-
-  // Null terminate, and pad to pointer size for this arch.
-  file.functionStarts.push_back(0);
-
-  auto size = file.functionStarts.size();
-  for (unsigned i = size, e = llvm::alignTo(size, _ctx.is64Bit() ? 8 : 4);
-       i != e; ++i)
-    file.functionStarts.push_back(0);
-}
-
-void Util::buildDataInCodeArray(const lld::File &, NormalizedFile &file) {
-  if (!_ctx.generateDataInCodeLoadCommand())
-    return;
-  for (SectionInfo *si : _sectionInfos) {
-    for (const AtomInfo &info : si->atomsAndOffsets) {
-      // Atoms that contain data-in-code have "transition" references
-      // which mark a point where the embedded data starts of ends.
-      // This needs to be converted to the mach-o format which is an array
-      // of data-in-code ranges.
-      uint32_t startOffset = 0;
-      DataRegionType mode = DataRegionType(0);
-      for (const Reference *ref : *info.atom) {
-        if (ref->kindNamespace() != Reference::KindNamespace::mach_o)
-          continue;
-        if (_archHandler.isDataInCodeTransition(ref->kindValue())) {
-          DataRegionType nextMode = (DataRegionType)ref->addend();
-          if (mode != nextMode) {
-            if (mode != 0) {
-              // Found end data range, so make range entry.
-              DataInCode entry;
-              entry.offset = si->address + info.offsetInSection + startOffset;
-              entry.length = ref->offsetInAtom() - startOffset;
-              entry.kind   = mode;
-              file.dataInCode.push_back(entry);
-            }
-          }
-          mode = nextMode;
-          startOffset = ref->offsetInAtom();
-        }
-      }
-      if (mode != 0) {
-        // Function ends with data (no end transition).
-        DataInCode entry;
-        entry.offset = si->address + info.offsetInSection + startOffset;
-        entry.length = info.atom->size() - startOffset;
-        entry.kind   = mode;
-        file.dataInCode.push_back(entry);
-      }
-    }
-  }
-}
-
-void Util::addRebaseAndBindingInfo(const lld::File &atomFile,
-                                                        NormalizedFile &nFile) {
-  if (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT)
-    return;
-
-  uint8_t segmentIndex;
-  uint64_t segmentStartAddr;
-  uint32_t offsetInBindInfo = 0;
-
-  for (SectionInfo *sect : _sectionInfos) {
-    segIndexForSection(sect, segmentIndex, segmentStartAddr);
-    for (const AtomInfo &info : sect->atomsAndOffsets) {
-      const DefinedAtom *atom = info.atom;
-      for (const Reference *ref : *atom) {
-        uint64_t segmentOffset = _atomToAddress[atom] + ref->offsetInAtom()
-                                - segmentStartAddr;
-        const Atom* targ = ref->target();
-        if (_archHandler.isPointer(*ref)) {
-          // A pointer to a DefinedAtom requires rebasing.
-          if (isa<DefinedAtom>(targ)) {
-            RebaseLocation rebase;
-            rebase.segIndex = segmentIndex;
-            rebase.segOffset = segmentOffset;
-            rebase.kind = llvm::MachO::REBASE_TYPE_POINTER;
-            nFile.rebasingInfo.push_back(rebase);
-          }
-          // A pointer to an SharedLibraryAtom requires binding.
-          if (const SharedLibraryAtom *sa = dyn_cast<SharedLibraryAtom>(targ)) {
-            BindLocation bind;
-            bind.segIndex = segmentIndex;
-            bind.segOffset = segmentOffset;
-            bind.kind = llvm::MachO::BIND_TYPE_POINTER;
-            bind.canBeNull = sa->canBeNullAtRuntime();
-            bind.ordinal = dylibOrdinal(sa);
-            bind.symbolName = targ->name();
-            bind.addend = ref->addend();
-            nFile.bindingInfo.push_back(bind);
-          }
-        }
-        else if (_archHandler.isLazyPointer(*ref)) {
-          BindLocation bind;
-          if (const SharedLibraryAtom *sa = dyn_cast<SharedLibraryAtom>(targ)) {
-            bind.ordinal = dylibOrdinal(sa);
-          } else {
-            bind.ordinal = llvm::MachO::BIND_SPECIAL_DYLIB_SELF;
-          }
-          bind.segIndex = segmentIndex;
-          bind.segOffset = segmentOffset;
-          bind.kind = llvm::MachO::BIND_TYPE_POINTER;
-          bind.canBeNull = false; //sa->canBeNullAtRuntime();
-          bind.symbolName = targ->name();
-          bind.addend = ref->addend();
-          nFile.lazyBindingInfo.push_back(bind);
-
-          // Now that we know the segmentOffset and the ordinal attribute,
-          // we can fix the helper's code
-
-          fixLazyReferenceImm(atom, offsetInBindInfo, nFile);
-
-          // 5 bytes for opcodes + variable sizes (target name + \0 and offset
-          // encode's size)
-          offsetInBindInfo +=
-              6 + targ->name().size() + llvm::getULEB128Size(bind.segOffset);
-          if (bind.ordinal > BIND_IMMEDIATE_MASK)
-            offsetInBindInfo += llvm::getULEB128Size(bind.ordinal);
-        }
-      }
-    }
-  }
-}
-
-void Util::fixLazyReferenceImm(const DefinedAtom *atom, uint32_t offset,
-                               NormalizedFile &file) {
-  for (const Reference *ref : *atom) {
-    const DefinedAtom *da = dyn_cast<DefinedAtom>(ref->target());
-    if (da == nullptr)
-      return;
-
-    const Reference *helperRef = nullptr;
-    for (const Reference *hr : *da) {
-      if (hr->kindValue() == _archHandler.lazyImmediateLocationKind()) {
-        helperRef = hr;
-        break;
-      }
-    }
-    if (helperRef == nullptr)
-      continue;
-
-    // TODO: maybe get the fixed atom content from _archHandler ?
-    for (SectionInfo *sectInfo : _sectionInfos) {
-      for (const AtomInfo &atomInfo : sectInfo->atomsAndOffsets) {
-        if (atomInfo.atom == helperRef->target()) {
-          auto sectionContent =
-              file.sections[sectInfo->normalizedSectionIndex].content;
-          uint8_t *rawb =
-              file.ownedAllocations.Allocate<uint8_t>(sectionContent.size());
-          llvm::MutableArrayRef<uint8_t> newContent{rawb,
-                                                    sectionContent.size()};
-          std::copy(sectionContent.begin(), sectionContent.end(),
-                    newContent.begin());
-          llvm::support::ulittle32_t *loc =
-              reinterpret_cast<llvm::support::ulittle32_t *>(
-                  &newContent[atomInfo.offsetInSection +
-                              helperRef->offsetInAtom()]);
-          *loc = offset;
-          file.sections[sectInfo->normalizedSectionIndex].content = newContent;
-        }
-      }
-    }
-  }
-}
-
-void Util::addExportInfo(const lld::File &atomFile, NormalizedFile &nFile) {
-  if (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT)
-    return;
-
-  for (SectionInfo *sect : _sectionInfos) {
-    for (const AtomInfo &info : sect->atomsAndOffsets) {
-      const DefinedAtom *atom = info.atom;
-      if (atom->scope() != Atom::scopeGlobal)
-        continue;
-      if (_ctx.exportRestrictMode()) {
-        if (!_ctx.exportSymbolNamed(atom->name()))
-          continue;
-      }
-      Export exprt;
-      exprt.name = atom->name();
-      exprt.offset = _atomToAddress[atom] - _ctx.baseAddress();
-      exprt.kind = EXPORT_SYMBOL_FLAGS_KIND_REGULAR;
-      if (atom->merge() == DefinedAtom::mergeAsWeak)
-        exprt.flags = EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;
-      else
-        exprt.flags = 0;
-      exprt.otherOffset = 0;
-      exprt.otherName = StringRef();
-      nFile.exportInfo.push_back(exprt);
-    }
-  }
-}
-
-uint32_t Util::fileFlags() {
-  // FIXME: these need to determined at runtime.
-  if (_ctx.outputMachOType() == MH_OBJECT) {
-    return _subsectionsViaSymbols ? (uint32_t)MH_SUBSECTIONS_VIA_SYMBOLS : 0;
-  } else {
-    uint32_t flags = MH_DYLDLINK;
-    if (!_ctx.useFlatNamespace())
-        flags |= MH_TWOLEVEL | MH_NOUNDEFS;
-    if ((_ctx.outputMachOType() == MH_EXECUTE) && _ctx.PIE())
-      flags |= MH_PIE;
-    if (_hasTLVDescriptors)
-      flags |= (MH_PIE | MH_HAS_TLV_DESCRIPTORS);
-    return flags;
-  }
-}
-
-} // end anonymous namespace
-
-namespace lld {
-namespace mach_o {
-namespace normalized {
-
-/// Convert a set of Atoms into a normalized mach-o file.
-llvm::Expected<std::unique_ptr<NormalizedFile>>
-normalizedFromAtoms(const lld::File &atomFile,
-                                           const MachOLinkingContext &context) {
-  // The util object buffers info until the normalized file can be made.
-  Util util(context);
-  util.processDefinedAtoms(atomFile);
-  util.organizeSections();
-
-  std::unique_ptr<NormalizedFile> f(new NormalizedFile());
-  NormalizedFile &normFile = *f.get();
-  normFile.arch = context.arch();
-  normFile.fileType = context.outputMachOType();
-  normFile.flags = util.fileFlags();
-  normFile.stackSize = context.stackSize();
-  normFile.installName = context.installName();
-  normFile.currentVersion = context.currentVersion();
-  normFile.compatVersion = context.compatibilityVersion();
-  normFile.os = context.os();
-
-  // If we are emitting an object file, then the min version is the maximum
-  // of the min's of all the source files and the cmdline.
-  if (normFile.fileType == llvm::MachO::MH_OBJECT)
-    normFile.minOSverson = std::max(context.osMinVersion(), util.minVersion());
-  else
-    normFile.minOSverson = context.osMinVersion();
-
-  normFile.minOSVersionKind = util.minVersionCommandType();
-
-  normFile.sdkVersion = context.sdkVersion();
-  normFile.sourceVersion = context.sourceVersion();
-
-  if (context.generateVersionLoadCommand() &&
-      context.os() != MachOLinkingContext::OS::unknown)
-    normFile.hasMinVersionLoadCommand = true;
-  else if (normFile.fileType == llvm::MachO::MH_OBJECT &&
-           util.allSourceFilesHaveMinVersions() &&
-           ((normFile.os != MachOLinkingContext::OS::unknown) ||
-            util.minVersionCommandType())) {
-    // If we emit an object file, then it should contain a min version load
-    // command if all of the source files also contained min version commands.
-    // Also, we either need to have a platform, or found a platform from the
-    // source object files.
-    normFile.hasMinVersionLoadCommand = true;
-  }
-  normFile.generateDataInCodeLoadCommand =
-    context.generateDataInCodeLoadCommand();
-  normFile.pageSize = context.pageSize();
-  normFile.rpaths = context.rpaths();
-  util.addDependentDylibs(atomFile, normFile);
-  util.copySegmentInfo(normFile);
-  util.copySectionInfo(normFile);
-  util.assignAddressesToSections(normFile);
-  util.buildAtomToAddressMap();
-  if (auto err = util.synthesizeDebugNotes(normFile))
-    return std::move(err);
-  util.updateSectionInfo(normFile);
-  util.copySectionContent(normFile);
-  if (auto ec = util.addSymbols(atomFile, normFile)) {
-    return std::move(ec);
-  }
-  util.addIndirectSymbols(atomFile, normFile);
-  util.addRebaseAndBindingInfo(atomFile, normFile);
-  util.addExportInfo(atomFile, normFile);
-  util.addSectionRelocs(atomFile, normFile);
-  util.addFunctionStarts(atomFile, normFile);
-  util.buildDataInCodeArray(atomFile, normFile);
-  util.copyEntryPointAddress(normFile);
-
-  return std::move(f);
-}
-
-} // namespace normalized
-} // namespace mach_o
-} // namespace lld
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
deleted file mode 100644 (file)
index 164a283..0000000
+++ /dev/null
@@ -1,1635 +0,0 @@
-//===- lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp --------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-///
-/// \file Converts from in-memory normalized mach-o to in-memory Atoms.
-///
-///                  +------------+
-///                  | normalized |
-///                  +------------+
-///                        |
-///                        |
-///                        v
-///                    +-------+
-///                    | Atoms |
-///                    +-------+
-
-#include "ArchHandler.h"
-#include "Atoms.h"
-#include "File.h"
-#include "MachONormalizedFile.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/Error.h"
-#include "llvm/BinaryFormat/Dwarf.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
-#include "llvm/Support/DataExtractor.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/LEB128.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm::MachO;
-using namespace lld::mach_o::normalized;
-
-#define DEBUG_TYPE "normalized-file-to-atoms"
-
-namespace lld {
-namespace mach_o {
-
-
-namespace { // anonymous
-
-
-#define ENTRY(seg, sect, type, atomType) \
-  {seg, sect, type, DefinedAtom::atomType }
-
-struct MachORelocatableSectionToAtomType {
-  StringRef                 segmentName;
-  StringRef                 sectionName;
-  SectionType               sectionType;
-  DefinedAtom::ContentType  atomType;
-};
-
-const MachORelocatableSectionToAtomType sectsToAtomType[] = {
-  ENTRY("__TEXT", "__text",           S_REGULAR,          typeCode),
-  ENTRY("__TEXT", "__text",           S_REGULAR,          typeResolver),
-  ENTRY("__TEXT", "__cstring",        S_CSTRING_LITERALS, typeCString),
-  ENTRY("",       "",                 S_CSTRING_LITERALS, typeCString),
-  ENTRY("__TEXT", "__ustring",        S_REGULAR,          typeUTF16String),
-  ENTRY("__TEXT", "__const",          S_REGULAR,          typeConstant),
-  ENTRY("__TEXT", "__const_coal",     S_COALESCED,        typeConstant),
-  ENTRY("__TEXT", "__eh_frame",       S_COALESCED,        typeCFI),
-  ENTRY("__TEXT", "__eh_frame",       S_REGULAR,          typeCFI),
-  ENTRY("__TEXT", "__literal4",       S_4BYTE_LITERALS,   typeLiteral4),
-  ENTRY("__TEXT", "__literal8",       S_8BYTE_LITERALS,   typeLiteral8),
-  ENTRY("__TEXT", "__literal16",      S_16BYTE_LITERALS,  typeLiteral16),
-  ENTRY("__TEXT", "__gcc_except_tab", S_REGULAR,          typeLSDA),
-  ENTRY("__DATA", "__data",           S_REGULAR,          typeData),
-  ENTRY("__DATA", "__datacoal_nt",    S_COALESCED,        typeData),
-  ENTRY("__DATA", "__const",          S_REGULAR,          typeConstData),
-  ENTRY("__DATA", "__cfstring",       S_REGULAR,          typeCFString),
-  ENTRY("__DATA", "__mod_init_func",  S_MOD_INIT_FUNC_POINTERS,
-                                                          typeInitializerPtr),
-  ENTRY("__DATA", "__mod_term_func",  S_MOD_TERM_FUNC_POINTERS,
-                                                          typeTerminatorPtr),
-  ENTRY("__DATA", "__got",            S_NON_LAZY_SYMBOL_POINTERS,
-                                                          typeGOT),
-  ENTRY("__DATA", "__bss",            S_ZEROFILL,         typeZeroFill),
-  ENTRY("",       "",                 S_NON_LAZY_SYMBOL_POINTERS,
-                                                          typeGOT),
-  ENTRY("__DATA", "__interposing",    S_INTERPOSING,      typeInterposingTuples),
-  ENTRY("__DATA", "__thread_vars",    S_THREAD_LOCAL_VARIABLES,
-                                                          typeThunkTLV),
-  ENTRY("__DATA", "__thread_data", S_THREAD_LOCAL_REGULAR, typeTLVInitialData),
-  ENTRY("__DATA", "__thread_bss",     S_THREAD_LOCAL_ZEROFILL,
-                                                        typeTLVInitialZeroFill),
-  ENTRY("__DATA", "__objc_imageinfo", S_REGULAR,          typeObjCImageInfo),
-  ENTRY("__DATA", "__objc_catlist",   S_REGULAR,          typeObjC2CategoryList),
-  ENTRY("",       "",                 S_INTERPOSING,      typeInterposingTuples),
-  ENTRY("__LD",   "__compact_unwind", S_REGULAR,
-                                                         typeCompactUnwindInfo),
-  ENTRY("",       "",                 S_REGULAR,          typeUnknown)
-};
-#undef ENTRY
-
-
-/// Figures out ContentType of a mach-o section.
-DefinedAtom::ContentType atomTypeFromSection(const Section &section,
-                                             bool &customSectionName) {
-  // First look for match of name and type. Empty names in table are wildcards.
-  customSectionName = false;
-  for (const MachORelocatableSectionToAtomType *p = sectsToAtomType ;
-                                 p->atomType != DefinedAtom::typeUnknown; ++p) {
-    if (p->sectionType != section.type)
-      continue;
-    if (!p->segmentName.equals(section.segmentName) && !p->segmentName.empty())
-      continue;
-    if (!p->sectionName.equals(section.sectionName) && !p->sectionName.empty())
-      continue;
-    customSectionName = p->segmentName.empty() && p->sectionName.empty();
-    return p->atomType;
-  }
-  // Look for code denoted by section attributes
-  if (section.attributes & S_ATTR_PURE_INSTRUCTIONS)
-    return DefinedAtom::typeCode;
-
-  return DefinedAtom::typeUnknown;
-}
-
-enum AtomizeModel {
-  atomizeAtSymbols,
-  atomizeFixedSize,
-  atomizePointerSize,
-  atomizeUTF8,
-  atomizeUTF16,
-  atomizeCFI,
-  atomizeCU,
-  atomizeCFString
-};
-
-/// Returns info on how to atomize a section of the specified ContentType.
-void sectionParseInfo(DefinedAtom::ContentType atomType,
-                      unsigned int &sizeMultiple,
-                      DefinedAtom::Scope &scope,
-                      DefinedAtom::Merge &merge,
-                      AtomizeModel &atomizeModel) {
-  struct ParseInfo {
-    DefinedAtom::ContentType  atomType;
-    unsigned int              sizeMultiple;
-    DefinedAtom::Scope        scope;
-    DefinedAtom::Merge        merge;
-    AtomizeModel              atomizeModel;
-  };
-
-  #define ENTRY(type, size, scope, merge, model) \
-    {DefinedAtom::type, size, DefinedAtom::scope, DefinedAtom::merge, model }
-
-  static const ParseInfo parseInfo[] = {
-    ENTRY(typeCode,              1, scopeGlobal,          mergeNo,
-                                                            atomizeAtSymbols),
-    ENTRY(typeData,              1, scopeGlobal,          mergeNo,
-                                                            atomizeAtSymbols),
-    ENTRY(typeConstData,         1, scopeGlobal,          mergeNo,
-                                                            atomizeAtSymbols),
-    ENTRY(typeZeroFill,          1, scopeGlobal,          mergeNo,
-                                                            atomizeAtSymbols),
-    ENTRY(typeConstant,          1, scopeGlobal,          mergeNo,
-                                                            atomizeAtSymbols),
-    ENTRY(typeCString,           1, scopeLinkageUnit,     mergeByContent,
-                                                            atomizeUTF8),
-    ENTRY(typeUTF16String,       1, scopeLinkageUnit,     mergeByContent,
-                                                            atomizeUTF16),
-    ENTRY(typeCFI,               4, scopeTranslationUnit, mergeNo,
-                                                            atomizeCFI),
-    ENTRY(typeLiteral4,          4, scopeLinkageUnit,     mergeByContent,
-                                                            atomizeFixedSize),
-    ENTRY(typeLiteral8,          8, scopeLinkageUnit,     mergeByContent,
-                                                            atomizeFixedSize),
-    ENTRY(typeLiteral16,        16, scopeLinkageUnit,     mergeByContent,
-                                                            atomizeFixedSize),
-    ENTRY(typeCFString,          4, scopeLinkageUnit,     mergeByContent,
-                                                            atomizeCFString),
-    ENTRY(typeInitializerPtr,    4, scopeTranslationUnit, mergeNo,
-                                                            atomizePointerSize),
-    ENTRY(typeTerminatorPtr,     4, scopeTranslationUnit, mergeNo,
-                                                            atomizePointerSize),
-    ENTRY(typeCompactUnwindInfo, 4, scopeTranslationUnit, mergeNo,
-                                                            atomizeCU),
-    ENTRY(typeGOT,               4, scopeLinkageUnit,     mergeByContent,
-                                                            atomizePointerSize),
-    ENTRY(typeObjC2CategoryList, 4, scopeTranslationUnit, mergeByContent,
-                                                            atomizePointerSize),
-    ENTRY(typeUnknown,           1, scopeGlobal,          mergeNo,
-                                                            atomizeAtSymbols)
-  };
-  #undef ENTRY
-  const int tableLen = sizeof(parseInfo) / sizeof(ParseInfo);
-  for (int i=0; i < tableLen; ++i) {
-    if (parseInfo[i].atomType == atomType) {
-      sizeMultiple = parseInfo[i].sizeMultiple;
-      scope        = parseInfo[i].scope;
-      merge        = parseInfo[i].merge;
-      atomizeModel = parseInfo[i].atomizeModel;
-      return;
-    }
-  }
-
-  // Unknown type is atomized by symbols.
-  sizeMultiple = 1;
-  scope = DefinedAtom::scopeGlobal;
-  merge = DefinedAtom::mergeNo;
-  atomizeModel = atomizeAtSymbols;
-}
-
-
-Atom::Scope atomScope(uint8_t scope) {
-  switch (scope) {
-  case N_EXT:
-    return Atom::scopeGlobal;
-  case N_PEXT:
-  case N_PEXT | N_EXT:
-    return Atom::scopeLinkageUnit;
-  case 0:
-    return Atom::scopeTranslationUnit;
-  }
-  llvm_unreachable("unknown scope value!");
-}
-
-void appendSymbolsInSection(
-    const std::vector<lld::mach_o::normalized::Symbol> &inSymbols,
-    uint32_t sectionIndex,
-    SmallVector<const lld::mach_o::normalized::Symbol *, 64> &outSyms) {
-  for (const lld::mach_o::normalized::Symbol &sym : inSymbols) {
-    // Only look at definition symbols.
-    if ((sym.type & N_TYPE) != N_SECT)
-      continue;
-    if (sym.sect != sectionIndex)
-      continue;
-    outSyms.push_back(&sym);
-  }
-}
-
-void atomFromSymbol(DefinedAtom::ContentType atomType, const Section &section,
-                    MachOFile &file, uint64_t symbolAddr, StringRef symbolName,
-                    uint16_t symbolDescFlags, Atom::Scope symbolScope,
-                    uint64_t nextSymbolAddr, bool scatterable, bool copyRefs) {
-  // Mach-O symbol table does have size in it. Instead the size is the
-  // difference between this and the next symbol.
-  uint64_t size = nextSymbolAddr - symbolAddr;
-  uint64_t offset = symbolAddr - section.address;
-  bool noDeadStrip = (symbolDescFlags & N_NO_DEAD_STRIP) || !scatterable;
-  if (isZeroFillSection(section.type)) {
-    file.addZeroFillDefinedAtom(symbolName, symbolScope, offset, size,
-                                noDeadStrip, copyRefs, &section);
-  } else {
-    DefinedAtom::Merge merge = (symbolDescFlags & N_WEAK_DEF)
-                              ? DefinedAtom::mergeAsWeak : DefinedAtom::mergeNo;
-    bool thumb = (symbolDescFlags & N_ARM_THUMB_DEF);
-    if (atomType == DefinedAtom::typeUnknown) {
-      // Mach-O needs a segment and section name.  Concatenate those two
-      // with a / separator (e.g. "seg/sect") to fit into the lld model
-      // of just a section name.
-      std::string segSectName = section.segmentName.str()
-                                + "/" + section.sectionName.str();
-      file.addDefinedAtomInCustomSection(symbolName, symbolScope, atomType,
-                                         merge, thumb, noDeadStrip, offset,
-                                         size, segSectName, true, &section);
-    } else {
-      if ((atomType == lld::DefinedAtom::typeCode) &&
-          (symbolDescFlags & N_SYMBOL_RESOLVER)) {
-        atomType = lld::DefinedAtom::typeResolver;
-      }
-      file.addDefinedAtom(symbolName, symbolScope, atomType, merge,
-                          offset, size, thumb, noDeadStrip, copyRefs, &section);
-    }
-  }
-}
-
-llvm::Error processSymboledSection(DefinedAtom::ContentType atomType,
-                                   const Section &section,
-                                   const NormalizedFile &normalizedFile,
-                                   MachOFile &file, bool scatterable,
-                                   bool copyRefs) {
-  // Find section's index.
-  uint32_t sectIndex = 1;
-  for (auto &sect : normalizedFile.sections) {
-    if (&sect == &section)
-      break;
-    ++sectIndex;
-  }
-
-  // Find all symbols in this section.
-  SmallVector<const lld::mach_o::normalized::Symbol *, 64> symbols;
-  appendSymbolsInSection(normalizedFile.globalSymbols, sectIndex, symbols);
-  appendSymbolsInSection(normalizedFile.localSymbols,  sectIndex, symbols);
-
-  // Sort symbols.
-  std::sort(symbols.begin(), symbols.end(),
-            [](const lld::mach_o::normalized::Symbol *lhs,
-               const lld::mach_o::normalized::Symbol *rhs) -> bool {
-              if (lhs == rhs)
-                return false;
-              // First by address.
-              uint64_t lhsAddr = lhs->value;
-              uint64_t rhsAddr = rhs->value;
-              if (lhsAddr != rhsAddr)
-                return lhsAddr < rhsAddr;
-              // If same address, one is an alias so sort by scope.
-              Atom::Scope lScope = atomScope(lhs->scope);
-              Atom::Scope rScope = atomScope(rhs->scope);
-              if (lScope != rScope)
-                return lScope < rScope;
-              // If same address and scope, see if one might be better as
-              // the alias.
-              bool lPrivate = (lhs->name.front() == 'l');
-              bool rPrivate = (rhs->name.front() == 'l');
-              if (lPrivate != rPrivate)
-                return lPrivate;
-              // If same address and scope, sort by name.
-              return lhs->name < rhs->name;
-            });
-
-  // Debug logging of symbols.
-  // for (const Symbol *sym : symbols)
-  //  llvm::errs() << "  sym: "
-  //    << llvm::format("0x%08llx ", (uint64_t)sym->value)
-  //    << ", " << sym->name << "\n";
-
-  // If section has no symbols and no content, there are no atoms.
-  if (symbols.empty() && section.content.empty())
-    return llvm::Error::success();
-
-  if (symbols.empty()) {
-    // Section has no symbols, put all content in one anonymous atom.
-    atomFromSymbol(atomType, section, file, section.address, StringRef(),
-                  0, Atom::scopeTranslationUnit,
-                  section.address + section.content.size(),
-                  scatterable, copyRefs);
-  }
-  else if (symbols.front()->value != section.address) {
-    // Section has anonymous content before first symbol.
-    atomFromSymbol(atomType, section, file, section.address, StringRef(),
-                   0, Atom::scopeTranslationUnit, symbols.front()->value,
-                   scatterable, copyRefs);
-  }
-
-  const lld::mach_o::normalized::Symbol *lastSym = nullptr;
-  for (const lld::mach_o::normalized::Symbol *sym : symbols) {
-    if (lastSym != nullptr) {
-      // Ignore any assembler added "ltmpNNN" symbol at start of section
-      // if there is another symbol at the start.
-      if ((lastSym->value != sym->value)
-          || lastSym->value != section.address
-          || !lastSym->name.startswith("ltmp")) {
-        atomFromSymbol(atomType, section, file, lastSym->value, lastSym->name,
-                       lastSym->desc, atomScope(lastSym->scope), sym->value,
-                       scatterable, copyRefs);
-      }
-    }
-    lastSym = sym;
-  }
-  if (lastSym != nullptr) {
-    atomFromSymbol(atomType, section, file, lastSym->value, lastSym->name,
-                   lastSym->desc, atomScope(lastSym->scope),
-                   section.address + section.content.size(),
-                   scatterable, copyRefs);
-  }
-
-  // If object built without .subsections_via_symbols, add reference chain.
-  if (!scatterable) {
-    MachODefinedAtom *prevAtom = nullptr;
-    file.eachAtomInSection(section,
-                           [&](MachODefinedAtom *atom, uint64_t offset)->void {
-      if (prevAtom)
-        prevAtom->addReference(Reference::KindNamespace::all,
-                               Reference::KindArch::all,
-                               Reference::kindLayoutAfter, 0, atom, 0);
-      prevAtom = atom;
-    });
-  }
-
-  return llvm::Error::success();
-}
-
-llvm::Error processSection(DefinedAtom::ContentType atomType,
-                           const Section &section,
-                           bool customSectionName,
-                           const NormalizedFile &normalizedFile,
-                           MachOFile &file, bool scatterable,
-                           bool copyRefs) {
-  const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
-  const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
-
-  // Get info on how to atomize section.
-  unsigned int       sizeMultiple;
-  DefinedAtom::Scope scope;
-  DefinedAtom::Merge merge;
-  AtomizeModel       atomizeModel;
-  sectionParseInfo(atomType, sizeMultiple, scope, merge, atomizeModel);
-
-  // Validate section size.
-  if ((section.content.size() % sizeMultiple) != 0)
-    return llvm::make_error<GenericError>(Twine("Section ")
-                                          + section.segmentName
-                                          + "/" + section.sectionName
-                                          + " has size ("
-                                          + Twine(section.content.size())
-                                          + ") which is not a multiple of "
-                                          + Twine(sizeMultiple));
-
-  if (atomizeModel == atomizeAtSymbols) {
-    // Break section up into atoms each with a fixed size.
-    return processSymboledSection(atomType, section, normalizedFile, file,
-                                  scatterable, copyRefs);
-  } else {
-    unsigned int size;
-    for (unsigned int offset = 0, e = section.content.size(); offset != e;) {
-      switch (atomizeModel) {
-      case atomizeFixedSize:
-        // Break section up into atoms each with a fixed size.
-        size = sizeMultiple;
-        break;
-      case atomizePointerSize:
-        // Break section up into atoms each the size of a pointer.
-        size = is64 ? 8 : 4;
-        break;
-      case atomizeUTF8:
-        // Break section up into zero terminated c-strings.
-        size = 0;
-        for (unsigned int i = offset; i < e; ++i) {
-          if (section.content[i] == 0) {
-            size = i + 1 - offset;
-            break;
-          }
-        }
-        break;
-      case atomizeUTF16:
-        // Break section up into zero terminated UTF16 strings.
-        size = 0;
-        for (unsigned int i = offset; i < e; i += 2) {
-          if ((section.content[i] == 0) && (section.content[i + 1] == 0)) {
-            size = i + 2 - offset;
-            break;
-          }
-        }
-        break;
-      case atomizeCFI:
-        // Break section up into dwarf unwind CFIs (FDE or CIE).
-        size = read32(&section.content[offset], isBig) + 4;
-        if (offset+size > section.content.size()) {
-          return llvm::make_error<GenericError>(Twine("Section ")
-                                                + section.segmentName
-                                                + "/" + section.sectionName
-                                                + " is malformed.  Size of CFI "
-                                                "starting at offset ("
-                                                + Twine(offset)
-                                                + ") is past end of section.");
-        }
-        break;
-      case atomizeCU:
-        // Break section up into compact unwind entries.
-        size = is64 ? 32 : 20;
-        break;
-      case atomizeCFString:
-        // Break section up into NS/CFString objects.
-        size = is64 ? 32 : 16;
-        break;
-      case atomizeAtSymbols:
-        break;
-      }
-      if (size == 0) {
-        return llvm::make_error<GenericError>(Twine("Section ")
-                                              + section.segmentName
-                                              + "/" + section.sectionName
-                                              + " is malformed.  The last atom "
-                                              "is not zero terminated.");
-      }
-      if (customSectionName) {
-        // Mach-O needs a segment and section name.  Concatenate those two
-        // with a / separator (e.g. "seg/sect") to fit into the lld model
-        // of just a section name.
-        std::string segSectName = section.segmentName.str()
-                                  + "/" + section.sectionName.str();
-        file.addDefinedAtomInCustomSection(StringRef(), scope, atomType,
-                                           merge, false, false, offset,
-                                           size, segSectName, true, &section);
-      } else {
-        file.addDefinedAtom(StringRef(), scope, atomType, merge, offset, size,
-                            false, false, copyRefs, &section);
-      }
-      offset += size;
-    }
-  }
-  return llvm::Error::success();
-}
-
-const Section* findSectionCoveringAddress(const NormalizedFile &normalizedFile,
-                                          uint64_t address) {
-  for (const Section &s : normalizedFile.sections) {
-    uint64_t sAddr = s.address;
-    if ((sAddr <= address) && (address < sAddr+s.content.size())) {
-      return &s;
-    }
-  }
-  return nullptr;
-}
-
-const MachODefinedAtom *
-findAtomCoveringAddress(const NormalizedFile &normalizedFile, MachOFile &file,
-                        uint64_t addr, Reference::Addend &addend) {
-  const Section *sect = nullptr;
-  sect = findSectionCoveringAddress(normalizedFile, addr);
-  if (!sect)
-    return nullptr;
-
-  uint32_t offsetInTarget;
-  uint64_t offsetInSect = addr - sect->address;
-  auto atom =
-      file.findAtomCoveringAddress(*sect, offsetInSect, &offsetInTarget);
-  addend = offsetInTarget;
-  return atom;
-}
-
-// Walks all relocations for a section in a normalized .o file and
-// creates corresponding lld::Reference objects.
-llvm::Error convertRelocs(const Section &section,
-                          const NormalizedFile &normalizedFile,
-                          bool scatterable,
-                          MachOFile &file,
-                          ArchHandler &handler) {
-  // Utility function for ArchHandler to find atom by its address.
-  auto atomByAddr = [&] (uint32_t sectIndex, uint64_t addr,
-                         const lld::Atom **atom, Reference::Addend *addend)
-                         -> llvm::Error {
-    if (sectIndex > normalizedFile.sections.size())
-      return llvm::make_error<GenericError>(Twine("out of range section "
-                                     "index (") + Twine(sectIndex) + ")");
-    const Section *sect = nullptr;
-    if (sectIndex == 0) {
-      sect = findSectionCoveringAddress(normalizedFile, addr);
-      if (!sect)
-        return llvm::make_error<GenericError>(Twine("address (" + Twine(addr)
-                                       + ") is not in any section"));
-    } else {
-      sect = &normalizedFile.sections[sectIndex-1];
-    }
-    uint32_t offsetInTarget;
-    uint64_t offsetInSect = addr - sect->address;
-    *atom = file.findAtomCoveringAddress(*sect, offsetInSect, &offsetInTarget);
-    *addend = offsetInTarget;
-    return llvm::Error::success();
-  };
-
-  // Utility function for ArchHandler to find atom by its symbol index.
-  auto atomBySymbol = [&] (uint32_t symbolIndex, const lld::Atom **result)
-                           -> llvm::Error {
-    // Find symbol from index.
-    const lld::mach_o::normalized::Symbol *sym = nullptr;
-    uint32_t numStabs  = normalizedFile.stabsSymbols.size();
-    uint32_t numLocal  = normalizedFile.localSymbols.size();
-    uint32_t numGlobal = normalizedFile.globalSymbols.size();
-    uint32_t numUndef  = normalizedFile.undefinedSymbols.size();
-    assert(symbolIndex >= numStabs && "Searched for stab via atomBySymbol?");
-    if (symbolIndex < numStabs+numLocal) {
-      sym = &normalizedFile.localSymbols[symbolIndex-numStabs];
-    } else if (symbolIndex < numStabs+numLocal+numGlobal) {
-      sym = &normalizedFile.globalSymbols[symbolIndex-numStabs-numLocal];
-    } else if (symbolIndex < numStabs+numLocal+numGlobal+numUndef) {
-      sym = &normalizedFile.undefinedSymbols[symbolIndex-numStabs-numLocal-
-                                             numGlobal];
-    } else {
-      return llvm::make_error<GenericError>(Twine("symbol index (")
-                                     + Twine(symbolIndex) + ") out of range");
-    }
-
-    // Find atom from symbol.
-    if ((sym->type & N_TYPE) == N_SECT) {
-      if (sym->sect > normalizedFile.sections.size())
-        return llvm::make_error<GenericError>(Twine("symbol section index (")
-                                        + Twine(sym->sect) + ") out of range ");
-      const Section &symSection = normalizedFile.sections[sym->sect-1];
-      uint64_t targetOffsetInSect = sym->value - symSection.address;
-      MachODefinedAtom *target = file.findAtomCoveringAddress(symSection,
-                                                            targetOffsetInSect);
-      if (target) {
-        *result = target;
-        return llvm::Error::success();
-      }
-      return llvm::make_error<GenericError>("no atom found for defined symbol");
-    } else if ((sym->type & N_TYPE) == N_UNDF) {
-      const lld::Atom *target = file.findUndefAtom(sym->name);
-      if (target) {
-        *result = target;
-        return llvm::Error::success();
-      }
-      return llvm::make_error<GenericError>("no undefined atom found for sym");
-    } else {
-      // Search undefs
-      return llvm::make_error<GenericError>("no atom found for symbol");
-    }
-  };
-
-  const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
-  // Use old-school iterator so that paired relocations can be grouped.
-  for (auto it=section.relocations.begin(), e=section.relocations.end();
-                                                                it != e; ++it) {
-    const Relocation &reloc = *it;
-    // Find atom this relocation is in.
-    if (reloc.offset > section.content.size())
-      return llvm::make_error<GenericError>(
-                                    Twine("r_address (") + Twine(reloc.offset)
-                                    + ") is larger than section size ("
-                                    + Twine(section.content.size()) + ")");
-    uint32_t offsetInAtom;
-    MachODefinedAtom *inAtom = file.findAtomCoveringAddress(section,
-                                                            reloc.offset,
-                                                            &offsetInAtom);
-    assert(inAtom && "r_address in range, should have found atom");
-    uint64_t fixupAddress = section.address + reloc.offset;
-
-    const lld::Atom *target = nullptr;
-    Reference::Addend addend = 0;
-    Reference::KindValue kind;
-    if (handler.isPairedReloc(reloc)) {
-      // Handle paired relocations together.
-      const Relocation &reloc2 = *++it;
-      auto relocErr = handler.getPairReferenceInfo(
-          reloc, reloc2, inAtom, offsetInAtom, fixupAddress, isBig, scatterable,
-          atomByAddr, atomBySymbol, &kind, &target, &addend);
-      if (relocErr) {
-        return handleErrors(std::move(relocErr),
-                            [&](std::unique_ptr<GenericError> GE) {
-          return llvm::make_error<GenericError>(
-            Twine("bad relocation (") + GE->getMessage()
-             + ") in section "
-             + section.segmentName + "/" + section.sectionName
-             + " (r1_address=" + Twine::utohexstr(reloc.offset)
-             + ", r1_type=" + Twine(reloc.type)
-             + ", r1_extern=" + Twine(reloc.isExtern)
-             + ", r1_length=" + Twine((int)reloc.length)
-             + ", r1_pcrel=" + Twine(reloc.pcRel)
-             + (!reloc.scattered ? (Twine(", r1_symbolnum=")
-                                    + Twine(reloc.symbol))
-                                 : (Twine(", r1_scattered=1, r1_value=")
-                                    + Twine(reloc.value)))
-             + ")"
-             + ", (r2_address=" + Twine::utohexstr(reloc2.offset)
-             + ", r2_type=" + Twine(reloc2.type)
-             + ", r2_extern=" + Twine(reloc2.isExtern)
-             + ", r2_length=" + Twine((int)reloc2.length)
-             + ", r2_pcrel=" + Twine(reloc2.pcRel)
-             + (!reloc2.scattered ? (Twine(", r2_symbolnum=")
-                                     + Twine(reloc2.symbol))
-                                  : (Twine(", r2_scattered=1, r2_value=")
-                                     + Twine(reloc2.value)))
-             + ")" );
-          });
-      }
-    }
-    else {
-      // Use ArchHandler to convert relocation record into information
-      // needed to instantiate an lld::Reference object.
-      auto relocErr = handler.getReferenceInfo(
-          reloc, inAtom, offsetInAtom, fixupAddress, isBig, atomByAddr,
-          atomBySymbol, &kind, &target, &addend);
-      if (relocErr) {
-        return handleErrors(std::move(relocErr),
-                            [&](std::unique_ptr<GenericError> GE) {
-          return llvm::make_error<GenericError>(
-            Twine("bad relocation (") + GE->getMessage()
-             + ") in section "
-             + section.segmentName + "/" + section.sectionName
-             + " (r_address=" + Twine::utohexstr(reloc.offset)
-             + ", r_type=" + Twine(reloc.type)
-             + ", r_extern=" + Twine(reloc.isExtern)
-             + ", r_length=" + Twine((int)reloc.length)
-             + ", r_pcrel=" + Twine(reloc.pcRel)
-             + (!reloc.scattered ? (Twine(", r_symbolnum=") + Twine(reloc.symbol))
-                                 : (Twine(", r_scattered=1, r_value=")
-                                    + Twine(reloc.value)))
-             + ")" );
-          });
-      }
-    }
-    // Instantiate an lld::Reference object and add to its atom.
-    inAtom->addReference(Reference::KindNamespace::mach_o,
-                         handler.kindArch(),
-                         kind, offsetInAtom, target, addend);
-  }
-
-  return llvm::Error::success();
-}
-
-bool isDebugInfoSection(const Section &section) {
-  if ((section.attributes & S_ATTR_DEBUG) == 0)
-    return false;
-  return section.segmentName.equals("__DWARF");
-}
-
-static const Atom* findDefinedAtomByName(MachOFile &file, Twine name) {
-  std::string strName = name.str();
-  for (auto *atom : file.defined())
-    if (atom->name() == strName)
-      return atom;
-  return nullptr;
-}
-
-static StringRef copyDebugString(StringRef str, BumpPtrAllocator &alloc) {
-  char *strCopy = alloc.Allocate<char>(str.size() + 1);
-  memcpy(strCopy, str.data(), str.size());
-  strCopy[str.size()] = '\0';
-  return strCopy;
-}
-
-llvm::Error parseStabs(MachOFile &file,
-                       const NormalizedFile &normalizedFile,
-                       bool copyRefs) {
-
-  if (normalizedFile.stabsSymbols.empty())
-    return llvm::Error::success();
-
-  // FIXME: Kill this off when we can move to sane yaml parsing.
-  std::unique_ptr<BumpPtrAllocator> allocator;
-  if (copyRefs)
-    allocator = std::make_unique<BumpPtrAllocator>();
-
-  enum { start, inBeginEnd } state = start;
-
-  const Atom *currentAtom = nullptr;
-  uint64_t currentAtomAddress = 0;
-  StabsDebugInfo::StabsList stabsList;
-  for (const auto &stabSym : normalizedFile.stabsSymbols) {
-    Stab stab(nullptr, stabSym.type, stabSym.sect, stabSym.desc,
-              stabSym.value, stabSym.name);
-    switch (state) {
-    case start:
-      switch (static_cast<StabType>(stabSym.type)) {
-      case N_BNSYM:
-        state = inBeginEnd;
-        currentAtomAddress = stabSym.value;
-        Reference::Addend addend;
-        currentAtom = findAtomCoveringAddress(normalizedFile, file,
-                                              currentAtomAddress, addend);
-        if (addend != 0)
-          return llvm::make_error<GenericError>(
-                   "Non-zero addend for BNSYM '" + stabSym.name + "' in " +
-                   file.path());
-        if (currentAtom)
-          stab.atom = currentAtom;
-        else {
-          // FIXME: ld64 just issues a warning here - should we match that?
-          return llvm::make_error<GenericError>(
-                   "can't find atom for stabs BNSYM at " +
-                   Twine::utohexstr(stabSym.value) + " in " + file.path());
-        }
-        break;
-      case N_SO:
-      case N_OSO:
-        // Not associated with an atom, just copy.
-        if (copyRefs)
-          stab.str = copyDebugString(stabSym.name, *allocator);
-        else
-          stab.str = stabSym.name;
-        break;
-      case N_GSYM: {
-        auto colonIdx = stabSym.name.find(':');
-        if (colonIdx != StringRef::npos) {
-          StringRef name = stabSym.name.substr(0, colonIdx);
-          currentAtom = findDefinedAtomByName(file, "_" + name);
-          stab.atom = currentAtom;
-          if (copyRefs)
-            stab.str = copyDebugString(stabSym.name, *allocator);
-          else
-            stab.str = stabSym.name;
-        } else {
-          currentAtom = findDefinedAtomByName(file, stabSym.name);
-          stab.atom = currentAtom;
-          if (copyRefs)
-            stab.str = copyDebugString(stabSym.name, *allocator);
-          else
-            stab.str = stabSym.name;
-        }
-        if (stab.atom == nullptr)
-          return llvm::make_error<GenericError>(
-                   "can't find atom for N_GSYM stabs" + stabSym.name +
-                   " in " + file.path());
-        break;
-      }
-      case N_FUN:
-        return llvm::make_error<GenericError>(
-                 "old-style N_FUN stab '" + stabSym.name + "' unsupported");
-      default:
-        return llvm::make_error<GenericError>(
-                 "unrecognized stab symbol '" + stabSym.name + "'");
-      }
-      break;
-    case inBeginEnd:
-      stab.atom = currentAtom;
-      switch (static_cast<StabType>(stabSym.type)) {
-      case N_ENSYM:
-        state = start;
-        currentAtom = nullptr;
-        break;
-      case N_FUN:
-        // Just copy the string.
-        if (copyRefs)
-          stab.str = copyDebugString(stabSym.name, *allocator);
-        else
-          stab.str = stabSym.name;
-        break;
-      default:
-        return llvm::make_error<GenericError>(
-                 "unrecognized stab symbol '" + stabSym.name + "'");
-      }
-    }
-    llvm::dbgs() << "Adding to stabsList: " << stab << "\n";
-    stabsList.push_back(stab);
-  }
-
-  file.setDebugInfo(std::make_unique<StabsDebugInfo>(std::move(stabsList)));
-
-  // FIXME: Kill this off when we fix YAML memory ownership.
-  file.debugInfo()->setAllocator(std::move(allocator));
-
-  return llvm::Error::success();
-}
-
-static llvm::DataExtractor
-dataExtractorFromSection(const NormalizedFile &normalizedFile,
-                         const Section &S) {
-  const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
-  const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
-  StringRef SecData(reinterpret_cast<const char*>(S.content.data()),
-                    S.content.size());
-  return llvm::DataExtractor(SecData, !isBig, is64 ? 8 : 4);
-}
-
-// FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
-//        inspection" code if possible.
-static uint64_t getCUAbbrevOffset(llvm::DataExtractor abbrevData,
-                                  uint64_t abbrCode) {
-  uint64_t offset = 0;
-  while (abbrevData.getULEB128(&offset) != abbrCode) {
-    // Tag
-    abbrevData.getULEB128(&offset);
-    // DW_CHILDREN
-    abbrevData.getU8(&offset);
-    // Attributes
-    while (abbrevData.getULEB128(&offset) | abbrevData.getULEB128(&offset))
-      ;
-  }
-  return offset;
-}
-
-// FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
-//        inspection" code if possible.
-static Expected<const char *>
-getIndexedString(const NormalizedFile &normalizedFile,
-                 llvm::dwarf::Form form, llvm::DataExtractor infoData,
-                 uint64_t &infoOffset, const Section &stringsSection) {
-  if (form == llvm::dwarf::DW_FORM_string)
-   return infoData.getCStr(&infoOffset);
-  if (form != llvm::dwarf::DW_FORM_strp)
-    return llvm::make_error<GenericError>(
-        "string field encoded without DW_FORM_strp");
-  uint64_t stringOffset = infoData.getU32(&infoOffset);
-  llvm::DataExtractor stringsData =
-    dataExtractorFromSection(normalizedFile, stringsSection);
-  return stringsData.getCStr(&stringOffset);
-}
-
-// FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
-//        inspection" code if possible.
-static llvm::Expected<TranslationUnitSource>
-readCompUnit(const NormalizedFile &normalizedFile,
-             const Section &info,
-             const Section &abbrev,
-             const Section &strings,
-             StringRef path) {
-  // FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
-  //        inspection" code if possible.
-  uint64_t offset = 0;
-  llvm::dwarf::DwarfFormat Format = llvm::dwarf::DwarfFormat::DWARF32;
-  auto infoData = dataExtractorFromSection(normalizedFile, info);
-  uint32_t length = infoData.getU32(&offset);
-  if (length == llvm::dwarf::DW_LENGTH_DWARF64) {
-    Format = llvm::dwarf::DwarfFormat::DWARF64;
-    infoData.getU64(&offset);
-  }
-  else if (length >= llvm::dwarf::DW_LENGTH_lo_reserved)
-    return llvm::make_error<GenericError>("Malformed DWARF in " + path);
-
-  uint16_t version = infoData.getU16(&offset);
-
-  if (version < 2 || version > 4)
-    return llvm::make_error<GenericError>("Unsupported DWARF version in " +
-                                          path);
-
-  infoData.getU32(&offset); // Abbrev offset (should be zero)
-  uint8_t addrSize = infoData.getU8(&offset);
-
-  uint32_t abbrCode = infoData.getULEB128(&offset);
-  auto abbrevData = dataExtractorFromSection(normalizedFile, abbrev);
-  uint64_t abbrevOffset = getCUAbbrevOffset(abbrevData, abbrCode);
-  uint64_t tag = abbrevData.getULEB128(&abbrevOffset);
-  if (tag != llvm::dwarf::DW_TAG_compile_unit)
-    return llvm::make_error<GenericError>("top level DIE is not a compile unit");
-  // DW_CHILDREN
-  abbrevData.getU8(&abbrevOffset);
-  uint32_t name;
-  llvm::dwarf::Form form;
-  llvm::dwarf::FormParams formParams = {version, addrSize, Format};
-  TranslationUnitSource tu;
-  while ((name = abbrevData.getULEB128(&abbrevOffset)) |
-         (form = static_cast<llvm::dwarf::Form>(
-             abbrevData.getULEB128(&abbrevOffset))) &&
-         (name != 0 || form != 0)) {
-    switch (name) {
-    case llvm::dwarf::DW_AT_name: {
-      if (auto eName = getIndexedString(normalizedFile, form, infoData, offset,
-                                        strings))
-          tu.name = *eName;
-      else
-        return eName.takeError();
-      break;
-    }
-    case llvm::dwarf::DW_AT_comp_dir: {
-      if (auto eName = getIndexedString(normalizedFile, form, infoData, offset,
-                                        strings))
-        tu.path = *eName;
-      else
-        return eName.takeError();
-      break;
-    }
-    default:
-      llvm::DWARFFormValue::skipValue(form, infoData, &offset, formParams);
-    }
-  }
-  return tu;
-}
-
-llvm::Error parseDebugInfo(MachOFile &file,
-                           const NormalizedFile &normalizedFile, bool copyRefs) {
-
-  // Find the interesting debug info sections.
-  const Section *debugInfo = nullptr;
-  const Section *debugAbbrev = nullptr;
-  const Section *debugStrings = nullptr;
-
-  for (auto &s : normalizedFile.sections) {
-    if (s.segmentName == "__DWARF") {
-      if (s.sectionName == "__debug_info")
-        debugInfo = &s;
-      else if (s.sectionName == "__debug_abbrev")
-        debugAbbrev = &s;
-      else if (s.sectionName == "__debug_str")
-        debugStrings = &s;
-    }
-  }
-
-  if (!debugInfo)
-    return parseStabs(file, normalizedFile, copyRefs);
-
-  if (debugInfo->content.size() == 0)
-    return llvm::Error::success();
-
-  if (debugInfo->content.size() < 12)
-    return llvm::make_error<GenericError>("Malformed __debug_info section in " +
-                                          file.path() + ": too small");
-
-  if (!debugAbbrev)
-    return llvm::make_error<GenericError>("Missing __dwarf_abbrev section in " +
-                                          file.path());
-
-  if (auto tuOrErr = readCompUnit(normalizedFile, *debugInfo, *debugAbbrev,
-                                  *debugStrings, file.path())) {
-    // FIXME: Kill of allocator and code under 'copyRefs' when we fix YAML
-    //        memory ownership.
-    std::unique_ptr<BumpPtrAllocator> allocator;
-    if (copyRefs) {
-      allocator = std::make_unique<BumpPtrAllocator>();
-      tuOrErr->name = copyDebugString(tuOrErr->name, *allocator);
-      tuOrErr->path = copyDebugString(tuOrErr->path, *allocator);
-    }
-    file.setDebugInfo(std::make_unique<DwarfDebugInfo>(std::move(*tuOrErr)));
-    if (copyRefs)
-      file.debugInfo()->setAllocator(std::move(allocator));
-  } else
-    return tuOrErr.takeError();
-
-  return llvm::Error::success();
-}
-
-static int64_t readSPtr(bool is64, bool isBig, const uint8_t *addr) {
-  if (is64)
-    return read64(addr, isBig);
-
-  int32_t res = read32(addr, isBig);
-  return res;
-}
-
-/// --- Augmentation String Processing ---
-
-struct CIEInfo {
-  bool _augmentationDataPresent = false;
-  bool _mayHaveEH = false;
-  uint32_t _offsetOfLSDA = ~0U;
-  uint32_t _offsetOfPersonality = ~0U;
-  uint32_t _offsetOfFDEPointerEncoding = ~0U;
-  uint32_t _augmentationDataLength = ~0U;
-};
-
-typedef llvm::DenseMap<const MachODefinedAtom*, CIEInfo> CIEInfoMap;
-
-static llvm::Error processAugmentationString(const uint8_t *augStr,
-                                             CIEInfo &cieInfo,
-                                             unsigned &len) {
-
-  if (augStr[0] == '\0') {
-    len = 1;
-    return llvm::Error::success();
-  }
-
-  if (augStr[0] != 'z')
-    return llvm::make_error<GenericError>("expected 'z' at start of "
-                                          "augmentation string");
-
-  cieInfo._augmentationDataPresent = true;
-  uint64_t idx = 1;
-
-  uint32_t offsetInAugmentationData = 0;
-  while (augStr[idx] != '\0') {
-    if (augStr[idx] == 'L') {
-      cieInfo._offsetOfLSDA = offsetInAugmentationData;
-      // This adds a single byte to the augmentation data.
-      ++offsetInAugmentationData;
-      ++idx;
-      continue;
-    }
-    if (augStr[idx] == 'P') {
-      cieInfo._offsetOfPersonality = offsetInAugmentationData;
-      // This adds a single byte to the augmentation data for the encoding,
-      // then a number of bytes for the pointer data.
-      // FIXME: We are assuming 4 is correct here for the pointer size as we
-      // always currently use delta32ToGOT.
-      offsetInAugmentationData += 5;
-      ++idx;
-      continue;
-    }
-    if (augStr[idx] == 'R') {
-      cieInfo._offsetOfFDEPointerEncoding = offsetInAugmentationData;
-      // This adds a single byte to the augmentation data.
-      ++offsetInAugmentationData;
-      ++idx;
-      continue;
-    }
-    if (augStr[idx] == 'e') {
-      if (augStr[idx + 1] != 'h')
-        return llvm::make_error<GenericError>("expected 'eh' in "
-                                              "augmentation string");
-      cieInfo._mayHaveEH = true;
-      idx += 2;
-      continue;
-    }
-    ++idx;
-  }
-
-  cieInfo._augmentationDataLength = offsetInAugmentationData;
-
-  len = idx + 1;
-  return llvm::Error::success();
-}
-
-static llvm::Error processCIE(const NormalizedFile &normalizedFile,
-                              MachOFile &file,
-                              mach_o::ArchHandler &handler,
-                              const Section *ehFrameSection,
-                              MachODefinedAtom *atom,
-                              uint64_t offset,
-                              CIEInfoMap &cieInfos) {
-  const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
-  const uint8_t *frameData = atom->rawContent().data();
-
-  CIEInfo cieInfo;
-
-  uint32_t size = read32(frameData, isBig);
-  uint64_t cieIDField = size == 0xffffffffU
-                          ? sizeof(uint32_t) + sizeof(uint64_t)
-                          : sizeof(uint32_t);
-  uint64_t versionField = cieIDField + sizeof(uint32_t);
-  uint64_t augmentationStringField = versionField + sizeof(uint8_t);
-
-  unsigned augmentationStringLength = 0;
-  if (auto err = processAugmentationString(frameData + augmentationStringField,
-                                           cieInfo, augmentationStringLength))
-    return err;
-
-  if (cieInfo._offsetOfPersonality != ~0U) {
-    // If we have augmentation data for the personality function, then we may
-    // need to implicitly generate its relocation.
-
-    // Parse the EH Data field which is pointer sized.
-    uint64_t EHDataField = augmentationStringField + augmentationStringLength;
-    const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
-    unsigned EHDataFieldSize = (cieInfo._mayHaveEH ? (is64 ? 8 : 4) : 0);
-
-    // Parse Code Align Factor which is a ULEB128.
-    uint64_t CodeAlignField = EHDataField + EHDataFieldSize;
-    unsigned lengthFieldSize = 0;
-    llvm::decodeULEB128(frameData + CodeAlignField, &lengthFieldSize);
-
-    // Parse Data Align Factor which is a SLEB128.
-    uint64_t DataAlignField = CodeAlignField + lengthFieldSize;
-    llvm::decodeSLEB128(frameData + DataAlignField, &lengthFieldSize);
-
-    // Parse Return Address Register which is a byte.
-    uint64_t ReturnAddressField = DataAlignField + lengthFieldSize;
-
-    // Parse the augmentation length which is a ULEB128.
-    uint64_t AugmentationLengthField = ReturnAddressField + 1;
-    uint64_t AugmentationLength =
-      llvm::decodeULEB128(frameData + AugmentationLengthField,
-                          &lengthFieldSize);
-
-    if (AugmentationLength != cieInfo._augmentationDataLength)
-      return llvm::make_error<GenericError>("CIE augmentation data length "
-                                            "mismatch");
-
-    // Get the start address of the augmentation data.
-    uint64_t AugmentationDataField = AugmentationLengthField + lengthFieldSize;
-
-    // Parse the personality function from the augmentation data.
-    uint64_t PersonalityField =
-      AugmentationDataField + cieInfo._offsetOfPersonality;
-
-    // Parse the personality encoding.
-    // FIXME: Verify that this is a 32-bit pcrel offset.
-    uint64_t PersonalityFunctionField = PersonalityField + 1;
-
-    if (atom->begin() != atom->end()) {
-      // If we have an explicit relocation, then make sure it matches this
-      // offset as this is where we'd expect it to be applied to.
-      DefinedAtom::reference_iterator CurrentRef = atom->begin();
-      if (CurrentRef->offsetInAtom() != PersonalityFunctionField)
-        return llvm::make_error<GenericError>("CIE personality reloc at "
-                                              "wrong offset");
-
-      if (++CurrentRef != atom->end())
-        return llvm::make_error<GenericError>("CIE contains too many relocs");
-    } else {
-      // Implicitly generate the personality function reloc.  It's assumed to
-      // be a delta32 offset to a GOT entry.
-      // FIXME: Parse the encoding and check this.
-      int32_t funcDelta = read32(frameData + PersonalityFunctionField, isBig);
-      uint64_t funcAddress = ehFrameSection->address + offset +
-                             PersonalityFunctionField;
-      funcAddress += funcDelta;
-
-      const MachODefinedAtom *func = nullptr;
-      Reference::Addend addend;
-      func = findAtomCoveringAddress(normalizedFile, file, funcAddress,
-                                     addend);
-      atom->addReference(Reference::KindNamespace::mach_o, handler.kindArch(),
-                         handler.unwindRefToPersonalityFunctionKind(),
-                         PersonalityFunctionField, func, addend);
-    }
-  } else if (atom->begin() != atom->end()) {
-    // Otherwise, we expect there to be no relocations in this atom as the only
-    // relocation would have been to the personality function.
-    return llvm::make_error<GenericError>("unexpected relocation in CIE");
-  }
-
-
-  cieInfos[atom] = std::move(cieInfo);
-
-  return llvm::Error::success();
-}
-
-static llvm::Error processFDE(const NormalizedFile &normalizedFile,
-                              MachOFile &file,
-                              mach_o::ArchHandler &handler,
-                              const Section *ehFrameSection,
-                              MachODefinedAtom *atom,
-                              uint64_t offset,
-                              const CIEInfoMap &cieInfos) {
-
-  const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
-  const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
-
-  // Compiler wasn't lazy and actually told us what it meant.
-  // Unfortunately, the compiler may not have generated references for all of
-  // [cie, func, lsda] and so we still need to parse the FDE and add references
-  // for any the compiler didn't generate.
-  if (atom->begin() != atom->end())
-    atom->sortReferences();
-
-  DefinedAtom::reference_iterator CurrentRef = atom->begin();
-
-  // This helper returns the reference (if one exists) at the offset we are
-  // currently processing.  It automatically increments the ref iterator if we
-  // do return a ref, and throws an error if we pass over a ref without
-  // comsuming it.
-  auto currentRefGetter = [&CurrentRef,
-                           &atom](uint64_t Offset)->const Reference* {
-    // If there are no more refs found, then we are done.
-    if (CurrentRef == atom->end())
-      return nullptr;
-
-    const Reference *Ref = *CurrentRef;
-
-    // If we haven't reached the offset for this reference, then return that
-    // we don't yet have a reference to process.
-    if (Offset < Ref->offsetInAtom())
-      return nullptr;
-
-    // If the offset is equal, then we want to process this ref.
-    if (Offset == Ref->offsetInAtom()) {
-      ++CurrentRef;
-      return Ref;
-    }
-
-    // The current ref is at an offset which is earlier than the current
-    // offset, then we failed to consume it when we should have.  In this case
-    // throw an error.
-    llvm::report_fatal_error("Skipped reference when processing FDE");
-  };
-
-  // Helper to either get the reference at this current location, and verify
-  // that it is of the expected type, or add a reference of that type.
-  // Returns the reference target.
-  auto verifyOrAddReference = [&](uint64_t targetAddress,
-                                  Reference::KindValue refKind,
-                                  uint64_t refAddress,
-                                  bool allowsAddend)->const Atom* {
-    if (auto *ref = currentRefGetter(refAddress)) {
-      // The compiler already emitted a relocation for the CIE ref.  This should
-      // have been converted to the correct type of reference in
-      // get[Pair]ReferenceInfo().
-      assert(ref->kindValue() == refKind &&
-             "Incorrect EHFrame reference kind");
-      return ref->target();
-    }
-    Reference::Addend addend;
-    auto *target = findAtomCoveringAddress(normalizedFile, file,
-                                           targetAddress, addend);
-    atom->addReference(Reference::KindNamespace::mach_o, handler.kindArch(),
-                       refKind, refAddress, target, addend);
-
-    if (!allowsAddend)
-      assert(!addend && "EHFrame reference cannot have addend");
-    return target;
-  };
-
-  const uint8_t *startFrameData = atom->rawContent().data();
-  const uint8_t *frameData = startFrameData;
-
-  uint32_t size = read32(frameData, isBig);
-  uint64_t cieFieldInFDE = size == 0xffffffffU
-    ? sizeof(uint32_t) + sizeof(uint64_t)
-    : sizeof(uint32_t);
-
-  // Linker needs to fixup a reference from the FDE to its parent CIE (a
-  // 32-bit byte offset backwards in the __eh_frame section).
-  uint32_t cieDelta = read32(frameData + cieFieldInFDE, isBig);
-  uint64_t cieAddress = ehFrameSection->address + offset + cieFieldInFDE;
-  cieAddress -= cieDelta;
-
-  auto *cieRefTarget = verifyOrAddReference(cieAddress,
-                                            handler.unwindRefToCIEKind(),
-                                            cieFieldInFDE, false);
-  const MachODefinedAtom *cie = dyn_cast<MachODefinedAtom>(cieRefTarget);
-  assert(cie && cie->contentType() == DefinedAtom::typeCFI &&
-         "FDE's CIE field does not point at the start of a CIE.");
-
-  const CIEInfo &cieInfo = cieInfos.find(cie)->second;
-
-  // Linker needs to fixup reference from the FDE to the function it's
-  // describing. FIXME: there are actually different ways to do this, and the
-  // particular method used is specified in the CIE's augmentation fields
-  // (hopefully)
-  uint64_t rangeFieldInFDE = cieFieldInFDE + sizeof(uint32_t);
-
-  int64_t functionFromFDE = readSPtr(is64, isBig,
-                                     frameData + rangeFieldInFDE);
-  uint64_t rangeStart = ehFrameSection->address + offset + rangeFieldInFDE;
-  rangeStart += functionFromFDE;
-
-  verifyOrAddReference(rangeStart,
-                       handler.unwindRefToFunctionKind(),
-                       rangeFieldInFDE, true);
-
-  // Handle the augmentation data if there is any.
-  if (cieInfo._augmentationDataPresent) {
-    // First process the augmentation data length field.
-    uint64_t augmentationDataLengthFieldInFDE =
-      rangeFieldInFDE + 2 * (is64 ? sizeof(uint64_t) : sizeof(uint32_t));
-    unsigned lengthFieldSize = 0;
-    uint64_t augmentationDataLength =
-      llvm::decodeULEB128(frameData + augmentationDataLengthFieldInFDE,
-                          &lengthFieldSize);
-
-    if (cieInfo._offsetOfLSDA != ~0U && augmentationDataLength > 0) {
-
-      // Look at the augmentation data field.
-      uint64_t augmentationDataFieldInFDE =
-        augmentationDataLengthFieldInFDE + lengthFieldSize;
-
-      int64_t lsdaFromFDE = readSPtr(is64, isBig,
-                                     frameData + augmentationDataFieldInFDE);
-      uint64_t lsdaStart =
-        ehFrameSection->address + offset + augmentationDataFieldInFDE +
-        lsdaFromFDE;
-
-      verifyOrAddReference(lsdaStart,
-                           handler.unwindRefToFunctionKind(),
-                           augmentationDataFieldInFDE, true);
-    }
-  }
-
-  return llvm::Error::success();
-}
-
-llvm::Error addEHFrameReferences(const NormalizedFile &normalizedFile,
-                                 MachOFile &file,
-                                 mach_o::ArchHandler &handler) {
-
-  const Section *ehFrameSection = nullptr;
-  for (auto &section : normalizedFile.sections)
-    if (section.segmentName == "__TEXT" &&
-        section.sectionName == "__eh_frame") {
-      ehFrameSection = &section;
-      break;
-    }
-
-  // No __eh_frame so nothing to do.
-  if (!ehFrameSection)
-    return llvm::Error::success();
-
-  llvm::Error ehFrameErr = llvm::Error::success();
-  CIEInfoMap cieInfos;
-
-  file.eachAtomInSection(*ehFrameSection,
-                         [&](MachODefinedAtom *atom, uint64_t offset) -> void {
-    assert(atom->contentType() == DefinedAtom::typeCFI);
-
-    // Bail out if we've encountered an error.
-    if (ehFrameErr)
-      return;
-
-    const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
-    if (ArchHandler::isDwarfCIE(isBig, atom))
-      ehFrameErr = processCIE(normalizedFile, file, handler, ehFrameSection,
-                              atom, offset, cieInfos);
-    else
-      ehFrameErr = processFDE(normalizedFile, file, handler, ehFrameSection,
-                              atom, offset, cieInfos);
-  });
-
-  return ehFrameErr;
-}
-
-llvm::Error parseObjCImageInfo(const Section &sect,
-                               const NormalizedFile &normalizedFile,
-                               MachOFile &file) {
-
-  //   struct objc_image_info  {
-  //           uint32_t        version;        // initially 0
-  //           uint32_t        flags;
-  //   };
-
-  ArrayRef<uint8_t> content = sect.content;
-  if (content.size() != 8)
-    return llvm::make_error<GenericError>(sect.segmentName + "/" +
-                                          sect.sectionName +
-                                          " in file " + file.path() +
-                                          " should be 8 bytes in size");
-
-  const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
-  uint32_t version = read32(content.data(), isBig);
-  if (version)
-    return llvm::make_error<GenericError>(sect.segmentName + "/" +
-                                          sect.sectionName +
-                                          " in file " + file.path() +
-                                          " should have version=0");
-
-  uint32_t flags = read32(content.data() + 4, isBig);
-  if (flags & (MachOLinkingContext::objc_supports_gc |
-               MachOLinkingContext::objc_gc_only))
-    return llvm::make_error<GenericError>(sect.segmentName + "/" +
-                                          sect.sectionName +
-                                          " in file " + file.path() +
-                                          " uses GC.  This is not supported");
-
-  if (flags & MachOLinkingContext::objc_retainReleaseForSimulator)
-    file.setObjcConstraint(MachOLinkingContext::objc_retainReleaseForSimulator);
-  else
-    file.setObjcConstraint(MachOLinkingContext::objc_retainRelease);
-
-  file.setSwiftVersion((flags >> 8) & 0xFF);
-
-  return llvm::Error::success();
-}
-
-/// Converts normalized mach-o file into an lld::File and lld::Atoms.
-llvm::Expected<std::unique_ptr<lld::File>>
-objectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
-              bool copyRefs) {
-  auto file = std::make_unique<MachOFile>(path);
-  if (auto ec = normalizedObjectToAtoms(file.get(), normalizedFile, copyRefs))
-    return std::move(ec);
-  return std::unique_ptr<File>(std::move(file));
-}
-
-llvm::Expected<std::unique_ptr<lld::File>>
-dylibToAtoms(const NormalizedFile &normalizedFile, StringRef path,
-             bool copyRefs) {
-  // Instantiate SharedLibraryFile object.
-  auto file = std::make_unique<MachODylibFile>(path);
-  if (auto ec = normalizedDylibToAtoms(file.get(), normalizedFile, copyRefs))
-    return std::move(ec);
-  return std::unique_ptr<File>(std::move(file));
-}
-
-} // anonymous namespace
-
-namespace normalized {
-
-static bool isObjCImageInfo(const Section &sect) {
-  return (sect.segmentName == "__OBJC" && sect.sectionName == "__image_info") ||
-    (sect.segmentName == "__DATA" && sect.sectionName == "__objc_imageinfo");
-}
-
-llvm::Error
-normalizedObjectToAtoms(MachOFile *file,
-                        const NormalizedFile &normalizedFile,
-                        bool copyRefs) {
-  LLVM_DEBUG(llvm::dbgs() << "******** Normalizing file to atoms: "
-                          << file->path() << "\n");
-  bool scatterable = ((normalizedFile.flags & MH_SUBSECTIONS_VIA_SYMBOLS) != 0);
-
-  // Create atoms from each section.
-  for (auto &sect : normalizedFile.sections) {
-
-    // If this is a debug-info section parse it specially.
-    if (isDebugInfoSection(sect))
-      continue;
-
-    // If the file contains an objc_image_info struct, then we should parse the
-    // ObjC flags and Swift version.
-    if (isObjCImageInfo(sect)) {
-      if (auto ec = parseObjCImageInfo(sect, normalizedFile, *file))
-        return ec;
-      // We then skip adding atoms for this section as we use the ObjCPass to
-      // re-emit this data after it has been aggregated for all files.
-      continue;
-    }
-
-    bool customSectionName;
-    DefinedAtom::ContentType atomType = atomTypeFromSection(sect,
-                                                            customSectionName);
-    if (auto ec =  processSection(atomType, sect, customSectionName,
-                                  normalizedFile, *file, scatterable, copyRefs))
-      return ec;
-  }
-  // Create atoms from undefined symbols.
-  for (auto &sym : normalizedFile.undefinedSymbols) {
-    // Undefined symbols with n_value != 0 are actually tentative definitions.
-    if (sym.value == Hex64(0)) {
-      file->addUndefinedAtom(sym.name, copyRefs);
-    } else {
-      file->addTentativeDefAtom(sym.name, atomScope(sym.scope), sym.value,
-                                DefinedAtom::Alignment(1 << (sym.desc >> 8)),
-                                copyRefs);
-    }
-  }
-
-  // Convert mach-o relocations to References
-  std::unique_ptr<mach_o::ArchHandler> handler
-                                     = ArchHandler::create(normalizedFile.arch);
-  for (auto &sect : normalizedFile.sections) {
-    if (isDebugInfoSection(sect))
-      continue;
-    if (llvm::Error ec = convertRelocs(sect, normalizedFile, scatterable,
-                                       *file, *handler))
-      return ec;
-  }
-
-  // Add additional arch-specific References
-  file->eachDefinedAtom([&](MachODefinedAtom* atom) -> void {
-    handler->addAdditionalReferences(*atom);
-  });
-
-  // Each __eh_frame section needs references to both __text (the function we're
-  // providing unwind info for) and itself (FDE -> CIE). These aren't
-  // represented in the relocations on some architectures, so we have to add
-  // them back in manually there.
-  if (auto ec = addEHFrameReferences(normalizedFile, *file, *handler))
-    return ec;
-
-  // Process mach-o data-in-code regions array. That information is encoded in
-  // atoms as References at each transition point.
-  unsigned nextIndex = 0;
-  for (const DataInCode &entry : normalizedFile.dataInCode) {
-    ++nextIndex;
-    const Section* s = findSectionCoveringAddress(normalizedFile, entry.offset);
-    if (!s) {
-      return llvm::make_error<GenericError>(Twine("LC_DATA_IN_CODE address ("
-                                                  + Twine(entry.offset)
-                                                  + ") is not in any section"));
-    }
-    uint64_t offsetInSect = entry.offset - s->address;
-    uint32_t offsetInAtom;
-    MachODefinedAtom *atom = file->findAtomCoveringAddress(*s, offsetInSect,
-                                                           &offsetInAtom);
-    if (offsetInAtom + entry.length > atom->size()) {
-      return llvm::make_error<GenericError>(Twine("LC_DATA_IN_CODE entry "
-                                                  "(offset="
-                                                  + Twine(entry.offset)
-                                                  + ", length="
-                                                  + Twine(entry.length)
-                                                  + ") crosses atom boundary."));
-    }
-    // Add reference that marks start of data-in-code.
-    atom->addReference(Reference::KindNamespace::mach_o, handler->kindArch(),
-                       handler->dataInCodeTransitionStart(*atom),
-                       offsetInAtom, atom, entry.kind);
-
-    // Peek at next entry, if it starts where this one ends, skip ending ref.
-    if (nextIndex < normalizedFile.dataInCode.size()) {
-      const DataInCode &nextEntry = normalizedFile.dataInCode[nextIndex];
-      if (nextEntry.offset == (entry.offset + entry.length))
-        continue;
-    }
-
-    // If data goes to end of function, skip ending ref.
-    if ((offsetInAtom + entry.length) == atom->size())
-      continue;
-
-    // Add reference that marks end of data-in-code.
-    atom->addReference(Reference::KindNamespace::mach_o, handler->kindArch(),
-                       handler->dataInCodeTransitionEnd(*atom),
-                       offsetInAtom+entry.length, atom, 0);
-  }
-
-  // Cache some attributes on the file for use later.
-  file->setFlags(normalizedFile.flags);
-  file->setArch(normalizedFile.arch);
-  file->setOS(normalizedFile.os);
-  file->setMinVersion(normalizedFile.minOSverson);
-  file->setMinVersionLoadCommandKind(normalizedFile.minOSVersionKind);
-
-  // Sort references in each atom to their canonical order.
-  for (const DefinedAtom* defAtom : file->defined()) {
-    reinterpret_cast<const SimpleDefinedAtom*>(defAtom)->sortReferences();
-  }
-
-  if (auto err = parseDebugInfo(*file, normalizedFile, copyRefs))
-    return err;
-
-  return llvm::Error::success();
-}
-
-llvm::Error
-normalizedDylibToAtoms(MachODylibFile *file,
-                       const NormalizedFile &normalizedFile,
-                       bool copyRefs) {
-  file->setInstallName(normalizedFile.installName);
-  file->setCompatVersion(normalizedFile.compatVersion);
-  file->setCurrentVersion(normalizedFile.currentVersion);
-
-  // Tell MachODylibFile object about all symbols it exports.
-  if (!normalizedFile.exportInfo.empty()) {
-    // If exports trie exists, use it instead of traditional symbol table.
-    for (const Export &exp : normalizedFile.exportInfo) {
-      bool weakDef = (exp.flags & EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
-      // StringRefs from export iterator are ephemeral, so force copy.
-      file->addExportedSymbol(exp.name, weakDef, true);
-    }
-  } else {
-    for (auto &sym : normalizedFile.globalSymbols) {
-      assert((sym.scope & N_EXT) && "only expect external symbols here");
-      bool weakDef = (sym.desc & N_WEAK_DEF);
-      file->addExportedSymbol(sym.name, weakDef, copyRefs);
-    }
-  }
-  // Tell MachODylibFile object about all dylibs it re-exports.
-  for (const DependentDylib &dep : normalizedFile.dependentDylibs) {
-    if (dep.kind == llvm::MachO::LC_REEXPORT_DYLIB)
-      file->addReExportedDylib(dep.path);
-  }
-  return llvm::Error::success();
-}
-
-void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
-                                          StringRef &segmentName,
-                                          StringRef &sectionName,
-                                          SectionType &sectionType,
-                                          SectionAttr &sectionAttrs,
-                                          bool &relocsToDefinedCanBeImplicit) {
-
-  for (const MachORelocatableSectionToAtomType *p = sectsToAtomType ;
-                                 p->atomType != DefinedAtom::typeUnknown; ++p) {
-    if (p->atomType != atomType)
-      continue;
-    // Wild carded entries are ignored for reverse lookups.
-    if (p->segmentName.empty() || p->sectionName.empty())
-      continue;
-    segmentName = p->segmentName;
-    sectionName = p->sectionName;
-    sectionType = p->sectionType;
-    sectionAttrs = 0;
-    relocsToDefinedCanBeImplicit = false;
-    if (atomType == DefinedAtom::typeCode)
-      sectionAttrs = S_ATTR_PURE_INSTRUCTIONS;
-    if (atomType == DefinedAtom::typeCFI)
-      relocsToDefinedCanBeImplicit = true;
-    return;
-  }
-  llvm_unreachable("content type not yet supported");
-}
-
-llvm::Expected<std::unique_ptr<lld::File>>
-normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
-                  bool copyRefs) {
-  switch (normalizedFile.fileType) {
-  case MH_DYLIB:
-  case MH_DYLIB_STUB:
-    return dylibToAtoms(normalizedFile, path, copyRefs);
-  case MH_OBJECT:
-    return objectToAtoms(normalizedFile, path, copyRefs);
-  default:
-    llvm_unreachable("unhandled MachO file type!");
-  }
-}
-
-} // namespace normalized
-} // namespace mach_o
-} // namespace lld
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp b/gnu/llvm/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
deleted file mode 100644 (file)
index 3826e97..0000000
+++ /dev/null
@@ -1,840 +0,0 @@
-//===- lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp -----------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-///
-/// \file For mach-o object files, this implementation uses YAML I/O to
-/// provide the convert between YAML and the normalized mach-o (NM).
-///
-///                  +------------+         +------+
-///                  | normalized |   <->   | yaml |
-///                  +------------+         +------+
-
-#include "MachONormalizedFile.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/Error.h"
-#include "lld/ReaderWriter/YamlContext.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/YAMLTraits.h"
-#include "llvm/Support/raw_ostream.h"
-#include <system_error>
-
-using llvm::StringRef;
-using namespace llvm::yaml;
-using namespace llvm::MachO;
-using namespace lld::mach_o::normalized;
-using lld::YamlContext;
-
-LLVM_YAML_IS_SEQUENCE_VECTOR(Segment)
-LLVM_YAML_IS_SEQUENCE_VECTOR(DependentDylib)
-LLVM_YAML_IS_SEQUENCE_VECTOR(RebaseLocation)
-LLVM_YAML_IS_SEQUENCE_VECTOR(BindLocation)
-LLVM_YAML_IS_SEQUENCE_VECTOR(Export)
-LLVM_YAML_IS_SEQUENCE_VECTOR(DataInCode)
-
-
-// for compatibility with gcc-4.7 in C++11 mode, add extra namespace
-namespace llvm {
-namespace yaml {
-
-// A vector of Sections is a sequence.
-template<>
-struct SequenceTraits< std::vector<Section> > {
-  static size_t size(IO &io, std::vector<Section> &seq) {
-    return seq.size();
-  }
-  static Section& element(IO &io, std::vector<Section> &seq, size_t index) {
-    if ( index >= seq.size() )
-      seq.resize(index+1);
-    return seq[index];
-  }
-};
-
-template<>
-struct SequenceTraits< std::vector<Symbol> > {
-  static size_t size(IO &io, std::vector<Symbol> &seq) {
-    return seq.size();
-  }
-  static Symbol& element(IO &io, std::vector<Symbol> &seq, size_t index) {
-    if ( index >= seq.size() )
-      seq.resize(index+1);
-    return seq[index];
-  }
-};
-
-// A vector of Relocations is a sequence.
-template<>
-struct SequenceTraits< Relocations > {
-  static size_t size(IO &io, Relocations &seq) {
-    return seq.size();
-  }
-  static Relocation& element(IO &io, Relocations &seq, size_t index) {
-    if ( index >= seq.size() )
-      seq.resize(index+1);
-    return seq[index];
-  }
-};
-
-// The content for a section is represented as a flow sequence of hex bytes.
-template<>
-struct SequenceTraits< ContentBytes > {
-  static size_t size(IO &io, ContentBytes &seq) {
-    return seq.size();
-  }
-  static Hex8& element(IO &io, ContentBytes &seq, size_t index) {
-    if ( index >= seq.size() )
-      seq.resize(index+1);
-    return seq[index];
-  }
-  static const bool flow = true;
-};
-
-// The indirect symbols for a section is represented as a flow sequence
-// of numbers (symbol table indexes).
-template<>
-struct SequenceTraits< IndirectSymbols > {
-  static size_t size(IO &io, IndirectSymbols &seq) {
-    return seq.size();
-  }
-  static uint32_t& element(IO &io, IndirectSymbols &seq, size_t index) {
-    if ( index >= seq.size() )
-      seq.resize(index+1);
-    return seq[index];
-  }
-  static const bool flow = true;
-};
-
-template <>
-struct ScalarEnumerationTraits<lld::MachOLinkingContext::Arch> {
-  static void enumeration(IO &io, lld::MachOLinkingContext::Arch &value) {
-    io.enumCase(value, "unknown",lld::MachOLinkingContext::arch_unknown);
-    io.enumCase(value, "ppc",    lld::MachOLinkingContext::arch_ppc);
-    io.enumCase(value, "x86",    lld::MachOLinkingContext::arch_x86);
-    io.enumCase(value, "x86_64", lld::MachOLinkingContext::arch_x86_64);
-    io.enumCase(value, "armv6",  lld::MachOLinkingContext::arch_armv6);
-    io.enumCase(value, "armv7",  lld::MachOLinkingContext::arch_armv7);
-    io.enumCase(value, "armv7s", lld::MachOLinkingContext::arch_armv7s);
-    io.enumCase(value, "arm64",  lld::MachOLinkingContext::arch_arm64);
-  }
-};
-
-template <>
-struct ScalarEnumerationTraits<lld::MachOLinkingContext::OS> {
-  static void enumeration(IO &io, lld::MachOLinkingContext::OS &value) {
-    io.enumCase(value, "unknown",
-                          lld::MachOLinkingContext::OS::unknown);
-    io.enumCase(value, "Mac OS X",
-                          lld::MachOLinkingContext::OS::macOSX);
-    io.enumCase(value, "iOS",
-                          lld::MachOLinkingContext::OS::iOS);
-    io.enumCase(value, "iOS Simulator",
-                          lld::MachOLinkingContext::OS::iOS_simulator);
-  }
-};
-
-
-template <>
-struct ScalarEnumerationTraits<HeaderFileType> {
-  static void enumeration(IO &io, HeaderFileType &value) {
-    io.enumCase(value, "MH_OBJECT",   llvm::MachO::MH_OBJECT);
-    io.enumCase(value, "MH_DYLIB",    llvm::MachO::MH_DYLIB);
-    io.enumCase(value, "MH_EXECUTE",  llvm::MachO::MH_EXECUTE);
-    io.enumCase(value, "MH_BUNDLE",   llvm::MachO::MH_BUNDLE);
-  }
-};
-
-
-template <>
-struct ScalarBitSetTraits<FileFlags> {
-  static void bitset(IO &io, FileFlags &value) {
-    io.bitSetCase(value, "MH_TWOLEVEL",
-                          llvm::MachO::MH_TWOLEVEL);
-    io.bitSetCase(value, "MH_SUBSECTIONS_VIA_SYMBOLS",
-                          llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
-  }
-};
-
-
-template <>
-struct ScalarEnumerationTraits<SectionType> {
-  static void enumeration(IO &io, SectionType &value) {
-    io.enumCase(value, "S_REGULAR",
-                        llvm::MachO::S_REGULAR);
-    io.enumCase(value, "S_ZEROFILL",
-                        llvm::MachO::S_ZEROFILL);
-    io.enumCase(value, "S_CSTRING_LITERALS",
-                        llvm::MachO::S_CSTRING_LITERALS);
-    io.enumCase(value, "S_4BYTE_LITERALS",
-                        llvm::MachO::S_4BYTE_LITERALS);
-    io.enumCase(value, "S_8BYTE_LITERALS",
-                        llvm::MachO::S_8BYTE_LITERALS);
-    io.enumCase(value, "S_LITERAL_POINTERS",
-                        llvm::MachO::S_LITERAL_POINTERS);
-    io.enumCase(value, "S_NON_LAZY_SYMBOL_POINTERS",
-                        llvm::MachO::S_NON_LAZY_SYMBOL_POINTERS);
-    io.enumCase(value, "S_LAZY_SYMBOL_POINTERS",
-                        llvm::MachO::S_LAZY_SYMBOL_POINTERS);
-    io.enumCase(value, "S_SYMBOL_STUBS",
-                        llvm::MachO::S_SYMBOL_STUBS);
-    io.enumCase(value, "S_MOD_INIT_FUNC_POINTERS",
-                        llvm::MachO::S_MOD_INIT_FUNC_POINTERS);
-    io.enumCase(value, "S_MOD_TERM_FUNC_POINTERS",
-                        llvm::MachO::S_MOD_TERM_FUNC_POINTERS);
-    io.enumCase(value, "S_COALESCED",
-                        llvm::MachO::S_COALESCED);
-    io.enumCase(value, "S_GB_ZEROFILL",
-                        llvm::MachO::S_GB_ZEROFILL);
-    io.enumCase(value, "S_INTERPOSING",
-                        llvm::MachO::S_INTERPOSING);
-    io.enumCase(value, "S_16BYTE_LITERALS",
-                        llvm::MachO::S_16BYTE_LITERALS);
-    io.enumCase(value, "S_DTRACE_DOF",
-                        llvm::MachO::S_DTRACE_DOF);
-    io.enumCase(value, "S_LAZY_DYLIB_SYMBOL_POINTERS",
-                        llvm::MachO::S_LAZY_DYLIB_SYMBOL_POINTERS);
-    io.enumCase(value, "S_THREAD_LOCAL_REGULAR",
-                        llvm::MachO::S_THREAD_LOCAL_REGULAR);
-    io.enumCase(value, "S_THREAD_LOCAL_ZEROFILL",
-                        llvm::MachO::S_THREAD_LOCAL_ZEROFILL);
-    io.enumCase(value, "S_THREAD_LOCAL_VARIABLES",
-                        llvm::MachO::S_THREAD_LOCAL_VARIABLES);
-    io.enumCase(value, "S_THREAD_LOCAL_VARIABLE_POINTERS",
-                        llvm::MachO::S_THREAD_LOCAL_VARIABLE_POINTERS);
-    io.enumCase(value, "S_THREAD_LOCAL_INIT_FUNCTION_POINTERS",
-                        llvm::MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS);
-  }
-};
-
-template <>
-struct ScalarBitSetTraits<SectionAttr> {
-  static void bitset(IO &io, SectionAttr &value) {
-    io.bitSetCase(value, "S_ATTR_PURE_INSTRUCTIONS",
-                          llvm::MachO::S_ATTR_PURE_INSTRUCTIONS);
-    io.bitSetCase(value, "S_ATTR_SOME_INSTRUCTIONS",
-                          llvm::MachO::S_ATTR_SOME_INSTRUCTIONS);
-    io.bitSetCase(value, "S_ATTR_NO_DEAD_STRIP",
-                          llvm::MachO::S_ATTR_NO_DEAD_STRIP);
-    io.bitSetCase(value, "S_ATTR_EXT_RELOC",
-                          llvm::MachO::S_ATTR_EXT_RELOC);
-    io.bitSetCase(value, "S_ATTR_LOC_RELOC",
-                          llvm::MachO::S_ATTR_LOC_RELOC);
-    io.bitSetCase(value, "S_ATTR_DEBUG",
-                         llvm::MachO::S_ATTR_DEBUG);
-  }
-};
-
-/// This is a custom formatter for SectionAlignment.  Values are
-/// the power to raise by, ie, the n in 2^n.
-template <> struct ScalarTraits<SectionAlignment> {
-  static void output(const SectionAlignment &value, void *ctxt,
-                     raw_ostream &out) {
-    out << llvm::format("%d", (uint32_t)value);
-  }
-
-  static StringRef input(StringRef scalar, void *ctxt,
-                         SectionAlignment &value) {
-    uint32_t alignment;
-    if (scalar.getAsInteger(0, alignment)) {
-      return "malformed alignment value";
-    }
-    if (!llvm::isPowerOf2_32(alignment))
-      return "alignment must be a power of 2";
-    value = alignment;
-    return StringRef(); // returning empty string means success
-  }
-
-  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
-};
-
-template <>
-struct ScalarEnumerationTraits<NListType> {
-  static void enumeration(IO &io, NListType &value) {
-    io.enumCase(value, "N_UNDF",  llvm::MachO::N_UNDF);
-    io.enumCase(value, "N_ABS",   llvm::MachO::N_ABS);
-    io.enumCase(value, "N_SECT",  llvm::MachO::N_SECT);
-    io.enumCase(value, "N_PBUD",  llvm::MachO::N_PBUD);
-    io.enumCase(value, "N_INDR",  llvm::MachO::N_INDR);
-  }
-};
-
-template <>
-struct ScalarBitSetTraits<SymbolScope> {
-  static void bitset(IO &io, SymbolScope &value) {
-    io.bitSetCase(value, "N_EXT",   llvm::MachO::N_EXT);
-    io.bitSetCase(value, "N_PEXT",  llvm::MachO::N_PEXT);
-  }
-};
-
-template <>
-struct ScalarBitSetTraits<SymbolDesc> {
-  static void bitset(IO &io, SymbolDesc &value) {
-    io.bitSetCase(value, "N_NO_DEAD_STRIP",   llvm::MachO::N_NO_DEAD_STRIP);
-    io.bitSetCase(value, "N_WEAK_REF",        llvm::MachO::N_WEAK_REF);
-    io.bitSetCase(value, "N_WEAK_DEF",        llvm::MachO::N_WEAK_DEF);
-    io.bitSetCase(value, "N_ARM_THUMB_DEF",   llvm::MachO::N_ARM_THUMB_DEF);
-    io.bitSetCase(value, "N_SYMBOL_RESOLVER", llvm::MachO::N_SYMBOL_RESOLVER);
-  }
-};
-
-
-template <>
-struct MappingTraits<Section> {
-  struct NormalizedContentBytes;
-  static void mapping(IO &io, Section &sect) {
-    io.mapRequired("segment",         sect.segmentName);
-    io.mapRequired("section",         sect.sectionName);
-    io.mapRequired("type",            sect.type);
-    io.mapOptional("attributes",      sect.attributes);
-    io.mapOptional("alignment",       sect.alignment, (SectionAlignment)1);
-    io.mapRequired("address",         sect.address);
-    if (isZeroFillSection(sect.type)) {
-      // S_ZEROFILL sections use "size:" instead of "content:"
-      uint64_t size = sect.content.size();
-      io.mapOptional("size",          size);
-      if (!io.outputting()) {
-        uint8_t *bytes = nullptr;
-        sect.content = makeArrayRef(bytes, size);
-      }
-    } else {
-      MappingNormalization<NormalizedContent, ArrayRef<uint8_t>> content(
-        io, sect.content);
-      io.mapOptional("content",         content->_normalizedContent);
-    }
-    io.mapOptional("relocations",     sect.relocations);
-    io.mapOptional("indirect-syms",   sect.indirectSymbols);
-  }
-
-  struct NormalizedContent {
-    NormalizedContent(IO &io) : _io(io) {}
-    NormalizedContent(IO &io, ArrayRef<uint8_t> content) : _io(io) {
-      // When writing yaml, copy content byte array to Hex8 vector.
-      for (auto &c : content) {
-        _normalizedContent.push_back(c);
-      }
-    }
-    ArrayRef<uint8_t> denormalize(IO &io) {
-      // When reading yaml, allocate byte array owned by NormalizedFile and
-      // copy Hex8 vector to byte array.
-      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-      assert(info != nullptr);
-      NormalizedFile *file = info->_normalizeMachOFile;
-      assert(file != nullptr);
-      size_t size = _normalizedContent.size();
-      if (!size)
-        return None;
-      uint8_t *bytes = file->ownedAllocations.Allocate<uint8_t>(size);
-      std::copy(_normalizedContent.begin(), _normalizedContent.end(), bytes);
-      return makeArrayRef(bytes, size);
-    }
-
-    IO                &_io;
-    ContentBytes       _normalizedContent;
-  };
-};
-
-
-template <>
-struct MappingTraits<Relocation> {
-  static void mapping(IO &io, Relocation &reloc) {
-    io.mapRequired("offset",    reloc.offset);
-    io.mapOptional("scattered", reloc.scattered, false);
-    io.mapRequired("type",      reloc.type);
-    io.mapRequired("length",    reloc.length);
-    io.mapRequired("pc-rel",    reloc.pcRel);
-    if ( !reloc.scattered )
-     io.mapRequired("extern",   reloc.isExtern);
-    if ( reloc.scattered )
-     io.mapRequired("value",    reloc.value);
-    if ( !reloc.scattered )
-     io.mapRequired("symbol",   reloc.symbol);
-  }
-};
-
-
-template <>
-struct ScalarEnumerationTraits<RelocationInfoType> {
-  static void enumeration(IO &io, RelocationInfoType &value) {
-    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-    assert(info != nullptr);
-    NormalizedFile *file = info->_normalizeMachOFile;
-    assert(file != nullptr);
-    switch (file->arch) {
-    case lld::MachOLinkingContext::arch_x86_64:
-      io.enumCase(value, "X86_64_RELOC_UNSIGNED",
-                                  llvm::MachO::X86_64_RELOC_UNSIGNED);
-      io.enumCase(value, "X86_64_RELOC_SIGNED",
-                                  llvm::MachO::X86_64_RELOC_SIGNED);
-      io.enumCase(value, "X86_64_RELOC_BRANCH",
-                                  llvm::MachO::X86_64_RELOC_BRANCH);
-      io.enumCase(value, "X86_64_RELOC_GOT_LOAD",
-                                  llvm::MachO::X86_64_RELOC_GOT_LOAD);
-      io.enumCase(value, "X86_64_RELOC_GOT",
-                                  llvm::MachO::X86_64_RELOC_GOT);
-      io.enumCase(value, "X86_64_RELOC_SUBTRACTOR",
-                                  llvm::MachO::X86_64_RELOC_SUBTRACTOR);
-      io.enumCase(value, "X86_64_RELOC_SIGNED_1",
-                                  llvm::MachO::X86_64_RELOC_SIGNED_1);
-      io.enumCase(value, "X86_64_RELOC_SIGNED_2",
-                                  llvm::MachO::X86_64_RELOC_SIGNED_2);
-      io.enumCase(value, "X86_64_RELOC_SIGNED_4",
-                                  llvm::MachO::X86_64_RELOC_SIGNED_4);
-      io.enumCase(value, "X86_64_RELOC_TLV",
-                                  llvm::MachO::X86_64_RELOC_TLV);
-      break;
-    case lld::MachOLinkingContext::arch_x86:
-      io.enumCase(value, "GENERIC_RELOC_VANILLA",
-                                  llvm::MachO::GENERIC_RELOC_VANILLA);
-      io.enumCase(value, "GENERIC_RELOC_PAIR",
-                                  llvm::MachO::GENERIC_RELOC_PAIR);
-      io.enumCase(value, "GENERIC_RELOC_SECTDIFF",
-                                  llvm::MachO::GENERIC_RELOC_SECTDIFF);
-      io.enumCase(value, "GENERIC_RELOC_LOCAL_SECTDIFF",
-                                  llvm::MachO::GENERIC_RELOC_LOCAL_SECTDIFF);
-      io.enumCase(value, "GENERIC_RELOC_TLV",
-                                  llvm::MachO::GENERIC_RELOC_TLV);
-      break;
-    case lld::MachOLinkingContext::arch_armv6:
-    case lld::MachOLinkingContext::arch_armv7:
-    case lld::MachOLinkingContext::arch_armv7s:
-       io.enumCase(value, "ARM_RELOC_VANILLA",
-                                  llvm::MachO::ARM_RELOC_VANILLA);
-      io.enumCase(value, "ARM_RELOC_PAIR",
-                                  llvm::MachO::ARM_RELOC_PAIR);
-      io.enumCase(value, "ARM_RELOC_SECTDIFF",
-                                  llvm::MachO::ARM_RELOC_SECTDIFF);
-      io.enumCase(value, "ARM_RELOC_LOCAL_SECTDIFF",
-                                  llvm::MachO::ARM_RELOC_LOCAL_SECTDIFF);
-      io.enumCase(value, "ARM_RELOC_BR24",
-                                  llvm::MachO::ARM_RELOC_BR24);
-      io.enumCase(value, "ARM_THUMB_RELOC_BR22",
-                                  llvm::MachO::ARM_THUMB_RELOC_BR22);
-      io.enumCase(value, "ARM_RELOC_HALF",
-                                  llvm::MachO::ARM_RELOC_HALF);
-      io.enumCase(value, "ARM_RELOC_HALF_SECTDIFF",
-                                  llvm::MachO::ARM_RELOC_HALF_SECTDIFF);
-      break;
-    case lld::MachOLinkingContext::arch_arm64:
-      io.enumCase(value, "ARM64_RELOC_UNSIGNED",
-                                  llvm::MachO::ARM64_RELOC_UNSIGNED);
-      io.enumCase(value, "ARM64_RELOC_SUBTRACTOR",
-                                  llvm::MachO::ARM64_RELOC_SUBTRACTOR);
-      io.enumCase(value, "ARM64_RELOC_BRANCH26",
-                                  llvm::MachO::ARM64_RELOC_BRANCH26);
-      io.enumCase(value, "ARM64_RELOC_PAGE21",
-                                  llvm::MachO::ARM64_RELOC_PAGE21);
-      io.enumCase(value, "ARM64_RELOC_PAGEOFF12",
-                                  llvm::MachO::ARM64_RELOC_PAGEOFF12);
-      io.enumCase(value, "ARM64_RELOC_GOT_LOAD_PAGE21",
-                                  llvm::MachO::ARM64_RELOC_GOT_LOAD_PAGE21);
-      io.enumCase(value, "ARM64_RELOC_GOT_LOAD_PAGEOFF12",
-                                  llvm::MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12);
-      io.enumCase(value, "ARM64_RELOC_POINTER_TO_GOT",
-                                  llvm::MachO::ARM64_RELOC_POINTER_TO_GOT);
-      io.enumCase(value, "ARM64_RELOC_TLVP_LOAD_PAGE21",
-                                  llvm::MachO::ARM64_RELOC_TLVP_LOAD_PAGE21);
-      io.enumCase(value, "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
-                                  llvm::MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12);
-      io.enumCase(value, "ARM64_RELOC_ADDEND",
-                                  llvm::MachO::ARM64_RELOC_ADDEND);
-      break;
-    default:
-      llvm_unreachable("unknown architecture");
-    }
- }
-};
-
-
-template <>
-struct MappingTraits<Symbol> {
-  static void mapping(IO &io, Symbol& sym) {
-    io.mapRequired("name",    sym.name);
-    io.mapRequired("type",    sym.type);
-    io.mapOptional("scope",   sym.scope, SymbolScope(0));
-    io.mapOptional("sect",    sym.sect, (uint8_t)0);
-    if (sym.type == llvm::MachO::N_UNDF) {
-      // In undef symbols, desc field contains alignment/ordinal info
-      // which is better represented as a hex vaule.
-      uint16_t t1 = sym.desc;
-      Hex16 t2 = t1;
-      io.mapOptional("desc",  t2, Hex16(0));
-      sym.desc = t2;
-    } else {
-      // In defined symbols, desc fit is a set of option bits.
-      io.mapOptional("desc",    sym.desc, SymbolDesc(0));
-    }
-    io.mapRequired("value",  sym.value);
-  }
-};
-
-// Custom mapping for VMProtect (e.g. "r-x").
-template <>
-struct ScalarTraits<VMProtect> {
-  static void output(const VMProtect &value, void*, raw_ostream &out) {
-    out << ( (value & llvm::MachO::VM_PROT_READ)    ? 'r' : '-');
-    out << ( (value & llvm::MachO::VM_PROT_WRITE)   ? 'w' : '-');
-    out << ( (value & llvm::MachO::VM_PROT_EXECUTE) ? 'x' : '-');
-  }
-  static StringRef input(StringRef scalar, void*, VMProtect &value) {
-    value = 0;
-    if (scalar.size() != 3)
-      return "segment access protection must be three chars (e.g. \"r-x\")";
-    switch (scalar[0]) {
-    case 'r':
-      value = llvm::MachO::VM_PROT_READ;
-      break;
-    case '-':
-      break;
-    default:
-      return "segment access protection first char must be 'r' or '-'";
-    }
-    switch (scalar[1]) {
-    case 'w':
-      value = value | llvm::MachO::VM_PROT_WRITE;
-      break;
-    case '-':
-      break;
-    default:
-      return "segment access protection second char must be 'w' or '-'";
-    }
-    switch (scalar[2]) {
-    case 'x':
-      value = value | llvm::MachO::VM_PROT_EXECUTE;
-      break;
-    case '-':
-      break;
-    default:
-      return "segment access protection third char must be 'x' or '-'";
-    }
-    // Return the empty string on success,
-    return StringRef();
-  }
-  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
-};
-
-
-template <>
-struct MappingTraits<Segment> {
-  static void mapping(IO &io, Segment& seg) {
-    io.mapRequired("name",            seg.name);
-    io.mapRequired("address",         seg.address);
-    io.mapRequired("size",            seg.size);
-    io.mapRequired("init-access",     seg.init_access);
-    io.mapRequired("max-access",      seg.max_access);
-  }
-};
-
-template <>
-struct ScalarEnumerationTraits<LoadCommandType> {
-  static void enumeration(IO &io, LoadCommandType &value) {
-    io.enumCase(value, "LC_LOAD_DYLIB",
-                        llvm::MachO::LC_LOAD_DYLIB);
-    io.enumCase(value, "LC_LOAD_WEAK_DYLIB",
-                        llvm::MachO::LC_LOAD_WEAK_DYLIB);
-    io.enumCase(value, "LC_REEXPORT_DYLIB",
-                        llvm::MachO::LC_REEXPORT_DYLIB);
-    io.enumCase(value, "LC_LOAD_UPWARD_DYLIB",
-                        llvm::MachO::LC_LOAD_UPWARD_DYLIB);
-    io.enumCase(value, "LC_LAZY_LOAD_DYLIB",
-                        llvm::MachO::LC_LAZY_LOAD_DYLIB);
-    io.enumCase(value, "LC_VERSION_MIN_MACOSX",
-                        llvm::MachO::LC_VERSION_MIN_MACOSX);
-    io.enumCase(value, "LC_VERSION_MIN_IPHONEOS",
-                        llvm::MachO::LC_VERSION_MIN_IPHONEOS);
-    io.enumCase(value, "LC_VERSION_MIN_TVOS",
-                        llvm::MachO::LC_VERSION_MIN_TVOS);
-    io.enumCase(value, "LC_VERSION_MIN_WATCHOS",
-                        llvm::MachO::LC_VERSION_MIN_WATCHOS);
-  }
-};
-
-template <>
-struct MappingTraits<DependentDylib> {
-  static void mapping(IO &io, DependentDylib& dylib) {
-    io.mapRequired("path",            dylib.path);
-    io.mapOptional("kind",            dylib.kind,
-                                      llvm::MachO::LC_LOAD_DYLIB);
-    io.mapOptional("compat-version",  dylib.compatVersion,
-                                      PackedVersion(0x10000));
-    io.mapOptional("current-version", dylib.currentVersion,
-                                      PackedVersion(0x10000));
-  }
-};
-
-template <>
-struct ScalarEnumerationTraits<RebaseType> {
-  static void enumeration(IO &io, RebaseType &value) {
-    io.enumCase(value, "REBASE_TYPE_POINTER",
-                        llvm::MachO::REBASE_TYPE_POINTER);
-    io.enumCase(value, "REBASE_TYPE_TEXT_PCREL32",
-                        llvm::MachO::REBASE_TYPE_TEXT_PCREL32);
-    io.enumCase(value, "REBASE_TYPE_TEXT_ABSOLUTE32",
-                        llvm::MachO::REBASE_TYPE_TEXT_ABSOLUTE32);
-  }
-};
-
-
-template <>
-struct MappingTraits<RebaseLocation> {
-  static void mapping(IO &io, RebaseLocation& rebase) {
-    io.mapRequired("segment-index",   rebase.segIndex);
-    io.mapRequired("segment-offset",  rebase.segOffset);
-    io.mapOptional("kind",            rebase.kind,
-                                      llvm::MachO::REBASE_TYPE_POINTER);
-  }
-};
-
-
-
-template <>
-struct ScalarEnumerationTraits<BindType> {
-  static void enumeration(IO &io, BindType &value) {
-    io.enumCase(value, "BIND_TYPE_POINTER",
-                        llvm::MachO::BIND_TYPE_POINTER);
-    io.enumCase(value, "BIND_TYPE_TEXT_ABSOLUTE32",
-                        llvm::MachO::BIND_TYPE_TEXT_ABSOLUTE32);
-    io.enumCase(value, "BIND_TYPE_TEXT_PCREL32",
-                        llvm::MachO::BIND_TYPE_TEXT_PCREL32);
-  }
-};
-
-template <>
-struct MappingTraits<BindLocation> {
-  static void mapping(IO &io, BindLocation &bind) {
-    io.mapRequired("segment-index",   bind.segIndex);
-    io.mapRequired("segment-offset",  bind.segOffset);
-    io.mapOptional("kind",            bind.kind,
-                                      llvm::MachO::BIND_TYPE_POINTER);
-    io.mapOptional("can-be-null",     bind.canBeNull, false);
-    io.mapRequired("ordinal",         bind.ordinal);
-    io.mapRequired("symbol-name",     bind.symbolName);
-    io.mapOptional("addend",          bind.addend, Hex64(0));
-  }
-};
-
-
-template <>
-struct ScalarEnumerationTraits<ExportSymbolKind> {
-  static void enumeration(IO &io, ExportSymbolKind &value) {
-    io.enumCase(value, "EXPORT_SYMBOL_FLAGS_KIND_REGULAR",
-                        llvm::MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR);
-    io.enumCase(value, "EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL",
-                        llvm::MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL);
-    io.enumCase(value, "EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE",
-                        llvm::MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
-  }
-};
-
-template <>
-struct ScalarBitSetTraits<ExportFlags> {
-  static void bitset(IO &io, ExportFlags &value) {
-    io.bitSetCase(value, "EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION",
-                          llvm::MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
-    io.bitSetCase(value, "EXPORT_SYMBOL_FLAGS_REEXPORT",
-                          llvm::MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
-    io.bitSetCase(value, "EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER",
-                          llvm::MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
-  }
-};
-
-
-template <>
-struct MappingTraits<Export> {
-  static void mapping(IO &io, Export &exp) {
-    io.mapRequired("name",         exp.name);
-    io.mapOptional("offset",       exp.offset);
-    io.mapOptional("kind",         exp.kind,
-                                llvm::MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR);
-    if (!io.outputting() || exp.flags)
-      io.mapOptional("flags",      exp.flags);
-    io.mapOptional("other",        exp.otherOffset, Hex32(0));
-    io.mapOptional("other-name",   exp.otherName, StringRef());
-  }
-};
-
-template <>
-struct ScalarEnumerationTraits<DataRegionType> {
-  static void enumeration(IO &io, DataRegionType &value) {
-    io.enumCase(value, "DICE_KIND_DATA",
-                        llvm::MachO::DICE_KIND_DATA);
-    io.enumCase(value, "DICE_KIND_JUMP_TABLE8",
-                        llvm::MachO::DICE_KIND_JUMP_TABLE8);
-    io.enumCase(value, "DICE_KIND_JUMP_TABLE16",
-                        llvm::MachO::DICE_KIND_JUMP_TABLE16);
-    io.enumCase(value, "DICE_KIND_JUMP_TABLE32",
-                        llvm::MachO::DICE_KIND_JUMP_TABLE32);
-    io.enumCase(value, "DICE_KIND_ABS_JUMP_TABLE32",
-                        llvm::MachO::DICE_KIND_ABS_JUMP_TABLE32);
-  }
-};
-
-template <>
-struct MappingTraits<DataInCode> {
-  static void mapping(IO &io, DataInCode &entry) {
-    io.mapRequired("offset",       entry.offset);
-    io.mapRequired("length",       entry.length);
-    io.mapRequired("kind",         entry.kind);
-  }
-};
-
-template <>
-struct ScalarTraits<PackedVersion> {
-  static void output(const PackedVersion &value, void*, raw_ostream &out) {
-    out << llvm::format("%d.%d", (value >> 16), (value >> 8) & 0xFF);
-    if (value & 0xFF) {
-      out << llvm::format(".%d", (value & 0xFF));
-    }
-  }
-  static StringRef input(StringRef scalar, void*, PackedVersion &result) {
-    uint32_t value;
-    if (lld::MachOLinkingContext::parsePackedVersion(scalar, value))
-      return "malformed version number";
-    result = value;
-    // Return the empty string on success,
-    return StringRef();
-  }
-  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
-};
-
-template <>
-struct MappingTraits<NormalizedFile> {
-  static void mapping(IO &io, NormalizedFile &file) {
-    io.mapRequired("arch",             file.arch);
-    io.mapRequired("file-type",        file.fileType);
-    io.mapOptional("flags",            file.flags);
-    io.mapOptional("dependents",       file.dependentDylibs);
-    io.mapOptional("install-name",     file.installName,    StringRef());
-    io.mapOptional("compat-version",   file.compatVersion,  PackedVersion(0x10000));
-    io.mapOptional("current-version",  file.currentVersion, PackedVersion(0x10000));
-    io.mapOptional("has-UUID",         file.hasUUID,        true);
-    io.mapOptional("rpaths",           file.rpaths);
-    io.mapOptional("entry-point",      file.entryAddress,   Hex64(0));
-    io.mapOptional("stack-size",       file.stackSize,      Hex64(0));
-    io.mapOptional("source-version",   file.sourceVersion,  Hex64(0));
-    io.mapOptional("OS",               file.os);
-    io.mapOptional("min-os-version",   file.minOSverson,    PackedVersion(0));
-    io.mapOptional("min-os-version-kind",   file.minOSVersionKind, (LoadCommandType)0);
-    io.mapOptional("sdk-version",      file.sdkVersion,     PackedVersion(0));
-    io.mapOptional("segments",         file.segments);
-    io.mapOptional("sections",         file.sections);
-    io.mapOptional("local-symbols",    file.localSymbols);
-    io.mapOptional("global-symbols",   file.globalSymbols);
-    io.mapOptional("undefined-symbols",file.undefinedSymbols);
-    io.mapOptional("page-size",        file.pageSize,       Hex32(4096));
-    io.mapOptional("rebasings",        file.rebasingInfo);
-    io.mapOptional("bindings",         file.bindingInfo);
-    io.mapOptional("weak-bindings",    file.weakBindingInfo);
-    io.mapOptional("lazy-bindings",    file.lazyBindingInfo);
-    io.mapOptional("exports",          file.exportInfo);
-    io.mapOptional("dataInCode",       file.dataInCode);
-  }
-  static std::string validate(IO &io, NormalizedFile &file) { return {}; }
-};
-
-} // namespace llvm
-} // namespace yaml
-
-
-namespace lld {
-namespace mach_o {
-
-/// Handles !mach-o tagged yaml documents.
-bool MachOYamlIOTaggedDocumentHandler::handledDocTag(llvm::yaml::IO &io,
-                                                 const lld::File *&file) const {
-  if (!io.mapTag("!mach-o"))
-    return false;
-  // Step 1: parse yaml into normalized mach-o struct.
-  NormalizedFile nf;
-  YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-  assert(info != nullptr);
-  assert(info->_normalizeMachOFile == nullptr);
-  info->_normalizeMachOFile = &nf;
-  MappingTraits<NormalizedFile>::mapping(io, nf);
-  // Step 2: parse normalized mach-o struct into atoms.
-  auto fileOrError = normalizedToAtoms(nf, info->_path, true);
-
-  // Check that we parsed successfully.
-  if (!fileOrError) {
-    std::string buffer;
-    llvm::raw_string_ostream stream(buffer);
-    handleAllErrors(fileOrError.takeError(),
-                    [&](const llvm::ErrorInfoBase &EI) {
-      EI.log(stream);
-      stream << "\n";
-    });
-    io.setError(stream.str());
-    return false;
-  }
-
-  if (nf.arch != _arch) {
-    io.setError(Twine("file is wrong architecture. Expected ("
-                      + MachOLinkingContext::nameFromArch(_arch)
-                      + ") found ("
-                      + MachOLinkingContext::nameFromArch(nf.arch)
-                      + ")"));
-    return false;
-  }
-  info->_normalizeMachOFile = nullptr;
-  file = fileOrError->release();
-  return true;
-}
-
-
-
-namespace normalized {
-
-/// Parses a yaml encoded mach-o file to produce an in-memory normalized view.
-llvm::Expected<std::unique_ptr<NormalizedFile>>
-readYaml(std::unique_ptr<MemoryBuffer> &mb) {
-  // Make empty NormalizedFile.
-  std::unique_ptr<NormalizedFile> f(new NormalizedFile());
-
-  // Create YAML Input parser.
-  YamlContext yamlContext;
-  yamlContext._normalizeMachOFile = f.get();
-  llvm::yaml::Input yin(mb->getBuffer(), &yamlContext);
-
-  // Fill NormalizedFile by parsing yaml.
-  yin >> *f;
-
-  // Return error if there were parsing problems.
-  if (auto ec = yin.error())
-    return llvm::make_error<GenericError>(Twine("YAML parsing error: ")
-                                          + ec.message());
-
-  // Hand ownership of instantiated NormalizedFile to caller.
-  return std::move(f);
-}
-
-
-/// Writes a yaml encoded mach-o files from an in-memory normalized view.
-std::error_code writeYaml(const NormalizedFile &file, raw_ostream &out) {
-  // YAML I/O is not const aware, so need to cast away ;-(
-  NormalizedFile *f = const_cast<NormalizedFile*>(&file);
-
-  // Create yaml Output writer, using yaml options for context.
-  YamlContext yamlContext;
-  yamlContext._normalizeMachOFile = f;
-  llvm::yaml::Output yout(out, &yamlContext);
-
-  // Stream out yaml.
-  yout << *f;
-
-  return std::error_code();
-}
-
-} // namespace normalized
-} // namespace mach_o
-} // namespace lld
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/MachOPasses.h b/gnu/llvm/lld/lib/ReaderWriter/MachO/MachOPasses.h
deleted file mode 100644 (file)
index 93cd3e4..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-//===- lib/ReaderWriter/MachO/MachOPasses.h -------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_PASSES_H
-#define LLD_READER_WRITER_MACHO_PASSES_H
-
-#include "lld/Core/PassManager.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-
-namespace lld {
-namespace mach_o {
-
-void addLayoutPass(PassManager &pm, const MachOLinkingContext &ctx);
-void addStubsPass(PassManager &pm, const MachOLinkingContext &ctx);
-void addGOTPass(PassManager &pm, const MachOLinkingContext &ctx);
-void addTLVPass(PassManager &pm, const MachOLinkingContext &ctx);
-void addCompactUnwindPass(PassManager &pm, const MachOLinkingContext &ctx);
-void addObjCPass(PassManager &pm, const MachOLinkingContext &ctx);
-void addShimPass(PassManager &pm, const MachOLinkingContext &ctx);
-
-} // namespace mach_o
-} // namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_PASSES_H
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/ObjCPass.cpp b/gnu/llvm/lld/lib/ReaderWriter/MachO/ObjCPass.cpp
deleted file mode 100644 (file)
index 02a95b5..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-//===- lib/ReaderWriter/MachO/ObjCPass.cpp -------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "File.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "MachOPasses.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/Simple.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/STLExtras.h"
-
-namespace lld {
-namespace mach_o {
-
-///
-/// ObjC Image Info Atom created by the ObjC pass.
-///
-class ObjCImageInfoAtom : public SimpleDefinedAtom {
-public:
-  ObjCImageInfoAtom(const File &file, bool isBig,
-                    MachOLinkingContext::ObjCConstraint objCConstraint,
-                    uint32_t swiftVersion)
-      : SimpleDefinedAtom(file) {
-
-    Data.info.version = 0;
-
-    switch (objCConstraint) {
-    case MachOLinkingContext::objc_unknown:
-      llvm_unreachable("Shouldn't run the objc pass without a constraint");
-    case MachOLinkingContext::objc_supports_gc:
-    case MachOLinkingContext::objc_gc_only:
-      llvm_unreachable("GC is not supported");
-    case MachOLinkingContext::objc_retainReleaseForSimulator:
-      // The retain/release for simulator flag is already the correct
-      // encoded value for the data so just set it here.
-      Data.info.flags = (uint32_t)objCConstraint;
-      break;
-    case MachOLinkingContext::objc_retainRelease:
-      // We don't need to encode this flag, so just leave the flags as 0.
-      Data.info.flags = 0;
-      break;
-    }
-
-    Data.info.flags |= (swiftVersion << 8);
-
-    normalized::write32(Data.bytes + 4, Data.info.flags, isBig);
-  }
-
-  ~ObjCImageInfoAtom() override = default;
-
-  ContentType contentType() const override {
-    return DefinedAtom::typeObjCImageInfo;
-  }
-
-  Alignment alignment() const override {
-    return 4;
-  }
-
-  uint64_t size() const override {
-    return 8;
-  }
-
-  ContentPermissions permissions() const override {
-    return DefinedAtom::permR__;
-  }
-
-  ArrayRef<uint8_t> rawContent() const override {
-    return llvm::makeArrayRef(Data.bytes, size());
-  }
-
-private:
-
-  struct objc_image_info  {
-    uint32_t   version;
-    uint32_t   flags;
-  };
-
-  union {
-    objc_image_info info;
-    uint8_t bytes[8];
-  } Data;
-};
-
-class ObjCPass : public Pass {
-public:
-  ObjCPass(const MachOLinkingContext &context)
-      : _ctx(context),
-        _file(*_ctx.make_file<MachOFile>("<mach-o objc pass>")) {
-    _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
-  }
-
-  llvm::Error perform(SimpleFile &mergedFile) override {
-    // Add the image info.
-    mergedFile.addAtom(*getImageInfo());
-
-    return llvm::Error::success();
-  }
-
-private:
-
-  const DefinedAtom* getImageInfo() {
-    bool IsBig = MachOLinkingContext::isBigEndian(_ctx.arch());
-    return new (_file.allocator()) ObjCImageInfoAtom(_file, IsBig,
-                                                     _ctx.objcConstraint(),
-                                                     _ctx.swiftVersion());
-  }
-
-  const MachOLinkingContext   &_ctx;
-  MachOFile                   &_file;
-};
-
-
-
-void addObjCPass(PassManager &pm, const MachOLinkingContext &ctx) {
-  pm.add(std::make_unique<ObjCPass>(ctx));
-}
-
-} // end namespace mach_o
-} // end namespace lld
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/SectCreateFile.h b/gnu/llvm/lld/lib/ReaderWriter/MachO/SectCreateFile.h
deleted file mode 100644 (file)
index 7bb98e1..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-//===---- lib/ReaderWriter/MachO/SectCreateFile.h ---------------*- c++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_SECTCREATE_FILE_H
-#define LLD_READER_WRITER_MACHO_SECTCREATE_FILE_H
-
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/Simple.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-
-namespace lld {
-namespace mach_o {
-
-//
-// A FlateNamespaceFile instance may be added as a resolution source of last
-// resort, depending on how -flat_namespace and -undefined are set.
-//
-class SectCreateFile : public File {
-public:
-  class SectCreateAtom : public SimpleDefinedAtom {
-  public:
-    SectCreateAtom(const File &file, StringRef segName, StringRef sectName,
-                   std::unique_ptr<MemoryBuffer> content)
-      : SimpleDefinedAtom(file),
-        _combinedName((segName + "/" + sectName).str()),
-        _content(std::move(content)) {}
-
-    ~SectCreateAtom() override = default;
-
-    uint64_t size() const override { return _content->getBufferSize(); }
-
-    Scope scope() const override { return scopeGlobal; }
-
-    ContentType contentType() const override { return typeSectCreate; }
-
-    SectionChoice sectionChoice() const override { return sectionCustomRequired; }
-
-    StringRef customSectionName() const override { return _combinedName; }
-
-    DeadStripKind deadStrip() const override { return deadStripNever; }
-
-    ArrayRef<uint8_t> rawContent() const override {
-      const uint8_t *data =
-        reinterpret_cast<const uint8_t*>(_content->getBufferStart());
-      return ArrayRef<uint8_t>(data, _content->getBufferSize());
-    }
-
-    StringRef segmentName() const { return _segName; }
-    StringRef sectionName() const { return _sectName; }
-
-  private:
-    std::string _combinedName;
-    StringRef _segName;
-    StringRef _sectName;
-    std::unique_ptr<MemoryBuffer> _content;
-  };
-
-  SectCreateFile() : File("sectcreate", kindSectCreateObject) {}
-
-  void addSection(StringRef seg, StringRef sect,
-                  std::unique_ptr<MemoryBuffer> content) {
-    _definedAtoms.push_back(
-      new (allocator()) SectCreateAtom(*this, seg, sect, std::move(content)));
-  }
-
-  const AtomRange<DefinedAtom> defined() const override {
-    return _definedAtoms;
-  }
-
-  const AtomRange<UndefinedAtom> undefined() const override {
-    return _noUndefinedAtoms;
-  }
-
-  const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
-    return _noSharedLibraryAtoms;
-  }
-
-  const AtomRange<AbsoluteAtom> absolute() const override {
-    return _noAbsoluteAtoms;
-  }
-
-  void clearAtoms() override {
-    _definedAtoms.clear();
-    _noUndefinedAtoms.clear();
-    _noSharedLibraryAtoms.clear();
-    _noAbsoluteAtoms.clear();
-  }
-
-private:
-  AtomVector<DefinedAtom> _definedAtoms;
-};
-
-} // namespace mach_o
-} // namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_SECTCREATE_FILE_H
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/ShimPass.cpp b/gnu/llvm/lld/lib/ReaderWriter/MachO/ShimPass.cpp
deleted file mode 100644 (file)
index a5b34cf..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-//===- lib/ReaderWriter/MachO/ShimPass.cpp -------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This linker pass updates branch-sites whose target is a different mode
-// (thumb vs arm).
-//
-// Arm code has two instruction encodings thumb and arm.  When branching from
-// one code encoding to another, you need to use an instruction that switches
-// the instruction mode.  Usually the transition only happens at call sites, and
-// the linker can transform a BL instruction in BLX (or vice versa).  But if the
-// compiler did a tail call optimization and a function ends with a branch (not
-// branch and link), there is no pc-rel BX instruction.
-//
-// The ShimPass looks for pc-rel B instructions that will need to switch mode.
-// For those cases it synthesizes a shim which does the transition, then
-// modifies the original atom with the B instruction to target to the shim atom.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "File.h"
-#include "MachOPasses.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/Simple.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/STLExtras.h"
-
-namespace lld {
-namespace mach_o {
-
-class ShimPass : public Pass {
-public:
-  ShimPass(const MachOLinkingContext &context)
-      : _ctx(context), _archHandler(_ctx.archHandler()),
-        _stubInfo(_archHandler.stubInfo()),
-        _file(*_ctx.make_file<MachOFile>("<mach-o shim pass>")) {
-    _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
-  }
-
-  llvm::Error perform(SimpleFile &mergedFile) override {
-    // Scan all references in all atoms.
-    for (const DefinedAtom *atom : mergedFile.defined()) {
-      for (const Reference *ref : *atom) {
-        // Look at non-call branches.
-        if (!_archHandler.isNonCallBranch(*ref))
-          continue;
-        const Atom *target = ref->target();
-        assert(target != nullptr);
-        if (const lld::DefinedAtom *daTarget = dyn_cast<DefinedAtom>(target)) {
-          bool atomIsThumb = _archHandler.isThumbFunction(*atom);
-          bool targetIsThumb = _archHandler.isThumbFunction(*daTarget);
-          if (atomIsThumb != targetIsThumb)
-            updateBranchToUseShim(atomIsThumb, *daTarget, ref);
-        }
-      }
-    }
-    // Exit early if no shims needed.
-    if (_targetToShim.empty())
-      return llvm::Error::success();
-
-    // Sort shim atoms so the layout order is stable.
-    std::vector<const DefinedAtom *> shims;
-    shims.reserve(_targetToShim.size());
-    for (auto element : _targetToShim) {
-      shims.push_back(element.second);
-    }
-    std::sort(shims.begin(), shims.end(),
-              [](const DefinedAtom *l, const DefinedAtom *r) {
-                return (l->name() < r->name());
-              });
-
-    // Add all shims to master file.
-    for (const DefinedAtom *shim : shims)
-      mergedFile.addAtom(*shim);
-
-    return llvm::Error::success();
-  }
-
-private:
-
-  void updateBranchToUseShim(bool thumbToArm, const DefinedAtom& target,
-                             const Reference *ref) {
-    // Make file-format specific stub and other support atoms.
-    const DefinedAtom *shim = this->getShim(thumbToArm, target);
-    assert(shim != nullptr);
-    // Switch branch site to target shim atom.
-    const_cast<Reference *>(ref)->setTarget(shim);
-  }
-
-  const DefinedAtom* getShim(bool thumbToArm, const DefinedAtom& target) {
-    auto pos = _targetToShim.find(&target);
-    if ( pos != _targetToShim.end() ) {
-      // Reuse an existing shim.
-      assert(pos->second != nullptr);
-      return pos->second;
-    } else {
-      // There is no existing shim, so create a new one.
-      const DefinedAtom *shim = _archHandler.createShim(_file, thumbToArm,
-                                                        target);
-       _targetToShim[&target] = shim;
-       return shim;
-    }
-  }
-
-  const MachOLinkingContext &_ctx;
-  mach_o::ArchHandler                            &_archHandler;
-  const ArchHandler::StubInfo                    &_stubInfo;
-  MachOFile                                      &_file;
-  llvm::DenseMap<const Atom*, const DefinedAtom*> _targetToShim;
-};
-
-
-
-void addShimPass(PassManager &pm, const MachOLinkingContext &ctx) {
-  pm.add(std::make_unique<ShimPass>(ctx));
-}
-
-} // end namespace mach_o
-} // end namespace lld
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/StubsPass.cpp b/gnu/llvm/lld/lib/ReaderWriter/MachO/StubsPass.cpp
deleted file mode 100644 (file)
index fbbd8b2..0000000
+++ /dev/null
@@ -1,377 +0,0 @@
-//===- lib/ReaderWriter/MachO/StubsPass.cpp ---------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This linker pass updates call-sites which have references to shared library
-// atoms to instead have a reference to a stub (PLT entry) for the specified
-// symbol.  Each file format defines a subclass of StubsPass which implements
-// the abstract methods for creating the file format specific StubAtoms.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "File.h"
-#include "MachOPasses.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/Simple.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallVector.h"
-
-namespace lld {
-namespace mach_o {
-
-//
-//  Lazy Pointer Atom created by the stubs pass.
-//
-class LazyPointerAtom : public SimpleDefinedAtom {
-public:
-  LazyPointerAtom(const File &file, bool is64)
-    : SimpleDefinedAtom(file), _is64(is64) { }
-
-  ~LazyPointerAtom() override = default;
-
-  ContentType contentType() const override {
-    return DefinedAtom::typeLazyPointer;
-  }
-
-  Alignment alignment() const override {
-    return _is64 ? 8 : 4;
-  }
-
-  uint64_t size() const override {
-    return _is64 ? 8 : 4;
-  }
-
-  ContentPermissions permissions() const override {
-    return DefinedAtom::permRW_;
-  }
-
-  ArrayRef<uint8_t> rawContent() const override {
-    static const uint8_t zeros[] =
-        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-    return llvm::makeArrayRef(zeros, size());
-  }
-
-private:
-  const bool _is64;
-};
-
-//
-//  NonLazyPointer (GOT) Atom created by the stubs pass.
-//
-class NonLazyPointerAtom : public SimpleDefinedAtom {
-public:
-  NonLazyPointerAtom(const File &file, bool is64, ContentType contentType)
-    : SimpleDefinedAtom(file), _is64(is64), _contentType(contentType) { }
-
-  ~NonLazyPointerAtom() override = default;
-
-  ContentType contentType() const override {
-    return _contentType;
-  }
-
-  Alignment alignment() const override {
-    return _is64 ? 8 : 4;
-  }
-
-  uint64_t size() const override {
-    return _is64 ? 8 : 4;
-  }
-
-  ContentPermissions permissions() const override {
-    return DefinedAtom::permRW_;
-  }
-
-  ArrayRef<uint8_t> rawContent() const override {
-    static const uint8_t zeros[] =
-        { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-    return llvm::makeArrayRef(zeros, size());
-  }
-
-private:
-  const bool _is64;
-  const ContentType _contentType;
-};
-
-//
-// Stub Atom created by the stubs pass.
-//
-class StubAtom : public SimpleDefinedAtom {
-public:
-  StubAtom(const File &file, const ArchHandler::StubInfo &stubInfo)
-      : SimpleDefinedAtom(file), _stubInfo(stubInfo){ }
-
-  ~StubAtom() override = default;
-
-  ContentType contentType() const override {
-    return DefinedAtom::typeStub;
-  }
-
-  Alignment alignment() const override {
-    return 1 << _stubInfo.codeAlignment;
-  }
-
-  uint64_t size() const override {
-    return _stubInfo.stubSize;
-  }
-
-  ContentPermissions permissions() const override {
-    return DefinedAtom::permR_X;
-  }
-
-  ArrayRef<uint8_t> rawContent() const override {
-    return llvm::makeArrayRef(_stubInfo.stubBytes, _stubInfo.stubSize);
-  }
-
-private:
-  const ArchHandler::StubInfo   &_stubInfo;
-};
-
-//
-// Stub Helper Atom created by the stubs pass.
-//
-class StubHelperAtom : public SimpleDefinedAtom {
-public:
-  StubHelperAtom(const File &file, const ArchHandler::StubInfo &stubInfo)
-      : SimpleDefinedAtom(file), _stubInfo(stubInfo) { }
-
-  ~StubHelperAtom() override = default;
-
-  ContentType contentType() const override {
-    return DefinedAtom::typeStubHelper;
-  }
-
-  Alignment alignment() const override {
-    return 1 << _stubInfo.codeAlignment;
-  }
-
-  uint64_t size() const override {
-    return _stubInfo.stubHelperSize;
-  }
-
-  ContentPermissions permissions() const override {
-    return DefinedAtom::permR_X;
-  }
-
-  ArrayRef<uint8_t> rawContent() const override {
-    return llvm::makeArrayRef(_stubInfo.stubHelperBytes,
-                              _stubInfo.stubHelperSize);
-  }
-
-private:
-  const ArchHandler::StubInfo   &_stubInfo;
-};
-
-//
-// Stub Helper Common Atom created by the stubs pass.
-//
-class StubHelperCommonAtom : public SimpleDefinedAtom {
-public:
-  StubHelperCommonAtom(const File &file, const ArchHandler::StubInfo &stubInfo)
-      : SimpleDefinedAtom(file), _stubInfo(stubInfo) { }
-
-  ~StubHelperCommonAtom() override = default;
-
-  ContentType contentType() const override {
-    return DefinedAtom::typeStubHelper;
-  }
-
-  Alignment alignment() const override {
-    return 1 << _stubInfo.stubHelperCommonAlignment;
-  }
-
-  uint64_t size() const override {
-    return _stubInfo.stubHelperCommonSize;
-  }
-
-  ContentPermissions permissions() const override {
-    return DefinedAtom::permR_X;
-  }
-
-  ArrayRef<uint8_t> rawContent() const override {
-    return llvm::makeArrayRef(_stubInfo.stubHelperCommonBytes,
-                        _stubInfo.stubHelperCommonSize);
-  }
-
-private:
-  const ArchHandler::StubInfo   &_stubInfo;
-};
-
-class StubsPass : public Pass {
-public:
-  StubsPass(const MachOLinkingContext &context)
-      : _ctx(context), _archHandler(_ctx.archHandler()),
-        _stubInfo(_archHandler.stubInfo()),
-        _file(*_ctx.make_file<MachOFile>("<mach-o Stubs pass>")) {
-    _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
-  }
-
-  llvm::Error perform(SimpleFile &mergedFile) override {
-    // Skip this pass if output format uses text relocations instead of stubs.
-    if (!this->noTextRelocs())
-      return llvm::Error::success();
-
-    // Scan all references in all atoms.
-    for (const DefinedAtom *atom : mergedFile.defined()) {
-      for (const Reference *ref : *atom) {
-        // Look at call-sites.
-        if (!this->isCallSite(*ref))
-          continue;
-        const Atom *target = ref->target();
-        assert(target != nullptr);
-        if (isa<SharedLibraryAtom>(target)) {
-          // Calls to shared libraries go through stubs.
-          _targetToUses[target].push_back(ref);
-          continue;
-        }
-        const DefinedAtom *defTarget = dyn_cast<DefinedAtom>(target);
-        if (defTarget && defTarget->interposable() != DefinedAtom::interposeNo){
-          // Calls to interposable functions in same linkage unit must also go
-          // through a stub.
-          assert(defTarget->scope() != DefinedAtom::scopeTranslationUnit);
-          _targetToUses[target].push_back(ref);
-        }
-      }
-    }
-
-    // Exit early if no stubs needed.
-    if (_targetToUses.empty())
-      return llvm::Error::success();
-
-    // First add help-common and GOT slots used by lazy binding.
-    SimpleDefinedAtom *helperCommonAtom =
-        new (_file.allocator()) StubHelperCommonAtom(_file, _stubInfo);
-    SimpleDefinedAtom *helperCacheNLPAtom =
-        new (_file.allocator()) NonLazyPointerAtom(_file, _ctx.is64Bit(),
-                                    _stubInfo.stubHelperImageCacheContentType);
-    SimpleDefinedAtom *helperBinderNLPAtom =
-        new (_file.allocator()) NonLazyPointerAtom(_file, _ctx.is64Bit(),
-                                    _stubInfo.stubHelperImageCacheContentType);
-    addReference(helperCommonAtom, _stubInfo.stubHelperCommonReferenceToCache,
-                 helperCacheNLPAtom);
-    addOptReference(
-        helperCommonAtom, _stubInfo.stubHelperCommonReferenceToCache,
-        _stubInfo.optStubHelperCommonReferenceToCache, helperCacheNLPAtom);
-    addReference(helperCommonAtom, _stubInfo.stubHelperCommonReferenceToBinder,
-                 helperBinderNLPAtom);
-    addOptReference(
-        helperCommonAtom, _stubInfo.stubHelperCommonReferenceToBinder,
-        _stubInfo.optStubHelperCommonReferenceToBinder, helperBinderNLPAtom);
-    mergedFile.addAtom(*helperCommonAtom);
-    mergedFile.addAtom(*helperBinderNLPAtom);
-    mergedFile.addAtom(*helperCacheNLPAtom);
-
-    // Add reference to dyld_stub_binder in libSystem.dylib
-    auto I = llvm::find_if(
-        mergedFile.sharedLibrary(), [&](const SharedLibraryAtom *atom) {
-          return atom->name().equals(_stubInfo.binderSymbolName);
-        });
-    assert(I != mergedFile.sharedLibrary().end() &&
-           "dyld_stub_binder not found");
-    addReference(helperBinderNLPAtom, _stubInfo.nonLazyPointerReferenceToBinder, *I);
-
-    // Sort targets by name, so stubs and lazy pointers are consistent
-    std::vector<const Atom *> targetsNeedingStubs;
-    for (auto it : _targetToUses)
-      targetsNeedingStubs.push_back(it.first);
-    std::sort(targetsNeedingStubs.begin(), targetsNeedingStubs.end(),
-              [](const Atom * left, const Atom * right) {
-      return (left->name().compare(right->name()) < 0);
-    });
-
-    // Make and append stubs, lazy pointers, and helpers in alphabetical order.
-    unsigned lazyOffset = 0;
-    for (const Atom *target : targetsNeedingStubs) {
-      auto *stub = new (_file.allocator()) StubAtom(_file, _stubInfo);
-      auto *lp =
-          new (_file.allocator()) LazyPointerAtom(_file, _ctx.is64Bit());
-      auto *helper = new (_file.allocator()) StubHelperAtom(_file, _stubInfo);
-
-      addReference(stub, _stubInfo.stubReferenceToLP, lp);
-      addOptReference(stub, _stubInfo.stubReferenceToLP,
-                      _stubInfo.optStubReferenceToLP, lp);
-      addReference(lp, _stubInfo.lazyPointerReferenceToHelper, helper);
-      addReference(lp, _stubInfo.lazyPointerReferenceToFinal, target);
-      addReference(helper, _stubInfo.stubHelperReferenceToImm, helper);
-      addReferenceAddend(helper, _stubInfo.stubHelperReferenceToImm, helper,
-                         lazyOffset);
-      addReference(helper, _stubInfo.stubHelperReferenceToHelperCommon,
-                   helperCommonAtom);
-
-      mergedFile.addAtom(*stub);
-      mergedFile.addAtom(*lp);
-      mergedFile.addAtom(*helper);
-
-      // Update each reference to use stub.
-      for (const Reference *ref : _targetToUses[target]) {
-        assert(ref->target() == target);
-        // Switch call site to reference stub atom instead.
-        const_cast<Reference *>(ref)->setTarget(stub);
-      }
-
-      // Calculate new offset
-      lazyOffset += target->name().size() + 12;
-    }
-
-    return llvm::Error::success();
-  }
-
-private:
-  bool noTextRelocs() {
-    return true;
-  }
-
-  bool isCallSite(const Reference &ref) {
-    return _archHandler.isCallSite(ref);
-  }
-
-  void addReference(SimpleDefinedAtom* atom,
-                    const ArchHandler::ReferenceInfo &refInfo,
-                    const lld::Atom* target) {
-    atom->addReference(Reference::KindNamespace::mach_o,
-                      refInfo.arch, refInfo.kind, refInfo.offset,
-                      target, refInfo.addend);
-  }
-
-  void addReferenceAddend(SimpleDefinedAtom *atom,
-                          const ArchHandler::ReferenceInfo &refInfo,
-                          const lld::Atom *target, uint64_t addend) {
-    atom->addReference(Reference::KindNamespace::mach_o, refInfo.arch,
-                       refInfo.kind, refInfo.offset, target, addend);
-  }
-
-   void addOptReference(SimpleDefinedAtom* atom,
-                    const ArchHandler::ReferenceInfo &refInfo,
-                    const ArchHandler::OptionalRefInfo &optRef,
-                    const lld::Atom* target) {
-      if (!optRef.used)
-        return;
-    atom->addReference(Reference::KindNamespace::mach_o,
-                      refInfo.arch, optRef.kind, optRef.offset,
-                      target, optRef.addend);
-  }
-
-  typedef llvm::DenseMap<const Atom*,
-                         llvm::SmallVector<const Reference *, 8>> TargetToUses;
-
-  const MachOLinkingContext &_ctx;
-  mach_o::ArchHandler                            &_archHandler;
-  const ArchHandler::StubInfo                    &_stubInfo;
-  MachOFile                                      &_file;
-  TargetToUses                                    _targetToUses;
-};
-
-void addStubsPass(PassManager &pm, const MachOLinkingContext &ctx) {
-  pm.add(std::unique_ptr<Pass>(new StubsPass(ctx)));
-}
-
-} // end namespace mach_o
-} // end namespace lld
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/TLVPass.cpp b/gnu/llvm/lld/lib/ReaderWriter/MachO/TLVPass.cpp
deleted file mode 100644 (file)
index e0a031c..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-//===- lib/ReaderWriter/MachO/TLVPass.cpp -----------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// This linker pass transforms all TLV references to real references.
-///
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "File.h"
-#include "MachOPasses.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/Debug.h"
-
-namespace lld {
-namespace mach_o {
-
-//
-// TLVP Entry Atom created by the TLV pass.
-//
-class TLVPEntryAtom : public SimpleDefinedAtom {
-public:
-  TLVPEntryAtom(const File &file, bool is64, StringRef name)
-      : SimpleDefinedAtom(file), _is64(is64), _name(name) {}
-
-  ~TLVPEntryAtom() override = default;
-
-  ContentType contentType() const override {
-    return DefinedAtom::typeTLVInitializerPtr;
-  }
-
-  Alignment alignment() const override {
-    return _is64 ? 8 : 4;
-  }
-
-  uint64_t size() const override {
-    return _is64 ? 8 : 4;
-  }
-
-  ContentPermissions permissions() const override {
-    return DefinedAtom::permRW_;
-  }
-
-  ArrayRef<uint8_t> rawContent() const override {
-    static const uint8_t zeros[] =
-      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-    return llvm::makeArrayRef(zeros, size());
-  }
-
-  StringRef slotName() const {
-    return _name;
-  }
-
-private:
-  const bool _is64;
-  StringRef _name;
-};
-
-class TLVPass : public Pass {
-public:
-  TLVPass(const MachOLinkingContext &context)
-      : _ctx(context), _archHandler(_ctx.archHandler()),
-        _file(*_ctx.make_file<MachOFile>("<mach-o TLV pass>")) {
-    _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
-  }
-
-private:
-  llvm::Error perform(SimpleFile &mergedFile) override {
-    bool allowTLV = _ctx.minOS("10.7", "1.0");
-
-    for (const DefinedAtom *atom : mergedFile.defined()) {
-      for (const Reference *ref : *atom) {
-        if (!_archHandler.isTLVAccess(*ref))
-          continue;
-
-        if (!allowTLV)
-          return llvm::make_error<GenericError>(
-            "targeted OS version does not support use of thread local "
-            "variables in " + atom->name() + " for architecture " +
-            _ctx.archName());
-
-        const Atom *target = ref->target();
-        assert(target != nullptr);
-
-        const DefinedAtom *tlvpEntry = makeTLVPEntry(target);
-        const_cast<Reference*>(ref)->setTarget(tlvpEntry);
-        _archHandler.updateReferenceToTLV(ref);
-      }
-    }
-
-    std::vector<const TLVPEntryAtom*> entries;
-    entries.reserve(_targetToTLVP.size());
-    for (auto &it : _targetToTLVP)
-      entries.push_back(it.second);
-    std::sort(entries.begin(), entries.end(),
-              [](const TLVPEntryAtom *lhs, const TLVPEntryAtom *rhs) {
-                return (lhs->slotName().compare(rhs->slotName()) < 0);
-              });
-
-    for (const TLVPEntryAtom *slot : entries)
-      mergedFile.addAtom(*slot);
-
-    return llvm::Error::success();
-  }
-
-  const DefinedAtom *makeTLVPEntry(const Atom *target) {
-    auto pos = _targetToTLVP.find(target);
-
-    if (pos != _targetToTLVP.end())
-      return pos->second;
-
-    auto *tlvpEntry = new (_file.allocator())
-      TLVPEntryAtom(_file, _ctx.is64Bit(), target->name());
-    _targetToTLVP[target] = tlvpEntry;
-    const ArchHandler::ReferenceInfo &nlInfo =
-      _archHandler.stubInfo().nonLazyPointerReferenceToBinder;
-    tlvpEntry->addReference(Reference::KindNamespace::mach_o, nlInfo.arch,
-                            nlInfo.kind, 0, target, 0);
-    return tlvpEntry;
-  }
-
-  const MachOLinkingContext &_ctx;
-  mach_o::ArchHandler &_archHandler;
-  MachOFile           &_file;
-  llvm::DenseMap<const Atom*, const TLVPEntryAtom*> _targetToTLVP;
-};
-
-void addTLVPass(PassManager &pm, const MachOLinkingContext &ctx) {
-  assert(ctx.needsTLVPass());
-  pm.add(std::make_unique<TLVPass>(ctx));
-}
-
-} // end namespace mach_o
-} // end namespace lld
diff --git a/gnu/llvm/lld/lib/ReaderWriter/MachO/WriterMachO.cpp b/gnu/llvm/lld/lib/ReaderWriter/MachO/WriterMachO.cpp
deleted file mode 100644 (file)
index 60e0e9d..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-//===- lib/ReaderWriter/MachO/WriterMachO.cpp -----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "ExecutableAtoms.h"
-#include "MachONormalizedFile.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Writer.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <system_error>
-
-using lld::mach_o::normalized::NormalizedFile;
-
-namespace lld {
-namespace mach_o {
-
-class MachOWriter : public Writer {
-public:
-  MachOWriter(const MachOLinkingContext &ctxt) : _ctx(ctxt) {}
-
-  llvm::Error writeFile(const lld::File &file, StringRef path) override {
-    // Construct empty normalized file from atoms.
-    llvm::Expected<std::unique_ptr<NormalizedFile>> nFile =
-        normalized::normalizedFromAtoms(file, _ctx);
-    if (auto ec = nFile.takeError())
-      return ec;
-
-    // For testing, write out yaml form of normalized file.
-    if (_ctx.printAtoms()) {
-      std::unique_ptr<Writer> yamlWriter = createWriterYAML(_ctx);
-      if (auto ec = yamlWriter->writeFile(file, "-"))
-        return ec;
-    }
-
-    // Write normalized file as mach-o binary.
-    return writeBinary(*nFile->get(), path);
-  }
-
-  void createImplicitFiles(std::vector<std::unique_ptr<File>> &r) override {
-    // When building main executables, add _main as required entry point.
-    if (_ctx.outputTypeHasEntry())
-      r.emplace_back(new CEntryFile(_ctx));
-    // If this can link with dylibs, need helper function (dyld_stub_binder).
-    if (_ctx.needsStubsPass())
-      r.emplace_back(new StubHelperFile(_ctx));
-    // Final linked images can access a symbol for their mach_header.
-    if (_ctx.outputMachOType() != llvm::MachO::MH_OBJECT)
-      r.emplace_back(new MachHeaderAliasFile(_ctx));
-  }
-private:
-  const MachOLinkingContext &_ctx;
- };
-
-
-} // namespace mach_o
-
-std::unique_ptr<Writer> createWriterMachO(const MachOLinkingContext &context) {
-  return std::unique_ptr<Writer>(new lld::mach_o::MachOWriter(context));
-}
-
-} // namespace lld
diff --git a/gnu/llvm/lld/lib/ReaderWriter/YAML/CMakeLists.txt b/gnu/llvm/lld/lib/ReaderWriter/YAML/CMakeLists.txt
deleted file mode 100644 (file)
index 0e63574..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-add_lld_library(lldYAML
-  ReaderWriterYAML.cpp
-
-  LINK_COMPONENTS
-    Support
-
-  LINK_LIBS
-    lldCore
-  )
diff --git a/gnu/llvm/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/gnu/llvm/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
deleted file mode 100644 (file)
index c0e6e03..0000000
+++ /dev/null
@@ -1,1403 +0,0 @@
-//===- lib/ReaderWriter/YAML/ReaderWriterYAML.cpp -------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/AbsoluteAtom.h"
-#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/Atom.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/Error.h"
-#include "lld/Core/File.h"
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Reader.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/SharedLibraryAtom.h"
-#include "lld/Core/Simple.h"
-#include "lld/Core/UndefinedAtom.h"
-#include "lld/Core/Writer.h"
-#include "lld/ReaderWriter/YamlContext.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/Magic.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/YAMLTraits.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-#include <cstdint>
-#include <cstring>
-#include <memory>
-#include <string>
-#include <system_error>
-#include <vector>
-
-using llvm::file_magic;
-using llvm::yaml::MappingTraits;
-using llvm::yaml::ScalarEnumerationTraits;
-using llvm::yaml::ScalarTraits;
-using llvm::yaml::IO;
-using llvm::yaml::SequenceTraits;
-using llvm::yaml::DocumentListTraits;
-
-using namespace lld;
-
-/// The conversion of Atoms to and from YAML uses LLVM's YAML I/O.  This
-/// file just defines template specializations on the lld types which control
-/// how the mapping is done to and from YAML.
-
-namespace {
-
-/// Used when writing yaml files.
-/// In most cases, atoms names are unambiguous, so references can just
-/// use the atom name as the target (e.g. target: foo).  But in a few
-/// cases that does not work, so ref-names are added.  These are labels
-/// used only in yaml.  The labels do not exist in the Atom model.
-///
-/// One need for ref-names are when atoms have no user supplied name
-/// (e.g. c-string literal).  Another case is when two object files with
-/// identically named static functions are merged (ld -r) into one object file.
-/// In that case referencing the function by name is ambiguous, so a unique
-/// ref-name is added.
-class RefNameBuilder {
-public:
-  RefNameBuilder(const lld::File &file)
-      : _collisionCount(0), _unnamedCounter(0) {
-    // visit all atoms
-    for (const lld::DefinedAtom *atom : file.defined()) {
-      // Build map of atoms names to detect duplicates
-      if (!atom->name().empty())
-        buildDuplicateNameMap(*atom);
-
-      // Find references to unnamed atoms and create ref-names for them.
-      for (const lld::Reference *ref : *atom) {
-        // create refname for any unnamed reference target
-        const lld::Atom *target = ref->target();
-        if ((target != nullptr) && target->name().empty()) {
-          std::string storage;
-          llvm::raw_string_ostream buffer(storage);
-          buffer << llvm::format("L%03d", _unnamedCounter++);
-          StringRef newName = copyString(buffer.str());
-          _refNames[target] = std::string(newName);
-          DEBUG_WITH_TYPE("WriterYAML",
-                          llvm::dbgs() << "unnamed atom: creating ref-name: '"
-                                       << newName << "' ("
-                                       << (const void *)newName.data() << ", "
-                                       << newName.size() << ")\n");
-        }
-      }
-    }
-    for (const lld::UndefinedAtom *undefAtom : file.undefined()) {
-      buildDuplicateNameMap(*undefAtom);
-    }
-    for (const lld::SharedLibraryAtom *shlibAtom : file.sharedLibrary()) {
-      buildDuplicateNameMap(*shlibAtom);
-    }
-    for (const lld::AbsoluteAtom *absAtom : file.absolute()) {
-      if (!absAtom->name().empty())
-        buildDuplicateNameMap(*absAtom);
-    }
-  }
-
-  void buildDuplicateNameMap(const lld::Atom &atom) {
-    assert(!atom.name().empty());
-    NameToAtom::iterator pos = _nameMap.find(atom.name());
-    if (pos != _nameMap.end()) {
-      // Found name collision, give each a unique ref-name.
-      std::string Storage;
-      llvm::raw_string_ostream buffer(Storage);
-      buffer << atom.name() << llvm::format(".%03d", ++_collisionCount);
-      StringRef newName = copyString(buffer.str());
-      _refNames[&atom] = std::string(newName);
-      DEBUG_WITH_TYPE("WriterYAML",
-                      llvm::dbgs() << "name collision: creating ref-name: '"
-                                   << newName << "' ("
-                                   << (const void *)newName.data()
-                                   << ", " << newName.size() << ")\n");
-      const lld::Atom *prevAtom = pos->second;
-      AtomToRefName::iterator pos2 = _refNames.find(prevAtom);
-      if (pos2 == _refNames.end()) {
-        // Only create ref-name for previous if none already created.
-        std::string Storage2;
-        llvm::raw_string_ostream buffer2(Storage2);
-        buffer2 << prevAtom->name() << llvm::format(".%03d", ++_collisionCount);
-        StringRef newName2 = copyString(buffer2.str());
-        _refNames[prevAtom] = std::string(newName2);
-        DEBUG_WITH_TYPE("WriterYAML",
-                        llvm::dbgs() << "name collision: creating ref-name: '"
-                                     << newName2 << "' ("
-                                     << (const void *)newName2.data() << ", "
-                                     << newName2.size() << ")\n");
-      }
-    } else {
-      // First time we've seen this name, just add it to map.
-      _nameMap[atom.name()] = &atom;
-      DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs()
-                                        << "atom name seen for first time: '"
-                                        << atom.name() << "' ("
-                                        << (const void *)atom.name().data()
-                                        << ", " << atom.name().size() << ")\n");
-    }
-  }
-
-  bool hasRefName(const lld::Atom *atom) { return _refNames.count(atom); }
-
-  StringRef refName(const lld::Atom *atom) {
-    return _refNames.find(atom)->second;
-  }
-
-private:
-  typedef llvm::StringMap<const lld::Atom *> NameToAtom;
-  typedef llvm::DenseMap<const lld::Atom *, std::string> AtomToRefName;
-
-  // Allocate a new copy of this string in _storage, so the strings
-  // can be freed when RefNameBuilder is destroyed.
-  StringRef copyString(StringRef str) {
-    char *s = _storage.Allocate<char>(str.size());
-    memcpy(s, str.data(), str.size());
-    return StringRef(s, str.size());
-  }
-
-  unsigned int                         _collisionCount;
-  unsigned int                         _unnamedCounter;
-  NameToAtom                           _nameMap;
-  AtomToRefName                        _refNames;
-  llvm::BumpPtrAllocator               _storage;
-};
-
-/// Used when reading yaml files to find the target of a reference
-/// that could be a name or ref-name.
-class RefNameResolver {
-public:
-  RefNameResolver(const lld::File *file, IO &io);
-
-  const lld::Atom *lookup(StringRef name) const {
-    NameToAtom::const_iterator pos = _nameMap.find(name);
-    if (pos != _nameMap.end())
-      return pos->second;
-    _io.setError(Twine("no such atom name: ") + name);
-    return nullptr;
-  }
-
-private:
-  typedef llvm::StringMap<const lld::Atom *> NameToAtom;
-
-  void add(StringRef name, const lld::Atom *atom) {
-    if (_nameMap.count(name)) {
-      _io.setError(Twine("duplicate atom name: ") + name);
-    } else {
-      _nameMap[name] = atom;
-    }
-  }
-
-  IO &_io;
-  NameToAtom _nameMap;
-};
-
-/// Mapping of Atoms.
-template <typename T> class AtomList {
-  using Ty = std::vector<OwningAtomPtr<T>>;
-
-public:
-  typename Ty::iterator begin() { return _atoms.begin(); }
-  typename Ty::iterator end() { return _atoms.end(); }
-  Ty _atoms;
-};
-
-/// Mapping of kind: field in yaml files.
-enum FileKinds {
-  fileKindObjectAtoms, // atom based object file encoded in yaml
-  fileKindArchive,     // static archive library encoded in yaml
-  fileKindObjectMachO  // mach-o object files encoded in yaml
-};
-
-struct ArchMember {
-  FileKinds         _kind;
-  StringRef         _name;
-  const lld::File  *_content;
-};
-
-// The content bytes in a DefinedAtom are just uint8_t but we want
-// special formatting, so define a strong type.
-LLVM_YAML_STRONG_TYPEDEF(uint8_t, ImplicitHex8)
-
-// SharedLibraryAtoms have a bool canBeNull() method which we'd like to be
-// more readable than just true/false.
-LLVM_YAML_STRONG_TYPEDEF(bool, ShlibCanBeNull)
-
-// lld::Reference::Kind is a tuple of <namespace, arch, value>.
-// For yaml, we just want one string that encapsulates the tuple.
-struct RefKind {
-  Reference::KindNamespace  ns;
-  Reference::KindArch       arch;
-  Reference::KindValue      value;
-};
-
-} // end anonymous namespace
-
-LLVM_YAML_IS_SEQUENCE_VECTOR(ArchMember)
-LLVM_YAML_IS_SEQUENCE_VECTOR(const lld::Reference *)
-// Always write DefinedAtoms content bytes as a flow sequence.
-LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(ImplicitHex8)
-
-// for compatibility with gcc-4.7 in C++11 mode, add extra namespace
-namespace llvm {
-namespace yaml {
-
-// This is a custom formatter for RefKind
-template <> struct ScalarTraits<RefKind> {
-  static void output(const RefKind &kind, void *ctxt, raw_ostream &out) {
-    assert(ctxt != nullptr);
-    YamlContext *info = reinterpret_cast<YamlContext *>(ctxt);
-    assert(info->_registry);
-    StringRef str;
-    if (info->_registry->referenceKindToString(kind.ns, kind.arch, kind.value,
-                                               str))
-      out << str;
-    else
-      out << (int)(kind.ns) << "-" << (int)(kind.arch) << "-" << kind.value;
-  }
-
-  static StringRef input(StringRef scalar, void *ctxt, RefKind &kind) {
-    assert(ctxt != nullptr);
-    YamlContext *info = reinterpret_cast<YamlContext *>(ctxt);
-    assert(info->_registry);
-    if (info->_registry->referenceKindFromString(scalar, kind.ns, kind.arch,
-                                                 kind.value))
-      return StringRef();
-    return StringRef("unknown reference kind");
-  }
-
-  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
-};
-
-template <> struct ScalarEnumerationTraits<lld::File::Kind> {
-  static void enumeration(IO &io, lld::File::Kind &value) {
-    io.enumCase(value, "error-object",   lld::File::kindErrorObject);
-    io.enumCase(value, "object",         lld::File::kindMachObject);
-    io.enumCase(value, "shared-library", lld::File::kindSharedLibrary);
-    io.enumCase(value, "static-library", lld::File::kindArchiveLibrary);
-  }
-};
-
-template <> struct ScalarEnumerationTraits<lld::Atom::Scope> {
-  static void enumeration(IO &io, lld::Atom::Scope &value) {
-    io.enumCase(value, "global", lld::Atom::scopeGlobal);
-    io.enumCase(value, "hidden", lld::Atom::scopeLinkageUnit);
-    io.enumCase(value, "static", lld::Atom::scopeTranslationUnit);
-  }
-};
-
-template <> struct ScalarEnumerationTraits<lld::DefinedAtom::SectionChoice> {
-  static void enumeration(IO &io, lld::DefinedAtom::SectionChoice &value) {
-    io.enumCase(value, "content", lld::DefinedAtom::sectionBasedOnContent);
-    io.enumCase(value, "custom",  lld::DefinedAtom::sectionCustomPreferred);
-    io.enumCase(value, "custom-required",
-                                 lld::DefinedAtom::sectionCustomRequired);
-  }
-};
-
-template <> struct ScalarEnumerationTraits<lld::DefinedAtom::Interposable> {
-  static void enumeration(IO &io, lld::DefinedAtom::Interposable &value) {
-    io.enumCase(value, "no",           DefinedAtom::interposeNo);
-    io.enumCase(value, "yes",          DefinedAtom::interposeYes);
-    io.enumCase(value, "yes-and-weak", DefinedAtom::interposeYesAndRuntimeWeak);
-  }
-};
-
-template <> struct ScalarEnumerationTraits<lld::DefinedAtom::Merge> {
-  static void enumeration(IO &io, lld::DefinedAtom::Merge &value) {
-    io.enumCase(value, "no",           lld::DefinedAtom::mergeNo);
-    io.enumCase(value, "as-tentative", lld::DefinedAtom::mergeAsTentative);
-    io.enumCase(value, "as-weak",      lld::DefinedAtom::mergeAsWeak);
-    io.enumCase(value, "as-addressed-weak",
-                                   lld::DefinedAtom::mergeAsWeakAndAddressUsed);
-    io.enumCase(value, "by-content",   lld::DefinedAtom::mergeByContent);
-    io.enumCase(value, "same-name-and-size",
-                lld::DefinedAtom::mergeSameNameAndSize);
-    io.enumCase(value, "largest", lld::DefinedAtom::mergeByLargestSection);
-  }
-};
-
-template <> struct ScalarEnumerationTraits<lld::DefinedAtom::DeadStripKind> {
-  static void enumeration(IO &io, lld::DefinedAtom::DeadStripKind &value) {
-    io.enumCase(value, "normal", lld::DefinedAtom::deadStripNormal);
-    io.enumCase(value, "never",  lld::DefinedAtom::deadStripNever);
-    io.enumCase(value, "always", lld::DefinedAtom::deadStripAlways);
-  }
-};
-
-template <> struct ScalarEnumerationTraits<lld::DefinedAtom::DynamicExport> {
-  static void enumeration(IO &io, lld::DefinedAtom::DynamicExport &value) {
-    io.enumCase(value, "normal", lld::DefinedAtom::dynamicExportNormal);
-    io.enumCase(value, "always", lld::DefinedAtom::dynamicExportAlways);
-  }
-};
-
-template <> struct ScalarEnumerationTraits<lld::DefinedAtom::CodeModel> {
-  static void enumeration(IO &io, lld::DefinedAtom::CodeModel &value) {
-    io.enumCase(value, "none", lld::DefinedAtom::codeNA);
-    io.enumCase(value, "mips-pic", lld::DefinedAtom::codeMipsPIC);
-    io.enumCase(value, "mips-micro", lld::DefinedAtom::codeMipsMicro);
-    io.enumCase(value, "mips-micro-pic", lld::DefinedAtom::codeMipsMicroPIC);
-    io.enumCase(value, "mips-16", lld::DefinedAtom::codeMips16);
-    io.enumCase(value, "arm-thumb", lld::DefinedAtom::codeARMThumb);
-    io.enumCase(value, "arm-a", lld::DefinedAtom::codeARM_a);
-    io.enumCase(value, "arm-d", lld::DefinedAtom::codeARM_d);
-    io.enumCase(value, "arm-t", lld::DefinedAtom::codeARM_t);
-  }
-};
-
-template <>
-struct ScalarEnumerationTraits<lld::DefinedAtom::ContentPermissions> {
-  static void enumeration(IO &io, lld::DefinedAtom::ContentPermissions &value) {
-    io.enumCase(value, "---",     lld::DefinedAtom::perm___);
-    io.enumCase(value, "r--",     lld::DefinedAtom::permR__);
-    io.enumCase(value, "r-x",     lld::DefinedAtom::permR_X);
-    io.enumCase(value, "rw-",     lld::DefinedAtom::permRW_);
-    io.enumCase(value, "rwx",     lld::DefinedAtom::permRWX);
-    io.enumCase(value, "rw-l",    lld::DefinedAtom::permRW_L);
-    io.enumCase(value, "unknown", lld::DefinedAtom::permUnknown);
-  }
-};
-
-template <> struct ScalarEnumerationTraits<lld::DefinedAtom::ContentType> {
-  static void enumeration(IO &io, lld::DefinedAtom::ContentType &value) {
-    io.enumCase(value, "unknown",         DefinedAtom::typeUnknown);
-    io.enumCase(value, "code",            DefinedAtom::typeCode);
-    io.enumCase(value, "stub",            DefinedAtom::typeStub);
-    io.enumCase(value, "constant",        DefinedAtom::typeConstant);
-    io.enumCase(value, "data",            DefinedAtom::typeData);
-    io.enumCase(value, "quick-data",      DefinedAtom::typeDataFast);
-    io.enumCase(value, "zero-fill",       DefinedAtom::typeZeroFill);
-    io.enumCase(value, "zero-fill-quick", DefinedAtom::typeZeroFillFast);
-    io.enumCase(value, "const-data",      DefinedAtom::typeConstData);
-    io.enumCase(value, "got",             DefinedAtom::typeGOT);
-    io.enumCase(value, "resolver",        DefinedAtom::typeResolver);
-    io.enumCase(value, "branch-island",   DefinedAtom::typeBranchIsland);
-    io.enumCase(value, "branch-shim",     DefinedAtom::typeBranchShim);
-    io.enumCase(value, "stub-helper",     DefinedAtom::typeStubHelper);
-    io.enumCase(value, "c-string",        DefinedAtom::typeCString);
-    io.enumCase(value, "utf16-string",    DefinedAtom::typeUTF16String);
-    io.enumCase(value, "unwind-cfi",      DefinedAtom::typeCFI);
-    io.enumCase(value, "unwind-lsda",     DefinedAtom::typeLSDA);
-    io.enumCase(value, "const-4-byte",    DefinedAtom::typeLiteral4);
-    io.enumCase(value, "const-8-byte",    DefinedAtom::typeLiteral8);
-    io.enumCase(value, "const-16-byte",   DefinedAtom::typeLiteral16);
-    io.enumCase(value, "lazy-pointer",    DefinedAtom::typeLazyPointer);
-    io.enumCase(value, "lazy-dylib-pointer",
-                                          DefinedAtom::typeLazyDylibPointer);
-    io.enumCase(value, "cfstring",        DefinedAtom::typeCFString);
-    io.enumCase(value, "initializer-pointer",
-                                          DefinedAtom::typeInitializerPtr);
-    io.enumCase(value, "terminator-pointer",
-                                          DefinedAtom::typeTerminatorPtr);
-    io.enumCase(value, "c-string-pointer",DefinedAtom::typeCStringPtr);
-    io.enumCase(value, "objc-class-pointer",
-                                          DefinedAtom::typeObjCClassPtr);
-    io.enumCase(value, "objc-category-list",
-                                          DefinedAtom::typeObjC2CategoryList);
-    io.enumCase(value, "objc-image-info",
-                                          DefinedAtom::typeObjCImageInfo);
-    io.enumCase(value, "objc-method-list",
-                                          DefinedAtom::typeObjCMethodList);
-    io.enumCase(value, "objc-class1",     DefinedAtom::typeObjC1Class);
-    io.enumCase(value, "dtraceDOF",       DefinedAtom::typeDTraceDOF);
-    io.enumCase(value, "interposing-tuples",
-                                          DefinedAtom::typeInterposingTuples);
-    io.enumCase(value, "lto-temp",        DefinedAtom::typeTempLTO);
-    io.enumCase(value, "compact-unwind",  DefinedAtom::typeCompactUnwindInfo);
-    io.enumCase(value, "unwind-info",     DefinedAtom::typeProcessedUnwindInfo);
-    io.enumCase(value, "tlv-thunk",       DefinedAtom::typeThunkTLV);
-    io.enumCase(value, "tlv-data",        DefinedAtom::typeTLVInitialData);
-    io.enumCase(value, "tlv-zero-fill",   DefinedAtom::typeTLVInitialZeroFill);
-    io.enumCase(value, "tlv-initializer-ptr",
-                                          DefinedAtom::typeTLVInitializerPtr);
-    io.enumCase(value, "mach_header",     DefinedAtom::typeMachHeader);
-    io.enumCase(value, "dso_handle",      DefinedAtom::typeDSOHandle);
-    io.enumCase(value, "sectcreate",      DefinedAtom::typeSectCreate);
-  }
-};
-
-template <> struct ScalarEnumerationTraits<lld::UndefinedAtom::CanBeNull> {
-  static void enumeration(IO &io, lld::UndefinedAtom::CanBeNull &value) {
-    io.enumCase(value, "never",       lld::UndefinedAtom::canBeNullNever);
-    io.enumCase(value, "at-runtime",  lld::UndefinedAtom::canBeNullAtRuntime);
-    io.enumCase(value, "at-buildtime",lld::UndefinedAtom::canBeNullAtBuildtime);
-  }
-};
-
-template <> struct ScalarEnumerationTraits<ShlibCanBeNull> {
-  static void enumeration(IO &io, ShlibCanBeNull &value) {
-    io.enumCase(value, "never",      false);
-    io.enumCase(value, "at-runtime", true);
-  }
-};
-
-template <>
-struct ScalarEnumerationTraits<lld::SharedLibraryAtom::Type> {
-  static void enumeration(IO &io, lld::SharedLibraryAtom::Type &value) {
-    io.enumCase(value, "code",    lld::SharedLibraryAtom::Type::Code);
-    io.enumCase(value, "data",    lld::SharedLibraryAtom::Type::Data);
-    io.enumCase(value, "unknown", lld::SharedLibraryAtom::Type::Unknown);
-  }
-};
-
-/// This is a custom formatter for lld::DefinedAtom::Alignment.  Values look
-/// like:
-///     8           # 8-byte aligned
-///     7 mod 16    # 16-byte aligned plus 7 bytes
-template <> struct ScalarTraits<lld::DefinedAtom::Alignment> {
-  static void output(const lld::DefinedAtom::Alignment &value, void *ctxt,
-                     raw_ostream &out) {
-    if (value.modulus == 0) {
-      out << llvm::format("%d", value.value);
-    } else {
-      out << llvm::format("%d mod %d", value.modulus, value.value);
-    }
-  }
-
-  static StringRef input(StringRef scalar, void *ctxt,
-                         lld::DefinedAtom::Alignment &value) {
-    value.modulus = 0;
-    size_t modStart = scalar.find("mod");
-    if (modStart != StringRef::npos) {
-      StringRef modStr = scalar.slice(0, modStart);
-      modStr = modStr.rtrim();
-      unsigned int modulus;
-      if (modStr.getAsInteger(0, modulus)) {
-        return "malformed alignment modulus";
-      }
-      value.modulus = modulus;
-      scalar = scalar.drop_front(modStart + 3);
-      scalar = scalar.ltrim();
-    }
-    unsigned int power;
-    if (scalar.getAsInteger(0, power)) {
-      return "malformed alignment power";
-    }
-    value.value = power;
-    if (value.modulus >= power) {
-      return "malformed alignment, modulus too large for power";
-    }
-    return StringRef(); // returning empty string means success
-  }
-
-  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
-};
-
-template <> struct ScalarEnumerationTraits<FileKinds> {
-  static void enumeration(IO &io, FileKinds &value) {
-    io.enumCase(value, "object",        fileKindObjectAtoms);
-    io.enumCase(value, "archive",       fileKindArchive);
-    io.enumCase(value, "object-mach-o", fileKindObjectMachO);
-  }
-};
-
-template <> struct MappingTraits<ArchMember> {
-  static void mapping(IO &io, ArchMember &member) {
-    io.mapOptional("kind",    member._kind, fileKindObjectAtoms);
-    io.mapOptional("name",    member._name);
-    io.mapRequired("content", member._content);
-  }
-};
-
-// Declare that an AtomList is a yaml sequence.
-template <typename T> struct SequenceTraits<AtomList<T> > {
-  static size_t size(IO &io, AtomList<T> &seq) { return seq._atoms.size(); }
-  static T *&element(IO &io, AtomList<T> &seq, size_t index) {
-    if (index >= seq._atoms.size())
-      seq._atoms.resize(index + 1);
-    return seq._atoms[index].get();
-  }
-};
-
-// Declare that an AtomRange is a yaml sequence.
-template <typename T> struct SequenceTraits<File::AtomRange<T> > {
-  static size_t size(IO &io, File::AtomRange<T> &seq) { return seq.size(); }
-  static T *&element(IO &io, File::AtomRange<T> &seq, size_t index) {
-    assert(io.outputting() && "AtomRange only used when outputting");
-    assert(index < seq.size() && "Out of range access");
-    return seq[index].get();
-  }
-};
-
-// Used to allow DefinedAtom content bytes to be a flow sequence of
-// two-digit hex numbers without the leading 0x (e.g. FF, 04, 0A)
-template <> struct ScalarTraits<ImplicitHex8> {
-  static void output(const ImplicitHex8 &val, void *, raw_ostream &out) {
-    uint8_t num = val;
-    out << llvm::format("%02X", num);
-  }
-
-  static StringRef input(StringRef str, void *, ImplicitHex8 &val) {
-    unsigned long long n;
-    if (getAsUnsignedInteger(str, 16, n))
-      return "invalid two-digit-hex number";
-    if (n > 0xFF)
-      return "out of range two-digit-hex number";
-    val = n;
-    return StringRef(); // returning empty string means success
-  }
-
-  static QuotingType mustQuote(StringRef) { return QuotingType::None; }
-};
-
-// YAML conversion for std::vector<const lld::File*>
-template <> struct DocumentListTraits<std::vector<const lld::File *> > {
-  static size_t size(IO &io, std::vector<const lld::File *> &seq) {
-    return seq.size();
-  }
-  static const lld::File *&element(IO &io, std::vector<const lld::File *> &seq,
-                                   size_t index) {
-    if (index >= seq.size())
-      seq.resize(index + 1);
-    return seq[index];
-  }
-};
-
-// YAML conversion for const lld::File*
-template <> struct MappingTraits<const lld::File *> {
-  class NormArchiveFile : public lld::ArchiveLibraryFile {
-  public:
-    NormArchiveFile(IO &io) : ArchiveLibraryFile("") {}
-
-    NormArchiveFile(IO &io, const lld::File *file)
-        : ArchiveLibraryFile(file->path()), _path(file->path()) {
-      // If we want to support writing archives, this constructor would
-      // need to populate _members.
-    }
-
-    const lld::File *denormalize(IO &io) { return this; }
-
-    const AtomRange<lld::DefinedAtom> defined() const override {
-      return _noDefinedAtoms;
-    }
-
-    const AtomRange<lld::UndefinedAtom> undefined() const override {
-      return _noUndefinedAtoms;
-    }
-
-    const AtomRange<lld::SharedLibraryAtom> sharedLibrary() const override {
-      return _noSharedLibraryAtoms;
-    }
-
-    const AtomRange<lld::AbsoluteAtom> absolute() const override {
-      return _noAbsoluteAtoms;
-    }
-
-    void clearAtoms() override {
-      _noDefinedAtoms.clear();
-      _noUndefinedAtoms.clear();
-      _noSharedLibraryAtoms.clear();
-      _noAbsoluteAtoms.clear();
-    }
-
-    File *find(StringRef name) override {
-      for (const ArchMember &member : _members)
-        for (const lld::DefinedAtom *atom : member._content->defined())
-          if (name == atom->name())
-            return const_cast<File *>(member._content);
-      return nullptr;
-    }
-
-    std::error_code
-    parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
-      return std::error_code();
-    }
-
-    StringRef               _path;
-    std::vector<ArchMember> _members;
-  };
-
-  class NormalizedFile : public lld::File {
-  public:
-    NormalizedFile(IO &io)
-      : File("", kindNormalizedObject), _io(io), _rnb(nullptr),
-        _definedAtomsRef(_definedAtoms._atoms),
-        _undefinedAtomsRef(_undefinedAtoms._atoms),
-        _sharedLibraryAtomsRef(_sharedLibraryAtoms._atoms),
-        _absoluteAtomsRef(_absoluteAtoms._atoms) {}
-
-    NormalizedFile(IO &io, const lld::File *file)
-        : File(file->path(), kindNormalizedObject), _io(io),
-          _rnb(new RefNameBuilder(*file)), _path(file->path()),
-        _definedAtomsRef(file->defined()),
-        _undefinedAtomsRef(file->undefined()),
-        _sharedLibraryAtomsRef(file->sharedLibrary()),
-        _absoluteAtomsRef(file->absolute()) {
-    }
-
-    ~NormalizedFile() override {
-    }
-
-    const lld::File *denormalize(IO &io);
-
-    const AtomRange<lld::DefinedAtom> defined() const override {
-      return _definedAtomsRef;
-    }
-
-    const AtomRange<lld::UndefinedAtom> undefined() const override {
-      return _undefinedAtomsRef;
-    }
-
-    const AtomRange<lld::SharedLibraryAtom> sharedLibrary() const override {
-      return _sharedLibraryAtomsRef;
-    }
-
-    const AtomRange<lld::AbsoluteAtom> absolute() const override {
-      return _absoluteAtomsRef;
-    }
-
-    void clearAtoms() override {
-      _definedAtoms._atoms.clear();
-      _undefinedAtoms._atoms.clear();
-      _sharedLibraryAtoms._atoms.clear();
-      _absoluteAtoms._atoms.clear();
-    }
-
-    // Allocate a new copy of this string in _storage, so the strings
-    // can be freed when File is destroyed.
-    StringRef copyString(StringRef str) {
-      char *s = _storage.Allocate<char>(str.size());
-      memcpy(s, str.data(), str.size());
-      return StringRef(s, str.size());
-    }
-
-    IO                                  &_io;
-    std::unique_ptr<RefNameBuilder>      _rnb;
-    StringRef                            _path;
-    AtomList<lld::DefinedAtom>           _definedAtoms;
-    AtomList<lld::UndefinedAtom>         _undefinedAtoms;
-    AtomList<lld::SharedLibraryAtom>     _sharedLibraryAtoms;
-    AtomList<lld::AbsoluteAtom>          _absoluteAtoms;
-    AtomRange<lld::DefinedAtom>          _definedAtomsRef;
-    AtomRange<lld::UndefinedAtom>        _undefinedAtomsRef;
-    AtomRange<lld::SharedLibraryAtom>    _sharedLibraryAtomsRef;
-    AtomRange<lld::AbsoluteAtom>         _absoluteAtomsRef;
-    llvm::BumpPtrAllocator               _storage;
-  };
-
-  static void mapping(IO &io, const lld::File *&file) {
-    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-    assert(info != nullptr);
-    // Let any register tag handler process this.
-    if (info->_registry && info->_registry->handleTaggedDoc(io, file))
-      return;
-    // If no registered handler claims this tag and there is no tag,
-    // grandfather in as "!native".
-    if (io.mapTag("!native", true) || io.mapTag("tag:yaml.org,2002:map"))
-      mappingAtoms(io, file);
-  }
-
-  static void mappingAtoms(IO &io, const lld::File *&file) {
-    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-    MappingNormalizationHeap<NormalizedFile, const lld::File *>
-      keys(io, file, nullptr);
-    assert(info != nullptr);
-    info->_file = keys.operator->();
-
-    io.mapOptional("path",                 keys->_path);
-
-    if (io.outputting()) {
-      io.mapOptional("defined-atoms",        keys->_definedAtomsRef);
-      io.mapOptional("undefined-atoms",      keys->_undefinedAtomsRef);
-      io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtomsRef);
-      io.mapOptional("absolute-atoms",       keys->_absoluteAtomsRef);
-    } else {
-      io.mapOptional("defined-atoms",        keys->_definedAtoms);
-      io.mapOptional("undefined-atoms",      keys->_undefinedAtoms);
-      io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtoms);
-      io.mapOptional("absolute-atoms",       keys->_absoluteAtoms);
-    }
-  }
-
-  static void mappingArchive(IO &io, const lld::File *&file) {
-    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-    MappingNormalizationHeap<NormArchiveFile, const lld::File *>
-      keys(io, file, &info->_file->allocator());
-
-    io.mapOptional("path",    keys->_path);
-    io.mapOptional("members", keys->_members);
-  }
-};
-
-// YAML conversion for const lld::Reference*
-template <> struct MappingTraits<const lld::Reference *> {
-  class NormalizedReference : public lld::Reference {
-  public:
-    NormalizedReference(IO &io)
-        : lld::Reference(lld::Reference::KindNamespace::all,
-                         lld::Reference::KindArch::all, 0),
-          _target(nullptr), _offset(0), _addend(0), _tag(0) {}
-
-    NormalizedReference(IO &io, const lld::Reference *ref)
-        : lld::Reference(ref->kindNamespace(), ref->kindArch(),
-                         ref->kindValue()),
-          _target(nullptr), _targetName(targetName(io, ref)),
-          _offset(ref->offsetInAtom()), _addend(ref->addend()),
-          _tag(ref->tag()) {
-      _mappedKind.ns = ref->kindNamespace();
-      _mappedKind.arch = ref->kindArch();
-      _mappedKind.value = ref->kindValue();
-    }
-
-    const lld::Reference *denormalize(IO &io) {
-      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-      assert(info != nullptr);
-      typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
-      NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
-      if (!_targetName.empty())
-        _targetName = f->copyString(_targetName);
-      DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs()
-                                        << "created Reference to name: '"
-                                        << _targetName << "' ("
-                                        << (const void *)_targetName.data()
-                                        << ", " << _targetName.size() << ")\n");
-      setKindNamespace(_mappedKind.ns);
-      setKindArch(_mappedKind.arch);
-      setKindValue(_mappedKind.value);
-      return this;
-    }
-
-    void bind(const RefNameResolver &);
-    static StringRef targetName(IO &io, const lld::Reference *ref);
-
-    uint64_t offsetInAtom() const override { return _offset; }
-    const lld::Atom *target() const override { return _target; }
-    Addend addend() const override { return _addend; }
-    void setAddend(Addend a) override { _addend = a; }
-    void setTarget(const lld::Atom *a) override { _target = a; }
-
-    const lld::Atom *_target;
-    StringRef        _targetName;
-    uint32_t         _offset;
-    Addend           _addend;
-    RefKind          _mappedKind;
-    uint32_t         _tag;
-  };
-
-  static void mapping(IO &io, const lld::Reference *&ref) {
-    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-    MappingNormalizationHeap<NormalizedReference, const lld::Reference *> keys(
-        io, ref, &info->_file->allocator());
-
-    io.mapRequired("kind",   keys->_mappedKind);
-    io.mapOptional("offset", keys->_offset);
-    io.mapOptional("target", keys->_targetName);
-    io.mapOptional("addend", keys->_addend, (lld::Reference::Addend)0);
-    io.mapOptional("tag",    keys->_tag, 0u);
-  }
-};
-
-// YAML conversion for const lld::DefinedAtom*
-template <> struct MappingTraits<const lld::DefinedAtom *> {
-
-  class NormalizedAtom : public lld::DefinedAtom {
-  public:
-    NormalizedAtom(IO &io)
-        : _file(fileFromContext(io)), _contentType(), _alignment(1) {
-      static uint32_t ordinalCounter = 1;
-      _ordinal = ordinalCounter++;
-    }
-
-    NormalizedAtom(IO &io, const lld::DefinedAtom *atom)
-        : _file(fileFromContext(io)), _name(atom->name()),
-          _scope(atom->scope()), _interpose(atom->interposable()),
-          _merge(atom->merge()), _contentType(atom->contentType()),
-          _alignment(atom->alignment()), _sectionChoice(atom->sectionChoice()),
-          _deadStrip(atom->deadStrip()), _dynamicExport(atom->dynamicExport()),
-          _codeModel(atom->codeModel()),
-          _permissions(atom->permissions()), _size(atom->size()),
-          _sectionName(atom->customSectionName()),
-          _sectionSize(atom->sectionSize()) {
-      for (const lld::Reference *r : *atom)
-        _references.push_back(r);
-      if (!atom->occupiesDiskSpace())
-        return;
-      ArrayRef<uint8_t> cont = atom->rawContent();
-      _content.reserve(cont.size());
-      for (uint8_t x : cont)
-        _content.push_back(x);
-    }
-
-    ~NormalizedAtom() override = default;
-
-    const lld::DefinedAtom *denormalize(IO &io) {
-      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-      assert(info != nullptr);
-      typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
-      NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
-      if (!_name.empty())
-        _name = f->copyString(_name);
-      if (!_refName.empty())
-        _refName = f->copyString(_refName);
-      if (!_sectionName.empty())
-        _sectionName = f->copyString(_sectionName);
-      DEBUG_WITH_TYPE("WriterYAML",
-                      llvm::dbgs() << "created DefinedAtom named: '" << _name
-                                   << "' (" << (const void *)_name.data()
-                                   << ", " << _name.size() << ")\n");
-      return this;
-    }
-
-    void bind(const RefNameResolver &);
-
-    // Extract current File object from YAML I/O parsing context
-    const lld::File &fileFromContext(IO &io) {
-      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-      assert(info != nullptr);
-      assert(info->_file != nullptr);
-      return *info->_file;
-    }
-
-    const lld::File &file() const override { return _file; }
-    StringRef name() const override { return _name; }
-    uint64_t size() const override { return _size; }
-    Scope scope() const override { return _scope; }
-    Interposable interposable() const override { return _interpose; }
-    Merge merge() const override { return _merge; }
-    ContentType contentType() const override { return _contentType; }
-    Alignment alignment() const override { return _alignment; }
-    SectionChoice sectionChoice() const override { return _sectionChoice; }
-    StringRef customSectionName() const override { return _sectionName; }
-    uint64_t sectionSize() const override { return _sectionSize; }
-    DeadStripKind deadStrip() const override { return _deadStrip; }
-    DynamicExport dynamicExport() const override { return _dynamicExport; }
-    CodeModel codeModel() const override { return _codeModel; }
-    ContentPermissions permissions() const override { return _permissions; }
-    ArrayRef<uint8_t> rawContent() const override {
-      if (!occupiesDiskSpace())
-        return ArrayRef<uint8_t>();
-      return ArrayRef<uint8_t>(
-          reinterpret_cast<const uint8_t *>(_content.data()), _content.size());
-    }
-
-    uint64_t ordinal() const override { return _ordinal; }
-
-    reference_iterator begin() const override {
-      uintptr_t index = 0;
-      const void *it = reinterpret_cast<const void *>(index);
-      return reference_iterator(*this, it);
-    }
-    reference_iterator end() const override {
-      uintptr_t index = _references.size();
-      const void *it = reinterpret_cast<const void *>(index);
-      return reference_iterator(*this, it);
-    }
-    const lld::Reference *derefIterator(const void *it) const override {
-      uintptr_t index = reinterpret_cast<uintptr_t>(it);
-      assert(index < _references.size());
-      return _references[index];
-    }
-    void incrementIterator(const void *&it) const override {
-      uintptr_t index = reinterpret_cast<uintptr_t>(it);
-      ++index;
-      it = reinterpret_cast<const void *>(index);
-    }
-
-    void addReference(Reference::KindNamespace ns,
-                      Reference::KindArch arch,
-                      Reference::KindValue kindValue, uint64_t off,
-                      const Atom *target, Reference::Addend a) override {
-      assert(target && "trying to create reference to nothing");
-      auto node = new (file().allocator()) SimpleReference(ns, arch, kindValue,
-                                                           off, target, a);
-      _references.push_back(node);
-    }
-
-    const lld::File                    &_file;
-    StringRef                           _name;
-    StringRef                           _refName;
-    Scope                               _scope;
-    Interposable                        _interpose;
-    Merge                               _merge;
-    ContentType                         _contentType;
-    Alignment                           _alignment;
-    SectionChoice                       _sectionChoice;
-    DeadStripKind                       _deadStrip;
-    DynamicExport                       _dynamicExport;
-    CodeModel                           _codeModel;
-    ContentPermissions                  _permissions;
-    uint32_t                            _ordinal;
-    std::vector<ImplicitHex8>           _content;
-    uint64_t                            _size;
-    StringRef                           _sectionName;
-    uint64_t                            _sectionSize;
-    std::vector<const lld::Reference *> _references;
-  };
-
-  static void mapping(IO &io, const lld::DefinedAtom *&atom) {
-    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-    MappingNormalizationHeap<NormalizedAtom, const lld::DefinedAtom *> keys(
-        io, atom, &info->_file->allocator());
-    if (io.outputting()) {
-      // If writing YAML, check if atom needs a ref-name.
-      typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
-      assert(info != nullptr);
-      NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
-      assert(f);
-      assert(f->_rnb);
-      if (f->_rnb->hasRefName(atom)) {
-        keys->_refName = f->_rnb->refName(atom);
-      }
-    }
-
-    io.mapOptional("name",             keys->_name,    StringRef());
-    io.mapOptional("ref-name",         keys->_refName, StringRef());
-    io.mapOptional("scope",            keys->_scope,
-                                         DefinedAtom::scopeTranslationUnit);
-    io.mapOptional("type",             keys->_contentType,
-                                         DefinedAtom::typeCode);
-    io.mapOptional("content",          keys->_content);
-    io.mapOptional("size",             keys->_size, (uint64_t)keys->_content.size());
-    io.mapOptional("interposable",     keys->_interpose,
-                                         DefinedAtom::interposeNo);
-    io.mapOptional("merge",            keys->_merge, DefinedAtom::mergeNo);
-    io.mapOptional("alignment",        keys->_alignment,
-                                         DefinedAtom::Alignment(1));
-    io.mapOptional("section-choice",   keys->_sectionChoice,
-                                         DefinedAtom::sectionBasedOnContent);
-    io.mapOptional("section-name",     keys->_sectionName, StringRef());
-    io.mapOptional("section-size",     keys->_sectionSize, (uint64_t)0);
-    io.mapOptional("dead-strip",       keys->_deadStrip,
-                                         DefinedAtom::deadStripNormal);
-    io.mapOptional("dynamic-export",   keys->_dynamicExport,
-                                         DefinedAtom::dynamicExportNormal);
-    io.mapOptional("code-model",       keys->_codeModel, DefinedAtom::codeNA);
-    // default permissions based on content type
-    io.mapOptional("permissions",      keys->_permissions,
-                                         DefinedAtom::permissions(
-                                                          keys->_contentType));
-    io.mapOptional("references",       keys->_references);
-  }
-};
-
-template <> struct MappingTraits<lld::DefinedAtom *> {
-  static void mapping(IO &io, lld::DefinedAtom *&atom) {
-    const lld::DefinedAtom *atomPtr = atom;
-    MappingTraits<const lld::DefinedAtom *>::mapping(io, atomPtr);
-    atom = const_cast<lld::DefinedAtom *>(atomPtr);
-  }
-};
-
-// YAML conversion for const lld::UndefinedAtom*
-template <> struct MappingTraits<const lld::UndefinedAtom *> {
-  class NormalizedAtom : public lld::UndefinedAtom {
-  public:
-    NormalizedAtom(IO &io)
-        : _file(fileFromContext(io)), _canBeNull(canBeNullNever) {}
-
-    NormalizedAtom(IO &io, const lld::UndefinedAtom *atom)
-        : _file(fileFromContext(io)), _name(atom->name()),
-          _canBeNull(atom->canBeNull()) {}
-
-    ~NormalizedAtom() override = default;
-
-    const lld::UndefinedAtom *denormalize(IO &io) {
-      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-      assert(info != nullptr);
-      typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
-      NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
-      if (!_name.empty())
-        _name = f->copyString(_name);
-
-      DEBUG_WITH_TYPE("WriterYAML",
-                      llvm::dbgs() << "created UndefinedAtom named: '" << _name
-                      << "' (" << (const void *)_name.data() << ", "
-                      << _name.size() << ")\n");
-      return this;
-    }
-
-    // Extract current File object from YAML I/O parsing context
-    const lld::File &fileFromContext(IO &io) {
-      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-      assert(info != nullptr);
-      assert(info->_file != nullptr);
-      return *info->_file;
-    }
-
-    const lld::File &file() const override { return _file; }
-    StringRef name() const override { return _name; }
-    CanBeNull canBeNull() const override { return _canBeNull; }
-
-    const lld::File     &_file;
-    StringRef            _name;
-    CanBeNull            _canBeNull;
-  };
-
-  static void mapping(IO &io, const lld::UndefinedAtom *&atom) {
-    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-    MappingNormalizationHeap<NormalizedAtom, const lld::UndefinedAtom *> keys(
-        io, atom, &info->_file->allocator());
-
-    io.mapRequired("name",        keys->_name);
-    io.mapOptional("can-be-null", keys->_canBeNull,
-                                  lld::UndefinedAtom::canBeNullNever);
-  }
-};
-
-template <> struct MappingTraits<lld::UndefinedAtom *> {
-  static void mapping(IO &io, lld::UndefinedAtom *&atom) {
-    const lld::UndefinedAtom *atomPtr = atom;
-    MappingTraits<const lld::UndefinedAtom *>::mapping(io, atomPtr);
-    atom = const_cast<lld::UndefinedAtom *>(atomPtr);
-  }
-};
-
-// YAML conversion for const lld::SharedLibraryAtom*
-template <> struct MappingTraits<const lld::SharedLibraryAtom *> {
-  class NormalizedAtom : public lld::SharedLibraryAtom {
-  public:
-    NormalizedAtom(IO &io)
-        : _file(fileFromContext(io)), _canBeNull(false),
-          _type(Type::Unknown), _size(0) {}
-
-    NormalizedAtom(IO &io, const lld::SharedLibraryAtom *atom)
-        : _file(fileFromContext(io)), _name(atom->name()),
-          _loadName(atom->loadName()), _canBeNull(atom->canBeNullAtRuntime()),
-          _type(atom->type()), _size(atom->size()) {}
-
-    ~NormalizedAtom() override = default;
-
-    const lld::SharedLibraryAtom *denormalize(IO &io) {
-      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-      assert(info != nullptr);
-      typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
-      NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
-      if (!_name.empty())
-        _name = f->copyString(_name);
-      if (!_loadName.empty())
-        _loadName = f->copyString(_loadName);
-
-      DEBUG_WITH_TYPE("WriterYAML",
-                      llvm::dbgs() << "created SharedLibraryAtom named: '"
-                                   << _name << "' ("
-                                   << (const void *)_name.data()
-                                   << ", " << _name.size() << ")\n");
-      return this;
-    }
-
-    // Extract current File object from YAML I/O parsing context
-    const lld::File &fileFromContext(IO &io) {
-      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-      assert(info != nullptr);
-      assert(info->_file != nullptr);
-      return *info->_file;
-    }
-
-    const lld::File &file() const override { return _file; }
-    StringRef name() const override { return _name; }
-    StringRef loadName() const override { return _loadName; }
-    bool canBeNullAtRuntime() const override { return _canBeNull; }
-    Type type() const override { return _type; }
-    uint64_t size() const override { return _size; }
-
-    const lld::File &_file;
-    StringRef        _name;
-    StringRef        _loadName;
-    ShlibCanBeNull   _canBeNull;
-    Type             _type;
-    uint64_t         _size;
-  };
-
-  static void mapping(IO &io, const lld::SharedLibraryAtom *&atom) {
-
-    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-    MappingNormalizationHeap<NormalizedAtom, const lld::SharedLibraryAtom *>
-    keys(io, atom, &info->_file->allocator());
-
-    io.mapRequired("name",        keys->_name);
-    io.mapOptional("load-name",   keys->_loadName);
-    io.mapOptional("can-be-null", keys->_canBeNull, (ShlibCanBeNull) false);
-    io.mapOptional("type",        keys->_type, SharedLibraryAtom::Type::Code);
-    io.mapOptional("size",        keys->_size, uint64_t(0));
-  }
-};
-
-template <> struct MappingTraits<lld::SharedLibraryAtom *> {
-  static void mapping(IO &io, lld::SharedLibraryAtom *&atom) {
-    const lld::SharedLibraryAtom *atomPtr = atom;
-    MappingTraits<const lld::SharedLibraryAtom *>::mapping(io, atomPtr);
-    atom = const_cast<lld::SharedLibraryAtom *>(atomPtr);
-  }
-};
-
-// YAML conversion for const lld::AbsoluteAtom*
-template <> struct MappingTraits<const lld::AbsoluteAtom *> {
-  class NormalizedAtom : public lld::AbsoluteAtom {
-  public:
-    NormalizedAtom(IO &io)
-        : _file(fileFromContext(io)), _scope(), _value(0) {}
-
-    NormalizedAtom(IO &io, const lld::AbsoluteAtom *atom)
-        : _file(fileFromContext(io)), _name(atom->name()),
-          _scope(atom->scope()), _value(atom->value()) {}
-
-    ~NormalizedAtom() override = default;
-
-    const lld::AbsoluteAtom *denormalize(IO &io) {
-      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-      assert(info != nullptr);
-      typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
-      NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
-      if (!_name.empty())
-        _name = f->copyString(_name);
-
-      DEBUG_WITH_TYPE("WriterYAML",
-                      llvm::dbgs() << "created AbsoluteAtom named: '" << _name
-                                   << "' (" << (const void *)_name.data()
-                                   << ", " << _name.size() << ")\n");
-      return this;
-    }
-
-    // Extract current File object from YAML I/O parsing context
-    const lld::File &fileFromContext(IO &io) {
-      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-      assert(info != nullptr);
-      assert(info->_file != nullptr);
-      return *info->_file;
-    }
-
-    const lld::File &file() const override { return _file; }
-    StringRef name() const override { return _name; }
-    uint64_t value() const override { return _value; }
-    Scope scope() const override { return _scope; }
-
-    const lld::File &_file;
-    StringRef        _name;
-    StringRef        _refName;
-    Scope            _scope;
-    Hex64            _value;
-  };
-
-  static void mapping(IO &io, const lld::AbsoluteAtom *&atom) {
-    YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-    MappingNormalizationHeap<NormalizedAtom, const lld::AbsoluteAtom *> keys(
-        io, atom, &info->_file->allocator());
-
-    if (io.outputting()) {
-      typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
-      YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-      assert(info != nullptr);
-      NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
-      assert(f);
-      assert(f->_rnb);
-      if (f->_rnb->hasRefName(atom)) {
-        keys->_refName = f->_rnb->refName(atom);
-      }
-    }
-
-    io.mapRequired("name",     keys->_name);
-    io.mapOptional("ref-name", keys->_refName, StringRef());
-    io.mapOptional("scope",    keys->_scope);
-    io.mapRequired("value",    keys->_value);
-  }
-};
-
-template <> struct MappingTraits<lld::AbsoluteAtom *> {
-  static void mapping(IO &io, lld::AbsoluteAtom *&atom) {
-    const lld::AbsoluteAtom *atomPtr = atom;
-    MappingTraits<const lld::AbsoluteAtom *>::mapping(io, atomPtr);
-    atom = const_cast<lld::AbsoluteAtom *>(atomPtr);
-  }
-};
-
-} // end namespace llvm
-} // end namespace yaml
-
-RefNameResolver::RefNameResolver(const lld::File *file, IO &io) : _io(io) {
-  typedef MappingTraits<const lld::DefinedAtom *>::NormalizedAtom
-  NormalizedAtom;
-  for (const lld::DefinedAtom *a : file->defined()) {
-    const auto *na = (const NormalizedAtom *)a;
-    if (!na->_refName.empty())
-      add(na->_refName, a);
-    else if (!na->_name.empty())
-      add(na->_name, a);
-  }
-
-  for (const lld::UndefinedAtom *a : file->undefined())
-    add(a->name(), a);
-
-  for (const lld::SharedLibraryAtom *a : file->sharedLibrary())
-    add(a->name(), a);
-
-  typedef MappingTraits<const lld::AbsoluteAtom *>::NormalizedAtom NormAbsAtom;
-  for (const lld::AbsoluteAtom *a : file->absolute()) {
-    const auto *na = (const NormAbsAtom *)a;
-    if (na->_refName.empty())
-      add(na->_name, a);
-    else
-      add(na->_refName, a);
-  }
-}
-
-inline const lld::File *
-MappingTraits<const lld::File *>::NormalizedFile::denormalize(IO &io) {
-  typedef MappingTraits<const lld::DefinedAtom *>::NormalizedAtom
-  NormalizedAtom;
-
-  RefNameResolver nameResolver(this, io);
-  // Now that all atoms are parsed, references can be bound.
-  for (const lld::DefinedAtom *a : this->defined()) {
-    auto *normAtom = (NormalizedAtom *)const_cast<DefinedAtom *>(a);
-    normAtom->bind(nameResolver);
-  }
-
-  return this;
-}
-
-inline void MappingTraits<const lld::DefinedAtom *>::NormalizedAtom::bind(
-    const RefNameResolver &resolver) {
-  typedef MappingTraits<const lld::Reference *>::NormalizedReference
-  NormalizedReference;
-  for (const lld::Reference *ref : _references) {
-    auto *normRef = (NormalizedReference *)const_cast<Reference *>(ref);
-    normRef->bind(resolver);
-  }
-}
-
-inline void MappingTraits<const lld::Reference *>::NormalizedReference::bind(
-    const RefNameResolver &resolver) {
-  _target = resolver.lookup(_targetName);
-}
-
-inline StringRef
-MappingTraits<const lld::Reference *>::NormalizedReference::targetName(
-    IO &io, const lld::Reference *ref) {
-  if (ref->target() == nullptr)
-    return StringRef();
-  YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
-  assert(info != nullptr);
-  typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
-  NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
-  RefNameBuilder &rnb = *f->_rnb;
-  if (rnb.hasRefName(ref->target()))
-    return rnb.refName(ref->target());
-  return ref->target()->name();
-}
-
-namespace lld {
-namespace yaml {
-
-class Writer : public lld::Writer {
-public:
-  Writer(const LinkingContext &context) : _ctx(context) {}
-
-  llvm::Error writeFile(const lld::File &file, StringRef outPath) override {
-    // Create stream to path.
-    std::error_code ec;
-    llvm::raw_fd_ostream out(outPath, ec, llvm::sys::fs::OF_TextWithCRLF);
-    if (ec)
-      return llvm::errorCodeToError(ec);
-
-    // Create yaml Output writer, using yaml options for context.
-    YamlContext yamlContext;
-    yamlContext._ctx = &_ctx;
-    yamlContext._registry = &_ctx.registry();
-    llvm::yaml::Output yout(out, &yamlContext);
-
-    // Write yaml output.
-    const lld::File *fileRef = &file;
-    yout << fileRef;
-
-    return llvm::Error::success();
-  }
-
-private:
-  const LinkingContext &_ctx;
-};
-
-} // end namespace yaml
-
-namespace {
-
-/// Handles !native tagged yaml documents.
-class NativeYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
-  bool handledDocTag(llvm::yaml::IO &io, const lld::File *&file) const override {
-    if (io.mapTag("!native")) {
-      MappingTraits<const lld::File *>::mappingAtoms(io, file);
-      return true;
-    }
-    return false;
-  }
-};
-
-/// Handles !archive tagged yaml documents.
-class ArchiveYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
-  bool handledDocTag(llvm::yaml::IO &io, const lld::File *&file) const override {
-    if (io.mapTag("!archive")) {
-      MappingTraits<const lld::File *>::mappingArchive(io, file);
-      return true;
-    }
-    return false;
-  }
-};
-
-class YAMLReader : public Reader {
-public:
-  YAMLReader(const Registry &registry) : _registry(registry) {}
-
-  bool canParse(file_magic magic, MemoryBufferRef mb) const override {
-    StringRef name = mb.getBufferIdentifier();
-    return name.endswith(".objtxt") || name.endswith(".yaml");
-  }
-
-  ErrorOr<std::unique_ptr<File>>
-  loadFile(std::unique_ptr<MemoryBuffer> mb,
-           const class Registry &) const override {
-    // Create YAML Input Reader.
-    YamlContext yamlContext;
-    yamlContext._registry = &_registry;
-    yamlContext._path = mb->getBufferIdentifier();
-    llvm::yaml::Input yin(mb->getBuffer(), &yamlContext);
-
-    // Fill vector with File objects created by parsing yaml.
-    std::vector<const lld::File *> createdFiles;
-    yin >> createdFiles;
-    assert(createdFiles.size() == 1);
-
-    // Error out now if there were parsing errors.
-    if (yin.error())
-      return make_error_code(lld::YamlReaderError::illegal_value);
-
-    std::shared_ptr<MemoryBuffer> smb(mb.release());
-    const File *file = createdFiles[0];
-    // Note: loadFile() should return vector of *const* File
-    File *f = const_cast<File *>(file);
-    f->setLastError(std::error_code());
-    f->setSharedMemoryBuffer(smb);
-    return std::unique_ptr<File>(f);
-  }
-
-private:
-  const Registry &_registry;
-};
-
-} // end anonymous namespace
-
-void Registry::addSupportYamlFiles() {
-  add(std::unique_ptr<Reader>(new YAMLReader(*this)));
-  add(std::unique_ptr<YamlIOTaggedDocumentHandler>(
-                                    new NativeYamlIOTaggedDocumentHandler()));
-  add(std::unique_ptr<YamlIOTaggedDocumentHandler>(
-                                    new ArchiveYamlIOTaggedDocumentHandler()));
-}
-
-std::unique_ptr<Writer> createWriterYAML(const LinkingContext &context) {
-  return std::unique_ptr<Writer>(new lld::yaml::Writer(context));
-}
-
-} // end namespace lld
index 1262839..c094591 100644 (file)
@@ -23,11 +23,16 @@ lld_target_link_libraries(lld
   lldCommon
   lldCOFF
   lldELF
-  lldMachO
   lldMinGW
   lldWasm
   )
 
+if (LLD_ENABLE_MACHO)
+  target_link_libraries(lld  
+    lldMachO
+    )
+endif() 
+
 install(TARGETS lld
   RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
 
index 8d76f25..a24964c 100644 (file)
@@ -25,6 +25,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "lld/Common/CommonLinkerContext.h"
 #include "lld/Common/Driver.h"
 #include "lld/Common/ErrorHandler.h"
 #include "lld/Common/Memory.h"
@@ -39,7 +40,9 @@
 #include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/PluginLoader.h"
+#include "llvm/Support/Process.h"
 #include <cstdlib>
+#include <optional>
 
 using namespace lld;
 using namespace llvm;
@@ -47,11 +50,10 @@ using namespace llvm::sys;
 
 enum Flavor {
   Invalid,
-  Gnu,       // -flavor gnu
-  WinLink,   // -flavor link
-  Darwin,    // -flavor darwin
-  DarwinOld, // -flavor darwinold
-  Wasm,      // -flavor wasm
+  Gnu,     // -flavor gnu
+  WinLink, // -flavor link
+  Darwin,  // -flavor darwin
+  Wasm,    // -flavor wasm
 };
 
 [[noreturn]] static void die(const Twine &s) {
@@ -64,13 +66,11 @@ static Flavor getFlavor(StringRef s) {
       .CasesLower("ld", "ld.lld", "gnu", Gnu)
       .CasesLower("wasm", "ld-wasm", Wasm)
       .CaseLower("link", WinLink)
-      .CasesLower("ld64", "ld64.lld", "darwin", "darwinnew",
-                  "ld64.lld.darwinnew", Darwin)
-      .CasesLower("darwinold", "ld64.lld.darwinold", DarwinOld)
+      .CasesLower("ld64", "ld64.lld", "darwin", Darwin)
       .Default(Invalid);
 }
 
-#ifndef __OpenBSD__
+#ifdef LLD_ENABLE_MINGW
 static cl::TokenizerCallback getDefaultQuotingStyle() {
   if (Triple(sys::getProcessTriple()).getOS() == Triple::Win32)
     return cl::TokenizeWindowsCommandLine;
@@ -90,7 +90,11 @@ static bool isPETarget(std::vector<const char *> &v) {
   // Expand response files (arguments in the form of @<filename>)
   // to allow detecting the -m argument from arguments in them.
   SmallVector<const char *, 256> expandedArgs(v.data(), v.data() + v.size());
-  cl::ExpandResponseFiles(saver, getDefaultQuotingStyle(), expandedArgs);
+  BumpPtrAllocator a;
+  StringSaver saver(a);
+  cl::ExpansionContext ECtx(saver.getAllocator(), getDefaultQuotingStyle());
+  if (Error Err = ECtx.expandResponseFiles(expandedArgs))
+    die(toString(std::move(Err)));
   for (auto it = expandedArgs.begin(); it + 1 != expandedArgs.end(); ++it) {
     if (StringRef(*it) != "-m")
       continue;
@@ -138,33 +142,52 @@ static Flavor parseFlavor(std::vector<const char *> &v) {
   return parseProgname(arg0);
 }
 
+bool inTestOutputDisabled = false;
+
 /// Universal linker main(). This linker emulates the gnu, darwin, or
 /// windows linker based on the argv[0] or -flavor option.
 static int lldMain(int argc, const char **argv, llvm::raw_ostream &stdoutOS,
                    llvm::raw_ostream &stderrOS, bool exitEarly = true) {
   std::vector<const char *> args(argv, argv + argc);
-  switch (parseFlavor(args)) {
-  case Gnu:
-#ifndef __OpenBSD__
-    if (isPETarget(args))
-      return !mingw::link(args, exitEarly, stdoutOS, stderrOS);
+  auto link = [&args]() {
+    Flavor f = parseFlavor(args);
+#ifdef LLD_ENABLE_MINGW
+    if (f == Gnu && isPETarget(args))
+      return mingw::link;
+    else if (f == Gnu)
+#else
+    if (f == Gnu)
 #endif
-    return !elf::link(args, exitEarly, stdoutOS, stderrOS);
-#ifndef __OpenBSD__
-  case WinLink:
-    return !coff::link(args, exitEarly, stdoutOS, stderrOS);
-  case Darwin:
-    return !macho::link(args, exitEarly, stdoutOS, stderrOS);
-  case DarwinOld:
-    return !mach_o::link(args, exitEarly, stdoutOS, stderrOS);
-  case Wasm:
-    return !lld::wasm::link(args, exitEarly, stdoutOS, stderrOS);
+      return elf::link;
+#ifdef LLD_ENABLE_COFF
+    else if (f == WinLink)
+      return coff::link;
 #endif
-  default:
-    die("lld is a generic driver.\n"
-        "Invoke ld.lld (Unix), ld64.lld (macOS), lld-link (Windows), wasm-ld"
-        " (WebAssembly) instead");
-  }
+#ifdef LLD_ENABLE_MACHO
+    else if (f == Darwin)
+      return macho::link;
+#endif
+#ifdef LLD_ENABLE_WASM
+    else if (f == Wasm)
+      return lld::wasm::link;
+#endif
+    else
+      die("lld is a generic driver.\n"
+          "Invoke ld.lld (Unix), ld64.lld (macOS), lld-link (Windows), wasm-ld"
+          " (WebAssembly) instead");
+  }();
+  // Run the driver. If an error occurs, false will be returned.
+  bool r = link(args, stdoutOS, stderrOS, exitEarly, inTestOutputDisabled);
+
+  // Call exit() if we can to avoid calling destructors.
+  if (exitEarly)
+    exitLld(!r ? 1 : 0);
+
+  // Delete the global context and clear the global context pointer, so that it
+  // cannot be accessed anymore.
+  CommonLinkerContext::destroy();
+
+  return !r ? 1 : 0;
 }
 
 // Similar to lldMain except that exceptions are caught.
@@ -186,7 +209,7 @@ SafeReturn lld::safeLldMain(int argc, const char **argv,
   // Cleanup memory and reset everything back in pristine condition. This path
   // is only taken when LLD is in test, or when it is used as a library.
   llvm::CrashRecoveryContext crc;
-  if (!crc.RunSafely([&]() { errorHandler().reset(); })) {
+  if (!crc.RunSafely([&]() { CommonLinkerContext::destroy(); })) {
     // The memory is corrupted beyond any possible recovery.
     return {r, /*canRunAgain=*/false};
   }
@@ -203,24 +226,32 @@ static unsigned inTestVerbosity() {
   return v;
 }
 
-int main(int argc, const char **argv) {
+int lld_main(int argc, char **argv) {
   InitLLVM x(argc, argv);
+  sys::Process::UseANSIEscapeCodes(true);
+
+  if (::getenv("FORCE_LLD_DIAGNOSTICS_CRASH")) {
+    llvm::errs()
+        << "crashing due to environment variable FORCE_LLD_DIAGNOSTICS_CRASH\n";
+    LLVM_BUILTIN_TRAP;
+  }
 
   // Not running in lit tests, just take the shortest codepath with global
   // exception handling and no memory cleanup on exit.
   if (!inTestVerbosity())
-    return lldMain(argc, argv, llvm::outs(), llvm::errs());
+    return lldMain(argc, const_cast<const char **>(argv), llvm::outs(),
+                   llvm::errs());
 
-  Optional<int> mainRet;
+  std::optional<int> mainRet;
   CrashRecoveryContext::Enable();
 
   for (unsigned i = inTestVerbosity(); i > 0; --i) {
     // Disable stdout/stderr for all iterations but the last one.
-    if (i != 1)
-      errorHandler().disableOutput = true;
+    inTestOutputDisabled = (i != 1);
 
     // Execute one iteration.
-    auto r = safeLldMain(argc, argv, llvm::outs(), llvm::errs());
+    auto r = safeLldMain(argc, const_cast<const char **>(argv), llvm::outs(),
+                         llvm::errs());
     if (!r.canRunAgain)
       exitLld(r.ret); // Exit now, can't re-execute again.
 
diff --git a/gnu/llvm/lld/unittests/CMakeLists.txt b/gnu/llvm/lld/unittests/CMakeLists.txt
deleted file mode 100644 (file)
index 84d35d4..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-add_custom_target(LLDUnitTests)
-set_target_properties(LLDUnitTests PROPERTIES FOLDER "lld tests")
-
-set(CMAKE_BUILD_WITH_INSTALL_RPATH OFF)
-
-# add_lld_unittest(test_dirname file1.cpp file2.cpp)
-#
-# Will compile the list of files together and link against lld
-# Produces a binary named 'basename(test_dirname)'.
-function(add_lld_unittest test_dirname)
-  add_unittest(LLDUnitTests ${test_dirname} ${ARGN})
-  target_link_libraries(${test_dirname} ${LLVM_COMMON_LIBS})
-endfunction()
-
-add_subdirectory(DriverTests)
-add_subdirectory(MachOTests)
diff --git a/gnu/llvm/lld/unittests/DriverTests/CMakeLists.txt b/gnu/llvm/lld/unittests/DriverTests/CMakeLists.txt
deleted file mode 100644 (file)
index 7137d69..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-add_lld_unittest(DriverTests
-  DarwinLdDriverTest.cpp
-  )
-
-target_link_libraries(DriverTests
-  PRIVATE
-  lldDriver
-  lldMachO
-  )
diff --git a/gnu/llvm/lld/unittests/DriverTests/DarwinLdDriverTest.cpp b/gnu/llvm/lld/unittests/DriverTests/DarwinLdDriverTest.cpp
deleted file mode 100644 (file)
index af0fbbe..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-//===- lld/unittest/DarwinLdDriverTest.cpp --------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// Darwin's ld driver tests.
-///
-//===----------------------------------------------------------------------===//
-
-#include "lld/Common/Driver.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/raw_ostream.h"
-#include "gtest/gtest.h"
-
-using namespace llvm;
-using namespace lld;
-
-namespace lld {
-namespace mach_o {
-bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx);
-}
-}
-
-namespace {
-class DarwinLdParserTest : public testing::Test {
-protected:
-  int inputFileCount() { return _ctx.getNodes().size(); }
-
-  StringRef inputFile(int index) {
-    Node &node = *_ctx.getNodes()[index];
-    if (node.kind() == Node::Kind::File)
-      return cast<FileNode>(&node)->getFile()->path();
-    llvm_unreachable("not handling other types of input files");
-  }
-
-  bool parse(std::vector<const char *> args) {
-    args.insert(args.begin(), "ld");
-    return mach_o::parse(args, _ctx);
-  }
-
-  MachOLinkingContext _ctx;
-};
-}
-
-TEST_F(DarwinLdParserTest, Basic) {
-  EXPECT_TRUE(parse({"foo.o", "bar.o", "-arch", "i386"}));
-  EXPECT_FALSE(_ctx.allowRemainingUndefines());
-  EXPECT_FALSE(_ctx.deadStrip());
-  EXPECT_EQ(2, inputFileCount());
-  EXPECT_EQ("foo.o", inputFile(0));
-  EXPECT_EQ("bar.o", inputFile(1));
-}
-
-TEST_F(DarwinLdParserTest, Output) {
-  EXPECT_TRUE(parse({"-o", "my.out", "foo.o", "-arch", "i386"}));
-  EXPECT_EQ("my.out", _ctx.outputPath());
-}
-
-TEST_F(DarwinLdParserTest, Dylib) {
-  EXPECT_TRUE(parse({"-dylib", "foo.o", "-arch", "i386"}));
-  EXPECT_EQ(llvm::MachO::MH_DYLIB, _ctx.outputMachOType());
-}
-
-TEST_F(DarwinLdParserTest, Relocatable) {
-  EXPECT_TRUE(parse({"-r", "foo.o", "-arch", "i386"}));
-  EXPECT_EQ(llvm::MachO::MH_OBJECT, _ctx.outputMachOType());
-}
-
-TEST_F(DarwinLdParserTest, Bundle) {
-  EXPECT_TRUE(parse({"-bundle", "foo.o", "-arch", "i386"}));
-  EXPECT_EQ(llvm::MachO::MH_BUNDLE, _ctx.outputMachOType());
-}
-
-TEST_F(DarwinLdParserTest, Preload) {
-  EXPECT_TRUE(parse({"-preload", "foo.o", "-arch", "i386"}));
-  EXPECT_EQ(llvm::MachO::MH_PRELOAD, _ctx.outputMachOType());
-}
-
-TEST_F(DarwinLdParserTest, Static) {
-  EXPECT_TRUE(parse({"-static", "foo.o", "-arch", "i386"}));
-  EXPECT_EQ(llvm::MachO::MH_EXECUTE, _ctx.outputMachOType());
-}
-
-TEST_F(DarwinLdParserTest, Entry) {
-  EXPECT_TRUE(parse({"-e", "entryFunc", "foo.o", "-arch", "i386"}));
-  EXPECT_EQ("entryFunc", _ctx.entrySymbolName());
-}
-
-TEST_F(DarwinLdParserTest, DeadStrip) {
-  EXPECT_TRUE(parse({"-arch", "x86_64", "-dead_strip", "foo.o"}));
-  EXPECT_TRUE(_ctx.deadStrip());
-}
-
-TEST_F(DarwinLdParserTest, DeadStripRootsExe) {
-  EXPECT_TRUE(parse({"-arch", "x86_64", "-dead_strip", "foo.o"}));
-  EXPECT_FALSE(_ctx.globalsAreDeadStripRoots());
-}
-
-TEST_F(DarwinLdParserTest, DeadStripRootsDylib) {
-  EXPECT_TRUE(parse({"-arch", "x86_64", "-dylib", "-dead_strip", "foo.o"}));
-  EXPECT_FALSE(_ctx.globalsAreDeadStripRoots());
-}
-
-TEST_F(DarwinLdParserTest, DeadStripRootsRelocatable) {
-  EXPECT_TRUE(parse({"-arch", "x86_64", "-r", "-dead_strip", "foo.o"}));
-  EXPECT_FALSE(_ctx.globalsAreDeadStripRoots());
-}
-
-TEST_F(DarwinLdParserTest, DeadStripRootsExportDynamicExe) {
-  EXPECT_TRUE(
-      parse({"-arch", "x86_64", "-dead_strip", "-export_dynamic", "foo.o"}));
-  EXPECT_TRUE(_ctx.globalsAreDeadStripRoots());
-}
-
-TEST_F(DarwinLdParserTest, DeadStripRootsExportDynamicDylib) {
-  EXPECT_TRUE(parse({"-arch", "x86_64", "-dylib", "-dead_strip",
-                     "-export_dynamic", "foo.o"}));
-  EXPECT_TRUE(_ctx.globalsAreDeadStripRoots());
-}
-
-TEST_F(DarwinLdParserTest, DeadStripRootsExportDynamicRelocatable) {
-  EXPECT_TRUE(parse(
-      {"-arch", "x86_64", "-r", "-dead_strip", "-export_dynamic", "foo.o"}));
-  EXPECT_FALSE(_ctx.globalsAreDeadStripRoots());
-}
-
-TEST_F(DarwinLdParserTest, Arch) {
-  EXPECT_TRUE(parse({"-arch", "x86_64", "foo.o"}));
-  EXPECT_EQ(MachOLinkingContext::arch_x86_64, _ctx.arch());
-  EXPECT_EQ((uint32_t)llvm::MachO::CPU_TYPE_X86_64, _ctx.getCPUType());
-  EXPECT_EQ(llvm::MachO::CPU_SUBTYPE_X86_64_ALL, _ctx.getCPUSubType());
-}
-
-TEST_F(DarwinLdParserTest, Arch_x86) {
-  EXPECT_TRUE(parse({"-arch", "i386", "foo.o"}));
-  EXPECT_EQ(MachOLinkingContext::arch_x86, _ctx.arch());
-  EXPECT_EQ((uint32_t)llvm::MachO::CPU_TYPE_I386, _ctx.getCPUType());
-  EXPECT_EQ(llvm::MachO::CPU_SUBTYPE_X86_ALL, _ctx.getCPUSubType());
-}
-
-TEST_F(DarwinLdParserTest, Arch_armv6) {
-  EXPECT_TRUE(parse({"-arch", "armv6", "foo.o"}));
-  EXPECT_EQ(MachOLinkingContext::arch_armv6, _ctx.arch());
-  EXPECT_EQ((uint32_t)llvm::MachO::CPU_TYPE_ARM, _ctx.getCPUType());
-  EXPECT_EQ(llvm::MachO::CPU_SUBTYPE_ARM_V6, _ctx.getCPUSubType());
-}
-
-TEST_F(DarwinLdParserTest, Arch_armv7) {
-  EXPECT_TRUE(parse({"-arch", "armv7", "foo.o"}));
-  EXPECT_EQ(MachOLinkingContext::arch_armv7, _ctx.arch());
-  EXPECT_EQ((uint32_t)llvm::MachO::CPU_TYPE_ARM, _ctx.getCPUType());
-  EXPECT_EQ(llvm::MachO::CPU_SUBTYPE_ARM_V7, _ctx.getCPUSubType());
-}
-
-TEST_F(DarwinLdParserTest, Arch_armv7s) {
-  EXPECT_TRUE(parse({"-arch", "armv7s", "foo.o"}));
-  EXPECT_EQ(MachOLinkingContext::arch_armv7s, _ctx.arch());
-  EXPECT_EQ((uint32_t)llvm::MachO::CPU_TYPE_ARM, _ctx.getCPUType());
-  EXPECT_EQ(llvm::MachO::CPU_SUBTYPE_ARM_V7S, _ctx.getCPUSubType());
-}
-
-TEST_F(DarwinLdParserTest, MinMacOSX10_7) {
-  EXPECT_TRUE(
-      parse({"-macosx_version_min", "10.7", "foo.o", "-arch", "x86_64"}));
-  EXPECT_EQ(MachOLinkingContext::OS::macOSX, _ctx.os());
-  EXPECT_TRUE(_ctx.minOS("10.7", ""));
-  EXPECT_FALSE(_ctx.minOS("10.8", ""));
-}
-
-TEST_F(DarwinLdParserTest, MinMacOSX10_8) {
-  EXPECT_TRUE(
-      parse({"-macosx_version_min", "10.8.3", "foo.o", "-arch", "x86_64"}));
-  EXPECT_EQ(MachOLinkingContext::OS::macOSX, _ctx.os());
-  EXPECT_TRUE(_ctx.minOS("10.7", ""));
-  EXPECT_TRUE(_ctx.minOS("10.8", ""));
-}
-
-TEST_F(DarwinLdParserTest, iOS5) {
-  EXPECT_TRUE(parse({"-ios_version_min", "5.0", "foo.o", "-arch", "armv7"}));
-  EXPECT_EQ(MachOLinkingContext::OS::iOS, _ctx.os());
-  EXPECT_TRUE(_ctx.minOS("", "5.0"));
-  EXPECT_FALSE(_ctx.minOS("", "6.0"));
-}
-
-TEST_F(DarwinLdParserTest, iOS6) {
-  EXPECT_TRUE(parse({"-ios_version_min", "6.0", "foo.o", "-arch", "armv7"}));
-  EXPECT_EQ(MachOLinkingContext::OS::iOS, _ctx.os());
-  EXPECT_TRUE(_ctx.minOS("", "5.0"));
-  EXPECT_TRUE(_ctx.minOS("", "6.0"));
-}
-
-TEST_F(DarwinLdParserTest, iOS_Simulator5) {
-  EXPECT_TRUE(
-      parse({"-ios_simulator_version_min", "5.0", "a.o", "-arch", "i386"}));
-  EXPECT_EQ(MachOLinkingContext::OS::iOS_simulator, _ctx.os());
-  EXPECT_TRUE(_ctx.minOS("", "5.0"));
-  EXPECT_FALSE(_ctx.minOS("", "6.0"));
-}
-
-TEST_F(DarwinLdParserTest, iOS_Simulator6) {
-  EXPECT_TRUE(
-      parse({"-ios_simulator_version_min", "6.0", "a.o", "-arch", "i386"}));
-  EXPECT_EQ(MachOLinkingContext::OS::iOS_simulator, _ctx.os());
-  EXPECT_TRUE(_ctx.minOS("", "5.0"));
-  EXPECT_TRUE(_ctx.minOS("", "6.0"));
-}
-
-TEST_F(DarwinLdParserTest, compatibilityVersion) {
-  EXPECT_TRUE(parse(
-      {"-dylib", "-compatibility_version", "1.2.3", "a.o", "-arch", "i386"}));
-  EXPECT_EQ(_ctx.compatibilityVersion(), 0x10203U);
-}
-
-TEST_F(DarwinLdParserTest, compatibilityVersionInvalidType) {
-  EXPECT_FALSE(parse(
-      {"-bundle", "-compatibility_version", "1.2.3", "a.o", "-arch", "i386"}));
-}
-
-TEST_F(DarwinLdParserTest, compatibilityVersionInvalidValue) {
-  EXPECT_FALSE(parse(
-      {"-bundle", "-compatibility_version", "1,2,3", "a.o", "-arch", "i386"}));
-}
-
-TEST_F(DarwinLdParserTest, currentVersion) {
-  EXPECT_TRUE(
-      parse({"-dylib", "-current_version", "1.2.3", "a.o", "-arch", "i386"}));
-  EXPECT_EQ(_ctx.currentVersion(), 0x10203U);
-}
-
-TEST_F(DarwinLdParserTest, currentVersionInvalidType) {
-  EXPECT_FALSE(
-      parse({"-bundle", "-current_version", "1.2.3", "a.o", "-arch", "i386"}));
-}
-
-TEST_F(DarwinLdParserTest, currentVersionInvalidValue) {
-  EXPECT_FALSE(
-      parse({"-bundle", "-current_version", "1,2,3", "a.o", "-arch", "i386"}));
-}
-
-TEST_F(DarwinLdParserTest, bundleLoader) {
-  EXPECT_TRUE(
-      parse({"-bundle", "-bundle_loader", "/bin/ls", "a.o", "-arch", "i386"}));
-  EXPECT_EQ(_ctx.bundleLoader(), "/bin/ls");
-}
-
-TEST_F(DarwinLdParserTest, bundleLoaderInvalidType) {
-  EXPECT_FALSE(parse({"-bundle_loader", "/bin/ls", "a.o", "-arch", "i386"}));
-}
-
-TEST_F(DarwinLdParserTest, deadStrippableDylib) {
-  EXPECT_TRUE(
-      parse({"-dylib", "-mark_dead_strippable_dylib", "a.o", "-arch", "i386"}));
-  EXPECT_EQ(true, _ctx.deadStrippableDylib());
-}
-
-TEST_F(DarwinLdParserTest, deadStrippableDylibInvalidType) {
-  EXPECT_FALSE(parse({"-mark_dead_strippable_dylib", "a.o", "-arch", "i386"}));
-}
diff --git a/gnu/llvm/lld/unittests/MachOTests/CMakeLists.txt b/gnu/llvm/lld/unittests/MachOTests/CMakeLists.txt
deleted file mode 100644 (file)
index b2b22fb..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-
-add_lld_unittest(lldMachOTests
-  MachONormalizedFileBinaryReaderTests.cpp
-  MachONormalizedFileBinaryWriterTests.cpp
-  MachONormalizedFileToAtomsTests.cpp
-  MachONormalizedFileYAMLTests.cpp
-  )
-
-target_link_libraries(lldMachOTests
-  PRIVATE
-  lldDriver
-  lldMachO
-  lldYAML
-  )
diff --git a/gnu/llvm/lld/unittests/MachOTests/MachONormalizedFileBinaryReaderTests.cpp b/gnu/llvm/lld/unittests/MachOTests/MachONormalizedFileBinaryReaderTests.cpp
deleted file mode 100644 (file)
index fbf18a8..0000000
+++ /dev/null
@@ -1,753 +0,0 @@
-//===- lld/unittest/MachOTests/MachONormalizedFileBinaryReaderTests.cpp ---===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "../../lib/ReaderWriter/MachO/MachONormalizedFile.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/YAMLTraits.h"
-#include "gtest/gtest.h"
-#include <cstdint>
-#include <memory>
-
-using llvm::SmallString;
-using llvm::StringRef;
-using llvm::MemoryBuffer;
-using llvm::Twine;
-
-using namespace lld::mach_o::normalized;
-using namespace llvm::MachO;
-
-static std::unique_ptr<NormalizedFile>
-fromBinary(const uint8_t bytes[], unsigned length, StringRef archStr) {
-  StringRef sr((const char*)bytes, length);
-  std::unique_ptr<MemoryBuffer> mb(MemoryBuffer::getMemBuffer(sr, "", false));
-  llvm::Expected<std::unique_ptr<NormalizedFile>> r =
-      lld::mach_o::normalized::readBinary(
-          mb, lld::MachOLinkingContext::archFromName(archStr));
-  EXPECT_FALSE(!r);
-  return std::move(*r);
-}
-
-// The Mach-O object reader uses functions such as read32 or read64
-// which don't allow unaligned access. Our in-memory object file
-// needs to be aligned to a larger boundary than uint8_t's.
-#if _MSC_VER
-#define FILEBYTES __declspec(align(64)) const uint8_t fileBytes[]
-#else
-#define FILEBYTES const uint8_t fileBytes[] __attribute__((aligned(64)))
-#endif
-
-TEST(BinaryReaderTest, empty_obj_x86_64) {
-  FILEBYTES = {
-      0xcf, 0xfa, 0xed, 0xfe, 0x07, 0x00, 0x00, 0x01,
-      0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-      0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00,
-      0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x19, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-      0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x5f, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x5f, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-  std::unique_ptr<NormalizedFile> f =
-      fromBinary(fileBytes, sizeof(fileBytes), "x86_64");
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64);
-  EXPECT_EQ((int)(f->fileType), MH_OBJECT);
-  EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_TRUE(f->localSymbols.empty());
-  EXPECT_TRUE(f->globalSymbols.empty());
-  EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(BinaryReaderTest, empty_obj_x86) {
-  FILEBYTES = {
-      0xce, 0xfa, 0xed, 0xfe, 0x07, 0x00, 0x00, 0x00,
-      0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-      0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
-      0x00, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-      0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-      0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x74, 0x65,
-      0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x54, 0x45,
-      0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-  std::unique_ptr<NormalizedFile> f =
-      fromBinary(fileBytes, sizeof(fileBytes), "i386");
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86);
-  EXPECT_EQ((int)(f->fileType), MH_OBJECT);
-  EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_TRUE(f->localSymbols.empty());
-  EXPECT_TRUE(f->globalSymbols.empty());
-  EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(BinaryReaderTest, empty_obj_ppc) {
-  FILEBYTES = {
-      0xfe, 0xed, 0xfa, 0xce, 0x00, 0x00, 0x00, 0x12,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-      0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7c,
-      0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01,
-      0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
-      0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01,
-      0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x74, 0x65,
-      0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x54, 0x45,
-      0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-  std::unique_ptr<NormalizedFile> f =
-      fromBinary(fileBytes, sizeof(fileBytes), "ppc");
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_ppc);
-  EXPECT_EQ((int)(f->fileType), MH_OBJECT);
-  EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_TRUE(f->localSymbols.empty());
-  EXPECT_TRUE(f->globalSymbols.empty());
-  EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(BinaryReaderTest, empty_obj_armv7) {
-  FILEBYTES = {
-      0xce, 0xfa, 0xed, 0xfe, 0x0c, 0x00, 0x00, 0x00,
-      0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-      0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
-      0x00, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-      0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-      0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x74, 0x65,
-      0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x54, 0x45,
-      0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-  std::unique_ptr<NormalizedFile> f =
-      fromBinary(fileBytes, sizeof(fileBytes), "armv7");
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv7);
-  EXPECT_EQ((int)(f->fileType), MH_OBJECT);
-  EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_TRUE(f->localSymbols.empty());
-  EXPECT_TRUE(f->globalSymbols.empty());
-  EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(BinaryReaderTest, empty_obj_x86_64_arm7) {
-  FILEBYTES = {
-#include "empty_obj_x86_armv7.txt"
-  };
-  std::unique_ptr<NormalizedFile> f =
-      fromBinary(fileBytes, sizeof(fileBytes), "x86_64");
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64);
-  EXPECT_EQ((int)(f->fileType), MH_OBJECT);
-  EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_TRUE(f->localSymbols.empty());
-  EXPECT_TRUE(f->globalSymbols.empty());
-  EXPECT_TRUE(f->undefinedSymbols.empty());
-
-  std::unique_ptr<NormalizedFile> f2 =
-      fromBinary(fileBytes, sizeof(fileBytes), "armv7");
-  EXPECT_EQ(f2->arch, lld::MachOLinkingContext::arch_armv7);
-  EXPECT_EQ((int)(f2->fileType), MH_OBJECT);
-  EXPECT_EQ((int)(f2->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_TRUE(f2->localSymbols.empty());
-  EXPECT_TRUE(f2->globalSymbols.empty());
-  EXPECT_TRUE(f2->undefinedSymbols.empty());
-}
-
-TEST(BinaryReaderTest, hello_obj_x86_64) {
-  FILEBYTES = {
-    0xCF, 0xFA, 0xED, 0xFE, 0x07, 0x00, 0x00, 0x01,
-    0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0x03, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00,
-    0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x19, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-    0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x5F, 0x5F, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x5F, 0x5F, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x70, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-    0xA4, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-    0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x5F, 0x5F, 0x63, 0x73, 0x74, 0x72, 0x69, 0x6E,
-    0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x5F, 0x5F, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x9D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
-    0xB4, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-    0xE4, 0x01, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
-    0x0B, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x55, 0x48, 0x89, 0xE5, 0x48, 0x83, 0xEC, 0x10,
-    0x48, 0x8D, 0x3D, 0x00, 0x00, 0x00, 0x00, 0xC7,
-    0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x00,
-    0xE8, 0x00, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00,
-    0x00, 0x00, 0x89, 0x45, 0xF8, 0x89, 0xC8, 0x48,
-    0x83, 0xC4, 0x10, 0x5D, 0xC3, 0x68, 0x65, 0x6C,
-    0x6C, 0x6F, 0x0A, 0x00, 0x19, 0x00, 0x00, 0x00,
-    0x02, 0x00, 0x00, 0x2D, 0x0B, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x1D, 0x0F, 0x00, 0x00, 0x00,
-    0x0E, 0x02, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x6D, 0x61,
-    0x69, 0x6E, 0x00, 0x5F, 0x70, 0x72, 0x69, 0x6E,
-    0x74, 0x66, 0x00, 0x4C, 0x5F, 0x2E, 0x73, 0x74,
-    0x72, 0x00, 0x00, 0x00 };
-  std::unique_ptr<NormalizedFile> f =
-      fromBinary(fileBytes, sizeof(fileBytes), "x86_64");
-
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64);
-  EXPECT_EQ((int)(f->fileType), MH_OBJECT);
-  EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_EQ(f->sections.size(), 2UL);
-  const Section& text = f->sections[0];
-  EXPECT_TRUE(text.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(text.sectionName.equals("__text"));
-  EXPECT_EQ(text.type, S_REGULAR);
-  EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
-                                      | S_ATTR_SOME_INSTRUCTIONS));
-  EXPECT_EQ((uint16_t)text.alignment, 16U);
-  EXPECT_EQ(text.address, Hex64(0x0));
-  EXPECT_EQ(text.content.size(), 45UL);
-  EXPECT_EQ((int)(text.content[0]), 0x55);
-  EXPECT_EQ((int)(text.content[1]), 0x48);
-  EXPECT_TRUE(text.indirectSymbols.empty());
-  EXPECT_EQ(text.relocations.size(), 2UL);
-  const Relocation& call = text.relocations[0];
-  EXPECT_EQ(call.offset, Hex32(0x19));
-  EXPECT_EQ(call.type, X86_64_RELOC_BRANCH);
-  EXPECT_EQ(call.length, 2);
-  EXPECT_EQ(call.isExtern, true);
-  EXPECT_EQ(call.symbol, 2U);
-  const Relocation& str = text.relocations[1];
-  EXPECT_EQ(str.offset, Hex32(0xB));
-  EXPECT_EQ(str.type, X86_64_RELOC_SIGNED);
-  EXPECT_EQ(str.length, 2);
-  EXPECT_EQ(str.isExtern, true);
-  EXPECT_EQ(str.symbol, 0U);
-
-  const Section& cstring = f->sections[1];
-  EXPECT_TRUE(cstring.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(cstring.sectionName.equals("__cstring"));
-  EXPECT_EQ(cstring.type, S_CSTRING_LITERALS);
-  EXPECT_EQ(cstring.attributes, SectionAttr(0));
-  EXPECT_EQ((uint16_t)cstring.alignment, 1U);
-  EXPECT_EQ(cstring.address, Hex64(0x02D));
-  EXPECT_EQ(cstring.content.size(), 7UL);
-  EXPECT_EQ((int)(cstring.content[0]), 0x68);
-  EXPECT_EQ((int)(cstring.content[1]), 0x65);
-  EXPECT_EQ((int)(cstring.content[2]), 0x6c);
-  EXPECT_TRUE(cstring.indirectSymbols.empty());
-  EXPECT_TRUE(cstring.relocations.empty());
-
-  EXPECT_EQ(f->localSymbols.size(), 1UL);
-  const Symbol& strLabel = f->localSymbols[0];
-  EXPECT_EQ(strLabel.type, N_SECT);
-  EXPECT_EQ(strLabel.sect, 2);
-  EXPECT_EQ(strLabel.value, Hex64(0x2D));
-  EXPECT_EQ(f->globalSymbols.size(), 1UL);
-  const Symbol& mainLabel = f->globalSymbols[0];
-  EXPECT_TRUE(mainLabel.name.equals("_main"));
-  EXPECT_EQ(mainLabel.type, N_SECT);
-  EXPECT_EQ(mainLabel.sect, 1);
-  EXPECT_EQ(mainLabel.scope, SymbolScope(N_EXT));
-  EXPECT_EQ(mainLabel.value, Hex64(0x0));
-  EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
-  const Symbol& printfLabel = f->undefinedSymbols[0];
-  EXPECT_TRUE(printfLabel.name.equals("_printf"));
-  EXPECT_EQ(printfLabel.type, N_UNDF);
-  EXPECT_EQ(printfLabel.scope, SymbolScope(N_EXT));
-}
-
-TEST(BinaryReaderTest, hello_obj_x86) {
-  FILEBYTES = {
-    0xCE, 0xFA, 0xED, 0xFE, 0x07, 0x00, 0x00, 0x00,
-    0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0x03, 0x00, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
-    0x00, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x37, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00,
-    0x37, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-    0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x5F, 0x5F, 0x74, 0x65,
-    0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x5F, 0x5F, 0x54, 0x45,
-    0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x30, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00,
-    0x04, 0x00, 0x00, 0x00, 0x7C, 0x01, 0x00, 0x00,
-    0x03, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x80,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x5F, 0x5F, 0x63, 0x73, 0x74, 0x72, 0x69, 0x6E,
-    0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x5F, 0x5F, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x30, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-    0x74, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-    0x18, 0x00, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00,
-    0x02, 0x00, 0x00, 0x00, 0xAC, 0x01, 0x00, 0x00,
-    0x10, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
-    0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xE5, 0x83,
-    0xEC, 0x18, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x58,
-    0x8D, 0x80, 0x25, 0x00, 0x00, 0x00, 0xC7, 0x45,
-    0xFC, 0x00, 0x00, 0x00, 0x00, 0x89, 0x04, 0x24,
-    0xE8, 0xDF, 0xFF, 0xFF, 0xFF, 0xB9, 0x00, 0x00,
-    0x00, 0x00, 0x89, 0x45, 0xF8, 0x89, 0xC8, 0x83,
-    0xC4, 0x18, 0x5D, 0xC3, 0x68, 0x65, 0x6C, 0x6C,
-    0x6F, 0x0A, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x0D, 0x0E, 0x00, 0x00, 0xA4,
-    0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1,
-    0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x6D, 0x61,
-    0x69, 0x6E, 0x00, 0x5F, 0x70, 0x72, 0x69, 0x6E,
-    0x74, 0x66, 0x00, 0x00
-  };
-  std::unique_ptr<NormalizedFile> f =
-      fromBinary(fileBytes, sizeof(fileBytes), "i386");
-
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86);
-  EXPECT_EQ((int)(f->fileType), MH_OBJECT);
-  EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_EQ(f->sections.size(), 2UL);
-  const Section& text = f->sections[0];
-  EXPECT_TRUE(text.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(text.sectionName.equals("__text"));
-  EXPECT_EQ(text.type, S_REGULAR);
-  EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
-                                      | S_ATTR_SOME_INSTRUCTIONS));
-  EXPECT_EQ((uint16_t)text.alignment, 16U);
-  EXPECT_EQ(text.address, Hex64(0x0));
-  EXPECT_EQ(text.content.size(), 48UL);
-  EXPECT_EQ((int)(text.content[0]), 0x55);
-  EXPECT_EQ((int)(text.content[1]), 0x89);
-  EXPECT_TRUE(text.indirectSymbols.empty());
-  EXPECT_EQ(text.relocations.size(), 3UL);
-  const Relocation& call = text.relocations[0];
-  EXPECT_EQ(call.offset, Hex32(0x1D));
-  EXPECT_EQ(call.scattered, false);
-  EXPECT_EQ(call.type, GENERIC_RELOC_VANILLA);
-  EXPECT_EQ(call.pcRel, true);
-  EXPECT_EQ(call.length, 2);
-  EXPECT_EQ(call.isExtern, true);
-  EXPECT_EQ(call.symbol, 1U);
-  const Relocation& sectDiff = text.relocations[1];
-  EXPECT_EQ(sectDiff.offset, Hex32(0xE));
-  EXPECT_EQ(sectDiff.scattered, true);
-  EXPECT_EQ(sectDiff.type, GENERIC_RELOC_LOCAL_SECTDIFF);
-  EXPECT_EQ(sectDiff.pcRel, false);
-  EXPECT_EQ(sectDiff.length, 2);
-  EXPECT_EQ(sectDiff.value, 0x30U);
-  const Relocation& pair = text.relocations[2];
-  EXPECT_EQ(pair.offset, Hex32(0x0));
-  EXPECT_EQ(pair.scattered, true);
-  EXPECT_EQ(pair.type, GENERIC_RELOC_PAIR);
-  EXPECT_EQ(pair.pcRel, false);
-  EXPECT_EQ(pair.length, 2);
-  EXPECT_EQ(pair.value, 0x0BU);
-
-  const Section& cstring = f->sections[1];
-  EXPECT_TRUE(cstring.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(cstring.sectionName.equals("__cstring"));
-  EXPECT_EQ(cstring.type, S_CSTRING_LITERALS);
-  EXPECT_EQ(cstring.attributes, SectionAttr(0));
-  EXPECT_EQ((uint16_t)cstring.alignment, 1U);
-  EXPECT_EQ(cstring.address, Hex64(0x030));
-  EXPECT_EQ(cstring.content.size(), 7UL);
-  EXPECT_EQ((int)(cstring.content[0]), 0x68);
-  EXPECT_EQ((int)(cstring.content[1]), 0x65);
-  EXPECT_EQ((int)(cstring.content[2]), 0x6c);
-  EXPECT_TRUE(cstring.indirectSymbols.empty());
-  EXPECT_TRUE(cstring.relocations.empty());
-
-  EXPECT_EQ(f->localSymbols.size(), 0UL);
-  EXPECT_EQ(f->globalSymbols.size(), 1UL);
-  const Symbol& mainLabel = f->globalSymbols[0];
-  EXPECT_TRUE(mainLabel.name.equals("_main"));
-  EXPECT_EQ(mainLabel.type, N_SECT);
-  EXPECT_EQ(mainLabel.sect, 1);
-  EXPECT_EQ(mainLabel.scope, SymbolScope(N_EXT));
-  EXPECT_EQ(mainLabel.value, Hex64(0x0));
-  EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
-  const Symbol& printfLabel = f->undefinedSymbols[0];
-  EXPECT_TRUE(printfLabel.name.equals("_printf"));
-  EXPECT_EQ(printfLabel.type, N_UNDF);
-  EXPECT_EQ(printfLabel.scope, SymbolScope(N_EXT));
-}
-
-TEST(BinaryReaderTest, hello_obj_armv7) {
-  FILEBYTES = {
-    0xCE, 0xFA, 0xED, 0xFE, 0x0C, 0x00, 0x00, 0x00,
-    0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0x03, 0x00, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
-    0x00, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x31, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00,
-    0x31, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-    0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x5F, 0x5F, 0x74, 0x65,
-    0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x5F, 0x5F, 0x54, 0x45,
-    0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x2A, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00,
-    0x02, 0x00, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00,
-    0x05, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x80,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x5F, 0x5F, 0x63, 0x73, 0x74, 0x72, 0x69, 0x6E,
-    0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x5F, 0x5F, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x2A, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-    0x6E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-    0x18, 0x00, 0x00, 0x00, 0xA0, 0x01, 0x00, 0x00,
-    0x02, 0x00, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00,
-    0x10, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
-    0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x80, 0xB5, 0x6F, 0x46,
-    0x82, 0xB0, 0x40, 0xF2, 0x18, 0x00, 0xC0, 0xF2,
-    0x00, 0x00, 0x78, 0x44, 0x00, 0x21, 0xC0, 0xF2,
-    0x00, 0x01, 0x01, 0x91, 0xFF, 0xF7, 0xF2, 0xFF,
-    0x00, 0x21, 0xC0, 0xF2, 0x00, 0x01, 0x00, 0x90,
-    0x08, 0x46, 0x02, 0xB0, 0x80, 0xBD, 0x68, 0x65,
-    0x6C, 0x6C, 0x6F, 0x0A, 0x00, 0x00, 0x00, 0x00,
-    0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x6D,
-    0x0A, 0x00, 0x00, 0xB9, 0x2A, 0x00, 0x00, 0x00,
-    0x18, 0x00, 0x00, 0xB1, 0x0E, 0x00, 0x00, 0x00,
-    0x06, 0x00, 0x00, 0xA9, 0x2A, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0xA1, 0x0E, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x00, 0x0F, 0x01, 0x08, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x5F, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x5F,
-    0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x00
-  };
-  std::unique_ptr<NormalizedFile> f =
-      fromBinary(fileBytes, sizeof(fileBytes), "armv7");
-
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv7);
-  EXPECT_EQ((int)(f->fileType), MH_OBJECT);
-  EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_EQ(f->sections.size(), 2UL);
-  const Section& text = f->sections[0];
-  EXPECT_TRUE(text.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(text.sectionName.equals("__text"));
-  EXPECT_EQ(text.type, S_REGULAR);
-  EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
-                                      | S_ATTR_SOME_INSTRUCTIONS));
-  EXPECT_EQ((uint16_t)text.alignment, 4U);
-  EXPECT_EQ(text.address, Hex64(0x0));
-  EXPECT_EQ(text.content.size(), 42UL);
-  EXPECT_EQ((int)(text.content[0]), 0x80);
-  EXPECT_EQ((int)(text.content[1]), 0xB5);
-  EXPECT_TRUE(text.indirectSymbols.empty());
-  EXPECT_EQ(text.relocations.size(), 5UL);
-  const Relocation& call = text.relocations[0];
-  EXPECT_EQ(call.offset, Hex32(0x18));
-  EXPECT_EQ(call.scattered, false);
-  EXPECT_EQ(call.type, ARM_THUMB_RELOC_BR22);
-  EXPECT_EQ(call.length, 2);
-  EXPECT_EQ(call.isExtern, true);
-  EXPECT_EQ(call.symbol, 1U);
-  const Relocation& movt = text.relocations[1];
-  EXPECT_EQ(movt.offset, Hex32(0xA));
-  EXPECT_EQ(movt.scattered, true);
-  EXPECT_EQ(movt.type, ARM_RELOC_HALF_SECTDIFF);
-  EXPECT_EQ(movt.length, 3);
-  EXPECT_EQ(movt.value, Hex32(0x2A));
-  const Relocation& movtPair = text.relocations[2];
-  EXPECT_EQ(movtPair.offset, Hex32(0x18));
-  EXPECT_EQ(movtPair.scattered, true);
-  EXPECT_EQ(movtPair.type, ARM_RELOC_PAIR);
-  EXPECT_EQ(movtPair.length, 3);
-  EXPECT_EQ(movtPair.value, Hex32(0xE));
-  const Relocation& movw = text.relocations[3];
-  EXPECT_EQ(movw.offset, Hex32(0x6));
-  EXPECT_EQ(movw.scattered, true);
-  EXPECT_EQ(movw.type, ARM_RELOC_HALF_SECTDIFF);
-  EXPECT_EQ(movw.length, 2);
-  EXPECT_EQ(movw.value, Hex32(0x2A));
-  const Relocation& movwPair = text.relocations[4];
-  EXPECT_EQ(movwPair.offset, Hex32(0x0));
-  EXPECT_EQ(movwPair.scattered, true);
-  EXPECT_EQ(movwPair.type, ARM_RELOC_PAIR);
-  EXPECT_EQ(movwPair.length, 2);
-  EXPECT_EQ(movwPair.value, Hex32(0xE));
-
-  const Section& cstring = f->sections[1];
-  EXPECT_TRUE(cstring.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(cstring.sectionName.equals("__cstring"));
-  EXPECT_EQ(cstring.type, S_CSTRING_LITERALS);
-  EXPECT_EQ(cstring.attributes, SectionAttr(0));
-  EXPECT_EQ((uint16_t)cstring.alignment, 1U);
-  EXPECT_EQ(cstring.address, Hex64(0x02A));
-  EXPECT_EQ(cstring.content.size(), 7UL);
-  EXPECT_EQ((int)(cstring.content[0]), 0x68);
-  EXPECT_EQ((int)(cstring.content[1]), 0x65);
-  EXPECT_EQ((int)(cstring.content[2]), 0x6c);
-  EXPECT_TRUE(cstring.indirectSymbols.empty());
-  EXPECT_TRUE(cstring.relocations.empty());
-
-  EXPECT_EQ(f->localSymbols.size(), 0UL);
-  EXPECT_EQ(f->globalSymbols.size(), 1UL);
-  const Symbol& mainLabel = f->globalSymbols[0];
-  EXPECT_TRUE(mainLabel.name.equals("_main"));
-  EXPECT_EQ(mainLabel.type, N_SECT);
-  EXPECT_EQ(mainLabel.sect, 1);
-  EXPECT_EQ(mainLabel.scope, SymbolScope(N_EXT));
-  EXPECT_EQ(mainLabel.value, Hex64(0x0));
-  EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
-  const Symbol& printfLabel = f->undefinedSymbols[0];
-  EXPECT_TRUE(printfLabel.name.equals("_printf"));
-  EXPECT_EQ(printfLabel.type, N_UNDF);
-  EXPECT_EQ(printfLabel.scope, SymbolScope(N_EXT));
-}
-
-TEST(BinaryReaderTest, hello_obj_ppc) {
-  FILEBYTES = {
-    0xFE, 0xED, 0xFA, 0xCE, 0x00, 0x00, 0x00, 0x12,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-    0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x28,
-    0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01,
-    0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x01, 0x44,
-    0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x07,
-    0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02,
-    0x00, 0x00, 0x00, 0x00, 0x5F, 0x5F, 0x74, 0x65,
-    0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x5F, 0x5F, 0x54, 0x45,
-    0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, 0x44,
-    0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x90,
-    0x00, 0x00, 0x00, 0x05, 0x80, 0x00, 0x04, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x5F, 0x5F, 0x63, 0x73, 0x74, 0x72, 0x69, 0x6E,
-    0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x5F, 0x5F, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x07,
-    0x00, 0x00, 0x01, 0x88, 0x00, 0x00, 0x00, 0x02,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
-    0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x01, 0xB8,
-    0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0xD0,
-    0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0B,
-    0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
-    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x7C, 0x08, 0x02, 0xA6,
-    0xBF, 0xC1, 0xFF, 0xF8, 0x90, 0x01, 0x00, 0x08,
-    0x94, 0x21, 0xFF, 0xB0, 0x7C, 0x3E, 0x0B, 0x78,
-    0x42, 0x9F, 0x00, 0x05, 0x7F, 0xE8, 0x02, 0xA6,
-    0x3C, 0x5F, 0x00, 0x00, 0x38, 0x62, 0x00, 0x2C,
-    0x4B, 0xFF, 0xFF, 0xDD, 0x38, 0x00, 0x00, 0x00,
-    0x7C, 0x03, 0x03, 0x78, 0x80, 0x21, 0x00, 0x00,
-    0x80, 0x01, 0x00, 0x08, 0x7C, 0x08, 0x03, 0xA6,
-    0xBB, 0xC1, 0xFF, 0xF8, 0x4E, 0x80, 0x00, 0x20,
-    0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x01, 0xD3,
-    0xAB, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x44,
-    0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
-    0xAC, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x44,
-    0xA1, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x18,
-    0x00, 0x00, 0x00, 0x01, 0x0F, 0x01, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
-    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x5F, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x5F,
-    0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x00
-  };
-  std::unique_ptr<NormalizedFile> f =
-      fromBinary(fileBytes, sizeof(fileBytes), "ppc");
-
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_ppc);
-  EXPECT_EQ((int)(f->fileType), MH_OBJECT);
-  EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_EQ(f->sections.size(), 2UL);
-  const Section& text = f->sections[0];
-  EXPECT_TRUE(text.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(text.sectionName.equals("__text"));
-  EXPECT_EQ(text.type, S_REGULAR);
-  EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
-                                      | S_ATTR_SOME_INSTRUCTIONS));
-  EXPECT_EQ((uint16_t)text.alignment, 4U);
-  EXPECT_EQ(text.address, Hex64(0x0));
-  EXPECT_EQ(text.content.size(), 68UL);
-  EXPECT_EQ((int)(text.content[0]), 0x7C);
-  EXPECT_EQ((int)(text.content[1]), 0x08);
-  EXPECT_TRUE(text.indirectSymbols.empty());
-  EXPECT_EQ(text.relocations.size(), 5UL);
-  const Relocation& bl = text.relocations[0];
-  EXPECT_EQ(bl.offset, Hex32(0x24));
-  EXPECT_EQ(bl.type, PPC_RELOC_BR24);
-  EXPECT_EQ(bl.length, 2);
-  EXPECT_EQ(bl.isExtern, true);
-  EXPECT_EQ(bl.symbol, 1U);
-  const Relocation& lo = text.relocations[1];
-  EXPECT_EQ(lo.offset, Hex32(0x20));
-  EXPECT_EQ(lo.scattered, true);
-  EXPECT_EQ(lo.type, PPC_RELOC_LO16_SECTDIFF);
-  EXPECT_EQ(lo.length, 2);
-  EXPECT_EQ(lo.value, Hex32(0x44));
-  const Relocation& loPair = text.relocations[2];
-  EXPECT_EQ(loPair.offset, Hex32(0x0));
-  EXPECT_EQ(loPair.scattered, true);
-  EXPECT_EQ(loPair.type, PPC_RELOC_PAIR);
-  EXPECT_EQ(loPair.length, 2);
-  EXPECT_EQ(loPair.value, Hex32(0x18));
-  const Relocation& ha = text.relocations[3];
-  EXPECT_EQ(ha.offset, Hex32(0x1C));
-  EXPECT_EQ(ha.scattered, true);
-  EXPECT_EQ(ha.type, PPC_RELOC_HA16_SECTDIFF);
-  EXPECT_EQ(ha.length, 2);
-  EXPECT_EQ(ha.value, Hex32(0x44));
-  const Relocation& haPair = text.relocations[4];
-  EXPECT_EQ(haPair.offset, Hex32(0x2c));
-  EXPECT_EQ(haPair.scattered, true);
-  EXPECT_EQ(haPair.type, PPC_RELOC_PAIR);
-  EXPECT_EQ(haPair.length, 2);
-  EXPECT_EQ(haPair.value, Hex32(0x18));
-
-  const Section& cstring = f->sections[1];
-  EXPECT_TRUE(cstring.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(cstring.sectionName.equals("__cstring"));
-  EXPECT_EQ(cstring.type, S_CSTRING_LITERALS);
-  EXPECT_EQ(cstring.attributes, SectionAttr(0));
-  EXPECT_EQ((uint16_t)cstring.alignment, 4U);
-  EXPECT_EQ(cstring.address, Hex64(0x044));
-  EXPECT_EQ(cstring.content.size(), 7UL);
-  EXPECT_EQ((int)(cstring.content[0]), 0x68);
-  EXPECT_EQ((int)(cstring.content[1]), 0x65);
-  EXPECT_EQ((int)(cstring.content[2]), 0x6c);
-  EXPECT_TRUE(cstring.indirectSymbols.empty());
-  EXPECT_TRUE(cstring.relocations.empty());
-
-  EXPECT_EQ(f->localSymbols.size(), 0UL);
-  EXPECT_EQ(f->globalSymbols.size(), 1UL);
-  const Symbol& mainLabel = f->globalSymbols[0];
-  EXPECT_TRUE(mainLabel.name.equals("_main"));
-  EXPECT_EQ(mainLabel.type, N_SECT);
-  EXPECT_EQ(mainLabel.sect, 1);
-  EXPECT_EQ(mainLabel.scope, SymbolScope(N_EXT));
-  EXPECT_EQ(mainLabel.value, Hex64(0x0));
-  EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
-  const Symbol& printfLabel = f->undefinedSymbols[0];
-  EXPECT_TRUE(printfLabel.name.equals("_printf"));
-  EXPECT_EQ(printfLabel.type, N_UNDF);
-  EXPECT_EQ(printfLabel.scope, SymbolScope(N_EXT));
-
-  SmallString<128> tmpFl;
-  std::error_code ec =
-      llvm::sys::fs::createTemporaryFile(Twine("xx"), "o", tmpFl);
-  EXPECT_FALSE(ec);
-  llvm::Error ec2 = writeBinary(*f, tmpFl);
-  EXPECT_FALSE(ec2);
-  llvm::sys::fs::remove(tmpFl);
-}
diff --git a/gnu/llvm/lld/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp b/gnu/llvm/lld/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp
deleted file mode 100644 (file)
index f2314da..0000000
+++ /dev/null
@@ -1,695 +0,0 @@
-//===- lld/unittest/MachOTests/MachONormalizedFileBinaryWriterTests.cpp ---===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "../../lib/ReaderWriter/MachO/MachONormalizedFile.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/FileSystem.h"
-#include "gtest/gtest.h"
-#include <cassert>
-#include <memory>
-#include <system_error>
-#include <vector>
-
-using llvm::StringRef;
-using llvm::MemoryBuffer;
-using llvm::SmallString;
-using llvm::Twine;
-using llvm::ErrorOr;
-using namespace llvm::MachO;
-using namespace lld::mach_o::normalized;
-
-// Parses binary mach-o file at specified path and returns
-// ownership of buffer to mb parameter and ownership of
-// Normalized file to nf parameter.
-static void fromBinary(StringRef path, std::unique_ptr<MemoryBuffer> &mb,
-                       std::unique_ptr<NormalizedFile> &nf, StringRef archStr) {
-  ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr = MemoryBuffer::getFile(path);
-  std::error_code ec = mbOrErr.getError();
-  EXPECT_FALSE(ec);
-  mb = std::move(mbOrErr.get());
-
-  llvm::Expected<std::unique_ptr<NormalizedFile>> r =
-      lld::mach_o::normalized::readBinary(
-          mb, lld::MachOLinkingContext::archFromName(archStr));
-  EXPECT_FALSE(!r);
-  nf.reset(r->release());
-}
-
-static Relocation
-makeReloc(unsigned addr, bool rel, bool ext, RelocationInfoType type,
-                                                              unsigned sym) {
-  Relocation result;
-  result.offset = addr;
-  result.scattered = false;
-  result.type = type;
-  result.length = 2;
-  result.pcRel = rel;
-  result.isExtern = ext;
-  result.value = 0;
-  result.symbol = sym;
-  return result;
-}
-
-static Relocation
-makeScatReloc(unsigned addr, RelocationInfoType type, unsigned value) {
-  Relocation result;
-  result.offset = addr;
-  result.scattered = true;
-  result.type = type;
-  result.length = 2;
-  result.pcRel = false;
-  result.isExtern = true;
-  result.value = value;
-  result.symbol = 0;
-  return result;
-}
-
-static Symbol
-makeUndefSymbol(StringRef name) {
-  Symbol sym;
-  sym.name = name;
-  sym.type = N_UNDF;
-  sym.scope = N_EXT;
-  sym.sect = NO_SECT;
-  sym.desc = 0;
-  sym.value = 0;
-  return sym;
-}
-
-
-static Symbol
-makeSymbol(StringRef name, unsigned addr) {
-  Symbol sym;
-  sym.name = name;
-  sym.type = N_SECT;
-  sym.scope = N_EXT;
-  sym.sect = 1;
-  sym.desc = 0;
-  sym.value = addr;
-  return sym;
-}
-
-static Symbol
-makeThumbSymbol(StringRef name, unsigned addr) {
-  Symbol sym;
-  sym.name = name;
-  sym.type = N_SECT;
-  sym.scope = N_EXT;
-  sym.sect = 1;
-  sym.desc = N_ARM_THUMB_DEF;
-  sym.value = addr;
-  return sym;
-}
-
-TEST(BinaryWriterTest, obj_relocs_x86_64) {
-  SmallString<128> tmpFl;
-  {
-    NormalizedFile f;
-    f.arch = lld::MachOLinkingContext::arch_x86_64;
-    f.fileType = MH_OBJECT;
-    f.flags = MH_SUBSECTIONS_VIA_SYMBOLS;
-    f.os = lld::MachOLinkingContext::OS::macOSX;
-    f.sections.resize(1);
-    Section& text = f.sections.front();
-    text.segmentName = "__TEXT";
-    text.sectionName = "__text";
-    text.type = S_REGULAR;
-    text.attributes = SectionAttr(S_ATTR_PURE_INSTRUCTIONS
-                                      | S_ATTR_SOME_INSTRUCTIONS);
-    text.alignment = 16;
-    text.address = 0;
-    const uint8_t textBytes[] = {
-      0xe8, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x05,
-      0x00, 0x00, 0x00, 0x00, 0xff, 0x35, 0x00, 0x00,
-      0x00, 0x00, 0x8b, 0x05, 0x00, 0x00, 0x00, 0x00,
-      0xc6, 0x05, 0xff, 0xff, 0xff, 0xff, 0x12, 0xc7,
-      0x05, 0xfc, 0xff, 0xff, 0xff, 0x78, 0x56, 0x34,
-      0x12, 0x48, 0x8b, 0x3d, 0x00, 0x00, 0x00, 0x00 };
-
-    text.content = llvm::makeArrayRef(textBytes, sizeof(textBytes));
-    text.relocations.push_back(makeReloc(0x01, false, true, X86_64_RELOC_BRANCH, 1));
-    text.relocations.push_back(makeReloc(0x08, false, true, X86_64_RELOC_GOT_LOAD, 1));
-    text.relocations.push_back(makeReloc(0x0E, false, true, X86_64_RELOC_GOT, 1));
-    text.relocations.push_back(makeReloc(0x14, false, true, X86_64_RELOC_SIGNED, 1));
-    text.relocations.push_back(makeReloc(0x1A, false, true, X86_64_RELOC_SIGNED_1, 1));
-    text.relocations.push_back(makeReloc(0x21, false, true, X86_64_RELOC_SIGNED_4, 1));
-    text.relocations.push_back(makeReloc(0x2C, false, true, X86_64_RELOC_TLV, 2));
-
-    f.undefinedSymbols.push_back(makeUndefSymbol("_bar"));
-    f.undefinedSymbols.push_back(makeUndefSymbol("_tbar"));
-
-    std::error_code ec =
-        llvm::sys::fs::createTemporaryFile(Twine("xx"), "o", tmpFl);
-    EXPECT_FALSE(ec);
-    llvm::Error ec2 = writeBinary(f, tmpFl);
-    EXPECT_FALSE(ec2);
-  }
-
-  std::unique_ptr<MemoryBuffer> bufferOwner;
-  std::unique_ptr<NormalizedFile> f2;
-  fromBinary(tmpFl, bufferOwner, f2, "x86_64");
-
-  EXPECT_EQ(lld::MachOLinkingContext::arch_x86_64, f2->arch);
-  EXPECT_EQ(MH_OBJECT, f2->fileType);
-  EXPECT_EQ(FileFlags(MH_SUBSECTIONS_VIA_SYMBOLS), f2->flags);
-
-  EXPECT_TRUE(f2->localSymbols.empty());
-  EXPECT_TRUE(f2->globalSymbols.empty());
-  EXPECT_EQ(2UL, f2->undefinedSymbols.size());
-  const Symbol& barUndef = f2->undefinedSymbols[0];
-  EXPECT_TRUE(barUndef.name.equals("_bar"));
-  EXPECT_EQ(N_UNDF, barUndef.type);
-  EXPECT_EQ(SymbolScope(N_EXT), barUndef.scope);
-  const Symbol& tbarUndef = f2->undefinedSymbols[1];
-  EXPECT_TRUE(tbarUndef.name.equals("_tbar"));
-  EXPECT_EQ(N_UNDF, tbarUndef.type);
-  EXPECT_EQ(SymbolScope(N_EXT), tbarUndef.scope);
-
-  EXPECT_EQ(1UL, f2->sections.size());
-  const Section& text = f2->sections[0];
-  EXPECT_TRUE(text.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(text.sectionName.equals("__text"));
-  EXPECT_EQ(S_REGULAR, text.type);
-  EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
-                                      | S_ATTR_SOME_INSTRUCTIONS));
-  EXPECT_EQ((uint16_t)text.alignment, 16U);
-  EXPECT_EQ(text.address, Hex64(0x0));
-  EXPECT_EQ(48UL, text.content.size());
-  const Relocation& call = text.relocations[0];
-  EXPECT_EQ(call.offset, Hex32(0x1));
-  EXPECT_EQ(call.type, X86_64_RELOC_BRANCH);
-  EXPECT_EQ(call.length, 2);
-  EXPECT_EQ(call.isExtern, true);
-  EXPECT_EQ(call.symbol, 1U);
-  const Relocation& gotLoad = text.relocations[1];
-  EXPECT_EQ(gotLoad.offset, Hex32(0x8));
-  EXPECT_EQ(gotLoad.type, X86_64_RELOC_GOT_LOAD);
-  EXPECT_EQ(gotLoad.length, 2);
-  EXPECT_EQ(gotLoad.isExtern, true);
-  EXPECT_EQ(gotLoad.symbol, 1U);
-  const Relocation& gotUse = text.relocations[2];
-  EXPECT_EQ(gotUse.offset, Hex32(0xE));
-  EXPECT_EQ(gotUse.type, X86_64_RELOC_GOT);
-  EXPECT_EQ(gotUse.length, 2);
-  EXPECT_EQ(gotUse.isExtern, true);
-  EXPECT_EQ(gotUse.symbol, 1U);
-  const Relocation& signed0 = text.relocations[3];
-  EXPECT_EQ(signed0.offset, Hex32(0x14));
-  EXPECT_EQ(signed0.type, X86_64_RELOC_SIGNED);
-  EXPECT_EQ(signed0.length, 2);
-  EXPECT_EQ(signed0.isExtern, true);
-  EXPECT_EQ(signed0.symbol, 1U);
-  const Relocation& signed1 = text.relocations[4];
-  EXPECT_EQ(signed1.offset, Hex32(0x1A));
-  EXPECT_EQ(signed1.type, X86_64_RELOC_SIGNED_1);
-  EXPECT_EQ(signed1.length, 2);
-  EXPECT_EQ(signed1.isExtern, true);
-  EXPECT_EQ(signed1.symbol, 1U);
-  const Relocation& signed4 = text.relocations[5];
-  EXPECT_EQ(signed4.offset, Hex32(0x21));
-  EXPECT_EQ(signed4.type, X86_64_RELOC_SIGNED_4);
-  EXPECT_EQ(signed4.length, 2);
-  EXPECT_EQ(signed4.isExtern, true);
-  EXPECT_EQ(signed4.symbol, 1U);
-
-  bufferOwner.reset(nullptr);
-  std::error_code ec = llvm::sys::fs::remove(Twine(tmpFl));
-  EXPECT_FALSE(ec);
-}
-
-
-
-TEST(BinaryWriterTest, obj_relocs_x86) {
-  SmallString<128> tmpFl;
-  {
-    NormalizedFile f;
-    f.arch = lld::MachOLinkingContext::arch_x86;
-    f.fileType = MH_OBJECT;
-    f.flags = MH_SUBSECTIONS_VIA_SYMBOLS;
-    f.os = lld::MachOLinkingContext::OS::macOSX;
-    f.sections.resize(1);
-    Section& text = f.sections.front();
-    text.segmentName = "__TEXT";
-    text.sectionName = "__text";
-    text.type = S_REGULAR;
-    text.attributes = SectionAttr(S_ATTR_PURE_INSTRUCTIONS
-                                      | S_ATTR_SOME_INSTRUCTIONS);
-    text.alignment = 16;
-    text.address = 0;
-    const uint8_t textBytes[] = {
-       0xe8, 0xfb, 0xff, 0xff, 0xff, 0xa1, 0x00, 0x00,
-       0x00, 0x00, 0x8b, 0xb0, 0xfb, 0xff, 0xff, 0xff,
-       0x8b, 0x80, 0x11, 0x00, 0x00, 0x00 };
-
-    text.content = llvm::makeArrayRef(textBytes, sizeof(textBytes));
-    text.relocations.push_back(makeReloc(0x01, true, true, GENERIC_RELOC_VANILLA, 0));
-    text.relocations.push_back(makeReloc(0x06, false, true, GENERIC_RELOC_VANILLA, 0));
-    text.relocations.push_back(makeScatReloc(0x0c, GENERIC_RELOC_LOCAL_SECTDIFF, 0));
-    text.relocations.push_back(makeScatReloc(0x0, GENERIC_RELOC_PAIR, 5));
-    text.relocations.push_back(makeReloc(0x12, true, true, GENERIC_RELOC_TLV, 1));
-
-    f.undefinedSymbols.push_back(makeUndefSymbol("_bar"));
-    f.undefinedSymbols.push_back(makeUndefSymbol("_tbar"));
-
-    std::error_code ec =
-        llvm::sys::fs::createTemporaryFile(Twine("xx"), "o", tmpFl);
-    EXPECT_FALSE(ec);
-    llvm::Error ec2 = writeBinary(f, tmpFl);
-    EXPECT_FALSE(ec2);
-  }
-  std::unique_ptr<MemoryBuffer> bufferOwner;
-  std::unique_ptr<NormalizedFile> f2;
-  fromBinary(tmpFl, bufferOwner, f2, "i386");
-
-  EXPECT_EQ(lld::MachOLinkingContext::arch_x86, f2->arch);
-  EXPECT_EQ(MH_OBJECT, f2->fileType);
-  EXPECT_EQ(FileFlags(MH_SUBSECTIONS_VIA_SYMBOLS), f2->flags);
-
-  EXPECT_TRUE(f2->localSymbols.empty());
-  EXPECT_TRUE(f2->globalSymbols.empty());
-  EXPECT_EQ(2UL, f2->undefinedSymbols.size());
-  const Symbol& barUndef = f2->undefinedSymbols[0];
-  EXPECT_TRUE(barUndef.name.equals("_bar"));
-  EXPECT_EQ(N_UNDF, barUndef.type);
-  EXPECT_EQ(SymbolScope(N_EXT), barUndef.scope);
-  const Symbol& tbarUndef = f2->undefinedSymbols[1];
-  EXPECT_TRUE(tbarUndef.name.equals("_tbar"));
-  EXPECT_EQ(N_UNDF, tbarUndef.type);
-  EXPECT_EQ(SymbolScope(N_EXT), tbarUndef.scope);
-
-  EXPECT_EQ(1UL, f2->sections.size());
-  const Section& text = f2->sections[0];
-  EXPECT_TRUE(text.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(text.sectionName.equals("__text"));
-  EXPECT_EQ(S_REGULAR, text.type);
-  EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
-                                      | S_ATTR_SOME_INSTRUCTIONS));
-  EXPECT_EQ((uint16_t)text.alignment, 16U);
-  EXPECT_EQ(text.address, Hex64(0x0));
-  EXPECT_EQ(22UL, text.content.size());
-  const Relocation& call = text.relocations[0];
-  EXPECT_EQ(call.offset, Hex32(0x1));
-  EXPECT_EQ(call.scattered, false);
-  EXPECT_EQ(call.type, GENERIC_RELOC_VANILLA);
-  EXPECT_EQ(call.pcRel, true);
-  EXPECT_EQ(call.length, 2);
-  EXPECT_EQ(call.isExtern, true);
-  EXPECT_EQ(call.symbol, 0U);
-  const Relocation& absLoad = text.relocations[1];
-  EXPECT_EQ(absLoad.offset, Hex32(0x6));
-  EXPECT_EQ(absLoad.scattered, false);
-  EXPECT_EQ(absLoad.type, GENERIC_RELOC_VANILLA);
-  EXPECT_EQ(absLoad.pcRel, false);
-  EXPECT_EQ(absLoad.length, 2);
-  EXPECT_EQ(absLoad.isExtern, true);
-  EXPECT_EQ(absLoad.symbol,0U);
-  const Relocation& pic1 = text.relocations[2];
-  EXPECT_EQ(pic1.offset, Hex32(0xc));
-  EXPECT_EQ(pic1.scattered, true);
-  EXPECT_EQ(pic1.type, GENERIC_RELOC_LOCAL_SECTDIFF);
-  EXPECT_EQ(pic1.length, 2);
-  EXPECT_EQ(pic1.value, 0U);
-  const Relocation& pic2 = text.relocations[3];
-  EXPECT_EQ(pic2.offset, Hex32(0x0));
-  EXPECT_EQ(pic1.scattered, true);
-  EXPECT_EQ(pic2.type, GENERIC_RELOC_PAIR);
-  EXPECT_EQ(pic2.length, 2);
-  EXPECT_EQ(pic2.value, 5U);
-  const Relocation& tlv = text.relocations[4];
-  EXPECT_EQ(tlv.offset, Hex32(0x12));
-  EXPECT_EQ(tlv.type, GENERIC_RELOC_TLV);
-  EXPECT_EQ(tlv.length, 2);
-  EXPECT_EQ(tlv.isExtern, true);
-  EXPECT_EQ(tlv.symbol, 1U);
-
-  // lld::errs() << "temp = " << tmpFl << "\n";
-  bufferOwner.reset(nullptr);
-  std::error_code ec = llvm::sys::fs::remove(Twine(tmpFl));
-  EXPECT_FALSE(ec);
-}
-
-
-
-TEST(BinaryWriterTest, obj_relocs_armv7) {
-  SmallString<128> tmpFl;
-  {
-    NormalizedFile f;
-    f.arch = lld::MachOLinkingContext::arch_armv7;
-    f.fileType = MH_OBJECT;
-    f.flags = MH_SUBSECTIONS_VIA_SYMBOLS;
-    f.os = lld::MachOLinkingContext::OS::macOSX;
-    f.sections.resize(1);
-    Section& text = f.sections.front();
-    text.segmentName = "__TEXT";
-    text.sectionName = "__text";
-    text.type = S_REGULAR;
-    text.attributes = SectionAttr(S_ATTR_PURE_INSTRUCTIONS
-                                      | S_ATTR_SOME_INSTRUCTIONS);
-    text.alignment = 4;
-    text.address = 0;
-    const uint8_t textBytes[] = {
-      0xff, 0xf7, 0xfe, 0xef, 0x40, 0xf2, 0x05, 0x01,
-      0xc0, 0xf2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0xbf };
-
-    text.content = llvm::makeArrayRef(textBytes, sizeof(textBytes));
-    text.relocations.push_back(makeReloc(0x00, true, true,
-                                        ARM_THUMB_RELOC_BR22, 2));
-    text.relocations.push_back(makeScatReloc(0x04,
-                                        ARM_RELOC_HALF_SECTDIFF, 0x10));
-    text.relocations.push_back(makeScatReloc(0x00,
-                                        ARM_RELOC_PAIR, 0xC));
-    text.relocations.push_back(makeScatReloc(0x08,
-                                        ARM_RELOC_HALF_SECTDIFF, 0x10));
-    text.relocations.push_back(makeScatReloc(0x00,
-                                        ARM_RELOC_PAIR, 0xC));
-    text.relocations.push_back(makeReloc(0x0C, false, true,
-                                        ARM_RELOC_VANILLA, 2));
-
-    f.globalSymbols.push_back(makeThumbSymbol("_foo", 0x00));
-    f.globalSymbols.push_back(makeThumbSymbol("_foo2", 0x10));
-    f.undefinedSymbols.push_back(makeUndefSymbol("_bar"));
-
-    std::error_code ec =
-        llvm::sys::fs::createTemporaryFile(Twine("xx"), "o", tmpFl);
-    EXPECT_FALSE(ec);
-    llvm::Error ec2 = writeBinary(f, tmpFl);
-    EXPECT_FALSE(ec2);
-  }
-  std::unique_ptr<MemoryBuffer> bufferOwner;
-  std::unique_ptr<NormalizedFile> f2;
-  fromBinary(tmpFl, bufferOwner, f2, "armv7");
-
-  EXPECT_EQ(lld::MachOLinkingContext::arch_armv7, f2->arch);
-  EXPECT_EQ(MH_OBJECT, f2->fileType);
-  EXPECT_EQ(FileFlags(MH_SUBSECTIONS_VIA_SYMBOLS), f2->flags);
-
-  EXPECT_TRUE(f2->localSymbols.empty());
-  EXPECT_EQ(2UL, f2->globalSymbols.size());
-  const Symbol& fooDef = f2->globalSymbols[0];
-  EXPECT_TRUE(fooDef.name.equals("_foo"));
-  EXPECT_EQ(N_SECT, fooDef.type);
-  EXPECT_EQ(1, fooDef.sect);
-  EXPECT_EQ(SymbolScope(N_EXT), fooDef.scope);
-  const Symbol& foo2Def = f2->globalSymbols[1];
-  EXPECT_TRUE(foo2Def.name.equals("_foo2"));
-  EXPECT_EQ(N_SECT, foo2Def.type);
-  EXPECT_EQ(1, foo2Def.sect);
-  EXPECT_EQ(SymbolScope(N_EXT), foo2Def.scope);
-
-  EXPECT_EQ(1UL, f2->undefinedSymbols.size());
-  const Symbol& barUndef = f2->undefinedSymbols[0];
-  EXPECT_TRUE(barUndef.name.equals("_bar"));
-  EXPECT_EQ(N_UNDF, barUndef.type);
-  EXPECT_EQ(SymbolScope(N_EXT), barUndef.scope);
-
-  EXPECT_EQ(1UL, f2->sections.size());
-  const Section& text = f2->sections[0];
-  EXPECT_TRUE(text.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(text.sectionName.equals("__text"));
-  EXPECT_EQ(S_REGULAR, text.type);
-  EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
-                                      | S_ATTR_SOME_INSTRUCTIONS));
-  EXPECT_EQ((uint16_t)text.alignment, 4U);
-  EXPECT_EQ(text.address, Hex64(0x0));
-  EXPECT_EQ(18UL, text.content.size());
-  const Relocation& blx = text.relocations[0];
-  EXPECT_EQ(blx.offset, Hex32(0x0));
-  EXPECT_EQ(blx.scattered, false);
-  EXPECT_EQ(blx.type, ARM_THUMB_RELOC_BR22);
-  EXPECT_EQ(blx.pcRel, true);
-  EXPECT_EQ(blx.length, 2);
-  EXPECT_EQ(blx.isExtern, true);
-  EXPECT_EQ(blx.symbol, 2U);
-  const Relocation& movw1 = text.relocations[1];
-  EXPECT_EQ(movw1.offset, Hex32(0x4));
-  EXPECT_EQ(movw1.scattered, true);
-  EXPECT_EQ(movw1.type, ARM_RELOC_HALF_SECTDIFF);
-  EXPECT_EQ(movw1.length, 2);
-  EXPECT_EQ(movw1.value, 0x10U);
-  const Relocation& movw2 = text.relocations[2];
-  EXPECT_EQ(movw2.offset, Hex32(0x0));
-  EXPECT_EQ(movw2.scattered, true);
-  EXPECT_EQ(movw2.type, ARM_RELOC_PAIR);
-  EXPECT_EQ(movw2.length, 2);
-  EXPECT_EQ(movw2.value, Hex32(0xC));
-   const Relocation& movt1 = text.relocations[3];
-  EXPECT_EQ(movt1.offset, Hex32(0x8));
-  EXPECT_EQ(movt1.scattered, true);
-  EXPECT_EQ(movt1.type, ARM_RELOC_HALF_SECTDIFF);
-  EXPECT_EQ(movt1.length, 2);
-  EXPECT_EQ(movt1.value, Hex32(0x10));
-  const Relocation& movt2 = text.relocations[4];
-  EXPECT_EQ(movt2.offset, Hex32(0x0));
-  EXPECT_EQ(movt2.scattered, true);
-  EXPECT_EQ(movt2.type, ARM_RELOC_PAIR);
-  EXPECT_EQ(movt2.length, 2);
-  EXPECT_EQ(movt2.value, Hex32(0xC));
- const Relocation& absPointer = text.relocations[5];
-  EXPECT_EQ(absPointer.offset, Hex32(0xC));
-  EXPECT_EQ(absPointer.type, ARM_RELOC_VANILLA);
-  EXPECT_EQ(absPointer.length, 2);
-  EXPECT_EQ(absPointer.isExtern, true);
-  EXPECT_EQ(absPointer.symbol, 2U);
-
-  // lld::errs() << "temp = " << tmpFl << "\n";
-  bufferOwner.reset(nullptr);
-  std::error_code ec = llvm::sys::fs::remove(Twine(tmpFl));
-  EXPECT_FALSE(ec);
-}
-
-
-
-TEST(BinaryWriterTest, obj_relocs_ppc) {
-  SmallString<128> tmpFl;
-  {
-    NormalizedFile f;
-    f.arch = lld::MachOLinkingContext::arch_ppc;
-    f.fileType = MH_OBJECT;
-    f.flags = MH_SUBSECTIONS_VIA_SYMBOLS;
-    f.os = lld::MachOLinkingContext::OS::macOSX;
-    f.sections.resize(1);
-    Section& text = f.sections.front();
-    text.segmentName = "__TEXT";
-    text.sectionName = "__text";
-    text.type = S_REGULAR;
-    text.attributes = SectionAttr(S_ATTR_PURE_INSTRUCTIONS
-                                      | S_ATTR_SOME_INSTRUCTIONS);
-    text.alignment = 4;
-    text.address = 0;
-    const uint8_t textBytes[] = {
-      0x48, 0x00, 0x00, 0x01, 0x40, 0x82, 0xff, 0xfc,
-      0x3c, 0x62, 0x00, 0x00, 0x3c, 0x62, 0x00, 0x00,
-      0x80, 0x63, 0x00, 0x24, 0x80, 0x63, 0x00, 0x24,
-      0x3c, 0x40, 0x00, 0x00, 0x3c, 0x60, 0x00, 0x00,
-      0x80, 0x42, 0x00, 0x28, 0x80, 0x63, 0x00, 0x28,
-      0x60, 0x00, 0x00, 0x00 };
-
-    text.content = llvm::makeArrayRef(textBytes, sizeof(textBytes));
-    text.relocations.push_back(makeReloc(0x00, true, true,
-                                        PPC_RELOC_BR24, 2));
-    text.relocations.push_back(makeReloc(0x04, true, true,
-                                        PPC_RELOC_BR14, 2));
-    text.relocations.push_back(makeScatReloc(0x08,
-                                        PPC_RELOC_HI16_SECTDIFF, 0x28));
-    text.relocations.push_back(makeScatReloc(0x24,
-                                        PPC_RELOC_PAIR, 0x4));
-    text.relocations.push_back(makeScatReloc(0x0C,
-                                        PPC_RELOC_HA16_SECTDIFF, 0x28));
-    text.relocations.push_back(makeScatReloc(0x24,
-                                        PPC_RELOC_PAIR, 0x4));
-    text.relocations.push_back(makeScatReloc(0x10,
-                                        PPC_RELOC_LO16_SECTDIFF, 0x28));
-    text.relocations.push_back(makeScatReloc(0x00,
-                                        PPC_RELOC_PAIR, 0x4));
-    text.relocations.push_back(makeScatReloc(0x14,
-                                        PPC_RELOC_LO14_SECTDIFF, 0x28));
-    text.relocations.push_back(makeScatReloc(0x00,
-                                        PPC_RELOC_PAIR, 0x4));
-    text.relocations.push_back(makeReloc(0x18, false, false,
-                                        PPC_RELOC_HI16, 1));
-    text.relocations.push_back(makeReloc(0x28, false, false,
-                                        PPC_RELOC_PAIR, 0));
-    text.relocations.push_back(makeReloc(0x1C, false, false,
-                                        PPC_RELOC_HA16, 1));
-    text.relocations.push_back(makeReloc(0x28, false, false,
-                                        PPC_RELOC_PAIR, 0));
-    text.relocations.push_back(makeReloc(0x20, false, false,
-                                        PPC_RELOC_LO16, 1));
-    text.relocations.push_back(makeReloc(0x00, false, false,
-                                        PPC_RELOC_PAIR, 0));
-    text.relocations.push_back(makeReloc(0x24, false, false,
-                                        PPC_RELOC_LO14, 1));
-    text.relocations.push_back(makeReloc(0x00, false, false,
-                                        PPC_RELOC_PAIR, 0));
-
-    f.globalSymbols.push_back(makeSymbol("_foo", 0x00));
-    f.globalSymbols.push_back(makeSymbol("_foo2", 0x28));
-    f.undefinedSymbols.push_back(makeUndefSymbol("_bar"));
-
-    std::error_code ec =
-        llvm::sys::fs::createTemporaryFile(Twine("xx"), "o", tmpFl);
-    EXPECT_FALSE(ec);
-    llvm::Error ec2 = writeBinary(f, tmpFl);
-    EXPECT_FALSE(ec2);
-  }
-  std::unique_ptr<MemoryBuffer> bufferOwner;
-  std::unique_ptr<NormalizedFile> f2;
-  fromBinary(tmpFl, bufferOwner, f2, "ppc");
-
-  EXPECT_EQ(lld::MachOLinkingContext::arch_ppc, f2->arch);
-  EXPECT_EQ(MH_OBJECT, f2->fileType);
-  EXPECT_EQ(FileFlags(MH_SUBSECTIONS_VIA_SYMBOLS), f2->flags);
-
-  EXPECT_TRUE(f2->localSymbols.empty());
-  EXPECT_EQ(2UL, f2->globalSymbols.size());
-  const Symbol& fooDef = f2->globalSymbols[0];
-  EXPECT_TRUE(fooDef.name.equals("_foo"));
-  EXPECT_EQ(N_SECT, fooDef.type);
-  EXPECT_EQ(1, fooDef.sect);
-  EXPECT_EQ(SymbolScope(N_EXT), fooDef.scope);
-  const Symbol& foo2Def = f2->globalSymbols[1];
-  EXPECT_TRUE(foo2Def.name.equals("_foo2"));
-  EXPECT_EQ(N_SECT, foo2Def.type);
-  EXPECT_EQ(1, foo2Def.sect);
-  EXPECT_EQ(SymbolScope(N_EXT), foo2Def.scope);
-
-  EXPECT_EQ(1UL, f2->undefinedSymbols.size());
-  const Symbol& barUndef = f2->undefinedSymbols[0];
-  EXPECT_TRUE(barUndef.name.equals("_bar"));
-  EXPECT_EQ(N_UNDF, barUndef.type);
-  EXPECT_EQ(SymbolScope(N_EXT), barUndef.scope);
-
-  EXPECT_EQ(1UL, f2->sections.size());
-  const Section& text = f2->sections[0];
-  EXPECT_TRUE(text.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(text.sectionName.equals("__text"));
-  EXPECT_EQ(S_REGULAR, text.type);
-  EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
-                                      | S_ATTR_SOME_INSTRUCTIONS));
-  EXPECT_EQ((uint16_t)text.alignment, 4U);
-  EXPECT_EQ(text.address, Hex64(0x0));
-  EXPECT_EQ(44UL, text.content.size());
-  const Relocation& br24 = text.relocations[0];
-  EXPECT_EQ(br24.offset, Hex32(0x0));
-  EXPECT_EQ(br24.scattered, false);
-  EXPECT_EQ(br24.type, PPC_RELOC_BR24);
-  EXPECT_EQ(br24.pcRel, true);
-  EXPECT_EQ(br24.length, 2);
-  EXPECT_EQ(br24.isExtern, true);
-  EXPECT_EQ(br24.symbol, 2U);
-  const Relocation& br14 = text.relocations[1];
-  EXPECT_EQ(br14.offset, Hex32(0x4));
-  EXPECT_EQ(br14.scattered, false);
-  EXPECT_EQ(br14.type, PPC_RELOC_BR14);
-  EXPECT_EQ(br14.pcRel, true);
-  EXPECT_EQ(br14.length, 2);
-  EXPECT_EQ(br14.isExtern, true);
-  EXPECT_EQ(br14.symbol, 2U);
-  const Relocation& pichi1 = text.relocations[2];
-  EXPECT_EQ(pichi1.offset, Hex32(0x8));
-  EXPECT_EQ(pichi1.scattered, true);
-  EXPECT_EQ(pichi1.type, PPC_RELOC_HI16_SECTDIFF);
-  EXPECT_EQ(pichi1.length, 2);
-  EXPECT_EQ(pichi1.value, 0x28U);
-  const Relocation& pichi2 = text.relocations[3];
-  EXPECT_EQ(pichi2.offset, Hex32(0x24));
-  EXPECT_EQ(pichi2.scattered, true);
-  EXPECT_EQ(pichi2.type, PPC_RELOC_PAIR);
-  EXPECT_EQ(pichi2.length, 2);
-  EXPECT_EQ(pichi2.value, 0x4U);
-  const Relocation& picha1 = text.relocations[4];
-  EXPECT_EQ(picha1.offset, Hex32(0xC));
-  EXPECT_EQ(picha1.scattered, true);
-  EXPECT_EQ(picha1.type, PPC_RELOC_HA16_SECTDIFF);
-  EXPECT_EQ(picha1.length, 2);
-  EXPECT_EQ(picha1.value, 0x28U);
-  const Relocation& picha2 = text.relocations[5];
-  EXPECT_EQ(picha2.offset, Hex32(0x24));
-  EXPECT_EQ(picha2.scattered, true);
-  EXPECT_EQ(picha2.type, PPC_RELOC_PAIR);
-  EXPECT_EQ(picha2.length, 2);
-  EXPECT_EQ(picha2.value, 0x4U);
-  const Relocation& piclo1 = text.relocations[6];
-  EXPECT_EQ(piclo1.offset, Hex32(0x10));
-  EXPECT_EQ(piclo1.scattered, true);
-  EXPECT_EQ(piclo1.type, PPC_RELOC_LO16_SECTDIFF);
-  EXPECT_EQ(piclo1.length, 2);
-  EXPECT_EQ(piclo1.value, 0x28U);
-  const Relocation& piclo2 = text.relocations[7];
-  EXPECT_EQ(piclo2.offset, Hex32(0x0));
-  EXPECT_EQ(piclo2.scattered, true);
-  EXPECT_EQ(piclo2.type, PPC_RELOC_PAIR);
-  EXPECT_EQ(piclo2.length, 2);
-  EXPECT_EQ(piclo2.value, 0x4U);
-  const Relocation& picloa1 = text.relocations[8];
-  EXPECT_EQ(picloa1.offset, Hex32(0x14));
-  EXPECT_EQ(picloa1.scattered, true);
-  EXPECT_EQ(picloa1.type, PPC_RELOC_LO14_SECTDIFF);
-  EXPECT_EQ(picloa1.length, 2);
-  EXPECT_EQ(picloa1.value, 0x28U);
-  const Relocation& picloa2 = text.relocations[9];
-  EXPECT_EQ(picloa2.offset, Hex32(0x0));
-  EXPECT_EQ(picloa2.scattered, true);
-  EXPECT_EQ(picloa2.type, PPC_RELOC_PAIR);
-  EXPECT_EQ(picloa2.length, 2);
-  EXPECT_EQ(picloa2.value, 0x4U);
-  const Relocation& abshi1 = text.relocations[10];
-  EXPECT_EQ(abshi1.offset, Hex32(0x18));
-  EXPECT_EQ(abshi1.scattered, false);
-  EXPECT_EQ(abshi1.type, PPC_RELOC_HI16);
-  EXPECT_EQ(abshi1.length, 2);
-  EXPECT_EQ(abshi1.symbol, 1U);
-  const Relocation& abshi2 = text.relocations[11];
-  EXPECT_EQ(abshi2.offset, Hex32(0x28));
-  EXPECT_EQ(abshi2.scattered, false);
-  EXPECT_EQ(abshi2.type, PPC_RELOC_PAIR);
-  EXPECT_EQ(abshi2.length, 2);
-  EXPECT_EQ(abshi2.symbol, 0U);
-  const Relocation& absha1 = text.relocations[12];
-  EXPECT_EQ(absha1.offset, Hex32(0x1C));
-  EXPECT_EQ(absha1.scattered, false);
-  EXPECT_EQ(absha1.type, PPC_RELOC_HA16);
-  EXPECT_EQ(absha1.length, 2);
-  EXPECT_EQ(absha1.symbol, 1U);
-  const Relocation& absha2 = text.relocations[13];
-  EXPECT_EQ(absha2.offset, Hex32(0x28));
-  EXPECT_EQ(absha2.scattered, false);
-  EXPECT_EQ(absha2.type, PPC_RELOC_PAIR);
-  EXPECT_EQ(absha2.length, 2);
-  EXPECT_EQ(absha2.symbol, 0U);
-  const Relocation& abslo1 = text.relocations[14];
-  EXPECT_EQ(abslo1.offset, Hex32(0x20));
-  EXPECT_EQ(abslo1.scattered, false);
-  EXPECT_EQ(abslo1.type, PPC_RELOC_LO16);
-  EXPECT_EQ(abslo1.length, 2);
-  EXPECT_EQ(abslo1.symbol, 1U);
-  const Relocation& abslo2 = text.relocations[15];
-  EXPECT_EQ(abslo2.offset, Hex32(0x00));
-  EXPECT_EQ(abslo2.scattered, false);
-  EXPECT_EQ(abslo2.type, PPC_RELOC_PAIR);
-  EXPECT_EQ(abslo2.length, 2);
-  EXPECT_EQ(abslo2.symbol, 0U);
-  const Relocation& absloa1 = text.relocations[16];
-  EXPECT_EQ(absloa1.offset, Hex32(0x24));
-  EXPECT_EQ(absloa1.scattered, false);
-  EXPECT_EQ(absloa1.type, PPC_RELOC_LO14);
-  EXPECT_EQ(absloa1.length, 2);
-  EXPECT_EQ(absloa1.symbol, 1U);
-  const Relocation& absloa2 = text.relocations[17];
-  EXPECT_EQ(absloa2.offset, Hex32(0x00));
-  EXPECT_EQ(absloa2.scattered, false);
-  EXPECT_EQ(absloa2.type, PPC_RELOC_PAIR);
-  EXPECT_EQ(absloa2.length, 2);
-  EXPECT_EQ(absloa2.symbol, 0U);
-
-  bufferOwner.reset(nullptr);
-  std::error_code ec = llvm::sys::fs::remove(Twine(tmpFl));
-  EXPECT_FALSE(ec);
-}
diff --git a/gnu/llvm/lld/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp b/gnu/llvm/lld/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp
deleted file mode 100644 (file)
index 19534ea..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-//===- lld/unittest/MachOTests/MachONormalizedFileToAtomsTests.cpp --------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "../../lib/ReaderWriter/MachO/MachONormalizedFile.h"
-#include "lld/Core/Atom.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/UndefinedAtom.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/YAMLTraits.h"
-#include "gtest/gtest.h"
-#include <cstdint>
-#include <memory>
-
-using namespace lld::mach_o::normalized;
-using namespace llvm::MachO;
-
-TEST(ToAtomsTest, empty_obj_x86_64) {
-  NormalizedFile f;
-  f.arch = lld::MachOLinkingContext::arch_x86_64;
-  llvm::Expected<std::unique_ptr<const lld::File>> atom_f =
-      normalizedToAtoms(f, "", false);
-  EXPECT_FALSE(!atom_f);
-  EXPECT_EQ(0U, (*atom_f)->defined().size());
-}
-
-TEST(ToAtomsTest, basic_obj_x86_64) {
-  NormalizedFile f;
-  f.arch = lld::MachOLinkingContext::arch_x86_64;
-  Section textSection;
-  static const uint8_t contentBytes[] = { 0x90, 0xC3, 0xC3, 0xC4 };
-  const unsigned contentSize = sizeof(contentBytes) / sizeof(contentBytes[0]);
-  textSection.content = llvm::makeArrayRef(contentBytes, contentSize);
-  f.sections.push_back(textSection);
-  Symbol fooSymbol;
-  fooSymbol.name = "_foo";
-  fooSymbol.type = N_SECT;
-  fooSymbol.scope = N_EXT;
-  fooSymbol.sect = 1;
-  fooSymbol.value = 0;
-  f.globalSymbols.push_back(fooSymbol);
-  Symbol barSymbol;
-  barSymbol.name = "_bar";
-  barSymbol.type = N_SECT;
-  barSymbol.scope = N_EXT;
-  barSymbol.sect = 1;
-  barSymbol.value = 2;
-  f.globalSymbols.push_back(barSymbol);
-  Symbol undefSym;
-  undefSym.name = "_undef";
-  undefSym.type = N_UNDF;
-  f.undefinedSymbols.push_back(undefSym);
-  Symbol bazSymbol;
-  bazSymbol.name = "_baz";
-  bazSymbol.type = N_SECT;
-  bazSymbol.scope = N_EXT | N_PEXT;
-  bazSymbol.sect = 1;
-  bazSymbol.value = 3;
-  f.localSymbols.push_back(bazSymbol);
-
-  llvm::Expected<std::unique_ptr<const lld::File>> atom_f =
-      normalizedToAtoms(f, "", false);
-  EXPECT_FALSE(!atom_f);
-  const lld::File &file = **atom_f;
-  EXPECT_EQ(3U, file.defined().size());
-  auto it = file.defined().begin();
-  const lld::DefinedAtom *atom1 = *it;
-  ++it;
-  const lld::DefinedAtom *atom2 = *it;
-  ++it;
-  const lld::DefinedAtom *atom3 = *it;
-  const lld::UndefinedAtom *atom4 = *file.undefined().begin();
-  EXPECT_TRUE(atom1->name().equals("_foo"));
-  EXPECT_EQ(2U, atom1->rawContent().size());
-  EXPECT_EQ(0x90, atom1->rawContent()[0]);
-  EXPECT_EQ(0xC3, atom1->rawContent()[1]);
-  EXPECT_EQ(lld::Atom::scopeGlobal, atom1->scope());
-
-  EXPECT_TRUE(atom2->name().equals("_bar"));
-  EXPECT_EQ(1U, atom2->rawContent().size());
-  EXPECT_EQ(0xC3, atom2->rawContent()[0]);
-  EXPECT_EQ(lld::Atom::scopeGlobal, atom2->scope());
-
-  EXPECT_TRUE(atom3->name().equals("_baz"));
-  EXPECT_EQ(1U, atom3->rawContent().size());
-  EXPECT_EQ(0xC4, atom3->rawContent()[0]);
-  EXPECT_EQ(lld::Atom::scopeLinkageUnit, atom3->scope());
-
-  EXPECT_TRUE(atom4->name().equals("_undef"));
-  EXPECT_EQ(lld::Atom::definitionUndefined, atom4->definition());
-}
-
-TEST(ToAtomsTest, reservedUnitLength) {
-  static const uint8_t debugInfoWithReservedLengthContent[12] = {
-      0xf0, 0xff, 0xff, 0xff // Reserved length value
-  };
-  static const uint8_t debugInfoWithValidBigLengthContent[12] = {
-      0xef, 0xff, 0xff, 0xff, // The maximum valid length value for DWARF32
-      0x00, 0x00              // Wrong version
-  };
-  static const uint8_t dummyContent[] = {0x00};
-
-  NormalizedFile fReservedLength, fValidBigLength;
-  fReservedLength.arch = lld::MachOLinkingContext::arch_x86;
-  fValidBigLength.arch = lld::MachOLinkingContext::arch_x86;
-  Section section;
-  section.segmentName = "__DWARF";
-  section.sectionName = "__debug_info";
-  section.content = llvm::makeArrayRef(debugInfoWithReservedLengthContent);
-  fReservedLength.sections.push_back(section);
-  section.content = llvm::makeArrayRef(debugInfoWithValidBigLengthContent);
-  fValidBigLength.sections.push_back(section);
-  section.sectionName = "__debug_abbrev";
-  section.content = llvm::makeArrayRef(dummyContent);
-  fReservedLength.sections.push_back(section);
-  fValidBigLength.sections.push_back(section);
-  section.sectionName = "__debug_str";
-  fReservedLength.sections.push_back(section);
-  fValidBigLength.sections.push_back(section);
-
-  auto resultReservedLength = normalizedToAtoms(fReservedLength, "foo", false);
-  auto resultValidBigLength = normalizedToAtoms(fValidBigLength, "foo", false);
-
-  // Both cases should return errors, but different.
-  ASSERT_FALSE(resultReservedLength);
-  ASSERT_FALSE(resultValidBigLength);
-
-  EXPECT_STREQ("Malformed DWARF in foo",
-               toString(resultReservedLength.takeError()).c_str());
-  EXPECT_STREQ("Unsupported DWARF version in foo",
-               toString(resultValidBigLength.takeError()).c_str());
-}
diff --git a/gnu/llvm/lld/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp b/gnu/llvm/lld/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp
deleted file mode 100644 (file)
index dbfe3a0..0000000
+++ /dev/null
@@ -1,762 +0,0 @@
-//===- lld/unittest/MachOTests/MachONormalizedFileYAMLTests.cpp -----------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "../../lib/ReaderWriter/MachO/MachONormalizedFile.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include "gtest/gtest.h"
-#include <cstdint>
-#include <memory>
-#include <string>
-#include <system_error>
-
-using llvm::StringRef;
-using llvm::MemoryBuffer;
-using lld::mach_o::normalized::NormalizedFile;
-using lld::mach_o::normalized::Symbol;
-using lld::mach_o::normalized::Section;
-using lld::mach_o::normalized::Relocation;
-
-static std::unique_ptr<NormalizedFile> fromYAML(StringRef str) {
-  std::unique_ptr<MemoryBuffer> mb(MemoryBuffer::getMemBuffer(str));
-  llvm::Expected<std::unique_ptr<NormalizedFile>> r
-                                    = lld::mach_o::normalized::readYaml(mb);
-  EXPECT_FALSE(!r);
-  return std::move(*r);
-}
-
-static void toYAML(const NormalizedFile &f, std::string &out) {
-  llvm::raw_string_ostream ostr(out);
-  std::error_code ec = lld::mach_o::normalized::writeYaml(f, ostr);
-  EXPECT_TRUE(!ec);
-}
-
-// ppc is no longer supported, but it is here to test endianness handling.
-TEST(ObjectFileYAML, empty_ppc) {
-  std::unique_ptr<NormalizedFile> f = fromYAML(
-    "---\n"
-    "arch:      ppc\n"
-    "file-type: MH_OBJECT\n"
-    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
-    "...\n");
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_ppc);
-  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
-  EXPECT_EQ((int)(f->flags), (int)(int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_TRUE(f->sections.empty());
-  EXPECT_TRUE(f->localSymbols.empty());
-  EXPECT_TRUE(f->globalSymbols.empty());
-  EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(ObjectFileYAML, empty_x86_64) {
-  std::unique_ptr<NormalizedFile> f = fromYAML(
-    "---\n"
-    "arch:      x86_64\n"
-    "file-type: MH_OBJECT\n"
-    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
-    "...\n");
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64);
-  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
-  EXPECT_EQ((int)(f->flags), (int)(int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_TRUE(f->sections.empty());
-  EXPECT_TRUE(f->localSymbols.empty());
-  EXPECT_TRUE(f->globalSymbols.empty());
-  EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(ObjectFileYAML, empty_x86) {
-  std::unique_ptr<NormalizedFile> f = fromYAML(
-    "---\n"
-    "arch:      x86\n"
-    "file-type: MH_OBJECT\n"
-    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
-    "...\n");
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86);
-  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
-  EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_TRUE(f->sections.empty());
-  EXPECT_TRUE(f->localSymbols.empty());
-  EXPECT_TRUE(f->globalSymbols.empty());
-  EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(ObjectFileYAML, empty_armv6) {
-  std::unique_ptr<NormalizedFile> f = fromYAML(
-    "---\n"
-    "arch:      armv6\n"
-    "file-type: MH_OBJECT\n"
-    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
-    "...\n");
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv6);
-  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
-  EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_TRUE(f->sections.empty());
-  EXPECT_TRUE(f->localSymbols.empty());
-  EXPECT_TRUE(f->globalSymbols.empty());
-  EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(ObjectFileYAML, empty_armv7) {
-  std::unique_ptr<NormalizedFile> f = fromYAML(
-    "---\n"
-    "arch:      armv7\n"
-    "file-type: MH_OBJECT\n"
-    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
-    "...\n");
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv7);
-  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
-  EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_TRUE(f->sections.empty());
-  EXPECT_TRUE(f->localSymbols.empty());
-  EXPECT_TRUE(f->globalSymbols.empty());
-  EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(ObjectFileYAML, empty_armv7s) {
-  std::unique_ptr<NormalizedFile> f = fromYAML(
-    "---\n"
-    "arch:      armv7s\n"
-    "file-type: MH_OBJECT\n"
-    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
-    "...\n");
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv7s);
-  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
-  EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_TRUE(f->sections.empty());
-  EXPECT_TRUE(f->localSymbols.empty());
-  EXPECT_TRUE(f->globalSymbols.empty());
-  EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(ObjectFileYAML, roundTrip) {
-  std::string intermediate;
-  {
-    NormalizedFile f;
-    f.arch = lld::MachOLinkingContext::arch_x86_64;
-    f.fileType = llvm::MachO::MH_OBJECT;
-    f.flags = (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
-    f.os = lld::MachOLinkingContext::OS::macOSX;
-    toYAML(f, intermediate);
-  }
-  {
-    std::unique_ptr<NormalizedFile> f2 = fromYAML(intermediate);
-    EXPECT_EQ(f2->arch, lld::MachOLinkingContext::arch_x86_64);
-    EXPECT_EQ((int)(f2->fileType), llvm::MachO::MH_OBJECT);
-    EXPECT_EQ((int)(f2->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
-    EXPECT_TRUE(f2->sections.empty());
-    EXPECT_TRUE(f2->localSymbols.empty());
-    EXPECT_TRUE(f2->globalSymbols.empty());
-    EXPECT_TRUE(f2->undefinedSymbols.empty());
-  }
-}
-
-TEST(ObjectFileYAML, oneSymbol) {
-  std::unique_ptr<NormalizedFile> f = fromYAML(
-    "---\n"
-    "arch:      x86_64\n"
-    "file-type: MH_OBJECT\n"
-    "global-symbols:\n"
-    "  - name:   _main\n"
-    "    type:   N_SECT\n"
-    "    scope:  [ N_EXT ]\n"
-    "    sect:   1\n"
-    "    desc:   [ ]\n"
-    "    value:  0x100\n"
-    "...\n");
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64);
-  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
-  EXPECT_TRUE(f->sections.empty());
-  EXPECT_TRUE(f->localSymbols.empty());
-  EXPECT_TRUE(f->undefinedSymbols.empty());
-  EXPECT_EQ(f->globalSymbols.size(), 1UL);
-  const Symbol& sym = f->globalSymbols[0];
-  EXPECT_TRUE(sym.name.equals("_main"));
-  EXPECT_EQ((int)(sym.type), llvm::MachO::N_SECT);
-  EXPECT_EQ((int)(sym.scope), llvm::MachO::N_EXT);
-  EXPECT_EQ(sym.sect, 1);
-  EXPECT_EQ((int)(sym.desc), 0);
-  EXPECT_EQ((uint64_t)sym.value, 0x100ULL);
-}
-
-TEST(ObjectFileYAML, oneSection) {
-  std::unique_ptr<NormalizedFile> f = fromYAML(
-    "---\n"
-    "arch:      x86_64\n"
-    "file-type: MH_OBJECT\n"
-    "sections:\n"
-    "  - segment:     __TEXT\n"
-    "    section:     __text\n"
-    "    type:        S_REGULAR\n"
-    "    attributes:  [ S_ATTR_PURE_INSTRUCTIONS ]\n"
-    "    alignment:   2\n"
-    "    address:     0x12345678\n"
-    "    content:     [ 0x90, 0x90 ]\n"
-    "...\n");
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64);
-  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
-  EXPECT_TRUE(f->localSymbols.empty());
-  EXPECT_TRUE(f->globalSymbols.empty());
-  EXPECT_TRUE(f->undefinedSymbols.empty());
-  EXPECT_EQ(f->sections.size(), 1UL);
-  const Section& sect = f->sections[0];
-  EXPECT_TRUE(sect.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(sect.sectionName.equals("__text"));
-  EXPECT_EQ((uint32_t)(sect.type), (uint32_t)(llvm::MachO::S_REGULAR));
-  EXPECT_EQ((uint32_t)(sect.attributes),
-                            (uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS));
-  EXPECT_EQ((uint16_t)sect.alignment, 2U);
-  EXPECT_EQ((uint64_t)sect.address, 0x12345678ULL);
-  EXPECT_EQ(sect.content.size(), 2UL);
-  EXPECT_EQ((int)(sect.content[0]), 0x90);
-  EXPECT_EQ((int)(sect.content[1]), 0x90);
-}
-
-TEST(ObjectFileYAML, hello_x86_64) {
-  std::unique_ptr<NormalizedFile> f = fromYAML(
-    "---\n"
-    "arch:      x86_64\n"
-    "file-type: MH_OBJECT\n"
-    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
-    "sections:\n"
-    "  - segment:     __TEXT\n"
-    "    section:     __text\n"
-    "    type:        S_REGULAR\n"
-    "    attributes:  [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS]\n"
-    "    alignment:   1\n"
-    "    address:     0x0000\n"
-    "    content:     [ 0x55, 0x48, 0x89, 0xe5, 0x48, 0x8d, 0x3d, 0x00,\n"
-    "                   0x00, 0x00, 0x00, 0x30, 0xc0, 0xe8, 0x00, 0x00,\n"
-    "                   0x00, 0x00, 0x31, 0xc0, 0x5d, 0xc3 ]\n"
-    "    relocations:\n"
-    "     - offset:     0x0e\n"
-    "       type:       X86_64_RELOC_BRANCH\n"
-    "       length:     2\n"
-    "       pc-rel:     true\n"
-    "       extern:     true\n"
-    "       symbol:     2\n"
-    "     - offset:     0x07\n"
-    "       type:       X86_64_RELOC_SIGNED\n"
-    "       length:     2\n"
-    "       pc-rel:     true\n"
-    "       extern:     true\n"
-    "       symbol:     1\n"
-    "  - segment:     __TEXT\n"
-    "    section:     __cstring\n"
-    "    type:        S_CSTRING_LITERALS\n"
-    "    attributes:  [ ]\n"
-    "    alignment:   1\n"
-    "    address:     0x0016\n"
-    "    content:     [ 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x00 ]\n"
-    "global-symbols:\n"
-    "  - name:   _main\n"
-    "    type:   N_SECT\n"
-    "    scope:  [ N_EXT ]\n"
-    "    sect:   1\n"
-    "    value:  0x0\n"
-    "local-symbols:\n"
-    "  - name:   L_.str\n"
-    "    type:   N_SECT\n"
-    "    scope:  [ ]\n"
-    "    sect:   2\n"
-    "    value:  0x16\n"
-    "undefined-symbols:\n"
-    "  - name:   _printf\n"
-    "    type:   N_UNDF\n"
-    "    value:  0x0\n"
-    "...\n");
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64);
-  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
-  EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_EQ(f->sections.size(), 2UL);
-
-  const Section& sect1 = f->sections[0];
-  EXPECT_TRUE(sect1.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(sect1.sectionName.equals("__text"));
-  EXPECT_EQ((uint32_t)(sect1.type), (uint32_t)(llvm::MachO::S_REGULAR));
-  EXPECT_EQ((uint32_t)(sect1.attributes),
-                            (uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS
-                                     | llvm::MachO::S_ATTR_SOME_INSTRUCTIONS));
-  EXPECT_EQ((uint16_t)sect1.alignment, 1U);
-  EXPECT_EQ((uint64_t)sect1.address, 0x0ULL);
-  EXPECT_EQ(sect1.content.size(), 22UL);
-  EXPECT_EQ((int)(sect1.content[0]), 0x55);
-  EXPECT_EQ((int)(sect1.content[1]), 0x48);
-  EXPECT_EQ(sect1.relocations.size(), 2UL);
-  const Relocation& reloc1 = sect1.relocations[0];
-  EXPECT_EQ(reloc1.offset, 0x0eU);
-  EXPECT_FALSE(reloc1.scattered);
-  EXPECT_EQ((int)reloc1.type, (int)llvm::MachO::X86_64_RELOC_BRANCH);
-  EXPECT_EQ(reloc1.length, 2);
-  EXPECT_TRUE(reloc1.pcRel);
-  EXPECT_TRUE(reloc1.isExtern);
-  EXPECT_EQ(reloc1.symbol, 2U);
-  EXPECT_EQ((int)(reloc1.value), 0);
-  const Relocation& reloc2 = sect1.relocations[1];
-  EXPECT_EQ(reloc2.offset, 0x07U);
-  EXPECT_FALSE(reloc2.scattered);
-  EXPECT_EQ((int)reloc2.type, (int)llvm::MachO::X86_64_RELOC_SIGNED);
-  EXPECT_EQ(reloc2.length, 2);
-  EXPECT_TRUE(reloc2.pcRel);
-  EXPECT_TRUE(reloc2.isExtern);
-  EXPECT_EQ(reloc2.symbol, 1U);
-  EXPECT_EQ((int)(reloc2.value), 0);
-
-  const Section& sect2 = f->sections[1];
-  EXPECT_TRUE(sect2.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(sect2.sectionName.equals("__cstring"));
-  EXPECT_EQ((uint32_t)(sect2.type), (uint32_t)(llvm::MachO::S_CSTRING_LITERALS));
-  EXPECT_EQ((uint32_t)(sect2.attributes), 0U);
-  EXPECT_EQ((uint16_t)sect2.alignment, 1U);
-  EXPECT_EQ((uint64_t)sect2.address, 0x016ULL);
-  EXPECT_EQ(sect2.content.size(), 7UL);
-  EXPECT_EQ((int)(sect2.content[0]), 0x68);
-  EXPECT_EQ((int)(sect2.content[1]), 0x65);
-  EXPECT_EQ((int)(sect2.content[2]), 0x6c);
-
-  EXPECT_EQ(f->globalSymbols.size(), 1UL);
-  const Symbol& sym1 = f->globalSymbols[0];
-  EXPECT_TRUE(sym1.name.equals("_main"));
-  EXPECT_EQ((int)(sym1.type), llvm::MachO::N_SECT);
-  EXPECT_EQ((int)(sym1.scope), llvm::MachO::N_EXT);
-  EXPECT_EQ(sym1.sect, 1);
-  EXPECT_EQ((int)(sym1.desc), 0);
-  EXPECT_EQ((uint64_t)sym1.value, 0x0ULL);
-  EXPECT_EQ(f->localSymbols.size(), 1UL);
-  const Symbol& sym2 = f->localSymbols[0];
-  EXPECT_TRUE(sym2.name.equals("L_.str"));
-  EXPECT_EQ((int)(sym2.type), llvm::MachO::N_SECT);
-  EXPECT_EQ((int)(sym2.scope), 0);
-  EXPECT_EQ(sym2.sect, 2);
-  EXPECT_EQ((int)(sym2.desc), 0);
-  EXPECT_EQ((uint64_t)sym2.value, 0x16ULL);
-  EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
-  const Symbol& sym3 = f->undefinedSymbols[0];
-  EXPECT_TRUE(sym3.name.equals("_printf"));
-  EXPECT_EQ((int)(sym3.type), llvm::MachO::N_UNDF);
-  EXPECT_EQ((int)(sym3.scope), 0);
-  EXPECT_EQ(sym3.sect, 0);
-  EXPECT_EQ((int)(sym3.desc), 0);
-  EXPECT_EQ((uint64_t)sym3.value, 0x0ULL);
-}
-
-TEST(ObjectFileYAML, hello_x86) {
-  std::unique_ptr<NormalizedFile> f = fromYAML(
-    "---\n"
-    "arch:      x86\n"
-    "file-type: MH_OBJECT\n"
-    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
-    "sections:\n"
-    "  - segment:     __TEXT\n"
-    "    section:     __text\n"
-    "    type:        S_REGULAR\n"
-    "    attributes:  [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS]\n"
-    "    alignment:   1\n"
-    "    address:     0x0000\n"
-    "    content:     [ 0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0xe8, 0x00,\n"
-    "                   0x00, 0x00, 0x00, 0x58, 0x8d, 0x80, 0x16, 0x00,\n"
-    "                   0x00, 0x00, 0x89, 0x04, 0x24, 0xe8, 0xe6, 0xff,\n"
-    "                   0xff, 0xff, 0x31, 0xc0, 0x83, 0xc4, 0x08, 0x5d,\n"
-    "                   0xc3 ]\n"
-    "    relocations:\n"
-    "     - offset:     0x16\n"
-    "       type:       GENERIC_RELOC_VANILLA\n"
-    "       length:     2\n"
-    "       pc-rel:     true\n"
-    "       extern:     true\n"
-    "       symbol:     1\n"
-    "     - offset:     0x0e\n"
-    "       scattered:  true\n"
-    "       type:       GENERIC_RELOC_LOCAL_SECTDIFF\n"
-    "       length:     2\n"
-    "       pc-rel:     false\n"
-    "       value:      0x21\n"
-    "     - offset:     0x0\n"
-    "       scattered:  true\n"
-    "       type:       GENERIC_RELOC_PAIR\n"
-    "       length:     2\n"
-    "       pc-rel:     false\n"
-    "       value:      0xb\n"
-    "  - segment:     __TEXT\n"
-    "    section:     __cstring\n"
-    "    type:        S_CSTRING_LITERALS\n"
-    "    attributes:  [ ]\n"
-    "    alignment:   1\n"
-    "    address:     0x0021\n"
-    "    content:     [ 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x00 ]\n"
-    "global-symbols:\n"
-    "  - name:   _main\n"
-    "    type:   N_SECT\n"
-    "    scope:  [ N_EXT ]\n"
-    "    sect:   1\n"
-    "    value:  0x0\n"
-    "undefined-symbols:\n"
-    "  - name:   _printf\n"
-    "    type:   N_UNDF\n"
-    "    value:  0x0\n"
-    "...\n");
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86);
-  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
-  EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_EQ(f->sections.size(), 2UL);
-
-  const Section& sect1 = f->sections[0];
-  EXPECT_TRUE(sect1.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(sect1.sectionName.equals("__text"));
-  EXPECT_EQ((uint32_t)(sect1.type), (uint32_t)(llvm::MachO::S_REGULAR));
-  EXPECT_EQ((uint32_t)(sect1.attributes),
-                            (uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS
-                                     | llvm::MachO::S_ATTR_SOME_INSTRUCTIONS));
-  EXPECT_EQ((uint16_t)sect1.alignment, 1U);
-  EXPECT_EQ((uint64_t)sect1.address, 0x0ULL);
-  EXPECT_EQ(sect1.content.size(), 33UL);
-  EXPECT_EQ((int)(sect1.content[0]), 0x55);
-  EXPECT_EQ((int)(sect1.content[1]), 0x89);
-  EXPECT_EQ(sect1.relocations.size(), 3UL);
-  const Relocation& reloc1 = sect1.relocations[0];
-  EXPECT_EQ(reloc1.offset, 0x16U);
-  EXPECT_FALSE(reloc1.scattered);
-  EXPECT_EQ((int)reloc1.type, (int)llvm::MachO::GENERIC_RELOC_VANILLA);
-  EXPECT_EQ(reloc1.length, 2);
-  EXPECT_TRUE(reloc1.pcRel);
-  EXPECT_TRUE(reloc1.isExtern);
-  EXPECT_EQ(reloc1.symbol, 1U);
-  EXPECT_EQ((int)(reloc1.value), 0);
-  const Relocation& reloc2 = sect1.relocations[1];
-  EXPECT_EQ(reloc2.offset, 0x0eU);
-  EXPECT_TRUE(reloc2.scattered);
-  EXPECT_EQ((int)reloc2.type, (int)llvm::MachO::GENERIC_RELOC_LOCAL_SECTDIFF);
-  EXPECT_EQ(reloc2.length, 2);
-  EXPECT_FALSE(reloc2.pcRel);
-  EXPECT_EQ(reloc2.symbol, 0U);
-  EXPECT_EQ((int)(reloc2.value), 0x21);
-  const Relocation& reloc3 = sect1.relocations[2];
-  EXPECT_EQ(reloc3.offset, 0U);
-  EXPECT_TRUE(reloc3.scattered);
-  EXPECT_EQ((int)reloc3.type, (int)llvm::MachO::GENERIC_RELOC_PAIR);
-  EXPECT_EQ(reloc3.length, 2);
-  EXPECT_FALSE(reloc3.pcRel);
-  EXPECT_EQ(reloc3.symbol, 0U);
-  EXPECT_EQ((int)(reloc3.value), 0xb);
-
-  const Section& sect2 = f->sections[1];
-  EXPECT_TRUE(sect2.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(sect2.sectionName.equals("__cstring"));
-  EXPECT_EQ((uint32_t)(sect2.type), (uint32_t)(llvm::MachO::S_CSTRING_LITERALS));
-  EXPECT_EQ((uint32_t)(sect2.attributes), 0U);
-  EXPECT_EQ((uint16_t)sect2.alignment, 1U);
-  EXPECT_EQ((uint64_t)sect2.address, 0x021ULL);
-  EXPECT_EQ(sect2.content.size(), 7UL);
-  EXPECT_EQ((int)(sect2.content[0]), 0x68);
-  EXPECT_EQ((int)(sect2.content[1]), 0x65);
-  EXPECT_EQ((int)(sect2.content[2]), 0x6c);
-
-  EXPECT_EQ(f->globalSymbols.size(), 1UL);
-  const Symbol& sym1 = f->globalSymbols[0];
-  EXPECT_TRUE(sym1.name.equals("_main"));
-  EXPECT_EQ((int)(sym1.type), llvm::MachO::N_SECT);
-  EXPECT_EQ((int)(sym1.scope), llvm::MachO::N_EXT);
-  EXPECT_EQ(sym1.sect, 1);
-  EXPECT_EQ((int)(sym1.desc), 0);
-  EXPECT_EQ((uint64_t)sym1.value, 0x0ULL);
-  EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
-  const Symbol& sym2 = f->undefinedSymbols[0];
-  EXPECT_TRUE(sym2.name.equals("_printf"));
-  EXPECT_EQ((int)(sym2.type), llvm::MachO::N_UNDF);
-  EXPECT_EQ((int)(sym2.scope), 0);
-  EXPECT_EQ(sym2.sect, 0);
-  EXPECT_EQ((int)(sym2.desc), 0);
-  EXPECT_EQ((uint64_t)sym2.value, 0x0ULL);
-}
-
-TEST(ObjectFileYAML, hello_armv6) {
-  std::unique_ptr<NormalizedFile> f = fromYAML(
-    "---\n"
-    "arch:      armv6\n"
-    "file-type: MH_OBJECT\n"
-    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
-    "sections:\n"
-    "  - segment:     __TEXT\n"
-    "    section:     __text\n"
-    "    type:        S_REGULAR\n"
-    "    attributes:  [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS]\n"
-    "    alignment:   4\n"
-    "    address:     0x0000\n"
-    "    content:     [ 0x80, 0x40, 0x2d, 0xe9, 0x10, 0x00, 0x9f, 0xe5,\n"
-    "                   0x0d, 0x70, 0xa0, 0xe1, 0x00, 0x00, 0x8f, 0xe0,\n"
-    "                   0xfa, 0xff, 0xff, 0xeb, 0x00, 0x00, 0xa0, 0xe3,\n"
-    "                   0x80, 0x80, 0xbd, 0xe8, 0x0c, 0x00, 0x00, 0x00 ]\n"
-    "    relocations:\n"
-    "     - offset:     0x1c\n"
-    "       scattered:  true\n"
-    "       type:       ARM_RELOC_SECTDIFF\n"
-    "       length:     2\n"
-    "       pc-rel:     false\n"
-    "       value:      0x20\n"
-    "     - offset:     0x0\n"
-    "       scattered:  true\n"
-    "       type:       ARM_RELOC_PAIR\n"
-    "       length:     2\n"
-    "       pc-rel:     false\n"
-    "       value:      0xc\n"
-    "     - offset:     0x10\n"
-    "       type:       ARM_RELOC_BR24\n"
-    "       length:     2\n"
-    "       pc-rel:     true\n"
-    "       extern:     true\n"
-    "       symbol:     1\n"
-    "  - segment:     __TEXT\n"
-    "    section:     __cstring\n"
-    "    type:        S_CSTRING_LITERALS\n"
-    "    attributes:  [ ]\n"
-    "    alignment:   1\n"
-    "    address:     0x0020\n"
-    "    content:     [ 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x00 ]\n"
-    "global-symbols:\n"
-    "  - name:   _main\n"
-    "    type:   N_SECT\n"
-    "    scope:  [ N_EXT ]\n"
-    "    sect:   1\n"
-    "    value:  0x0\n"
-    "undefined-symbols:\n"
-    "  - name:   _printf\n"
-    "    type:   N_UNDF\n"
-    "    value:  0x0\n"
-    "...\n");
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv6);
-  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
-  EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_EQ(f->sections.size(), 2UL);
-
-  const Section& sect1 = f->sections[0];
-  EXPECT_TRUE(sect1.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(sect1.sectionName.equals("__text"));
-  EXPECT_EQ((uint32_t)(sect1.type), (uint32_t)(llvm::MachO::S_REGULAR));
-  EXPECT_EQ((uint32_t)(sect1.attributes),
-                            (uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS
-                                     | llvm::MachO::S_ATTR_SOME_INSTRUCTIONS));
-  EXPECT_EQ((uint16_t)sect1.alignment, 4U);
-  EXPECT_EQ((uint64_t)sect1.address, 0x0ULL);
-  EXPECT_EQ(sect1.content.size(), 32UL);
-  EXPECT_EQ((int)(sect1.content[0]), 0x80);
-  EXPECT_EQ((int)(sect1.content[1]), 0x40);
-  EXPECT_EQ(sect1.relocations.size(), 3UL);
-  const Relocation& reloc1 = sect1.relocations[0];
-  EXPECT_EQ(reloc1.offset, 0x1cU);
-  EXPECT_TRUE(reloc1.scattered);
-  EXPECT_EQ((int)reloc1.type, (int)llvm::MachO::ARM_RELOC_SECTDIFF);
-  EXPECT_EQ(reloc1.length, 2);
-  EXPECT_FALSE(reloc1.pcRel);
-  EXPECT_EQ(reloc1.symbol, 0U);
-  EXPECT_EQ((int)(reloc1.value), 0x20);
-  const Relocation& reloc2 = sect1.relocations[1];
-  EXPECT_EQ(reloc2.offset, 0x0U);
-  EXPECT_TRUE(reloc2.scattered);
-  EXPECT_EQ((int)reloc2.type, (int)llvm::MachO::ARM_RELOC_PAIR);
-  EXPECT_EQ(reloc2.length, 2);
-  EXPECT_FALSE(reloc2.pcRel);
-  EXPECT_EQ(reloc2.symbol, 0U);
-  EXPECT_EQ((int)(reloc2.value), 0xc);
-  const Relocation& reloc3 = sect1.relocations[2];
-  EXPECT_EQ(reloc3.offset, 0x10U);
-  EXPECT_FALSE(reloc3.scattered);
-  EXPECT_EQ((int)reloc3.type, (int)llvm::MachO::ARM_RELOC_BR24);
-  EXPECT_EQ(reloc3.length, 2);
-  EXPECT_TRUE(reloc3.pcRel);
-  EXPECT_TRUE(reloc3.isExtern);
-  EXPECT_EQ(reloc3.symbol, 1U);
-  EXPECT_EQ((int)(reloc3.value), 0);
-
-  const Section& sect2 = f->sections[1];
-  EXPECT_TRUE(sect2.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(sect2.sectionName.equals("__cstring"));
-  EXPECT_EQ((uint32_t)(sect2.type), (uint32_t)(llvm::MachO::S_CSTRING_LITERALS));
-  EXPECT_EQ((uint32_t)(sect2.attributes), 0U);
-  EXPECT_EQ((uint16_t)sect2.alignment, 1U);
-  EXPECT_EQ((uint64_t)sect2.address, 0x020ULL);
-  EXPECT_EQ(sect2.content.size(), 7UL);
-  EXPECT_EQ((int)(sect2.content[0]), 0x68);
-  EXPECT_EQ((int)(sect2.content[1]), 0x65);
-  EXPECT_EQ((int)(sect2.content[2]), 0x6c);
-
-  EXPECT_EQ(f->globalSymbols.size(), 1UL);
-  const Symbol& sym1 = f->globalSymbols[0];
-  EXPECT_TRUE(sym1.name.equals("_main"));
-  EXPECT_EQ((int)(sym1.type), llvm::MachO::N_SECT);
-  EXPECT_EQ((int)(sym1.scope), llvm::MachO::N_EXT);
-  EXPECT_EQ(sym1.sect, 1);
-  EXPECT_EQ((int)(sym1.desc), 0);
-  EXPECT_EQ((uint64_t)sym1.value, 0x0ULL);
-  EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
-  const Symbol& sym2 = f->undefinedSymbols[0];
-  EXPECT_TRUE(sym2.name.equals("_printf"));
-  EXPECT_EQ((int)(sym2.type), llvm::MachO::N_UNDF);
-  EXPECT_EQ((int)(sym2.scope), 0);
-  EXPECT_EQ(sym2.sect, 0);
-  EXPECT_EQ((int)(sym2.desc), 0);
-  EXPECT_EQ((uint64_t)sym2.value, 0x0ULL);
-}
-
-TEST(ObjectFileYAML, hello_armv7) {
-  std::unique_ptr<NormalizedFile> f = fromYAML(
-    "---\n"
-    "arch:      armv7\n"
-    "file-type: MH_OBJECT\n"
-    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
-    "sections:\n"
-    "  - segment:     __TEXT\n"
-    "    section:     __text\n"
-    "    type:        S_REGULAR\n"
-    "    attributes:  [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS]\n"
-    "    alignment:   2\n"
-    "    address:     0x0000\n"
-    "    content:     [ 0x80, 0xb5, 0x40, 0xf2, 0x06, 0x00, 0x6f, 0x46,\n"
-    "                   0xc0, 0xf2, 0x00, 0x00, 0x78, 0x44, 0xff, 0xf7,\n"
-    "                   0xf8, 0xef, 0x00, 0x20, 0x80, 0xbd ]\n"
-    "    relocations:\n"
-    "     - offset:     0x0e\n"
-    "       type:       ARM_THUMB_RELOC_BR22\n"
-    "       length:     2\n"
-    "       pc-rel:     true\n"
-    "       extern:     true\n"
-    "       symbol:     1\n"
-    "     - offset:     0x08\n"
-    "       scattered:  true\n"
-    "       type:       ARM_RELOC_HALF_SECTDIFF\n"
-    "       length:     3\n"
-    "       pc-rel:     false\n"
-    "       value:      0x16\n"
-    "     - offset:     0x06\n"
-    "       scattered:  true\n"
-    "       type:       ARM_RELOC_PAIR\n"
-    "       length:     3\n"
-    "       pc-rel:     false\n"
-    "       value:      0xc\n"
-    "     - offset:     0x02\n"
-    "       scattered:  true\n"
-    "       type:       ARM_RELOC_HALF_SECTDIFF\n"
-    "       length:     2\n"
-    "       pc-rel:     false\n"
-    "       value:      0x16\n"
-    "     - offset:     0x0\n"
-    "       scattered:  true\n"
-    "       type:       ARM_RELOC_PAIR\n"
-    "       length:     2\n"
-    "       pc-rel:     false\n"
-    "       value:      0xc\n"
-    "  - segment:     __TEXT\n"
-    "    section:     __cstring\n"
-    "    type:        S_CSTRING_LITERALS\n"
-    "    attributes:  [ ]\n"
-    "    alignment:   1\n"
-    "    address:     0x0016\n"
-    "    content:     [ 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x00 ]\n"
-    "global-symbols:\n"
-    "  - name:   _main\n"
-    "    type:   N_SECT\n"
-    "    scope:  [ N_EXT ]\n"
-    "    sect:   1\n"
-    "    desc:   [ N_ARM_THUMB_DEF ]\n"
-    "    value:  0x0\n"
-    "undefined-symbols:\n"
-    "  - name:   _printf\n"
-    "    type:   N_UNDF\n"
-    "    value:  0x0\n"
-    "...\n");
-  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv7);
-  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
-  EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
-  EXPECT_EQ(f->sections.size(), 2UL);
-
-  const Section& sect1 = f->sections[0];
-  EXPECT_TRUE(sect1.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(sect1.sectionName.equals("__text"));
-  EXPECT_EQ((uint32_t)(sect1.type), (uint32_t)(llvm::MachO::S_REGULAR));
-  EXPECT_EQ((uint32_t)(sect1.attributes),
-                            (uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS
-                                     | llvm::MachO::S_ATTR_SOME_INSTRUCTIONS));
-  EXPECT_EQ((uint16_t)sect1.alignment, 2U);
-  EXPECT_EQ((uint64_t)sect1.address, 0x0ULL);
-  EXPECT_EQ(sect1.content.size(), 22UL);
-  EXPECT_EQ((int)(sect1.content[0]), 0x80);
-  EXPECT_EQ((int)(sect1.content[1]), 0xb5);
-  EXPECT_EQ(sect1.relocations.size(), 5UL);
-  const Relocation& reloc1 = sect1.relocations[0];
-  EXPECT_EQ(reloc1.offset, 0x0eU);
-  EXPECT_FALSE(reloc1.scattered);
-  EXPECT_EQ((int)reloc1.type, (int)llvm::MachO::ARM_THUMB_RELOC_BR22);
-  EXPECT_EQ(reloc1.length, 2);
-  EXPECT_TRUE(reloc1.pcRel);
-  EXPECT_TRUE(reloc1.isExtern);
-  EXPECT_EQ(reloc1.symbol, 1U);
-  EXPECT_EQ((int)(reloc1.value), 0);
-  const Relocation& reloc2 = sect1.relocations[1];
-  EXPECT_EQ(reloc2.offset, 0x8U);
-  EXPECT_TRUE(reloc2.scattered);
-  EXPECT_EQ((int)reloc2.type, (int)llvm::MachO::ARM_RELOC_HALF_SECTDIFF);
-  EXPECT_EQ(reloc2.length, 3);
-  EXPECT_FALSE(reloc2.pcRel);
-  EXPECT_EQ(reloc2.symbol, 0U);
-  EXPECT_EQ((int)(reloc2.value), 0x16);
-  const Relocation& reloc3 = sect1.relocations[2];
-  EXPECT_EQ(reloc3.offset, 0x6U);
-  EXPECT_TRUE(reloc3.scattered);
-  EXPECT_EQ((int)reloc3.type, (int)llvm::MachO::ARM_RELOC_PAIR);
-  EXPECT_EQ(reloc3.length, 3);
-  EXPECT_FALSE(reloc3.pcRel);
-  EXPECT_EQ(reloc3.symbol, 0U);
-  EXPECT_EQ((int)(reloc3.value), 0xc);
-   const Relocation& reloc4 = sect1.relocations[3];
-  EXPECT_EQ(reloc4.offset, 0x2U);
-  EXPECT_TRUE(reloc4.scattered);
-  EXPECT_EQ((int)reloc4.type, (int)llvm::MachO::ARM_RELOC_HALF_SECTDIFF);
-  EXPECT_EQ(reloc4.length, 2);
-  EXPECT_FALSE(reloc4.pcRel);
-  EXPECT_EQ(reloc4.symbol, 0U);
-  EXPECT_EQ((int)(reloc4.value), 0x16);
-  const Relocation& reloc5 = sect1.relocations[4];
-  EXPECT_EQ(reloc5.offset, 0x0U);
-  EXPECT_TRUE(reloc5.scattered);
-  EXPECT_EQ((int)reloc5.type, (int)llvm::MachO::ARM_RELOC_PAIR);
-  EXPECT_EQ(reloc5.length, 2);
-  EXPECT_FALSE(reloc5.pcRel);
-  EXPECT_EQ(reloc5.symbol, 0U);
-  EXPECT_EQ((int)(reloc5.value), 0xc);
-
-  const Section& sect2 = f->sections[1];
-  EXPECT_TRUE(sect2.segmentName.equals("__TEXT"));
-  EXPECT_TRUE(sect2.sectionName.equals("__cstring"));
-  EXPECT_EQ((uint32_t)(sect2.type), (uint32_t)(llvm::MachO::S_CSTRING_LITERALS));
-  EXPECT_EQ((uint32_t)(sect2.attributes), 0U);
-  EXPECT_EQ((uint16_t)sect2.alignment, 1U);
-  EXPECT_EQ((uint64_t)sect2.address, 0x016ULL);
-  EXPECT_EQ(sect2.content.size(), 7UL);
-  EXPECT_EQ((int)(sect2.content[0]), 0x68);
-  EXPECT_EQ((int)(sect2.content[1]), 0x65);
-  EXPECT_EQ((int)(sect2.content[2]), 0x6c);
-
-  EXPECT_EQ(f->globalSymbols.size(), 1UL);
-  const Symbol& sym1 = f->globalSymbols[0];
-  EXPECT_TRUE(sym1.name.equals("_main"));
-  EXPECT_EQ((int)(sym1.type), llvm::MachO::N_SECT);
-  EXPECT_EQ((int)(sym1.scope), llvm::MachO::N_EXT);
-  EXPECT_EQ(sym1.sect, 1);
-  EXPECT_EQ((int)(sym1.desc), (int)(llvm::MachO::N_ARM_THUMB_DEF));
-  EXPECT_EQ((uint64_t)sym1.value, 0x0ULL);
-  EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
-  const Symbol& sym2 = f->undefinedSymbols[0];
-  EXPECT_TRUE(sym2.name.equals("_printf"));
-  EXPECT_EQ((int)(sym2.type), llvm::MachO::N_UNDF);
-  EXPECT_EQ((int)(sym2.scope), 0);
-  EXPECT_EQ(sym2.sect, 0);
-  EXPECT_EQ((int)(sym2.desc), 0);
-  EXPECT_EQ((uint64_t)sym2.value, 0x0ULL);
-}
diff --git a/gnu/llvm/lld/unittests/MachOTests/empty_obj_x86_armv7.txt b/gnu/llvm/lld/unittests/MachOTests/empty_obj_x86_armv7.txt
deleted file mode 100644 (file)
index 9d340cb..0000000
+++ /dev/null
@@ -1,1272 +0,0 @@
-0xca, 0xfe, 0xba, 0xbe, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x07, 0x00,
-0x00, 0x00, 0x03, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00,
-0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x40,
-0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0xcf, 0xfa, 0xed, 0xfe, 0x07, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00,
-0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00,
-0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x98, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
-0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x5f, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0xce, 0xfa, 0xed, 0xfe, 0x0c, 0x00, 0x00, 0x00, 0x09,
-0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00,
-0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00,
-0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x74,
-0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x5f, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00