Recent

Author Topic: That annoying assembler window -- debugger / stepping  (Read 1547 times)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 11795
  • Debugger - SynEdit - and more
    • wiki
That annoying assembler window -- debugger / stepping
« on: April 11, 2024, 01:03:38 pm »
Ok, so here is a question for all those who complain about the asm window popping up

Using the app from https://forum.lazarus.freepascal.org/index.php/topic,66927.0.html
Breakpoint on line 333
Code: Pascal  [Select][+][-]
  1. function WndProc(Wnd : hWnd; Msg : UINT; wParam, lParam : ptrint)
  2.          : ptrint; stdcall;
  3. ....
  4.   WndProc := DefWindowProc (Wnd, Msg, wParam, lParam);

The callstack will be
Code: Text  [Select][+][-]
  1. #0 WNDPROC(14421428, 36, 0, 22411956) at ColorSteps.lpr:333
  2. #1 user32:AddClipboardFormatListener+75 at :0
  3. #2 user32:GetClassLongW+1962 at :0
  4. #3 user32:GetClassLongW+938 at :0
  5. #4 user32:SystemParametersInfoForDpi+265 at :0
  6. #5 ntdll:KiUserCallbackDispatcher+77 at :0
  7. #6 user32:CreateWindowExW+359 at :0
  8. #7 user32:CreateWindowExA+56 at :0
  9. #8 WINMAIN at ColorSteps.lpr:398
  10. #9 main at ColorSteps.lpr:428
  11. #10 Exe_entry(Failed to read Mem at Address $FFFFFFFFFFFFFFFC (while calculating location)) at system.pp:170
  12. #11 _FPC_WinMainCRTStartup at sysinitpas.pp:49
  13. #12 kernel32:BaseThreadInitThunk+25 at :0
  14. #13 kernel32:FindActCtxSectionGuid+992 at :0
  15. #14  at :-1

So if you keep  stepping with F8, you will step out of that function.

Then you will be in "user32:AddClipboardFormatListener". And that does not have sources.
    What should the IDE show?


The thing is, in 3.99 I have the IDE to try and avoid the asm a bit harder than in older versions => So the IDE now finds the code for frame 9. And the IDE displays the source at "ColorSteps.lpr:398" as active line.
But since it really is in the function "user32:AddClipboardFormatListener" further stepping with F8 steps through user32:AddClipboardFormatListener.

In other words, you can press F8 for a hundred times, and the IDE will keep insisting you are at line "ColorSteps.lpr:398".

So that is, why I think the IDE should open the asm window.



And just to say, trying to automatically step out all the way has its dangers too. What if it does not actually step out to the frame 9, but instead a frame in the middle steps into the mainloop of the app, and runs the app.
Then the F8 would turn into an F9, that would only stop again when you close the app.

And the only way to find such a hidden "run" would be to asm-single-step the entire code, but that can be slow, and could easily mean the debugger would take 5 minutes before it finds were the app goes...

So, what should happen?



If an assert or raise exception happens, then IMHO it is ok to show the calling code, because any stepping should get you to the except/finally block. But otherwise...

440bx

  • Hero Member
  • *****
  • Posts: 5807
Re: That annoying assembler window -- debugger / stepping
« Reply #1 on: April 11, 2024, 02:26:03 pm »
Yes, there are some difficult choices to be made when debugging can switch from source to assembly and back.

My viewpoint about the case you presented is that if the programmer puts a breakpoint at a line that will enter the O/S (in this case the DefWindowProc) then there are two possibilities:

1. if the user presses F7 (step into) then open the assembly window and the user is on his/her own.  The reason being is that by pressing F7 the user specifically requested to enter and step through code that is not part of the program.  If the programmer makes that choice then the programmer has to live with it.

2. if the user presses F8 (step over) then the problem is that, from a source standpoint, it is unclear where execution will resume.  After a long winded path in O/S code it could end back in the GetMessage/Dispatch message loop but, it could also, easily, re-enter the window procedure or go back to some other place that forced a call to the window procedure (e.g, UpdateWindow which can be called from just about anywhere in the program.)  There is no _reasonable_ way for the IDE to figure out the _next_ source instruction that will be executed - and in some cases, it is simply not possible.   Therefore that's not a solution.

I'd say, in the case of F8, I see only two reasonable courses of action.  The first one would be to warn the user that execution will enter O/S code and source debugging can only resume when and if the O/S re-enters the program code _and_ a user breakpoint will be hit.

The second option is to inform the user that if he/she wants to trace through O/S code to press F7 instead.

In either case a warning is issued, likely in the form of a message box, with the option of "do this choice" and "don't show this box again (i.e, "always the choice I specified".)

