Skip to content

Instantly share code, notes, and snippets.

@hyuni
Forked from dankogai/peekFunc.swift
Last active December 17, 2018 13:08
Show Gist options
  • Save hyuni/e8725a1af1c7662cacf419a4e300caa3 to your computer and use it in GitHub Desktop.
Save hyuni/e8725a1af1c7662cacf419a4e300caa3 to your computer and use it in GitHub Desktop.
Get the internal function pointer in swift
/// See
/// https://github.com/rodionovd/SWRoute/wiki/Function-hooking-in-Swift
/// https://github.com/rodionovd/SWRoute/blob/master/SWRoute/rd_get_func_impl.c
/// to find why this works
func peekFunc<A, R>(_ f: @escaping (A) -> R) -> (fp: Int, ctx: Int) {
typealias IntInt = (Int, Int)
let (_, lo) = unsafeBitCast(f, to: IntInt.self)
let offset = MemoryLayout<Int>.size == 8 ? 16 : 12
let ptr = UnsafePointer<Int>(bitPattern: lo + offset)!
return (ptr.pointee, ptr.successor().pointee)
}
func === <A, R>(lhs: @escaping (A) -> R, rhs: @escaping (A) -> R) -> Bool {
let (tl, tr) = (peekFunc(lhs), peekFunc(rhs))
return tl.0 == tr.0 && tl.1 == tr.1
}
// simple functions
func genericId<T>(t:T)->T { return t }
func incr(i:Int)->Int { return i + 1 }
var f: (Int) -> Int = genericId
var g = f; print("(f === g) == \(f === g)")
f = genericId; print("(f === g) == \(f === g)")
f = g; print("(f === g) == \(f === g)")
// closures
func mkcounter() -> () -> Int {
var count: Int = 0
return {
count += 1
return count
}
}
var c0 = mkcounter()
var c1 = mkcounter()
var c2 = c0
print("peekFunc(c0) == \(peekFunc(c0))")
print("peekFunc(c1) == \(peekFunc(c1))")
print("peekFunc(c2) == \(peekFunc(c2))")
print("(c0() == c1()) == \(c0() == c1())") // true : both are called once
print("(c0() == c2()) == \(c0() == c2())") // false: because c0() means c2()
print("(c0 === c1) == \(c0 === c1)")
print("(c0 === c2) == \(c0 === c2)")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment