{"record":{"id":"63d1fbaa2a97328c","repo":"egametang/ET","slug":"address-offset-of-target-and-replace-must-larger-t","errorCode":null,"errorMessage":"address offset of target and replace must larger than ((1 << 25) - 1), please use InstructionModifier_arm32_near instead","messagePattern":"address offset of target and replace must larger than \\(\\(1 << 25\\) - 1\\), please use InstructionModifier_arm32_near instead","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.hybridclr/Scripts/Editor/Share/3rds/UnityHook/CodePatcher.cs","lineNumber":226,"sourceCode":"                *ptr++ = (byte)(val >> 16);\n                *ptr++ = 0xEA;\n            }\n            return ret;\n        }\n    }\n\n    public unsafe class CodePatcher_arm32_far : CodePatcher\n    {\n        private static readonly byte[] s_jmpCode = new byte[]    // 8 bytes\n        {\n            0x04, 0xF0, 0x1F, 0xE5,                         // LDR PC, [PC, #-4]\n            0x00, 0x00, 0x00, 0x00,                         // $val\n        };\n\n        public CodePatcher_arm32_far(IntPtr target, IntPtr replace, IntPtr proxy) : base(target, replace, proxy, s_jmpCode.Length)\n        {\n            if (Math.Abs((long)target - (long)replace) < ((1 << 25) - 1))\n                throw new ArgumentException(\"address offset of target and replace must larger than ((1 << 25) - 1), please use InstructionModifier_arm32_near instead\");\n\n#if ENABLE_HOOK_DEBUG\n            Debug.Log($\"CodePatcher_arm32_far: {PrintAddrs()}\");\n#endif\n        }\n\n        protected override unsafe byte[] GenJmpCode(void* jmpFrom, void* jmpTo)\n        {\n            byte[] ret = new byte[s_jmpCode.Length];\n\n            fixed (void* p = &ret[0])\n            {\n                uint* ptr = (uint*)p;\n                *ptr++ = 0xE51FF004;\n                *ptr = (uint)jmpTo;\n            }\n            return ret;\n        }","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.hybridclr/Scripts/Editor/Share/3rds/UnityHook/CodePatcher.cs#L208-L244","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nvar patcher = new CodePatcher_arm32_far(targetPtr, replacePtr, proxyPtr);\n\n// after — select based on distance\nlong offset = Math.Abs((long)targetPtr - (long)replacePtr);\nCodePatcher patcher = offset < ((1 << 25) - 1)\n    ? (CodePatcher)new CodePatcher_arm32_near(targetPtr, replacePtr, proxyPtr)\n    : new CodePatcher_arm32_far(targetPtr, replacePtr, proxyPtr);","handlingStrategy":"validation","validationCode":"long offset = Math.Abs((long)targetPtr - (long)replacePtr);\nconst long ARM32_NEAR_LIMIT = (1 << 25) - 1;\nif (offset < ARM32_NEAR_LIMIT)\n{\n    // Use near patcher instead — far patcher will reject this offset\n    Debug.LogWarning($\"Offset {offset} is within near range. Use CodePatcher_arm32_near.\");\n}","typeGuard":"static bool ShouldUseArm32Near(IntPtr target, IntPtr replace)\n{\n    return Math.Abs((long)target - (long)replace) < ((1 << 25) - 1);\n}","tryCatchPattern":"try\n{\n    var patcher = new CodePatcher_arm32_far(targetPtr, replacePtr, proxyPtr);\n}\ncatch (ArgumentException ex) when (ex.Message.Contains(\"must larger than ((1 << 25)\"))\n{\n    // Switch to near patcher since offset is small enough\n    var patcher = new CodePatcher_arm32_near(targetPtr, replacePtr, proxyPtr);\n}","preventionTips":["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."],"tags":["unityhook","arm32","code-patching","wrong-patcher","method-hook"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}