(追記)引用元ブログの追加。肝心なものを忘れてた。。
Swiftのランタイムをリバースエンジニアリングした人のブログ。いくつか興味深い調査結果を紹介している。
気になったところを抜き出してみる。
Objects, Classes,...
Swift objects are actually Objective-C objects.
Swift classes have no Objective-C methods.
SwiftObject is a root Objective-C class, similar to NSObject. It has no superclass,...
classes for Swift objects have no methods. Instead, they have been replaced with C++-like functions, mangling and all. This is likely why Swift has been said to be much faster than Objective-C; there is no more need for objc_msgSend to find and call method implementations.
Swiftのメソッドは、Objective-Cのメソッドの代わりに C++ライクな関数で実装されていて、これが速い理由の一つのようだ。C++のような vtableをクラスが持っているとのこと。
Name Mangling
Swiftは関数のメタ情報を保持する。これを Name Mangling と呼ぶらしい。
例えば
class Shape{
func numberOfSides() -> Int {
return 5
}
}
というクラスがあった場合、The mangled nameは_TFC9swifttest5Shape17simpleDescriptionfS0_FT_Si.となる。それぞれの文字が意味を持っている。Objective-Cのタイプエンコードっぽいが、クラス名とメソッド名も一緒にまとめられている。
Function Hooking
脱獄系ツールのMobileSubstrateを使っての解析。
class Shape {
var numberOfSides: Int;
init(){
numberOfSides = 5;
}
}
関数フックを使ってメンバ変数 numberOfSidesの値を4に変えてみる。先ほどの Name Mangling を応用してメンバ変数のget/setをフックしている。
まず getter
int (*numberOfSides)(id self);
MSHook(int, numberOfSides, id self){
return 4;
}
%ctor{
numberOfSides = (int (*)(id self)) dlsym(RTLD_DEFAULT, "_TFC9swifttest5Shapeg13numberOfSidesSi");
MSHookFunction(numberOfSides, MSHake(numberOfSides));
}
これは成功。次に setter
void (*setNumberOfSides)(int newNumber, id self);
MSHook(void, setNumberOfSides, int newNumber, id self){
_setNumberOfSides(4, self);
}
%ctor {
setNumberOfSides = (void (*)(int newNumber, id self)) dlsym(RTLD_DEFAULT, "_TFC9swifttest5Shapes13numberOfSidesSi");
MSHookFunction(setNumberOfSides, MSHake(setNumberOfSides));
}
これは失敗。コンストラクタにおけるメンバ変数設定はインラインで行われる(setterを呼ばない)ため。そこでsetterを経由せず直接設定
void (*setNumberOfSides)(int newNumber, id self);
MSHook(void, setNumberOfSides, int newNumber, id self){
MSHookIvar(self, "numberOfSides") = 4;
}
%ctor {
setNumberOfSides = (void (*)(int newNumber, id self)) dlsym(RTLD_DEFAULT, "_TFC9swifttest5Shapes13numberOfSidesSi");
MSHookFunction(setNumberOfSides, MSHake(setNumberOfSides));
}
これは成功。参考:dlsym
dlsym() が特別な handle RTLD_DEFAULT を使用して呼び出された場合は、オブジェクトが ロードされる際に未定義のシンボルを解決するために 使用されるアルゴリズムに従ってシンボルを探索します。 探索されるオブジェクトは次のように書かれた順番になります。.....


