title: Position independent executable and fixed entry point address
body: <p>A position independent ELF executable can be loaded and run from arbitrary address within the virtual address space.</p>
  <p>I tried to build below simple program:</p>
  <p><strong>pie.c</strong></p>
  <pre><code>#include &lt;stdio.h&gt;
  
  void main(void)
  {
      printf(&quot;hello, pie!\n&quot;);
  }
  </code></pre>
  <p>Build command:</p>
  <pre><code>gcc pie.c -o pie -pie
  </code></pre>
  <p>The ELF header of the executable is:</p>
  <p><strong>pie</strong>:</p>
  <pre><code>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:                              DYN (Shared object file)
    Machine:                           Advanced Micro Devices X86-64
    Version:                           0x1
    Entry point address:               0x530 &lt;================= FIXED entry point
    Start of program headers:          64 (bytes into file)
    Start of section headers:          6440 (bytes into file)
    Flags:                             0x0
    Size of this header:               64 (bytes)
    Size of program headers:           56 (bytes)
    Number of program headers:         9
    Size of section headers:           64 (bytes)
    Number of section headers:         29
    Section header string table index: 28
  </code></pre>
  <p>So the entry point address is fixed.</p>
  <p>And it is the symbol <code>_start</code> there:</p>
  <pre><code>0000000000000530 T _start
  </code></pre>
  <p>So it means the <code>_start</code> must be placed at <code>0x530</code>.</p>
  <p><strong>Isn't this contradictory to being position independent?</strong></p>
  <h2>ADD 1 - 10:44 AM 8/16/2021</h2>
  <p>I tried to build the same program without the <code>-pie</code> flag:</p>
  <pre><code>gcc pie.c -o pie_not
  </code></pre>
  <p>The generated ELF header is:</p>
  <p><strong>pie_not</strong>:</p>
  <pre><code>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:                              DYN (Shared object file)
    Machine:                           Advanced Micro Devices X86-64
    Version:                           0x1
    Entry point address:               0x530  &lt;============ Still the same value as with -pie flag
    Start of program headers:          64 (bytes into file)
    Start of section headers:          6440 (bytes into file)
    Flags:                             0x0
    Size of this header:               64 (bytes)
    Size of program headers:           56 (bytes)
    Number of program headers:         9
    Size of section headers:           64 (bytes)
    Number of section headers:         29
    Section header string table index: 28
  </code></pre>
  <p>And I further compared the built results <code>pie</code> and <code>pie_not</code>. Their binaries are identical.</p>
  <p><strong>So how could the operating system tell which one should be treated as position independent code??</strong></p>
  <h2>ADD 2 - 10:56 AM 8/16/2021</h2>
  <p>I guess I figured it out.
  It seems gcc use <code>-pie</code> by default. To avoid it, I have to add <code>-no-pie</code> flag explicitly.</p>
  <pre><code>gcc pie.c -o pie_not -no-pie
  </code></pre>
  <p>And the generated ELF header is like this:</p>
  <p><strong>pie_not</strong>:</p>
  <pre><code>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:                              EXEC (Executable file) &lt;==== File type also changed!!!
    Machine:                           Advanced Micro Devices X86-64
    Version:                           0x1
    Entry point address:               0x400400 &lt;===== Entry point address changed!
    Start of program headers:          64 (bytes into file)
    Start of section headers:          6376 (bytes into file)
    Flags:                             0x0
    Size of this header:               64 (bytes)
    Size of program headers:           56 (bytes)
    Number of program headers:         9
    Size of section headers:           64 (bytes)
    Number of section headers:         29
    Section header string table index: 28
  </code></pre>
  <p>I believe the loader relies on the Type filed in ELF header to decide how to treat the binary.</p>