Lastly, I'd like to see the Assembly window _not_ be a separate popup window.  Instead, I'd like to see it as it is in Visual Studio, simply another tab in the collection of "source windows" but that one would be titled "Assembler" (like the current window) or some other title that makes it clear it is not a source code window.

Essentially, it boils to this: there are times when the IDE has no choice but to enter assembly code that is not part of the program, e.g, F7/F8 on a call to DefWindowProc.  In those cases, I think it's totally fair for the IDE to warn the programmer that he/she is about to enter O/S code.

The other thing that I believe is not only fair but required is, if a programmer enters O/S code then it is more than totally acceptable to expect the programmer to know what he/she is doing.  IOW, the IDE should _not_ try to bend over backwards to accommodate programmers who don't have the knowledge to deal with situations they put themselves into.  The best the IDE can do is warn the user of what's about to happen.

For the record, Visual Studio will go into assembly if there is no other possibility without any warning whatsoever (as it should be.)

On a related but different note, I'd love to see the values displayed in registers default to hex. They can currently be changed to "hex" but I don't think the extra step should be necessary.  Registers and Hex are two things that really go together.  Decimal is for the grocery store not the CPU.

FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 11795
  • Debugger - SynEdit - and more
    • wiki
Re: That annoying assembler window -- debugger / stepping
« Reply #2 on: April 11, 2024, 03:04:41 pm »
IMHO, in this case F7 vs F8 should make no difference.

In neither case is there any "stepping into". And F7 only should "step into" code that has sources.

But, both F7 and F8 must perform a step out, if they reach the end of the current procedure. And once stepped out, they will be inside the kernel.
The same would happen if a user debugs his Paint method, and he keeps stepping out (or even just steps out, and has an LCL without debug info). There is plenty of possibilities for step out, to leave the available sources.



Yes, a warning dialog would be an option => but you can see the asm dialog as just that.

Maybe it is just me, but I would find a "Sorry but the debugger can't step into/over because there is no further source code (in the caller)" way more annoying than the asm window.
- It still gets me off the sources
- It still is an extra window that I need to close
- I am now forced to use some other key combo (as the same would apply to "step out" I could not even use the normal step-out key combo to work my way out)

But that is why I ask, maybe that is just me.
So, if there are plenty of people who would rather get such a dialog, and have the debugger to do nothing => then ok.

The only advantage of such a dialog is, if it could offer you an alternative. And the option to make that default. E.g., if it would say "Do you want the debugger to run/F9  your code if F7/F8 leaves the sources (Don't ask again)".

However using F7 as the "force the debugger to step out, rather than showing the dialog" is not an option. There are enough situations were people step with F7 instead of F8 => and then they would never get the dialog, but without choice get the asm window.... (which is completely defying the idea of showing a dialog instead).

So the big issue with the dialog is, that either
- it need different key combos to continue stepping (anything but run/F9)
- or, the dialog has a button "force the step", and you always have to go through the dialog

Trying to "step out" until sources, is a limited alternative => because there are cases were the stack can not be unwound, and the calling sources can not be found. Or they may not even exist (e.g. leaving the main code of a thread).



Quote
Lastly, I'd like to see the Assembly window _not_ be a separate popup window.  Instead, I'd like to see it as it is in Visual Studio, simply another tab in the collection of "source windows"
Doesn't anchordocking get you close enough to that?

Yes, it isn't in the same set of tabs as the other source editors, but it can be in the same docking location (just a new tab-bar with "asm" and "source-editor").

I am not sure if I would do that as a feature outside of anchordocking. To me it would be a problem, as I always have several Source editors, and would then have to keep making sure it is in the correct one, or in its own one....

Not to mention, it would be a good amount of work, since the source editors want to have a SynEdit in them.... And the asm, has it's own text drawer (could be changed), and a toolbar, ....

So, even the bars for a contribution on this would be very high... Starting with a general interface for the source editor to handle such different content.

440bx

  • Hero Member
  • *****
  • Posts: 5807
Re: That annoying assembler window -- debugger / stepping
« Reply #3 on: April 11, 2024, 04:22:42 pm »
IMHO, in this case F7 vs F8 should make no difference.
I see what you're saying. 

Honestly, the thing about the dialog box warning is something I have mixed feelings about. I suggested it because Lazarus is inherently a friendly environment and the dialog box would be "friendly information".  Honestly, personally I don't need nor really care to have a dialog box telling me what I already know but I tried to think about what might be good for other people (let them know what is going to happen... in case they don't know/realize.)

For the record, I think the current Assembly window just popping up is fine (though I would prefer it as an additional tab... more on that later.)  A bit surprising when you don't expect it but, there is no harm done anywhere.

