読者です 読者をやめる 読者になる 読者になる

メモ書き

自分が後で見直すためにつけている作業のメモ書きです.それ以上の意味はありません

SkyEye(TOPPERS版)とGDBデバッグ可能な環境の準備(CodeSourceryを使わずに)

SkyEye 向けにRTOSをポーティングしたくて,環境を整えていたのでメモ.

開発ツールとして CodeSourcery が使われることが多いが,どうしても使いたくないので別のツール(たとえばGCC ARM Embedded in Launchpadとか)を使ってコンパイルデバッグまで出来ないかどうかを試してみる.

ちなみに,SkyEyeは TOPPERSプロジェクト/TOPPERSカーネル向けシミュレーション環境 の skyeye_devm_package-1.0.5.zip を使用する.もっと新しいの(たとえばSkyEye download | SourceForge.netとかには1.3.5とかがある)でもよいのだけれど,動作実績のある組み合わせで試したかったのでこちらを使うことにした.

コンパイラは先に挙げた LanchPad の ARM向けGCC 4.9を利用.
シェルは Cygwin を使用.ホスト向けコンパイラとかその辺はインストール済み.

サンプルとしてはこちらを試してみた.

そのままではビルドできなかったのでちょっと修正.

  • Makefile で,ツールチェインの target triplet を arm-non-eabi に変更.
  • hello.c で,putc が標準ライブラリと被ると警告が出るので別の名称に変更.

これでビルドは出来たので,skyeye(TOPPERS版) で実行してみる.

$ skyeye.exe -c skyeye.conf -e timerirq_hello
big_endian is false.
arch : arm
cpu info: armv3, arm7tdmi, 41007700, fff8ff00, 0
mach info: name at91, mach_init addr 0x41d650
uart_mod:0, desc_in:, desc_out:, converter:
SKYEYE: use arm7100 mmu ops
exec file "timerirq_hello"'s format is elf32-little.
load section .text: addr = 0x00000000  size = 0x0000011c.
load section .rodata.str1.4: addr = 0x0000011c  size = 0x00000010.
load section .data: addr = 0x00002000  size = 0x00001c00.
not load section .comment: addr = 0x00000000  size = 0x00000070 .
not load section .ARM.attributes: addr = 0x00000000  size = 0x00000025 .
not load section .debug_abbrev: addr = 0x00000000  size = 0x000000fe .
not load section .debug_info: addr = 0x00000000  size = 0x00000148 .
not load section .debug_line: addr = 0x00000000  size = 0x000000ca .
not load section .debug_aranges: addr = 0x00000000  size = 0x00000040 .
not load section .debug_loc: addr = 0x00000000  size = 0x0000004d .
not load section .debug_str: addr = 0x00000000  size = 0x000000c3 .
not load section .debug_frame: addr = 0x00000000  size = 0x00000030 .
call ARMul_InitSymTable,kernel filename is timerirq_hello.
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!

あっさり動く.

次は gdb でリモートデバッグを試す.

Cygwinのウィンドウを2つ用意し,片方で skyeye を gdb のリモートサーバとして起動.

$ skyeye.exe -c skyeye.conf -d

**************************** WARNING **********************************
If you want to run ELF image, you should use -e option to indicate
your elf-format image filename. Or you only want to run binary image,
you need to set the filename of the image and its entry in skyeye.conf.
***********************************************************************

big_endian is false.
arch : arm
cpu info: armv3, arm7tdmi, 41007700, fff8ff00, 0
mach info: name at91, mach_init addr 0x41d650
uart_mod:0, desc_in:, desc_out:, converter:
SKYEYE: use arm7100 mmu ops
debugmode= 1, filename = skyeye.conf, server TCP port:12345

もう一方で gdb を起動.

$ arm-none-eabi-gdb timerirq_hello
GNU gdb (GNU Tools for ARM Embedded Processors) 7.8.0.20150304-cvs
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-w64-mingw32 --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from timerirq_hello...done.
(gdb) target remote localhost:12345
Remote debugging using localhost:12345
Reply contains invalid hex digit 117
(gdb)

接続に失敗する.ちなみにリモートサーバの方も接続に失敗の表示が出てる.

