4

I wrote this small program today and I was blown away by the results. Here is the program


int main(int argc, char **argv)
{
 int a;
 printf("\n\tMain is located at: %p and the variable a is located at address: %p",main,&a);
 return 0;
}

on my machine the main function is always loaded at address "0x80483d4" and the address of the variable keeps on varying How does this happen? I read in operating systems that as a part of virtualization scheme the OS keeps relocating the address of instructions. So why is it that everytime I run this program that main is loaded at the same address?

thanks in advance guys.

Matt
  • 22,721
  • 17
  • 71
  • 112
user446236
  • 51
  • 1
  • 3
  • This link might be helpful: http://en.wikipedia.org/wiki/Address_space_layout_randomization . I think that the address of entrypoint is not randomized. – PeterK Sep 13 '10 at 11:18
  • @pmg: +1 for that xkcd linky... :) – t0mm13b Sep 13 '10 at 11:19
  • I added another "user defined function" into this code and suprisingly it is also loaded at the same address between consecutive executions. I ran the compiled program 4 times and this new function was loaded at "0x80483d4" everytime I executed the program!! – user446236 Sep 13 '10 at 11:24
  • 1
    Maybe it would help if you told us what Operating System you're trying that program on? ??? DOS? VMS? Symbian? – pmg Sep 13 '10 at 11:28
  • OMG sorry!! I am using arch linux kernel version "2.6.35-ARCH #1 SMP PREEMPT" and I used gcc version 4.5.1 (GCC) to compile the program using "gcc --std=gnu99 -o op address.c" Oh and I am executing the binary in "konsole" – user446236 Sep 13 '10 at 11:36
  • Function addresses cannot be randomized without impacting performance significantly (building in "PIE" mode is necessary). Randomizing the start of the stack has no cost, and is done by default on modern operating systems. If you tried a global variable, you'd find that its address will not change either. – R.. GitHub STOP HELPING ICE Sep 13 '10 at 12:25
  • Wow yes it does not!! So is this address decided during compile time itself? If yes what would happen if the pre-determined slot in the memory were not available? Like if the location is already occupied by another program? – user446236 Sep 13 '10 at 12:38

2 Answers2

8

On ELF systems such as Linux, the addresses at which the segments of normal executable files (ELF type ET_EXEC) load are fixed at compile time. Shared objects (ELF type ET_DYN) such as libraries are built to be position-independent, with their segments loadable anywhere in the address space (potentially with some restrictions on some architectures). It is possible to build executables such that they are actually ET_DYN -- these are known as "position-independent executables" (PIE), but is not a common technique.

What you are seeing is the fact that your main() function is in the fixed-address text segment of your compiled executable. Try also printing the address of a library function such as printf() after locating it via dlsym() -- if your system does support and have enabled address space layout randomization (ASLR), then you should see the address of that function change from run to run of your program. (If you just print the address of the library function by putting the reference directly in your code, what you may actually get is the address of the function's procedure lookup table (PLT) trampoline, which is statically compiled at a fixed address in your executable.)

The variable you see change address from run-to-run because it is an automatic variable created on the stack, not in statically allocated memory. Depending on OS and version, the address of the base of the stack may shift from run to run even without ASLR. If you move the variable declaration to be a global outside of your function, you see it behave the same way your main() function does.

Here's a full example -- compile with something like gcc -o example example.c -dl:

#include <stdio.h>
#include <dlfcn.h>

int a = 0;

int main(int argc, char **argv)
{
    int b = 0;
    void *handle = dlopen(NULL, RTLD_LAZY);
    printf("&main: %p; &a: %p\n", &main, &a);
    printf("&printf: %p; &b: %p\n", dlsym(handle, "printf"), &b);
    return 0;
}
llasram
  • 4,417
  • 28
  • 28
  • Yes it does! Wow you have cleared lots of things. One question still remains in my mind though, let us suppose that after compilation a function func() is to be loaded at address "X" in the memory, now what if before execution this location "X" were to be occupied by some other program? What would happen in that case? Will the program be relocated? Will it have to wait? – user446236 Sep 13 '10 at 12:53
  • In most contemporary OSes, the kernel provides every process its own virtual address space. As far as each different process is concerned, it has the entire range of addresses available user context to itself. This prevents the accidental collision you describe, and also prevents programs from maliciously interfering with each other. And if you like my answer, please upvote and accept :-). – llasram Sep 13 '10 at 13:01
  • Oh yes! How could I forget that? HAHAHAHAHA thanks a lot man you have cleared up every inch of doubt! Props! – user446236 Sep 13 '10 at 13:03
0

main(...) is a runtime start-up library code in which the operating system loads and executes each time. Have a look at the CRT (C Runtime Library) which would contain the code to do this depending on your compiler.

Another thing to bear in mind, that address - I would not worry about it too much as long as the C code works. That is a fluke pattern, by order of dependant on a number of factors such as OS load, drivers used, hardware, AntiVirus software etc...

Also, in relation to the code, if you add static variables, functions, pointers, that will change the layout of the binary code, and more importantly, the addresses of those symbols that gets loaded at run-time, will be different.

t0mm13b
  • 34,087
  • 8
  • 78
  • 110
  • Hello! I have added another user defined function into the same program and it is also loaded at the same memory address between consecutive executions of the program! Oh and I executed the program more than 4-5 times. The address of the functions changes once I recompile the code but after that it sticks to the new value! Strange isn't it? – user446236 Sep 13 '10 at 11:42
  • 1
    The CRT is interesting, but not relevant here -- `main()` is defined in the provided code. – llasram Sep 13 '10 at 12:27