[lld] 38dfcd9 - [ELF] Pass Ctx & to read32/write32

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 13 10:37:54 PDT 2024


Author: Fangrui Song
Date: 2024-10-13T10:37:47-07:00
New Revision: 38dfcd9ac9cceaebc86fc3d08bdc29ecef82c874

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

LOG: [ELF] Pass Ctx & to read32/write32

Added: 
    

Modified: 
    lld/ELF/Arch/AArch64.cpp
    lld/ELF/Arch/ARM.cpp
    lld/ELF/Arch/Hexagon.cpp
    lld/ELF/Arch/Mips.cpp
    lld/ELF/Arch/PPC.cpp
    lld/ELF/Arch/PPC64.cpp
    lld/ELF/Arch/RISCV.cpp
    lld/ELF/OutputSections.cpp
    lld/ELF/SyntheticSections.cpp
    lld/ELF/Target.h
    lld/ELF/Thunks.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 51d2f19c6f9296..e1b06240493635 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -265,7 +265,7 @@ int64_t AArch64::getImplicitAddend(const uint8_t *buf, RelType type) const {
     return SignExtend64<16>(read16(buf));
   case R_AARCH64_ABS32:
   case R_AARCH64_PREL32:
-    return SignExtend64<32>(read32(buf));
+    return SignExtend64<32>(read32(ctx, buf));
   case R_AARCH64_ABS64:
   case R_AARCH64_PREL64:
   case R_AARCH64_RELATIVE:
@@ -490,12 +490,12 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
   case R_AARCH64_ABS32:
   case R_AARCH64_PREL32:
     checkIntUInt(loc, val, 32, rel);
-    write32(loc, val);
+    write32(ctx, loc, val);
     break;
   case R_AARCH64_PLT32:
   case R_AARCH64_GOTPCREL32:
     checkInt(loc, val, 32, rel);
-    write32(loc, val);
+    write32(ctx, loc, val);
     break;
   case R_AARCH64_ABS64:
     // AArch64 relocations to tagged symbols have extended semantics, as
@@ -526,7 +526,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
     //   finalizeAddressDependentContent(). Writing the value is harmless
     //   because dynamic linking ignores it.
     if (isInt<32>(val))
-      write32(loc, val);
+      write32(ctx, loc, val);
     break;
   case R_AARCH64_ADD_ABS_LO12_NC:
     write32Imm12(loc, val);

diff  --git a/lld/ELF/Arch/ARM.cpp b/lld/ELF/Arch/ARM.cpp
index 2219d2d6ce0c41..d6fbea13e8d725 100644
--- a/lld/ELF/Arch/ARM.cpp
+++ b/lld/ELF/Arch/ARM.cpp
@@ -208,28 +208,28 @@ RelType ARM::getDynRel(RelType type) const {
 }
 
 void ARM::writeGotPlt(uint8_t *buf, const Symbol &) const {
-  write32(buf, ctx.in.plt->getVA());
+  write32(ctx, buf, ctx.in.plt->getVA());
 }
 
 void ARM::writeIgotPlt(uint8_t *buf, const Symbol &s) const {
   // An ARM entry is the address of the ifunc resolver function.
-  write32(buf, s.getVA());
+  write32(ctx, buf, s.getVA());
 }
 
 // Long form PLT Header that does not have any restrictions on the displacement
 // of the .plt from the .got.plt.
 static void writePltHeaderLong(Ctx &ctx, uint8_t *buf) {
-  write32(buf + 0, 0xe52de004);   //     str lr, [sp,#-4]!
-  write32(buf + 4, 0xe59fe004);   //     ldr lr, L2
-  write32(buf + 8, 0xe08fe00e);   // L1: add lr, pc, lr
-  write32(buf + 12, 0xe5bef008);  //     ldr pc, [lr, #8]
-  write32(buf + 16, 0x00000000);  // L2: .word   &(.got.plt) - L1 - 8
-  write32(buf + 20, 0xd4d4d4d4);  //     Pad to 32-byte boundary
-  write32(buf + 24, 0xd4d4d4d4);  //     Pad to 32-byte boundary
-  write32(buf + 28, 0xd4d4d4d4);
+  write32(ctx, buf + 0, 0xe52de004);  //     str lr, [sp,#-4]!
+  write32(ctx, buf + 4, 0xe59fe004);  //     ldr lr, L2
+  write32(ctx, buf + 8, 0xe08fe00e);  // L1: add lr, pc, lr
+  write32(ctx, buf + 12, 0xe5bef008); //     ldr pc, [lr, #8]
+  write32(ctx, buf + 16, 0x00000000); // L2: .word   &(.got.plt) - L1 - 8
+  write32(ctx, buf + 20, 0xd4d4d4d4); //     Pad to 32-byte boundary
+  write32(ctx, buf + 24, 0xd4d4d4d4); //     Pad to 32-byte boundary
+  write32(ctx, buf + 28, 0xd4d4d4d4);
   uint64_t gotPlt = ctx.in.gotPlt->getVA();
   uint64_t l1 = ctx.in.plt->getVA() + 8;
-  write32(buf + 16, gotPlt - l1 - 8);
+  write32(ctx, buf + 16, gotPlt - l1 - 8);
 }
 
 // True if we should use Thumb PLTs, which currently require Thumb2, and are
@@ -263,7 +263,7 @@ void ARM::writePltHeader(uint8_t *buf) const {
     // Split into two halves to support endianness correctly.
     write16(buf + 8, 0xf85e);
     write16(buf + 10, 0xff08);
-    write32(buf + 12, offset);
+    write32(ctx, buf + 12, offset);
 
     memcpy(buf + 16, trapInstr.data(), 4);  // Pad to 32-byte boundary
     memcpy(buf + 20, trapInstr.data(), 4);
@@ -287,10 +287,10 @@ void ARM::writePltHeader(uint8_t *buf) const {
       writePltHeaderLong(ctx, buf);
       return;
     }
-    write32(buf + 0, pltData[0]);
-    write32(buf + 4, pltData[1] | ((offset >> 20) & 0xff));
-    write32(buf + 8, pltData[2] | ((offset >> 12) & 0xff));
-    write32(buf + 12, pltData[3] | (offset & 0xfff));
+    write32(ctx, buf + 0, pltData[0]);
+    write32(ctx, buf + 4, pltData[1] | ((offset >> 20) & 0xff));
+    write32(ctx, buf + 8, pltData[2] | ((offset >> 12) & 0xff));
+    write32(ctx, buf + 12, pltData[3] | (offset & 0xfff));
     memcpy(buf + 16, trapInstr.data(), 4); // Pad to 32-byte boundary
     memcpy(buf + 20, trapInstr.data(), 4);
     memcpy(buf + 24, trapInstr.data(), 4);
@@ -312,12 +312,12 @@ void ARM::addPltHeaderSymbols(InputSection &isec) const {
 // of the .plt from the .got.plt.
 static void writePltLong(uint8_t *buf, uint64_t gotPltEntryAddr,
                          uint64_t pltEntryAddr) {
-  write32(buf + 0, 0xe59fc004);   //     ldr ip, L2
-  write32(buf + 4, 0xe08cc00f);   // L1: add ip, ip, pc
-  write32(buf + 8, 0xe59cf000);   //     ldr pc, [ip]
-  write32(buf + 12, 0x00000000);  // L2: .word   Offset(&(.got.plt) - L1 - 8
+  write32(ctx, buf + 0, 0xe59fc004);  //     ldr ip, L2
+  write32(ctx, buf + 4, 0xe08cc00f);  // L1: add ip, ip, pc
+  write32(ctx, buf + 8, 0xe59cf000);  //     ldr pc, [ip]
+  write32(ctx, buf + 12, 0x00000000); // L2: .word   Offset(&(.got.plt) - L1 - 8
   uint64_t l1 = pltEntryAddr + 4;
-  write32(buf + 12, gotPltEntryAddr - l1 - 8);
+  write32(ctx, buf + 12, gotPltEntryAddr - l1 - 8);
 }
 
 // The default PLT entries require the .got.plt to be within 128 Mb of the
@@ -342,9 +342,9 @@ void ARM::writePlt(uint8_t *buf, const Symbol &sym,
       writePltLong(buf, sym.getGotPltVA(ctx), pltEntryAddr);
       return;
     }
-    write32(buf + 0, pltData[0] | ((offset >> 20) & 0xff));
-    write32(buf + 4, pltData[1] | ((offset >> 12) & 0xff));
-    write32(buf + 8, pltData[2] | (offset & 0xfff));
+    write32(ctx, buf + 0, pltData[0] | ((offset >> 20) & 0xff));
+    write32(ctx, buf + 4, pltData[1] | ((offset >> 12) & 0xff));
+    write32(ctx, buf + 8, pltData[2] | (offset & 0xfff));
     memcpy(buf + 12, trapInstr.data(), 4); // Pad to 16-byte boundary
   } else {
     uint64_t offset = sym.getGotPltVA(ctx) - pltEntryAddr - 12;
@@ -558,7 +558,8 @@ void ARM::encodeAluGroup(uint8_t *loc, const Relocation &rel, uint64_t val,
   if (check && imm > 0xff)
     error(getErrorLoc(ctx, loc) + "unencodeable immediate " + Twine(val).str() +
           " for relocation " + toString(rel.type));
-  write32(loc, (read32(loc) & 0xff3ff000) | opcode | rot | (imm & 0xff));
+  write32(ctx, loc,
+          (read32(ctx, loc) & 0xff3ff000) | opcode | rot | (imm & 0xff));
 }
 
 static void encodeLdrGroup(uint8_t *loc, const Relocation &rel, uint64_t val,
@@ -576,7 +577,7 @@ static void encodeLdrGroup(uint8_t *loc, const Relocation &rel, uint64_t val,
   }
   uint32_t imm = getRemAndLZForGroup(group, val).first;
   checkUInt(loc, imm, 12, rel);
-  write32(loc, (read32(loc) & 0xff7ff000) | opcode | imm);
+  write32(ctx, loc, (read32(ctx, loc) & 0xff7ff000) | opcode | imm);
 }
 
 static void encodeLdrsGroup(uint8_t *loc, const Relocation &rel, uint64_t val,
@@ -594,8 +595,9 @@ static void encodeLdrsGroup(uint8_t *loc, const Relocation &rel, uint64_t val,
   }
   uint32_t imm = getRemAndLZForGroup(group, val).first;
   checkUInt(loc, imm, 8, rel);
-  write32(loc, (read32(loc) & 0xff7ff0f0) | opcode | ((imm & 0xf0) << 4) |
-                     (imm & 0xf));
+  write32(ctx, loc,
+          (read32(ctx, loc) & 0xff7ff0f0) | opcode | ((imm & 0xf0) << 4) |
+              (imm & 0xf));
 }
 
 void ARM::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
@@ -617,11 +619,11 @@ void ARM::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   case R_ARM_TLS_LE32:
   case R_ARM_TLS_TPOFF32:
   case R_ARM_TLS_DTPOFF32:
-    write32(loc, val);
+    write32(ctx, loc, val);
     break;
   case R_ARM_PREL31:
     checkInt(loc, val, 31, rel);
-    write32(loc, (read32(loc) & 0x80000000) | (val & ~0x80000000));
+    write32(ctx, loc, (read32(ctx, loc) & 0x80000000) | (val & ~0x80000000));
     break;
   case R_ARM_CALL: {
     // R_ARM_CALL is used for BL and BLX instructions, for symbols of type
@@ -630,7 +632,7 @@ void ARM::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     // not of type STT_FUNC then we must preserve the original instruction.
     assert(rel.sym); // R_ARM_CALL is always reached via relocate().
     bool bit0Thumb = val & 1;
-    bool isBlx = (read32(loc) & 0xfe000000) == 0xfa000000;
+    bool isBlx = (read32(ctx, loc) & 0xfe000000) == 0xfa000000;
     // lld 10.0 and before always used bit0Thumb when deciding to write a BLX
     // even when type not STT_FUNC.
     if (!rel.sym->isFunc() && isBlx != bit0Thumb)
@@ -638,14 +640,15 @@ void ARM::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     if (rel.sym->isFunc() ? bit0Thumb : isBlx) {
       // The BLX encoding is 0xfa:H:imm24 where Val = imm24:H:'1'
       checkInt(loc, val, 26, rel);
-      write32(loc, 0xfa000000 |                    // opcode
-                         ((val & 2) << 23) |         // H
-                         ((val >> 2) & 0x00ffffff)); // imm24
+      write32(ctx, loc,
+              0xfa000000 |                    // opcode
+                  ((val & 2) << 23) |         // H
+                  ((val >> 2) & 0x00ffffff)); // imm24
       break;
     }
     // BLX (always unconditional) instruction to an ARM Target, select an
     // unconditional BL.
-    write32(loc, 0xeb000000 | (read32(loc) & 0x00ffffff));
+    write32(ctx, loc, 0xeb000000 | (read32(ctx, loc) & 0x00ffffff));
     // fall through as BL encoding is shared with B
   }
     [[fallthrough]];
@@ -653,17 +656,18 @@ void ARM::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   case R_ARM_PC24:
   case R_ARM_PLT32:
     checkInt(loc, val, 26, rel);
-    write32(loc, (read32(loc) & ~0x00ffffff) | ((val >> 2) & 0x00ffffff));
+    write32(ctx, loc,
+            (read32(ctx, loc) & ~0x00ffffff) | ((val >> 2) & 0x00ffffff));
     break;
   case R_ARM_THM_JUMP8:
     // We do a 9 bit check because val is right-shifted by 1 bit.
     checkInt(loc, val, 9, rel);
-    write16(loc, (read32(loc) & 0xff00) | ((val >> 1) & 0x00ff));
+    write16(loc, (read32(ctx, loc) & 0xff00) | ((val >> 1) & 0x00ff));
     break;
   case R_ARM_THM_JUMP11:
     // We do a 12 bit check because val is right-shifted by 1 bit.
     checkInt(loc, val, 12, rel);
-    write16(loc, (read32(loc) & 0xf800) | ((val >> 1) & 0x07ff));
+    write16(loc, (read32(ctx, loc) & 0xf800) | ((val >> 1) & 0x07ff));
     break;
   case R_ARM_THM_JUMP19:
     // Encoding T3: Val = S:J2:J1:imm6:imm11:0
@@ -733,14 +737,16 @@ void ARM::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
   case R_ARM_MOVW_ABS_NC:
   case R_ARM_MOVW_PREL_NC:
   case R_ARM_MOVW_BREL_NC:
-    write32(loc, (read32(loc) & ~0x000f0fff) | ((val & 0xf000) << 4) |
-                       (val & 0x0fff));
+    write32(ctx, loc,
+            (read32(ctx, loc) & ~0x000f0fff) | ((val & 0xf000) << 4) |
+                (val & 0x0fff));
     break;
   case R_ARM_MOVT_ABS:
   case R_ARM_MOVT_PREL:
   case R_ARM_MOVT_BREL:
-    write32(loc, (read32(loc) & ~0x000f0fff) |
-                       (((val >> 16) & 0xf000) << 4) | ((val >> 16) & 0xfff));
+    write32(ctx, loc,
+            (read32(ctx, loc) & ~0x000f0fff) | (((val >> 16) & 0xf000) << 4) |
+                ((val >> 16) & 0xfff));
     break;
   case R_ARM_THM_MOVT_ABS:
   case R_ARM_THM_MOVT_PREL:
@@ -890,14 +896,14 @@ int64_t ARM::getImplicitAddend(const uint8_t *buf, RelType type) const {
   case R_ARM_TLS_LE32:
   case R_ARM_TLS_LDO32:
   case R_ARM_TLS_TPOFF32:
-    return SignExtend64<32>(read32(buf));
+    return SignExtend64<32>(read32(ctx, buf));
   case R_ARM_PREL31:
-    return SignExtend64<31>(read32(buf));
+    return SignExtend64<31>(read32(ctx, buf));
   case R_ARM_CALL:
   case R_ARM_JUMP24:
   case R_ARM_PC24:
   case R_ARM_PLT32:
-    return SignExtend64<26>(read32(buf) << 2);
+    return SignExtend64<26>(read32(ctx, buf) << 2);
   case R_ARM_THM_JUMP8:
     return SignExtend64<9>(read16(buf) << 1);
   case R_ARM_THM_JUMP11:
@@ -942,7 +948,7 @@ int64_t ARM::getImplicitAddend(const uint8_t *buf, RelType type) const {
   case R_ARM_MOVT_PREL:
   case R_ARM_MOVW_BREL_NC:
   case R_ARM_MOVT_BREL: {
-    uint64_t val = read32(buf) & 0x000f0fff;
+    uint64_t val = read32(ctx, buf) & 0x000f0fff;
     return SignExtend64<16>(((val & 0x000f0000) >> 4) | (val & 0x00fff));
   }
   case R_ARM_THM_MOVW_ABS_NC:
@@ -973,7 +979,7 @@ int64_t ARM::getImplicitAddend(const uint8_t *buf, RelType type) const {
     // right rotation and 8-bit constant. After the rotation the value
     // is zero-extended. When bit 23 is set the instruction is an add, when
     // bit 22 is set it is a sub.
-    uint32_t instr = read32(buf);
+    uint32_t instr = read32(ctx, buf);
     uint32_t val = rotr32(instr & 0xff, ((instr & 0xf00) >> 8) * 2);
     return (instr & 0x00400000) ? -val : val;
   }
@@ -982,15 +988,15 @@ int64_t ARM::getImplicitAddend(const uint8_t *buf, RelType type) const {
   case R_ARM_LDR_PC_G2: {
     // ADR (literal) add = bit23, sub = bit22
     // LDR (literal) u = bit23 unsigned imm12
-    bool u = read32(buf) & 0x00800000;
-    uint32_t imm12 = read32(buf) & 0xfff;
+    bool u = read32(ctx, buf) & 0x00800000;
+    uint32_t imm12 = read32(ctx, buf) & 0xfff;
     return u ? imm12 : -imm12;
   }
   case R_ARM_LDRS_PC_G0:
   case R_ARM_LDRS_PC_G1:
   case R_ARM_LDRS_PC_G2: {
     // LDRD/LDRH/LDRSB/LDRSH (literal) u = bit23 unsigned imm8
-    uint32_t opcode = read32(buf);
+    uint32_t opcode = read32(ctx, buf);
     bool u = opcode & 0x00800000;
     uint32_t imm4l = opcode & 0xf;
     uint32_t imm4h = (opcode & 0xf00) >> 4;
@@ -1089,7 +1095,7 @@ static void toLittleEndianInstructions(uint8_t *buf, uint64_t start,
   CodeState curState = static_cast<CodeState>(width);
   if (curState == CodeState::Arm)
     for (uint64_t i = start; i < end; i += width)
-      write32le(buf + i, read32(buf + i));
+      write32le(buf + i, read32(ctx, buf + i));
 
   if (curState == CodeState::Thumb)
     for (uint64_t i = start; i < end; i += width)

diff  --git a/lld/ELF/Arch/Hexagon.cpp b/lld/ELF/Arch/Hexagon.cpp
index 8c2d3126a3cc73..4f4d466ca75040 100644
--- a/lld/ELF/Arch/Hexagon.cpp
+++ b/lld/ELF/Arch/Hexagon.cpp
@@ -410,7 +410,7 @@ int64_t Hexagon::getImplicitAddend(const uint8_t *buf, RelType type) const {
   case R_HEX_DTPMOD_32:
   case R_HEX_DTPREL_32:
   case R_HEX_TPREL_32:
-    return SignExtend64<32>(read32(buf));
+    return SignExtend64<32>(read32(ctx, buf));
   default:
     internalLinkerError(getErrorLoc(ctx, buf),
                         "cannot read addend for relocation " + toString(type));

diff  --git a/lld/ELF/Arch/Mips.cpp b/lld/ELF/Arch/Mips.cpp
index 6313ac8ca4fb9a..8736b2cc734410 100644
--- a/lld/ELF/Arch/Mips.cpp
+++ b/lld/ELF/Arch/Mips.cpp
@@ -52,7 +52,7 @@ template <class ELFT> MIPS<ELFT>::MIPS(Ctx &ctx) : TargetInfo(ctx) {
   needsThunks = true;
 
   // Set `sigrie 1` as a trap instruction.
-  write32(trapInstr.data(), 0x04170001);
+  write32(ctx, trapInstr.data(), 0x04170001);
 
   if (ELFT::Is64Bits) {
     relativeRel = (R_MIPS_64 << 8) | R_MIPS_REL32;
@@ -208,7 +208,7 @@ void MIPS<ELFT>::writeGotPlt(uint8_t *buf, const Symbol &) const {
   uint64_t va = ctx.in.plt->getVA();
   if (isMicroMips(ctx))
     va |= 1;
-  write32(buf, va);
+  write32(ctx, buf, va);
 }
 
 template <endianness E> static uint32_t readShuffle(const uint8_t *loc) {
@@ -218,7 +218,7 @@ template <endianness E> static uint32_t readShuffle(const uint8_t *loc) {
   // as early as possible. To do so, little-endian binaries keep 16-bit
   // words in a big-endian order. That is why we have to swap these
   // words to get a correct value.
-  uint32_t v = read32(loc);
+  uint32_t v = read32(ctx, loc);
   if (E == llvm::endianness::little)
     return (v << 16) | (v >> 16);
   return v;
@@ -226,10 +226,10 @@ template <endianness E> static uint32_t readShuffle(const uint8_t *loc) {
 
 static void writeValue(uint8_t *loc, uint64_t v, uint8_t bitsSize,
                        uint8_t shift) {
-  uint32_t instr = read32(loc);
+  uint32_t instr = read32(ctx, loc);
   uint32_t mask = 0xffffffff >> (32 - bitsSize);
   uint32_t data = (instr & ~mask) | ((v >> shift) & mask);
-  write32(loc, data);
+  write32(ctx, loc, data);
 }
 
 template <endianness E>
@@ -284,31 +284,31 @@ template <class ELFT> void MIPS<ELFT>::writePltHeader(uint8_t *buf) const {
   }
 
   if (ctx.arg.mipsN32Abi) {
-    write32(buf, 0x3c0e0000);      // lui   $14, %hi(&GOTPLT[0])
-    write32(buf + 4, 0x8dd90000);  // lw    $25, %lo(&GOTPLT[0])($14)
-    write32(buf + 8, 0x25ce0000);  // addiu $14, $14, %lo(&GOTPLT[0])
-    write32(buf + 12, 0x030ec023); // subu  $24, $24, $14
-    write32(buf + 16, 0x03e07825); // move  $15, $31
-    write32(buf + 20, 0x0018c082); // srl   $24, $24, 2
+    write32(ctx, buf, 0x3c0e0000);      // lui   $14, %hi(&GOTPLT[0])
+    write32(ctx, buf + 4, 0x8dd90000);  // lw    $25, %lo(&GOTPLT[0])($14)
+    write32(ctx, buf + 8, 0x25ce0000);  // addiu $14, $14, %lo(&GOTPLT[0])
+    write32(ctx, buf + 12, 0x030ec023); // subu  $24, $24, $14
+    write32(ctx, buf + 16, 0x03e07825); // move  $15, $31
+    write32(ctx, buf + 20, 0x0018c082); // srl   $24, $24, 2
   } else if (ELFT::Is64Bits) {
-    write32(buf, 0x3c0e0000);      // lui   $14, %hi(&GOTPLT[0])
-    write32(buf + 4, 0xddd90000);  // ld    $25, %lo(&GOTPLT[0])($14)
-    write32(buf + 8, 0x25ce0000);  // addiu $14, $14, %lo(&GOTPLT[0])
-    write32(buf + 12, 0x030ec023); // subu  $24, $24, $14
-    write32(buf + 16, 0x03e07825); // move  $15, $31
-    write32(buf + 20, 0x0018c0c2); // srl   $24, $24, 3
+    write32(ctx, buf, 0x3c0e0000);      // lui   $14, %hi(&GOTPLT[0])
+    write32(ctx, buf + 4, 0xddd90000);  // ld    $25, %lo(&GOTPLT[0])($14)
+    write32(ctx, buf + 8, 0x25ce0000);  // addiu $14, $14, %lo(&GOTPLT[0])
+    write32(ctx, buf + 12, 0x030ec023); // subu  $24, $24, $14
+    write32(ctx, buf + 16, 0x03e07825); // move  $15, $31
+    write32(ctx, buf + 20, 0x0018c0c2); // srl   $24, $24, 3
   } else {
-    write32(buf, 0x3c1c0000);      // lui   $28, %hi(&GOTPLT[0])
-    write32(buf + 4, 0x8f990000);  // lw    $25, %lo(&GOTPLT[0])($28)
-    write32(buf + 8, 0x279c0000);  // addiu $28, $28, %lo(&GOTPLT[0])
-    write32(buf + 12, 0x031cc023); // subu  $24, $24, $28
-    write32(buf + 16, 0x03e07825); // move  $15, $31
-    write32(buf + 20, 0x0018c082); // srl   $24, $24, 2
+    write32(ctx, buf, 0x3c1c0000);      // lui   $28, %hi(&GOTPLT[0])
+    write32(ctx, buf + 4, 0x8f990000);  // lw    $25, %lo(&GOTPLT[0])($28)
+    write32(ctx, buf + 8, 0x279c0000);  // addiu $28, $28, %lo(&GOTPLT[0])
+    write32(ctx, buf + 12, 0x031cc023); // subu  $24, $24, $28
+    write32(ctx, buf + 16, 0x03e07825); // move  $15, $31
+    write32(ctx, buf + 20, 0x0018c082); // srl   $24, $24, 2
   }
 
   uint32_t jalrInst = ctx.arg.zHazardplt ? 0x0320fc09 : 0x0320f809;
-  write32(buf + 24, jalrInst); // jalr.hb $25 or jalr $25
-  write32(buf + 28, 0x2718fffe); // subu  $24, $24, 2
+  write32(ctx, buf + 24, jalrInst);   // jalr.hb $25 or jalr $25
+  write32(ctx, buf + 28, 0x2718fffe); // subu  $24, $24, 2
 
   uint64_t gotPlt = ctx.in.gotPlt->getVA();
   writeValue(buf, gotPlt + 0x8000, 16, 16);
@@ -346,10 +346,10 @@ void MIPS<ELFT>::writePlt(uint8_t *buf, const Symbol &sym,
                         : (ctx.arg.zHazardplt ? 0x03200408 : 0x03200008);
   uint32_t addInst = ELFT::Is64Bits ? 0x65f80000 : 0x25f80000;
 
-  write32(buf, 0x3c0f0000);     // lui   $15, %hi(.got.plt entry)
-  write32(buf + 4, loadInst);   // l[wd] $25, %lo(.got.plt entry)($15)
-  write32(buf + 8, jrInst);     // jr  $25 / jr.hb $25
-  write32(buf + 12, addInst);   // [d]addiu $24, $15, %lo(.got.plt entry)
+  write32(ctx, buf, 0x3c0f0000);   // lui   $15, %hi(.got.plt entry)
+  write32(ctx, buf + 4, loadInst); // l[wd] $25, %lo(.got.plt entry)($15)
+  write32(ctx, buf + 8, jrInst);   // jr  $25 / jr.hb $25
+  write32(ctx, buf + 12, addInst); // [d]addiu $24, $15, %lo(.got.plt entry)
   writeValue(buf, gotPltEntryAddr + 0x8000, 16, 16);
   writeValue(buf + 4, gotPltEntryAddr, 16, 0);
   writeValue(buf + 12, gotPltEntryAddr, 16, 0);
@@ -389,18 +389,18 @@ int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *buf, RelType type) const {
   case R_MIPS_TLS_DTPREL32:
   case R_MIPS_TLS_DTPMOD32:
   case R_MIPS_TLS_TPREL32:
-    return SignExtend64<32>(read32(buf));
+    return SignExtend64<32>(read32(ctx, buf));
   case R_MIPS_26:
     // FIXME (simon): If the relocation target symbol is not a PLT entry
     // we should use another expression for calculation:
     // ((A << 2) | (P & 0xf0000000)) >> 2
-    return SignExtend64<28>(read32(buf) << 2);
+    return SignExtend64<28>(read32(ctx, buf) << 2);
   case R_MIPS_CALL_HI16:
   case R_MIPS_GOT16:
   case R_MIPS_GOT_HI16:
   case R_MIPS_HI16:
   case R_MIPS_PCHI16:
-    return SignExtend64<16>(read32(buf)) << 16;
+    return SignExtend64<16>(read32(ctx, buf)) << 16;
   case R_MIPS_CALL16:
   case R_MIPS_CALL_LO16:
   case R_MIPS_GOT_LO16:
@@ -414,7 +414,7 @@ int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *buf, RelType type) const {
   case R_MIPS_TLS_LDM:
   case R_MIPS_TLS_TPREL_HI16:
   case R_MIPS_TLS_TPREL_LO16:
-    return SignExtend64<16>(read32(buf));
+    return SignExtend64<16>(read32(ctx, buf));
   case R_MICROMIPS_GOT16:
   case R_MICROMIPS_HI16:
     return SignExtend64<16>(readShuffle<e>(buf)) << 16;
@@ -432,15 +432,15 @@ int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *buf, RelType type) const {
   case R_MICROMIPS_GPREL7_S2:
     return SignExtend64<9>(readShuffle<e>(buf) << 2);
   case R_MIPS_PC16:
-    return SignExtend64<18>(read32(buf) << 2);
+    return SignExtend64<18>(read32(ctx, buf) << 2);
   case R_MIPS_PC19_S2:
-    return SignExtend64<21>(read32(buf) << 2);
+    return SignExtend64<21>(read32(ctx, buf) << 2);
   case R_MIPS_PC21_S2:
-    return SignExtend64<23>(read32(buf) << 2);
+    return SignExtend64<23>(read32(ctx, buf) << 2);
   case R_MIPS_PC26_S2:
-    return SignExtend64<28>(read32(buf) << 2);
+    return SignExtend64<28>(read32(ctx, buf) << 2);
   case R_MIPS_PC32:
-    return SignExtend64<32>(read32(buf));
+    return SignExtend64<32>(read32(ctx, buf));
   case R_MICROMIPS_26_S1:
     return SignExtend64<27>(readShuffle<e>(buf) << 1);
   case R_MICROMIPS_PC7_S1:
@@ -466,7 +466,7 @@ int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *buf, RelType type) const {
   case (R_MIPS_64 << 8) | R_MIPS_REL32:
     return read64(buf);
   case R_MIPS_COPY:
-    return ctx.arg.is64 ? read64(buf) : read32(buf);
+    return ctx.arg.is64 ? read64(buf) : read32(ctx, buf);
   case R_MIPS_NONE:
   case R_MIPS_JUMP_SLOT:
   case R_MIPS_JALR:
@@ -531,7 +531,7 @@ static uint64_t fixupCrossModeJump(uint8_t *loc, RelType type, uint64_t val) {
 
   switch (type) {
   case R_MIPS_26: {
-    uint32_t inst = read32(loc) >> 26;
+    uint32_t inst = read32(ctx, loc) >> 26;
     if (inst == 0x3 || inst == 0x1d) { // JAL or JALX
       writeValue(loc, 0x1d << 26, 32, 0);
       return val;
@@ -591,7 +591,7 @@ void MIPS<ELFT>::relocate(uint8_t *loc, const Relocation &rel,
   case R_MIPS_GPREL32:
   case R_MIPS_TLS_DTPREL32:
   case R_MIPS_TLS_TPREL32:
-    write32(loc, val);
+    write32(ctx, loc, val);
     break;
   case R_MIPS_64:
   case R_MIPS_TLS_DTPREL64:
@@ -682,12 +682,12 @@ void MIPS<ELFT>::relocate(uint8_t *loc, const Relocation &rel,
     // Replace jalr/jr instructions by bal/b if the target
     // offset fits into the 18-bit range.
     if (isInt<18>(val)) {
-      switch (read32(loc)) {
+      switch (read32(ctx, loc)) {
       case 0x0320f809:  // jalr $25 => bal sym
-        write32(loc, 0x04110000 | ((val >> 2) & 0xffff));
+        write32(ctx, loc, 0x04110000 | ((val >> 2) & 0xffff));
         break;
       case 0x03200008:  // jr $25 => b sym
-        write32(loc, 0x10000000 | ((val >> 2) & 0xffff));
+        write32(ctx, loc, 0x10000000 | ((val >> 2) & 0xffff));
         break;
       }
     }

diff  --git a/lld/ELF/Arch/PPC.cpp b/lld/ELF/Arch/PPC.cpp
index fa1b2a6c39d494..79962d06e5553b 100644
--- a/lld/ELF/Arch/PPC.cpp
+++ b/lld/ELF/Arch/PPC.cpp
@@ -65,11 +65,11 @@ static uint16_t lo(uint32_t v) { return v; }
 static uint16_t ha(uint32_t v) { return (v + 0x8000) >> 16; }
 
 static uint32_t readFromHalf16(Ctx &ctx, const uint8_t *loc) {
-  return read32(ctx.arg.isLE ? loc : loc - 2);
+  return read32(ctx, ctx.arg.isLE ? loc : loc - 2);
 }
 
 static void writeFromHalf16(Ctx &ctx, uint8_t *loc, uint32_t insn) {
-  write32(ctx.arg.isLE ? loc : loc - 2, insn);
+  write32(ctx, ctx.arg.isLE ? loc : loc - 2, insn);
 }
 
 void elf::writePPC32GlinkSection(Ctx &ctx, uint8_t *buf, size_t numEntries) {
@@ -96,7 +96,7 @@ void elf::writePPC32GlinkSection(Ctx &ctx, uint8_t *buf, size_t numEntries) {
 
   // Write N `b PLTresolve` first.
   for (size_t i = 0; i != numEntries; ++i)
-    write32(buf + 4 * i, 0x48000000 | 4 * (numEntries - i));
+    write32(ctx, buf + 4 * i, 0x48000000 | 4 * (numEntries - i));
   buf += 4 * numEntries;
 
   // Then write PLTresolve(), which has two forms: PIC and non-PIC. PLTresolve()
@@ -107,49 +107,53 @@ void elf::writePPC32GlinkSection(Ctx &ctx, uint8_t *buf, size_t numEntries) {
   if (ctx.arg.isPic) {
     uint32_t afterBcl = 4 * ctx.in.plt->getNumEntries() + 12;
     uint32_t gotBcl = got + 4 - (glink + afterBcl);
-    write32(buf + 0, 0x3d6b0000 | ha(afterBcl));  // addis r11,r11,1f-glink at ha
-    write32(buf + 4, 0x7c0802a6);                 // mflr r0
-    write32(buf + 8, 0x429f0005);                 // bcl 20,30,.+4
-    write32(buf + 12, 0x396b0000 | lo(afterBcl)); // 1: addi r11,r11,1b-glink at l
-    write32(buf + 16, 0x7d8802a6);                // mflr r12
-    write32(buf + 20, 0x7c0803a6);                // mtlr r0
-    write32(buf + 24, 0x7d6c5850);                // sub r11,r11,r12
-    write32(buf + 28, 0x3d8c0000 | ha(gotBcl));   // addis 12,12,GOT+4-1b at ha
+    write32(ctx, buf + 0,
+            0x3d6b0000 | ha(afterBcl)); // addis r11,r11,1f-glink at ha
+    write32(ctx, buf + 4, 0x7c0802a6);  // mflr r0
+    write32(ctx, buf + 8, 0x429f0005);  // bcl 20,30,.+4
+    write32(ctx, buf + 12,
+            0x396b0000 | lo(afterBcl)); // 1: addi r11,r11,1b-glink at l
+    write32(ctx, buf + 16, 0x7d8802a6); // mflr r12
+    write32(ctx, buf + 20, 0x7c0803a6); // mtlr r0
+    write32(ctx, buf + 24, 0x7d6c5850); // sub r11,r11,r12
+    write32(ctx, buf + 28, 0x3d8c0000 | ha(gotBcl)); // addis 12,12,GOT+4-1b at ha
     if (ha(gotBcl) == ha(gotBcl + 4)) {
-      write32(buf + 32, 0x800c0000 | lo(gotBcl)); // lwz r0,r12,GOT+4-1b at l(r12)
-      write32(buf + 36,
-              0x818c0000 | lo(gotBcl + 4));       // lwz r12,r12,GOT+8-1b at l(r12)
+      write32(ctx, buf + 32,
+              0x800c0000 | lo(gotBcl)); // lwz r0,r12,GOT+4-1b at l(r12)
+      write32(ctx, buf + 36,
+              0x818c0000 | lo(gotBcl + 4)); // lwz r12,r12,GOT+8-1b at l(r12)
     } else {
-      write32(buf + 32, 0x840c0000 | lo(gotBcl)); // lwzu r0,r12,GOT+4-1b at l(r12)
-      write32(buf + 36, 0x818c0000 | 4);          // lwz r12,r12,4(r12)
+      write32(ctx, buf + 32,
+              0x840c0000 | lo(gotBcl));       // lwzu r0,r12,GOT+4-1b at l(r12)
+      write32(ctx, buf + 36, 0x818c0000 | 4); // lwz r12,r12,4(r12)
     }
-    write32(buf + 40, 0x7c0903a6);                // mtctr 0
-    write32(buf + 44, 0x7c0b5a14);                // add r0,11,11
-    write32(buf + 48, 0x7d605a14);                // add r11,0,11
-    write32(buf + 52, 0x4e800420);                // bctr
+    write32(ctx, buf + 40, 0x7c0903a6); // mtctr 0
+    write32(ctx, buf + 44, 0x7c0b5a14); // add r0,11,11
+    write32(ctx, buf + 48, 0x7d605a14); // add r11,0,11
+    write32(ctx, buf + 52, 0x4e800420); // bctr
     buf += 56;
   } else {
-    write32(buf + 0, 0x3d800000 | ha(got + 4));   // lis     r12,GOT+4 at ha
-    write32(buf + 4, 0x3d6b0000 | ha(-glink));    // addis   r11,r11,-glink at ha
+    write32(ctx, buf + 0, 0x3d800000 | ha(got + 4)); // lis     r12,GOT+4 at ha
+    write32(ctx, buf + 4, 0x3d6b0000 | ha(-glink)); // addis   r11,r11,-glink at ha
     if (ha(got + 4) == ha(got + 8))
-      write32(buf + 8, 0x800c0000 | lo(got + 4)); // lwz r0,GOT+4 at l(r12)
+      write32(ctx, buf + 8, 0x800c0000 | lo(got + 4)); // lwz r0,GOT+4 at l(r12)
     else
-      write32(buf + 8, 0x840c0000 | lo(got + 4)); // lwzu r0,GOT+4 at l(r12)
-    write32(buf + 12, 0x396b0000 | lo(-glink));   // addi    r11,r11,-glink at l
-    write32(buf + 16, 0x7c0903a6);                // mtctr   r0
-    write32(buf + 20, 0x7c0b5a14);                // add     r0,r11,r11
+      write32(ctx, buf + 8, 0x840c0000 | lo(got + 4)); // lwzu r0,GOT+4 at l(r12)
+    write32(ctx, buf + 12, 0x396b0000 | lo(-glink)); // addi    r11,r11,-glink at l
+    write32(ctx, buf + 16, 0x7c0903a6);              // mtctr   r0
+    write32(ctx, buf + 20, 0x7c0b5a14);              // add     r0,r11,r11
     if (ha(got + 4) == ha(got + 8))
-      write32(buf + 24, 0x818c0000 | lo(got + 8)); // lwz r12,GOT+8 at l(r12)
+      write32(ctx, buf + 24, 0x818c0000 | lo(got + 8)); // lwz r12,GOT+8 at l(r12)
     else
-      write32(buf + 24, 0x818c0000 | 4);          // lwz r12,4(r12)
-    write32(buf + 28, 0x7d605a14);                // add     r11,r0,r11
-    write32(buf + 32, 0x4e800420);                // bctr
+      write32(ctx, buf + 24, 0x818c0000 | 4); // lwz r12,4(r12)
+    write32(ctx, buf + 28, 0x7d605a14);       // add     r11,r0,r11
+    write32(ctx, buf + 32, 0x4e800420);       // bctr
     buf += 36;
   }
 
   // Pad with nop. They should not be executed.
   for (; buf < end; buf += 4)
-    write32(buf, 0x60000000);
+    write32(ctx, buf, 0x60000000);
 }
 
 PPC::PPC(Ctx &ctx) : TargetInfo(ctx) {
@@ -174,7 +178,7 @@ PPC::PPC(Ctx &ctx) : TargetInfo(ctx) {
   defaultMaxPageSize = 65536;
   defaultImageBase = 0x10000000;
 
-  write32(trapInstr.data(), 0x7fe00008);
+  write32(ctx, trapInstr.data(), 0x7fe00008);
 }
 
 void PPC::writeIplt(uint8_t *buf, const Symbol &sym,
@@ -188,12 +192,12 @@ void PPC::writeGotHeader(uint8_t *buf) const {
   // _GLOBAL_OFFSET_TABLE_[0] = _DYNAMIC
   // glibc stores _dl_runtime_resolve in _GLOBAL_OFFSET_TABLE_[1],
   // link_map in _GLOBAL_OFFSET_TABLE_[2].
-  write32(buf, ctx.mainPart->dynamic->getVA());
+  write32(ctx, buf, ctx.mainPart->dynamic->getVA());
 }
 
 void PPC::writeGotPlt(uint8_t *buf, const Symbol &s) const {
   // Address of the symbol resolver stub in .glink .
-  write32(buf,
+  write32(ctx, buf,
           ctx.in.plt->getVA() + ctx.in.plt->headerSize + 4 * s.getPltIdx(ctx));
 }
 
@@ -290,7 +294,7 @@ int64_t PPC::getImplicitAddend(const uint8_t *buf, RelType type) const {
   case R_PPC_DTPMOD32:
   case R_PPC_DTPREL32:
   case R_PPC_TPREL32:
-    return SignExtend64<32>(read32(buf));
+    return SignExtend64<32>(read32(ctx, buf));
   default:
     internalLinkerError(getErrorLoc(ctx, buf),
                         "cannot read addend for relocation " + toString(type));
@@ -361,13 +365,13 @@ void PPC::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     break;
   case R_PPC_ADDR32:
   case R_PPC_REL32:
-    write32(loc, val);
+    write32(ctx, loc, val);
     break;
   case R_PPC_REL14: {
     uint32_t mask = 0x0000FFFC;
     checkInt(loc, val, 16, rel);
     checkAlignment(loc, val, 4, rel);
-    write32(loc, (read32(loc) & ~mask) | (val & mask));
+    write32(ctx, loc, (read32(ctx, loc) & ~mask) | (val & mask));
     break;
   }
   case R_PPC_ADDR24:
@@ -377,7 +381,7 @@ void PPC::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     uint32_t mask = 0x03FFFFFC;
     checkInt(loc, val, 26, rel);
     checkAlignment(loc, val, 4, rel);
-    write32(loc, (read32(loc) & ~mask) | (val & mask));
+    write32(ctx, loc, (read32(ctx, loc) & ~mask) | (val & mask));
     break;
   }
   default:
@@ -419,7 +423,7 @@ void PPC::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
   }
   case R_PPC_TLSGD:
     // bl __tls_get_addr(x at tldgd) --> add r3, r3, r2
-    write32(loc, 0x7c631214);
+    write32(ctx, loc, 0x7c631214);
     break;
   default:
     llvm_unreachable("unsupported relocation for TLS GD to IE relaxation");
@@ -435,7 +439,7 @@ void PPC::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
     break;
   case R_PPC_TLSGD:
     // bl __tls_get_addr(x at tldgd) --> add r3, r3, x at tprel@l
-    write32(loc, 0x38630000 | lo(val));
+    write32(ctx, loc, 0x38630000 | lo(val));
     break;
   default:
     llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");
@@ -453,7 +457,7 @@ void PPC::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
     // r3+x at dtprel computes r3+x-0x8000, while we want it to compute r3+x at tprel
     // = r3+x-0x7000, so add 4096 to r3.
     // bl __tls_get_addr(x at tlsld) --> addi r3, r3, 4096
-    write32(loc, 0x38631000);
+    write32(ctx, loc, 0x38631000);
     break;
   case R_PPC_DTPREL16:
   case R_PPC_DTPREL16_HA:
@@ -476,18 +480,18 @@ void PPC::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
     break;
   }
   case R_PPC_TLS: {
-    uint32_t insn = read32(loc);
+    uint32_t insn = read32(ctx, loc);
     if (insn >> 26 != 31)
       error("unrecognized instruction for IE to LE R_PPC_TLS");
     // addi rT, rT, x at tls --> addi rT, rT, x at tprel@l
-    unsigned secondaryOp = (read32(loc) & 0x000007fe) >> 1;
+    unsigned secondaryOp = (read32(ctx, loc) & 0x000007fe) >> 1;
     uint32_t dFormOp = getPPCDFormOp(secondaryOp);
     if (dFormOp == 0) { // Expecting a DS-Form instruction.
       dFormOp = getPPCDSFormOp(secondaryOp);
       if (dFormOp == 0)
         error("unrecognized instruction for IE to LE R_PPC_TLS");
     }
-    write32(loc, (dFormOp | (insn & 0x03ff0000) | lo(val)));
+    write32(ctx, loc, (dFormOp | (insn & 0x03ff0000) | lo(val)));
     break;
   }
   default:

diff  --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp
index 6948ae0263aab9..647954106322e8 100644
--- a/lld/ELF/Arch/PPC64.cpp
+++ b/lld/ELF/Arch/PPC64.cpp
@@ -275,10 +275,10 @@ static void writeSequence(Ctx &ctx, MutableArrayRef<uint32_t> buf,
     format("%s%d", prefix, r).snprint(name, sizeof(name));
     if (addOptional(ctx, name, 4 * (r - from), defined) && defined.size() == 1)
       first = r - from;
-    write32(ptr++, firstInsn + 0x200008 * (r - from));
+    write32(ctx, ptr++, firstInsn + 0x200008 * (r - from));
   }
   for (uint32_t insn : tail)
-    write32(ptr++, insn);
+    write32(ctx, ptr++, insn);
   assert(ptr == &*buf.end());
 
   if (defined.empty())
@@ -566,11 +566,11 @@ static int64_t getTotalDisp(uint64_t prefixedInsn, uint32_t accessInsn) {
 // little-endian it is pointing to the start of the word. These 2 helpers are to
 // simplify reading and writing in that context.
 static void writeFromHalf16(Ctx &ctx, uint8_t *loc, uint32_t insn) {
-  write32(ctx.arg.isLE ? loc : loc - 2, insn);
+  write32(ctx, ctx.arg.isLE ? loc : loc - 2, insn);
 }
 
 static uint32_t readFromHalf16(Ctx &ctx, const uint8_t *loc) {
-  return read32(ctx.arg.isLE ? loc : loc - 2);
+  return read32(ctx, ctx.arg.isLE ? loc : loc - 2);
 }
 
 static uint64_t readPrefixedInst(Ctx &ctx, const uint8_t *loc) {
@@ -613,7 +613,7 @@ PPC64::PPC64(Ctx &ctx) : TargetInfo(ctx) {
   // use 0x10000000 as the starting address.
   defaultImageBase = 0x10000000;
 
-  write32(trapInstr.data(), 0x7fe00008);
+  write32(ctx, trapInstr.data(), 0x7fe00008);
 }
 
 int PPC64::getTlsGdRelaxSkip(RelType type) const {
@@ -684,7 +684,7 @@ void PPC64::relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     // be relaxed. The eligibility for the relaxation needs to be determined
     // on that relocation since this one does not relocate a symbol.
     uint64_t insn = readPrefixedInst(ctx, loc);
-    uint32_t accessInsn = read32(loc + rel.addend);
+    uint32_t accessInsn = read32(ctx, loc + rel.addend);
     uint64_t pcRelInsn = getPCRelativeForm(accessInsn);
 
     // This error is not necessary for correctness but is emitted for now
@@ -705,7 +705,7 @@ void PPC64::relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     writePrefixedInst(ctx, loc,
                       pcRelInsn | ((totalDisp & 0x3ffff0000) << 16) |
                           (totalDisp & 0xffff));
-    write32(loc + rel.addend, NOP); // nop accessInsn.
+    write32(ctx, loc + rel.addend, NOP); // nop accessInsn.
     break;
   }
   default:
@@ -757,15 +757,15 @@ void PPC64::relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
     //            addi r3, r3, x at tprel@l
     const uintptr_t locAsInt = reinterpret_cast<uintptr_t>(loc);
     if (locAsInt % 4 == 0) {
-      write32(loc, NOP);            // nop
-      write32(loc + 4, 0x38630000); // addi r3, r3
+      write32(ctx, loc, NOP);            // nop
+      write32(ctx, loc + 4, 0x38630000); // addi r3, r3
       // Since we are relocating a half16 type relocation and Loc + 4 points to
       // the start of an instruction we need to advance the buffer by an extra
       // 2 bytes on BE.
       relocateNoSym(loc + 4 + (ctx.arg.ekind == ELF64BEKind ? 2 : 0),
                     R_PPC64_TPREL16_LO, val);
     } else if (locAsInt % 4 == 1) {
-      write32(loc - 1, NOP);
+      write32(ctx, loc - 1, NOP);
     } else {
       errorOrWarn("R_PPC64_TLSGD has unexpected byte alignment");
     }
@@ -818,10 +818,10 @@ void PPC64::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
     //            addi r3, r3, 4096
     const uintptr_t locAsInt = reinterpret_cast<uintptr_t>(loc);
     if (locAsInt % 4 == 0) {
-      write32(loc, NOP);
-      write32(loc + 4, 0x38631000); // addi r3, r3, 4096
+      write32(ctx, loc, NOP);
+      write32(ctx, loc + 4, 0x38631000); // addi r3, r3, 4096
     } else if (locAsInt % 4 == 1) {
-      write32(loc - 1, NOP);
+      write32(ctx, loc - 1, NOP);
     } else {
       errorOrWarn("R_PPC64_TLSLD has unexpected byte alignment");
     }
@@ -912,12 +912,12 @@ void PPC64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
   unsigned offset = (ctx.arg.ekind == ELF64BEKind) ? 2 : 0;
   switch (rel.type) {
   case R_PPC64_GOT_TPREL16_HA:
-    write32(loc - offset, NOP);
+    write32(ctx, loc - offset, NOP);
     break;
   case R_PPC64_GOT_TPREL16_LO_DS:
   case R_PPC64_GOT_TPREL16_DS: {
-    uint32_t regNo = read32(loc - offset) & 0x03E00000; // bits 6-10
-    write32(loc - offset, 0x3C0D0000 | regNo);          // addis RegNo, r13
+    uint32_t regNo = read32(ctx, loc - offset) & 0x03e00000; // bits 6-10
+    write32(ctx, loc - offset, 0x3c0d0000 | regNo);          // addis RegNo, r13
     relocateNoSym(loc, R_PPC64_TPREL16_HA, val);
     break;
   }
@@ -931,10 +931,10 @@ void PPC64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
   case R_PPC64_TLS: {
     const uintptr_t locAsInt = reinterpret_cast<uintptr_t>(loc);
     if (locAsInt % 4 == 0) {
-      uint32_t primaryOp = getPrimaryOpCode(read32(loc));
+      uint32_t primaryOp = getPrimaryOpCode(read32(ctx, loc));
       if (primaryOp != 31)
         error("unrecognized instruction for IE to LE R_PPC64_TLS");
-      uint32_t secondaryOp = (read32(loc) & 0x000007FE) >> 1; // bits 21-30
+      uint32_t secondaryOp = (read32(ctx, loc) & 0x000007fe) >> 1; // bits 21-30
       uint32_t dFormOp = getPPCDFormOp(secondaryOp);
       uint32_t finalReloc;
       if (dFormOp == 0) { // Expecting a DS-Form instruction.
@@ -944,13 +944,13 @@ void PPC64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
         finalReloc = R_PPC64_TPREL16_LO_DS;
       } else
         finalReloc = R_PPC64_TPREL16_LO;
-      write32(loc, dFormOp | (read32(loc) & 0x03ff0000));
+      write32(ctx, loc, dFormOp | (read32(ctx, loc) & 0x03ff0000));
       relocateNoSym(loc + offset, finalReloc, val);
     } else if (locAsInt % 4 == 1) {
       // If the offset is not 4 byte aligned then we have a PCRel type reloc.
       // This version of the relocation is offset by one byte from the
       // instruction it references.
-      uint32_t tlsInstr = read32(loc - 1);
+      uint32_t tlsInstr = read32(ctx, loc - 1);
       uint32_t primaryOp = getPrimaryOpCode(tlsInstr);
       if (primaryOp != 31)
         errorOrWarn("unrecognized instruction for IE to LE R_PPC64_TLS");
@@ -963,10 +963,11 @@ void PPC64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
         uint32_t rt = (tlsInstr & 0x03E00000) >> 21; // bits 6-10
         uint32_t ra = (tlsInstr & 0x001F0000) >> 16; // bits 11-15
         if (ra == rt) {
-          write32(loc - 1, NOP);
+          write32(ctx, loc - 1, NOP);
         } else {
           // mr rt, ra
-          write32(loc - 1, 0x7C000378 | (rt << 16) | (ra << 21) | (ra << 11));
+          write32(ctx, loc - 1,
+                  0x7C000378 | (rt << 16) | (ra << 21) | (ra << 11));
         }
       } else {
         uint32_t dFormOp = getPPCDFormOp(secondaryOp);
@@ -975,7 +976,7 @@ void PPC64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
           if (dFormOp == 0)
             errorOrWarn("unrecognized instruction for IE to LE R_PPC64_TLS");
         }
-        write32(loc - 1, (dFormOp | (tlsInstr & 0x03ff0000)));
+        write32(ctx, loc - 1, (dFormOp | (tlsInstr & 0x03ff0000)));
       }
     } else {
       errorOrWarn("R_PPC64_TLS must be either 4 byte aligned or one byte "
@@ -1116,7 +1117,7 @@ int64_t PPC64::getImplicitAddend(const uint8_t *buf, RelType type) const {
   case R_PPC64_JMP_SLOT:
     return 0;
   case R_PPC64_REL32:
-    return SignExtend64<32>(read32(buf));
+    return SignExtend64<32>(read32(ctx, buf));
   case R_PPC64_ADDR64:
   case R_PPC64_REL64:
   case R_PPC64_RELATIVE:
@@ -1138,19 +1139,19 @@ void PPC64::writeGotHeader(uint8_t *buf) const {
 
 void PPC64::writePltHeader(uint8_t *buf) const {
   // The generic resolver stub goes first.
-  write32(buf +  0, 0x7c0802a6); // mflr r0
-  write32(buf +  4, 0x429f0005); // bcl  20,4*cr7+so,8 <_glink+0x8>
-  write32(buf +  8, 0x7d6802a6); // mflr r11
-  write32(buf + 12, 0x7c0803a6); // mtlr r0
-  write32(buf + 16, 0x7d8b6050); // subf r12, r11, r12
-  write32(buf + 20, 0x380cffcc); // subi r0,r12,52
-  write32(buf + 24, 0x7800f082); // srdi r0,r0,62,2
-  write32(buf + 28, 0xe98b002c); // ld   r12,44(r11)
-  write32(buf + 32, 0x7d6c5a14); // add  r11,r12,r11
-  write32(buf + 36, 0xe98b0000); // ld   r12,0(r11)
-  write32(buf + 40, 0xe96b0008); // ld   r11,8(r11)
-  write32(buf + 44, 0x7d8903a6); // mtctr   r12
-  write32(buf + 48, 0x4e800420); // bctr
+  write32(ctx, buf + 0, 0x7c0802a6);  // mflr r0
+  write32(ctx, buf + 4, 0x429f0005);  // bcl  20,4*cr7+so,8 <_glink+0x8>
+  write32(ctx, buf + 8, 0x7d6802a6);  // mflr r11
+  write32(ctx, buf + 12, 0x7c0803a6); // mtlr r0
+  write32(ctx, buf + 16, 0x7d8b6050); // subf r12, r11, r12
+  write32(ctx, buf + 20, 0x380cffcc); // subi r0,r12,52
+  write32(ctx, buf + 24, 0x7800f082); // srdi r0,r0,62,2
+  write32(ctx, buf + 28, 0xe98b002c); // ld   r12,44(r11)
+  write32(ctx, buf + 32, 0x7d6c5a14); // add  r11,r12,r11
+  write32(ctx, buf + 36, 0xe98b0000); // ld   r12,0(r11)
+  write32(ctx, buf + 40, 0xe96b0008); // ld   r11,8(r11)
+  write32(ctx, buf + 44, 0x7d8903a6); // mtctr   r12
+  write32(ctx, buf + 48, 0x4e800420); // bctr
 
   // The 'bcl' instruction will set the link register to the address of the
   // following instruction ('mflr r11'). Here we store the offset from that
@@ -1163,7 +1164,7 @@ void PPC64::writePlt(uint8_t *buf, const Symbol &sym,
                      uint64_t /*pltEntryAddr*/) const {
   int32_t offset = pltHeaderSize + sym.getPltIdx(ctx) * pltEntrySize;
   // bl __glink_PLTresolve
-  write32(buf, 0x48000000 | ((-offset) & 0x03FFFFFc));
+  write32(ctx, buf, 0x48000000 | ((-offset) & 0x03fffffc));
 }
 
 void PPC64::writeIplt(uint8_t *buf, const Symbol &sym,
@@ -1277,7 +1278,7 @@ void PPC64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     break;
   case R_PPC64_ADDR32:
     checkIntUInt(loc, val, 32, rel);
-    write32(loc, val);
+    write32(ctx, loc, val);
     break;
   case R_PPC64_ADDR16_DS:
   case R_PPC64_TPREL16_DS: {
@@ -1366,7 +1367,7 @@ void PPC64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     break;
   case R_PPC64_REL32:
     checkInt(loc, val, 32, rel);
-    write32(loc, val);
+    write32(ctx, loc, val);
     break;
   case R_PPC64_ADDR64:
   case R_PPC64_REL64:
@@ -1377,7 +1378,7 @@ void PPC64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     uint32_t mask = 0x0000FFFC;
     checkInt(loc, val, 16, rel);
     checkAlignment(loc, val, 4, rel);
-    write32(loc, (read32(loc) & ~mask) | (val & mask));
+    write32(ctx, loc, (read32(ctx, loc) & ~mask) | (val & mask));
     break;
   }
   case R_PPC64_REL24:
@@ -1385,7 +1386,7 @@ void PPC64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
     uint32_t mask = 0x03FFFFFC;
     checkInt(loc, val, 26, rel);
     checkAlignment(loc, val, 4, rel);
-    write32(loc, (read32(loc) & ~mask) | (val & mask));
+    write32(ctx, loc, (read32(ctx, loc) & ~mask) | (val & mask));
     break;
   }
   case R_PPC64_DTPREL64:
@@ -1544,11 +1545,11 @@ void PPC64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
     //            add r3, r3, r13
     const uintptr_t locAsInt = reinterpret_cast<uintptr_t>(loc);
     if (locAsInt % 4 == 0) {
-      write32(loc, NOP);            // bl __tls_get_addr(sym at tlsgd) --> nop
-      write32(loc + 4, 0x7c636A14); // nop --> add r3, r3, r13
+      write32(ctx, loc, NOP);            // bl __tls_get_addr(sym at tlsgd) --> nop
+      write32(ctx, loc + 4, 0x7c636a14); // nop --> add r3, r3, r13
     } else if (locAsInt % 4 == 1) {
       // bl __tls_get_addr(sym at tlsgd) --> add r3, r3, r13
-      write32(loc - 1, 0x7c636a14);
+      write32(ctx, loc - 1, 0x7c636a14);
     } else {
       errorOrWarn("R_PPC64_TLSGD has unexpected byte alignment");
     }
@@ -1598,7 +1599,7 @@ void PPC64::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
       // If this is a call to __tls_get_addr, it may be part of a TLS
       // sequence that has been relaxed and turned into a nop. In this
       // case, we don't want to handle it as a call.
-      if (read32(loc) == 0x60000000) // nop
+      if (read32(ctx, loc) == 0x60000000) // nop
         break;
 
       // Patch a nop (0x60000000) to a ld.
@@ -1608,7 +1609,7 @@ void PPC64::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
         // wrong in the common case where the function is not preempted at
         // runtime. Just ignore.
         if ((rel.offset + 8 > sec.content().size() ||
-             read32(loc + 4) != 0x60000000) &&
+             read32(ctx, loc + 4) != 0x60000000) &&
             rel.sym->file != sec.file) {
           // Use substr(6) to remove the "__plt_" prefix.
           errorOrWarn(getErrorLoc(ctx, loc) + "call to " +
@@ -1616,7 +1617,7 @@ void PPC64::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
                       " lacks nop, can't restore toc");
           break;
         }
-        write32(loc + 4, 0xe8410018); // ld %r2, 24(%r1)
+        write32(ctx, loc + 4, 0xe8410018); // ld %r2, 24(%r1)
       }
       relocate(loc, rel, val);
       break;
@@ -1682,14 +1683,14 @@ bool PPC64::adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
     return false;
 
   // First instruction must be `ld r0, -0x7000-64(r13)`
-  if (read32(loc) != 0xe80d8fc0)
+  if (read32(ctx, loc) != 0xe80d8fc0)
     return false;
 
   int16_t hiImm = 0;
   int16_t loImm = 0;
   // First instruction can be either an addis if the frame size is larger then
   // 32K, or an addi if the size is less then 32K.
-  int32_t firstInstr = read32(loc + 4);
+  int32_t firstInstr = read32(ctx, loc + 4);
   if (getPrimaryOpCode(firstInstr) == 15) {
     hiImm = firstInstr & 0xFFFF;
   } else if (getPrimaryOpCode(firstInstr) == 14) {
@@ -1700,7 +1701,7 @@ bool PPC64::adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
 
   // Second instruction is either an addi or a nop. If the first instruction was
   // an addi then LoImm is set and the second instruction must be a nop.
-  uint32_t secondInstr = read32(loc + 8);
+  uint32_t secondInstr = read32(ctx, loc + 8);
   if (!loImm && getPrimaryOpCode(secondInstr) == 14) {
     loImm = secondInstr & 0xFFFF;
   } else if (secondInstr != NOP) {
@@ -1734,14 +1735,14 @@ bool PPC64::adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
   loImm = adjustedStackFrameSize & 0xFFFF;
   hiImm = (adjustedStackFrameSize + 0x8000) >> 16;
   if (hiImm) {
-    write32(loc + 4, 0x3D810000 | (uint16_t)hiImm);
+    write32(ctx, loc + 4, 0x3d810000 | (uint16_t)hiImm);
     // If the low immediate is zero the second instruction will be a nop.
     secondInstr = loImm ? 0x398C0000 | (uint16_t)loImm : NOP;
-    write32(loc + 8, secondInstr);
+    write32(ctx, loc + 8, secondInstr);
   } else {
     // addi r12, r1, imm
-    write32(loc + 4, (0x39810000) | (uint16_t)loImm);
-    write32(loc + 8, NOP);
+    write32(ctx, loc + 4, (0x39810000) | (uint16_t)loImm);
+    write32(ctx, loc + 8, NOP);
   }
 
   return true;

diff  --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index d65467f10378be..cbbda83c7f848e 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1282,14 +1282,14 @@ void RISCVAttributesSection::writeTo(uint8_t *buf) {
   const size_t size = getSize();
   uint8_t *const end = buf + size;
   *buf = ELFAttrs::Format_Version;
-  write32(buf + 1, size - 1);
+  write32(ctx, buf + 1, size - 1);
   buf += 5;
 
   memcpy(buf, vendor.data(), vendor.size());
   buf += vendor.size() + 1;
 
   *buf = ELFAttrs::File;
-  write32(buf + 1, end - buf);
+  write32(ctx, buf + 1, end - buf);
   buf += 5;
 
   for (auto &attr : intAttr) {

diff  --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index d6abb6184f3619..0b9daef951b216 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -464,7 +464,7 @@ static void writeInt(uint8_t *buf, uint64_t data, uint64_t size) {
   else if (size == 2)
     write16(buf, data);
   else if (size == 4)
-    write32(buf, data);
+    write32(ctx, buf, data);
   else if (size == 8)
     write64(buf, data);
   else
@@ -512,7 +512,7 @@ void OutputSection::writeTo(Ctx &ctx, uint8_t *buf, parallel::TaskGroup &tg) {
   // Write leading padding.
   ArrayRef<InputSection *> sections = getInputSections(*this, storage);
   std::array<uint8_t, 4> filler = getFiller(ctx);
-  bool nonZeroFiller = read32(filler.data()) != 0;
+  bool nonZeroFiller = read32(ctx, filler.data()) != 0;
   if (nonZeroFiller)
     fill(buf, sections.empty() ? size : sections[0]->outSecOff, filler);
 
@@ -605,7 +605,7 @@ static void finalizeShtGroup(Ctx &ctx, OutputSection *os,
   DenseSet<uint32_t> seen;
   ArrayRef<InputSectionBase *> sections = section->file->getSections();
   for (const uint32_t &idx : section->getDataAs<uint32_t>().slice(1))
-    if (OutputSection *osec = sections[read32(&idx)]->getOutputSection())
+    if (OutputSection *osec = sections[read32(ctx, &idx)]->getOutputSection())
       seen.insert(osec->sectionIndex);
   os->size = (1 + seen.size()) * sizeof(uint32_t);
 }

diff  --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index b44b87f8276e94..01a7e9a7866c36 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -60,14 +60,14 @@ using llvm::support::endian::write64le;
 constexpr size_t MergeNoTailSection::numShards;
 
 static uint64_t readUint(Ctx &ctx, uint8_t *buf) {
-  return ctx.arg.is64 ? read64(buf) : read32(buf);
+  return ctx.arg.is64 ? read64(buf) : read32(ctx, buf);
 }
 
 static void writeUint(Ctx &ctx, uint8_t *buf, uint64_t val) {
   if (ctx.arg.is64)
     write64(buf, val);
   else
-    write32(buf, val);
+    write32(ctx, buf, val);
 }
 
 // Returns an LLD version string.
@@ -323,9 +323,9 @@ GnuPropertySection::GnuPropertySection(Ctx &ctx)
                        ctx.arg.wordsize, ".note.gnu.property") {}
 
 void GnuPropertySection::writeTo(uint8_t *buf) {
-  write32(buf, 4);                          // Name size
-  write32(buf + 4, getSize() - 16);         // Content size
-  write32(buf + 8, NT_GNU_PROPERTY_TYPE_0); // Type
+  write32(ctx, buf, 4);                          // Name size
+  write32(ctx, buf + 4, getSize() - 16);         // Content size
+  write32(ctx, buf + 8, NT_GNU_PROPERTY_TYPE_0); // Type
   memcpy(buf + 12, "GNU", 4);               // Name string
 
   uint32_t featureAndType = ctx.arg.emachine == EM_AARCH64
@@ -334,17 +334,17 @@ void GnuPropertySection::writeTo(uint8_t *buf) {
 
   unsigned offset = 16;
   if (ctx.arg.andFeatures != 0) {
-    write32(buf + offset + 0, featureAndType);      // Feature type
-    write32(buf + offset + 4, 4);                   // Feature size
-    write32(buf + offset + 8, ctx.arg.andFeatures); // Feature flags
+    write32(ctx, buf + offset + 0, featureAndType);      // Feature type
+    write32(ctx, buf + offset + 4, 4);                   // Feature size
+    write32(ctx, buf + offset + 8, ctx.arg.andFeatures); // Feature flags
     if (ctx.arg.is64)
-      write32(buf + offset + 12, 0); // Padding
+      write32(ctx, buf + offset + 12, 0); // Padding
     offset += 16;
   }
 
   if (!ctx.aarch64PauthAbiCoreInfo.empty()) {
-    write32(buf + offset + 0, GNU_PROPERTY_AARCH64_FEATURE_PAUTH);
-    write32(buf + offset + 4, ctx.aarch64PauthAbiCoreInfo.size());
+    write32(ctx, buf + offset + 0, GNU_PROPERTY_AARCH64_FEATURE_PAUTH);
+    write32(ctx, buf + offset + 4, ctx.aarch64PauthAbiCoreInfo.size());
     memcpy(buf + offset + 8, ctx.aarch64PauthAbiCoreInfo.data(),
            ctx.aarch64PauthAbiCoreInfo.size());
   }
@@ -365,9 +365,9 @@ BuildIdSection::BuildIdSection(Ctx &ctx)
       hashSize(getHashSize(ctx)) {}
 
 void BuildIdSection::writeTo(uint8_t *buf) {
-  write32(buf, 4);                      // Name size
-  write32(buf + 4, hashSize);           // Content size
-  write32(buf + 8, NT_GNU_BUILD_ID);    // Type
+  write32(ctx, buf, 4);                   // Name size
+  write32(ctx, buf + 4, hashSize);        // Content size
+  write32(ctx, buf + 8, NT_GNU_BUILD_ID); // Type
   memcpy(buf + 12, "GNU", 4);           // Name string
   hashBuf = buf + 16;
 }
@@ -509,7 +509,7 @@ void EhFrameSection::iterateFDEWithLSDA(
 static void writeCieFde(uint8_t *buf, ArrayRef<uint8_t> d) {
   memcpy(buf, d.data(), d.size());
   // Fix the size field. -4 since size does not include the size field itself.
-  write32(buf, d.size() - 4);
+  write32(ctx, buf, d.size() - 4);
 }
 
 void EhFrameSection::finalizeContents() {
@@ -600,9 +600,9 @@ static uint64_t readFdeAddr(Ctx &ctx, uint8_t *buf, int size) {
   case DW_EH_PE_sdata2:
     return (int16_t)read16(buf);
   case DW_EH_PE_udata4:
-    return read32(buf);
+    return read32(ctx, buf);
   case DW_EH_PE_sdata4:
-    return (int32_t)read32(buf);
+    return (int32_t)read32(ctx, buf);
   case DW_EH_PE_udata8:
   case DW_EH_PE_sdata8:
     return read64(buf);
@@ -640,7 +640,7 @@ void EhFrameSection::writeTo(uint8_t *buf) {
 
       // FDE's second word should have the offset to an associated CIE.
       // Write it.
-      write32(buf + off + 4, off + 4 - cieOffset);
+      write32(ctx, buf + off + 4, off + 4 - cieOffset);
     }
   }
 
@@ -2355,7 +2355,7 @@ void SymtabShndxSection::writeTo(uint8_t *buf) {
   for (const SymbolTableEntry &entry : ctx.in.symTab->getSymbols()) {
     if (!getCommonSec(relocatable, entry.sym) &&
         getSymSectionIndex(entry.sym) == SHN_XINDEX)
-      write32(buf, entry.sym->getOutputSection()->sectionIndex);
+      write32(ctx, buf, entry.sym->getOutputSection()->sectionIndex);
     buf += 4;
   }
 }
@@ -2436,10 +2436,11 @@ void GnuHashTableSection::finalizeContents() {
 
 void GnuHashTableSection::writeTo(uint8_t *buf) {
   // Write a header.
-  write32(buf, nBuckets);
-  write32(buf + 4, getPartition().dynSymTab->getNumSymbols() - symbols.size());
-  write32(buf + 8, maskWords);
-  write32(buf + 12, Shift2);
+  write32(ctx, buf, nBuckets);
+  write32(ctx, buf + 4,
+          getPartition().dynSymTab->getNumSymbols() - symbols.size());
+  write32(ctx, buf + 8, maskWords);
+  write32(ctx, buf + 12, Shift2);
   buf += 16;
 
   // Write the 2-bit bloom filter.
@@ -2466,13 +2467,13 @@ void GnuHashTableSection::writeTo(uint8_t *buf) {
     uint32_t hash = i->hash;
     bool isLastInChain = (i + 1) == e || i->bucketIdx != (i + 1)->bucketIdx;
     hash = isLastInChain ? hash | 1 : hash & ~1;
-    write32(values++, hash);
+    write32(ctx, values++, hash);
 
     if (i->bucketIdx == oldBucket)
       continue;
     // Write a hash bucket. Hash buckets contain indices in the following hash
     // value table.
-    write32(buckets + i->bucketIdx,
+    write32(ctx, buckets + i->bucketIdx,
             getPartition().dynSymTab->getSymbolIndex(*i->sym));
     oldBucket = i->bucketIdx;
   }
@@ -2544,8 +2545,8 @@ void HashTableSection::writeTo(uint8_t *buf) {
   unsigned numSymbols = symTab->getNumSymbols();
 
   uint32_t *p = reinterpret_cast<uint32_t *>(buf);
-  write32(p++, numSymbols); // nbucket
-  write32(p++, numSymbols); // nchain
+  write32(ctx, p++, numSymbols); // nbucket
+  write32(ctx, p++, numSymbols); // nchain
 
   uint32_t *buckets = p;
   uint32_t *chains = p + numSymbols;
@@ -2556,7 +2557,7 @@ void HashTableSection::writeTo(uint8_t *buf) {
     unsigned i = sym->dynsymIndex;
     uint32_t hash = hashSysV(name) % numSymbols;
     chains[i] = buckets[hash];
-    write32(buckets + hash, i);
+    write32(ctx, buckets + hash, i);
   }
 }
 
@@ -3672,14 +3673,14 @@ void EhFrameHeader::write() {
   buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4;
   buf[2] = DW_EH_PE_udata4;
   buf[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4;
-  write32(buf + 4,
+  write32(ctx, buf + 4,
           getPartition().ehFrame->getParent()->addr - this->getVA() - 4);
-  write32(buf + 8, fdes.size());
+  write32(ctx, buf + 8, fdes.size());
   buf += 12;
 
   for (FdeData &fde : fdes) {
-    write32(buf, fde.pcRel);
-    write32(buf + 4, fde.fdeVARel);
+    write32(ctx, buf, fde.pcRel);
+    write32(ctx, buf + 4, fde.fdeVARel);
     buf += 8;
   }
 }
@@ -3728,13 +3729,13 @@ void VersionDefinitionSection::writeOne(uint8_t *buf, uint32_t index,
   write16(buf + 2, flags);          // vd_flags
   write16(buf + 4, index);          // vd_ndx
   write16(buf + 6, 1);              // vd_cnt
-  write32(buf + 8, hashSysV(name)); // vd_hash
-  write32(buf + 12, 20);            // vd_aux
-  write32(buf + 16, 28);            // vd_next
+  write32(ctx, buf + 8, hashSysV(name)); // vd_hash
+  write32(ctx, buf + 12, 20);            // vd_aux
+  write32(ctx, buf + 16, 28);            // vd_next
 
   // Write a veraux.
-  write32(buf + 20, nameOff); // vda_name
-  write32(buf + 24, 0);       // vda_next
+  write32(ctx, buf + 20, nameOff); // vda_name
+  write32(ctx, buf + 24, 0);       // vda_next
 }
 
 void VersionDefinitionSection::writeTo(uint8_t *buf) {
@@ -3747,7 +3748,7 @@ void VersionDefinitionSection::writeTo(uint8_t *buf) {
   }
 
   // Need to terminate the last version definition.
-  write32(buf + 16, 0); // vd_next
+  write32(ctx, buf + 16, 0); // vd_next
 }
 
 size_t VersionDefinitionSection::getSize() const {
@@ -4081,7 +4082,8 @@ static bool isDuplicateArmExidxSec(InputSection *prev, InputSection *cur) {
   // nullptr then it will be a synthesized EXIDX_CANTUNWIND entry.
   uint32_t prevUnwind = 1;
   if (prev)
-    prevUnwind = read32(prev->content().data() + prev->content().size() - 4);
+    prevUnwind =
+        read32(ctx, prev->content().data() + prev->content().size() - 4);
   if (isExtabRef(prevUnwind))
     return false;
 
@@ -4098,7 +4100,7 @@ static bool isDuplicateArmExidxSec(InputSection *prev, InputSection *cur) {
     return prevUnwind == 1;
 
   for (uint32_t offset = 4; offset < (uint32_t)cur->content().size(); offset +=8) {
-    uint32_t curUnwind = read32(cur->content().data() + offset);
+    uint32_t curUnwind = read32(ctx, cur->content().data() + offset);
     if (isExtabRef(curUnwind) || curUnwind != prevUnwind)
       return false;
   }
@@ -4211,8 +4213,8 @@ void ARMExidxSyntheticSection::writeTo(uint8_t *buf) {
     if (InputSection *d = findExidxSection(isec)) {
       for (int dataOffset = 0; dataOffset != (int)d->content().size();
            dataOffset += 4)
-        write32(buf + offset + dataOffset,
-                read32(d->content().data() + dataOffset));
+        write32(ctx, buf + offset + dataOffset,
+                read32(ctx, d->content().data() + dataOffset));
       // Recalculate outSecOff as finalizeAddressDependentContent()
       // may have altered syntheticSection outSecOff.
       d->outSecOff = offset + outSecOff;
@@ -4220,8 +4222,8 @@ void ARMExidxSyntheticSection::writeTo(uint8_t *buf) {
       offset += d->getSize();
     } else {
       // A Linker generated CANTUNWIND section.
-      write32(buf + offset + 0, 0x0);
-      write32(buf + offset + 4, 0x1);
+      write32(ctx, buf + offset + 0, 0x0);
+      write32(ctx, buf + offset + 4, 0x1);
       uint64_t s = isec->getVA();
       uint64_t p = getVA() + offset;
       ctx.target->relocateNoSym(buf + offset, R_ARM_PREL31, s - p);
@@ -4229,8 +4231,8 @@ void ARMExidxSyntheticSection::writeTo(uint8_t *buf) {
     }
   }
   // Write Sentinel CANTUNWIND entry.
-  write32(buf + offset + 0, 0x0);
-  write32(buf + offset + 4, 0x1);
+  write32(ctx, buf + offset + 0, 0x0);
+  write32(ctx, buf + offset + 4, 0x1);
   uint64_t s = sentinel->getVA(sentinel->getSize());
   uint64_t p = getVA() + offset;
   ctx.target->relocateNoSym(buf + offset, R_ARM_PREL31, s - p);
@@ -4480,14 +4482,15 @@ void PartitionIndexSection::finalizeContents() {
 void PartitionIndexSection::writeTo(uint8_t *buf) {
   uint64_t va = getVA();
   for (size_t i = 1; i != ctx.partitions.size(); ++i) {
-    write32(buf, ctx.mainPart->dynStrTab->getVA() +
-                     ctx.partitions[i].nameStrTab - va);
-    write32(buf + 4, ctx.partitions[i].elfHeader->getVA() - (va + 4));
+    write32(ctx, buf,
+            ctx.mainPart->dynStrTab->getVA() + ctx.partitions[i].nameStrTab -
+                va);
+    write32(ctx, buf + 4, ctx.partitions[i].elfHeader->getVA() - (va + 4));
 
     SyntheticSection *next = i == ctx.partitions.size() - 1
                                  ? ctx.in.partEnd.get()
                                  : ctx.partitions[i + 1].elfHeader.get();
-    write32(buf + 8, next->getVA() - ctx.partitions[i].elfHeader->getVA());
+    write32(ctx, buf + 8, next->getVA() - ctx.partitions[i].elfHeader->getVA());
 
     va += 12;
     buf += 12;
@@ -4553,9 +4556,9 @@ void MemtagAndroidNote::writeTo(uint8_t *buf) {
       "Android 11 & 12 have an ABI that the note name is 8 bytes long. Keep it "
       "that way for backwards compatibility.");
 
-  write32(buf, sizeof(kMemtagAndroidNoteName));
-  write32(buf + 4, sizeof(uint32_t));
-  write32(buf + 8, ELF::NT_ANDROID_TYPE_MEMTAG);
+  write32(ctx, buf, sizeof(kMemtagAndroidNoteName));
+  write32(ctx, buf + 4, sizeof(uint32_t));
+  write32(ctx, buf + 8, ELF::NT_ANDROID_TYPE_MEMTAG);
   memcpy(buf + 12, kMemtagAndroidNoteName, sizeof(kMemtagAndroidNoteName));
   buf += 12 + alignTo(sizeof(kMemtagAndroidNoteName), 4);
 
@@ -4567,7 +4570,7 @@ void MemtagAndroidNote::writeTo(uint8_t *buf) {
   // binary on Android 11 or 12 will result in a checkfail in the loader.
   if (ctx.arg.androidMemtagStack)
     value |= ELF::NT_MEMTAG_STACK;
-  write32(buf, value); // note value
+  write32(ctx, buf, value); // note value
 }
 
 size_t MemtagAndroidNote::getSize() const {
@@ -4577,9 +4580,9 @@ size_t MemtagAndroidNote::getSize() const {
 }
 
 void PackageMetadataNote::writeTo(uint8_t *buf) {
-  write32(buf, 4);
-  write32(buf + 4, ctx.arg.packageMetadata.size() + 1);
-  write32(buf + 8, FDO_PACKAGING_METADATA);
+  write32(ctx, buf, 4);
+  write32(ctx, buf + 4, ctx.arg.packageMetadata.size() + 1);
+  write32(ctx, buf + 8, FDO_PACKAGING_METADATA);
   memcpy(buf + 12, "FDO", 4);
   memcpy(buf + 16, ctx.arg.packageMetadata.data(),
          ctx.arg.packageMetadata.size());

diff  --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index 8a415c84cb5742..f94d3cf0552a84 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -296,7 +296,7 @@ inline uint16_t read16(const void *p) {
   return llvm::support::endian::read16(p, ctx.arg.endianness);
 }
 
-inline uint32_t read32(const void *p) {
+inline uint32_t read32(Ctx &ctx, const void *p) {
   return llvm::support::endian::read32(p, ctx.arg.endianness);
 }
 
@@ -308,7 +308,7 @@ inline void write16(void *p, uint16_t v) {
   llvm::support::endian::write16(p, v, ctx.arg.endianness);
 }
 
-inline void write32(void *p, uint32_t v) {
+inline void write32(Ctx &ctx, void *p, uint32_t v) {
   llvm::support::endian::write32(p, v, ctx.arg.endianness);
 }
 

diff  --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp
index f239fda758b6fe..16066926c860d5 100644
--- a/lld/ELF/Thunks.cpp
+++ b/lld/ELF/Thunks.cpp
@@ -570,7 +570,7 @@ void AArch64Thunk::writeTo(uint8_t *buf) {
   }
   uint64_t s = getAArch64ThunkDestVA(ctx, destination, addend);
   uint64_t p = getThunkTargetSym()->getVA();
-  write32(buf, 0x14000000); // b S
+  write32(ctx, buf, 0x14000000); // b S
   ctx.target->relocateNoSym(buf, R_AARCH64_CALL26, s - p);
 }
 
@@ -647,7 +647,7 @@ void AArch64BTILandingPadThunk::writeTo(uint8_t *buf) {
     writeLong(buf);
     return;
   }
-  write32(buf, 0xd503245f); // BTI c
+  write32(ctx, buf, 0xd503245f); // BTI c
   // Control falls through to target in following section.
 }
 
@@ -672,8 +672,8 @@ bool AArch64BTILandingPadThunk::getMayUseShortThunk() {
 void AArch64BTILandingPadThunk::writeLong(uint8_t *buf) {
   uint64_t s = destination.getVA(addend);
   uint64_t p = getThunkTargetSym()->getVA() + 4;
-  write32(buf, 0xd503245f);     // BTI c
-  write32(buf + 4, 0x14000000); // B S
+  write32(ctx, buf, 0xd503245f);     // BTI c
+  write32(ctx, buf + 4, 0x14000000); // B S
   ctx.target->relocateNoSym(buf + 4, R_AARCH64_CALL26, s - p);
 }
 
@@ -708,7 +708,7 @@ void ARMThunk::writeTo(uint8_t *buf) {
   uint64_t s = getARMThunkDestVA(ctx, destination);
   uint64_t p = getThunkTargetSym()->getVA();
   int64_t offset = s - p - 8;
-  write32(buf, 0xea000000); // b S
+  write32(ctx, buf, 0xea000000); // b S
   ctx.target->relocateNoSym(buf, R_ARM_JUMP24, offset);
 }
 
@@ -767,9 +767,9 @@ bool ThumbThunk::isCompatibleWith(const InputSection &isec,
 }
 
 void ARMV7ABSLongThunk::writeLong(uint8_t *buf) {
-  write32(buf + 0, 0xe300c000); // movw ip,:lower16:S
-  write32(buf + 4, 0xe340c000); // movt ip,:upper16:S
-  write32(buf + 8, 0xe12fff1c); // bx   ip
+  write32(ctx, buf + 0, 0xe300c000); // movw ip,:lower16:S
+  write32(ctx, buf + 4, 0xe340c000); // movt ip,:upper16:S
+  write32(ctx, buf + 8, 0xe12fff1c); // bx   ip
   uint64_t s = getARMThunkDestVA(ctx, destination);
   ctx.target->relocateNoSym(buf, R_ARM_MOVW_ABS_NC, s);
   ctx.target->relocateNoSym(buf + 4, R_ARM_MOVT_ABS, s);
@@ -799,10 +799,12 @@ void ThumbV7ABSLongThunk::addSymbols(ThunkSection &isec) {
 }
 
 void ARMV7PILongThunk::writeLong(uint8_t *buf) {
-  write32(buf + 0, 0xe30fcff0);   // P:  movw ip,:lower16:S - (P + (L1-P) + 8)
-  write32(buf + 4, 0xe340c000);   //     movt ip,:upper16:S - (P + (L1-P) + 8)
-  write32(buf + 8, 0xe08cc00f);   // L1: add  ip, ip, pc
-  write32(buf + 12, 0xe12fff1c);  //     bx   ip
+  write32(ctx, buf + 0,
+          0xe30fcff0); // P:  movw ip,:lower16:S - (P + (L1-P) + 8)
+  write32(ctx, buf + 4,
+          0xe340c000); //     movt ip,:upper16:S - (P + (L1-P) + 8)
+  write32(ctx, buf + 8, 0xe08cc00f);  // L1: add  ip, ip, pc
+  write32(ctx, buf + 12, 0xe12fff1c); //     bx   ip
   uint64_t s = getARMThunkDestVA(ctx, destination);
   uint64_t p = getThunkTargetSym()->getVA();
   int64_t offset = s - p - 16;
@@ -845,7 +847,7 @@ void ThumbV6MABSLongThunk::writeLong(uint8_t *buf) {
   write16(buf + 2, 0x4801);   // ldr r0, [pc, #4] ; L1
   write16(buf + 4, 0x9001);   // str r0, [sp, #4] ; SP + 4 = S
   write16(buf + 6, 0xbd01);   // pop {r0, pc} ; restore r0 and branch to dest
-  write32(buf + 8, 0x00000000);   // L1: .word S
+  write32(ctx, buf + 8, 0x00000000); // L1: .word S
   uint64_t s = getARMThunkDestVA(ctx, destination);
   ctx.target->relocateNoSym(buf + 8, R_ARM_ABS32, s);
 }
@@ -896,7 +898,7 @@ void ThumbV6MPILongThunk::writeLong(uint8_t *buf) {
   write16(buf + 6, 0xbc01);   //     pop {r0}         ; restore scratch register
   write16(buf + 8, 0x44e7);   // L1: add pc, ip       ; transfer control
   write16(buf + 10, 0x46c0);  //     nop              ; pad to 4-byte boundary
-  write32(buf + 12, 0x00000000);  // L2: .word S - (P + (L1 - P) + 4)
+  write32(ctx, buf + 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 4)
   uint64_t s = getARMThunkDestVA(ctx, destination);
   uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
   ctx.target->relocateNoSym(buf + 12, R_ARM_REL32, s - p - 12);
@@ -911,8 +913,8 @@ void ThumbV6MPILongThunk::addSymbols(ThunkSection &isec) {
 }
 
 void ARMV5LongLdrPcThunk::writeLong(uint8_t *buf) {
-  write32(buf + 0, 0xe51ff004); // ldr pc, [pc,#-4] ; L1
-  write32(buf + 4, 0x00000000); // L1: .word S
+  write32(ctx, buf + 0, 0xe51ff004); // ldr pc, [pc,#-4] ; L1
+  write32(ctx, buf + 4, 0x00000000); // L1: .word S
   ctx.target->relocateNoSym(buf + 4, R_ARM_ABS32,
                             getARMThunkDestVA(ctx, destination));
 }
@@ -926,9 +928,9 @@ void ARMV5LongLdrPcThunk::addSymbols(ThunkSection &isec) {
 }
 
 void ARMV4ABSLongBXThunk::writeLong(uint8_t *buf) {
-  write32(buf + 0, 0xe59fc000); // ldr r12, [pc] ; L1
-  write32(buf + 4, 0xe12fff1c); // bx r12
-  write32(buf + 8, 0x00000000); // L1: .word S
+  write32(ctx, buf + 0, 0xe59fc000); // ldr r12, [pc] ; L1
+  write32(ctx, buf + 4, 0xe12fff1c); // bx r12
+  write32(ctx, buf + 8, 0x00000000); // L1: .word S
   ctx.target->relocateNoSym(buf + 8, R_ARM_ABS32,
                             getARMThunkDestVA(ctx, destination));
 }
@@ -944,8 +946,8 @@ void ARMV4ABSLongBXThunk::addSymbols(ThunkSection &isec) {
 void ThumbV4ABSLongBXThunk::writeLong(uint8_t *buf) {
   write16(buf + 0, 0x4778); // bx pc
   write16(buf + 2, 0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc
-  write32(buf + 4, 0xe51ff004); // ldr pc, [pc, #-4] ; L1
-  write32(buf + 8, 0x00000000); // L1: .word S
+  write32(ctx, buf + 4, 0xe51ff004); // ldr pc, [pc, #-4] ; L1
+  write32(ctx, buf + 8, 0x00000000); // L1: .word S
   ctx.target->relocateNoSym(buf + 8, R_ARM_ABS32,
                             getARMThunkDestVA(ctx, destination));
 }
@@ -962,9 +964,9 @@ void ThumbV4ABSLongBXThunk::addSymbols(ThunkSection &isec) {
 void ThumbV4ABSLongThunk::writeLong(uint8_t *buf) {
   write16(buf + 0, 0x4778); // bx pc
   write16(buf + 2, 0xe7fd); // b #-6 ; Arm recommended sequence to follow bx pc
-  write32(buf + 4, 0xe59fc000); // ldr r12, [pc] ; L1
-  write32(buf + 8, 0xe12fff1c); // bx r12
-  write32(buf + 12, 0x00000000); // L1: .word S
+  write32(ctx, buf + 4, 0xe59fc000);  // ldr r12, [pc] ; L1
+  write32(ctx, buf + 8, 0xe12fff1c);  // bx r12
+  write32(ctx, buf + 12, 0x00000000); // L1: .word S
   ctx.target->relocateNoSym(buf + 12, R_ARM_ABS32,
                             getARMThunkDestVA(ctx, destination));
 }
@@ -979,10 +981,10 @@ void ThumbV4ABSLongThunk::addSymbols(ThunkSection &isec) {
 }
 
 void ARMV4PILongBXThunk::writeLong(uint8_t *buf) {
-  write32(buf + 0, 0xe59fc004); // P:  ldr ip, [pc,#4] ; L2
-  write32(buf + 4, 0xe08fc00c);	// L1: add ip, pc, ip
-  write32(buf + 8, 0xe12fff1c);	//     bx ip
-  write32(buf + 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
+  write32(ctx, buf + 0, 0xe59fc004);  // P:  ldr ip, [pc,#4] ; L2
+  write32(ctx, buf + 4, 0xe08fc00c);  // L1: add ip, pc, ip
+  write32(ctx, buf + 8, 0xe12fff1c);  //     bx ip
+  write32(ctx, buf + 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
   uint64_t s = getARMThunkDestVA(ctx, destination);
   uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
   ctx.target->relocateNoSym(buf + 12, R_ARM_REL32, s - p - 12);
@@ -997,9 +999,9 @@ void ARMV4PILongBXThunk::addSymbols(ThunkSection &isec) {
 }
 
 void ARMV4PILongThunk::writeLong(uint8_t *buf) {
-  write32(buf + 0, 0xe59fc000); // P:  ldr ip, [pc] ; L2
-  write32(buf + 4, 0xe08ff00c); // L1: add pc, pc, r12
-  write32(buf + 8, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
+  write32(ctx, buf + 0, 0xe59fc000); // P:  ldr ip, [pc] ; L2
+  write32(ctx, buf + 4, 0xe08ff00c); // L1: add pc, pc, r12
+  write32(ctx, buf + 8, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
   uint64_t s = getARMThunkDestVA(ctx, destination);
   uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
   ctx.target->relocateNoSym(buf + 8, R_ARM_REL32, s - p - 12);
@@ -1016,9 +1018,9 @@ void ARMV4PILongThunk::addSymbols(ThunkSection &isec) {
 void ThumbV4PILongBXThunk::writeLong(uint8_t *buf) {
   write16(buf + 0, 0x4778); // P:  bx pc
   write16(buf + 2, 0xe7fd); //     b #-6 ; Arm recommended sequence to follow bx pc
-  write32(buf + 4, 0xe59fc000); //     ldr r12, [pc] ; L2
-  write32(buf + 8, 0xe08cf00f); // L1: add pc, r12, pc
-  write32(buf + 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
+  write32(ctx, buf + 4, 0xe59fc000);  //     ldr r12, [pc] ; L2
+  write32(ctx, buf + 8, 0xe08cf00f);  // L1: add pc, r12, pc
+  write32(ctx, buf + 12, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
   uint64_t s = getARMThunkDestVA(ctx, destination);
   uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
   ctx.target->relocateNoSym(buf + 12, R_ARM_REL32, s - p - 16);
@@ -1036,10 +1038,10 @@ void ThumbV4PILongBXThunk::addSymbols(ThunkSection &isec) {
 void ThumbV4PILongThunk::writeLong(uint8_t *buf) {
   write16(buf + 0, 0x4778); // P:  bx pc
   write16(buf + 2, 0xe7fd); //     b #-6 ; Arm recommended sequence to follow bx pc
-  write32(buf + 4, 0xe59fc004); //     ldr ip, [pc,#4] ; L2
-  write32(buf + 8, 0xe08fc00c); // L1: add ip, pc, ip
-  write32(buf + 12, 0xe12fff1c); //     bx ip
-  write32(buf + 16, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
+  write32(ctx, buf + 4, 0xe59fc004);  //     ldr ip, [pc,#4] ; L2
+  write32(ctx, buf + 8, 0xe08fc00c);  // L1: add ip, pc, ip
+  write32(ctx, buf + 12, 0xe12fff1c); //     bx ip
+  write32(ctx, buf + 16, 0x00000000); // L2: .word S - (P + (L1 - P) + 8)
   uint64_t s = getARMThunkDestVA(ctx, destination);
   uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
   ctx.target->relocateNoSym(buf + 16, R_ARM_REL32, s - p - 16);
@@ -1056,7 +1058,7 @@ void ThumbV4PILongThunk::addSymbols(ThunkSection &isec) {
 
 // Use the long jump which covers a range up to 8MiB.
 void AVRThunk::writeTo(uint8_t *buf) {
-  write32(buf, 0x940c); // jmp func
+  write32(ctx, buf, 0x940c); // jmp func
   ctx.target->relocateNoSym(buf, R_AVR_CALL, destination.getVA());
 }
 
@@ -1068,10 +1070,10 @@ void AVRThunk::addSymbols(ThunkSection &isec) {
 // Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
 void MipsThunk::writeTo(uint8_t *buf) {
   uint64_t s = destination.getVA();
-  write32(buf, 0x3c190000); // lui   $25, %hi(func)
-  write32(buf + 4, 0x08000000 | (s >> 2)); // j     func
-  write32(buf + 8, 0x27390000); // addiu $25, $25, %lo(func)
-  write32(buf + 12, 0x00000000); // nop
+  write32(ctx, buf, 0x3c190000);                // lui   $25, %hi(func)
+  write32(ctx, buf + 4, 0x08000000 | (s >> 2)); // j     func
+  write32(ctx, buf + 8, 0x27390000);            // addiu $25, $25, %lo(func)
+  write32(ctx, buf + 12, 0x00000000);           // nop
   ctx.target->relocateNoSym(buf, R_MIPS_HI16, s);
   ctx.target->relocateNoSym(buf + 8, R_MIPS_LO16, s);
 }
@@ -1139,10 +1141,10 @@ InputSection *MicroMipsR6Thunk::getTargetInputSection() const {
 void elf::writePPC32PltCallStub(Ctx &ctx, uint8_t *buf, uint64_t gotPltVA,
                                 const InputFile *file, int64_t addend) {
   if (!ctx.arg.isPic) {
-    write32(buf + 0, 0x3d600000 | (gotPltVA + 0x8000) >> 16); // lis r11,ha
-    write32(buf + 4, 0x816b0000 | (uint16_t)gotPltVA);        // lwz r11,l(r11)
-    write32(buf + 8, 0x7d6903a6);                             // mtctr r11
-    write32(buf + 12, 0x4e800420);                            // bctr
+    write32(ctx, buf + 0, 0x3d600000 | (gotPltVA + 0x8000) >> 16); // lis r11,ha
+    write32(ctx, buf + 4, 0x816b0000 | (uint16_t)gotPltVA); // lwz r11,l(r11)
+    write32(ctx, buf + 8, 0x7d6903a6);                      // mtctr r11
+    write32(ctx, buf + 12, 0x4e800420);                     // bctr
     return;
   }
   uint32_t offset;
@@ -1160,15 +1162,15 @@ void elf::writePPC32PltCallStub(Ctx &ctx, uint8_t *buf, uint64_t gotPltVA,
   }
   uint16_t ha = (offset + 0x8000) >> 16, l = (uint16_t)offset;
   if (ha == 0) {
-    write32(buf + 0, 0x817e0000 | l); // lwz r11,l(r30)
-    write32(buf + 4, 0x7d6903a6);     // mtctr r11
-    write32(buf + 8, 0x4e800420);     // bctr
-    write32(buf + 12, 0x60000000);    // nop
+    write32(ctx, buf + 0, 0x817e0000 | l); // lwz r11,l(r30)
+    write32(ctx, buf + 4, 0x7d6903a6);     // mtctr r11
+    write32(ctx, buf + 8, 0x4e800420);     // bctr
+    write32(ctx, buf + 12, 0x60000000);    // nop
   } else {
-    write32(buf + 0, 0x3d7e0000 | ha); // addis r11,r30,ha
-    write32(buf + 4, 0x816b0000 | l);  // lwz r11,l(r11)
-    write32(buf + 8, 0x7d6903a6);      // mtctr r11
-    write32(buf + 12, 0x4e800420);     // bctr
+    write32(ctx, buf + 0, 0x3d7e0000 | ha); // addis r11,r30,ha
+    write32(ctx, buf + 4, 0x816b0000 | l);  // lwz r11,l(r11)
+    write32(ctx, buf + 8, 0x7d6903a6);      // mtctr r11
+    write32(ctx, buf + 12, 0x4e800420);     // bctr
   }
 }
 
@@ -1206,36 +1208,36 @@ void PPC32LongThunk::writeTo(uint8_t *buf) {
   uint32_t d = destination.getVA(addend);
   if (ctx.arg.isPic) {
     uint32_t off = d - (getThunkTargetSym()->getVA() + 8);
-    write32(buf + 0, 0x7c0802a6);            // mflr r12,0
-    write32(buf + 4, 0x429f0005);            // bcl r20,r31,.+4
-    write32(buf + 8, 0x7d8802a6);            // mtctr r12
-    write32(buf + 12, 0x3d8c0000 | ha(off)); // addis r12,r12,off at ha
-    write32(buf + 16, 0x398c0000 | lo(off)); // addi r12,r12,off at l
-    write32(buf + 20, 0x7c0803a6);           // mtlr r0
+    write32(ctx, buf + 0, 0x7c0802a6);            // mflr r12,0
+    write32(ctx, buf + 4, 0x429f0005);            // bcl r20,r31,.+4
+    write32(ctx, buf + 8, 0x7d8802a6);            // mtctr r12
+    write32(ctx, buf + 12, 0x3d8c0000 | ha(off)); // addis r12,r12,off at ha
+    write32(ctx, buf + 16, 0x398c0000 | lo(off)); // addi r12,r12,off at l
+    write32(ctx, buf + 20, 0x7c0803a6);           // mtlr r0
     buf += 24;
   } else {
-    write32(buf + 0, 0x3d800000 | ha(d));    // lis r12,d at ha
-    write32(buf + 4, 0x398c0000 | lo(d));    // addi r12,r12,d at l
+    write32(ctx, buf + 0, 0x3d800000 | ha(d)); // lis r12,d at ha
+    write32(ctx, buf + 4, 0x398c0000 | lo(d)); // addi r12,r12,d at l
     buf += 8;
   }
-  write32(buf + 0, 0x7d8903a6);              // mtctr r12
-  write32(buf + 4, 0x4e800420);              // bctr
+  write32(ctx, buf + 0, 0x7d8903a6); // mtctr r12
+  write32(ctx, buf + 4, 0x4e800420); // bctr
 }
 
 void elf::writePPC64LoadAndBranch(uint8_t *buf, int64_t offset) {
   uint16_t offHa = (offset + 0x8000) >> 16;
   uint16_t offLo = offset & 0xffff;
 
-  write32(buf + 0, 0x3d820000 | offHa); // addis r12, r2, OffHa
-  write32(buf + 4, 0xe98c0000 | offLo); // ld    r12, OffLo(r12)
-  write32(buf + 8, 0x7d8903a6);         // mtctr r12
-  write32(buf + 12, 0x4e800420);        // bctr
+  write32(ctx, buf + 0, 0x3d820000 | offHa); // addis r12, r2, OffHa
+  write32(ctx, buf + 4, 0xe98c0000 | offLo); // ld    r12, OffLo(r12)
+  write32(ctx, buf + 8, 0x7d8903a6);         // mtctr r12
+  write32(ctx, buf + 12, 0x4e800420);        // bctr
 }
 
 void PPC64PltCallStub::writeTo(uint8_t *buf) {
   int64_t offset = destination.getGotPltVA(ctx) - getPPC64TocBase(ctx);
   // Save the TOC pointer to the save-slot reserved in the call frame.
-  write32(buf + 0, 0xf8410018); // std     r2,24(r1)
+  write32(ctx, buf + 0, 0xf8410018); // std     r2,24(r1)
   writePPC64LoadAndBranch(buf + 4, offset);
 }
 
@@ -1253,10 +1255,10 @@ bool PPC64PltCallStub::isCompatibleWith(const InputSection &isec,
 
 void PPC64R2SaveStub::writeTo(uint8_t *buf) {
   const int64_t offset = computeOffset();
-  write32(buf + 0, 0xf8410018); // std  r2,24(r1)
+  write32(ctx, buf + 0, 0xf8410018); // std  r2,24(r1)
   // The branch offset needs to fit in 26 bits.
   if (getMayUseShortThunk()) {
-    write32(buf + 4, 0x48000000 | (offset & 0x03fffffc)); // b    <offset>
+    write32(ctx, buf + 4, 0x48000000 | (offset & 0x03fffffc)); // b    <offset>
   } else if (isInt<34>(offset)) {
     int nextInstOffset;
     uint64_t tocOffset = destination.getVA() - getPPC64TocBase(ctx);
@@ -1264,16 +1266,16 @@ void PPC64R2SaveStub::writeTo(uint8_t *buf) {
       const uint64_t addi = ADDI_R12_TO_R12_NO_DISP | (tocOffset & 0xffff);
       const uint64_t addis =
           ADDIS_R12_TO_R2_NO_DISP | ((tocOffset >> 16) & 0xffff);
-      write32(buf + 4, addis); // addis r12, r2 , top of offset
-      write32(buf + 8, addi);  // addi  r12, r12, bottom of offset
+      write32(ctx, buf + 4, addis); // addis r12, r2 , top of offset
+      write32(ctx, buf + 8, addi);  // addi  r12, r12, bottom of offset
       nextInstOffset = 12;
     } else {
       const uint64_t addi = ADDI_R12_TO_R2_NO_DISP | (tocOffset & 0xffff);
-      write32(buf + 4, addi); // addi r12, r2, offset
+      write32(ctx, buf + 4, addi); // addi r12, r2, offset
       nextInstOffset = 8;
     }
-    write32(buf + nextInstOffset, MTCTR_R12); // mtctr r12
-    write32(buf + nextInstOffset + 4, BCTR);  // bctr
+    write32(ctx, buf + nextInstOffset, MTCTR_R12); // mtctr r12
+    write32(ctx, buf + nextInstOffset + 4, BCTR);  // bctr
   } else {
     ctx.in.ppc64LongBranchTarget->addEntry(&destination, addend);
     const int64_t offsetFromTOC =
@@ -1311,20 +1313,20 @@ void PPC64R12SetupStub::writeTo(uint8_t *buf) {
     nextInstOffset = 8;
   } else {
     uint32_t off = offset - 8;
-    write32(buf + 0, 0x7d8802a6);                     // mflr 12
-    write32(buf + 4, 0x429f0005);                     // bcl 20,31,.+4
-    write32(buf + 8, 0x7d6802a6);                     // mflr 11
-    write32(buf + 12, 0x7d8803a6);                    // mtlr 12
-    write32(buf + 16,
-            0x3d8b0000 | ((off + 0x8000) >> 16));     // addis 12,11,off at ha
+    write32(ctx, buf + 0, 0x7d8802a6);  // mflr 12
+    write32(ctx, buf + 4, 0x429f0005);  // bcl 20,31,.+4
+    write32(ctx, buf + 8, 0x7d6802a6);  // mflr 11
+    write32(ctx, buf + 12, 0x7d8803a6); // mtlr 12
+    write32(ctx, buf + 16,
+            0x3d8b0000 | ((off + 0x8000) >> 16)); // addis 12,11,off at ha
     if (gotPlt)
-      write32(buf + 20, 0xe98c0000 | (off & 0xffff)); // ld 12, off at l(12)
+      write32(ctx, buf + 20, 0xe98c0000 | (off & 0xffff)); // ld 12, off at l(12)
     else
-      write32(buf + 20, 0x398c0000 | (off & 0xffff)); // addi 12,12,off at l
+      write32(ctx, buf + 20, 0x398c0000 | (off & 0xffff)); // addi 12,12,off at l
     nextInstOffset = 24;
   }
-  write32(buf + nextInstOffset, MTCTR_R12); // mtctr r12
-  write32(buf + nextInstOffset + 4, BCTR);  // bctr
+  write32(ctx, buf + nextInstOffset, MTCTR_R12); // mtctr r12
+  write32(ctx, buf + nextInstOffset + 4, BCTR);  // bctr
 }
 
 void PPC64R12SetupStub::addSymbols(ThunkSection &isec) {


        


More information about the llvm-commits mailing list