egametang/ET · error · ArgumentException
address offset of target and replace must larger than ((1 <<
Error message
address offset of target and replace must larger than ((1 << 25) - 1), please use InstructionModifier_arm32_near instead
What it means
Thrown by CodePatcher_arm32_far's constructor. The far branch variant (8-byte LDR PC, [PC, #-4]) works at any distance but is needlessly large when a near branch would suffice. As a guard against using the wrong patcher, the constructor rejects the case where the offset is actually small enough (< 32 MiB) for the near variant, directing you to use CodePatcher_arm32_near instead.
Source
Thrown at Packages/cn.etetet.hybridclr/Scripts/Editor/Share/3rds/UnityHook/CodePatcher.cs:226
*ptr++ = (byte)(val >> 16);
*ptr++ = 0xEA;
}
return ret;
}
}
public unsafe class CodePatcher_arm32_far : CodePatcher
{
private static readonly byte[] s_jmpCode = new byte[] // 8 bytes
{
0x04, 0xF0, 0x1F, 0xE5, // LDR PC, [PC, #-4]
0x00, 0x00, 0x00, 0x00, // $val
};
public CodePatcher_arm32_far(IntPtr target, IntPtr replace, IntPtr proxy) : base(target, replace, proxy, s_jmpCode.Length)
{
if (Math.Abs((long)target - (long)replace) < ((1 << 25) - 1))
throw new ArgumentException("address offset of target and replace must larger than ((1 << 25) - 1), please use InstructionModifier_arm32_near instead");
#if ENABLE_HOOK_DEBUG
Debug.Log($"CodePatcher_arm32_far: {PrintAddrs()}");
#endif
}
protected override unsafe byte[] GenJmpCode(void* jmpFrom, void* jmpTo)
{
byte[] ret = new byte[s_jmpCode.Length];
fixed (void* p = &ret[0])
{
uint* ptr = (uint*)p;
*ptr++ = 0xE51FF004;
*ptr = (uint)jmpTo;
}
return ret;
}View on GitHub (pinned to 5cab01f7a8)
Solutions
- Switch to CodePatcher_arm32_near for this target/replace pair since the offset is within range.
- Implement distance-based patcher selection so near is used when offset < (1<<25)-1 and far only when it exceeds that.
- If you intentionally want the far patcher for uniformity, you must fork the class and remove the guard.
Example fix
// before
var patcher = new CodePatcher_arm32_far(targetPtr, replacePtr, proxyPtr);
// after — select based on distance
long offset = Math.Abs((long)targetPtr - (long)replacePtr);
CodePatcher patcher = offset < ((1 << 25) - 1)
? (CodePatcher)new CodePatcher_arm32_near(targetPtr, replacePtr, proxyPtr)
: new CodePatcher_arm32_far(targetPtr, replacePtr, proxyPtr); Defensive patterns
Strategy: validation
Validate before calling
long offset = Math.Abs((long)targetPtr - (long)replacePtr);
const long ARM32_NEAR_LIMIT = (1 << 25) - 1;
if (offset < ARM32_NEAR_LIMIT)
{
// Use near patcher instead — far patcher will reject this offset
Debug.LogWarning($"Offset {offset} is within near range. Use CodePatcher_arm32_near.");
} Type guard
static bool ShouldUseArm32Near(IntPtr target, IntPtr replace)
{
return Math.Abs((long)target - (long)replace) < ((1 << 25) - 1);
} Try / catch
try
{
var patcher = new CodePatcher_arm32_far(targetPtr, replacePtr, proxyPtr);
}
catch (ArgumentException ex) when (ex.Message.Contains("must larger than ((1 << 25)"))
{
// Switch to near patcher since offset is small enough
var patcher = new CodePatcher_arm32_near(targetPtr, replacePtr, proxyPtr);
} Prevention
- Never hardcode the far patcher — always select based on distance.
- Use a factory pattern that picks the correct patcher subclass.
- Read the error message: it explicitly tells you to use the near variant.
- Centralize patcher selection logic to avoid ad-hoc construction.
When it happens
Trigger: Constructing a CodePatcher_arm32_far where Math.Abs((long)target - (long)replace) < 33,554,431 bytes. This means a near patcher would work, so the far patcher considers this a misconfiguration and throws ArgumentException.
Common situations: Hardcoding the far patcher class without distance-based selection; copying example code that used the far patcher for a different scenario; the hook framework's selection logic incorrectly choosing far when near applies.
Related errors
- address offset of target and replace must less than ((1 << 2
- address offset of target and replace must less than (1 << 26
- 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/63d1fbaa2a97328c.
Report an issue: GitHub.