Fork me on GitHub

GDB调试Python代码

Core Dump文件

凡事皆有两面性,OS在出Core的同时,虽然会终止掉当前进程,但是也会保留下第一手的现场数据,OS仿佛是一架被按下快门的相机,而照片就是产出的Core文件。里面含有当进程被终止时内存、CPU寄存器等信息,可以供后续开发人员进行调试。

Gdb可以附着在特定进程上调试,但是为了不影响运行中的进程,可以通过生成 core file 的方式来保存进程的当前信息。

实验环境配置

环境是Ubuntu20.04

# 新开一个Shell的时候,ulimit选项都恢复了默认选项,需要重新设置该值
# 查看shell进程资源
ulimit -a
# 查看core文件大小限制
ulimit -c
# 修改core文件大小限制
ulimit -c unlimited
# 查看修改是否生效
ulimit -c
# 设置core_pattern
# core_pattern文件中定义了当产生core dump后对core文件进行什么操作
cat /proc/sys/kernel/core_pattern
# 需要修改core_pattern文件使得core文件保存在磁盘上
# 方法1
        # 暂停apport服务
        sudo service apport stop
        cat /proc/sys/kernel/core_pattern

        # 生成core文件后恢复apport服务
        sudo service apport start

# 方法2
        mkdir /var/cores
        echo "/var/cores/core.%e.%p" > /proc/sys/kernel/core_pattern
# 方法3
        vim /etc/sysctl.conf
        # 在最后一行添加kernel.core_uses_pid = 1
        sysctl -p
# 阅读core文件头     
readelf -h core 

安装Python-dbg

sudo apt install gdb python3-dbg

GDB调试Python代码

实验1:直接调试core dump文件

将如下代码保存为explode.py

 import os

 def my_exploding_func():
     my_local_var = 'hi'
     number = 4 
     number2 = 5 
     number4 = number+3
     os.abort()

 my_exploding_func()

执行代码,产生core dump文件

python explode.py

同样的Python版本执行gdb调试

# 读取core文件
gdb `which python` core

可以使用一些常见的命令调试

#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50  ../sysdeps/unix/sysv/linux/raise.c: 没有那个文件或目录.
(gdb) py-list
   3    def my_exploding_func():
   4        my_local_var = 'hi'
   5        number = 4
   6        number2 = 5
   7        number4 = number+3
  >8        os.abort()
   9    
  10    my_exploding_func()
(gdb) py-bt
Traceback (most recent call first):
  <built-in method abort of module object at remote 0x7f08dfc7d360>
  File "explode.py", line 8, in my_exploding_func
    os.abort()
  File "explode.py", line 10, in <module>
    my_exploding_func()

实验2:主动生成core dump文件

如下代码保存为test.py

import time

def do(x):
    time.sleep(10)

def main():
    for x in range(10000):
        do(x)

if __name__ == '__main__':
    main()

运行该代码后找到PID

ps -ef | grep "python test.py"

主动生成core dump文件,不影响进程继续运行

gdb python PID
generate-core-file

所有gdb命令都支持使用,同时还有安装python-dbg支持的命令

在gdb调试命令行中输入

# py + TAB键位弹出常用命令
py-bt               py-list             py-up
py-bt-full          py-locals           python
py-down             py-print            python-interactive
# help + 命令显示帮助信息
help py-bt

参考

gdb Debugging Full Example

Linux上Core Dump文件的形成和分析

Linux上coredump实验

GDB调试Python命令

Debuggin with gdb

Comments