SWAT Blog

Posts Tagged ‘Memory’

Dissecting Executable and Linking Format (ELF)

Friday, April 1st, 2011

ELF: Executable and Linking Format
ELF is a portable object file format defining the composition and organization of the object file. Kernel and binary loader looks at this format to know how to load this file and find various pieces of information like code, initialized data, dependencies on shared libraries etc.

Types of Object files

  1. Relocatable files – holds code and data suitable to link with other object files
  2. Executable files – suitable for execution
  3. Shared object files – holds code and data suitable to link with other relocatable object or shared objects
    Object files are created by the assembler and link editor, object files are binary representations of programs intended to execute directly on a processor. 

    File Format

    Object files participate in program linking (building a program) and program execution (running a program). For convenience and efficiency, the object file format provides parallel views of a file’s contents, reflecting the differing needs of these activities.

    • ELF Header: Holds the roadmap describing the file’s organization
      Sections: Holds code/instructions, data, symbol table, relocation information, etc.
    • Program header table: Holds information to create a process image.Program header table is an array of structures, each describing a segment or other information the system needs to prepare the program for execution. An object file segment contains one or more sections
    • Section Header table: Section is an area in the object file that contains information which is useful for linking: program’s code, program’s data (variables, array, string), relocation information and other. So, in each area, several information is grouped and it has a distinct meaning: code section only hold code, data section only holds initialized or non-initialized data, etc.
    • Segments: An object file segment contains one or more sections. Segements are of variuos types – loadable, dynamic, etc.

    Dissecting an ELF

    We will start with a small C program to dissect ELF.

    #include <stdio.h>
    #include <stdlib.h>
    
    int globalVariableAssigned = 10;
    int globalVariableUnassigned;
    
    int main(int argc, char **argv){
    	int localVariable = 100;
    	printf("ELF test Coden");
    	printf("globalVariableAssigned = %dn", globalVariableAssigned);
    	printf("globalVariableUnassigned = %dn", globalVariableUnassigned);
    	printf("localVariable = %dn", localVariable);
    	return EXIT_SUCCESS;
    }

    Compile the above program

    $ gcc -o elf.o elf.c

    Now we’ll use readelf to look into the object file elf.o in more detail.

    • Looking at the ELF Header
      $ readelf -h elf.o
      • ELF Header: Holds the roadmap describing the file’s organization
        Sections: Holds code/instructions, data, symbol table, relocation information, etc.
      • Program header table: Holds information to create a process image.Program header table is an array of structures, each describing a segment or other information the system needs to prepare the program for execution. An object file segment contains one or more sections
      • Section Header table: Section is an area in the object file that contains information which is useful for linking: program’s code, program’s data (variables, array, string), relocation information and other. So, in each area, several information is grouped and it has a distinct meaning: code section only hold code, data section only holds initialized or non-initialized data, etc.
      • Segments: An object file segment contains one or more sections. Segements are of variuos types – loadable, dynamic, etc.
        • The executable is created for Advanced Micro Devices X86-64 (Machine field)
        • The object is a relocatable object file (Type field)
        • The program has 25 sections
      • Looking at the ELF Header

        $ readelf -h elf.o

        Thue output is as follows on my 64 bit machine:

        ELF Header:
          Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
          Class:                             ELF64
          Data:                              2's complement, little endian
          Version:                           1 (current)
          OS/ABI:                            UNIX - System V
          ABI Version:                       0
          Type:                              REL (Relocatable file)
          Machine:                           Advanced Micro Devices X86-64
          Version:                           0x1
          Entry point address:               0x0
          Start of program headers:          0 (bytes into file)
          Start of section headers:          22296 (bytes into file)
          Flags:                             0x0
          Size of this header:               64 (bytes)
          Size of program headers:           0 (bytes)
          Number of program headers:         0
          Size of section headers:           64 (bytes)
          Number of section headers:         25
          Section header string table index: 22

        Few interesting things that the header highlights:

      • Listing sections
        Below is the stripped out version of the output listing all 25 sections:

        Section Headers:
          [Nr] Name              Type             Flags  Link  Info  Align
          [ 0]                   NULL             	   0	 0     0
          [ 1] .text             PROGBITS         AX       0     0     4
          [ 2] .rela.text        RELA                     23     1     8
          [ 3] .data             PROGBITS         WA       0     0     4
          [ 4] .bss              NOBITS           WA       0     0     4
          [ 5] .debug_abbrev     PROGBITS                  0     0     1
          [ 6] .debug_info       PROGBITS                  0     0     1
          [ 7] .rela.debug_info  RELA                     23     6     8
          [ 8] .debug_line       PROGBITS                  0     0     1
          [ 9] .rela.debug_line  RELA                     23     8     8
          [10] .debug_macinfo    PROGBITS                  0     0     1
          [11] .rodata           PROGBITS         A       0     0     8
          [12] .debug_loc        PROGBITS                  0     0     1
          [13] .debug_pubnames   PROGBITS                  0     0     1
          [14] .rela.debug_pubna RELA                     23    13     8
          [15] .debug_aranges    PROGBITS                  0     0     1
          [16] .rela.debug_arang RELA                     23    15     8
          [17] .debug_str        PROGBITS         MS       0     0     1
          [18] .comment          PROGBITS         MS       0     0     1
          [19] .note.GNU-stack   PROGBITS                  0     0     1
          [20] .eh_frame         PROGBITS          A       0     0     8
          [21] .rela.eh_frame    RELA                     23    20     8
          [22] .shstrtab         STRTAB                    0     0     1
          [23] .symtab           SYMTAB                   24    17     8
          [24] .strtab           STRTAB                    0     0     1

        Most notable are:

        • “.text” which has a “X” or executable flag against it.
          To find out what is contained in this section we can take an object dump of this section

          $ objdump -d -j .text elf.o

          And the output is indeed the machine code of main() function. see partial output below:

          0000000000000000 <main>:
             0:	55                   	push   %rbp
             1:	48 89 e5             	mov    %rsp,%rbp
             4:	48 83 ec 20          	sub    $0x20,%rsp
             8:	89 7d ec             	mov    %edi,-0x14(%rbp)
             b:	48 89 75 e0          	mov    %rsi,-0x20(%rbp)
             f:	c7 45 fc 64 00 00 00 	movl   $0x64,-0x4(%rbp)
            16:	bf 00 00 00 00       	mov    $0x0,%edi
          ...
          ...
            66:	e8 00 00 00 00       	callq  6b <main+0x6b>
            6b:	b8 00 00 00 00       	mov    $0x0,%eax
            70:	c9                   	leaveq
            71:	c3                   	retq   
        • “.data” section hold all the initialized global variables inside the program that do not live inside the stack.
          To find out what is contained in this section we can take an object dump of this section

          $ objdump -d -j .data elf.o

          And output shows one assigned variable, which actually is variable globalVariableAssigned in the test program

          Disassembly of section .data:
          
          0000000000000000 <globalVariableAssigned>:
             0:	0a 00 00 00                                         ....
        • “.bss” – BSS (Block Started by Symbol) is a section where all unitialized variables are mapped. You can find out the content of this section using objdump. I am not going to to save some formatting on the blog. :)
  • © 2004-2015 Special Work & Technology Limited