Recent

Author Topic: Debugging macro behavior  (Read 289 times)

440bx

  • Hero Member
  • *****
  • Posts: 4686
Debugging macro behavior
« on: October 03, 2024, 07:49:38 pm »
Hello,

This post could probably be in the FPC section instead of the Lazarus one but, I had a hard time deciding where it should go, I chose this this section.

Consider a macro include file "Debug.macros.inc" to be as follows:
Code: Pascal  [Select][+][-]
  1. {$MACRO ON}
  2.  
  3. {$define _DebugBreak:=if IsDebuggerPresent() then asm int3 end}
  4.  
  5. //
  6. // end of file
  7. // ----------------------------------------------------------------------------
This macro is to save having to repeatedly type "if IsDebuggerPresent()... etc" and possibly (eventually) control the value of the macro based on other directives.

The "problem" is, using optimization level 1 (debugger friendly) then when the macro is found in the source, the breakpoint occurs in the "Debug.macros.inc" file instead of the file where the _DebugBreak macro invocation resides.  This is inconvenient because there is no visible context of what triggered the breakpoint.  Please see the first attachment (BreakpointMacroOpt1).

Strangely, if the executable is created using optimization level 3 (not a debugger friendly level) then the break occurs in the file where the macro was invoked which provides the desired context.  Please see the second attachment (BreakpointMacroOpt3).

My question is: is there some practical/reasonable way to have the level 1 optimization show the break the same way as level 3 does ?

Thank you for your help.

Note: I understand that it is unreasonable to expect a level 1 and level 3 optimizations program to behave the same way debugging-wise but, it would be nice if the behavior could be made consistent.



(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 10482
  • Debugger - SynEdit - and more
    • wiki
Re: Debugging macro behavior
« Reply #1 on: October 03, 2024, 08:11:28 pm »
Yep, that really is an fpc question (and I can not answer the question itself, but add some insight).

The debugger knows very little about files, units, lines in this context.

- It has asm instructions that reside at addresses.
- FPC provides to the debugger a list, for each address, what file and line it belongs too.

So for single stepping, the debugger just goes over asm statement, until that metadata changes. (simplified).

And for the IDE the debugger backend just says, look I paused, and the location is: file/line.
And the IDE shows that.

In reverse, if you set a breakpoint, the debugger searches for all addresses (start of each range) that map to the file/line. (again simplified)


So all that you observe is entirely controlled by FPC.  And the debugger doesn't even know if it is caused by a macro, or an inlined include file. Or if the filename changed for some other reason.


My guess, about the opt 3 - the compiler moved the generated code around (to optimize) and in that process "lost" some pieces of the debug info.


It's the joy of writing a debugger, you depend on lots of things that you don't control.

440bx

  • Hero Member
  • *****
  • Posts: 4686
Re: Debugging macro behavior
« Reply #2 on: October 03, 2024, 08:38:28 pm »
So all that you observe is entirely controlled by FPC.  And the debugger doesn't even know if it is caused by a macro, or an inlined include file. Or if the filename changed for some other reason.
I figured that was the case.

My guess, about the opt 3 - the compiler moved the generated code around (to optimize) and in that process "lost" some pieces of the debug info.
It lost the "nop" which caused the breakpoint to occur in what took its place which is an instruction in the file where the macro was invoked.  In the case, the elimination of that "nop" has a very desirable side effect (the ...Opt1 attachment shows what happened.)

It's the joy of writing a debugger, you depend on lots of things that you don't control.
Yes, that's a tough spot to be in.

I'm going to "ask" for something that I hesitate to ask for because it's really asking for more than the debugger can be expected to do but... the debugger could recognize the sequence "$CC, $90" (int3, nop), detect that execution stopped at the "nop" and  in that particular case automatically single step over the "nop".  That would be very nice because it would put the break where it is really desired. :)

Basically, I'm sheepishly asking for FpDebug to go out of its way to improve the behavior.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 10482
  • Debugger - SynEdit - and more
    • wiki
Re: Debugging macro behavior
« Reply #3 on: October 03, 2024, 08:56:48 pm »
Not sure where that nop comes from... But
That would last till the next rework of the fpc optimizer?

And there are still some actual work items on int3 on my list...

Probably: You can assign "asm single step" to a dedicated key, and press that once. Then you would step to the nop (for as long as the nop exists.


Fpc currently doesn't tell the debugger about inlined functions. So they look like the entire function is written on the single line on which the function was called.

So if you put your code into an inlined function that should work?

There is a 50/50 that this may still work if the macro calls that function. (So technically the function call is then in the macro)

440bx

  • Hero Member
  • *****
  • Posts: 4686
Re: Debugging macro behavior
« Reply #4 on: October 03, 2024, 09:32:49 pm »
Not sure where that nop comes from... But
That's the easy way for the compiler to generate code it knows works in all cases.

That would last till the next rework of the fpc optimizer?
True but, it's unlikely the optimizer for level 1 opt is going to change much and even if it does and the sequence is no longer present, it won't cause any harm. 


And there are still some actual work items on int3 on my list...
I have no doubt you have plenty to do.

Fpc currently doesn't tell the debugger about inlined functions. So they look like the entir
e function is written on the single line on which the function was called.
I tried that first. FPC won't inline a function that has "asm" statements.  That would have been nice.

Having it as a regular function doesn't solve the problem of loss of context.  It's basically like having a call to Windows' DebugBreak(), the break occurs in kernel32 instead of where the function is called forcing single stepping out of the function which is no big deal but inconvenient when it has to be repeated more than just a few times.

I'll just type it the thing instead of using a macro... no biggie.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

 

TinyPortal © 2005-2018