Linux 应用程序调试技术/内核分析
外观
为了获得良好的调用堆栈,重要的是 gdb 加载与生成核心转储的程序加载的相同库。如果我们分析内核的机器与内核转储的机器具有不同的库(或库位于不同的位置),则将库复制到分析机器上,以镜像转储机器。例如
$ tree .
.
|-- juggler-29964.core
|-- lib64
| |-- ld-linux-x86-64.so.2
| |-- libc.so.6
| |-- libm.so.6
| |-- libpthread.so.0
| `-- librt.so.1
...
在 gdb 提示符下
(gdb) set solib-absolute-prefix ./
(gdb) set solib-search-path .
(gdb) file ../../../../../threadpool/bin.v2/libs/threadpool/example/juggler/gcc-4.1.2/debug/link-static/threading-multi/juggler
Reading symbols from /home/aurelian_melinte/threadpool/threadpool-0_2_5-src/threadpool/bin.v2/libs/threadpool/example/juggler/gcc-4.1.2/debug/link-static/threading-multi/juggler...done.
(gdb) core-file juggler-29964.core
Reading symbols from ./lib64/librt.so.1...(no debugging symbols found)...done.
Loaded symbols for ./lib64/librt.so.1
Reading symbols from ./lib64/libm.so.6...(no debugging symbols found)...done.
Loaded symbols for ./lib64/libm.so.6
Reading symbols from ./lib64/libpthread.so.0...(no debugging symbols found)...done.
Loaded symbols for ./lib64/libpthread.so.0
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 `../../../../bin.v2/libs/threadpool/example/juggler/gcc-4.1.2/debug/link-static/'.
Program terminated with signal 6, Aborted.
#0 0x0000003684030265 in raise () from ./lib64/libc.so.6
(gdb) frame 2
#2 0x0000000000404ae1 in dump_core_and_terminate () at juggler.cpp:30
这是一个脚本,它将为每个核心文件生成一个基本报告。当核心向你倾盆而下时,这个脚本很有用
#!/bin/bash
#
# A script to extract core-file informations
#
if [ $# -ne 1 ]
then
echo "Usage: `basename $0` <for-binary-image>"
exit -1
else
binimg=$1
fi
# Today and yesterdays cores
cores=`find . -name '*.core' -mtime -1`
#cores=`find . -name '*.core'`
for core in $cores
do
gdblogfile="$core-gdb.log"
rm $gdblogfile
bininfo=`ls -l $binimg`
coreinfo=`ls -l $core`
gdb -batch \
-ex "set logging file $gdblogfile" \
-ex "set logging on" \
-ex "set pagination off" \
-ex "printf \"**\n** Process info for $binimg - $core \n** Generated `date`\n\"" \
-ex "printf \"**\n** $bininfo \n** $coreinfo\n**\n\"" \
-ex "file $binimg" \
-ex "core-file $core" \
-ex "bt" \
-ex "info proc" \
-ex "printf \"*\n* Libraries \n*\n\"" \
-ex "info sharedlib" \
-ex "printf \"*\n* Memory map \n*\n\"" \
-ex "info target" \
-ex "printf \"*\n* Registers \n*\n\"" \
-ex "info registers" \
-ex "printf \"*\n* Current instructions \n*\n\"" -ex "x/16i \$pc" \
-ex "printf \"*\n* Threads (full) \n*\n\"" \
-ex "info threads" \
-ex "bt" \
-ex "thread apply all bt full" \
-ex "printf \"*\n* Threads (basic) \n*\n\"" \
-ex "info threads" \
-ex "thread apply all bt" \
-ex "printf \"*\n* Done \n*\n\"" \
-ex "quit"
done
相同的报告功能可以被预定义到 gdb 中
define procinfo
printf "**\n** Process Info: \n**\n"
info proc
printf "*\n* Libraries \n*\n"
info sharedlib
printf "*\n* Memory Map \n*\n"
info target
printf "*\n* Registers \n*\n"
info registers
printf "*\n* Current Instructions \n*\n"
x/16i $pc
printf "*\n* Threads (basic) \n*\n"
info threads
thread apply all bt
end
document procinfo
Infos about the debugee.
end
define analyze
procinfo
printf "*\n* Threads (full) \n*\n"
info threads
bt
thread apply all bt full
end
一个脚本,它将为运行的进程生成一个基本报告和一个核心文件
#!/bin/bash
#
# A script to generate a core and a status report for a running process.
#
if [ $# -ne 1 ]
then
echo "Usage: `basename $0` <PID>"
exit -1
else
pid=$1
fi
gdblogfile="analyze-$pid.log"
rm $gdblogfile
corefile="core-$pid.core"
gdb -batch \
-ex "set logging file $gdblogfile" \
-ex "set logging on" \
-ex "set pagination off" \
-ex "printf \"**\n** Process info for PID=$pid \n** Generated `date`\n\"" \
-ex "printf \"**\n** Core: $corefile \n**\n\"" \
-ex "attach $pid" \
-ex "bt" \
-ex "info proc" \
-ex "printf \"*\n* Libraries \n*\n\"" \
-ex "info sharedlib" \
-ex "printf \"*\n* Memory map \n*\n\"" \
-ex "info target" \
-ex "printf \"*\n* Registers \n*\n\"" \
-ex "info registers" \
-ex "printf \"*\n* Current instructions \n*\n\"" -ex "x/16i \$pc" \
-ex "printf \"*\n* Threads (full) \n*\n\"" \
-ex "info threads" \
-ex "bt" \
-ex "thread apply all bt full" \
-ex "printf \"*\n* Threads (basic) \n*\n\"" \
-ex "info threads" \
-ex "thread apply all bt" \
-ex "printf \"*\n* Done \n*\n\"" \
-ex "generate-core-file $corefile" \
-ex "detach" \
-ex "quit"
使用 gdb 在核心文件中访问 TLS 数据相当困难。