2010年03月03日

QEMUにデバッガをつなぐ

今回はQEMUにデバッガをつなぐ話をします。

  • QEMUそのものをgdbで追いかける
  • QEMU上の仮想マシンにgdbをつなぐ
  • QEMUそのものとその上の仮想マシンを同時に2つのgdbで追いかける


QEMUそのものをgdbで追いかける

インストールされたqemu-system-armはシンボル情報が削除されています。(stripped)

$ file /usr/bin/qemu-system-arm
/usr/bin/qemu-system-arm: ELF 64-bit LSB executable, x86-64, version 1 (SYSV),
 dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped

なので、QEMUをソースからビルドして、arm-softmmu ディレクトリにあるqemu-system-armを使います。

$ file obj/arm-softmmu/qemu-system-arm 
obj/arm-softmmu/qemu-system-arm: ELF 64-bit LSB executable, x86-64, version 1 (SYSV),
 dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped

gdbのインストール

Debian/Ubuntuの場合はapt-getで簡単にインストールできます。

 $ sudo apt-get install gdb

Windowsの場合はMinGWのダウンロードサイトの GNU Source-Level Debugger のところから gdb-7.0.1-mingw32-bin.tar.gz をダウンロードしてきてc:\MinGW\の下に展開します。

gdbの起動

通常のQEMUの起動方法で頭に "gdb --args " をつけると楽です。

 $ gdb --args qemu-system-arm -M versatilepb -m 256 \
 -kernel arch/arm/boot/zImage \
 -redir tcp:55555::22 \
 -append "root=/dev/nfs rw nfsroot=192.168.xx.xx:/export/debian_lenny_armel/root ip=dhcp "

gdbのプロンプトがでたら r または run と打ち込めばqemuが走り始めます。

コントロールCで強制停止します。

Linuxの場合だと頻繁にSIGUSR1のsignalで止まってしまうので、SIGUSR1を無視するようにカレントディレクトリの.gdbinitに以下を書いておくとよいです。

 $ cat .gdbinit 
 handle SIGUSR1 nostop
 handle SIGUSR1 noprint

(2012.1.16追記)

久しぶりにqemu-1.0で試すと、SIGUSR1でなくSIG38のシグナルが頻繁に入るようになっていました。そこで、.gdbinitは以下のようにしました。

$ cat .gdbinit
handle SIG38 nostop
handle SIG38 noprint

(2012.1.16追記ここまで。)

Windowsではgdbの起動をシェルスクリプトにしているとコントロールCで、そのシェルスクリプト自体が終了してしまうということが起こりました。コマンドプロンプトから直接gdbを起動するか、またはバッチファイルからgdbを起動するようにすれば、コントロールCでターゲットプログラムを強制停止させることができます。

QEMU上の仮想マシンにgdbをつなぐ

クロス開発でよく使うgdbserverの機能はqemu-system-armに内包されています。クロスのgdb (ARM用ならarm-eabi-gdb)はバイナリパッケージでは用意されていないのでソースからビルドします。

ARM用のクロスgdbのビルド

http://www.gnu.org/software/gdb/

からソースアーカイブをダウンロード。

Linuxでのビルド
 $ tar xvf gdb-7.0.1.tar.bz2
 $ mkdir obj
 $ cd obj
 $ ../gdb-7.0.1/configure --target=arm-eabi 
 $ make
 $ sudo make install

--prefixを省略すると/usr/localにインストールされます。

WindowsのMSYS環境でのビルド
 $ tar xvjf gdb-7.0.1.tar.bz2
 $ mkdir obj
 $ cd obj
 $ ../gdb-7.0.1/configure --target=arm-eabi --prefix=/mingw
 $ make
 $ make install

QEMUの起動

gdbと接続するために -S -gdb tcp::1234 のオプションを追加します。1234はgdbとの通信に使うポート番号です。

(qemu-0.10.xの頃は -S -s -p 1234 でしたが変更されました。)

$ qemu-system-arm \
 -S -gdb tcp::1234 \
 -M versatilepb -m 256 -kernel arch/arm/boot/zImage \
 -redir tcp:55555::22 \
 -append "root=/dev/nfs rw nfsroot=192.168.xx.xx:/export/debian_lenny_armel/root ip=dhcp "

起動するとすぐにgdbの接続待ちになります。(-S を省略すると待たずに続行します。)

クロスgdbの起動

 $ arm-eabi-gdb vmlinux

vmlinuxはデバッグオプション(-g)をつけてビルドしておく必要があります。

 (gdb) target remote localhost:1234
 (gdb) c

target remoteでqemuの動いているホストのIPアドレスと先ほどのポート番号を指定します。(arm-eabi-gdbとqemu-system-armが別々のマシンで動いていてもかまいません。)

その後、r(run)でなくてc(continue)でターゲットプログラムを続行します。

QEMUそのものとその上の仮想マシンを同時に2つのgdbで追いかける

上の2つはもちろん重ねて使うことができます。

$ gdb --args qemu-system-arm \
 -S -gdb tcp::1234 \
 -M versatilepb -m 256 -kernel arch/arm/boot/zImage \
 -redir tcp:55555::22 \
 -append "root=/dev/nfs rw nfsroot=192.168.xx.xx:/export/debian_lenny_armel/root ip=dhcp "

.

.

One more thing ...

カタログには載せていませんがQEMUにつながるPARTNERは存在します。

partner_android00

(クリックで拡大表示)

AndroidのエミュレータにPARTNERをつなげてdo_execveでブレークしたところ。PARTNERはWindows7で、AndroidエミュレータはUbuntuで動いています。



トラックバックURL

コメントする

名前
URL
 
  絵文字
 
 
記事検索
最新コメント
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

QRコード
QRコード