In my program, there is a point where it compares a variable (stored at rbp-0x84) to 0x1. However, when I go to view what is there, I get conflicting results.
gef➤ x/w $rbp-0x84
0x7fffffffdf5c: 0x00000000
gef➤ x/g $rbp-0x84
0x7fffffffdf5c: 0x0000000500000000
How does the first 8 bits change from 0x0 to 0x5?
Which leads me to my next problem... when I try:
gef➤ set $rbp-0x84 = 0x1
gef➤ x $rbp-0x84
0xffffffffffffff7d: Cannot access memory at address 0xffffffffffffff7d
How did the address go from 0x7fffffffdf5c to 0xffffffffffffff7d?
The low 32 bits of 0x0000000500000000
are all zeros. x86 is little-endian. The first 8 bits of the high gdb-work (x86 dword) in the gdb-giant (x86 qword) is 5.
Dump as single bytes to see this, like x /8xb
Since $rbp - 0x84
is 0xff...
, it appears that set $rbp-0x84 = 0x1
modified RBP (the register itself) to some small number, so x $rbp-0x84
wraps.
It's not going to modify memory because you didn't dereference it as a pointer value, like *(long*)($rbp-0x84) = 1
. x
contains an implicit dereference (it takes a pointer arg and shows you memory). set
and print
don't.
I'm surprised it worked at all with an expression on the left hand side of an assignment, though. That isn't allowed in C, but apparently GDB allows it. In fact I tested and it produces $rbp = 1
in GDB 9.1.
After this change to RBP, $rbp - 0x84
is a number just below 0
, i.e. 0xff..... Notice that it's not 0x7f...
anymore, and that it's wider1. This page is not mapped. (And fun fact; Linux will never let you map that virtual page even in the kernel because values in that range are treated as error codes, not valid pointers.)
footnote 1: User-space virtual addresses are at most 47 bits wide (until PML5 CPUs with so much RAM that the OS chooses to use an extra level of page tables). Linux puts the stack near the top of that.
User contributions licensed under CC BY-SA 3.0