Recent

Author Topic: Data\Watch Breakpoint by adress  (Read 3065 times)

zamtmn

  • Hero Member
  • *****
  • Posts: 681
Data\Watch Breakpoint by adress
« on: June 15, 2025, 02:52:56 pm »
That is, I need to catch a write/read not to a variable, but to a specific known address in memory. I think there was such an opportunity and seems I used it, but now I couldn't do it. Please remind me is this possible or not?

Khrys

  • Sr. Member
  • ****
  • Posts: 402
Re: Data\Watch Breakpoint by adress
« Reply #1 on: June 16, 2025, 07:14:24 am »
In GDB you could use the  awatch, rwatch  and  watch  commands:


(gdb) help awatch
Set an access watchpoint for EXPRESSION.
Usage: awatch [-location] EXPRESSION

Options:
  -location
    This evaluates EXPRESSION and watches the memory to which is refers.
    -l can be used as a short form of -location.

An access watchpoint stops execution of your program whenever the value
of an expression is either read or written.



For example, if you want to break whenever a pointer-sized value at  0x1470A20  is accessed, you could use  awatch *(void**) 0x1470A20  (C syntax) or  awatch ^Pointer(0x1470A20)^  (Pascal syntax).

ALLIGATOR

  • Sr. Member
  • ****
  • Posts: 404
  • I use FPC [main] 💪🐯💪
Re: Data\Watch Breakpoint by adress
« Reply #2 on: June 16, 2025, 07:25:54 am »
Is the GDB console available when debugging from Lazarus?

In general, I think the question was whether it is possible to do this from the Lazarus debugger GUI interface... because there are dialogs like that, but they don't seem to work
I may seem rude - please don't take it personally

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12207
  • Debugger - SynEdit - and more
    • wiki
Re: Data\Watch Breakpoint by adress
« Reply #3 on: June 16, 2025, 09:21:08 am »
Yes you can.

But you do need a type, as the debugger needs to know the size of memory that it should "watch".

Add a new "data breakpoint"

^byte($12345678)^      1 byte
^^byte($12345678)^    32/64 bit
or
^longword($12345678)^   4 byte


Of course if byte or longword (that is what FPC uses for integer) are not used in your app, then that may not work.

An intel/amd CPU allows up to 4 watch-points, of which each can be 1,2,4 or 8 bytes (8 only on 64 byte systems).


You can also add such expressions as watches.



ALLIGATOR

  • Sr. Member
  • ****
  • Posts: 404
  • I use FPC [main] 💪🐯💪
Re: Data\Watch Breakpoint by adress
« Reply #4 on: June 16, 2025, 09:58:27 am »
Wow, cool! It really works )

How did I ever live without this before? (Answer: badly.)

(Maybe a note about this (using bare addresses) should be added to the relevant section of the wiki? I looked through it but couldn't find anything)
« Last Edit: June 16, 2025, 10:06:01 am by ALLIGATOR »
I may seem rude - please don't take it personally

zamtmn

  • Hero Member
  • *****
  • Posts: 681
Re: Data\Watch Breakpoint by adress
« Reply #5 on: June 16, 2025, 10:11:57 am »
Great! I was prompted to do this once, and I used it. Right now I can't remember and I can't find any information about it.
Should we add a more familiar syntax like Pascal?
Code: Pascal  [Select][+][-]
  1. pbyte($12345678)^
If it were possible to do this, the question would not arise))

ALLIGATOR

  • Sr. Member
  • ****
  • Posts: 404
  • I use FPC [main] 💪🐯💪
Re: Data\Watch Breakpoint by adress
« Reply #6 on: June 16, 2025, 10:18:05 am »
PByte(Address)^ - It works ) I checked it )
I may seem rude - please don't take it personally

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12207
  • Debugger - SynEdit - and more
    • wiki
Re: Data\Watch Breakpoint by adress
« Reply #7 on: June 16, 2025, 10:32:04 am »
PByte(Address)^ - It works ) I checked it )

It works, if your code (or any code you include in your app with debug info) uses "pbyte".

The debugger does not know pbyte as a name. It searches for the definition that the compiler added to debug info. And that is only there if the type is used in the code.

The same is true for "byte", but that is more often used (especially since pbyte use byte, and the compiler likely includes both in this case). So constructing your pointer type as ^byte is more likely to work.




Mind you there may be slight differences in what types (byte, ^byte, pbyte) are available depending on the debugger backend you have in your configuration.

By default I am talking about FpDebug.
GDB however (IIRC) is similar. GDB may have byte built in, even if the compiler did not supply it. (afaik it includes "char", but need to double check).

For info: Adding some fallback types to FpDebug is on my todo. But there are drawbacks to it too. Some of those types can be defined depending on compile mode (integer can be 16 bit in dos mode). Some types can be redefined by the user. And that may even be on a local scope.
Adding hardcoded fallbacks, can then lead to more confusion...

zamtmn

  • Hero Member
  • *****
  • Posts: 681
Re: Data\Watch Breakpoint by adress
« Reply #8 on: June 16, 2025, 10:38:11 am »
not one of the ways doesn't work for me. apparently the problem is something else((

ALLIGATOR

  • Sr. Member
  • ****
  • Posts: 404
  • I use FPC [main] 💪🐯💪
Re: Data\Watch Breakpoint by adress
« Reply #9 on: June 16, 2025, 10:52:32 am »
Windows 11, FPC[git main] + Lazarus[git main]

Checked it this way - all breakpoints worked
(i.e. not just byte/4/8)

