qemuとは

qemuは高速なCPUエミュレータです。PC上にsh4のqemu環境を用意しておくと便利です。応用ワザはいろいろあります。

qemuには2つの使い方があります。

  • フルシステムエミュレーション。このモードでは、QEMUは(例えばPCでは)プロセッサや各種の周辺装置を含めたすべてのシステムをエミュレートします。再起動することなく、異なったオペレーティングシステムを起動し、システムコードをデバッグすることができます。
  • ユーザーモードエミュレーション(Linuxホストのみ)。Linux用のプロセスのみをエミュレーションします。具体的には sh4向けにクロスコンパイルされた a.out (ELF)を PC上で実行します。周辺機器やハードウェア、カーネルはエミュレーションしません。

今回は簡単なユーザーモードエミュレーションの話を書きます

作業環境

PCにdebian 5.0 (lenny)をインストールしてください。他のディストリビューションでも大丈夫かもしれませんが筆者は debian lenny を使っています。

# apt-get install zlib1g-dev git-svn

qemuの導入

ソースの入手

$ mkdir qemu-build
$ cd qemu-build
$ git clone git://git.qemu.org/qemu.git stable-1.0
$ cd  stable-1.0
$ git checkout stable-1.0

sh4の場合、stable-1.1 より新しいバージョンでは シグナルを送ると落ちてしまう不具合があるので 1.0 を使う事。原因は解析中。

ビルド

$ ./configure --target-list=sh4-linux-user --disable-vhost-net --disable-kvm --disable-vnc --disable-usb-redir --disable-smartcard-nss --disable-smartcard --disable-libiscsi --disable-spice --disable-blobs  --static
$ make      (すぐ終わります)
$ strip sh4-linux-user/qemu-sh4     (必須ではありません)

インストール

$ su
password:(ルートパスワード)
# cp sh4-linux-user/qemu-sh4 /usr/local/bin

qemuの使い方

基本的な使い方

qemu-sh4 コマンドが使えるようになったと思います。
hello.c を用意します。

/* hello.c */
#include <stdio.h>
int main(){
        printf("hello sh4 world\n");
        return 0;
}

sh4向けにクロスコンパイルします

クロスコンパイル(スタティックリンク指定)
$ sh4-linux-gnu-gcc hello.c -static

ファイル属性を確認する(Renesas SH実行形式である)
$ file a.out
a.out: ELF 32-bit LSB executable, Renesas SH, version 1 (SYSV), 
statically linked, for GNU/Linux 2.6.11, not stripped

実行してみる(当然実行できない)
$ ./a.out
bash: ./a.out: cannot execute binary file

そこで qemu-sh4の出番です

$ /usr/local/bin/qemu-sh4 ./a.out
hello sh4 world

sh4用の a.out が実行できました。このようの qemuを使うと 100%完璧ではありませんが、PC上で sh4のプロセス(コマンド)が実行できます。

共有ライブラリの場合

コンパイル時に -static (スタティックリンク指定)をせず、共有ライブラリとしてコンパイルした場合

$ sh4-linux-gnu-gcc hello.c   (普通にクロスコンパイル)

sh4用のライブラリが /usr/sh4-linux-gnu/lib にインストールされているはずですので、-L 指定で実行します

$ qemu-sh4 -L /usr/sh4-linux-gnu/ ./a.out
hello sh4 world

毎回々々-L /usr/sh4-linux-gnu/ を指定するのが面倒であれば、
configure スクリプトを編集して

interp_prefix="/usr/%M-linux-gnu/"

にして make してしまえばokそう。

binfmt_misc と組み合わせる

binfmt_misc とはバイナリファイルの拡張子やファイル先頭のヘッダとインタープリターを関連付ける仕組みです。
SH4のELFヘッダーと qemu-sh4 を関連付けます。

$ su
# apt-get install binfmt-support
# /usr/sbin/update-binfmts --install qemu-sh4 /usr/local/bin/qemu-sh4 \
--magic '\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a\x00' \
--mask '\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
# exit   (rootでの作業終了)

すると、先ほどの sh4 用の a.out がそのまま実行できます

$ sh4-linux-gnu-gcc hello.c -static
$ ./a.out
hello sh4 world

関連