Watch a memory range in gdb?

20,346

Solution 1

If you use GDB 7.4 together with Valgrind 3.7.0, then you have unlimited "emulated" hardware watchpoints.

Start your program under Valgrind, giving the arguments --vgdb=full --vgdb-error=0 then use GDB to connect to it (target remote | vgdb). Then you can e.g. watch or awatch or rwatch a memory range by doing rwatch (char[100]) *0x5180040

See the Valgrind user manual on gdb integration for more details

Solution 2

The feature that detects when a memory address has changed is called a hardware breakpoint, and it's actually a feature of the CPU — a register inside the memory controller that detects when a specific address is accessed, and triggers a debugger break interrupt. Unfortunately the x86 architecture only has four such registers and that's why you're limited in the number of memory watch breakpoints you can set.

That's why you need to use something like valgrind; if you want to watch an entire region, you have to do it by using software that simulates the memory access patterns. I don't know if valgrind actually supports watching entire memory ranges, though. You may have to patch it yourself. Modify VALGRIND_MAKE_MEM_NOACCESS() to throw a breakpoint but then allow the program to continue, maybe.

Share:
20,346
iblue
Author by

iblue

casting the runes One of ICL's most talented systems designers used to be called out occasionally to service machines which the field circus had given up on. Since he knew the design inside out, he could often find faults simply by listening to a quick outline of the symptoms. He used to play on this by going to some site where the field circus had just spent the last two weeks solid trying to find a fault, and spreading a diagram of the system out on a table top. He'd then shake some chicken bones and cast them over the diagram, peer at the bones intently for a minute, and then tell them that a certain module needed replacing. The system would start working again immediately upon the replacement. – The Jargon File, v4.4.7

Updated on February 16, 2023

Comments

  • iblue
    iblue over 1 year

    I am debugging a program in gdb and I want the program to stop when the memory region 0x08049000 to 0x0804a000 is accessed. When I try to set memory breakpoints manually, gdb does not seem to support more than two locations at a time.

    (gdb) awatch *0x08049000
    Hardware access (read/write) watchpoint 1: *0x08049000
    (gdb) awatch *0x08049001
    Hardware access (read/write) watchpoint 2: *0x08049001
    (gdb) awatch *0x08049002
    Hardware access (read/write) watchpoint 3: *0x08049002
    (gdb) run
    Starting program: /home/iblue/git/some-code/some-executable
    Warning:
    Could not insert hardware watchpoint 3.
    Could not insert hardware breakpoints:
    You may have requested too many hardware breakpoints/watchpoints.
    

    There is already a question where this has been asked and the answer was, that it may be possible to do this with valgrind. Unfortunately the answer does not contain any examples or reference to the valgrind manual, so it was not very enlightning: How can gdb be used to watch for any changes in an entire region of memory?

    So: How can I watch the whole memory region?