[lld] eba30b3 - [ELF] Replace config-> with ctx.arg. in [IS]*.cpp

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Sat Sep 21 12:47:52 PDT 2024


Author: Fangrui Song
Date: 2024-09-21T12:47:47-07:00
New Revision: eba30b3370e1269ec9772e75c3818080cb1f272a

URL: https://github.com/llvm/llvm-project/commit/eba30b3370e1269ec9772e75c3818080cb1f272a
DIFF: https://github.com/llvm/llvm-project/commit/eba30b3370e1269ec9772e75c3818080cb1f272a.diff

LOG: [ELF] Replace config-> with ctx.arg. in [IS]*.cpp

Added: 
    

Modified: 
    lld/ELF/ICF.cpp
    lld/ELF/InputFiles.cpp
    lld/ELF/InputFiles.h
    lld/ELF/InputSection.cpp
    lld/ELF/SymbolTable.cpp
    lld/ELF/Symbols.cpp
    lld/ELF/Symbols.h
    lld/ELF/SyntheticSections.cpp
    lld/ELF/SyntheticSections.h

Removed: 
    


################################################################################
diff  --git a/lld/ELF/ICF.cpp b/lld/ELF/ICF.cpp
index 952e4dfe982c80..9caff0bbe2b630 100644
--- a/lld/ELF/ICF.cpp
+++ b/lld/ELF/ICF.cpp
@@ -242,7 +242,7 @@ bool ICF<ELFT>::constantEq(const InputSection *secA, Relocs<RelTy> ra,
   auto rai = ra.begin(), rae = ra.end(), rbi = rb.begin();
   for (; rai != rae; ++rai, ++rbi) {
     if (rai->r_offset != rbi->r_offset ||
-        rai->getType(config->isMips64EL) != rbi->getType(config->isMips64EL))
+        rai->getType(ctx.arg.isMips64EL) != rbi->getType(ctx.arg.isMips64EL))
       return false;
 
     uint64_t addA = getAddend<ELFT>(*rai);
@@ -458,7 +458,7 @@ static void combineRelocHashes(unsigned cnt, InputSection *isec,
 }
 
 static void print(const Twine &s) {
-  if (config->printIcfSections)
+  if (ctx.arg.printIcfSections)
     message(s);
 }
 
@@ -467,7 +467,7 @@ template <class ELFT> void ICF<ELFT>::run() {
   // Compute isPreemptible early. We may add more symbols later, so this loop
   // cannot be merged with the later computeIsPreemptible() pass which is used
   // by scanRelocations().
-  if (config->hasDynSymTab)
+  if (ctx.arg.hasDynSymTab)
     for (Symbol *sym : symtab.getSymbols())
       sym->isPreemptible = computeIsPreemptible(*sym);
 

diff  --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 3f5f29591d2374..07a32a5ccea436 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -135,10 +135,10 @@ static void updateARMVFPArgs(const ARMAttributeParser &attributes,
     return;
   }
   // Follow ld.bfd and error if there is a mix of calling conventions.
-  if (config->armVFPArgs != arg && config->armVFPArgs != ARMVFPArgKind::Default)
+  if (ctx.arg.armVFPArgs != arg && ctx.arg.armVFPArgs != ARMVFPArgKind::Default)
     error(toString(f) + ": incompatible Tag_ABI_VFP_args");
   else
-    config->armVFPArgs = arg;
+    ctx.arg.armVFPArgs = arg;
 }
 
 // The ARM support in lld makes some use of instructions that are not available
@@ -168,19 +168,19 @@ static void updateSupportedARMFeatures(const ARMAttributeParser &attributes) {
   case ARMBuildAttrs::v6:
   case ARMBuildAttrs::v6KZ:
   case ARMBuildAttrs::v6K:
-    config->armHasBlx = true;
+    ctx.arg.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;
+    ctx.arg.armHasBlx = true;
+    ctx.arg.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;
+      ctx.arg.armHasMovtMovw = true;
     break;
   }
 
@@ -191,7 +191,7 @@ static void updateSupportedARMFeatures(const ARMAttributeParser &attributes) {
     return;
   if (arch >= ARMBuildAttrs::CPUArch::v8_M_Base &&
       profile == ARMBuildAttrs::MicroControllerProfile)
-    config->armCMSESupport = true;
+    ctx.arg.armCMSESupport = true;
 
   // The thumb PLT entries require Thumb2 which can be used on multiple archs.
   // For now, let's limit it to ones where ARM isn't available and we know have
@@ -200,8 +200,8 @@ static void updateSupportedARMFeatures(const ARMAttributeParser &attributes) {
       attributes.getAttributeValue(ARMBuildAttrs::ARM_ISA_use);
   std::optional<unsigned> thumb =
       attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use);
-  config->armHasArmISA |= armISA && *armISA >= ARMBuildAttrs::Allowed;
-  config->armHasThumb2ISA |= thumb && *thumb >= ARMBuildAttrs::AllowThumb32;
+  ctx.arg.armHasArmISA |= armISA && *armISA >= ARMBuildAttrs::Allowed;
+  ctx.arg.armHasThumb2ISA |= thumb && *thumb >= ARMBuildAttrs::AllowThumb32;
 }
 
 InputFile::InputFile(Kind k, MemoryBufferRef m)
@@ -217,16 +217,16 @@ std::optional<MemoryBufferRef> elf::readFile(StringRef 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.starts_with("/"))
-    path = saver().save(config->chroot + path);
+  if (!ctx.arg.chroot.empty() && path.starts_with("/"))
+    path = saver().save(ctx.arg.chroot + path);
 
   bool remapped = false;
-  auto it = config->remapInputs.find(path);
-  if (it != config->remapInputs.end()) {
+  auto it = ctx.arg.remapInputs.find(path);
+  if (it != ctx.arg.remapInputs.end()) {
     path = it->second;
     remapped = true;
   } else {
-    for (const auto &[pat, toFile] : config->remapInputsWildcards) {
+    for (const auto &[pat, toFile] : ctx.arg.remapInputsWildcards) {
       if (pat.match(path)) {
         path = toFile;
         remapped = true;
@@ -244,7 +244,7 @@ std::optional<MemoryBufferRef> elf::readFile(StringRef path) {
   }
 
   log(path);
-  config->dependencyFiles.insert(llvm::CachedHashString(path));
+  ctx.arg.dependencyFiles.insert(llvm::CachedHashString(path));
 
   auto mbOrErr = MemoryBuffer::getFile(path, /*IsText=*/false,
                                        /*RequiresNullTerminator=*/false);
@@ -268,15 +268,15 @@ static bool isCompatible(InputFile *file) {
   if (!file->isElf() && !isa<BitcodeFile>(file))
     return true;
 
-  if (file->ekind == config->ekind && file->emachine == config->emachine) {
-    if (config->emachine != EM_MIPS)
+  if (file->ekind == ctx.arg.ekind && file->emachine == ctx.arg.emachine) {
+    if (ctx.arg.emachine != EM_MIPS)
       return true;
-    if (isMipsN32Abi(file) == config->mipsN32Abi)
+    if (isMipsN32Abi(file) == ctx.arg.mipsN32Abi)
       return true;
   }
 
   StringRef target =
-      !config->bfdname.empty() ? config->bfdname : config->emulation;
+      !ctx.arg.bfdname.empty() ? ctx.arg.bfdname : ctx.arg.emulation;
   if (!target.empty()) {
     error(toString(file) + " is incompatible with " + target);
     return false;
@@ -311,7 +311,7 @@ template <class ELFT> static void doParseFile(InputFile *file) {
     return;
   }
 
-  if (config->trace)
+  if (ctx.arg.trace)
     message(toString(file));
 
   if (file->kind() == InputFile::ObjKind) {
@@ -419,7 +419,7 @@ StringRef InputFile::getNameForScript() const {
 // 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)
+  if (!ctx.arg.dependentLibraries)
     return;
   if (std::optional<std::string> s = searchLibraryBaseName(specifier))
     ctx.driver.addFile(saver().save(*s), /*withLOption=*/true);
@@ -599,7 +599,7 @@ template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) {
   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) {
+    if (sec.sh_type == SHT_LLVM_DEPENDENT_LIBRARIES && !ctx.arg.relocatable) {
       StringRef name = check(obj.getSectionName(sec, shstrtab));
       ArrayRef<char> data = CHECK(
           this->getObj().template getSectionContentsAsArray<char>(sec), this);
@@ -619,7 +619,7 @@ template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) {
       continue;
     }
 
-    if (sec.sh_type == SHT_ARM_ATTRIBUTES && config->emachine == EM_ARM) {
+    if (sec.sh_type == SHT_ARM_ATTRIBUTES && ctx.arg.emachine == EM_ARM) {
       ARMAttributeParser attributes;
       ArrayRef<uint8_t> contents =
           check(this->getObj().getSectionContents(sec));
@@ -672,7 +672,7 @@ template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) {
         symtab.comdatGroups.try_emplace(CachedHashStringRef(signature), this)
             .second;
     if (keepGroup) {
-      if (!config->resolveGroups)
+      if (!ctx.arg.resolveGroups)
         this->sections[i] = createInputSection(
             i, sec, check(obj.getSectionName(sec, shstrtab)));
       continue;
@@ -718,7 +718,7 @@ bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &sec, StringRef name) {
   // SHF_MERGE sections based both on their name and sh_entsize, but that seems
   // to be more trouble than it is worth. Instead, we just use the regular (-O1)
   // logic for -r.
-  if (config->optimize == 0 && !config->relocatable)
+  if (ctx.arg.optimize == 0 && !ctx.arg.relocatable)
     return false;
 
   // A mergeable section with size 0 is useless because they don't have
@@ -786,7 +786,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
     // 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_flags & SHF_EXCLUDE) && !ctx.arg.relocatable) {
       if (type == SHT_LLVM_CALL_GRAPH_PROFILE)
         cgProfileSectionIndex = i;
       if (type == SHT_LLVM_ADDRSIG) {
@@ -796,7 +796,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
         // in the address-significance table, which refers to symbols by index.
         if (sec.sh_link != 0)
           this->addrsigSec = &sec;
-        else if (config->icf == ICFLevel::Safe)
+        else if (ctx.arg.icf == ICFLevel::Safe)
           warn(toString(this) +
                ": --icf=safe conservatively ignores "
                "SHT_LLVM_ADDRSIG [index " +
@@ -810,7 +810,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
 
     switch (type) {
     case SHT_GROUP: {
-      if (!config->relocatable)
+      if (!ctx.arg.relocatable)
         sections[i] = &InputSection::discarded;
       StringRef signature =
           cantFail(this->getELFSyms<ELFT>()[sec.sh_info].getName(stringTable));
@@ -846,7 +846,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
       // The concatenated output does not properly reflect the linking
       // semantics. In addition, since we do not use the bitcode wrapper format,
       // the concatenated raw bitcode would be invalid.
-      if (config->relocatable && !config->fatLTOObjects) {
+      if (ctx.arg.relocatable && !ctx.arg.fatLTOObjects) {
         sections[i] = &InputSection::discarded;
         break;
       }
@@ -856,7 +856,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
           createInputSection(i, sec, check(obj.getSectionName(sec, shstrtab)));
       if (type == SHT_LLVM_SYMPART)
         ctx.hasSympart.store(true, std::memory_order_relaxed);
-      else if (config->rejectMismatch &&
+      else if (ctx.arg.rejectMismatch &&
                !isKnownSpecificSectionType(type, sec.sh_flags))
         errorOrWarn(toString(this->sections[i]) + ": unknown section type 0x" +
                     Twine::utohexstr(type));
@@ -909,7 +909,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
       // `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) {
+      if (ctx.arg.copyRelocs) {
         auto *isec = makeThreadLocal<InputSection>(
             *this, sec, check(obj.getSectionName(sec, shstrtab)));
         // If the relocated section is discarded (due to /DISCARD/ or
@@ -973,7 +973,7 @@ void readGnuProperty(const InputSection &sec, ObjFile<ELFT> &f) {
       continue;
     }
 
-    uint32_t featureAndType = config->emachine == EM_AARCH64
+    uint32_t featureAndType = ctx.arg.emachine == EM_AARCH64
                                   ? GNU_PROPERTY_AARCH64_FEATURE_1_AND
                                   : GNU_PROPERTY_X86_FEATURE_1_AND;
 
@@ -996,7 +996,7 @@ void readGnuProperty(const InputSection &sec, ObjFile<ELFT> &f) {
         if (size < 4)
           reportFatal(place, "FEATURE_1_AND entry is too short");
         f.andFeatures |= read32<ELFT::Endianness>(desc.data());
-      } else if (config->emachine == EM_AARCH64 &&
+      } else if (ctx.arg.emachine == EM_AARCH64 &&
                  type == GNU_PROPERTY_AARCH64_FEATURE_PAUTH) {
         if (!f.aarch64PauthAbiCoreInfo.empty()) {
           reportFatal(data.data(),
@@ -1080,7 +1080,7 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(uint32_t idx,
     // 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) {
+      if (ctx.arg.relocatable) {
         error(
             "cannot mix split-stack and non-split-stack in a relocatable link");
         return &InputSection::discarded;
@@ -1109,7 +1109,7 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(uint32_t idx,
   // 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)
+  if (name == ".eh_frame" && !ctx.arg.relocatable)
     return makeThreadLocal<EhInputSection>(*this, sec, name);
 
   if ((sec.sh_flags & SHF_MERGE) && shouldMerge(sec, name))
@@ -1358,7 +1358,7 @@ unsigned SharedFile::vernauxNum;
 
 SharedFile::SharedFile(MemoryBufferRef m, StringRef defaultSoName)
     : ELFFileBase(SharedKind, getELFKind(m, ""), m), soName(defaultSoName),
-      isNeeded(!config->asNeeded) {}
+      isNeeded(!ctx.arg.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
@@ -1578,7 +1578,7 @@ template <class ELFT> void SharedFile::parse() {
           Undefined{this, name, sym.getBinding(), sym.st_other, sym.getType()});
       s->exportDynamic = true;
       if (sym.getBinding() != STB_WEAK &&
-          config->unresolvedSymbolsInShlib != UnresolvedPolicy::Ignore)
+          ctx.arg.unresolvedSymbolsInShlib != UnresolvedPolicy::Ignore)
         requiredSymbols.push_back(s);
       continue;
     }
@@ -1588,7 +1588,7 @@ template <class ELFT> void SharedFile::parse() {
       // 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")
+      if (ctx.arg.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 " +
@@ -1702,7 +1702,7 @@ BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
   this->lazy = lazy;
 
   std::string path = mb.getBufferIdentifier().str();
-  if (config->thinLTOIndexOnly)
+  if (ctx.arg.thinLTOIndexOnly)
     path = replaceThinLTOSuffix(mb.getBufferIdentifier());
 
   // ThinLTO assumes that all MemoryBufferRefs given to it have a unique
@@ -1917,7 +1917,7 @@ bool InputFile::shouldExtractForCommon(StringRef name) const {
 }
 
 std::string elf::replaceThinLTOSuffix(StringRef path) {
-  auto [suffix, repl] = config->thinLTOObjectSuffixReplace;
+  auto [suffix, repl] = ctx.arg.thinLTOObjectSuffixReplace;
   if (path.consume_back(suffix))
     return (path + repl).str();
   return std::string(path);

diff  --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h
index b0a74877d0aaeb..4e777761e143b1 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -105,7 +105,7 @@ class InputFile {
   }
 
   template <typename RelT> Symbol &getRelocTargetSym(const RelT &rel) const {
-    uint32_t symIndex = rel.getSymbol(config->isMips64EL);
+    uint32_t symIndex = rel.getSymbol(ctx.arg.isMips64EL);
     return getSymbol(symIndex);
   }
 

diff  --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 363afe36c2449e..12c4a622ebba8e 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -79,7 +79,7 @@ InputSectionBase::InputSectionBase(InputFile *file, uint64_t flags,
 // --force-group-allocation, the SHF_GROUP flag and section groups are retained.
 static uint64_t getFlags(uint64_t flags) {
   flags &= ~(uint64_t)SHF_INFO_LINK;
-  if (config->resolveGroups)
+  if (ctx.arg.resolveGroups)
     flags &= ~(uint64_t)SHF_GROUP;
   return flags;
 }
@@ -298,7 +298,7 @@ std::string InputSectionBase::getLocation(uint64_t offset) const {
 
   // We don't have file for synthetic sections.
   if (file == nullptr)
-    return (config->outputFile + ":(" + secAndOffset).str();
+    return (ctx.arg.outputFile + ":(" + secAndOffset).str();
 
   std::string filename = toString(file);
   if (Defined *d = getEnclosingFunction(offset))
@@ -398,8 +398,8 @@ InputSectionBase *InputSection::getRelocatedSection() const {
 
 template <class ELFT, class RelTy>
 void InputSection::copyRelocations(uint8_t *buf) {
-  if (config->relax && !config->relocatable &&
-      (config->emachine == EM_RISCV || config->emachine == EM_LOONGARCH)) {
+  if (ctx.arg.relax && !ctx.arg.relocatable &&
+      (ctx.arg.emachine == EM_RISCV || ctx.arg.emachine == EM_LOONGARCH)) {
     // On LoongArch and RISC-V, relaxation might change relocations: copy
     // from internal ones that are updated by relaxation.
     InputSectionBase *sec = getRelocatedSection();
@@ -412,7 +412,7 @@ void InputSection::copyRelocations(uint8_t *buf) {
       const ObjFile<ELFT> &file;
       Relocation operator()(const RelTy &rel) const {
         // RelExpr is not used so set to a dummy value.
-        return Relocation{R_NONE, rel.getType(config->isMips64EL), rel.r_offset,
+        return Relocation{R_NONE, rel.getType(ctx.arg.isMips64EL), rel.r_offset,
                           getAddend<ELFT>(rel), &file.getRelocTargetSym(rel)};
       }
     };
@@ -453,7 +453,7 @@ void InputSection::copyRelocations(uint8_t *buf,
     // section, but for --emit-relocs it is a virtual address.
     p->r_offset = sec->getVA(rel.offset);
     p->setSymbolAndType(ctx.in.symTab->getSymbolIndex(sym), type,
-                        config->isMips64EL);
+                        ctx.arg.isMips64EL);
 
     if (sym.type == STT_SECTION) {
       // We combine multiple section symbols into only one per
@@ -490,7 +490,7 @@ void InputSection::copyRelocations(uint8_t *buf,
       if (!RelTy::HasAddend)
         addend = target.getImplicitAddend(bufLoc, type);
 
-      if (config->emachine == EM_MIPS &&
+      if (ctx.arg.emachine == EM_MIPS &&
           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
@@ -513,10 +513,10 @@ void InputSection::copyRelocations(uint8_t *buf,
       // writeSections will update the implicit addend. Non-SHF_ALLOC sections
       // utilize relocateNonAlloc to process raw relocations and do not need
       // this sec->relocations change.
-      else if (config->relocatable && (sec->flags & SHF_ALLOC) &&
+      else if (ctx.arg.relocatable && (sec->flags & SHF_ALLOC) &&
                type != target.noneRel)
         sec->addReloc({R_ABS, type, rel.offset, addend, &sym});
-    } else if (config->emachine == EM_PPC && type == R_PPC_PLTREL24 &&
+    } else if (ctx.arg.emachine == EM_PPC && type == R_PPC_PLTREL24 &&
                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
@@ -682,12 +682,12 @@ static int64_t getTlsTpOffset(const Symbol &s) {
   PhdrEntry *tls = ctx.tlsPhdr;
   if (!tls) // Reported an error in getSymVA
     return 0;
-  switch (config->emachine) {
+  switch (ctx.arg.emachine) {
     // Variant 1.
   case EM_ARM:
   case EM_AARCH64:
-    return s.getVA(0) + config->wordsize * 2 +
-           ((tls->p_vaddr - config->wordsize * 2) & (tls->p_align - 1));
+    return s.getVA(0) + ctx.arg.wordsize * 2 +
+           ((tls->p_vaddr - ctx.arg.wordsize * 2) & (tls->p_align - 1));
   case EM_MIPS:
   case EM_PPC:
   case EM_PPC64:
@@ -845,13 +845,13 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
       // 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)
+      if (ctx.arg.emachine == EM_ARM)
         dest = getARMUndefinedRelativeWeakVA(type, a, p);
-      else if (config->emachine == EM_AARCH64)
+      else if (ctx.arg.emachine == EM_AARCH64)
         dest = getAArch64UndefinedRelativeWeakVA(type, p) + a;
-      else if (config->emachine == EM_PPC)
+      else if (ctx.arg.emachine == EM_PPC)
         dest = p;
-      else if (config->emachine == EM_RISCV)
+      else if (ctx.arg.emachine == EM_RISCV)
         dest = getRISCVUndefinedRelativeWeakVA(type, p) + a;
       else
         dest = sym.getVA(a);
@@ -958,7 +958,7 @@ template <class ELFT, class RelTy>
 void InputSection::relocateNonAlloc(uint8_t *buf, Relocs<RelTy> rels) {
   const unsigned bits = sizeof(typename ELFT::uint) * 8;
   const TargetInfo &target = *elf::ctx.target;
-  const auto emachine = config->emachine;
+  const auto emachine = ctx.arg.emachine;
   const bool isDebug = isDebugSection(*this);
   const bool isDebugLine = isDebug && name == ".debug_line";
   std::optional<uint64_t> tombstone;
@@ -970,7 +970,7 @@ void InputSection::relocateNonAlloc(uint8_t *buf, Relocs<RelTy> rels) {
     else
       tombstone = 0;
   }
-  for (const auto &patAndValue : llvm::reverse(config->deadRelocInNonAlloc))
+  for (const auto &patAndValue : llvm::reverse(ctx.arg.deadRelocInNonAlloc))
     if (patAndValue.first.match(this->name)) {
       tombstone = patAndValue.second;
       break;
@@ -979,7 +979,7 @@ void InputSection::relocateNonAlloc(uint8_t *buf, Relocs<RelTy> rels) {
   const InputFile *f = this->file;
   for (auto it = rels.begin(), end = rels.end(); it != end; ++it) {
     const RelTy &rel = *it;
-    const RelType type = rel.getType(config->isMips64EL);
+    const RelType type = rel.getType(ctx.arg.isMips64EL);
     const uint64_t offset = rel.r_offset;
     uint8_t *bufLoc = buf + offset;
     int64_t addend = getAddend<ELFT>(rel);
@@ -1060,7 +1060,7 @@ void InputSection::relocateNonAlloc(uint8_t *buf, Relocs<RelTy> rels) {
     // explicit addend, such as RELA, remain unchanged and we can stop here.
     // While content relocated by relocation types with an implicit addend, such
     // as REL, needs the implicit addend updated.
-    if (config->relocatable && (RelTy::HasAddend || sym.type != STT_SECTION))
+    if (ctx.arg.relocatable && (RelTy::HasAddend || sym.type != STT_SECTION))
       continue;
 
     // R_ABS/R_DTPREL and some other relocations can be used from non-SHF_ALLOC
@@ -1371,7 +1371,7 @@ static size_t findNull(StringRef s, size_t entSize) {
 // Split SHF_STRINGS section. Such section is a sequence of
 // null-terminated strings.
 void MergeInputSection::splitStrings(StringRef s, size_t entSize) {
-  const bool live = !(flags & SHF_ALLOC) || !config->gcSections;
+  const bool live = !(flags & SHF_ALLOC) || !ctx.arg.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");
@@ -1397,7 +1397,7 @@ void MergeInputSection::splitNonStrings(ArrayRef<uint8_t> data,
                                         size_t entSize) {
   size_t size = data.size();
   assert((size % entSize) == 0);
-  const bool live = !(flags & SHF_ALLOC) || !config->gcSections;
+  const bool live = !(flags & SHF_ALLOC) || !ctx.arg.gcSections;
 
   pieces.resize_for_overwrite(size / entSize);
   for (size_t i = 0, j = 0; i != size; i += entSize, j++)

diff  --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index 258a78ab40bb57..4a4b4d3deed409 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -198,7 +198,7 @@ SmallVector<Symbol *, 0> SymbolTable::findAllByVersion(SymbolVersion ver,
 
 void SymbolTable::handleDynamicList() {
   SmallVector<Symbol *, 0> syms;
-  for (SymbolVersion &ver : config->dynamicList) {
+  for (SymbolVersion &ver : ctx.arg.dynamicList) {
     if (ver.hasWildcard)
       syms = findAllByVersion(ver, /*includeNonDefault=*/true);
     else
@@ -222,7 +222,7 @@ bool SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
       return "VER_NDX_LOCAL";
     if (ver == VER_NDX_GLOBAL)
       return "VER_NDX_GLOBAL";
-    return ("version '" + config->versionDefinitions[ver].name + "'").str();
+    return ("version '" + ctx.arg.versionDefinitions[ver].name + "'").str();
   };
 
   // Assign the version.
@@ -269,7 +269,7 @@ void SymbolTable::scanVersionScript() {
   SmallString<128> buf;
   // First, we assign versions to exact matching symbols,
   // i.e. version definitions not containing any glob meta-characters.
-  for (VersionDefinition &v : config->versionDefinitions) {
+  for (VersionDefinition &v : ctx.arg.versionDefinitions) {
     auto assignExact = [&](SymbolVersion pat, uint16_t id, StringRef ver) {
       bool found =
           assignExactVersion(pat, id, ver, /*includeNonDefault=*/false);
@@ -277,7 +277,7 @@ void SymbolTable::scanVersionScript() {
       found |= assignExactVersion({(pat.name + "@" + v.name).toStringRef(buf),
                                    pat.isExternCpp, /*hasWildCard=*/false},
                                   id, ver, /*includeNonDefault=*/true);
-      if (!found && !config->undefinedVersion)
+      if (!found && !ctx.arg.undefinedVersion)
         errorOrWarn("version script assignment of '" + ver + "' to symbol '" +
                     pat.name + "' failed: symbol not defined");
     };
@@ -300,7 +300,7 @@ void SymbolTable::scanVersionScript() {
                           id,
                           /*includeNonDefault=*/true);
   };
-  for (VersionDefinition &v : llvm::reverse(config->versionDefinitions)) {
+  for (VersionDefinition &v : llvm::reverse(ctx.arg.versionDefinitions)) {
     for (SymbolVersion &pat : v.nonLocalPatterns)
       if (pat.hasWildcard && pat.name != "*")
         assignWildcard(pat, v.id, v.name);
@@ -311,7 +311,7 @@ void SymbolTable::scanVersionScript() {
 
   // Then, assign versions to "*". In GNU linkers they have lower priority than
   // other wildcards.
-  for (VersionDefinition &v : llvm::reverse(config->versionDefinitions)) {
+  for (VersionDefinition &v : llvm::reverse(ctx.arg.versionDefinitions)) {
     for (SymbolVersion &pat : v.nonLocalPatterns)
       if (pat.hasWildcard && pat.name == "*")
         assignWildcard(pat, v.id, v.name);

diff  --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index cd3fdce06f7788..65283adf4e5052 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -45,7 +45,7 @@ LLVM_ATTRIBUTE_UNUSED static inline void assertSymbols() {
 
 // Returns a symbol for an error message.
 static std::string maybeDemangleSymbol(StringRef symName) {
-  return elf::config->demangle ? demangle(symName.str()) : symName.str();
+  return elf::ctx.arg.demangle ? demangle(symName.str()) : symName.str();
 }
 
 std::string lld::toString(const elf::Symbol &sym) {
@@ -109,11 +109,11 @@ static uint64_t getSymVA(const Symbol &sym, int64_t addend) {
     // a symbol value as-is (.dynamic section, `Elf_Ehdr::e_entry`
     // 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() &&
+    if (ctx.arg.emachine == EM_MIPS && isMicroMips() &&
         ((sym.stOther & STO_MIPS_MICROMIPS) || sym.hasFlag(NEEDS_COPY)))
       va |= 1;
 
-    if (d.isTls() && !config->relocatable) {
+    if (d.isTls() && !ctx.arg.relocatable) {
       // Use the address of the TLS segment's first section rather than the
       // segment's address, because segment addresses aren't initialized until
       // after sections are finalized. (e.g. Measuring the size of .rela.dyn
@@ -177,7 +177,7 @@ uint64_t Symbol::getPltVA() const {
   // While linking microMIPS code PLT code are always microMIPS
   // code. Set the less-significant bit to track that fact.
   // See detailed comment in the `getSymVA` function.
-  if (config->emachine == EM_MIPS && isMicroMips())
+  if (ctx.arg.emachine == EM_MIPS && isMicroMips())
     outVA |= 1;
   return outVA;
 }
@@ -242,7 +242,7 @@ void Symbol::parseSymbolVersion() {
   // so we do not report error in this case. We also do not error
   // if the symbol has a local version as it won't be in the dynamic
   // symbol table.
-  if (config->shared && versionId != VER_NDX_LOCAL)
+  if (ctx.arg.shared && versionId != VER_NDX_LOCAL)
     error(toString(file) + ": symbol " + s + " has undefined version " +
           verstr);
 }
@@ -258,7 +258,7 @@ uint8_t Symbol::computeBinding() const {
   auto v = visibility();
   if ((v != STV_DEFAULT && v != STV_PROTECTED) || versionId == VER_NDX_LOCAL)
     return STB_LOCAL;
-  if (binding == STB_GNU_UNIQUE && !config->gnuUnique)
+  if (binding == STB_GNU_UNIQUE && !ctx.arg.gnuUnique)
     return STB_GLOBAL;
   return binding;
 }
@@ -271,7 +271,7 @@ 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 !(isUndefWeak() && config->noDynamicLinker);
+    return !(isUndefWeak() && ctx.arg.noDynamicLinker);
 
   return exportDynamic || inDynamicList;
 }
@@ -299,7 +299,7 @@ static void recordWhyExtract(const InputFile *reference,
 }
 
 void elf::maybeWarnUnorderableSymbol(const Symbol *sym) {
-  if (!config->warnSymbolOrdering)
+  if (!ctx.arg.warnSymbolOrdering)
     return;
 
   // If UnresolvedPolicy::Ignore is used, no "undefined symbol" error/warning is
@@ -309,7 +309,7 @@ void elf::maybeWarnUnorderableSymbol(const Symbol *sym) {
   // Note, ld.bfd --symbol-ordering-file= does not warn on undefined symbols,
   // but we don't have to be compatible here.
   if (sym->isUndefined() && !cast<Undefined>(sym)->discardedSecIdx &&
-      config->unresolvedSymbols == UnresolvedPolicy::Ignore)
+      ctx.arg.unresolvedSymbols == UnresolvedPolicy::Ignore)
     return;
 
   const InputFile *file = sym->file;
@@ -347,18 +347,18 @@ bool elf::computeIsPreemptible(const Symbol &sym) {
   if (!sym.isDefined())
     return true;
 
-  if (!config->shared)
+  if (!ctx.arg.shared)
     return false;
 
   // If -Bsymbolic or --dynamic-list is specified, or -Bsymbolic-functions is
   // specified and the symbol is STT_FUNC, the symbol is preemptible iff it is
   // in the dynamic list. -Bsymbolic-non-weak-functions is a non-weak subset of
   // -Bsymbolic-functions.
-  if (config->symbolic ||
-      (config->bsymbolic == BsymbolicKind::NonWeak &&
+  if (ctx.arg.symbolic ||
+      (ctx.arg.bsymbolic == BsymbolicKind::NonWeak &&
        sym.binding != STB_WEAK) ||
-      (config->bsymbolic == BsymbolicKind::Functions && sym.isFunc()) ||
-      (config->bsymbolic == BsymbolicKind::NonWeakFunctions && sym.isFunc() &&
+      (ctx.arg.bsymbolic == BsymbolicKind::Functions && sym.isFunc()) ||
+      (ctx.arg.bsymbolic == BsymbolicKind::NonWeakFunctions && sym.isFunc() &&
        sym.binding != STB_WEAK))
     return sym.inDynamicList;
   return true;
@@ -458,11 +458,11 @@ void Symbol::resolve(const Undefined &other) {
     // A forms group 0. B form group 1. C and D (including their member object
     // files) form group 2. E forms group 3. I think that you can see how this
     // group assignment rule simulates the traditional linker's semantics.
-    bool backref = config->warnBackrefs && other.file &&
+    bool backref = ctx.arg.warnBackrefs && other.file &&
                    file->groupId < other.file->groupId;
     extract();
 
-    if (!config->whyExtract.empty())
+    if (!ctx.arg.whyExtract.empty())
       recordWhyExtract(other.file, *file, *this);
 
     // We don't report backward references to weak symbols as they can be
@@ -495,7 +495,7 @@ void Symbol::resolve(const Undefined &other) {
 // 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)
+    if (ctx.arg.warnCommon)
       warn("common " + getName() + " is overridden");
     return !other.isWeak();
   }
@@ -513,7 +513,7 @@ bool Symbol::shouldReplace(const Defined &other) const {
 
 void elf::reportDuplicate(const Symbol &sym, const InputFile *newFile,
                           InputSectionBase *errSec, uint64_t errOffset) {
-  if (config->allowMultipleDefinition)
+  if (ctx.arg.allowMultipleDefinition)
     return;
   // 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
@@ -568,13 +568,13 @@ void Symbol::resolve(const CommonSymbol &other) {
     setVisibility(v == STV_DEFAULT ? ov : std::min(v, ov));
   }
   if (isDefined() && !isWeak()) {
-    if (config->warnCommon)
+    if (ctx.arg.warnCommon)
       warn("common " + getName() + " is overridden");
     return;
   }
 
   if (CommonSymbol *oldSym = dyn_cast<CommonSymbol>(this)) {
-    if (config->warnCommon)
+    if (ctx.arg.warnCommon)
       warn("multiple common of " + getName());
     oldSym->alignment = std::max(oldSym->alignment, other.alignment);
     if (oldSym->size < other.size) {
@@ -617,7 +617,7 @@ void Symbol::resolve(const LazySymbol &other) {
 
   // For common objects, we want to look for global or weak definitions that
   // should be extracted as the canonical definition instead.
-  if (LLVM_UNLIKELY(isCommon()) && elf::config->fortranCommon &&
+  if (LLVM_UNLIKELY(isCommon()) && elf::ctx.arg.fortranCommon &&
       other.file->shouldExtractForCommon(getName())) {
     ctx.backwardReferences.erase(this);
     other.overwrite(*this);
@@ -644,7 +644,7 @@ void Symbol::resolve(const LazySymbol &other) {
 
   const InputFile *oldFile = file;
   other.extract();
-  if (!config->whyExtract.empty())
+  if (!ctx.arg.whyExtract.empty())
     recordWhyExtract(oldFile, *file, *this);
 }
 

diff  --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index 05aed16bfb0dc9..57aa423f28cae5 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -365,7 +365,7 @@ class Defined : public Symbol {
           uint8_t type, uint64_t value, uint64_t size, SectionBase *section)
       : Symbol(DefinedKind, file, name, binding, stOther, type), value(value),
         size(size), section(section) {
-    exportDynamic = config->exportDynamic;
+    exportDynamic = ctx.arg.exportDynamic;
   }
   void overwrite(Symbol &sym) const;
 
@@ -403,7 +403,7 @@ class CommonSymbol : public Symbol {
                uint8_t stOther, uint8_t type, uint64_t alignment, uint64_t size)
       : Symbol(CommonKind, file, name, binding, stOther, type),
         alignment(alignment), size(size) {
-    exportDynamic = config->exportDynamic;
+    exportDynamic = ctx.arg.exportDynamic;
   }
   void overwrite(Symbol &sym) const {
     Symbol::overwrite(sym, CommonKind);

diff  --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 2239c3645ae921..ecb4a02acc19fe 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -60,11 +60,11 @@ using llvm::support::endian::write64le;
 constexpr size_t MergeNoTailSection::numShards;
 
 static uint64_t readUint(uint8_t *buf) {
-  return config->is64 ? read64(buf) : read32(buf);
+  return ctx.arg.is64 ? read64(buf) : read32(buf);
 }
 
 static void writeUint(uint8_t *buf, uint64_t val) {
-  if (config->is64)
+  if (ctx.arg.is64)
     write64(buf, val);
   else
     write32(buf, val);
@@ -167,7 +167,7 @@ template <class ELFT> void MipsOptionsSection<ELFT>::writeTo(uint8_t *buf) {
   options->kind = ODK_REGINFO;
   options->size = getSize();
 
-  if (!config->relocatable)
+  if (!ctx.arg.relocatable)
     reginfo.ri_gp_value = ctx.in.mipsGot->getGp();
   memcpy(buf + sizeof(Elf_Mips_Options), &reginfo, sizeof(reginfo));
 }
@@ -224,7 +224,7 @@ MipsReginfoSection<ELFT>::MipsReginfoSection(Elf_Mips_RegInfo reginfo)
 }
 
 template <class ELFT> void MipsReginfoSection<ELFT>::writeTo(uint8_t *buf) {
-  if (!config->relocatable)
+  if (!ctx.arg.relocatable)
     reginfo.ri_gp_value = ctx.in.mipsGot->getGp();
   memcpy(buf, &reginfo, sizeof(reginfo));
 }
@@ -262,7 +262,7 @@ std::unique_ptr<MipsReginfoSection<ELFT>> MipsReginfoSection<ELFT>::create() {
 
 InputSection *elf::createInterpSection() {
   // StringSaver guarantees that the returned string ends with '\0'.
-  StringRef s = saver().save(config->dynamicLinker);
+  StringRef s = saver().save(ctx.arg.dynamicLinker);
   ArrayRef<uint8_t> contents = {(const uint8_t *)s.data(), s.size() + 1};
 
   return make<InputSection>(ctx.internalFile, SHF_ALLOC, SHT_PROGBITS, 1,
@@ -276,7 +276,7 @@ Defined *elf::addSyntheticLocal(StringRef name, uint8_t type, uint64_t value,
   if (ctx.in.symTab)
     ctx.in.symTab->addSymbol(s);
 
-  if (config->emachine == EM_ARM && !config->isLE && config->armBe8 &&
+  if (ctx.arg.emachine == EM_ARM && !ctx.arg.isLE && ctx.arg.armBe8 &&
       (section.flags & SHF_EXECINSTR))
     // Adding Linker generated mapping symbols to the arm specific mapping
     // symbols list.
@@ -286,7 +286,7 @@ Defined *elf::addSyntheticLocal(StringRef name, uint8_t type, uint64_t value,
 }
 
 static size_t getHashSize() {
-  switch (config->buildId) {
+  switch (ctx.arg.buildId) {
   case BuildIdKind::Fast:
     return 8;
   case BuildIdKind::Md5:
@@ -295,7 +295,7 @@ static size_t getHashSize() {
   case BuildIdKind::Sha1:
     return 20;
   case BuildIdKind::Hexstring:
-    return config->buildIdVector.size();
+    return ctx.arg.buildIdVector.size();
   default:
     llvm_unreachable("unknown BuildIdKind");
   }
@@ -315,7 +315,7 @@ static size_t getHashSize() {
 // we don't create this section.
 GnuPropertySection::GnuPropertySection()
     : SyntheticSection(llvm::ELF::SHF_ALLOC, llvm::ELF::SHT_NOTE,
-                       config->wordsize, ".note.gnu.property") {}
+                       ctx.arg.wordsize, ".note.gnu.property") {}
 
 void GnuPropertySection::writeTo(uint8_t *buf) {
   write32(buf, 4);                          // Name size
@@ -323,16 +323,16 @@ void GnuPropertySection::writeTo(uint8_t *buf) {
   write32(buf + 8, NT_GNU_PROPERTY_TYPE_0); // Type
   memcpy(buf + 12, "GNU", 4);               // Name string
 
-  uint32_t featureAndType = config->emachine == EM_AARCH64
+  uint32_t featureAndType = ctx.arg.emachine == EM_AARCH64
                                 ? GNU_PROPERTY_AARCH64_FEATURE_1_AND
                                 : GNU_PROPERTY_X86_FEATURE_1_AND;
 
   unsigned offset = 16;
-  if (config->andFeatures != 0) {
+  if (ctx.arg.andFeatures != 0) {
     write32(buf + offset + 0, featureAndType);      // Feature type
     write32(buf + offset + 4, 4);                   // Feature size
-    write32(buf + offset + 8, config->andFeatures); // Feature flags
-    if (config->is64)
+    write32(buf + offset + 8, ctx.arg.andFeatures); // Feature flags
+    if (ctx.arg.is64)
       write32(buf + offset + 12, 0); // Padding
     offset += 16;
   }
@@ -347,8 +347,8 @@ void GnuPropertySection::writeTo(uint8_t *buf) {
 
 size_t GnuPropertySection::getSize() const {
   uint32_t contentSize = 0;
-  if (config->andFeatures != 0)
-    contentSize += config->is64 ? 16 : 12;
+  if (ctx.arg.andFeatures != 0)
+    contentSize += ctx.arg.is64 ? 16 : 12;
   if (!ctx.aarch64PauthAbiCoreInfo.empty())
     contentSize += 4 + 4 + ctx.aarch64PauthAbiCoreInfo.size();
   assert(contentSize != 0);
@@ -508,7 +508,7 @@ static void writeCieFde(uint8_t *buf, ArrayRef<uint8_t> d) {
 void EhFrameSection::finalizeContents() {
   assert(!this->size); // Not finalized.
 
-  switch (config->ekind) {
+  switch (ctx.arg.ekind) {
   case ELFNoneKind:
     llvm_unreachable("invalid ekind");
   case ELF32LEKind:
@@ -615,7 +615,7 @@ uint64_t EhFrameSection::getFdePc(uint8_t *buf, size_t fdeOff,
   size_t off = fdeOff + 8;
   uint64_t addr = readFdeAddr(buf + off, enc & 0xf);
   if ((enc & 0x70) == DW_EH_PE_absptr)
-    return config->is64 ? addr : uint32_t(addr);
+    return ctx.arg.is64 ? addr : uint32_t(addr);
   if ((enc & 0x70) == DW_EH_PE_pcrel)
     return addr + getParent()->addr + off + outSecOff;
   fatal("unknown FDE size relative encoding");
@@ -679,13 +679,13 @@ bool GotSection::addDynTlsEntry(const Symbol &sym) {
 bool GotSection::addTlsIndex() {
   if (tlsIndexOff != uint32_t(-1))
     return false;
-  tlsIndexOff = numEntries * config->wordsize;
+  tlsIndexOff = numEntries * ctx.arg.wordsize;
   numEntries += 2;
   return true;
 }
 
 uint32_t GotSection::getTlsDescOffset(const Symbol &sym) const {
-  return sym.getTlsDescIdx() * config->wordsize;
+  return sym.getTlsDescIdx() * ctx.arg.wordsize;
 }
 
 uint64_t GotSection::getTlsDescAddr(const Symbol &sym) const {
@@ -693,20 +693,20 @@ uint64_t GotSection::getTlsDescAddr(const Symbol &sym) const {
 }
 
 uint64_t GotSection::getGlobalDynAddr(const Symbol &b) const {
-  return this->getVA() + b.getTlsGdIdx() * config->wordsize;
+  return this->getVA() + b.getTlsGdIdx() * ctx.arg.wordsize;
 }
 
 uint64_t GotSection::getGlobalDynOffset(const Symbol &b) const {
-  return b.getTlsGdIdx() * config->wordsize;
+  return b.getTlsGdIdx() * ctx.arg.wordsize;
 }
 
 void GotSection::finalizeContents() {
-  if (config->emachine == EM_PPC64 &&
+  if (ctx.arg.emachine == EM_PPC64 &&
       numEntries <= ctx.target->gotHeaderEntriesNum &&
       !ctx.sym.globalOffsetTable)
     size = 0;
   else
-    size = numEntries * config->wordsize;
+    size = numEntries * ctx.arg.wordsize;
 }
 
 bool GotSection::isNeeded() const {
@@ -806,7 +806,7 @@ uint64_t MipsGotSection::getPageEntryOffset(const InputFile *f,
   } else {
     index = g.local16.lookup({nullptr, getMipsPageAddr(sym.getVA(addend))});
   }
-  return index * config->wordsize;
+  return index * ctx.arg.wordsize;
 }
 
 uint64_t MipsGotSection::getSymEntryOffset(const InputFile *f, const Symbol &s,
@@ -814,22 +814,22 @@ uint64_t MipsGotSection::getSymEntryOffset(const InputFile *f, const Symbol &s,
   const FileGot &g = gots[f->mipsGotIndex];
   Symbol *sym = const_cast<Symbol *>(&s);
   if (sym->isTls())
-    return g.tls.lookup(sym) * config->wordsize;
+    return g.tls.lookup(sym) * ctx.arg.wordsize;
   if (sym->isPreemptible)
-    return g.global.lookup(sym) * config->wordsize;
-  return g.local16.lookup({sym, addend}) * config->wordsize;
+    return g.global.lookup(sym) * ctx.arg.wordsize;
+  return g.local16.lookup({sym, addend}) * ctx.arg.wordsize;
 }
 
 uint64_t MipsGotSection::getTlsIndexOffset(const InputFile *f) const {
   const FileGot &g = gots[f->mipsGotIndex];
-  return g.dynTlsSymbols.lookup(nullptr) * config->wordsize;
+  return g.dynTlsSymbols.lookup(nullptr) * ctx.arg.wordsize;
 }
 
 uint64_t MipsGotSection::getGlobalDynOffset(const InputFile *f,
                                             const Symbol &s) const {
   const FileGot &g = gots[f->mipsGotIndex];
   Symbol *sym = const_cast<Symbol *>(&s);
-  return g.dynTlsSymbols.lookup(sym) * config->wordsize;
+  return g.dynTlsSymbols.lookup(sym) * ctx.arg.wordsize;
 }
 
 const Symbol *MipsGotSection::getFirstGlobalEntry() const {
@@ -862,7 +862,7 @@ bool MipsGotSection::tryMergeGots(FileGot &dst, FileGot &src, bool isPrimary) {
   size_t count = isPrimary ? headerEntriesNum : 0;
   count += tmp.getIndexedEntriesNum();
 
-  if (count * config->wordsize > config->mipsGotSize)
+  if (count * ctx.arg.wordsize > ctx.arg.mipsGotSize)
     return false;
 
   std::swap(tmp, dst);
@@ -872,9 +872,9 @@ bool MipsGotSection::tryMergeGots(FileGot &dst, FileGot &src, bool isPrimary) {
 void MipsGotSection::finalizeContents() { updateAllocSize(); }
 
 bool MipsGotSection::updateAllocSize() {
-  size = headerEntriesNum * config->wordsize;
+  size = headerEntriesNum * ctx.arg.wordsize;
   for (const FileGot &g : gots)
-    size += g.getEntriesNum() * config->wordsize;
+    size += g.getEntriesNum() * ctx.arg.wordsize;
   return false;
 }
 
@@ -1013,20 +1013,20 @@ void MipsGotSection::build() {
     // Create dynamic relocations for TLS entries.
     for (std::pair<Symbol *, size_t> &p : got.tls) {
       Symbol *s = p.first;
-      uint64_t offset = p.second * config->wordsize;
+      uint64_t offset = p.second * ctx.arg.wordsize;
       // When building a shared library we still need a dynamic relocation
       // for the TP-relative offset as we don't know how much other data will
       // be allocated before us in the static TLS block.
-      if (s->isPreemptible || config->shared)
+      if (s->isPreemptible || ctx.arg.shared)
         ctx.mainPart->relaDyn->addReloc(
             {ctx.target->tlsGotRel, this, offset,
              DynamicReloc::AgainstSymbolWithTargetVA, *s, 0, R_ABS});
     }
     for (std::pair<Symbol *, size_t> &p : got.dynTlsSymbols) {
       Symbol *s = p.first;
-      uint64_t offset = p.second * config->wordsize;
+      uint64_t offset = p.second * ctx.arg.wordsize;
       if (s == nullptr) {
-        if (!config->shared)
+        if (!ctx.arg.shared)
           continue;
         ctx.mainPart->relaDyn->addReloc(
             {ctx.target->tlsModuleIndexRel, this, offset});
@@ -1035,7 +1035,7 @@ void MipsGotSection::build() {
         // for the module index. Therefore only checking for
         // S->isPreemptible is not sufficient (this happens e.g. for
         // thread-locals that have been marked as local through a linker script)
-        if (!s->isPreemptible && !config->shared)
+        if (!s->isPreemptible && !ctx.arg.shared)
           continue;
         ctx.mainPart->relaDyn->addSymbolReloc(ctx.target->tlsModuleIndexRel,
                                               *this, offset, *s);
@@ -1043,7 +1043,7 @@ void MipsGotSection::build() {
         // symbols since it is known even in shared libraries
         if (!s->isPreemptible)
           continue;
-        offset += config->wordsize;
+        offset += ctx.arg.wordsize;
         ctx.mainPart->relaDyn->addSymbolReloc(ctx.target->tlsOffsetRel, *this,
                                               offset, *s);
       }
@@ -1056,24 +1056,24 @@ 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;
+      uint64_t offset = p.second * ctx.arg.wordsize;
       ctx.mainPart->relaDyn->addSymbolReloc(ctx.target->relativeRel, *this,
                                             offset, *p.first);
     }
-    if (!config->isPic)
+    if (!ctx.arg.isPic)
       continue;
     // Dynamic relocations for "local" entries in case of PIC.
     for (const std::pair<const OutputSection *, FileGot::PageBlock> &l :
          got.pagesMap) {
       size_t pageCount = l.second.count;
       for (size_t pi = 0; pi < pageCount; ++pi) {
-        uint64_t offset = (l.second.firstIndex + pi) * config->wordsize;
+        uint64_t offset = (l.second.firstIndex + pi) * ctx.arg.wordsize;
         ctx.mainPart->relaDyn->addReloc({ctx.target->relativeRel, this, offset,
                                          l.first, int64_t(pi * 0x10000)});
       }
     }
     for (const std::pair<GotEntry, size_t> &p : got.local16) {
-      uint64_t offset = p.second * config->wordsize;
+      uint64_t offset = p.second * ctx.arg.wordsize;
       ctx.mainPart->relaDyn->addReloc({ctx.target->relativeRel, this, offset,
                                        DynamicReloc::AddendOnlyWithTargetVA,
                                        *p.first.first, p.first.second, R_ABS});
@@ -1084,7 +1084,7 @@ void MipsGotSection::build() {
 bool MipsGotSection::isNeeded() const {
   // We add the .got section to the result for dynamic MIPS target because
   // its address and properties are mentioned in the .dynamic section.
-  return !config->relocatable;
+  return !ctx.arg.relocatable;
 }
 
 uint64_t MipsGotSection::getGp(const InputFile *f) const {
@@ -1093,7 +1093,7 @@ uint64_t MipsGotSection::getGp(const InputFile *f) const {
   // individual _gp values.
   if (!f || f->mipsGotIndex == uint32_t(-1) || f->mipsGotIndex == 0)
     return ctx.sym.mipsGp->getVA(0);
-  return getVA() + gots[f->mipsGotIndex].startIndex * config->wordsize + 0x7ff0;
+  return getVA() + gots[f->mipsGotIndex].startIndex * ctx.arg.wordsize + 0x7ff0;
 }
 
 void MipsGotSection::writeTo(uint8_t *buf) {
@@ -1111,13 +1111,13 @@ void MipsGotSection::writeTo(uint8_t *buf) {
   // we've been doing this for years, it is probably a safe bet to
   // keep doing this for now. We really need to revisit this to see
   // if we had to do this.
-  writeUint(buf + config->wordsize, (uint64_t)1 << (config->wordsize * 8 - 1));
+  writeUint(buf + ctx.arg.wordsize, (uint64_t)1 << (ctx.arg.wordsize * 8 - 1));
   for (const FileGot &g : gots) {
     auto write = [&](size_t i, const Symbol *s, int64_t a) {
       uint64_t va = a;
       if (s)
         va = s->getVA(a);
-      writeUint(buf + i * config->wordsize, va);
+      writeUint(buf + i * ctx.arg.wordsize, va);
     };
     // Write 'page address' entries to the local part of the GOT.
     for (const std::pair<const OutputSection *, FileGot::PageBlock> &l :
@@ -1143,15 +1143,15 @@ void MipsGotSection::writeTo(uint8_t *buf) {
       write(p.second, p.first, 0);
     for (const std::pair<Symbol *, size_t> &p : g.tls)
       write(p.second, p.first,
-            p.first->isPreemptible || config->shared ? 0 : -0x7000);
+            p.first->isPreemptible || ctx.arg.shared ? 0 : -0x7000);
     for (const std::pair<Symbol *, size_t> &p : g.dynTlsSymbols) {
-      if (p.first == nullptr && !config->shared)
+      if (p.first == nullptr && !ctx.arg.shared)
         write(p.second, nullptr, 1);
       else if (p.first && !p.first->isPreemptible) {
         // 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)
+        if (!ctx.arg.shared)
           write(p.second, nullptr, 1);
         write(p.second + 1, p.first, -0x8000);
       }
@@ -1164,11 +1164,11 @@ void MipsGotSection::writeTo(uint8_t *buf) {
 // section. I don't know why we have a BSS style type for the section but it is
 // consistent across both 64-bit PowerPC ABIs as well as the 32-bit PowerPC ABI.
 GotPltSection::GotPltSection()
-    : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, config->wordsize,
+    : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, ctx.arg.wordsize,
                        ".got.plt") {
-  if (config->emachine == EM_PPC) {
+  if (ctx.arg.emachine == EM_PPC) {
     name = ".plt";
-  } else if (config->emachine == EM_PPC64) {
+  } else if (ctx.arg.emachine == EM_PPC64) {
     type = SHT_NOBITS;
     name = ".plt";
   }
@@ -1202,12 +1202,12 @@ bool GotPltSection::isNeeded() const {
 
 static StringRef getIgotPltName() {
   // On ARM the IgotPltSection is part of the GotSection.
-  if (config->emachine == EM_ARM)
+  if (ctx.arg.emachine == EM_ARM)
     return ".got";
 
   // On PowerPC64 the GotPltSection is renamed to '.plt' so the IgotPltSection
   // needs to be named the same.
-  if (config->emachine == EM_PPC64)
+  if (ctx.arg.emachine == EM_PPC64)
     return ".plt";
 
   return ".got.plt";
@@ -1217,7 +1217,7 @@ static StringRef getIgotPltName() {
 // with the IgotPltSection.
 IgotPltSection::IgotPltSection()
     : SyntheticSection(SHF_ALLOC | SHF_WRITE,
-                       config->emachine == EM_PPC64 ? SHT_NOBITS : SHT_PROGBITS,
+                       ctx.arg.emachine == EM_PPC64 ? SHT_NOBITS : SHT_PROGBITS,
                        ctx.target->gotEntrySize, getIgotPltName()) {}
 
 void IgotPltSection::addEntry(Symbol &sym) {
@@ -1280,7 +1280,7 @@ static unsigned getVerDefNum() {
 
 template <class ELFT>
 DynamicSection<ELFT>::DynamicSection()
-    : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_DYNAMIC, config->wordsize,
+    : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_DYNAMIC, ctx.arg.wordsize,
                        ".dynamic") {
   this->entsize = ELFT::Is64Bits ? 16 : 8;
 
@@ -1288,7 +1288,7 @@ DynamicSection<ELFT>::DynamicSection()
   // which passes -z rodynamic.
   // See "Special Section" in Chapter 4 in the following document:
   // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
-  if (config->emachine == EM_MIPS || config->zRodynamic)
+  if (ctx.arg.emachine == EM_MIPS || ctx.arg.zRodynamic)
     this->flags = SHF_ALLOC;
 }
 
@@ -1327,58 +1327,58 @@ DynamicSection<ELFT>::computeContents() {
     entries.emplace_back(tag, sec.getVA());
   };
 
-  for (StringRef s : config->filterList)
+  for (StringRef s : ctx.arg.filterList)
     addInt(DT_FILTER, part.dynStrTab->addString(s));
-  for (StringRef s : config->auxiliaryList)
+  for (StringRef s : ctx.arg.auxiliaryList)
     addInt(DT_AUXILIARY, part.dynStrTab->addString(s));
 
-  if (!config->rpath.empty())
-    addInt(config->enableNewDtags ? DT_RUNPATH : DT_RPATH,
-           part.dynStrTab->addString(config->rpath));
+  if (!ctx.arg.rpath.empty())
+    addInt(ctx.arg.enableNewDtags ? DT_RUNPATH : DT_RPATH,
+           part.dynStrTab->addString(ctx.arg.rpath));
 
   for (SharedFile *file : ctx.sharedFiles)
     if (file->isNeeded)
       addInt(DT_NEEDED, part.dynStrTab->addString(file->soName));
 
   if (isMain) {
-    if (!config->soName.empty())
-      addInt(DT_SONAME, part.dynStrTab->addString(config->soName));
+    if (!ctx.arg.soName.empty())
+      addInt(DT_SONAME, part.dynStrTab->addString(ctx.arg.soName));
   } else {
-    if (!config->soName.empty())
-      addInt(DT_NEEDED, part.dynStrTab->addString(config->soName));
+    if (!ctx.arg.soName.empty())
+      addInt(DT_NEEDED, part.dynStrTab->addString(ctx.arg.soName));
     addInt(DT_SONAME, part.dynStrTab->addString(part.name));
   }
 
   // Set DT_FLAGS and DT_FLAGS_1.
   uint32_t dtFlags = 0;
   uint32_t dtFlags1 = 0;
-  if (config->bsymbolic == BsymbolicKind::All)
+  if (ctx.arg.bsymbolic == BsymbolicKind::All)
     dtFlags |= DF_SYMBOLIC;
-  if (config->zGlobal)
+  if (ctx.arg.zGlobal)
     dtFlags1 |= DF_1_GLOBAL;
-  if (config->zInitfirst)
+  if (ctx.arg.zInitfirst)
     dtFlags1 |= DF_1_INITFIRST;
-  if (config->zInterpose)
+  if (ctx.arg.zInterpose)
     dtFlags1 |= DF_1_INTERPOSE;
-  if (config->zNodefaultlib)
+  if (ctx.arg.zNodefaultlib)
     dtFlags1 |= DF_1_NODEFLIB;
-  if (config->zNodelete)
+  if (ctx.arg.zNodelete)
     dtFlags1 |= DF_1_NODELETE;
-  if (config->zNodlopen)
+  if (ctx.arg.zNodlopen)
     dtFlags1 |= DF_1_NOOPEN;
-  if (config->pie)
+  if (ctx.arg.pie)
     dtFlags1 |= DF_1_PIE;
-  if (config->zNow) {
+  if (ctx.arg.zNow) {
     dtFlags |= DF_BIND_NOW;
     dtFlags1 |= DF_1_NOW;
   }
-  if (config->zOrigin) {
+  if (ctx.arg.zOrigin) {
     dtFlags |= DF_ORIGIN;
     dtFlags1 |= DF_1_ORIGIN;
   }
-  if (!config->zText)
+  if (!ctx.arg.zText)
     dtFlags |= DF_TEXTREL;
-  if (ctx.hasTlsIe && config->shared)
+  if (ctx.hasTlsIe && ctx.arg.shared)
     dtFlags |= DF_STATIC_TLS;
 
   if (dtFlags)
@@ -1394,7 +1394,7 @@ DynamicSection<ELFT>::computeContents() {
   // systems (currently only Fuchsia OS) provide other means to give the
   // debugger this information. Such systems may choose make .dynamic read-only.
   // If the target is such a system (used -z rodynamic) don't write DT_DEBUG.
-  if (!config->shared && !config->relocatable && !config->zRodynamic)
+  if (!ctx.arg.shared && !ctx.arg.relocatable && !ctx.arg.zRodynamic)
     addInt(DT_DEBUG, 0);
 
   if (part.relaDyn->isNeeded()) {
@@ -1402,26 +1402,26 @@ DynamicSection<ELFT>::computeContents() {
     entries.emplace_back(part.relaDyn->sizeDynamicTag,
                          addRelaSz(*part.relaDyn));
 
-    bool isRela = config->isRela;
+    bool isRela = ctx.arg.isRela;
     addInt(isRela ? DT_RELAENT : DT_RELENT,
            isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel));
 
     // MIPS dynamic loader does not support RELCOUNT tag.
     // The problem is in the tight relation between dynamic
     // relocations and GOT. So do not emit this tag on MIPS.
-    if (config->emachine != EM_MIPS) {
+    if (ctx.arg.emachine != EM_MIPS) {
       size_t numRelativeRels = part.relaDyn->getRelativeRelocCount();
-      if (config->zCombreloc && numRelativeRels)
+      if (ctx.arg.zCombreloc && numRelativeRels)
         addInt(isRela ? DT_RELACOUNT : DT_RELCOUNT, numRelativeRels);
     }
   }
   if (part.relrDyn && part.relrDyn->getParent() &&
       !part.relrDyn->relocs.empty()) {
-    addInSec(config->useAndroidRelrTags ? DT_ANDROID_RELR : DT_RELR,
+    addInSec(ctx.arg.useAndroidRelrTags ? DT_ANDROID_RELR : DT_RELR,
              *part.relrDyn);
-    addInt(config->useAndroidRelrTags ? DT_ANDROID_RELRSZ : DT_RELRSZ,
+    addInt(ctx.arg.useAndroidRelrTags ? DT_ANDROID_RELRSZ : DT_RELRSZ,
            part.relrDyn->getParent()->size);
-    addInt(config->useAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT,
+    addInt(ctx.arg.useAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT,
            sizeof(Elf_Relr));
   }
   if (part.relrAuthDyn && part.relrAuthDyn->getParent() &&
@@ -1433,7 +1433,7 @@ DynamicSection<ELFT>::computeContents() {
   if (isMain && ctx.in.relaPlt->isNeeded()) {
     addInSec(DT_JMPREL, *ctx.in.relaPlt);
     entries.emplace_back(DT_PLTRELSZ, addPltRelSz());
-    switch (config->emachine) {
+    switch (ctx.arg.emachine) {
     case EM_MIPS:
       addInSec(DT_MIPS_PLTGOT, *ctx.in.gotPlt);
       break;
@@ -1462,19 +1462,19 @@ DynamicSection<ELFT>::computeContents() {
       addInSec(DT_PLTGOT, *ctx.in.gotPlt);
       break;
     }
-    addInt(DT_PLTREL, config->isRela ? DT_RELA : DT_REL);
+    addInt(DT_PLTREL, ctx.arg.isRela ? DT_RELA : DT_REL);
   }
 
-  if (config->emachine == EM_AARCH64) {
-    if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
+  if (ctx.arg.emachine == EM_AARCH64) {
+    if (ctx.arg.andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
       addInt(DT_AARCH64_BTI_PLT, 0);
-    if (config->zPacPlt)
+    if (ctx.arg.zPacPlt)
       addInt(DT_AARCH64_PAC_PLT, 0);
 
     if (hasMemtag()) {
-      addInt(DT_AARCH64_MEMTAG_MODE, config->androidMemtagMode == NT_MEMTAG_LEVEL_ASYNC);
-      addInt(DT_AARCH64_MEMTAG_HEAP, config->androidMemtagHeap);
-      addInt(DT_AARCH64_MEMTAG_STACK, config->androidMemtagStack);
+      addInt(DT_AARCH64_MEMTAG_MODE, ctx.arg.androidMemtagMode == NT_MEMTAG_LEVEL_ASYNC);
+      addInt(DT_AARCH64_MEMTAG_HEAP, ctx.arg.androidMemtagHeap);
+      addInt(DT_AARCH64_MEMTAG_STACK, ctx.arg.androidMemtagStack);
       if (ctx.mainPart->memtagGlobalDescriptors->isNeeded()) {
         addInSec(DT_AARCH64_MEMTAG_GLOBALS,
                  *ctx.mainPart->memtagGlobalDescriptors);
@@ -1488,7 +1488,7 @@ DynamicSection<ELFT>::computeContents() {
   addInt(DT_SYMENT, sizeof(Elf_Sym));
   addInSec(DT_STRTAB, *part.dynStrTab);
   addInt(DT_STRSZ, part.dynStrTab->getSize());
-  if (!config->zText)
+  if (!ctx.arg.zText)
     addInt(DT_TEXTREL, 0);
   if (part.gnuHashTab && part.gnuHashTab->getParent())
     addInSec(DT_GNU_HASH, *part.gnuHashTab);
@@ -1509,10 +1509,10 @@ DynamicSection<ELFT>::computeContents() {
       addInt(DT_FINI_ARRAYSZ, ctx.out.finiArray->size);
     }
 
-    if (Symbol *b = symtab.find(config->init))
+    if (Symbol *b = symtab.find(ctx.arg.init))
       if (b->isDefined())
         addInt(DT_INIT, b->getVA());
-    if (Symbol *b = symtab.find(config->fini))
+    if (Symbol *b = symtab.find(ctx.arg.fini))
       if (b->isDefined())
         addInt(DT_FINI, b->getVA());
   }
@@ -1532,7 +1532,7 @@ DynamicSection<ELFT>::computeContents() {
     addInt(DT_VERNEEDNUM, needNum);
   }
 
-  if (config->emachine == EM_MIPS) {
+  if (ctx.arg.emachine == EM_MIPS) {
     addInt(DT_MIPS_RLD_VERSION, 1);
     addInt(DT_MIPS_FLAGS, RHF_NOTPOT);
     addInt(DT_MIPS_BASE_ADDRESS, ctx.target->getImageBase());
@@ -1545,7 +1545,7 @@ DynamicSection<ELFT>::computeContents() {
       addInt(DT_MIPS_GOTSYM, part.dynSymTab->getNumSymbols());
     addInSec(DT_PLTGOT, *ctx.in.mipsGot);
     if (ctx.in.mipsRldMap) {
-      if (!config->pie)
+      if (!ctx.arg.pie)
         addInSec(DT_MIPS_RLD_MAP, *ctx.in.mipsRldMap);
       // Store the offset to the .rld_map section
       // relative to the address of the tag.
@@ -1556,18 +1556,18 @@ DynamicSection<ELFT>::computeContents() {
 
   // 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)
+  if (ctx.arg.emachine == EM_PPC)
     addInSec(DT_PPC_GOT, *ctx.in.got);
 
   // Glink dynamic tag is required by the V2 abi if the plt section isn't empty.
-  if (config->emachine == EM_PPC64 && ctx.in.plt->isNeeded()) {
+  if (ctx.arg.emachine == EM_PPC64 && ctx.in.plt->isNeeded()) {
     // The Glink tag points to 32 bytes before the first lazy symbol resolution
     // stub, which starts directly after the header.
     addInt(DT_PPC64_GLINK,
            ctx.in.plt->getVA() + ctx.target->pltHeaderSize - 32);
   }
 
-  if (config->emachine == EM_PPC64)
+  if (ctx.arg.emachine == EM_PPC64)
     addInt(DT_PPC64_OPT, getPPC64TargetInfo()->ppc64DynamicSectionOpt);
 
   addInt(DT_NULL, 0);
@@ -1606,7 +1606,7 @@ int64_t DynamicReloc::computeAddend() const {
   case AgainstSymbolWithTargetVA: {
     uint64_t ca = InputSection::getRelocTargetVA(inputSec->file, type, addend,
                                                  getOffset(), *sym, expr);
-    return config->is64 ? ca : SignExtend64<32>(ca);
+    return ctx.arg.is64 ? ca : SignExtend64<32>(ca);
   }
   case MipsMultiGotPage:
     assert(sym == nullptr);
@@ -1632,7 +1632,7 @@ RelocationBaseSection::RelocationBaseSection(StringRef name, uint32_t type,
                                              int32_t sizeDynamicTag,
                                              bool combreloc,
                                              unsigned concurrency)
-    : SyntheticSection(SHF_ALLOC, type, config->wordsize, name),
+    : SyntheticSection(SHF_ALLOC, type, ctx.arg.wordsize, name),
       dynamicTag(dynamicTag), sizeDynamicTag(sizeDynamicTag),
       relocsVec(concurrency), combreloc(combreloc) {}
 
@@ -1725,11 +1725,11 @@ void RelocationBaseSection::computeRels() {
 template <class ELFT>
 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, combreloc,
+    : RelocationBaseSection(name, ctx.arg.isRela ? SHT_RELA : SHT_REL,
+                            ctx.arg.isRela ? DT_RELA : DT_REL,
+                            ctx.arg.isRela ? DT_RELASZ : DT_RELSZ, combreloc,
                             concurrency) {
-  this->entsize = config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
+  this->entsize = ctx.arg.isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
 }
 
 template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *buf) {
@@ -1737,10 +1737,10 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *buf) {
   for (const DynamicReloc &rel : relocs) {
     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->setSymbolAndType(rel.r_sym, rel.type, ctx.arg.isMips64EL);
+    if (ctx.arg.isRela)
       p->r_addend = rel.addend;
-    buf += config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
+    buf += ctx.arg.isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
   }
 }
 
@@ -1749,8 +1749,8 @@ RelrBaseSection::RelrBaseSection(unsigned concurrency, bool isAArch64Auth)
           SHF_ALLOC,
           isAArch64Auth
               ? SHT_AARCH64_AUTH_RELR
-              : (config->useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR),
-          config->wordsize, isAArch64Auth ? ".relr.auth.dyn" : ".relr.dyn"),
+              : (ctx.arg.useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR),
+          ctx.arg.wordsize, isAArch64Auth ? ".relr.auth.dyn" : ".relr.dyn"),
       relocsVec(concurrency) {}
 
 void RelrBaseSection::mergeRels() {
@@ -1767,9 +1767,9 @@ template <class ELFT>
 AndroidPackedRelocationSection<ELFT>::AndroidPackedRelocationSection(
     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,
+          name, ctx.arg.isRela ? SHT_ANDROID_RELA : SHT_ANDROID_REL,
+          ctx.arg.isRela ? DT_ANDROID_RELA : DT_ANDROID_REL,
+          ctx.arg.isRela ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ,
           /*combreloc=*/false, concurrency) {
   this->entsize = 1;
 }
@@ -1840,9 +1840,9 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
     r.r_offset = rel.getOffset();
     r.setSymbolAndType(rel.getSymIndex(getPartition().dynSymTab.get()),
                        rel.type, false);
-    r.r_addend = config->isRela ? rel.computeAddend() : 0;
+    r.r_addend = ctx.arg.isRela ? rel.computeAddend() : 0;
 
-    if (r.getType(config->isMips64EL) == ctx.target->relativeRel)
+    if (r.getType(ctx.arg.isMips64EL) == ctx.target->relativeRel)
       relatives.push_back(r);
     else
       nonRelatives.push_back(r);
@@ -1864,7 +1864,7 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
     std::vector<Elf_Rela> group;
     do {
       group.push_back(*i++);
-    } while (i != e && (i - 1)->r_offset + config->wordsize == i->r_offset);
+    } while (i != e && (i - 1)->r_offset + ctx.arg.wordsize == i->r_offset);
 
     if (group.size() < 8)
       ungroupedRelatives.insert(ungroupedRelatives.end(), group.begin(),
@@ -1909,9 +1909,9 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
   for (auto i = nonRelatives.begin(), e = nonRelatives.end(); i != e;) {
     auto j = i + 1;
     while (j != e && i->r_info == j->r_info &&
-           (!config->isRela || i->r_addend == j->r_addend))
+           (!ctx.arg.isRela || i->r_addend == j->r_addend))
       ++j;
-    if (j - i < 3 || (config->isRela && i->r_addend != 0))
+    if (j - i < 3 || (ctx.arg.isRela && i->r_addend != 0))
       ungroupedNonRelatives.insert(ungroupedNonRelatives.end(), i, j);
     else
       nonRelativeGroups.emplace_back(i, j);
@@ -1924,7 +1924,7 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
   });
 
   unsigned hasAddendIfRela =
-      config->isRela ? RELOCATION_GROUP_HAS_ADDEND_FLAG : 0;
+      ctx.arg.isRela ? RELOCATION_GROUP_HAS_ADDEND_FLAG : 0;
 
   uint64_t offset = 0;
   uint64_t addend = 0;
@@ -1941,7 +1941,7 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
         RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela);
     add(g[0].r_offset - offset);
     add(ctx.target->relativeRel);
-    if (config->isRela) {
+    if (ctx.arg.isRela) {
       add(g[0].r_addend - addend);
       addend = g[0].r_addend;
     }
@@ -1950,9 +1950,9 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
     add(g.size() - 1);
     add(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG |
         RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela);
-    add(config->wordsize);
+    add(ctx.arg.wordsize);
     add(ctx.target->relativeRel);
-    if (config->isRela) {
+    if (ctx.arg.isRela) {
       for (const auto &i : llvm::drop_begin(g)) {
         add(i.r_addend - addend);
         addend = i.r_addend;
@@ -1970,7 +1970,7 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
     for (Elf_Rela &r : ungroupedRelatives) {
       add(r.r_offset - offset);
       offset = r.r_offset;
-      if (config->isRela) {
+      if (ctx.arg.isRela) {
         add(r.r_addend - addend);
         addend = r.r_addend;
       }
@@ -1997,7 +1997,7 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
       add(r.r_offset - offset);
       offset = r.r_offset;
       add(r.r_info);
-      if (config->isRela) {
+      if (ctx.arg.isRela) {
         add(r.r_addend - addend);
         addend = r.r_addend;
       }
@@ -2020,7 +2020,7 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
 template <class ELFT>
 RelrSection<ELFT>::RelrSection(unsigned concurrency, bool isAArch64Auth)
     : RelrBaseSection(concurrency, isAArch64Auth) {
-  this->entsize = config->wordsize;
+  this->entsize = ctx.arg.wordsize;
 }
 
 template <class ELFT> bool RelrSection<ELFT>::updateAllocSize() {
@@ -2109,7 +2109,7 @@ template <class ELFT> bool RelrSection<ELFT>::updateAllocSize() {
 SymbolTableBaseSection::SymbolTableBaseSection(StringTableSection &strTabSec)
     : SyntheticSection(strTabSec.isDynamic() ? (uint64_t)SHF_ALLOC : 0,
                        strTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB,
-                       config->wordsize,
+                       ctx.arg.wordsize,
                        strTabSec.isDynamic() ? ".dynsym" : ".symtab"),
       strTabSec(strTabSec) {}
 
@@ -2148,7 +2148,7 @@ void SymbolTableBaseSection::finalizeContents() {
   if (getPartition().gnuHashTab) {
     // NB: It also sorts Symbols to meet the GNU hash table requirements.
     getPartition().gnuHashTab->addSymbols(symbols);
-  } else if (config->emachine == EM_MIPS) {
+  } else if (ctx.arg.emachine == EM_MIPS) {
     llvm::stable_sort(symbols, sortMipsSymbols);
   }
 
@@ -2228,7 +2228,7 @@ SymbolTableSection<ELFT>::SymbolTableSection(StringTableSection &strTabSec)
 }
 
 static BssSection *getCommonSec(Symbol *sym) {
-  if (config->relocatable)
+  if (ctx.arg.relocatable)
     if (auto *d = dyn_cast<Defined>(sym))
       return dyn_cast_or_null<BssSection>(d->section);
   return nullptr;
@@ -2291,7 +2291,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) {
   // pointer equality by STO_MIPS_PLT flag. That is necessary to help
   // dynamic linker distinguish such symbols and MIPS lazy-binding stubs.
   // https://sourceware.org/ml/binutils/2008-07/txt00000.txt
-  if (config->emachine == EM_MIPS) {
+  if (ctx.arg.emachine == EM_MIPS) {
     auto *eSym = reinterpret_cast<Elf_Sym *>(buf);
 
     for (SymbolTableEntry &ent : symbols) {
@@ -2313,7 +2313,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) {
           eSym->st_other |= STO_MIPS_MICROMIPS;
         }
       }
-      if (config->relocatable)
+      if (ctx.arg.relocatable)
         if (auto *d = dyn_cast<Defined>(sym))
           if (isMipsPIC<ELFT>(d))
             eSym->st_other |= STO_MIPS_PIC;
@@ -2391,7 +2391,7 @@ size_t SymtabShndxSection::getSize() const {
 // 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") {
+    : SyntheticSection(SHF_ALLOC, SHT_GNU_HASH, ctx.arg.wordsize, ".gnu.hash") {
 }
 
 void GnuHashTableSection::finalizeContents() {
@@ -2404,11 +2404,11 @@ void GnuHashTableSection::finalizeContents() {
     maskWords = 1;
   } else {
     uint64_t numBits = symbols.size() * 12;
-    maskWords = NextPowerOf2(numBits / (config->wordsize * 8));
+    maskWords = NextPowerOf2(numBits / (ctx.arg.wordsize * 8));
   }
 
   size = 16;                            // Header
-  size += config->wordsize * maskWords; // Bloom filter
+  size += ctx.arg.wordsize * maskWords; // Bloom filter
   size += nBuckets * 4;                 // Hash buckets
   size += symbols.size() * 4;           // Hash values
 }
@@ -2422,17 +2422,17 @@ void GnuHashTableSection::writeTo(uint8_t *buf) {
   buf += 16;
 
   // Write the 2-bit bloom filter.
-  const unsigned c = config->is64 ? 64 : 32;
+  const unsigned c = ctx.arg.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].
     size_t i = (sym.hash / c) & (maskWords - 1);
-    uint64_t val = readUint(buf + i * config->wordsize);
+    uint64_t val = readUint(buf + i * ctx.arg.wordsize);
     val |= uint64_t(1) << (sym.hash % c);
     val |= uint64_t(1) << ((sym.hash >> Shift2) % c);
-    writeUint(buf + i * config->wordsize, val);
+    writeUint(buf + i * ctx.arg.wordsize, val);
   }
-  buf += config->wordsize * maskWords;
+  buf += ctx.arg.wordsize * maskWords;
 
   // Write the hash table.
   uint32_t *buckets = reinterpret_cast<uint32_t *>(buf);
@@ -2543,20 +2543,20 @@ PltSection::PltSection()
     : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, ".plt"),
       headerSize(ctx.target->pltHeaderSize) {
   // On PowerPC, this section contains lazy symbol resolvers.
-  if (config->emachine == EM_PPC64) {
+  if (ctx.arg.emachine == EM_PPC64) {
     name = ".glink";
     addralign = 4;
   }
 
   // On x86 when IBT is enabled, this section contains the second PLT (lazy
   // symbol resolvers).
-  if ((config->emachine == EM_386 || config->emachine == EM_X86_64) &&
-      (config->andFeatures & GNU_PROPERTY_X86_FEATURE_1_IBT))
+  if ((ctx.arg.emachine == EM_386 || ctx.arg.emachine == EM_X86_64) &&
+      (ctx.arg.andFeatures & GNU_PROPERTY_X86_FEATURE_1_IBT))
     name = ".plt.sec";
 
   // The PLT needs to be writable on SPARC as the dynamic linker will
   // modify the instructions in the PLT entries.
-  if (config->emachine == EM_SPARCV9)
+  if (ctx.arg.emachine == EM_SPARCV9)
     this->flags |= SHF_WRITE;
 }
 
@@ -2584,7 +2584,7 @@ size_t PltSection::getSize() const {
 
 bool PltSection::isNeeded() const {
   // For -z retpolineplt, .iplt needs the .plt header.
-  return !entries.empty() || (config->zRetpolineplt && ctx.in.iplt->isNeeded());
+  return !entries.empty() || (ctx.arg.zRetpolineplt && ctx.in.iplt->isNeeded());
 }
 
 // Used by ARM to add mapping symbols in the PLT section, which aid
@@ -2601,7 +2601,7 @@ void PltSection::addSymbols() {
 
 IpltSection::IpltSection()
     : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, ".iplt") {
-  if (config->emachine == EM_PPC || config->emachine == EM_PPC64) {
+  if (ctx.arg.emachine == EM_PPC || ctx.arg.emachine == EM_PPC64) {
     name = ".glink";
     addralign = 4;
   }
@@ -3027,7 +3027,7 @@ std::pair<uint32_t, uint32_t> DebugNamesBaseSection::computeEntryPool(
   // Speed it up using multithreading, as the number of symbols can be in the
   // order of millions.
   const size_t concurrency =
-      bit_floor(std::min<size_t>(config->threadCount, numShards));
+      bit_floor(std::min<size_t>(ctx.arg.threadCount, numShards));
   const size_t shift = 32 - countr_zero(numShards);
   const uint8_t cuAttrSize = getMergedCuCountForm(hdr.CompUnitCount).first;
   DenseMap<CachedHashStringRef, size_t> maps[numShards];
@@ -3431,7 +3431,7 @@ createSymbols(
   // Shard GdbSymbols by hash's high bits.
   constexpr size_t numShards = 32;
   const size_t concurrency =
-      llvm::bit_floor(std::min<size_t>(config->threadCount, numShards));
+      llvm::bit_floor(std::min<size_t>(ctx.arg.threadCount, numShards));
   const size_t shift = 32 - llvm::countr_zero(numShards);
   auto map =
       std::make_unique<DenseMap<CachedHashStringRef, size_t>[]>(numShards);
@@ -3672,9 +3672,9 @@ VersionDefinitionSection::VersionDefinitionSection()
 StringRef VersionDefinitionSection::getFileDefName() {
   if (!getPartition().name.empty())
     return getPartition().name;
-  if (!config->soName.empty())
-    return config->soName;
-  return config->outputFile;
+  if (!ctx.arg.soName.empty())
+    return ctx.arg.soName;
+  return ctx.arg.outputFile;
 }
 
 void VersionDefinitionSection::finalizeContents() {
@@ -3789,7 +3789,7 @@ template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() {
     verneeds.emplace_back();
     Verneed &vn = verneeds.back();
     vn.nameStrTab = getPartition().dynStrTab->addString(f->soName);
-    bool isLibc = config->relrGlibc && f->soName.starts_with("libc.so.");
+    bool isLibc = ctx.arg.relrGlibc && f->soName.starts_with("libc.so.");
     bool isGlibc2 = false;
     for (unsigned i = 0; i != f->vernauxs.size(); ++i) {
       if (f->vernauxs[i] == 0)
@@ -3911,7 +3911,7 @@ void MergeNoTailSection::finalizeContents() {
   // Concurrency level. Must be a power of 2 to avoid expensive modulo
   // operations in the following tight loop.
   const size_t concurrency =
-      llvm::bit_floor(std::min<size_t>(config->threadCount, numShards));
+      llvm::bit_floor(std::min<size_t>(ctx.arg.threadCount, numShards));
 
   // Add section pieces to the builders.
   parallelFor(0, concurrency, [&](size_t threadId) {
@@ -3987,12 +3987,12 @@ void elf::combineEhSections() {
 }
 
 MipsRldMapSection::MipsRldMapSection()
-    : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, config->wordsize,
+    : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, ctx.arg.wordsize,
                        ".rld_map") {}
 
 ARMExidxSyntheticSection::ARMExidxSyntheticSection()
     : SyntheticSection(SHF_ALLOC | SHF_LINK_ORDER, SHT_ARM_EXIDX,
-                       config->wordsize, ".ARM.exidx") {}
+                       ctx.arg.wordsize, ".ARM.exidx") {}
 
 static InputSection *findExidxSection(InputSection *isec) {
   for (InputSection *d : isec->dependentSections)
@@ -4029,7 +4029,7 @@ bool ARMExidxSyntheticSection::addSection(InputSection *isec) {
   // and we would have to erase at a late stage relocations from merged entries.
   // Given that exception tables are already position independent and a binary
   // analyzer could derive the relocations we choose to erase the relocations.
-  if (config->emitRelocs && isec->type == SHT_REL)
+  if (ctx.arg.emitRelocs && isec->type == SHT_REL)
     if (InputSectionBase *ex = isec->getRelocatedSection())
       if (isa<InputSection>(ex) && ex->type == SHT_ARM_EXIDX)
         return true;
@@ -4090,7 +4090,7 @@ void ARMExidxSyntheticSection::finalizeContents() {
   // of sections.
   if (!originalExecutableSections.empty())
     executableSections = originalExecutableSections;
-  else if (config->enableNonContiguousRegions)
+  else if (ctx.arg.enableNonContiguousRegions)
     originalExecutableSections = executableSections;
 
   // The executableSections and exidxSections that we use to derive the final
@@ -4128,7 +4128,7 @@ void ARMExidxSyntheticSection::finalizeContents() {
   llvm::stable_sort(executableSections, compareByFilePosition);
   sentinel = executableSections.back();
   // std::optionally merge adjacent duplicate entries.
-  if (config->mergeArmExidx) {
+  if (ctx.arg.mergeArmExidx) {
     SmallVector<InputSection *, 0> selectedSections;
     selectedSections.reserve(executableSections.size());
     selectedSections.push_back(executableSections[0]);
@@ -4216,7 +4216,7 @@ bool ARMExidxSyntheticSection::isNeeded() const {
 
 ThunkSection::ThunkSection(OutputSection *os, uint64_t off)
     : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
-                       config->emachine == EM_PPC64 ? 16 : 4, ".text.thunk") {
+                       ctx.arg.emachine == EM_PPC64 ? 16 : 4, ".text.thunk") {
   this->parent = os;
   this->outSecOff = off;
 }
@@ -4293,7 +4293,7 @@ void PPC32Got2Section::finalizeContents() {
 // allocated and filled in by the dynamic linker.
 PPC64LongBranchTargetSection::PPC64LongBranchTargetSection()
     : SyntheticSection(SHF_ALLOC | SHF_WRITE,
-                       config->isPic ? SHT_NOBITS : SHT_PROGBITS, 8,
+                       ctx.arg.isPic ? SHT_NOBITS : SHT_PROGBITS, 8,
                        ".branch_lt") {}
 
 uint64_t PPC64LongBranchTargetSection::getEntryVA(const Symbol *sym,
@@ -4319,7 +4319,7 @@ 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.
-  if (config->isPic)
+  if (ctx.arg.isPic)
     return;
 
   for (auto entry : entries) {
@@ -4346,14 +4346,14 @@ bool PPC64LongBranchTargetSection::isNeeded() const {
 
 static uint8_t getAbiVersion() {
   // MIPS non-PIC executable gets ABI version 1.
-  if (config->emachine == EM_MIPS) {
-    if (!config->isPic && !config->relocatable &&
-        (config->eflags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC)
+  if (ctx.arg.emachine == EM_MIPS) {
+    if (!ctx.arg.isPic && !ctx.arg.relocatable &&
+        (ctx.arg.eflags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC)
       return 1;
     return 0;
   }
 
-  if (config->emachine == EM_AMDGPU && !ctx.objectFiles.empty()) {
+  if (ctx.arg.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)
@@ -4372,16 +4372,16 @@ template <typename ELFT> void elf::writeEhdr(uint8_t *buf, Partition &part) {
   eHdr->e_ident[EI_DATA] =
       ELFT::Endianness == endianness::little ? ELFDATA2LSB : ELFDATA2MSB;
   eHdr->e_ident[EI_VERSION] = EV_CURRENT;
-  eHdr->e_ident[EI_OSABI] = config->osabi;
+  eHdr->e_ident[EI_OSABI] = ctx.arg.osabi;
   eHdr->e_ident[EI_ABIVERSION] = getAbiVersion();
-  eHdr->e_machine = config->emachine;
+  eHdr->e_machine = ctx.arg.emachine;
   eHdr->e_version = EV_CURRENT;
-  eHdr->e_flags = config->eflags;
+  eHdr->e_flags = ctx.arg.eflags;
   eHdr->e_ehsize = sizeof(typename ELFT::Ehdr);
   eHdr->e_phnum = part.phdrs.size();
   eHdr->e_shentsize = sizeof(typename ELFT::Shdr);
 
-  if (!config->relocatable) {
+  if (!ctx.arg.relocatable) {
     eHdr->e_phoff = sizeof(typename ELFT::Ehdr);
     eHdr->e_phentsize = sizeof(typename ELFT::Phdr);
   }
@@ -4497,13 +4497,13 @@ void InStruct::reset() {
 }
 
 static bool needsInterpSection() {
-  return !config->relocatable && !config->shared &&
-         !config->dynamicLinker.empty() && ctx.script->needsInterpSection();
+  return !ctx.arg.relocatable && !ctx.arg.shared &&
+         !ctx.arg.dynamicLinker.empty() && ctx.script->needsInterpSection();
 }
 
 bool elf::hasMemtag() {
-  return config->emachine == EM_AARCH64 &&
-         config->androidMemtagMode != ELF::NT_MEMTAG_LEVEL_NONE;
+  return ctx.arg.emachine == EM_AARCH64 &&
+         ctx.arg.androidMemtagMode != ELF::NT_MEMTAG_LEVEL_NONE;
 }
 
 // Fully static executables don't support MTE globals at this point in time, as
@@ -4514,7 +4514,7 @@ bool elf::hasMemtag() {
 // that ifuncs use in fully static executables.
 bool elf::canHaveMemtagGlobals() {
   return hasMemtag() &&
-         (config->relocatable || config->shared || needsInterpSection());
+         (ctx.arg.relocatable || ctx.arg.shared || needsInterpSection());
 }
 
 constexpr char kMemtagAndroidNoteName[] = "Android";
@@ -4531,12 +4531,12 @@ void MemtagAndroidNote::writeTo(uint8_t *buf) {
   buf += 12 + alignTo(sizeof(kMemtagAndroidNoteName), 4);
 
   uint32_t value = 0;
-  value |= config->androidMemtagMode;
-  if (config->androidMemtagHeap)
+  value |= ctx.arg.androidMemtagMode;
+  if (ctx.arg.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)
+  if (ctx.arg.androidMemtagStack)
     value |= ELF::NT_MEMTAG_STACK;
   write32(buf, value); // note value
 }
@@ -4549,16 +4549,16 @@ size_t MemtagAndroidNote::getSize() const {
 
 void PackageMetadataNote::writeTo(uint8_t *buf) {
   write32(buf, 4);
-  write32(buf + 4, config->packageMetadata.size() + 1);
+  write32(buf + 4, ctx.arg.packageMetadata.size() + 1);
   write32(buf + 8, FDO_PACKAGING_METADATA);
   memcpy(buf + 12, "FDO", 4);
-  memcpy(buf + 16, config->packageMetadata.data(),
-         config->packageMetadata.size());
+  memcpy(buf + 16, ctx.arg.packageMetadata.data(),
+         ctx.arg.packageMetadata.size());
 }
 
 size_t PackageMetadataNote::getSize() const {
   return sizeof(llvm::ELF::Elf64_Nhdr) + 4 +
-         alignTo(config->packageMetadata.size() + 1, 4);
+         alignTo(ctx.arg.packageMetadata.size() + 1, 4);
 }
 
 // Helper function, return the size of the ULEB128 for 'v', optionally writing
@@ -4667,13 +4667,13 @@ template <class ELFT> void elf::createSyntheticSections() {
 
   auto add = [](SyntheticSection &sec) { ctx.inputSections.push_back(&sec); };
 
-  if (config->zSectionHeader)
+  if (ctx.arg.zSectionHeader)
     ctx.in.shStrTab = std::make_unique<StringTableSection>(".shstrtab", false);
 
   ctx.out.programHeaders = make<OutputSection>("", 0, SHF_ALLOC);
-  ctx.out.programHeaders->addralign = config->wordsize;
+  ctx.out.programHeaders->addralign = ctx.arg.wordsize;
 
-  if (config->strip != StripPolicy::All) {
+  if (ctx.arg.strip != StripPolicy::All) {
     ctx.in.strTab = std::make_unique<StringTableSection>(".strtab", false);
     ctx.in.symTab = std::make_unique<SymbolTableSection<ELFT>>(*ctx.in.strTab);
     ctx.in.symTabShndx = std::make_unique<SymtabShndxSection>();
@@ -4692,8 +4692,8 @@ template <class ELFT> void elf::createSyntheticSections() {
   add(*ctx.in.bssRelRo);
 
   // Add MIPS-specific sections.
-  if (config->emachine == EM_MIPS) {
-    if (!config->shared && config->hasDynSymTab) {
+  if (ctx.arg.emachine == EM_MIPS) {
+    if (!ctx.arg.shared && ctx.arg.hasDynSymTab) {
       ctx.in.mipsRldMap = std::make_unique<MipsRldMapSection>();
       add(*ctx.in.mipsRldMap);
     }
@@ -4705,9 +4705,9 @@ template <class ELFT> void elf::createSyntheticSections() {
       add(*ctx.in.mipsReginfo);
   }
 
-  StringRef relaDynName = config->isRela ? ".rela.dyn" : ".rel.dyn";
+  StringRef relaDynName = ctx.arg.isRela ? ".rela.dyn" : ".rel.dyn";
 
-  const unsigned threadCount = config->threadCount;
+  const unsigned threadCount = ctx.arg.threadCount;
   for (Partition &part : ctx.partitions) {
     auto add = [&](SyntheticSection &sec) {
       sec.partition = part.getNumber();
@@ -4724,7 +4724,7 @@ template <class ELFT> void elf::createSyntheticSections() {
       add(*part.programHeaders);
     }
 
-    if (config->buildId != BuildIdKind::None) {
+    if (ctx.arg.buildId != BuildIdKind::None) {
       part.buildId = std::make_unique<BuildIdSection>();
       add(*part.buildId);
     }
@@ -4735,7 +4735,7 @@ template <class ELFT> void elf::createSyntheticSections() {
     part.dynSymTab =
         std::make_unique<SymbolTableSection<ELFT>>(*part.dynStrTab);
 
-    if (config->relocatable)
+    if (ctx.arg.relocatable)
       continue;
     part.dynamic = std::make_unique<DynamicSection<ELFT>>();
 
@@ -4749,14 +4749,14 @@ template <class ELFT> void elf::createSyntheticSections() {
       }
     }
 
-    if (config->androidPackDynRelocs)
+    if (ctx.arg.androidPackDynRelocs)
       part.relaDyn = std::make_unique<AndroidPackedRelocationSection<ELFT>>(
           relaDynName, threadCount);
     else
       part.relaDyn = std::make_unique<RelocationSection<ELFT>>(
-          relaDynName, config->zCombreloc, threadCount);
+          relaDynName, ctx.arg.zCombreloc, threadCount);
 
-    if (config->hasDynSymTab) {
+    if (ctx.arg.hasDynSymTab) {
       add(*part.dynSymTab);
 
       part.verSym = std::make_unique<VersionTableSection>();
@@ -4770,12 +4770,12 @@ template <class ELFT> void elf::createSyntheticSections() {
       part.verNeed = std::make_unique<VersionNeedSection<ELFT>>();
       add(*part.verNeed);
 
-      if (config->gnuHash) {
+      if (ctx.arg.gnuHash) {
         part.gnuHashTab = std::make_unique<GnuHashTableSection>();
         add(*part.gnuHashTab);
       }
 
-      if (config->sysvHash) {
+      if (ctx.arg.sysvHash) {
         part.hashTab = std::make_unique<HashTableSection>();
         add(*part.hashTab);
       }
@@ -4785,7 +4785,7 @@ template <class ELFT> void elf::createSyntheticSections() {
     }
     add(*part.relaDyn);
 
-    if (config->relrPackDynRelocs) {
+    if (ctx.arg.relrPackDynRelocs) {
       part.relrDyn = std::make_unique<RelrSection<ELFT>>(threadCount);
       add(*part.relrDyn);
       part.relrAuthDyn = std::make_unique<RelrSection<ELFT>>(
@@ -4793,20 +4793,20 @@ template <class ELFT> void elf::createSyntheticSections() {
       add(*part.relrAuthDyn);
     }
 
-    if (config->ehFrameHdr) {
+    if (ctx.arg.ehFrameHdr) {
       part.ehFrameHdr = std::make_unique<EhFrameHeader>();
       add(*part.ehFrameHdr);
     }
     part.ehFrame = std::make_unique<EhFrameSection>();
     add(*part.ehFrame);
 
-    if (config->emachine == EM_ARM) {
+    if (ctx.arg.emachine == EM_ARM) {
       // This section replaces all the individual .ARM.exidx InputSections.
       part.armExidx = std::make_unique<ARMExidxSyntheticSection>();
       add(*part.armExidx);
     }
 
-    if (!config->packageMetadata.empty()) {
+    if (!ctx.arg.packageMetadata.empty()) {
       part.packageMetadataNote = std::make_unique<PackageMetadataNote>();
       add(*part.packageMetadataNote);
     }
@@ -4817,7 +4817,7 @@ template <class ELFT> void elf::createSyntheticSections() {
     // so that it is sorted after all other partitions. It also has other
     // special handling (see createPhdrs() and combineEhSections()).
     ctx.in.partEnd =
-        std::make_unique<BssSection>(".part.end", config->maxPageSize, 1);
+        std::make_unique<BssSection>(".part.end", ctx.arg.maxPageSize, 1);
     ctx.in.partEnd->partition = 255;
     add(*ctx.in.partEnd);
 
@@ -4830,7 +4830,7 @@ template <class ELFT> void elf::createSyntheticSections() {
 
   // Add .got. MIPS' .got is so 
diff erent from the other archs,
   // it has its own class.
-  if (config->emachine == EM_MIPS) {
+  if (ctx.arg.emachine == EM_MIPS) {
     ctx.in.mipsGot = std::make_unique<MipsGotSection>();
     add(*ctx.in.mipsGot);
   } else {
@@ -4838,12 +4838,12 @@ template <class ELFT> void elf::createSyntheticSections() {
     add(*ctx.in.got);
   }
 
-  if (config->emachine == EM_PPC) {
+  if (ctx.arg.emachine == EM_PPC) {
     ctx.in.ppc32Got2 = std::make_unique<PPC32Got2Section>();
     add(*ctx.in.ppc32Got2);
   }
 
-  if (config->emachine == EM_PPC64) {
+  if (ctx.arg.emachine == EM_PPC64) {
     ctx.in.ppc64LongBranchTarget =
         std::make_unique<PPC64LongBranchTargetSection>();
     add(*ctx.in.ppc64LongBranchTarget);
@@ -4855,21 +4855,21 @@ template <class ELFT> void elf::createSyntheticSections() {
   add(*ctx.in.igotPlt);
   // Add .relro_padding if DATA_SEGMENT_RELRO_END is used; otherwise, add the
   // section in the absence of PHDRS/SECTIONS commands.
-  if (config->zRelro &&
+  if (ctx.arg.zRelro &&
       ((ctx.script->phdrsCommands.empty() && !ctx.script->hasSectionsCommand) ||
        ctx.script->seenRelroEnd)) {
     ctx.in.relroPadding = std::make_unique<RelroPaddingSection>();
     add(*ctx.in.relroPadding);
   }
 
-  if (config->emachine == EM_ARM) {
+  if (ctx.arg.emachine == EM_ARM) {
     ctx.in.armCmseSGSection = std::make_unique<ArmCmseSGSection>();
     add(*ctx.in.armCmseSGSection);
   }
 
   // _GLOBAL_OFFSET_TABLE_ is defined relative to either .got.plt or .got. Treat
   // it as a relocation and ensure the referenced section is created.
-  if (ctx.sym.globalOffsetTable && config->emachine != EM_MIPS) {
+  if (ctx.sym.globalOffsetTable && ctx.arg.emachine != EM_MIPS) {
     if (ctx.target->gotBaseSymInGotPlt)
       ctx.in.gotPlt->hasGotPltOffRel = true;
     else
@@ -4879,17 +4879,17 @@ template <class ELFT> void elf::createSyntheticSections() {
   // We always need to add rel[a].plt to output if it has entries.
   // Even for static linking it can contain R_[*]_IRELATIVE relocations.
   ctx.in.relaPlt = std::make_unique<RelocationSection<ELFT>>(
-      config->isRela ? ".rela.plt" : ".rel.plt", /*sort=*/false,
+      ctx.arg.isRela ? ".rela.plt" : ".rel.plt", /*sort=*/false,
       /*threadCount=*/1);
   add(*ctx.in.relaPlt);
 
-  if ((config->emachine == EM_386 || config->emachine == EM_X86_64) &&
-      (config->andFeatures & GNU_PROPERTY_X86_FEATURE_1_IBT)) {
+  if ((ctx.arg.emachine == EM_386 || ctx.arg.emachine == EM_X86_64) &&
+      (ctx.arg.andFeatures & GNU_PROPERTY_X86_FEATURE_1_IBT)) {
     ctx.in.ibtPlt = std::make_unique<IBTPltSection>();
     add(*ctx.in.ibtPlt);
   }
 
-  if (config->emachine == EM_PPC)
+  if (ctx.arg.emachine == EM_PPC)
     ctx.in.plt = std::make_unique<PPC32GlinkSection>();
   else
     ctx.in.plt = std::make_unique<PltSection>();
@@ -4897,15 +4897,15 @@ template <class ELFT> void elf::createSyntheticSections() {
   ctx.in.iplt = std::make_unique<IpltSection>();
   add(*ctx.in.iplt);
 
-  if (config->andFeatures || !ctx.aarch64PauthAbiCoreInfo.empty())
+  if (ctx.arg.andFeatures || !ctx.aarch64PauthAbiCoreInfo.empty())
     add(*make<GnuPropertySection>());
 
-  if (config->debugNames) {
+  if (ctx.arg.debugNames) {
     ctx.in.debugNames = std::make_unique<DebugNamesSection<ELFT>>();
     add(*ctx.in.debugNames);
   }
 
-  if (config->gdbIndex) {
+  if (ctx.arg.gdbIndex) {
     ctx.in.gdbIndex = GdbIndexSection::create<ELFT>();
     add(*ctx.in.gdbIndex);
   }
@@ -4915,7 +4915,7 @@ template <class ELFT> void elf::createSyntheticSections() {
   // section to control the executable-ness of the stack area, but that
   // is irrelevant these days. Stack area should always be non-executable
   // by default. So we emit this section unconditionally.
-  if (config->relocatable)
+  if (ctx.arg.relocatable)
     add(*make<GnuStackSection>());
 
   if (ctx.in.symTab)

diff  --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 8e2664d64118b7..6d0634e0a16e90 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -533,7 +533,7 @@ class RelocationBaseSection : public SyntheticSection {
                 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))
+    if (ctx.arg.writeAddends && (expr != R_ADDEND || addend != 0))
       sec.addReloc({expr, addendRelType, offsetInSec, addend, &sym});
     addReloc<shard>({dynType, &sec, offsetInSec, kind, sym, addend, expr});
   }
@@ -551,7 +551,7 @@ class RelocationBaseSection : public SyntheticSection {
            (d->type == llvm::ELF::SHT_RELA || d->type == llvm::ELF::SHT_REL ||
             d->type == llvm::ELF::SHT_RELR ||
             (d->type == llvm::ELF::SHT_AARCH64_AUTH_RELR &&
-             config->emachine == llvm::ELF::EM_AARCH64));
+             ctx.arg.emachine == llvm::ELF::EM_AARCH64));
   }
   int32_t dynamicTag, sizeDynamicTag;
   SmallVector<DynamicReloc, 0> relocs;
@@ -1190,7 +1190,7 @@ template <class ELFT> class MipsReginfoSection final : public SyntheticSection {
 class MipsRldMapSection final : public SyntheticSection {
 public:
   MipsRldMapSection();
-  size_t getSize() const override { return config->wordsize; }
+  size_t getSize() const override { return ctx.arg.wordsize; }
   void writeTo(uint8_t *buf) override {}
 };
 


        


More information about the llvm-commits mailing list