网站建设都有什么栏目,织梦网站密码,秦淮html5响应式网站,沈阳网站建设工作初衷 gdb调试是每一个后端开发工程师所必备的技能#xff0c;我们工作总是会用gdb协助我们去分析和调试问题。但是大部分同学的技能仅停留在最基础的查看问题。即gdb program --r -- 问题复现 -- bt 查看源码中的哪一行出现了错误。再稍微熟练点的#xff0c;可能…初衷 gdb调试是每一个后端开发工程师所必备的技能我们工作总是会用gdb协助我们去分析和调试问题。但是大部分同学的技能仅停留在最基础的查看问题。即gdb program --r -- 问题复现 -- bt 查看源码中的哪一行出现了错误。再稍微熟练点的可能就是p var查看一下变量的值进一步协助排查。 我想说的是这点能力是完全不够的身边一些同事稍微遇到一点问题就不知道如何进行调试了。比如
目标平台没有gdb 工具
程序及动态库符号被strip了bt 查看不到详细信息
问题不是必现一直等待会耗费人力 一旦遇到这些问题大部分肯定都会一脸懵逼不知道该怎么办了。但是我认为作为后端开发工程师gdb 调试是必备技能这个技能应该是一个能力集不仅仅是会几个gdb 调试指令即可而是在这个过程中遇到任何问题都应该能够独立分析解决。这也是我写本篇文章的初心。
目标平台没有gdb怎么办 嵌入式平台的资源有限很多厂家并不会将gdb 等工具集成到设备中。这就导致很多新手同学不知道该怎么办了。犹记得刚毕业我天马行空的居然尝试将虚拟机中的gdb copy 到目标设备中期待能够正常使用现在想想真心觉得傻得可爱。【申明一下哈有可能会成功哦前提是你的开发设备和目标设备都是相同的架构】。 遇到这种情况我们一般都需要重新编译gdb 工具。有兴趣的同学可以参考这篇文章应该算是较为详细。工作中如何编译开源工具(gdb)_gdb编译_谢艺华的博客-CSDN博客。
coredump 我们在开发调试过程中若一直使用gdb进行调试这对于测试和开发而言会不太方便影响效率。特别是在压力测试的场景中。如何解决这一难题呢我们可以使用linux自带的coredump机制。 Coredump叫做核心转储它是进程运行时在突然崩溃的那一刻的一个内存快照。操作系统在程序发生异常而异常在进程内部又没有被捕获的情况下会把进程此刻内存、寄存器状态、运行堆栈等信息转储保存在一个文件里。 但是这个机制默认可能是没有开启的因为一旦开启后会对系统赞成较大的压力。开启方式有两种
系统设置
一、开启 coredump
执行ulimit -c查看coredump 是否开启若结果为0则认为没有启动coredump文件生成。需要进行打开。
1. 临时启用ulimit -c 1024或ulimit -c unlimited。
前一种是限制core dump的文件大小不超过1024K后一种是不限制core dump文件的大小。建议根据实际情况进行设置大小因为coredump是将程序崩溃的那一刻的内存进行快照因此越占用内存的进程其生成的core文件也就会越大。因此动辄几个G的core文件也就不再稀奇。很有可能把磁盘占满了导致程序异常。
2. 永久有效打开/etc/profile文件, 增加如下以下并生使其生效ulimit -S -c unlimited /dev/null 21。
二、设置coredump文件名 设备里面可能同时运行多个应用不同的应用可能都会发生crash若core文件名不做特殊识别可能无法在多个core文件中找到我们需要的那一个。因此对core文件进行文件名设置就显得很有必要。
echo /corefiles/core-%e-%p-%t /proc/sys/kernel/core_pattern其中
/corefiles是core文件的保存路径。
core-%e-%p-%t是core 文件名以core-开头。
%p 所dump进程的进程ID
%u 所dump进程的实际用户ID
%g 所dump进程的实际组ID
%s 导致本次core dump的信号
%t core dump的时间 (由1970年1月1日计起的秒数)
%h 主机名
%e 程序文件名
一般默认就设置为core-%e-%p-%t。
三、设置coredump文件保存位置 我们知道嵌入式平台的磁盘空间一般也是有限的但是它会通过挂载不同的磁盘分区实现扩容。比如 如上图我的环境中默认core文件保存的路径是/usr/share/apport/apport/,若/usr所挂载的分区磁盘空间不足怎么办那么此时就可以通过修改core文件保存路径实现。 同理同样通过修改/proc/sys/kernel/core_pattern。
代码设置 有时候我们也可以通过程序开启coredump这样测试人员就不用在意系统环境的设置了。但是前提是程序必须以root权限运行。代码示例如下 #include stdio.h#includestdlib.h#include sys/prctl.h#include sys/resource.h#include string.h#includefcntl.h#include time.h#define CORE_FILE_SIZE 1024*1024*5 /** core文件大小可根据实际情况设置*/#define KERNEL_PATTERN_FILE /proc/sys/kernel/core_patternvoid coredump_file_set(char *name){ struct rlimit rlim; getrlimit(RLIMIT_CORE, rlim); rlim.rlim_cur rlim.rlim_max CORE_FILE_SIZE; int32_t ret setrlimit(RLIMIT_CORE, rlim); if(ret 0){ perror(setrlimit); return; } char path[256] {0}; sprintf(path, /ota_master_data/%sCore_%t, name); int32_t core_pattern_fd open(KERNEL_PATTERN_FILE, O_RDWR|O_NDELAY|O_TRUNC, 0666); if(core_pattern_fd 0){ perror(open); free(localtime); return; } ret write(core_pattern_fd, path, strlen(path)); if(ret 0){ perror(write); } free(localtime); close(core_pattern_fd);}int32_t main(int32_t argc, char* argv[]){ coredump_file_set(App); return 0;}
调试 程序异常之后我们就可以在设置的路径下生成对应的coredump文件通过对应编译链中的gdb工具可分析coredump文件。为什么要用工具链中的gdb工具呢这个可以思考一下可以在评论区回答哦~~~。
调试程序步骤
1. 启动gdb进入core文件。命令格式gdb [exec file] [core file]。如下 yihuaubuntu:~/coredump/core$ /opt/corbos-linux/2.30.0/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux-gdb otamaster otaMasterCore_1699106821.8 GNU gdb (GDB) 9.2 Copyright (C) 2020 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 --hostx86_64-pokysdk-linux --targetaarch64-poky-linux. 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 otamaster... .....warning: Could not load shared library symbols for 43 libraries, e.g. /usr/library/libvdi_main.so.Use the info sharedlibrary command to see the complete listing.Do you need set solib-search-path or set sysroot? --Type RET for more, q to quit, c to continue without paging-- Core was generated by otamaster -c ../etc/otamasterConfig.json. Program terminated with signal SIGSEGV, Segmentation fault. #0 0x0000007f9b14ef90 in ?? () [Current thread is 1 (LWP 25)] (gdb)
2. 设置库的加载路径。可执行程序运行时会加载很多动态库core文件中的一些代码段很有可能就是在这些库中若不加载这些依赖库就无法观察相应的符号及堆栈信息。
3. 将设备中程序依赖的库拷贝出来。ldd或objdump -x programe | grep NEEDED查看依赖库。
4. 在GDB中设置动态库寻找路径。set solib-search-path。如 (gdb) info sharedlibrary From To Syms Read Shared Object Library No /usr/library/libvdi_main.so No /usr/library/libabupFoundation.so No /adaptive/usr/lib/libdlt.so.2 No /usr/library/libjson-c.so.5 No /usr/lib/libcrypto.so.1.1 No /usr/library/libota.so No /hostLibrary/lib/libMI_VCCD_MISESDK.so No /usr/library/libdiagSecurityAccess.so No /usr/library/libOTAMasterService.so No /usr/library/libOTAMasterVehCloudApi.so No /usr/library/libotamaster_api_vehicle_info.so No /xmiLibrary/usr/lib/libotaapi_shared.so No /usr/library/libota_delta.so No /xmiLibrary/usr/lib/libHostSecurityLog.so No /adaptive/lib/libpthread.so.0 No /adaptive/usr/lib/libstdc.so.6 No /adaptive/lib/libgcc_s.so.1 No /adaptive/lib/libc.so.6 No /lib/ld-linux-aarch64.so.1 No /adaptive/lib/libdl.so.2 No /usr/library/libvdi_convert.so No /xmiLibrary/usr/lib/libdoipequip.so No /hostLibrary/lib/libcn_x509_proxy.so No /usr/lib/libssl.so.1.1 No /adaptive/lib/librt.so.1 No /adaptive/lib/libm.so.6 No /hostLibrary/lib/libhse_wrapper.so No /hostLibrary/lib/libcert.so No /hostLibrary/lib/libnddscpp2.so No /hostLibrary/lib/libnddsc.so No /hostLibrary/lib/libnddscore.so No /hostLibrary/lib/librticonnextmsgcpp2.so No /xmiLibrary/usr/lib/libdoipcommon.so No /adaptive/usr/lib/libz.so.1 No /hostLibrary/lib/libcn_x509_crypto.so No /hostLibrary/lib/libcn_x509_common.so No /usr/lib/libhse-libclient.so No /xmiLibrary/usr/lib/libPersistencyCommon.so --Type RET for more, q to quit, c to continue without paging--
刚开始exec file 依赖这些动态库但是都没有加载到。执行set solib-search-path后。 (gdb) set solib-search-path .Reading symbols from /home/yihua/coredump/core/libvdi_main.so...Reading symbols from /home/yihua/coredump/core/libabupFoundation.so...Reading symbols from /home/yihua/coredump/core/libjson-c.so.5...Reading symbols from /home/yihua/coredump/core/libota.so...Reading symbols from /home/yihua/coredump/core/libdiagSecurityAccess.so...Reading symbols from /home/yihua/coredump/core/libOTAMasterService.so...(No debugging symbols found in /home/yihua/coredump/core/libOTAMasterService.so)Reading symbols from /home/yihua/coredump/core/libOTAMasterVehCloudApi.so...Reading symbols from /home/yihua/coredump/core/libotamaster_api_vehicle_info.so...Reading symbols from /home/yihua/coredump/core/libota_delta.so...Reading symbols from /home/yihua/coredump/core/libvdi_convert.so... (gdb) info sharedlibrary From To Syms Read Shared Object Library0x0000007f9d32cbe0 0x0000007f9d34a87c Yes /home/yihua/coredump/core/libvdi_main.so0x0000007f9c5d2230 0x0000007f9c8154e0 Yes /home/yihua/coredump/core/libabupFoundation.so No /adaptive/usr/lib/libdlt.so.20x0000007f9c443b60 0x0000007f9c44c2e4 Yes /home/yihua/coredump/core/libjson-c.so.5 No /usr/lib/libcrypto.so.1.10x0000007f9c198600 0x0000007f9c199e04 Yes /home/yihua/coredump/core/libota.so No /hostLibrary/lib/libMI_VCCD_MISESDK.so0x0000007f9c163950 0x0000007f9c1649f0 Yes /home/yihua/coredump/core/libdiagSecurityAccess.so0x0000007f9be0db20 0x0000007f9bff69b0 Yes (*) /home/yihua/coredump/core/libOTAMasterService.so0x0000007f9b539fc0 0x0000007f9b56132c Yes /home/yihua/coredump/core/libOTAMasterVehCloudApi.so0x0000007f9b5136b0 0x0000007f9b51e568 Yes /home/yihua/coredump/core/libotamaster_api_vehicle_info.so No /xmiLibrary/usr/lib/libotaapi_shared.so0x0000007f9b477cd0 0x0000007f9b47fbf8 Yes /home/yihua/coredump/core/libota_delta.so No /xmiLibrary/usr/lib/libHostSecurityLog.so No /adaptive/lib/libpthread.so.0 No /adaptive/usr/lib/libstdc.so.6 No /adaptive/lib/libgcc_s.so.1 No /adaptive/lib/libc.so.6 No /lib/ld-linux-aarch64.so.1 No /adaptive/lib/libdl.so.20x0000007f9b05bd40 0x0000007f9b08c42c Yes /home/yihua/coredump/core/libvdi_convert.so
如上设置动态库寻找路径后就可以正常加载动态库了。
5. 在进入gdb后查找段错误位置where或者bt。 gdb 常用调试命令 通过上面流程我们已经能够正式进入gdb调试阶段了。在这里我分享一下我常用的一些命令。
backtrace 与 frame
backtrace 可简写成 bt用于查看当前所在线程的调用堆栈。如果我们想切换到其他堆栈处则可以使用frame命令。frame命令可被简写成ff 堆栈编号。 info 用于查看一些信息我经常的搭配是
info locals 查看当前栈中的局部变量。
info threads 查看当前线程信息。
info b 查看当前断点信息。
info registers 查看当前寄存器值比如常见栈顶寄存器PC寄存器。
print 打印或修改变量寄存器的值。
x 打印内存值 x /nfu address。
n是一个正整数表示显示内存的长度也就是说从当前地址向后显示几个地址units的内容。
f 表示显示的格式format x hexadecimal按十六进制格式显示变量。 d signed decimal按十进制格式显示变量。 u unsigned decimal按十进制格式显示无符号整型。 o octal按八进制格式显示变量。 t binary按二进制格式显示变量。 a address按十六进制格式显示地址并显示距离前继符号的偏移量(offset)。常用于定位未知地址(变量)。 c character按字符格式显示变量。 f floating按浮点数格式显示变量。
u 表示the unit size从当前地址往后请求的位宽大小。如果不指定的话GDB默认是4个bytes。u参数可以用下面的字符来代替b表示单字节h表示双字节w表示四字 节g表示八字节。
例如打印当前栈顶地址开始4字节为单位以16进制输出共输出16个。即输出栈顶64字节内容。 info proc mappings 。查看当前进程的maps即动态库和可执行程序加载到虚拟地址的maps。在某些场景下作用非常大。可参考
案例实践 关于gdb的实际案例分析可参考我的gdb调试专栏。后续也会持续更新案例。
linux gdb 调试_谢艺华的博客-CSDN博客
技巧
一、 如何修改正在运行的程序的标准输出
场景有些情况下我们需要查看一个程序的日志输出但苦于这个程序并不是我们开发的。默认情况下该程序的输出默认是到/dev/null中的。如何查看它的输出呢
获取正在运行的进程pid。ps -ef | grep MCM_atcop_svr运行gdb命令。gdb -p pid通过close系统调用关闭标准输出(STDOUT)或者标准错音误(STDERR): call close(1)通过create系统调用打开一个文件并将其文件描述符通过dup2系统调用复制给标准输出或者标准错误:call dup2(creat(/tmp/log,0600),1)退出调试器:quit
总结 上述便是本文的分享如果能给各位看客带来一点帮助还请三连支持一下。您的支持就是我的动力。