この記事は iOS Jailbreaking Advent Calendar 2015 の7日目の記事です。
メタプログラミング的なのかはよくわかってない。
シチュエーション
iOS x用にこんなコードのtweakがあったとする。
%hook AClass
- (void)sampleMethod
{
// some code...
}
%end
そしてiOS yがリリースされ、AClass
がリネームされBClass
になっていた場合、というシチュエーションにとる手法の話。
愚直方式
処理を関数に外出しして%hook
は愚直に記載していく方法。
%orig
を使う場合はout of %hook blockエラーになるので#define
のCマクロにしてpreprocessをlogo preprocessより先に実行する方法もあるけど、結構使いにくいのでオススメ出来ません。
方法としてこれはこれでアリです。function内のコードは複数iOSで利用される事を想定しないとアップデートしたら前のiOSで動かなくなるのでそこには注意。
static void function()
{
// some code...
}
%hook AClass
- (void)sampleMethod
{
function();
}
%end
%hook BClass
- (void)sampleMethod
{
function();
}
%end
meta hook
hookするクラスを動的にすりゃあいいんだろう!のための記法がtheosにはあります。
こんなコードになります、ジャーン!
%group MetaHookGroup
%hook MetaClass
- (void)sampleMethod
{
// some code...
}
%end
%end // End of metaHookGroup
%ctor
{
Class $hookClass = %c(AClass) ?: %c(BClass);
%init(MetaHookGroup, MetaClass = $hookClass);
}
これでAClassが存在する場合は-[AClass sampleMethod]
がhookされ、BClassが存在する場合は-[BClass sampleMethod]
hookされます。
この場合もsome code...
の部分は前バージョンに対してリグレッションをおこさないよう留意する必要はあります。
この手法は複数バージョンにわたって1バイナリでサポートする時にそこそこ利用します。5プロジェクトに1つぐらいで。