@Override
	public RelocationResult relocate(MachoRelocation relocation)
			throws MemoryAccessException, RelocationException {
		
		if (!relocation.requiresRelocation()) {
			return RelocationResult.SKIPPED;
		}
		
		RelocationInfo relocationInfo = relocation.getRelocationInfo();
		Address targetAddr = relocation.getTargetAddress();
		long orig = read(relocation);

		int byteLength;
		switch (relocationInfo.getType()) {
			case ARM_RELOC_VANILLA:
				if (!relocationInfo.isPcRelocated()) {
					byteLength = write(relocation, targetAddr.getOffset());
				}
				else {
					return RelocationResult.UNSUPPORTED;
				}
				break;
			case ARM_THUMB_RELOC_BR22: {
				// BL and BLX
				boolean blx = (orig & 0xd000f800) == 0xc000f000;
				long s = (orig >> 10) & 0x1;
				long j1 = (orig >> 29) & 0x1;
				long j2 = (orig >> 27) & 0x1;
				long i1 = ~(j1 ^ s) & 0x1;
				long i2 = ~(j2 ^ s) & 0x1;
				long imm10 = orig & 0x3ff;
				long imm11 = (orig >> 16) & 0x7ff;
				long addend = (s << 24) | (i1 << 23) | (i2 << 22) | (imm10 << 12) | (imm11 << 1);
				addend |= s == 1 ? 0xfe000000 : 0; // sign extend
				addend &= blx ? ~0x3 : ~0; // 4-byte align BLX
				long value = targetAddr.getOffset() + addend;
				s = (value >> 24) & 0x1;
				i1 = (value >> 23) & 0x1;
				i2 = (value >> 22) & 0x1;
				j1 = ~(i1 ^ s) & 0x1;
				j2 = ~(i2 ^ s) & 0x1;
				imm10 = (value >> 12) & 0x3ff;
				imm11 = (value >> 1) & 0x7ff;
				long instr = orig & (blx ? 0xc000f800 : 0xd000f800);
				instr |= (j1 << 29) | (j2 << 27) | (imm11 << 16) | (s << 10) | imm10;
				byteLength = write(relocation, instr);
				break;
			}
			
			case ARM_RELOC_PAIR:           // should never see on its own here
			case ARM_RELOC_SECTDIFF:       // relocation not required (scattered)
			case ARM_RELOC_LOCAL_SECTDIFF: // relocation not required (scattered)
			case ARM_RELOC_PB_LA_PTR:      // not seen yet
			case ARM_RELOC_BR24:           // not seen yet
			case ARM_THUMB_32BIT_BRANCH:   // not seen yet
			case ARM_RELOC_HALF:           // relocation not required (scattered)
			case ARM_RELOC_HALF_SECTDIFF:  // relocation not required (scattered)
			default:
				return RelocationResult.UNSUPPORTED;
		}
		return new RelocationResult(Status.APPLIED, byteLength);
	}
A {@link MachoRelocationHandler} for ARM

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