JBなXperiaのカーネルを想定しています。
前提は以下です。
・この記事を参考にいろいろやった結果トラブっても自力で復旧できること(つまり自己責任)
・作業PCはWindows 7 64bit
■必要物資
・ターゲットとなるXperia端末のftf
・7za等、zipを展開できるツール
・lzop.exe(lzoを展開するツール)
・unpack-kernelsin
・pullkernellzo
・arm-linux-androideabi-objdump
・kallsymsprint
7zaは「7-zip」で検索、コマンドラインバージョンをダウンロードしてゲット。
lzop.exeは「lzop」で検索、Windows用をダウンロードしてゲット。
arm-linux-androideabi-objdump.exeは、android-ndk(sdkではない)の toolchains\arm-linux-androideabi-なんちゃら\prebuilt\windows\bin あたりに入っています。単体でも動くので、作業フォルダにコピーして使っても良いでしょう。
android-ndkはググってWindows用をダウンロードしてください。
■手順
1.ftfからkernel.sinを抽出
7za e なんちゃら.ftf kernel.sin
2.kernel.sinを展開
unpack-kernelsin.exe kernel.sin
「kernel.sin-header」「kernel.sin-kernel」「kernel.sin-ramdisk.cpio.gz」の3つが生成されます。
今回使用するのは「kernel.sin-kernel」です。
3.kernel.sin-kernelからlzo部分を抽出
pullkernellzo.exe kernel.sin-kernel
「kernelbin.lzo」が生成されます。
4.kernelbin.lzoを展開
lzop -d kernelbin.lzo
「kernelbin」が生成されます。
5.関数のアドレスをゲットする
欲しいアドレスは、
prepare_kernel_cred
commit_creds
remap_pfn_range
perf_swevent_enabled
ptmx_fops
の5つですが、このうち上から3つが関数のアドレス、残り2つは変数のアドレスです。
その2つの変数のアドレスを見付けるために、さらに以下の関数のアドレスも調べておきます。
sw_perf_event_destroy
pty_init
tty_default_fops
kallsymsprint.exe kernelbin > kallsymsprintdump.txt
上記を実行すると、何やらずらずらっと表示され、作業フォルダに「kallsymsprintdump.txt」というテキストファイルが生成されます。
kallsymsprintdump.txtの中を覗くと、
c00081c0 asm_do_IRQ
c00081c0 _stext
c00081c0 __exception_text_start
・
・
・
c00081c0 _stext
c00081c0 __exception_text_start
・
・
・
こんな感じで、アドレスと関数名の対応がひたすら並んでいます。
つまり、関数名でテキスト検索をかけると、関数の開始アドレスが分かるというわけです。
SO-01E(9.1.C.0.475)の例で言うと、各関数のアドレスは以下のような感じでした。
c009843c prepare_kernel_cred
c0097f60 commit_creds
c010e1f4 remap_pfn_range
c00e7b98 sw_perf_event_destroy
c0a1ecf8 pty_init
c02d267c tty_default_fops
c0097f60 commit_creds
c010e1f4 remap_pfn_range
c00e7b98 sw_perf_event_destroy
c0a1ecf8 pty_init
c02d267c tty_default_fops
とりあえず、求めたいアドレスのうち「prepare_kernel_cred」「commit_creds」「remap_pfn_range」はこれで判明しました。
6.kernelbinの逆アセンブル
perf_swevent_enabled を見付けるために sw_perf_event_destroy を、 ptmx_fops を見付けるために pty_init を逆アセンブルします。
それぞれの関数の開始アドレスから、0x1000くらいまでの範囲に絞って実行します。
arm-linux-androideabi-objdump -b binary -m arm --adjust-vma=0xc0008000 --start-address=0xc00e7b98 --stop-address=0xc00e8b98 -D kernelbin > kernel_asm1.txt
arm-linux-androideabi-objdump -b binary -m arm --adjust-vma=0xc0008000 --start-address=0xc0a1ecf8 --stop-address=0xc0a1fcf8 -D kernelbin > kernel_asm2.txt
7.アセンブリコードからアドレスを特定
まずテキストエディタでkernel_asm1.txt(sw_perf_event_destroyのコード)を開きます。
c00e7b98: e92d4070 push {r4, r5, r6, lr}
c00e7b9c: e1a04000 mov r4, r0
c00e7ba0: e590319c ldr r3, [r0, #412] ; 0x19c
c00e7ba4: e5905080 ldr r5, [r0, #128] ; 0x80
c00e7ba8: e3530000 cmp r3, #0
c00e7bac: 0a000002 beq 0xc00e7bbc
c00e7bb0: e59f0070 ldr r0, [pc, #112] ; 0xc00e7c28
c00e7bb4: e30113f9 movw r1, #5113 ; 0x13f9
c00e7bb8: ebfe3788 bl 0xc00759e0
c00e7bbc: e59f3068 ldr r3, [pc, #104] ; 0xc00e7c2c
c00e7bc0: e0835105 add r5, r3, r5, lsl #2
・
・
・
c00e7b9c: e1a04000 mov r4, r0
c00e7ba0: e590319c ldr r3, [r0, #412] ; 0x19c
c00e7ba4: e5905080 ldr r5, [r0, #128] ; 0x80
c00e7ba8: e3530000 cmp r3, #0
c00e7bac: 0a000002 beq 0xc00e7bbc
c00e7bb0: e59f0070 ldr r0, [pc, #112] ; 0xc00e7c28
c00e7bb4: e30113f9 movw r1, #5113 ; 0x13f9
c00e7bb8: ebfe3788 bl 0xc00759e0
c00e7bbc: e59f3068 ldr r3, [pc, #104] ; 0xc00e7c2c
c00e7bc0: e0835105 add r5, r3, r5, lsl #2
・
・
・
こんな感じの中身です。
左から、アドレス・機械語コード・ニーモニックですかね。
(ちなみに、関数は大体「push {うんたらかんたら}」で始まって、「pop {うんたらかんたら}」で終わります。ご参考までに。)
関数の結構最初の方(場合によっては後半)にある「add r5, r3, r5, lsl #2」の前の行、「ldr r3, [pc, #104] ; 0xc00e7c2c」に注目。
このr3の中身がperf_swevent_enabledのアドレスなのですが、「0xc00e7c2c」のアドレスに入ってるということで、そのアドレスの行がどうなっているか見てみます。
c00e7c2c: c0cee0f4 strdgt lr, [lr], #4
機械語部分が「c0cee0f4」となっています。これが perf_swevent_enabled のアドレスとなります。
次にkernel_asm2.txt(pty_initのコード)を開きます。
テキスト検索で、一番最初に出てくる「0xc02d267c」(前項で調べておいたtty_default_fopsのアドレス)のあたりを見ます。
・
・
・
c0a1ee64: e2850008 add r0, r5, #8
c0a1ee68: ebe2ce03 bl 0xc02d267c
・
・
・
・
・
c0a1ee64: e2850008 add r0, r5, #8
c0a1ee68: ebe2ce03 bl 0xc02d267c
・
・
・
「bl 0xc02d267c」で、tty_default_fopsに飛ぶ感じなのですが、その前の行「add r0, r5, #8」に注目。
これは「r5に8を足して、r0に代入するよ」ということです。
ここに出てくるr0が ptmx_fops のアドレスなのですが、r5が分かれば8を足せば良いということになりますね。
ではここからさかのぼって、直近の「ldr r5, [xxx]」を探します。
すると以下のような部分が見付かりました。
c0a1ed04: e59f51d4 ldr r5, [pc, #468] ; 0xc0a1eee0
「0xc0a1eee0」のアドレスに、r5の中身が入っていそうです。
ということで、c0a1eee0の行を調べてみると、
c0a1eee0: c0d03200 sbcsgt r3, r0, r0, lsl #4
となっていました。機械語部分は「c0d03200」です。つまり、「r5 = 0xc0d03200」ということになります。
先ほど述べたように、これに8を足せばいいので、 ptmx_fops のアドレスは「c0d03208」となります。
■結果
以上をもちまして、求めたいアドレスは以下のようになりました。
prepare_kernel_cred = 0xc009843c
commit_creds = 0xc0097f60
remap_pfn_range = 0xc010e1f4
perf_swevent_enabled = 0xc0cee0f4
ptmx_fops = 0xc0d03208
commit_creds = 0xc0097f60
remap_pfn_range = 0xc010e1f4
perf_swevent_enabled = 0xc0cee0f4
ptmx_fops = 0xc0d03208
わかりやすいまとめ、ありがとうございます。
返信削除恐縮です。
削除Cubemodをvl用にしたいんですが
返信削除具体的にどんなことをすればいいですか?
実機とぐぐる能力しかありません
コメント欄で一口に回答できるような内容ではありません。
削除大雑把に申し上げると、本来のapk、odexとmodのそれとを比較して変更点をおさえ、移植先のコードに反映、またリソースIDのズレを修正、実機で動作確認しながら調整という流れになるかと思いますが、一からmodを作るより大変かと思われます。
それから、次回からは記事の内容に関連したコメントをいただけるとありがたいです。
削除ちゃんとカーネル取り出すろことから書いたんですねぇ。
返信削除お疲れ様です。
ftf作るまでなら結構情報揃ってると判断しまして、その次の段階から説明したら誰でも出来るかな、という感じで、この形に落ち着きました。
削除お陰様で.401なSOL21でワンクリキットを作る事が出来ました。
返信削除素人にも解りやすい解説ありがとうございました。
はぐれさんも(^^)
いやはや、素晴らしいです。
削除殴り書き記事なので自分以外分かるのかこれ、と思ってましたが、ちゃんと伝わることが実証されました。
突っ込み等ありましたら、今後も遠慮無くご指摘下さいませ。