Remote debugging using port:12345
readchar: Got EOF
Remote side has terminated connection.  GDBserver will reopen the connection.

少しググったところでは,自分の使用していた arm-none-eabi-gdb (version7.8)が新しいために target remote で接続に失敗しているらしい.

hiro99ma blog: [os]SkyEyeとGDBで接続できんのはSkyEyeバグらしいのでGDBバージョンを落とした
SkyEye / Bugs / #68 sth. wrong about remote-gdb

新しい SkyEye を使ってうまくいく自信がないので先に gdb-7.1 のビルドを試すことにした.

http://ftp.gnu.org/gnu/gdb/ から gdb-7.1a.tar.gz をダウンロード

ファイルを展開,移動

tar xvf gdb-7.1a.tar.gz
cd gdb-7.1

適当な名称でディレクトリ作成して移動

mkdir build
cd build

ビルド

../configure --target=arm-none-eabi --prefix=/home/saito/tool/gdb-7.1 --enable-interwork --enable-multilib
make all
make install

途中でビルドエラーになった(libncurces-devが無かったり,-Werrorに引っかかったりした)が,その辺は省略(簡単に対処できると思うので).

それで,作った GDB-7.1 でサーバに接続して実行開始してみる.

$ ~/tool/gdb-7.1/bin/arm-none-eabi-gdb timerirq_hello
GNU gdb (GDB) 7.1
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-pc-cygwin --target=arm-none-eabi".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/saito/work/timerirq/timerirq_hello...Dwarf Error: wrong version in compilation unit header (is 4, should be 2) [in module /home/saito/work/timerirq/timerirq_hello]
(gdb) target remote localhost:12345
Remote debugging using localhost:12345
0x00000000 in ?? ()
(gdb) load
Loading section .text, size 0x11c lma 0x0
Loading section .rodata.str1.4, size 0x10 lma 0x11c
Loading section .data, size 0x1c00 lma 0x2000
Start address 0x0, load size 7468
Transfer rate: 911 KB/sec, 155 bytes/write.
(gdb) c
Continuing.
Can't send signals to this remote system.  SIGHUP not sent.

そうするとサーバはちゃんと動いている.

Remote debugging using port:12345
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!
hello world!

と,いうわけでとりあえず実行ファイルさえ作ってしまえばデバッグは出来そうだということは確認できた.
しかし,よく見ると

Reading symbols from /home/saito/work/timerirq/timerirq_hello...Dwarf Error: wrong version in compilation unit header (is 4, should be 2) [in module /home/saito/work/timerirq/timerirq_hello]

などというメッセージが出ているのが気になる.ステップ実行を試みても

(gdb) s
Cannot find bounds of current function

となって出来ない.

要するに,デバッグ情報の格納に使うフォーマット(DWARF)のバージョンが合ってないということらしい.GDBの方が古いので,それが解釈できるようなバージョンにしてやる必要があるらしい.

ということで Debugging Options - Using the GNU Compiler Collection (GCC) を見ても大量にあってよくわからないが,もう少しググってみたら次の情報を見つけた.

c++ - How to change the version of a compilation unit? - Stack Overflow

つまり -gdwarf-2 -gstrict-dwarf とかを -g に追加すればいいんじゃね?ということのようなので再度ビルドしてGDBに読み込ませてみた.

$ ~/tool/gdb-7.1/bin/arm-none-eabi-gdb timerirq_hello
GNU gdb (GDB) 7.1
(snip...)
Reading symbols from /home/saito/work/timerirq/timerirq_hello...done.

読み込み時のエラーが消えた.
さらに,接続してプログラムリストも表示させてみた.

(gdb) target remote localhost:12345
Remote debugging using localhost:12345
begin () at timerirq.S:26
26                      B           reset        /* 0x00 Reset handler */
(gdb) l
21      .text
22              .align 4
23              .global begin
24              .type begin, function
25      begin:
26                      B           reset        /* 0x00 Reset handler */
27      undefvec:
28                      B           .            /* 0x04 Undefined Instruction */
29      swivec:
30                      B           softirq      /* 0x08 Software Interrupt */
(gdb) 

表示もできる.ついでもステップ実行も出来た.というわけで,なんとかデバッグできる環境は準備できた.