kubo39's blog

ただの雑記です。

QEMUを使ってCortex M3なバイナリを動かしてみる

環境

$ cat /proc/version
Linux version 4.8.0-41-generic (buildd@lgw01-18) (gcc version 6.2.0 20161005 (Ubuntu 6.2.0-5ubuntu12) ) #44-Ubuntu SMP Fri Mar 3 15:27:17 UTC 2017
$ ldc2 -version| head -1
LDC - the LLVM D compiler (1.0.0):

インストール方法

$ sudo apt install -y gcc-arm-none-eabi gdb-arm-none-eabi qemu-system-arm ldc

手順

まず以下のようにD言語のプログラムを書いてみる。

import ldc.attributes;

extern(C):
@nogc:
nothrow:

@(section("_reset"))
void main()
{
    int y = void;
    auto x = 42;
    y = x;

    while (true) {}
}
$ ldc2 -march=thumb -mcpu=cortex-m3 -c -g main.d
$ arm-none-eabi-ld main.o -T layout.ld -nostartfiles -o main.bin

このままでは以下のようなエラーが出てしまう。

main.o: In function `ldc.register_dso':
main.d:(.text.ldc.register_dso+0x60): undefined reference to `_d_dso_registry'

_d_dso_registry はDランタイム内部で利用される関数である。

http://arsdnet.net/this-week-in-d/2016-oct-09.html

今回生成するバイナリでは必要ないものであるので、 LDC_no_moduleinfo を使って無効にする。

LDC-specific_language_changes

このようになっているはず。

import ldc.attributes;

extern(C):
@nogc:
nothrow:

pragma(LDC_no_moduleinfo);

@(section("_reset"))
void main()
{
    int y = void;
    auto x = 42;
    y = x;

    while (true) {}
}

QEMUを起動してgdbサーバをたてておく。

$ qemu-system-arm \
    -cpu cortex-m3 \
    -machine lm3s6965evb \
    -gdb tcp::3333 \
    -S \
    -nographic -monitor null \
    -serial null \
    -kernel main.bin

gdbを起動してstep実行。ループに入ったところで制御がきかなくなってしまった。

$ arm-none-eabi-gdb -q main.bin
Reading symbols from main.bin...done.
(gdb) target remote :3333
Remote debugging using :3333
main () at main.d:10
10      void main()
(gdb) step
13          auto x = 42;
(gdb) step
14          y = x;
(gdb) print x
$1 = 42
(gdb) print &x
$2 = (int *) 0x2000fff8
(gdb) print y
$3 = 0
(gdb) print &y
$4 = (int *) 0x2000fffc
(gdb)