cmemorylinkerobject-files

memory sharing in .o file


Lets say i have a A.c file and compile it to a A.o file. The A.c file is as follows:

int a;
void add(void)
{
}

The A.o file together with a B.o form a 1.exe file. The A.o file together with a C.o form a 2.exe file.

My question if I run 1.exe and 2.exe at the same time, will the address of a and add() be the same for these two .exe file? In another word, are there two A.o in the memory or there is only one?


Solution

  • You don't have any relocated object files in memory.

    I am guessing you have a Linux system. If on Windows, the principles remain the same, but the details are different.

    The linker (called to build both 1.exe and 2.exe) build an executable ELF file (made of several segments, notably the so called "text" segment for machine code and read-only constant data, and the "data" segment for mutable data). The execve(2) syscall starting that program is memory mapping several segments of the ELF file (nearly as would some mmap(2) syscall).

    Notice that using .exe file suffix for Linux executable files is confusing and uncommon. Conventionally, Linux executables have no suffix at all and start with a lowercase letter.

    The linker has copied and relocated both A.o files into different things (because of the relocation). So it usually happens that the address of a or add is different in 1.exe and in 2.exe, and so are the machine instructions dealing with them.

    Each process has its own address space (which can change with e.g. mmap(2) syscall). Type cat /proc/1234/maps to understand the address space of process of pid 1234. Try also cat /proc/self/maps to get the address space of the process running that cat.

    If instead of A.o object you have a shared object (or dynamic library) libA.so some of its (mmap-ed) segments will be shared (and others would be using copy on write techniques), and some relocation happens at dynamic link time (e.g. during dlopen if it is a plugin).

    Read also Levine's book on Linkers and Loaders.