6

Why is it that when running code from gdb, I get the same addresses for the variables declared, but while just executing the binary I don't get the same addresses.

#include<stdio.h>
void main()
{
    int *x,q;
    //I saw the address of the variable q in this program through gdb during the __1st__ execution.
    //I re-compiled the program to make x to point to this address.
    x=0x7fffffffe2bc; 
    *x=3;
    printf("%d",(*x));
}

I ran the program through gdb and it never Segfaulted.

$ gdb -q ./a.out  
Reading symbols from /home/eknath/needed2/a.out...done.  
(gdb) r  
Starting program: /home/eknath/needed2/a.out   
3
Program exited normally.  
(gdb) q  
$

But normal execution of the program always produces a SEGFAULT.

$ ./a.out   
Segmentation fault

I don't know if this question is a duplicate of Is this always the address for GDB debug program?

NOTE: I have not switched off ASLR

Community
  • 1
  • 1
Lelouch Lamperouge
  • 8,171
  • 8
  • 49
  • 60
  • See also: [c++ - Difference between gdb addresses and "real" addresses? - Stack Overflow](https://stackoverflow.com/questions/10061475/difference-between-gdb-addresses-and-real-addresses) – user202729 Dec 19 '21 at 03:08

2 Answers2

2

The reason you always get the same address for local variables while running under GDB is that GDB (in order to simplify most debugging scenarios) disables address space randomization.

You can ask GDB to not do that with set disable-address-randomization off.

For curious, disabling of address randomization for the current process does not require any privilege, and is done by calling personality(2). Here is the patch that added this feature.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
0

EDIT: Let me clarify my point as it may not have been clear. GDB by default disables ASLR so your variables will always have the same address (unless the code is change, adding variables or code before or even after in some cases can cause shifts in the assigned addresses and cause that to fail). This way your code succeeds because hardcoded addresses will be in the same spot while running in GDB. This helps in debugging because addresses will not change from debugging session to debugging session.

Jesus Ramos
  • 22,940
  • 10
  • 58
  • 88
  • So effectively, gdb switches off ASLR? – Lelouch Lamperouge Oct 11 '11 at 01:30
  • Yeah and some other things as well but for your question ASLR is the important bit. It also only allows 2 concurrent threads (older versions at least cant speak about newer ones) and has some other limitations. – Jesus Ramos Oct 11 '11 at 01:30
  • But I don't understand how it could do that. I mean ASLR can be set/unset only through sysctls or other privileged means, right? How does gdb, without root privileges or setuid, manages to do this? – Lelouch Lamperouge Oct 11 '11 at 01:32
  • GDB uses ptrace in its implementation and when a process is being traced there are options that can be set. – Jesus Ramos Oct 11 '11 at 01:33
  • Oh, nice. Can you show me some official documentation? I'd like to know more about this in greater detail. – Lelouch Lamperouge Oct 11 '11 at 01:34
  • http://www.gnu.org/s/gdb/current/ I just read the code :) I also happened to write some code using ptrace myself so I know some of it's caveats. I'm sure there's some technical docs buried somewhere in there. – Jesus Ramos Oct 11 '11 at 01:46
  • Large parts of this answer are completely bogus. – Employed Russian Oct 11 '11 at 03:07
  • @EmployedRussian Such as? As I said, some of these may not apply as I haven't read the GDB source code in years now, could you please clarify. – Jesus Ramos Oct 11 '11 at 03:08
  • "GDB loads all variables into memory before calling a function" -- GDB does no such thing; the program itself does (with or without GDB). "guarantees a certain order which is why" -- again GDB does no such thing. – Employed Russian Oct 11 '11 at 03:13
  • @EmployedRussian GDB loads all variables within the function scope into memory even if they are defined within an if block such as if (cond) { int mvar; ... }. – Jesus Ramos Oct 11 '11 at 03:15
  • @EmployedRussian By disabling ASLR it guarantees a certain order for memory addresses (single threaded) which is why his program will work only in gdb. Provided ASLR is kept disabled and the program is not changed in certain ways. – Jesus Ramos Oct 11 '11 at 03:22
  • @JesusRamos This isn't a place to have a prolonged discussion, but believe me, you are completely mistaken about what happens in GDB, and what happens in the debugged process. – Employed Russian Oct 11 '11 at 03:22
  • @EmployedRussian I may have picked my words incorrectly but the point I was trying to make is that BY DEFAULT gdb in his case will cause that to work because it disables ASLR – Jesus Ramos Oct 11 '11 at 03:25
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/4154/discussion-between-employed-russian-and-jesus-ramos) – Employed Russian Oct 11 '11 at 03:29