目的のMIPSをクロスコンパイル、アセンブル、逆アセンブルする環境が整いました。
おまけに実行環境まで揃いました。
手順は例の如く、この動画の通り進めます。
クロスコンパイル
まずはHelloWorldプログラムをコンパイルして見ます
#include<stdio.h> int main(){ puts("hello world\n"); return 0; }
以下のコマンドでx86/MIPSなどのCPUターゲット向けにビルドしています
gcc helloworld.c -o hellox86 mips-linux-gnu-gcc helloworld.c -o hellomips
それぞれ作成したhellox86とhellomipsファイルの情報を表示して見ます
$ file hellomips hellomips: ELF 32-bit MSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld.so.1, for GNU/Linux 3.2.0, BuildID[sha1]=99476e03a7fd711a9db72e3d26aed2eedfc4b978, not stripped $ file hellox86 hellox86: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=02c9c175d055b19d03b26fa37f9651d967c85611, not stripped
MIPSのソースを動かす
もちろんゲストOSのdebianはx86で動いている想定なので、直接mips用のバイナリを動かすことはできません
$ ./hellox86 hello world $ ./hellomips -bash: ./hellomips: cannot execute binary file: Exec format error
qemuを入れてそちらで動かします
sudo apt-get install qemu-user
動かして見たところ、動的リンクに失敗しているようです
$ qemu-mips hellomips /lib/ld.so.1: No such file or directory
静的リンクに切り替えてコンパイルして実行して見ます
$mips-linux-gnu-gcc -static helloworld.c -o hellomips_static $ file hellomips hellomips: ELF 32-bit MSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld.so.1, for GNU/Linux 3.2.0, BuildID[sha1]=99476e03a7fd711a9db72e3d26aed2eedfc4b978, not stripped $ file hellomips_static hellomips_static: ELF 32-bit MSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=4f0a58ae0f277369b2cc5d635e9226f7e30ed0e7, not stripped
statically linked
-staticオプションを利用してコンパイルしたもののファイル情報が変化しました。
静的リンクをしているのでやはり桁違いにバイナリサイズが大きいです
$ls -alt hellomips hellomips_static -rwxr-xr-x 1 vagrant vagrant 601504 Aug 13 21:41 hellomips_static -rwxr-xr-x 1 vagrant vagrant 6384 Aug 13 21:11 hellomips
では気を取り直して実行して見ます
$ qemu-mips hellomips_static hello world
gccでアセンブルせずにコンパイルだけする方法
gccでは-Sオプションをつけることでオブジェクトコードに変換せずアセンブリまででストップすることができます
$mips-linux-gnu-gcc -S helloworld.c -o helloworld_mips.s $ cat helloworld_mips.s .file 1 "helloworld.c" .section .mdebug.abi32 .previous .nan legacy .module fp=xx .module nooddspreg .abicalls .text .rdata .align 2 $LC0: .ascii "hello world\012\000" .text .align 2 .globl main .set nomips16 .set nomicromips .ent main .type main, @function main: .frame $fp,32,$31 # vars= 0, regs= 2/0, args= 16, gp= 8 .mask 0xc0000000,-4 .fmask 0x00000000,0 .set noreorder .cpload $25 .set nomacro addiu $sp,$sp,-32 sw $31,28($sp) sw $fp,24($sp) move $fp,$sp .cprestore 16 lw $2,%got($LC0)($28) addiu $4,$2,%lo($LC0) lw $2,%call16(puts)($28) move $25,$2 .reloc 1f,R_MIPS_JALR,puts 1: jalr $25 nop lw $28,16($fp) move $2,$0 move $sp,$fp lw $31,28($sp) lw $fp,24($sp) addiu $sp,$sp,32 jr $31 nop .set macro .set reorder .end main .size main, .-main .ident "GCC: (Debian 8.1.0-12) 8.1.0"
アセンブル/逆アセンブル
では次にこちらをアセンブルしてELFファイルを作って逆アセンブルしてみます
$ mips-linux-gnu-gcc -static helloworld_mips.s -o hellomips_static2
ファイルサイズを表示して見たところ全く同じだったので、diffをかけて見たところ全く同じ内容だった(当たり前といえば当たり前) GCCが自動的にコンパイル->アセンブルしている流れを手作業で段階的に同じステップを踏めるのは勉強するときに便利だと思う。
$ ls -alt hellomips_* -rwxr-xr-x 1 vagrant vagrant 601504 Aug 13 22:27 hellomips_static2 -rwxr-xr-x 1 vagrant vagrant 601504 Aug 13 21:41 hellomips_static $ diff hellomips_static hellomips_static2 (出力なし)
では逆アセンブルして見ます
$ mips-linux-gnu-objdump -d hellomips
結果(でかすぎるのでmain関数のところのみ) とりあえずstackを確保しているあたりくらいはアセンブリとほぼ同じですね。(正直アセンブリまだよくわかりません)
000007d0 <main>: 7d0: 3c1c0002 lui gp,0x2 7d4: 279c8240 addiu gp,gp,-32192 7d8: 0399e021 addu gp,gp,t9 7dc: 27bdffe0 addiu sp,sp,-32 7e0: afbf001c sw ra,28(sp) 7e4: afbe0018 sw s8,24(sp) 7e8: 03a0f025 move s8,sp 7ec: afbc0010 sw gp,16(sp) 7f0: 8f828034 lw v0,-32716(gp) 7f4: 244409d0 addiu a0,v0,2512 7f8: 8f82805c lw v0,-32676(gp) 7fc: 0040c825 move t9,v0 800: 0320f809 jalr t9 804: 00000000 nop 808: 8fdc0010 lw gp,16(s8) 80c: 00001025 move v0,zero 810: 03c0e825 move sp,s8 814: 8fbf001c lw ra,28(sp) 818: 8fbe0018 lw s8,24(sp) 81c: 27bd0020 addiu sp,sp,32 820: 03e00008 jr ra 824: 00000000 nop
これでパタヘネの学習内容の環境の整備に関してはやりたいことが終わりました。 このvagrantのboxファイルどっかで配布しようかな