On an ELF system, a program consists of one executable file and zero or more shared object files. To execute such a program, the system uses those files to create a process image in memory. A process image has segments which contain executable instructions, data and so on. For an ELF file to be loaded into memory, it has to have a program header which is an array of structures which describe segments and other information which the system needs to prepare the program for execution.
A segment consists of sections, which is the most important aspect of ELF from the programmer's point of view.
Each executable or shared object file generally contains a section table, which is an array of structure describing the sections inside the ELF object file. There are several special sections defined by the ELF documentations which hold program and control information. The following ones are very useful to programmers.
The .init and .fini sections have a special purpose. If a function is placed in the .init section, the system will execute it before the main function. Also the functions placed in the .fini section will be executed by the system after the main function returns. This feature is utilized by compilers to implement global constructors and destructors in C++.
When an ELF executable is executed, the system will load in all the shared object files before transferring control to the executable. With the properly constructed .init and .fini sections, constructors and destructors will be called in the right order.