Linuxで実行環境と異なる環境でgdbを使うときのポイント
Linuxでプログラムのデバッグをしているときに、たまに困るのが、coreファイルが生成された実行環境と同じ環境が手元にない場合です。
例えば、実行環境が、
# cat /etc/redhat-release
CentOS release 5.8 (Final)
# uname -a
Linux komata-centos58-i386 2.6.18-308.el5 #1 SMP Tue Feb 21 20:05:41 EST 2012 i686 i686 i386 GNU/Linux
で、デバッガを実行する環境が、
# cat /etc/redhat-release
CentOS Linux release 7.0.1406 (Core)
# uname -a
Linux komata-CentOS70 3.10.0-123.el7.x86_64 #1 SMP Mon Jun 30 12:09:22 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
と、OSのバージョンも、32bit:64bitも違う場合で紹介してみましょう。
普通に実行ファイルとコアファイルを指定してgdbを起動すると、
# gdb test core.4035
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-51.el7
Copyright (C) 2013 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 "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/GdbTest/test...done.
[New LWP 4035]
warning: Could not load shared library symbols for 3 libraries, e.g. /lib/libc.so.6.
Use the "info sharedlibrary" command to see the complete listing.
Do you need "set solib-search-path" or "set sysroot"?
warning: Can't read pathname for load map: 入力/出力エラーです.
Core was generated by `./test'.
Program terminated with signal 6, Aborted.
#0 0x00c84402 in __kernel_vsyscall ()
こんな感じに警告がいろいろ出て起動します。
(gdb) where
#0 0x00c84402 in __kernel_vsyscall ()
#1 0x006b9df0 in ?? ()
#2 0x007e6ff4 in ?? ()
#3 0x006bb701 in ?? ()
#4 0x00000006 in ?? ()
#5 0xbfe6298c in ?? ()
#6 0x006f23ab in ?? ()
#7 0x00000004 in ?? ()
#8 0xbfe62b50 in ?? ()
#9 0x006fa6c5 in ?? ()
#10 0x00000002 in ?? ()
#11 0x007ba404 in ?? ()
#12 0xbfe64ca7 in ?? ()
#13 0x006fab09 in ?? ()
#14 0x08049668 in __libc_start_main@got.plt ()
#15 0x00000001 in ?? ()
#16 0x0069d6c4 in ?? ()
#17 0x007e6ff4 in ?? ()
#18 0x080483ff in func () at test.c:10
#19 0x0804841c in main () at test.c:17
スタックの状態を見ると(コマンドがdbx風で失礼)、ところどころ関数のシンボル名が表示されません。この例はまだマシな方で、ひどい組み合わせだと、全ての関数名が全く表示されないこともあります。
(gdb) info share
warning: Can't read pathname for load map: 入力/出力エラーです.
From To Syms Read Shared Object Library
No /lib/libc.so.6
No /lib/ld-linux.so.2
No /lib/libgcc_s.so.1
(gdb) quit
とりあえず、使っている共有ライブラリを調べて、実行した環境からコピーしてきます。
# ls -l lib
合計 1832
-rwxr-xr-x 1 root root 130864 2月 22 2012 ld-linux.so.2
-rwxr-xr-x 1 root root 1693820 2月 22 2012 libc.so.6
-rwxr-xr-x 1 root root 46676 2月 22 2012 libgcc_s.so.1
./libに必要な共有ライブラリを置きました。この状態でgdbを起動します。
# gdb
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-51.el7
Copyright (C) 2013 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 "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) set sysroot ./
sysrootをカレントディレクトリにセットします。こうすると必要な共有ライブラリはカレント以下を探してくれます。
(gdb) file test
Reading symbols from /root/GdbTest/test...done.
それから実行ファイルと、以下のようにコアファイルを指定すると・・・
(gdb) core-file core.4035
[New LWP 4035]
warning: Ignoring non-absolute filename: <./lib/libc.so.6>
Missing separate debuginfo for ./lib/libc.so.6
warning: Ignoring non-absolute filename: <./lib/ld-linux.so.2>
Missing separate debuginfo for ./lib/ld-linux.so.2
warning: Ignoring non-absolute filename: <./lib/libgcc_s.so.1>
Missing separate debuginfo for ./lib/libgcc_s.so.1
Core was generated by `./test'.
Program terminated with signal 6, Aborted.
#0 0x00c84402 in __kernel_vsyscall ()
絶対パスじゃないとか警告が出ていますが、
(gdb) where
#0 0x00c84402 in __kernel_vsyscall ()
#1 0x006b9df0 in raise () from ./lib/libc.so.6
#2 0x006bb701 in abort () from ./lib/libc.so.6
#3 0x006f23ab in __libc_message () from ./lib/libc.so.6
#4 0x006fa6c5 in _int_free () from ./lib/libc.so.6
#5 0x006fab09 in free () from ./lib/libc.so.6
#6 0x080483ff in func () at test.c:10
#7 0x0804841c in main () at test.c:17
今度はシンボル名がきちんと表示されます。
(gdb) info share
From To Syms Read Shared Object Library
0x006a6c80 0x007a2720 Yes (*) ./lib/libc.so.6
0x006727f0 0x006880af Yes (*) ./lib/ld-linux.so.2
0x00b72660 0x00b79f34 Yes (*) ./lib/libgcc_s.so.1
(*): Shared library is missing debugging information.
共有ライブラリの情報を見ると、./lib/libc.so.6など、カレントディレクトリ以下のものが使われています。
OSのバージョン違いだけでなく、クロス開発環境でのデバッグの際にも同じ感じでできるようです。
実環境はRedHatEnterpriseLinuxで、開発環境はCentOSという場合などにこの方法はとても役立ちます。