2011年9月15日木曜日

ARM レジスタダンプ

ARM のレジスタの内容を regs[16] にダンプする関数 dumpregs。


[dumpregs.s]

.text
        .global dumpregs


dumpregs:
        stmfd sp!, {r0}


        ldr r0, clabel
        add r0, r0, #4
        stmea r0!, {r1-r15}


        ldmfd sp!, {r0}


        ldr r1, clabel
        stmea r1!, {r0}


        bx lr




clabel: .word regs


C コードからは、
unsigned int regs[16];
extern int dumpregs();
で宣言しておいて、dumpregs() を呼び出すとその時点でのレジスタの内容が
regs[16] にコピーされる。

コンパイルは、
$ arm-linux-gnueabi-gcc sample.c dumpregs.s

2011年9月14日水曜日

vmware player のディスク拡張

vmware player のディスクを拡張するためには、
・vmware の設定でディスクを拡張
・パーティションテーブルを変更
が必要。

パーティションテーブルの変更には、
gparted の iso ファイルを http://gparted.sourceforge.net/ からダウンロードして、
その iso イメージから vmware を起動した。

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)




2011年9月11日日曜日

Hello world

ARM バイナリの実行に qemu を使うことにする。
# apt-get install qemu

QEMU ARM 上で、Hello world を実行。

#include <stdio.h>

int main()
{
   printf("Hello world.\n");
}

% arm-linux-gnueabi-gcc sample.c
% qemu-arm -L /usr/arm-linux-gnueabi ./a.out
Hello world.


Debian squeeze で ARM クロスコンパイル環境構築

http://debian.fam.cx/index.php?Tips#v9530ebe を参考に、Debian squeeze 上に ARM クロスコンパイル環境を構築。

# aptitude install emdebian-crush emdebian-grip emdebian-archive-keyring

apt-line に下記を追加
deb http://www.emdebian.org/debian/ stable main

# aptitude install gcc-4.3-arm-linux-gnueabi