GDB
GDB是Linux下的调试工具,可以调试C、C++、Go、java等语言
GDB提供了以下四个功能:
- 程序启动时,可以按照自定义的要求运行程序,如设置参数和环境变量
- 可以让被调试的程序在所指定的代码处暂停运行,并查看当前运行状态(如当前变量的值,函数的执行结果),即支持断点调试
- 当程序被停止时,可以查看当前程序中的变量的状态
- 在程序执行过程中,可以改变某个变量的值,还可改变代码的执行顺序
要使用gdb调试,必须在源代码生成二进制程序的时候,加上 -g
选项,release 模式,如果没有 -g
,将看不见程序的函数名、变量名,所替代的全是运行时的内存地址
可以通过 readelf -S 可执行文件 | grep debug
和 file 可执行文件
查看某个二进制文件有没有调试信息,如下红色框是调试信息
启动 GDB 的方法
-
gdb program
:调式方式启动运行无参程序 -
gdb program core
:用 GDB 同时调试一个运行程序和 core 文件,core 是程序非法执行后 core dump 后产生的文件# 查看 limit (base) china@china:~$ ulimit -c 0 (base) china@china:~$ ulimit -a real-time non-blocking time (microseconds, -R) unlimited core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 127327 max locked memory (kbytes, -l) 4084144 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 127327 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited # 修改为不限制 core 文件大小 (base) china@china:~$ ulimit -c unlimited (base) china@china:~$ ulimit -c unlimited
-
gdb program process_id
:指定程序运行时的进程 ID,GDB 会自动 attach 上去,并调试,program 应该在 PATH 环境变量中搜索得到# 修改 /etc/sysctl.d/10-ptrace.conf kernel.yama.ptrace_scope = 0 # 调试 (base) china@china:~/thread-pool$ ps -ef | grep program_name china 53735 48756 0 20:32 pts/0 00:00:00 ./program_name (base) china@china:~/thread-pool$ sudo gdb program_name -p 53735
GDB 启动时常用参数
# 从指定文件中读取符号表
--symbols=SYMFILE
# 从指定文件中读取符号信息,并把它用在可执行文件中
--se=FILE
# 调试时 core dump 的 core 文件
--core=COREFILE
# 加入一个源文件的搜索路径,默认搜索路径是环境变量中 PATH 所定义的路径
--directory=DIR
调式core文件,段错误
# 查看
ulimit -a
ulimit -c
# 设置
ulimit -c unlimited
# 设置core生成目录为/data/coredump,默认当前目录下,%e表示程序名,%p表示进程id
echo /data/coredump/core.%e.%p> /proc/sys/kernel/core_pattern
当程序core dump时,可能会产生core文件,它能够很大程序帮助我们定位问题。但前提是系统没有限制core文件的产生。
ulimit -a
ulimit -c
ulimit -c unlimited # 此时会产生core文件
gdb 程序文件名 core文件名
调试core文件,需要设置ulimit -c unlimited,并设置core文件生成目录
当程序运行错误结束的时候,会自动生成一个core文件,gdb ./main core
GDB 命令
-
help
# help 命令仅显示 GDB 命令种类 (gdb) help # 查看 breakpoints 的所有命令 (gdb) help breakpoints
-
breakpoint:设置断点
# (gdb) braek function_name # (gdb) break line_num # 在当前行号的前 offset (gdb) break +offset # 在当前行号的后 offset (gdb) break -offset (gdb) break file_name:line_num (gdb) break file_name:function_name # 在程序运行的内存地址处 (gdb) break *address # 如果 cond 成立 (gdb) break …… if cond # 在下一条指令处停住 (gdb) break # 查看断点,[n]表示断点号 (gdb) info breakpoints [n]
-
watchpoint:设置观察点
# 一旦 expr 值变化,程序停止 (gdb) watch expr # 一旦 expr 被读时,程序停止 (gdb) rwatch expr # 当 expr 被读或写,程序停止 (gdb) awatch expr # 查看 (gdb) info watchpoints
-
catchpoint:设置捕捉点,捕捉程序运行时的一些时间
# 抛出的异常 (gdb) catch throw # 捕获的异常 (gdb) catch catch # 调用系统调用 exec 时 (gdb) catch exec # 调用系统调用 fork 时 (gdb) catch fork # 调用系统调用 vfork 时 (gdb) catch vfork # load 或 load 载入共享库时 (gdb) catch load # 卸载共享库时 (gdb) catch unload # 只设置一次捕捉点,当程序停止后,自动删除 (gdb) tcatch
-
维护停止点:delete、clear、disable、enable
# 清除所有已定义的停止点 (gdb) clear # (gdb) clear function_name # (gdb) clear line_num # 删除所有的断点 (gdb) delete # 删除指定的断点,breakpoints 是断点号,range 是断点号的范围 3-7 (gdb) delete [breakpoints] [range...] # 关闭所有的断点 (gdb) disable # 关闭指定的断点,breakpoints 是断点号,range 是断点号的范围 3-7 (gdb) disable [breakpoints] [range...] # 开启所有的断点 (gdb) enable # 开启指定的断点,breakpoints 是断点号,range 是断点号的范围 3-7 (gdb) enable [breakpoints] [range...]
-
run
# (gdb) set args ... # 运行程序,直到程序结束或下一个断点 (gdb) run args # 恢复程序运行,直到结束或者下一个断点 (gdb) continue # 单步,会进入函数 (gdb) setp # 单步,不会进入函数 (gdb) next # 运行程序,直到当前函数完成返回,打印函数返回时的堆栈地址和返回值及参数值等信息 (gdb) finish # 运行程序直到退出循环体 (gdb) until
-
quit
(gdb) quit
-
shell
# shell command (gdb) shell pwd # 查看运行环境 (gdb) path (gdb) show path # (gdb) cd # 查看当前目录 (gdb) pwd
-
log
set logging on 打开日志功能 默认在当前目录生成gdb.txt
工具
-
readelf:
root@china:~/csapp# readelf -S ./main | grep debug [28] .debug_aranges PROGBITS 0000000000000000 00003036 [29] .debug_info PROGBITS 0000000000000000 00003066 [30] .debug_abbrev PROGBITS 0000000000000000 000031af [31] .debug_line PROGBITS 0000000000000000 00003295 [32] .debug_str PROGBITS 0000000000000000 00003321 [33] .debug_line_str PROGBITS 0000000000000000 0000341a
-
file:
root@china:~/csapp# file ./main ./main: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=fa5fb837d07c13549e0880c95a0e6ea0c5e54f57, for GNU/Linux 3.2.0, with debug_info, not stripped