python with gdb
Table of Contents
OpenBSD 7.3
OpenBSD 7.3 今回は、いつもより若干速いリリース。順調が何よりだ。 案内をざっと見すると、
Python 2.7.18, 3.9.16, 3.10.10 and 3.11.2 豪華に、これだけ出しましたと さ。諸般の事情で、バージョンを大きく変更できない人むけか。
Python Developer's Guide に有る Status of Python Versions によれば、2系なんて、とっくに期限切れなんだけどな。独自にサポートして くれているのかな?
python macro
前回はpythonを関数型言語として見てみた。さかんにイテレータと持ち上げて いるのが、よく理解できたよ。それならば、マクロはどうよと思って調べてみ ろと、検討違いもはなはだしいものしか、かかってこなかった。
Python is an interpreted object-oriented programming language, and is often compared to Tcl, Perl or Scheme.
こんな紹介がFreeBSDのパッケージには、あるんだけどね。
Python とマクロ、インポートフックと抽象構文木 これぐらいしか、目当てな ものがなかった。でも、犬も歩けば、なんとやらで、
こんな楽しいURLをゲットしたよ。
gdb with python
そもそもpythonするって決心(そんな上等な心がけじゃないけど)したのは、 gdbを入れると、もれなくついてくる、お邪魔虫だったから。無視するのも、 なんだなと思った次第なんだ。
gdbでpythonをデバッグ use on ArchLinux ?
GDB support 本家のガイド
こちらは、gdbのマニュアル。 23.3 Extending GDB using Python (in gdb) 堂々と説明されてた。とりあえず、gdbを起動しておいて、
(gdb) python help() Welcome to Python 3.9's help utility! help> gdb Help on package gdb: NAME gdb - # Copyright (C) 2010-2023 Free Software Foundation, Inc. PACKAGE CONTENTS FrameDecorator FrameIterator command (package) disassembler frames function (package) printer (package) printing prompt styling types unwinder xmethod :
gdbモジュールの自己紹介をさせてみた。もう、本当にそこらにあるpythonと 同等だった。それもそのはず
[sakae@fb /tmp]$ ldd /usr/local/bin/gdb | grep python libpython3.9.so.1.0 => /usr/local/lib/libpython3.9.so.1.0 (0x21f34000)
しっかり、ライブラリィーを取り込んでいるよ。ただ、gdbモジュールはgdb上 でしか、生きられない制約がるんだけどね。
for debug
例によって観光目的で、gdbできるか確認。
on ArchLinux
[sakae@arch tmp]$ gdb -q python Reading symbols from python... Downloading separate debug info for /usr/bin/python3.10 Reading symbols from /home/sakae/.cache/debuginfod_client/8821701dd96b1c1a1fbfabdfe9a8463b8ed795d6/debuginfo... (gdb) b main Downloading source file /usr/src/debug/python/Python-3.10.10/./Programs/python.c Breakpoint 1 at 0x1120: file ./Programs/python.c, line 14. (gdb) r Starting program: /usr/bin/python Downloading separate debug info for /lib64/ld-linux-x86-64.so.2 Downloading separate debug info for system-supplied DSO at 0x7ffff7fc8000 Downloading separate debug info for /usr/lib/libpython3.10.so.1.0 Downloading separate debug info for /usr/lib/libc.so.6 [Thread debugging using libthread_db enabled] Using host libthread_db library "/usr/lib/libthread_db.so.1". Downloading separate debug info for /usr/lib/libm.so.6 Breakpoint 1, main (argc=1, argv=0x7fffffffea48) at ./Programs/python.c:14 14 { (gdb) b insertdict Downloading source file /usr/src/debug/python/Python-3.10.10/Objects/dictobject.c Breakpoint 2 at 0x7ffff7b2fb80: file Objects/dictobject.c, line 1070. (gdb) c Continuing. Breakpoint 2, insertdict (mp=0x7ffff77c9500, key=0x7ffff77c8230, hash=-8058398055468610483, value=0x7ffff77cc180) at Objects/dictobject.c:1070 1070 { (gdb) c Continuing. Python 3.10.10 (main, Mar 5 2023, 22:26:53) [GCC 12.2.1 20230201] on linux Type "help", "copyright", "credits" or "license" for more information. Downloading separate debug info for /usr/lib/python3.10/lib-dynload/readline.cpython-310-x86_64-linux-gnu.so Downloading separate debug info for /usr/lib/libreadline.so.8 Downloading separate debug info for /usr/lib/libncursesw.so.6 Downloading separate debug info for /usr/lib/python3.10/lib-dynload/_opcode.cpython-310-x86_64-linux-gnu.so
何もしなくても、gdbできるのね。資料は、こんな場所に保存されてる。
[sakae@arch ~]$ du -sh .cache/debuginfod_client/ 30M .cache/debuginfod_client/
cache_clean_interval_s
= 86400 しかし、うたかたの命。明日になれば反故
にされてしまう。
on Debian
sakae@deb:/tmp apt list | grep python3.9 : python3.9-dbg/stable,now 3.9.2-1 i386 [installed] python3.9-dev/stable,now 3.9.2-1 i386 [installed]
今迄は、3.9-devを入れておけばOKと思っていたけど、3.9-dbg版も重要と考え ていれてみた。きっとgdbと仲よくなれるだろう。開発じゃなくてDEBUGね。
x = input("Plese : ") print(x)
こんな他愛もない奴を走らせておき、そこにgdbからアタッチしてみる。
sakae@deb:/tmp$ gdb -q python 1981 Reading symbols from python... Reading symbols from /usr/lib/debug/.build-id/b7/d4636e94bdd0f435927069f0d92e67fae66596.debug... Attaching to program: /usr/bin/python, process 1981 Reading symbols from /lib/i386-linux-gnu/libpthread.so.0... Reading symbols from /usr/lib/debug/.build-id/b8/2adfa4e13739d42cb835a2e728642b91d177b7.debug... : (gdb) py-bt Traceback (most recent call first): <built-in method input of module object at remote 0xb76eb618> File "/tmp/test.py", line 2, in <module> x = input("Plese : ") (gdb) py-list 1 >2 x = input("Plese : ") 3 print(x)
なんとgdbなくせして、python用のpdbっぽい挙動を示したぞ。
(gdb) py-TAB ;; 補完して、その他のコマンドも列挙 py-bt py-down py-locals py-up py-bt-full py-list py-print (gdb) py-bt-full #13 <built-in method input of module object at remote 0xb76eb618> #17 Frame 0xb7690df0, for file /tmp/test.py, line 2, in <module> () x = input("Plese : ")
ひょっとして、#13とかは、gdbのフレーム番号ではなかろうか?
(gdb) f 13 #13 0x08164cae in cfunction_vectorcall_FASTCALL ( func=<built-in method input of module object at remote 0xb76eb618>, args=0xb7690f28, nargsf=2147483649, kwnames=0x0) at ../Objects/methodobject.c:426 426 ../Objects/methodobject.c: No such file or directory. (gdb) f 17 #17 _PyEval_EvalFrameDefault (tstate=<optimized out>, f=<optimized out>, throwflag=<optimized out>) at ../Python/ceval.c:3518 3518 ../Python/ceval.c: No such file or directory.
ビンゴだったな。
(gdb) f 23 #23 0x0825c56a in run_mod (mod=<optimized out>, filename=<optimized out>, globals={'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <SourceFileLoader(name='__main__', path='/tmp/test.py') at remote 0xb764bc70>, '__spec__': None, '__annotations__': {}, '__builtins__': <module at remote 0xb76eb618>, '__file__': '/tmp/test.py', '__cached__': None}, locals={'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <SourceFileLoader(name='__main__', path='/tmp/test.py') at remote 0xb764bc70>, '__spec__': None, '__annotations__': {}, '__builtins__': <module at remote 0xb76eb618>, '__file__': '/tmp/test.py', '__cached__': None}, flags=0xbf860888, arena=0xb76d8bd0) at ../Python/pythonrun.c:1239 1239 ../Python/pythonrun.c: No such file or directory.
そして、こんなオマケのデータも出てきた。嗅覚が鋭くなったものだ。猟犬で すよ。
ここまで親切なのにソースが不在。そういう時は、本家から貰ってくる。 https://www.python.org/ftp/python/3.9.2/Python-3.9.2.tgz
こやつを適当な所(って言っても、/tmpしかないけどね)に展開。そして、その 中にworkとか、これまた適当なdirを作って、その中からgdbを起動。 こんな流れになるかな。
sakae@deb:/tmp$ tar xf Python-3.9.2.tgz sakae@deb:/tmp$ cd Python-3.9.2/ sakae@deb:/tmp/Python-3.9.2$ mkdir work sakae@deb:/tmp/Python-3.9.2$ cd work/ sakae@deb:/tmp/Python-3.9.2/work$ ps a | grep python 2083 pts/2 S+ 0:00 python test.py 2156 pts/1 S+ 0:00 grep python sakae@deb:/tmp/Python-3.9.2/work$ gdb -q python 2083
これで準備完了。後は、下記のように、フレーム間を綱渡りしてくれ。ああ、 命綱はないから、落ちて死ぬなよ。それから、わざわざworkを作って、その中 から起動してるのは、gdbが検索するソースエリアの配置先を、わざわざ登録 しなくてもいいように、先回りする為だ。折角のworkなんで、ここに実験用の コードを納めておくといいだろう。
(gdb) f 18 #18 0x0814d9e7 in _PyEval_EvalFrame (throwflag=0, f=Frame 0xb76eddf0, for file /tmp/test.py, line 2, in <module> (), tstate=0x8894780) at ../Include/internal/pycore_ceval.h:40 40 return tstate->interp->eval_frame(tstate, f, throwflag); (gdb) l 35 void _PyEval_Fini(void); 36 37 static inline PyObject* 38 _PyEval_EvalFrame(PyThreadState *tstate, PyFrameObject *f, int throwflag) 39 { 40 return tstate->interp->eval_frame(tstate, f, throwflag); 41 } 42 43 extern PyObject *_PyEval_EvalCode( 44 PyThreadState *tstate,
もう、親切すぎて涙が出てきますよ。
on FreeBSD
オルターネイテイブで、こちらでもやってみる。configureしたら
configure: WARNING: Platform "i586-unknown-freebsd13.1" with compiler "clang" is not supported by the CPython core team, see https://peps.python.org/pep-0011/ for more information.
こんな脅しが出てきた。それは無いでしょう。見なかった事にして、しばし待 つ。
real 7m49.920s user 5m20.016s sys 0m13.180s
できあがった。本体部分が分離されてるので、こんなお呪いをしたよ。
[sakae@fb ~/MINE/bin]$ export LD_LIBRARY_PATH=/home/sakae/MINE/lib [sakae@fb ~/MINE/bin]$ ldd python3.11 python3.11: libpython3.11.so.1.0 => /home/sakae/MINE/lib/libpython3.11.so.1.0 (0x20443000) libdl.so.1 => /usr/lib/libdl.so.1 (0x208a8000) libutil.so.9 => /lib/libutil.so.9 (0x208ac000) libm.so.5 => /lib/libm.so.5 (0x208c3000) libthr.so.3 => /lib/libthr.so.3 (0x208ff000) libc.so.7 => /lib/libc.so.7 (0x20929000)
Debianに習ってpy-btとかが使えるようにする。コンパイルした所に、 python-gdb.pyが出てくる。その正体は、Tools/gdb/libpython.pyだ。それを、 lib/に、libpython3.11.so.1.0-gdb.pyな名前でcopyする。元々libpython3.11.so.1.0 と言う本体が有るので、それとペアを組むって事だ。
そして、.gdbinit
add-auto-load-safe-path /usr/home/sakae/MINE/lib/libpython3.11.so.1.0-gdb.py
を登録する。pythonの指南書とはちと違うけど、周りをじっと見回した結果見 つけた方法だ。
Reading symbols from /home/sakae/MINE/bin/python3... Attaching to program: /usr/home/sakae/MINE/bin/python3, process 5600 Reading symbols from /home/sakae/MINE/lib/libpython3.11.so.1.0... Reading symbols from /usr/lib/libdl.so.1... (No debugging symbols found in /usr/lib/libdl.so.1) : (gdb) py-list >1 x = input("Plese : ") 2 print(x) (gdb) py-bt-full #10 <built-in method input of module object at remote 0x20e04488> #13 Frame 0x20bf3010, for file /tmp/test.py, line 1, in <module> () x = input("Plese : ")
on OpenBSD
7.2最後のご奉公で、やってみる。
LD_LIBRARY_PATH=/home/sakae/MINE/Python-3.11.2 CC='cc -pthread' LDSHARED='cc -pthread -shared -fPIC ' OPT='-DNDEBUG -g -fwrapv -O3 -Wall' ./python -E ./setup.py build Traceback (most recent call last): File "/home/sakae/MINE/Python-3.11.2/./setup.py", line 49, in <module> from distutils.command.build_ext import build_ext File "/home/sakae/MINE/Python-3.11.2/Lib/distutils/command/build_ext.py", line 13, in <module> from distutils.sysconfig import customize_compiler, get_python_version File "/home/sakae/MINE/Python-3.11.2/Lib/distutils/sysconfig.py", line 51, in <module> _config_vars = get_config_vars() ^^^^^^^^^^^^^^^^^ File "/home/sakae/MINE/Python-3.11.2/Lib/sysconfig.py", line 670, in get_config_vars _init_posix(_CONFIG_VARS) File "/home/sakae/MINE/Python-3.11.2/Lib/sysconfig.py", line 531, in _init_posix _temp = __import__(name, globals(), locals(), ['build_time_vars'], 0) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ModuleNotFoundError: No module named '_sysconfigdata__openbsd7_i386-unknown-openbsd7' gmake: *** [Makefile:862: sharedmods] Error 1
何かパッチが必要なのかな。何かとOpenBSDは素直じゃないからな。