I'm trying to debug a bug in integrating our code with closed-source 3rd part library. Documentation is a bit sparse, so I'm trying to debug what is going on in assembly. To speed up things, I'm hooking few key methods using GitHub - rentzsch/mach_override: runtime function overriding for Mac OS X. For each method in question, I'm declaring two methods - first one overrides original method, second one is overriden by the the re-entry island. So calling the second method allows me to jump to the original impementation from the Swift code:
class Hook {
final func foo(x: X) -> Y {
let y = orig_foo(x: x)
print("foo: \(x) -> \(y)")
return y
}
final func orig_foo(x: X) -> Y {
fatalError()
}
}
This worked pretty well for method where I was able to guess the signature correctly. But currently fails miserably for another method, where my understanding of the signature is incorrect.
I know that I'm trying to hook an instance method of generic class with a single type parameter. Not sure if any protocol witnesses are involved. Method takes one argument which is a struct with two optional CGFloat
's and returns a struct with two CGFloat
's.
struct X {
var w: CGFloat?
var h: CGFloat?
}
struct Y {
var w: CGFloat
var h: CGFloat
}
According to the signature of the method provided by the xcrun swift-demangle
, argument should be passed by value. Code of the hook reads attempts to read its argument by value from %rdi
, %sil
, %rdx
and %cl
,which make sense for passing by value. But calling code passes the input by pointer in %rdi
. Both expect self
in %r13
and result in lower halves of %xmm0
-%xmm1
.
What am I missing? What can force a struct which is semantically passed by value to be passed by pointer?