Open gaogaotiantian opened 1 year ago
I linked a prototype for the instruction display. Please let me know if we want to proceed on this feature. I can either do two PRs(I would assume si
is going to be rather complicated) or do a big one.
We don't want a dis
command as it's easy for users to add an alias if they so choose. Using .pdbrc
they can define aliases that are always available.
As for working with opcodes, that's an interesting idea! But do we need a separate assembly mode? It feels to me like it would be more flexible to add new commands for this, like lo
| listopcodes
and llo
| longlistopcodes
. What do you think?
I was actually torn between the two ideas - whether to overload the existing command with a state flipper, or to add two extra commands. There are two reasons I'm leaning slightly toward the state solution:
l
and ll
.I can go along with the extra commands as well, the debugger I was using for C in my prev company uses more like a state switch solution. We can only display the current instruction when the user uses si
(or in the future other instruction-level commands).
Actually there's another possibility - we overload everything. In assembly mode, step
means stepinstruction
. I believe this is how windbgx works. If the users switched to "assembly mode", clicking "step" actually steps a single instruction. That's also one possible solution.
The reason I brought up a new command for dis
is that there are equivalents in gcc(and probably other debuggers). True the user can achieve that with .pdbrc
with alias
, but that's true for a lot of other commands(whatis
, interact
, retval
...). I think the ultimate decision falls on - will this introduce more trouble for the users don't use it, or will it benefits more for the users who do.
Also I guess there are a couple of names for the instruction
. disassembly
is one and opcode
you used. I always think opcode
is referring to the actual instruction type like LOAD_GLOBAL
or CACHE
, whereas instruction
is the full package with arguments, line number, positions and stuff. That's also how it's used in dis
docs if I understand correctly.
On the side note, now that I think about it, si
and ni
are two different commands and we need to separate them.
I am excited about this proposal. Indeed, there are plenty of options for how this could be implemented. I would like to know your thoughts on how LLDB handles disassembly.
LLDB has separate commands for source and instruction level stepping:
n
for source level single stepni
for instruction level single stepAdditionally, LLDB provides settings to control whether to display disassembly when stopped. I took a couple of screenshots for demonstration.
By default, LLDB only shows source code when stopped, even with instruction level stepping:
Although it does not display disassembly, it marks the corresponding piece of code that is being executed.
By setting settings set stop-disassembly-display always
, you can examine the source code and the assembly code at the same time:
Do you think pdb could provide a similar user experience? And how beneficial would such behaviour be for Python programmers?
pdb
currently does not have a settings
command to handle all potential settings (maybe for the next pdb
we should consider that). assem
would be the first state command if introduced.
I guess having assem
state determine whether to step inst or line is not that great an idea on command line tools. It's nice on GUI where the button overloading has more benifits. On command line tools, I guess users would like more distinct commands.
Personally, I'd like my debugger to show some difference when I do ni
. Just a note here that we can do specific code now with position
. I still think displaying the current instruction after ni
would be a better user experience. pdb
only list a single source line, compared to lldb
which has more context. So adding another instruction line would be cheaper(screen space wise) than lldb
. Also, it we do not have state, we won't have a choice - so it's either with or without. I'd lean forward to with.
As for the benefits, I'm not sure. I would guess most of the Python users debug their program with print()
. Even among the people who are using pdb
, most of them probably are not familiar with bytecodes. However, the number of users of Python is so large that if a small portion of a small portion is a significant number. At least for me, I often want to see the actual compiled bytecode of the function to see what's really going on there. (Thus the thought of dis
, which would be super convenient).
I'm totally fine with li
and lli
instead of assem
. Just want to hear more from the actual users.
Dear nosy:
I've finished a draft for the implementation. I decided to go no-state. Separate commands for all instruction-related stuff. So, li
, lli
, si
and ni
. Also when you do si
and ni
, the current instruction will be displayed in the prompt.
Anyone has suggestions/questions on this? Once the implementation is reviewed and confirmed, I can work on the tests and docs.
Overall, this approach looks good to me! I agree that it better suits CLI than having a separate assembly mode. I also like that ni
and si
show me both the current source line and the current instruction.
One more thing to consider is the terminal width. Disassembly output can be wide, at least because of the full file paths:
(Pdb) li
1 -> def foo(a, b):
--> 2 LOAD_CONST 0 (<code object foo at 0x101651210, file "/very/long/full/path/to/foo.py", line 1>)
However, I do not have a particular idea of how to approach that properly.
One more thing to consider is the terminal width. Disassembly output can be wide, at least because of the full file paths:
Unfortunately, this piece is using the internal function of dis
directly, which will provide a familiar experience to dis
users (assuming most of the people interested in instructions are using dis
). dis
has similar issues and I guess there's no perfect way to deal with it.
Hi all, the feature, test and docs are all finished and ready for review now.
This is very technically cool, but I can't think of any use cases for end users and it's a lot of code. (Am I just not creative enough?)
I can, however, imagine that core devs working on the Python bytecode compiler will get benefit from it. Maybe we should get buy in from some potential users before complicating Bdb?
This is very technically cool, but I can't think of any use cases for end users and it's a lot of code. (Am I just not creative enough?)
I can, however, imagine that core devs working on the Python bytecode compiler will get benefit from it. Maybe we should get buy in from some potential users before complicating Bdb?
Python has f_trace_opcodes
, so the ability to trace and debug opcode (instruction) is natural. The end user of Python is a large base, I for example, often need the capability to debug on instruction level. It's also very helpful to debug CPython itself.
All I'm saying is, there are different needs for different developers - for a lot of developers, they do not even use debuggers,. Having a working solution for debugging instructions does not make pdb worse. And yes, there are more code in bdb, but most of them are on isolated paths that are very specific to instruction tracing. It does not impact the current bdb responsibilities.
For use cases, there is a very common pattern in Python - one-liners. Often they consist of multiple expressions. As of now, pdb can only execute it as a full line, and the debuggability within the line is horrible. Having an instruction-level debugging in pdb would solve that.
However, with the new PEP 669, this work is blocked by the implementation of #103615 , which I'm also responsible for. So this feature will only be visited later.
Feature or enhancement
Support instruction-level debugging in pdb
li
andlli
to display instructions with source codesi
andni
commandPitch
pdb
could provide a better debugging experience by supporting instruction level debugging. We already have most of the utilities but we need to put them together.The new commands will be introduced:
li(listinst)
,lli(longlistinst)
,si(stepinst)
andni(nextinst)
(Another candidate would bedis
, which is short forimport dis; dis.dis()
).li
andlli
will list source file with the instructions.si
will step one instruction ahead andni
will stay in this frame. We haveopcode
event to support this.Previous discussion
Did not find any.
Linked PRs