egametang/ET · error · ArgumentException
address offset of target and replace must less than (1 << 26
Error message
address offset of target and replace must less than (1 << 26) - 1) * 4
What it means
Thrown by CodePatcher_arm64_near's constructor. On ARM64, the B (unconditional branch) instruction encodes a 26-bit signed immediate multiplied by 4, giving a ±128 MiB reach ((2^26 - 1) * 4 bytes). If the absolute difference between target and replacement addresses reaches or exceeds this limit, the near branch cannot encode the jump and the constructor throws ArgumentException.
Source
Thrown at Packages/cn.etetet.hybridclr/Scripts/Editor/Share/3rds/UnityHook/CodePatcher.cs:265
/// <summary>
/// arm64 下 ±128MB 范围内的跳转
/// </summary>
public unsafe class CodePatcher_arm64_near : CodePatcher
{
private static readonly byte[] s_jmpCode = new byte[] // 4 bytes
{
/*
* from 0x14 to 0x17 is B opcode
* offset bits is 26
* https://developer.arm.com/documentation/ddi0596/2021-09/Base-Instructions/B--Branch-
*/
0x00, 0x00, 0x00, 0x14, // B $val ; $val = (($dst - $src)/4) & 7FFFFFF
};
public CodePatcher_arm64_near(IntPtr target, IntPtr replace, IntPtr proxy) : base(target, replace, proxy, s_jmpCode.Length)
{
if (Math.Abs((long)target - (long)replace) >= ((1 << 26) - 1) * 4)
throw new ArgumentException("address offset of target and replace must less than (1 << 26) - 1) * 4");
#if ENABLE_HOOK_DEBUG
Debug.Log($"CodePatcher_arm64: {PrintAddrs()}");
#endif
}
protected override unsafe byte[] GenJmpCode(void* jmpFrom, void* jmpTo)
{
byte[] ret = new byte[s_jmpCode.Length];
int val = (int)((long)jmpTo - (long)jmpFrom) / 4;
fixed (void* p = &ret[0])
{
byte* ptr = (byte*)p;
*ptr++ = (byte)val;
*ptr++ = (byte)(val >> 8);
*ptr++ = (byte)(val >> 16);
View on GitHub (pinned to 5cab01f7a8)
Solutions
- Use CodePatcher_arm64_far (20-byte ADR+LDR+BR sequence) for out-of-range offsets.
- Implement distance-based patcher selection: near when offset < ((1<<26)-1)*4, far otherwise.
- Investigate whether the replacement function can be allocated closer to the target (e.g. via code allocation near the original).
- Verify you are on ARM64 — if the issue is on ARM32, use the arm32 patchers instead.
Example fix
// before
var patcher = new CodePatcher_arm64_near(targetPtr, replacePtr, proxy);
// after — choose based on distance
long offset = Math.Abs((long)targetPtr - (long)replacePtr);
CodePatcher patcher = offset < ((1L << 26) - 1) * 4
? new CodePatcher_arm64_near(targetPtr, replacePtr, proxy)
: new CodePatcher_arm64_far(targetPtr, replacePtr, proxy, 20); Defensive patterns
Strategy: validation
Validate before calling
long offset = Math.Abs((long)targetPtr - (long)replacePtr);
long arm64NearLimit = ((1L << 26) - 1) * 4; // ~128 MiB
if (offset >= arm64NearLimit)
{
Debug.LogWarning($"ARM64 near branch cannot reach offset {offset} (limit {arm64NearLimit}). Use CodePatcher_arm64_far.");
} Type guard
static bool CanUseArm64Near(IntPtr target, IntPtr replace)
{
return Math.Abs((long)target - (long)replace) < ((1L << 26) - 1) * 4;
} Try / catch
try
{
var patcher = new CodePatcher_arm64_near(targetPtr, replacePtr, proxy);
}
catch (ArgumentException ex) when (ex.Message.Contains("1 << 26"))
{
// Offset exceeds ±128 MiB; fall back to far patcher
var patcher = new CodePatcher_arm64_far(targetPtr, replacePtr, proxy, 20);
} Prevention
- Compute the offset before choosing arm64_near vs arm64_far.
- Use a patcher factory that selects based on measured distance.
- On ARM64 with high ASLR entropy, far patchers may be needed more often.
- Test on physical ARM64 devices to validate address layout assumptions.
When it happens
Trigger: Constructing a CodePatcher_arm64_near where Math.Abs((long)target - (long)replace) >= (67,108,863 * 4) = ~256 MiB. Occurs on ARM64 when ASLR, shared library loading, or JIT code allocation places the target and replacement functions more than ~128 MiB apart in the 64-bit address space.
Common situations: Hooking a method on ARM64 (modern Android, Apple Silicon) where the replacement lives in a separately loaded assembly or dynamically allocated code buffer far from the original; address space randomization (ASLR) on 64-bit placing libraries very far apart.
Related errors
- address offset of target and replace must less than ((1 << 2
- address offset of target and replace must larger than ((1 <<
- none of methods targetMethod or replacementMethod can be nul
- MethodHook:targetMethod and replacementMethod and proxyMetho
- WRANING: you can not hook abstract method [{methodName}]
AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13).
Data as JSON: /api/errors/318b3beca51f3260.
Report an issue: GitHub.