カヤックのAdvent Calendar 9日目は @Gemmbu がお送りします。
iOS でも実行時に確保したメモリ上のコードが動作することはある界隈では有名ですが、
手元で試したことがある方はすくないのではと思います。
そこで実行時に確保したメモリ上に、与えられた数値に 1 加算して返す関数を実装し動作させてみましょう。
流れ
- 与えられた数値に 1 加算して返すコードを書く
- アライメントを意識してメモリを確保する
- 確保したメモリにコードを書き込む
- 確保したメモリに実行権限を付与する
- 確保したメモリを関数として実行する
サンプルコード
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
// 与えられた数値に 1 加算して返すコード書く
// 以下は armv7s 用のコードであり、armv7 及び arm64 ではそれぞれ別のコードにする必要がある。
uint32_t code[] = {
0xe2800001, // add r0, r0, #1
0xe12fff1e, // br lr
};
// アライメントを意識してメモリを確保する
uint32_t *p;
long pagesize = sysconf(_SC_PAGE_SIZE);
NSLog(@"pagesize %@", @(pagesize));
int r = posix_memalign((void **)&p, pagesize, pagesize);
if(r != 0){
int err = errno;
NSCAssert(NO, @"posix_memalign failed %s(%d) ", strerror(err), err);
}
// 確保したメモリにコードを書き込む
memcpy(p, code, sizeof(code));
// 確保したメモリに実行権限を付与する
int errcode = mprotect(p, pagesize, PROT_READ | PROT_EXEC);
if (errcode != 0) {
int err = errno;
NSCAssert(NO, @"mprotect failed %s(%d) ", strerror(err), err);
}
// 確保したメモリを関数として実行する
NSLog(@"inc(1) = %d", ((int(*)(int))p)(1)); // > inc(1) = 2
...
ここから https://github.com/KAMEDAkyosuke/ios-dynamic-function コードを取得できます
これを応用することでオレオレ言語にオレオレ jit を乗せることもできちゃいますね。
カヤックでオレオレ言語といえばうんこ演算で使用されている Unko Script。
この Unko Script を jit 化して高速化したい情熱のある人はいないでしょうか。
NOTE
Unko Script は Scheme を元にして作られた関数型言語です。
明日は
アドベントカレンダー10日目を担当してくださるのは、組長さんです。
カヤックのサービスを支えてくださりいつもありがとうございます。
カヤックではエンジニアを大募集しています
カヤックでは普通の iOS エンジニアだけでなく、やりたいことを実現するためなら c 言語よりさらに下に潜ってもいいエンジニアを募集しております。
社員と直接話せるイベント、1社だけの合同説明会を、1月17日(土)に渋谷ヒカリエで開催します!!!
ぜひご参加ください