Reputation: 1608
I have a simple C program:
#include <stdio.h>
int main()
{
int i;
for(i = 0; i < 10; i++)
printf("Hello\n");
return 0;
}
I compile it using gcc:
gcc -g test.c
Then I run the debugger:
gdb -q ./a.out
I set a breakpoint at main and run:
(gdb) break main
(gdb) run
I then let it run until it hits the breakpoint and try to display the assembly instruction at the address rip is currently pointing:
(gdb) x/i $rip
=> 0x400538 <main+8>: mov DWORD PTR [rbp-0x4],0x0
It looks like the next instruction is going to initialize my local variable i with the value 0. Since it hasn't executed the instruction yet, I'd expect a garbage value to be there.
(gdb) x/4xb $rbp-4
0x7fffffffe0ec: 0x00 0x00 0x00 0x00
It doesn't look like garbage values, it looks like everything has already been zero'd out. The breakpoint should halt the program before any of the code in main is executed.
What am I missing here? Shouldn't that memory location contain random garbage values before the local variable i is initialized?
Upvotes: 3
Views: 646
Reputation:
It doesn't look like garbage values, it looks like everything has already been zero'd out.
I modified your example in order to show that it is just a coincidence.
#include <stdio.h>
int main()
{
int i1;
int i2;
int i3;
int i4;
int i5;
int i6;
int i;
for(i = 0; i < 10; i++)
printf("Hello\n");
return 0;
}
(gdb) start
Temporary breakpoint 1 at 0x4005ac: file main.cpp, line 13.
Starting program: /home/a.out
Temporary breakpoint 1, main () at main.cpp:13
13 for(i = 0; i < 10; i++)
(gdb) info locals
i1 = 0
i3 = 0
i5 = 32767
i = 0
i2 = 4195520
i4 = -7856
i6 = 0
You see, different values are possible.
As for your example the value at this address changes at least twice before reaching main()
. Just set watch
for this address and you will see that it is changed in functions called before main():
(gdb) watch *(int*)0x7fffffffe06c
Hardware watchpoint 1: *(int*)0x7fffffffe06c
(gdb) r
Starting program: /home/a.out
Hardware watchpoint 1: *(int*)0x7fffffffe06c
Old value = 0
New value = 58
0x0000003a1d890880 in handle_intel () from /lib64/libc.so.6
Hardware watchpoint 1: *(int*)0x7fffffffe06c
Old value = 58
New value = 0
0x0000003a1d0146fd in _dl_runtime_resolve () from /lib64/ld-linux-x86-64.so.2
Hardware watchpoint 1: *(int*)0x7fffffffe06c
Old value = 0
New value = 1
0x00000000004005c3 in main () at main.cpp:7
7 for(i = 0; i < 10; i++)
#0 0x00000000004005c3 in main () at main.cpp:7
Upvotes: 3
Reputation: 37944
It doesn't look like garbage values
Zero in this context is just a special case of "garbage value" (or more properly indeterminate value), that you can't rely on in any case, here is a slightly modified example, that produces different value on my compiler (gcc 4.4.7
):
#include <stdio.h>
int main(void)
{
int i, j, k;
for(i = 0; i < 10; i++)
printf("Hello\n");
return 0;
}
and gdb
session:
Breakpoint 1, main () at check.c:6
6 for(i = 0; i < 10; i++)
(gdb) x/i $pc
=> 0x4004cc <main+8>: mov DWORD PTR [rbp-0xc],0x0
(gdb) x/4xb $rbp-0xc
0x7fffffffe124: 0xff 0x7f 0x00 0x00
Good analogy for that might be random number generator, that returns zero. Zero is the same random value just as 112
or 377
.
Upvotes: 1
Reputation: 214310
A garbage value might be anything, including the value 0. The contents of that local variable are undefined, until the point where it is assigned a value. You cannot expect the contents to be of a certain kind before that happens.
It is however quite common that a zero-out is done on all local variables during debug builds. If this is the case with gdb, I have no idea. You could try printing the contents of the variable before it is initialized, then make a release build with no debugger and see if the behavior is the same.
More likely though, the compiler made the decision to initialize the variable earlier than the actual line i=0. A compiler is free to change the order in which the program is executed, if it can determine that doing so won't affect the program results. The compiler might have moved the zero-out to an earlier point in the program for performance reasons.
Upvotes: 2
Reputation: 215397
You misunderstand what is meant by "garbage" (which is not even a formal term). Uninitialized objects in C have indeterminate value. This does not mean the value is random, much less that it has any value as entropy (there was actually a huge OpenSSL/Debian fiasco over this misunderstanding long before Heartbleed happened and everyone realized what a mess OpenSSL was). All it means is that you cannot use the value. If you do, you don't have a valid C program but a meaningless one, and there's no point in trying to reason about what it does (except possibly if you're an attacker trying to exploit a vulnerability in the program).
Upvotes: 1