Skip to main content
Engineering LibreTexts

8.4: ELF Executables

  • Page ID
    77158
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    Executables are of course one of the primary uses of the ELF format. Contained within the binary is everything required for the operating system to execute the code as intended.

    Since an executable is designed to be run in a process with a unique address space (see Chapter 6, Virtual Memory) the code can make assumptions about where the various parts of the program will be loaded in memory. Example 8.10, “Segments of an executable file” shows an example using the readelf tool to examine the segments of an executable file. We can see the virtual addresses at which the LOAD segments are required to be placed at. We can further see that one segment is for code — it has read and execute permissions only — and one is for data, unsurprisingly with read and write permissions, but importantly no execute permissions (without execute permissions, even if a bug allowed an attacker to introduce arbitrary data the pages backing it would not be marked with execute permissions, and most processors will hence disallow any execution of code in those pages).

    Example 8.10. Segments of an executable file
      1 $ readelf --segments /bin/ls
        
        Elf file type is EXEC (Executable file)
        Entry point 0x4046d4
      5 There are 8 program headers, starting at offset 64
        
        Program Headers:
          Type           Offset             VirtAddr           PhysAddr
                         FileSiz            MemSiz              Flags  Align
     10   PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                         0x00000000000001c0 0x00000000000001c0  R E    8
          INTERP         0x0000000000000200 0x0000000000400200 0x0000000000400200
                         0x000000000000001c 0x000000000000001c  R      1
              [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
     15   LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                         0x0000000000019ef4 0x0000000000019ef4  R E    200000
          LOAD           0x000000000001a000 0x000000000061a000 0x000000000061a000
                         0x000000000000077c 0x0000000000001500  RW     200000
          DYNAMIC        0x000000000001a028 0x000000000061a028 0x000000000061a028
     20                  0x00000000000001d0 0x00000000000001d0  RW     8
          NOTE           0x000000000000021c 0x000000000040021c 0x000000000040021c
                         0x0000000000000044 0x0000000000000044  R      4
          GNU_EH_FRAME   0x0000000000017768 0x0000000000417768 0x0000000000417768
                         0x00000000000006fc 0x00000000000006fc  R      4
     25   GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                         0x0000000000000000 0x0000000000000000  RW     8
        
         Section to Segment mapping:
          Segment Sections...
     30    00     
           01     .interp 
           02     .interp .note.ABI-tag .note.gnu.build-id .hash .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 
           03     .ctors .dtors .jcr .dynamic .got .got.plt .data .bss 
           04     .dynamic 
     35    05     .note.ABI-tag .note.gnu.build-id 
           06     .eh_frame_hdr 
           07     
        

    The program segments must be loaded at these addresses; the last step of the linker is to resolve most relocations (the section called “Symbols and Relocations”) and patch them with the assumed absolute addresses — the data describing the relocation is then discarded in the final binary and there is no longer a way to find this information.

    In reality, executables generally have external dependencies on shared libraries, or pieces of common code abstracted and shared among the entire system — almost all of the confusing parts of Example 8.10, “Segments of an executable file” relate to the use of shared libraries. Libraries are discussed in the section called “Libraries”, dynamic libraries in Chapter 9, Dynamic Linking.


    This page titled 8.4: ELF Executables is shared under a CC BY-SA 3.0 license and was authored, remixed, and/or curated by Ian Wienand via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.

    • Was this article helpful?