th0x4c 備忘録

[GDB] 別環境で採取した Core ファイルを解析する方法

目的

別環境で採取した core ファイルを解析する。

環境

  • OS: Oracle Enterprise Linux 5.8
  • GDB: GNU gdb 7.0.1-42.el5

解析に必要なファイル

別環境で発生した core ファイルを解析するためには以下のファイルが必要。

  • core ファイル
  • 実行ファイル
  • 共有ライブラリ

例えば、以下のように abort() でわざと core を吐かせて試してみる。

$ cat hello.c
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  printf("hello, world\n");
  abort();
  return 0;
}

$ gcc -o hello hello.c
$ ./hello
hello, world
Aborted (core dumped)
$ ls -ltr | tail -1
-rw------- 1 oracle oinstall 184320 Oct 10 20:59 core.7441

core.7441 という core ファイルが吐かれた。

実行ファイルは core ファイルに対して file コマンドを実行すれば確認できる。

$ file core.7441
core.7441: ELF 64-bit LSB core file AMD x86-64, version 1 (SYSV), SVR4-style, from 'hello'

hello という実行ファイルによってこの core が吐かれたことが分かる。

共有ライブラリは GDB で core を読み込んで info share で確認できる。

$ gdb ./hello ./core.7441 
GNU gdb (GDB) Red Hat Enterprise Linux (7.0.1-42.el5)
Copyright (C) 2009 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 /tmp/hello...(no debugging symbols found)...done.
[New Thread 7441]
Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Core was generated by `./hello'.
Program terminated with signal 6, Aborted.
#0  0x00000037be430265 in raise () from /lib64/libc.so.6
(gdb) info share
From                To                  Syms Read   Shared Object Library
0x00000037be41d780  0x00000037be50ad68  Yes (*)     /lib64/libc.so.6
0x00000037be000a70  0x00000037be01682e  Yes (*)     /lib64/ld-linux-x86-64.so.2
(*): Shared library is missing debugging information.

共有ライブラリとしては以下が読み込まれていることが分かる。

  • /lib64/libc.so.6
  • /lib64/ld-linux-x86-64.so.2

なお、実行中に動的リンクを行うようなプログラムでなければ、共有ライブラリは ldd コマンドでも確認できる。

$ ldd ./hello
        linux-vdso.so.1 =>  (0x00007fffcd1ff000)
        libc.so.6 => /lib64/libc.so.6 (0x00000037be400000)
        /lib64/ld-linux-x86-64.so.2 (0x00000037be000000)

以上より、この例では他の環境でこの core ファイルを解析するためには次のファイルを採取する必要がある。

  • core ファイル => core.7441
  • 実行ファイル => hello
  • 共有ライブラリ => /lib64/libc.so.6, /lib64/ld-linux-x86-64.so.2

別環境での core の解析

別環境に先ほど採取したファイルを展開する。 今回は以下のように配置した。

/tmp/core.7441
/tmp/bin/hello
/tmp/lib/libc.so.6
/tmp/lib/ld-linux-x86-64.so.2

GDB でこの core を解析するためには、採取した共有ライブラリを読み込むために以下のように solib-absolute-prefix, solib-search-path を設定する。

$ cd /tmp
$ gdb
(gdb) set solib-absolute-prefix /tmp/lib
(gdb) set solib-search-path /tmp/lib
(gdb) file ./bin/hello
(gdb) core-file ./core.7441 

実際の実行例は以下。

$ gdb
GNU gdb (GDB) Red Hat Enterprise Linux (7.0.1-42.el5)
Copyright (C) 2009 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 solib-absolute-prefix /tmp/lib
(gdb) set solib-search-path /tmp/lib
(gdb) file ./bin/hello
Reading symbols from /tmp/bin/hello...(no debugging symbols found)...done.
(gdb) core-file ./core.7441 
[New Thread 7441]
Reading symbols from /tmp/lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /tmp/lib/libc.so.6
Reading symbols from /tmp/lib/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /tmp/lib/ld-linux-x86-64.so.2
Core was generated by `./hello'.
Program terminated with signal 6, Aborted.
#0  0x00000037be430265 in raise () from /tmp/lib/libc.so.6
(gdb) bt
#0  0x00000037be430265 in raise () from /tmp/lib/libc.so.6
#1  0x00000037be431d10 in abort () from /tmp/lib/libc.so.6
#2  0x00000000004004f6 in main ()

ソースファイル

デバックオプション(-g オプション)付きでコンパイルされている場合は、ソースファイルがあればソースコードを使用した調査ができる。 コンパイルした環境と別の環境で core 解析する場合、ソースコードを入手して、GDB の directory にてソースファイルを展開したディレクトリを指定する。

実行例は以下。(実行ファイルはデバックオプション付きでコンパイルしたものを使用)

(gdb) bt
#0  0x00000030ea830265 in raise () from /tmp/lib/libc.so.6
#1  0x00000030ea831d10 in abort () from /tmp/lib/libc.so.6
#2  0x00000000004004f6 in main (argc=1, argv=0x7fff9d995df8) at hello.c:7
(gdb) frame 2
#2  0x00000000004004f6 in main (argc=1, argv=0x7fff9d995df8) at hello.c:7
7   hello.c: No such file or directory.
    in hello.c
(gdb) list
2     in hello.c

ソースファイルが見つからないと上記のようにソースコードが必要な調査ができない。 directory にてソースファイルを展開したディレクトリを指定すると、ソースコードを元にした調査ができる。 (ディレクトリが複数ある場合は:で区切って複数指定するか、directory をディレクトリの分だけ実行すれば追加される)

(gdb) directory /tmp/src
Source directories searched: /tmp/src:$cdir:$cwd
(gdb) frame 2
#2  0x00000000004004f6 in main (argc=1, argv=0x7fff9d995df8) at hello.c:7
7         abort();
(gdb) list
2       #include <stdlib.h>
3       
4       int main(int argc, char *argv[])
5       {
6         printf("hello, world\n");
7         abort();
8         return 0;
9       }