From c3a2ef45274f9f88d65239441ecd366cdc18a69b Mon Sep 17 00:00:00 2001 From: Slav Ishutin Date: Fri, 16 Dec 2022 10:44:34 +0300 Subject: [PATCH 1/2] restore floating point registers from stack in reverse order --- Sources/SuperBuilder/src/ITKSuperBuilder.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/SuperBuilder/src/ITKSuperBuilder.m b/Sources/SuperBuilder/src/ITKSuperBuilder.m index a80e44f..ce793de 100644 --- a/Sources/SuperBuilder/src/ITKSuperBuilder.m +++ b/Sources/SuperBuilder/src/ITKSuperBuilder.m @@ -213,10 +213,10 @@ asm volatile ( #if PROTECT_FLOATING_POINT_REGISTERS // pop {q0-q7} - "ldp q6, q7, [sp], #32\n" - "ldp q4, q5, [sp], #32\n" - "ldp q2, q3, [sp], #32\n" "ldp q0, q1, [sp], #32\n" + "ldp q2, q3, [sp], #32\n" + "ldp q4, q5, [sp], #32\n" + "ldp q6, q7, [sp], #32\n" #endif // get new return (adr of the objc_super class) From a19eff539d564054b706fee4bde5e4a830010d03 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 11 Jun 2026 10:14:59 +0100 Subject: [PATCH 2/2] test: cover arm64 floating-point arguments --- CHANGELOG.md | 1 + .../ObjectInterposeTests.swift | 20 +++++++++++++++++++ Tests/InterposeKitTests/TestClass.swift | 9 +++++++++ 3 files changed, 30 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d4d683..36b6234 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ * Preserve trampoline argument registers in code-coverage builds. * Preserve object-hook super trampolines in optimized Release builds, fixing https://github.com/steipete/InterposeKit/issues/29. Thanks to [@Thomvis](https://github.com/Thomvis). +* Preserve floating-point arguments when object hooks invoke original methods on arm64. Thanks to [@ishutinvv](https://github.com/ishutinvv). ## 0.01 diff --git a/Tests/InterposeKitTests/ObjectInterposeTests.swift b/Tests/InterposeKitTests/ObjectInterposeTests.swift index ec1fb01..596f5b2 100644 --- a/Tests/InterposeKitTests/ObjectInterposeTests.swift +++ b/Tests/InterposeKitTests/ObjectInterposeTests.swift @@ -134,6 +134,26 @@ final class ObjectInterposeTests: InterposeKitTestCase { try hook.revert() } + #if arch(arm64) + func test8FloatingPointParameters() throws { + let testObj = TestClass() + let expected = 87_654_321.0 + XCTAssertEqual(testObj.combine(1, 2, 3, 4, 5, 6, 7, 8), expected) + + let hook = try testObj.hook(#selector(TestClass.combine)) { (store: TypedHook + <@convention(c) (AnyObject, Selector, Double, Double, Double, Double, + Double, Double, Double, Double) -> Double, + @convention(block) (AnyObject, Double, Double, Double, Double, + Double, Double, Double, Double) -> Double>) in { + store.original($0, store.selector, $1, $2, $3, $4, $5, $6, $7, $8) + } + } + + XCTAssertEqual(testObj.combine(1, 2, 3, 4, 5, 6, 7, 8), expected) + try hook.revert() + } + #endif + func testObjectCallReturn() throws { let testObj = TestClass() let str = "foo" diff --git a/Tests/InterposeKitTests/TestClass.swift b/Tests/InterposeKitTests/TestClass.swift index f754ef0..385b85a 100644 --- a/Tests/InterposeKitTests/TestClass.swift +++ b/Tests/InterposeKitTests/TestClass.swift @@ -53,6 +53,15 @@ class TestClass: NSObject { var1 + var2 + var3 + var4 + var5 + var6 } + #if arch(arm64) + // swiftlint:disable:next function_parameter_count + @objc dynamic func combine(_ value0: Double, _ value1: Double, _ value2: Double, _ value3: Double, + _ value4: Double, _ value5: Double, _ value6: Double, _ value7: Double) -> Double { + value0 + (value1 * 10) + (value2 * 100) + (value3 * 1_000) + + (value4 * 10_000) + (value5 * 100_000) + (value6 * 1_000_000) + (value7 * 10_000_000) + } + #endif + // This requires _objc_msgSendSuper_stret on x64, returns a large struct @objc dynamic func invert3DTransform(_ input: CATransform3D) -> CATransform3D { input.inverted