An instruction to pause the debugger. [SOLVED] lazarus / 12-Debugger ---------------------------------------------------------------------- BrunoK · 2024-06-29 15:16 Debugger : FpDebug, Lazarus 3.99 I have a pascal code generator and would like the generated code to be able to pause the execution with an instruction, like for the following code snippet from a CocoR grammar file : Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i SynchNext  (. var       lAfterSym,       lAheadSym: integer;     var       lNextSym,       lDefaultSym,       lPrevSym : integer;       lScanner: TRC5ExportScanner;  .)  = (. lScanner:=GetScanner;       lDefaultSym := identSym;       if not lScanner.fHashList.Hash(aAfterSymName, lAfterSym, lDefaultSym) then       Exit;       if not lScanner.fHashList.Hash(aAheadSymName, lAheadSym, lDefaultSym) then         Exit;       while fCurrentInputSymbol<>EOFSYMB do begin         if fCurrentInputSymbol=lAheadSym then begin           { Some checking about aAfterSymName preceding found aAheadSymName }           if lPrevSym<>lAfterSym then             { Scanner.pos}{PAUSE HERE >}    DebuggerPause; // <===== Programmed pause             lDefaultSym := lAfterSym;           Exit;         end;         lPrevSym := fCurrentInputSymbol;         Get;       end;    .)      . At DebuggerPause is there an existing instruction that would put the debugger in pause on that line. ---------------------------------------------------------------------- Martin_fr · 2024-06-29 15:23 yes, kinda.... On Windows: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i DebugBreakoder Win/Linux Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i asmint 3end;(mind the space before the 3) At least the latter, should probably be IFDEFed for debugging only. I.e., compile for debug with -dMY_DBG_DEFINE (which then goes into the ifdef) Only, by default the debugger ignores both (the first one also ends on a "int 3") In the Option, Debugger Backend, in the settings for FpDebug is "HandleDebugBreakInstruction", which is set to "IgnoreAll". Uncheck the IgnoreAll. Downside: Other code (libraries) can also contain "int 3" => and then that will also enter debug pause. ---------------------------------------------------------------------- BrunoK · 2024-06-29 16:37 Uncheck'ed the IgnoreAll. Put in my code Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i      if  lPrevSym=lAfterSym  then       {  Scanner.pos}       asm  int 3 end; // <- as suggested       lDefaultSym  :=  lAfterSym;     Exit; Raises QuoteCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i [Window Title] prjR5DataReportToDB [Content]Access violation. Press OK to ignore and risk data corruption.Press Abort to kill the program. [OK] [Abort] What didn't I understand ? ---------------------------------------------------------------------- MarkMLl · 2024-06-29 16:44 Quote from: Martin_fr on June 29, 2024, 05:23:14 pmCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i asmint 3end;(mind the space before the 3) At least the latter, should probably be IFDEFed for debugging only. I.e., compile for debug with -dMY_DBG_DEFINE (which then goes into the ifdef) Only, by default the debugger ignores both (the first one also ends on a "int 3") In the Option, Debugger Backend, in the settings for FpDebug is "HandleDebugBreakInstruction", which is set to "IgnoreAll". Uncheck the IgnoreAll. Downside: Other code (libraries) can also contain "int 3" => and then that will also enter debug pause. Thanks very much for that Martin. I admit to fairly regularly having an Assert(false,... if I want to be alerted that a program has got itself into a thoroughly discombobulated state. MarkMLl ---------------------------------------------------------------------- 440bx · 2024-06-29 16:57 Quote from: BrunoK on June 29, 2024, 06:37:00 pmUncheck'ed the IgnoreAll. What didn't I understand ? I just tried the "asm int 3 end;" and it didn't work.  The program execution got messed up. If you are using Windows, use DebugBreak(), that one works.  I use it all the time. HTH. ETA: using "asm int 3 end;" does work with GDB.  I know because that's what I used all the time before FpDebug supported DebugBreak(); Because of Martin's answer to you, I'm guessing that FpDebug now is supposed to support "asm int 3 end;" too but, as I mentioned above, I tried it and execution got messed up.  IOW, "asm int 3 end;" isn't working quite right at this time. ---------------------------------------------------------------------- BrunoK · 2024-06-29 17:41 Marking discussion as SOLVED. Quote from: 440bx on June 29, 2024, 06:57:23 pmIf you are using Windows, use DebugBreak(), that one works.  I use it all the time. Thank you very much, this works on Windows with FPDebugger provided the Uncheck'ed  IgnoreAll as indicated by Martin. No need of USES Windows ...  The bit of code (CocoR) ends up being :  Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i       while fCurrentInputSymbol<>EOFSYMB do begin         if fCurrentInputSymbol=lAheadSym then begin           DebugBreak;         { Some checking about aAfterSymName preceding found aAheadSymName }           if lPrevSym<>lAfterSym then             DebugBreak;           lDefaultSym := lAfterSym;           Exit;         end;         lPrevSym := fCurrentInputSymbol;         Get;       end; That pop's up the Call Stack when reaching one the DebugBreak instructions, then one F7 single step places you on the next executable line. Maybe, just maybe, a feature would be the debugger poping the source at the DebugBreak instruction as if a Break point had been set there. This is very useful and I should have asked many months/year ago. ---------------------------------------------------------------------- 440bx · 2024-06-29 17:54 Quote from: BrunoK on June 29, 2024, 07:41:33 pmThis is very useful and I should have asked many months/year ago. Just in case you might find this useful, this is what I do: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i       if IsDebuggerPresent() then      begin        DebugBreak();      end; Checking if the debugger is present before calling DebugBreak() allows leaving the debugging code in the executable.  This makes removing the DebugBreak() in the release version unnecessary.  Without the check for the Debugger presence then the calls to DebugBreak() have to be removed or placed in a {$ifdef } conditional compilation because if a DebugBreak() occurs without a debugger to catch it, Windows will report it as an unhandled exception and terminate the program (usually not a desirable outcome ) Activating the DebugBreak() only if a debugger is present is a very convenient and practical solution.  The cost is a slight increase in code size (I think about 8 bytes total per instance... that's nothing in today's machines.) HTH. ---------------------------------------------------------------------- Martin_fr · 2024-06-29 18:38 Quote from: BrunoK on June 29, 2024, 07:41:33 pmMaybe, just maybe, a feature would be the debugger poping the source at the DebugBreak instruction as if a Break point had been set there. There are a lot of refinements this could get. But, even though I do note that there is more interest than was originally anticipated, it will have to wait. Too many other things on my list. ---------------------------------------------------------------------- BrunoK · 2024-06-29 21:39 Quote from: 440bx on June 29, 2024, 07:54:36 pmJust in case you might find this useful, this is what I do: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i       if IsDebuggerPresent() then      begin        DebugBreak();      end; Noted, thank you. ---------------------------------------------------------------------- 440bx · 2024-06-30 01:19 You're welcome Bruno. ---------------------------------------------------------------------- Thaddy · 2024-06-30 20:12 May I suggest a codeless solution? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$ifopt D+}DebugBreak();{$endif}In effect about the same as assertions, the code does not end up in a release compile. IsDebuggerPresent was nice in the days but not always reliable. ---------------------------------------------------------------------- 440bx · 2024-06-30 21:23 Quote from: Thaddy on June 30, 2024, 10:12:06 pmMay I suggest a codeless solution? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$ifopt D+}DebugBreak();{$endif}In effect about the same as assertions, the code does not end up in a release compile. IsDebuggerPresent was nice in the days but not always reliable. IsDebuggerPresent() is _completely_ reliable except in one case, which is, when a cracker wants to hide the fact that he/she is running the app under a debugger (it's very easy to make IsDebuggerPresent() return false but, only with malice) Other than that exception which occurs as a result of malice, IsDebuggerPresent() is rock solid. Your suggestion still has merit but, if I were going that route, I'd make it a macro. Another reason I prefer IsDebuggerPresent() is because I can add ad- hoc code between the begin/end to debug a particular situation.  begin/end space... the ultimate frontier. ---------------------------------------------------------------------- BrunoK · 2024-07-01 12:52 QuoteCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$ifopt D+}DebugBreak();{$endif}Seems not to work in Windows, ifopt is always true. My current version is, in the program where I want to put the DebugBreak : Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function DebugBreak: boolean; inline;begin  {$ifdef windows}  Result := Windows.IsDebuggerPresent();  if Result then    Windows.DebugBreak;  {$else}    Result := False;  {$endif}  (* Testing  if Result then    WriteLn('{Has debug}')  else    WriteLn('{Doesn''''t have debug}');  *)end;The DebugBreak function inlines well. ---------------------------------------------------------------------- 440bx · 2024-07-01 13:15 Just a very minor thing... in that code I don't think you need the {$else} part because result will already be set by IsDebuggerPresent(); Another thing you may want to consider, if you change it to a procedure then you can make it use zero bytes if you don't need the DebugBreak facility.  Something like this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure DebugBreak(); inline;begin  {$if defined(USE_DEBUGBREAK)}    {$ifdef windows}    if Windows.IsDebuggerPresent() then       Windows.DebugBreak;    {$endif}  {$endif}end; the net effect of doing it that way is that if USE_DEBUGBREAK is not defined then the DebugBreak procedure is empty and since it is inlined, the compiler entirely omits the call.  IOW, it takes _zero_ bytes.  Basically, you can have your cake and eat it too whenever convenient. HTH. ---------------------------------------------------------------------- Martin_fr · 2024-07-01 13:16 If you write your own wrapper function, you can just fill it with Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i asm  nopend;and set a breakpoint there. Unless, you have multiple binaries (such as lots of dll, in each of which you want such a function). EDIT: if the function is "inline" then you can't set a breakpoint, as fpc does not provide line info for that. But if you IFDEF, then you can IFnDEF the "inline". ---------------------------------------------------------------------- BrunoK · 2024-07-01 14:49 Quote from: Martin_fr on July 01, 2024, 03:16:04 pmCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i asm  nopend;and set a breakpoint there. The initial use case is Coco/R parser generated pascal code that analyze a .txt file containing measurement results in text form. In some languages (french) the .txt file has a grammar is not LL(1) and needs quite a bit of debbugging and tweaking of the coco EBNF file description / normalization to be able to inject info in my database. I don't know where the point I want to BreakPoint will end up in the unit after the generating step, so it is more practical to have a instruction that suspends the execution at the desired point rather than laboriously deleting / re adding break points in the debugger. The inlining pops'up the stack trace at the line of the call of my local BreakPoint instruction call and one F7 places me on the instruction following the call, what is not to like. ---------------------------------------------------------------------- BrunoK · 2024-07-01 14:56 Quote from: 440bx on July 01, 2024, 03:15:35 pm... IOW, it takes _zero_ bytes.  Basically, you can have your cake and eat it too whenever convenient. HTH. Taking a few bytes / tens of bytes is none of my problem. ---------------------------------------------------------------------- 440bx · 2024-07-01 15:18 Quote from: BrunoK on July 01, 2024, 04:56:49 pmTaking a few bytes / tens of bytes is none of my problem. I can relate to that.  On today's multi-gigabyte machine it isn't a priority to squeeze a few bytes out (except in genuinely rare cases.) Still, I thought I'd mention it for completeness and just in case you might have been interested.