Yabu.log

ITなどの雑記

パタヘネのMIPS学習環境をMacOSのVagrant上に作成する2

目的のMIPSをクロスコンパイル、アセンブル、逆アセンブルする環境が整いました。

おまけに実行環境まで揃いました。

手順は例の如く、この動画の通り進めます。

www.youtube.com

ロスコンパイル

まずは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のdebianx86で動いている想定なので、直接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"

これでMIPSアセンブリが作成できました。

アセンブル/逆アセンブル

では次にこちらをアセンブルして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ファイルどっかで配布しようかな