GDB 获取python程序堆栈
Posted espzest
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GDB 获取python程序堆栈相关的知识,希望对你有一定的参考价值。
在调试python程序时,经常需要从gdb attach上去,跟踪stack信息。 虽然DebuggingWithGdb[https://wiki.python.org/moin/DebuggingWithGdb]提供了不错的方法,但是某些情况下还是需要gdb原始操作的。
typedef struct {
PyObject_HEAD
int co_argcount; /* #arguments, except *args */
int co_nlocals; /* #local variables */
int co_stacksize; /* #entries needed for evaluation stack */
int co_flags; /* CO_..., see below */
PyObject *co_code; /* instruction opcodes */
PyObject *co_consts; /* list (constants used) */
PyObject *co_names; /* list of strings (names used) */
PyObject *co_varnames; /* tuple of strings (local variable names) */
PyObject *co_freevars; /* tuple of strings (free variable names) */
PyObject *co_cellvars; /* tuple of strings (cell variable names) */
/* The rest doesn't count for hash/cmp */
PyObject *co_filename; /* string (where it was loaded from) */
PyObject *co_name; /* string (name, for reference) */
int co_firstlineno; /* first source line number */
PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) See
Objects/lnotab_notes.txt for details. */
void *co_zombieframe; /* for optimization only (see frameobject.c) */
PyObject *co_weakreflist; /* to support weakrefs to code objects */
} PyCodeObject;
其中重要的是:co_filename(文件名), co_firstlineno(首行), co_name(函数名)。
如果通过gdb拿到以下stack:
#0 0x000000395bee8f63 in epoll_wait () from /lib64/libc.so.6
#1 0x00007feb949885de in pyepoll_poll (self=0x7feb9c2acc00, args=<optimized out>, kwds=<optimized out>) at /n/filer3b/home/sqa/xuezhang/tickets/SCM-979/software-SCM-1280/Python-2.7.11/Modules/selectmodule.c:1034
#2 0x00000000004a2fc1 in call_function (pp_stack=<optimized out>, oparg=<optimized out>) at Python/ceval.c:4350
#3 0x00000000004a2fc1 in PyEval_EvalFrameEx (f=0x2b67fc0, throwflag=<optimized out>)
#4 0x00000000004a4890 in PyEval_EvalCodeEx (co=0x7feb94749630, globals=<optimized out>, locals=<optimized out>, args=0x7feb91a3f1d8, argcount=1, kws=0x7feb91a3f1e0, kwcount=0, defs=0x0, defcount=0, closure=0x0) at Python/ceval.c:3582
#5 0x00000000004a2c0e in call_function (pp_stack=<optimized out>, oparg=<optimized out>) at Python/ceval.c:4445
#6 0x00000000004a2c0e in PyEval_EvalFrameEx (f=0x7feb91a3f050, throwflag=<optimized out>)
#7 0x00000000004a3857 in call_function (pp_stack=<optimized out>, oparg=<optimized out>) at Python/ceval.c:4436
#8 0x00000000004a3857 in PyEval_EvalFrameEx (f=0x7feb9c2c2050, throwflag=<optimized out>)
#9 0x00000000004a4890 in PyEval_EvalCodeEx (co=0x7feb9c0ab730, globals=<optimized out>, locals=<optimized out>, args=0x0, argcount=0, kws=0x0, kwcount=0, defs=0x0, defcount=0, closure=0x0) at Python/ceval.c:3582
#10 0x00000000004a4a12 in PyEval_EvalCode (co=0x5, globals=0x2d36f50, locals=0x3ff) at Python/ceval.c:669
#11 0x00000000004c9983 in run_pyc_file (fp=<optimized out>, filename=<optimized out>, globals=0x2d36f50, locals=0x3ff, flags=<optimized out>) at Python/pythonrun.c:1400
#12 0x00000000004c9983 in PyRun_SimpleFileExFlags (fp=0x2586930, filename=<optimized out>, closeit=<optimized out>, flags=0x7ffd20d1d21c)
#13 0x0000000000414dd6 in Py_Main (argc=<optimized out>, argv=0x7ffd20d1d3c8) at Modules/main.c:640
#14 0x000000395be1ed5d in __libc_start_main () from /lib64/libc.so.6
#15 0x00000000004141da in _start ()
PyEval_EvalCodeEx(PyCodeObject* co, ...), 第一个参数函数含有我们需要的信息。
p ((PyCodeObject*)0x7feb9c0ab730)->co_firstlineno 得到首行行号: 3
x /50sb (PyStringObject*)(((PyCodeObject*)0x7feb9c0ab730)->co_name) 打印一系列字符串, 可以得到函数名: module
x /50sb (PyStringObject*)(((PyCodeObject*)0x7feb9c0ab730)->co_filename) 打印一系列字符串,可以得到文件名: ./backend/run.py
以上是关于GDB 获取python程序堆栈的主要内容,如果未能解决你的问题,请参考以下文章