Can I set a breakpoint on 'memory access' in GDB?
watch only breaks on write, rwatch let you break on read, and awatch let you break on read/write.
You can set read watchpoints on memory locations:
gdb$ rwatch *0xfeedface
Hardware read watchpoint 2: *0xfeedface
but one limitation applies to the rwatch and awatch commands; you can't use gdb variables
in expressions:
gdb$ rwatch $ebx+0xec1a04f
Expression cannot be implemented with read/access watchpoint.
So you have to expand them yourself:
gdb$ print $ebx
$13 = 0x135700
gdb$ rwatch *0x135700+0xec1a04f
Hardware read watchpoint 3: *0x135700 + 0xec1a04f
gdb$ c
Hardware read watchpoint 3: *0x135700 + 0xec1a04f
Value = 0xec34daf
0x9527d6e7 in objc_msgSend ()
Edit: Oh, and by the way. You need either hardware or software support. Software is obviously much slower. To find out if your OS supports hardware watchpoints you can see the can-use-hw-watchpoints environment setting.
gdb$ show can-use-hw-watchpoints
Debugger's willingness to use watchpoint hardware is 1.
Can I have gdb break on read/write from an address?
Yes.
Using Watchpoints:
watch - only breaks on write (and only if the value changes)
rwatch - breaks on read, and
awatch - breaks on read/write.
A more detailed brief from some internet sources:
watch
watch is gdb’s way of setting data breakpoints which will halt the execution of a program if memory changes at the specified location.
watch breakpoints can either be set on the variable name or any address location.
watch my_variable
watch *0x12345678
where 0x12345678 is a valid address.
rwatch
rwatch (read-watch) breakpoints break the execution of code when the program tries to read from a variable or memory location.
rwatch iWasAccessed
rwatch *0x12345678
where 0x12345678 is a valid address.
awatch
awatch or access watches break execution of the program if a variable or memory location is written to or read from. In summary, awatches are watches and rwatches all in one. It is a handy way of creating one breakpoint than two separate ones.
awatch *0x12345678
where 0x12345678 is a valid address.
GDB set breakpoint in function offset
(gdb) p &foo
$1 = (<text variable, no debug info> *) 0x555555555129 <foo>
(gdb) b *foo+0x10
Breakpoint 2 at 0x555555555139
QED.
GDB Cannot insert breakpoint, Cannot access memory at address XXX?
Debugging stripped code is probably very much useless (except for reverse engineering), but you can cause gdb
to stop at the very first instruction, and you are already doing this accidentally. If the address of a breakpoint cannot be mapped, gdb
stops and tells you the error. As a side effect, your program is stopped at its first instruction. An address that's guaranteed to be unmappable is 0
, so just do the following:
(gdb) b *0
Breakpoint 1 at 0x0
(gdb) r
Starting program: [...]
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x0
(gdb) disas
Dump of assembler code for function _start:
=> 0x00007ffff7ddd190 <+0>: mov %rsp,%rdi
0x00007ffff7ddd193 <+3>: callq 0x7ffff7de0750 <_dl_start>
Here you see the PC
sits at 0x00007ffff7ddd190
. So this is your entry point at runtime.
In order to be able to continue (or: single-step for example), you have to delete the offending breakpoint:
(gdb) delete
Delete all breakpoints? (y or n) y
(gdb) c
Continuing.
Credits for this answer go to this answer on reverse engineering
GDB breakpoint in main() cannot access memory
(gdb) x/24s $esp
0xffffffffffffe550: <error: Cannot access memory at address 0xffffffffffffe550>
On an x86-64 target, $rsp
should be used. Using $esp
will lead to incorrect results.
$esp
is taken from the bottom 32 bits of the 64-bit $rsp
register, and gdb treats it as type int32_t
. $rsp
in your example was probably 0x7fffffffe550
. Gdb's x
command, which wants to use a 64-bit address, will take the bottom 32 bits of $rsp
, 0xffffe550
, and sign-extend that to 0xffffffffffffe550
. That's almost certainly an invalid address; typical user-space addresses on Linux don't go above 0x7ffffffff000
or so.
Try x/24s $rsp
. If you're trying to follow exercises out of an old book, you may be able to duplicate their 32-bit examples by giving gcc the -m32
option, if it supports it. Then you can use $esp
.
Related Topics
How to Safely Pass Objects, Especially Stl Objects, to and from a Dll
What Are All the Member-Functions Created by Compiler For a Class? Does That Happen All the Time
Catching Exception: Divide by Zero
How to Handle Wrong Data Type Input
When I Change a Parameter Inside a Function, Does It Change For the Caller, Too
How to Implement the Factory Method Pattern in C++ Correctly
Officially, What Is Typename For
C++ Deprecated Conversion from String Constant to 'Char*'
How to Emulate C Array Initialization "Int Arr[] = { E1, E2, E3, ... }" Behaviour With Std::Array
How to Return an Array from a Function
Good Input Validation Loop Using Cin - C++
What Is the Best Open Xml Parser For C++
How to Determine If a String Is a Number With C++