2011年9月14日水曜日

ARM gcc

前回のソースコードのコンパイル結果がどんな感じになっているか見る。
アセンブラを見ると、



$ arm-linux-gnueabi-gcc -S sample.c
$ cat sample.s
        .cpu arm9tdmi
        .fpu softvfp
        .eabi_attribute 20, 1
        .eabi_attribute 21, 1
        .eabi_attribute 23, 3
        .eabi_attribute 24, 1
        .eabi_attribute 25, 1
        .eabi_attribute 26, 2
        .eabi_attribute 30, 6
        .eabi_attribute 18, 4
        .file   "sample.c"
        .section        .rodata
        .align  2
.LC0:
        .ascii  "Hello world.\000"
        .text
        .align  2
        .global main
        .type   main, %function
main:
        @ Function supports interworking.
        @ args = 0, pretend = 0, frame = 0
        @ frame_needed = 1, uses_anonymous_args = 0
        mov     ip, sp
        stmfd   sp!, {fp, ip, lr, pc}
        sub     fp, ip, #4
        ldr     r0, .L3
        bl      puts
        mov     r3, #0
        mov     r0, r3
        sub     sp, fp, #12
        ldmfd   sp, {fp, sp, lr}
        bx      lr
.L4:
        .align  2
.L3:
        .word   .LC0
        .size   main, .-main
        .ident  "GCC: (Debian 4.3.5-4) 4.3.5"
        .section        .note.GNU-stack,"",%progbits


途中で、puts を呼んでいる。
a.out は、puts を知らないのでそのままでは実行できない。libc が必要。


$ arm-linux-gnueabi-nm a.out  | grep " U "
         U __libc_start_main@@GLIBC_2.4
         U abort@@GLIBC_2.4
         U puts@@GLIBC_2.4
$ qemu-arm ./a.out
/lib/ld-linux.so.3: No such file or directory


qemu-arm 実行時に -L で libc の ARM バイナリの位置を与えると実行できる。



$ qemu-arm -L /usr/arm-linux-gnueabi ./a.out
Hello world.

puts などを静的リンクしておくこともできる。
$ arm-linux-gnueabi-gcc sample.c -static
$ arm-linux-gnueabi-nm a.out  | grep " U "
$ qemu-arm ./a.out
Hello world.


puts 内部では、システムコール write を呼ぶ。
qemu-arm では、write システムコールをホストマシンの write システムコール実行に置き換える。
write 以外にこんなシステムコールが使われている。



$ qemu-arm -strace -L /usr/arm-linux-gnueabi/ a.out
1698 brk(NULL) = 0x00011000
1698 uname(0x4006f7a0) = 0
1698 access("/etc/ld.so.nohwcap",F_OK) = -1 errno=2 (No such file or directory)
1698 mmap2(NULL,4096,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0x42071000
1698 access("/etc/ld.so.preload",R_OK) = -1 errno=2 (No such file or directory)
1698 open("/etc/ld.so.cache",O_RDONLY) = 3
1698 fstat64(3,0x4006f3b8) = 0
1698 mmap2(NULL,26461,PROT_READ,MAP_PRIVATE,3,0) = 0x42072000
1698 close(3) = 0
1698 access("/etc/ld.so.nohwcap",F_OK) = -1 errno=2 (No such file or directory)
1698 open("/lib/libc.so.6",O_RDONLY) = 3
1698 read(3,0x4006f4cc,512) = 512
1698 fstat64(3,0x4006f3f0) = 0
1698 mmap2(NULL,4096,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0x42079000
1698 mmap2(NULL,1242372,PROT_EXEC|PROT_READ,MAP_PRIVATE|MAP_DENYWRITE,3,0) = 0x4207a000
1698 mprotect(0x4219d000,28672,PROT_NONE) = 0
1698 mmap2(0x421a4000,12288,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_DENYWRITE|MAP_FIXED,3,0x122) = 0x421a4000
1698 mmap2(0x421a7000,9476,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,-1,0) = 0x421a7000
1698 close(3) = 0
1698 mmap2(NULL,4096,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0x421aa000
1698 open("/dev/urandom",O_RDONLY) = 3
1698 read(3,0x4006f96d,3) = 3
1698 close(3) = 0
1698 mprotect(0x421a4000,8192,PROT_READ) = 0
1698 mprotect(0x40095000,4096,PROT_READ) = 0
1698 munmap(0x42072000,26461) = 0
1698 fstat64(1,0x4006fb48) = 0
1698 mmap2(NULL,4096,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0) = 0x421ab000
1698 write(1,0x421ab000,13)Hello world.
 = 13
1698 exit_group(0)




0 件のコメント:

コメントを投稿