调试器GDB的基本使用方法 Linux环境下段错误的产生原因及调试方法小结 linux应用调试技术之GDB和GDBServer gdbServer + gdb 调试

GDB调试的三种方式:

1. 目标板直接使用GDB进行调试。

2. 目标板使用gdbserver,主机使用xxx-linux-gdb作为客户端。

3. 目标板使用ulimit -c unlimited,生成core文件;然后主机使用xxx-linux-gdb ./test ./core。

1. gdb调试

2. gdb+gdbserver远程调试

3. core dump离线分析

在目标板上执行ulimit -c unlimited,执行应用程序。

程序出错后,会在当前目录下生成core文件。

将core文件拷出后,再PC上执行xxx-linux-gdb ./test ./core进行分析。

3.1 加载库文件

在运行xxx-linux-gdb ./test ./core之后,可能存在库文件关联不上的情况。

使用info sharedlibrary,查看库加载情况。

From        To          Syms Read   Shared Object Library
                        No          xxx.so
                        No          /lib/libdl.so.2
                        No          /lib/libpthread.so.0
0x2ab6ec00  0x2ac09ba4  Yes         xxx/lib/libstdc++.so.6
                        No          /lib/libm.so.6
0x2acec460  0x2acf626c  Yes         xxx/lib/libgcc_s.so.1
                        No          /lib/libc.so.6
                        No          /lib/ld.so.1

可以通过set solib-search-pathset solib-absolute-prefix来设置,对应库所在的路径。

From        To          Syms Read   Shared Object Library
0x2aaca050  0x2aacc8d0  Yes         xxx.so
0x2aad0ad0  0x2aad17ac  Yes (*)     xxx/lib/libdl.so.2
0x2aad8a50  0x2aae7434  Yes (*)     xxx/lib/libpthread.so.0
0x2ab6ec00  0x2ac09ba4  Yes         xxx/lib/libstdc++.so.6
0x2ac4b3d0  0x2acb1988  Yes         xxx/lib/libm.so.6
0x2acec460  0x2acf626c  Yes         xxx/lib/libgcc_s.so.1
0x2ad17b80  0x2adf699e  Yes         xxx/lib/libc.so.6
0x2aaa89e0  0x2aabf66c  Yes (*)     xxx/lib/ld.so.1
(*): Shared library is missing debugging information.

可以看出相关库文件都已经加载,只是部分库文件没有调试信息。

3.2 查看backtrace

查看coredump的backtrace通过bt即可,更全的信息通过bt full。

产看函数调用栈的几个函数

bt:显示所有的函数调用栈帧的信息,每个帧一行。

bt n:显示栈定的n个帧信息。

bt -n:显示栈底的n个帧信息。

bt full:显示栈中所有帧的完全信息如:函数参数,本地变量。

bt full n:用法同上。

bt full -n

(gdb) bt
#0  0x2ad71f1e in memcpy () from xxx/lib/libc.so.6
#1  0x2ad71ac0 in memmove () from xxx/lib/libc.so.6
#2  0x0011f36c in std::__copy_move<false, true, std::random_access_iterator_tag>::__copy_m<unsigned char> (__first=0x34dfb008 "\377\330\377", <incomplete sequence \340>, __last=0x34eeea2c "", 
    ...
#3  0x0011ee22 in std::__copy_move_a<false, unsigned char*, unsigned char*> (__first=0x34dfb008 "\377\330\377", <incomplete sequence \340>, __last=0x34eeea2c "", __result=0x2b2013c0 "\377\330\377", <incomplete sequence \340>)
    at xxxinclude/c++/6.3.0/bits/stl_algobase.h:386
#4  0x0011e7e2 in std::__copy_move_a2<false, __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char> >, unsigned char*> (__first=..., __last=..., __result=0x2b2013c0 "\377\330\377", <incomplete sequence \340>)
    at xxx/bits/stl_algobase.h:424
#5  0x0011dfd2 in std::copy<__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char> >, unsigned char*> (__first=..., __last=..., __result=0x2b2013c0 "\377\330\377", <incomplete sequence \340>)
    at xxx/6.3.0/bits/stl_algobase.h:456
#6  0x0011c948 in xxx
#7  0x00133e08 in xxx
#8  0x2aada31e in start_thread () from xxx/libc/lib/libpthread.so.0
#9  0x005a11b4 in ?? ()

3.3 Core Dump核心转存储文件目录和命名规则

默认情况下core文件存在应用当前路径下,为了区分可以进行设置。

区分core主要通过/proc/sys/kernel/core_uses_pid和/proc/sys/kernel/core_pattern进行设置。

/proc/sys/kernel/core_uses_pid:可以控制产生的core文件的文件名中是否添加pid作为扩展,如果添加则文件内容为1,否则为0。

proc/sys/kernel/core_pattern:可以设置格式化的core文件保存位置或文件名,比如原来文件内容是core-%e

echo "/tmp/core-%e-%p" > core_pattern。

将会控制所产生的core文件会存放到/corefile目录下,产生的文件名为core-命令名-pid-时间戳

以下是参数列表:
    %p - insert pid into filename 添加pid
    %u - insert current uid into filename 添加当前uid
    %g - insert current gid into filename 添加当前gid
    %s - insert signal that caused the coredump into the filename 添加导致产生core的信号
    %t - insert UNIX time that the coredump occurred into filename 添加core文件生成时的unix时间
    %h - insert hostname where the coredump happened into filename 添加主机名
    %e - insert coredumping executable name into filename 添加命令名

当然,你可以用下列方式来完成:

sysctl -w kernel.core_pattern=/tmp/core-%e-%p

3.4 ulimit的使用

功能说明:控制shell程序的资源。

语  法:ulimit [-aHS][-c <core文件上限>][-d <数据节区大小>][-f <文件大小>][-m <内存大小>][-n <文件数目>][-p <缓冲区大小>][-s <堆叠大小>][-t <CPU时间>][-u <程序数目>][-v <虚拟内存大小>]

补充说明:ulimit为shell内建指令,可用来控制shell执行程序的资源。

参  数:
   -a  显示目前资源限制的设定。 
   -c <core文件上限>  设定core文件的最大值,单位为区块。 
   -d <数据节区大小>  程序数据节区的最大值,单位为KB。 
   -f <文件大小>  shell所能建立的最大文件,单位为区块。 
   -H  设定资源的硬性限制,也就是管理员所设下的限制。 
   -m <内存大小>  指定可使用内存的上限,单位为KB。 
   -n <文件数目>  指定同一时间最多可开启的文件数。 
   -p <缓冲区大小>  指定管道缓冲区的大小,单位512字节。 
   -s <堆叠大小>  指定堆叠的上限,单位为KB。 
   -S  设定资源的弹性限制。 
   -t <CPU时间>  指定CPU使用时间的上限,单位为秒。 
   -u <程序数目>  用户最多可开启的程序数目。 
   -v <虚拟内存大小>  指定可使用的虚拟内存上限,单位为KB。

参考文档:

Linux环境下段错误的产生原因及调试方法小结》《linux应用调试技术之GDB和GDBServer》《gdbServer + gdb 调试

猜你喜欢

转载自www.cnblogs.com/arnoldlu/p/9633254.html