前言
gdb的背景前面已经介绍:
根据上一章的介绍,此章节主要是对于调试方式如何使用的的深入介绍。
一、调试信息
gcc 编译生成的执行程序,需要包含调试信息(符号表中的信息)
一般要调试某个程序,为了能清晰地看到调试的每一行代码、调用的堆栈信息、变
量名和函数名等信息,需要调试程序含有调试符号信息。使用 gcc 编译程序时,如果加
上· -g ·选项即可在编译后的程序中保留 调试符号信息。
1. 例子
如何生成带符号信息的执行程序:
例如: hello.c gcc -g -o hello hello.c
2.如何判断是否带有调试信息
我们可以使用 gdb 来调试一下这个程序, gdb 会显示正确读取到该程序的调试信息,在打开的 Linux Shell 终端输入 gdb hello_server 查看显示结果即可:
[root@localhost chen]# gdb hello GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.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 /home/chen/hello...done. (gdb)
GDB加载成功之后,会出现如下的信息,
Reading symbols from /home/chen/hello...done.
** 未使用-g 编译生成的执行程序**
编译: gcc -o hello2 hello.c
Reading symbols from /home/chen/hello2…(
no debugging symbols found
)…done.(gdb)
3.如何编译的时候链接符号信息
方法一: 程序编译的时候不加上
-g
方法二:使用命令剔除符号信息(
strip
)
[root@localhost chen]# strip hello -rwxr-xr-x. 1 root root 6256 5月 13 17:10 hello # 原始数据 [root@localhost chen]# gcc -g -o hello teststr.c -rwxr-xr-x. 1 root root 9632 5月 13 17:11 hello [root@localhost chen]# nm hello 0000000000601044 B __bss_start 0000000000601044 b completed.6355 0000000000601040 D __data_start 0000000000601040 W data_start 0000000000400510 t deregister_tm_clones 0000000000400580 t __do_global_dtors_aux 0000000000600e18 t __do_global_dtors_aux_fini_array_entry 00000000004006c8 R __dso_handle 0000000000600e28 d _DYNAMIC 0000000000601044 D _edata 0000000000601048 B _end 00000000004006b4 T _fini 00000000004005a0 t frame_dummy 0000000000600e10 t __frame_dummy_init_array_entry 0000000000400870 r __FRAME_END__ 0000000000601000 d _GLOBAL_OFFSET_TABLE_ w __gmon_start__ 000000000040074c r __GNU_EH_FRAME_HDR 0000000000400458 T _init 0000000000600e18 t __init_array_end 0000000000600e10 t __init_array_start 00000000004006c0 R _IO_stdin_used 0000000000600e20 d __JCR_END__ 0000000000600e20 d __JCR_LIST__ 00000000004006b0 T __libc_csu_fini 0000000000400640 T __libc_csu_init U __libc_start_main@@GLIBC_2.2.5 00000000004005cd T main U printf@@GLIBC_2.2.5 U puts@@GLIBC_2.2.5 0000000000400540 t register_tm_clones 00000000004004e0 T _start U strcasestr@@GLIBC_2.2.5 0000000000601048 D __TMC_END__ [root@localhost chen]# strip hello [root@localhost chen]# nm hello nm: hello:无符号
二、GDB启动调试
1.直接调试目标程序
调试方法:
gdb file_name (gdb hello)
此方法是最简单的调试方法,只要确定程序中存在符号信息,就可以使用gdb 直接调试
2.附加进程调试
调试方法:
gdb attach pid 附加进程调试,需要加上权限sudo
相关命令: 分离关联 detaach
某些情况下程序已经在运行,我们想调试这个程序,但是又不想重启这个程序,我们可以使用采用附加进程的调试方式。这种方式当调试完程序想结束此次时, 而且不对当前进程 有任何影响。
例如 调试redis
第一步骤:获取程序id
[root@localhost ~]# ps -ef|grep redis root 17259 1 0 16:29 ? 00:00:25 /usr/local/redis/bin/redis-server *:6379 root 26105 25828 0 23:10 pts/3 00:00:00 grep --color=auto redis
获取redis 的进程PID为17259,然后使用gdb attach17259(注意权限问题,加上sudo
),既是 sudo gdb attach 17259.
[root@localhost ~]# sudo gdb attach 17259 GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.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/>... attach: 没有那个文件或目录. Attaching to process 17259 Reading symbols from /usr/local/redis/bin/redis-server...done. Reading symbols from /lib64/libm.so.6...(no debugging symbols found)...done. Loaded symbols for /lib64/libm.so.6 Reading symbols from /lib64/libdl.so.2...(no debugging symbols found)...done. Loaded symbols for /lib64/libdl.so.2 Reading symbols from /lib64/librt.so.1...(no debugging symbols found)...done. Loaded symbols for /lib64/librt.so.1 Reading symbols from /lib64/libpthread.so.0...(no debugging symbols found)...done. [New LWP 4411] [New LWP 17271] [New LWP 17270] [New LWP 17269] [New LWP 17268] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". 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 0x00007ffff71e20e3 in epoll_wait () from /lib64/libc.so.6 Missing separate debuginfos, use: debuginfo-install glibc-2.17-325.el7_9.x86_64 (gdb)
当用 gdb attach 上目标进程后,调试器会暂停下来,此时可以使用 continue ©命令让程序继续执行,或者添加断点然后在继续执行。当调试完程序想结束此次时, 而且不对当前进程 redis有任何影响.
程序分离gdb 调试,可以在gdb的命令界面中输入detach命令程序和gdb调试器分离,这样redis就可以继续运行了。
// 程序和gdb调试器分离 (gdb) detach Detaching from program: /usr/local/redis/bin/redis-server, process 17259 [Inferior 1 (process 17259) detached] (gdb)
3.调试core文件
调试方法:
gdb filename corename 调试core 文件
此方法涉及的信息比较多下一章节详细介绍
总结
此章节详细介绍了gdb 调试的三种方法的两种,以及带着简单的例子便于理解。具体的第三种方法比较复杂,重新开一章进行详细介绍。文章给中设计的符号表信息也在未来的章节中进行简单的介绍。