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 とマクロ、インポートフックと抽象構文木 これぐらいしか、目当てな ものがなかった。でも、犬も歩けば、なんとやらで、

jinja2 入門 その5 マクロとインポート

Python入門

Pythonで数学を学ぼう!

こんな楽しいURLをゲットしたよ。

gdb with python

そもそもpythonするって決心(そんな上等な心がけじゃないけど)したのは、 gdbを入れると、もれなくついてくる、お邪魔虫だったから。無視するのも、 なんだなと思った次第なんだ。

Pythonでgdbを操作する

GDBでPython scriptを実行する

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は素直じゃないからな。

inside python