python-源码阅读(7)-Cpython调试

一. 工作准备

1
2
3
4
5
6
7
8
9
10
# locally clone the repo.
git clone https://github.com/python/cpython
# Navigate to the repo directory
cd cpython
# Switch to the version of python you want to work on
git checkout 3.6
# configure a debug build for CPython
./configure --with-pydebug
# build without echoing commands and use 2 cores
make -s -j2

注意:
最好是linux系统

二. 了解python字节码

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> import dis
>>> def foo():
... a = 1
... a.x
...
>>> dis.dis(foo)
2 0 LOAD_CONST 1 (1)
3 STORE_FAST 0 (a)
3 6 LOAD_FAST 0 (a)
9 LOAD_ATTR 0 (x)
12 POP_TOP
13 LOAD_CONST 0 (None)
16 RETURN_VALUE

使用dis模块查看python字节码,其中LOAD_CONST指令对于如下

1
2
3
4
5
6
7
8
9
10
11
// Python/ceval.c
2862 TARGET(LOAD_ATTR) {
2863 PyObject *name = GETITEM(names, oparg);
2864 PyObject *owner = TOP();
2865 PyObject *res = PyObject_GetAttr(owner, name);
2866 Py_DECREF(owner);
2867 SET_TOP(res);
2868 if (res == NULL)
2869 goto error;
2870 DISPATCH();
}

gdb 调试

  1. 启动dgb,编写代码例子
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    sabbas@sabbas-VirtualBox:~/Documents/pythondev/cpython
    $ gdb python
    GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
    Copyright (C) 2016 Free Software Foundation, Inc.
    (gdb) run
    Starting program: /home/sabbas/Documents/pythondev/cpython/python
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
    Python 3.6.2+ (heads/3.6:cb7fdf6, Aug 23 2017, 22:24:16)
    [GCC 5.4.0 20160609] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>>
    >>>
    >>>
    >>> def foo():
    ... x = 1
    ... x.a
    ...
    >>>
  2. 另外启动一个终端 暂停python执行器,提供打入断点机会
    1
    2
    sabbas@sabbas-VirtualBox:~/Documents/pythondev/cpython
    $ pkill python -SIGTRAP
  3. 回到dgb调试打断点
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    sabbas@sabbas-VirtualBox:~/Documents/pythondev/cpython
    $ gdb python
    GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
    Copyright (C) 2016 Free Software Foundation, Inc.
    (gdb) run
    Starting program: /home/sabbas/Documents/pythondev/cpython/python
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
    Python 3.6.2+ (heads/3.6:cb7fdf6, Aug 23 2017, 22:24:16)
    [GCC 5.4.0 20160609] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>>
    >>>
    >>>
    >>> def foo():
    ... x = 1
    ... x.a
    ...
    >>>
    Program received signal SIGTRAP, Trace/breakpoint trap.
    0x00007ffff71dd573 in __select_nocancel () at ../sysdeps/unix/syscall-template.S:84
    84 ../sysdeps/unix/syscall-template.S: No such file or directory.
    (gdb) b Python/ceval.c:2855
    Breakpoint 1 at 0x5418d7: file Python/ceval.c, line 2855.
    (gdb)c
    Continuing.
    >>>
  4. 函数调用,断在cpython中了
    1
    2
    3
    4
    >>> foo()
    Breakpoint 1, _PyEval_EvalFrameDefault (f=<optimized out>, throwflag=<optimized out>) at Python/ceval.c:2855
    2855 PyObject *name = GETITEM(names, oparg);
    (gdb)
  5. 使用dbg相关命令查看cpython中变量,等等等