@Override
	public RelocationResult relocate(MachoRelocation relocation)
			throws MemoryAccessException, RelocationException {
		
		if (!relocation.requiresRelocation()) {
			return RelocationResult.SKIPPED;
		}
		
		RelocationInfo relocationInfo = relocation.getRelocationInfo();
		Address relocAddr = relocation.getRelocationAddress();
		Address targetAddr;
		long addendFromReloc;
		if (relocationInfo.getType() == ARM64_RELOC_ADDEND) {
			// ARM64_RELOC_ADDEND is a paired relocation, but it's a bit unique because it doesn't
			// define its own relocation target...simply an addend value to be applied to the 2nd
			// part of the relocation.  We'll just save off the addend value and proceed as if the
			// "extra" part of the relocation pair is a normal unpaired relocation.  
			targetAddr = relocation.getTargetAddressExtra();
			addendFromReloc = relocationInfo.getValue();
			relocationInfo = relocation.getRelocationInfoExtra();
		}
		else {
			targetAddr = relocation.getTargetAddress();
			addendFromReloc = 0;
			
		}
		long orig = read(relocation);

		int byteLength;
		switch (relocationInfo.getType()) {
			case ARM64_RELOC_UNSIGNED:
			case ARM64_RELOC_POINTER_TO_GOT: {
				long addend = orig;
				long value = targetAddr.getOffset() + addend;
				byteLength = write(relocation, value);
				break;
			}
			case ARM64_RELOC_SUBTRACTOR: {
				Address targetAddrExtra = relocation.getTargetAddressExtra();
				if (orig > 0) {
					byteLength = write(relocation, targetAddrExtra.add(orig).subtract(targetAddr));
				}
				else {
					byteLength = write(relocation, targetAddr.add(orig).subtract(targetAddrExtra));
				}
				break;
			}
			case ARM64_RELOC_BRANCH26: {
				long addend = orig & 0x3ffffff;
				long value = (targetAddr.subtract(relocAddr) >> 2) + addend;
				long instr = orig | (value & 0x3ffffff);
				byteLength = write(relocation, instr);
				break;
			}
			case ARM64_RELOC_PAGE21:
			case ARM64_RELOC_GOT_LOAD_PAGE21: {
				// ADRP
				long immlo = (orig >> 29) & 0x3;
				long immhi = (orig >> 5) & 0x7ffff;
				long addend = ((immhi << 2) | immlo) << 12;
				addend += addendFromReloc;
				long pageTarget = PG(targetAddr.getOffset() + addend);
				long pageReloc = PG(relocAddr.getOffset());
				long value = ((pageTarget - pageReloc) >> 12) & 0x1fffff;
				long instr =
					(orig & 0x9f00001f) | ((value << 3) & 0x7ffffe0) | ((value & 0x3) << 29);
				byteLength = write(relocation, instr);
				break;
			}
			case ARM64_RELOC_PAGEOFF12:
			case ARM64_RELOC_GOT_LOAD_PAGEOFF12: {
				long instr;
				long addend = addendFromReloc;
				if ((orig & 0x08000000) > 0) {
					// LDR/STR
					long size = (orig >> 30) & 0x3;
					addend += (orig >> 10) & 0xfff;
					long value = ((targetAddr.getOffset() + addend) & 0xfff) >> size;
					instr = orig | (value << 10);
				}
				else {
					// ADD
					addend += (orig >> 10) & 0xfff;
					long value = (targetAddr.getOffset() + addend) & 0xfff;
					instr = orig | (value << 10);
				}
				byteLength = write(relocation, instr);
				break;
			}
			case ARM64_RELOC_AUTHENTICATED_POINTER: {
				long addend = orig & Conv.INT_MASK;
				long value = targetAddr.getOffset() + addend;
				byteLength = write(relocation, value);
				break;
			}
			
			case ARM64_RELOC_TLVP_LOAD_PAGE21:    // not seen yet
			case ARM64_RELOC_TLVP_LOAD_PAGEOFF12: // not seen yet
			case ARM64_RELOC_ADDEND:              // should never see on its own here
			default:
				return RelocationResult.UNSUPPORTED;
		}
		return new RelocationResult(Status.APPLIED, byteLength);
	}
A {@link MachoRelocationHandler} for AARCH64

@see <a href="https://opensource.apple.com/source/xnu/xnu-7195.81.3/EXTERNAL_HEADERS/mach-o/arm64/reloc.h.auto.html">mach-o/arm64/reloc.h</a>
Ghidra/Processors/AARCH64/src/main/java/ghidra/app/util/bin/format/macho/relocation/AARCH64_MachoRelocationHandler.java