Code: Pascal  [Select][+][-]
  1. program app;
  2. {$mode objfpc}
  3.  
  4. procedure test;
  5. var
  6.   b1: Int8;
  7.   b2: Int16;
  8.   b4: Int32;
  9.   b8: Int64;
  10. begin
  11.   b1:=0;
  12.  
  13.   PByte(@b2)[0]:=0;
  14.   PByte(@b2)[1]:=0;
  15.  
  16.   PByte(@b4)[0]:=0;
  17.   PByte(@b4)[1]:=0;
  18.   PByte(@b4)[2]:=0;
  19.   PByte(@b4)[3]:=0;
  20.  
  21.   PByte(@b8)[0]:=0;
  22.   PByte(@b8)[1]:=0;
  23.   PByte(@b8)[2]:=0;
  24.   PByte(@b8)[3]:=0;
  25.   PByte(@b8)[4]:=0;
  26.   PByte(@b8)[5]:=0;
  27.   PByte(@b8)[6]:=0;
  28.   PByte(@b8)[7]:=0;
  29. end;
  30.  
  31. begin
  32.   test;
  33. end.

Code: [Select]
PByte(address)^
PWord(address)^
PDWord(address)^
PQWord(address)^

FPC and Lazarus are built with debugging symbols, apparently that's why everything works successfully )
I may seem rude - please don't take it personally

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12207
  • Debugger - SynEdit - and more
    • wiki
Re: Data\Watch Breakpoint by adress
« Reply #10 on: June 16, 2025, 10:56:03 am »
not one of the ways doesn't work for me. apparently the problem is something else((

First of all, which debugger backend are you using?

And: I am afraid, if you are on Mac, it may be more complicated.
IIRC the "LLDB + FpDebug" does not support watchpoints at all (but I would have to check), and the same for "lldb alpha". Though if they do, then the syntax must be known by LLDB. I am not sure what lldb takes.

If you are on a "non intel" (including non AMD) machine (e.g. risc/arm) then you likely must use gdb. Then the syntax for the expression must be understood by gdb. Though IIRC gdb does understand ^byte. But it may need 0x12345678 instead of $12345678

If you are on Intel/AMD and Windows/Linux, then you should use FpDebug (check that you do). And that should get you the desired result.




Does not work, means? => Open the "breakpoint window", it should list the watchpoint.
- does (when the app runs) the watchpoint have a red bullet? (NOT with a  question mark)?
- any other symbol ? (check the "state" column // needs resizing of the column)

Also, check if you have other, old watchpoints in there.
As indicated, only 4 can be used. Even if the other don't work, they may block the new one.




Test that watchpoints (data breakpoints) work in general.
Test in a contained small sample app.


- Put a watchpoint on a global or local variable, then run some code that writes to it.
- Try ^longint(@int_variable)^  and see if that works
- get the address of the int_variable (watch @intvar) and try the ^longint($1234)^


When you use the ^($1234)^ syntax, then try "watch scope" declaration. It should work with global or declaration, bot lets make sure....


Also, enter any expression (that you want to use for a watchpoint) as a normal watch first. It should show the value at the address.
If not, then it will give you an error, and that may help finding the problem.

zamtmn

  • Hero Member
  • *****
  • Posts: 681
Re: Data\Watch Breakpoint by adress
« Reply #11 on: June 16, 2025, 07:34:38 pm »
I use trunk lazarus+fpdebug\fpc x64 on win11
test program:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. var
  3.   a:integer;
  4. begin
  5.   a:=1;
  6.   a:=2;
  7.   writeln(a);
  8. end.  
if I watch "a" - all work
if I stop on a:=1; line, look a addr (@a in evaluate\modify) and set "pinteger($0000000100014010)^" - it not work

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12207
  • Debugger - SynEdit - and more
    • wiki
Re: Data\Watch Breakpoint by adress
« Reply #12 on: June 16, 2025, 08:05:51 pm »
if I stop on a:=1; line, look a addr (@a in evaluate\modify) and set "pinteger($0000000100014010)^" - it not work

It works for me - but only if my fpc/rtl is entirely build with debug info.

Otherwise your app does not contain the type "pinteger" => so FPC does not add that to the debug info. Then the debugger does not know it either.
You can check that by adding the expression as watch, because the watch window will display you the error.

The same for
   integer(a)
"integer" is not known. Because FPC adds it under the name "longint"

Therefore ^longint($12345678)^ works. (and that is because you have and use a variable of the type longint in your program, so debug info exists)

If you add the other types (and actually use them in code, or FPC will still skip them) then you can also use them in the debugger.



P.s. make sure to delete old watchpoints from the "breakpoint window"

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12207
  • Debugger - SynEdit - and more
    • wiki
Re: Data\Watch Breakpoint by adress
« Reply #13 on: June 16, 2025, 08:09:46 pm »
If you create a watchpoint
  pinteger($1234)^

and it does not work because of "pinteger" not being known, then the icon in front of the watchpoint (breakpoint window) will be red, but with a cross "X" in it. That indicates there is an error. (Make the state column wider, and you see the watchpoint is marked "invalid".

zamtmn

  • Hero Member
  • *****
  • Posts: 681
Re: Data\Watch Breakpoint by adress
« Reply #14 on: June 16, 2025, 08:24:31 pm »
Thanks for the clarifications! now everything is working

It seems to me that this is very unobvious, even though I have some experience, I was led astray (( it seems to me that simple basic types should be added to the syntax without the need for debugging information in the compiler. It would also be very helpful to have the text of the parser error. A question\a cross\a checkmark on a circle does not clarify anything.

 

TinyPortal © 2005-2018