As I have mentioned in Why do I need a debugger?:
(3) Debugger is a good tool to help you understand code.
So when I come across difficulty to understand vfscount.py code in bcc project, I know it is time to resort to pdb
, python
‘s debugger, to help me.
The thing which confuses me is here:
counts = b.get_table("counts")
for k, v in sorted(counts.items(), key=lambda counts: counts[1].value):
print("%-16x %-26s %8d" % (k.ip, b.ksym(k.ip), v.value))
From previous code:
BPF_HASH(counts, struct key_t, u64, 256);
It seems the v
‘s type is u64
, and I can’t figure out why use v.value
to fetch its data here.
pdb
‘s manual is very succinct and its command is so similar with gdb
‘s, so it is no learning curve for me. Just launch a debugging session and set breakpoint at “counts = b.get_table("counts")
” line:
# python -m pdb vfscount.py
> /root/Project/bcc/tools/vfscount.py(14)<module>()
-> from __future__ import print_function
(Pdb) b vfscount.py:49
Start the program and press Ctrl-C
after seconds; the breakpoint will be hit:
(Pdb) r
Tracing... Ctrl-C to end.
^C
ADDR FUNC COUNT
> /root/Project/bcc/tools/vfscount.py(49)<module>()
-> counts = b.get_table("counts")
Step into get_table
method, and single-step every line. Before leaving method, check the type of keytype
and leaftype
:
-> counts = b.get_table("counts")
(Pdb) s
--Call--
> /usr/lib/python3.6/site-packages/bcc/__init__.py(416)get_table()
-> def get_table(self, name, keytype=None, leaftype=None, reducer=None):
(Pdb) n
> /usr/lib/python3.6/site-packages/bcc/__init__.py(417)get_table()
-> map_id = lib.bpf_table_id(self.module, name.encode("ascii"))
......
(Pdb) p leaf_desc
b'"unsigned long long"'
(Pdb) n
> /usr/lib/python3.6/site-packages/bcc/__init__.py(430)get_table()
-> leaftype = BPF._decode_table_type(json.loads(leaf_desc.decode()))
(Pdb)
> /usr/lib/python3.6/site-packages/bcc/__init__.py(431)get_table()
-> return Table(self, map_id, map_fd, keytype, leaftype, reducer=reducer)
(Pdb) p leaftype
<class 'ctypes.c_ulong'>
(Pdb) p keytype
<class 'bcc.key_t'>
Yeah! The magic is here: leaftype
‘s type is not pure u64
, but ctypes.c_ulong
. According to document:
>>> print(i.value)
42
We should use v.value
to get its internal data.
Happy pdbing! Happy python
debugging!
PDB is more flexible than the debugger which is built into Python’s IDLE package. For simple debug sessions, IDLE’s GUI interface may also be useful:
https://docs.python.org/3/library/idle.html
Enjoying your blog, as it’s rare to find developers running Python under OpenBSD. Hope you continue to write about both.
thanks post nice