What follows is just the way I personally think about F7/F8.  To me F8 means execute the current instruction and F7 means _get into_ whatever the instruction is, which means if the source line reads "BeginPaint" then F7 means get into the code that implements "BeginPaint" (which is assembler) whereas F8 means don't get into "BeginPaint", just execute it.  IOW, F7 is always a "drill" into whatever is there.

Of course, when the instruction is the "end;" of a window procedure then either F7 or F8 go into assembly, as you said, they "step out".  There is nothing else they can do.

- It still gets me off the sources
- It still is an extra window that I need to close
- I am now forced to use some other key combo (as the same would apply to "step out" I could not even use the normal step-out key combo to work my way out)
About those.  The  first one is obviously unavoidable.  The second one, the need to close it could be minimized (more on that later.) The third one, honestly, I think F7 and F8 should be context sensitive and mean _exactly_ the same in the Assembly window as they do in the source window.  IOW, the option of Alt-F7/F8 should not exist.  There should _not_ be different keys for Pascal source and Assembly code execution.

The only advantage of such a dialog is, if it could offer you an alternative. And the option to make that default. E.g., if it would say "Do you want the debugger to run/F9  your code if F7/F8 leaves the sources (Don't ask again)".
That's it.  Just being friendly but, this may well be a case of "too friendly".

Trying to "step out" until sources, is a limited alternative => because there are cases were the stack can not be unwound, and the calling sources can not be found. Or they may not even exist (e.g. leaving the main code of a thread).
I don't think the IDE should even attempt providing that alternative because there are too many cases when there is no reasonable way for the IDE to make good on that offer.

Doesn't anchordocking get you close enough to that?
I don't use anchordocking because I feel it doesn't use the space efficiently.  I have one "main" window which is the "Source Editor" window.  I think it would be nice if the assembly window could simply be another tab in the "Source Editor" window.  Maybe the assembly tab could be a different color to make it readily identifiable (I like that.)

Not to mention, it would be a good amount of work, since the source editors want to have a SynEdit in them.... And the asm, has it's own text drawer (could be changed), and a toolbar, ....
I basically have no knowledge of Lazarus internals but, couldn't the assembly window just be associated with a tab that is managed by the "Source Editor" window, what I'm saying is, the upper level window (source editor) does not need to know nor should it care what the _actual_ window contains, it should just see another window on the list. 

Note that I am not suggesting in any way that the assembly window should have a SynEdit in it.  Particularly considering that the assembly code is not editable (in addition to the many other reason why a SynEdit window would not be the best choice for the assembly window.)

FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 11795
  • Debugger - SynEdit - and more
    • wiki
Re: That annoying assembler window -- debugger / stepping
« Reply #4 on: April 11, 2024, 05:05:41 pm »
What follows is just the way I personally think about F7/F8.  To me F8 means execute the current instruction and F7 means _get into_ whatever the instruction is, which means if the source line reads "BeginPaint" then F7 means get into the code that implements "BeginPaint" (which is assembler) whereas F8 means don't get into "BeginPaint", just execute it.  IOW, F7 is always a "drill" into whatever is there.
F7 will only get into "BeginPaint", if Begin Paint has sources (or if it is a jump-pad to code with source, but that is a technicality).

If you step into "Move(a,b,10)" then it wont go there, unless your rtl has debug info.
But if your rtl has debug info, then F7 will step into fpc_AnsiStr_Assign on the line "MyString := 'foo';".
(And that is a different topic, but a blacklist would be useful....)

So stepping outside of sources either
- requires explicit asm stepping (either ALT-F7  or contexct-F7 with focus on asm window  or buttons in asm window)
- "Stepping out" leaving a routine into no sources caller.
- faulty stepping (some versions of gdb in combination with some versions of fpc) or other bugs

IIRC, the main issue that triggered the asm window complains were not stepping related (except if stepping is buggy and stops incorrectly, but then the asm window is not the primary issue).

Exceptions and asserts may have been it. But I don't have a list... (And they should behave better now, as long as the stack can be unrolled)

Watchpoints could trigger it too.
That I actually would need to test. Watchpoints could show sources, but if you continue with stepping (rather than F9) then it may have to take you into asm land. Ideally they would be able to step out... But not sure.

Anyway, I'll just leave that here, as a collection point for related issues.


Quote
I basically have no knowledge of Lazarus internals but, couldn't the assembly window just be associated with a tab that is managed by the "Source Editor" window, what I'm saying is, the upper level window (source editor) does not need to know nor should it care what the _actual_ window contains, it should just see another window on the list. 

Those tabs are managed by TSourceNotebook, which expects TSourceEditor for each tab. And there is lots and lots of code that relies on those structures (more than 20 years worth of code). It was a challenge to be able to open editor-macros (pascal script) in those tabs. Because they don't have unit info, nor a file associated with them, but at least the can be shown in source editors.

 

TinyPortal © 2005-2018