title: Why use the Global Offset Table for symbols defined in the shared library itself?
body: <p>Consider the following simple shared library source code:</p>
  
  <p><em>library.cpp:</em></p>
  
  <pre class="lang-cpp prettyprint-override"><code>static int global = 10;
  
  int foo()
  {
      return global;
  }
  </code></pre>
  
  <p>Compiled with <code>-fPIC</code> option in clang, it results in this object assembly (x86-64):</p>
  
  <pre><code>foo(): # @foo()
    push rbp
    mov rbp, rsp
    mov eax, dword ptr [rip + global]
    pop rbp
    ret
  global:
    .long 10 # 0xa
  </code></pre>
  
  <p>Since the symbol is defined inside the library, the compiler is using a PC relative addressing as expected: <code>mov eax, dword ptr [rip + global]</code></p>
  
  <p>However if we change <code>static int global = 10;</code> to <code>int global = 10;</code> making it a symbol with external linkage, the resulting assembly is:</p>
  
  <pre><code>foo(): # @foo()
    push rbp
    mov rbp, rsp
    mov rax, qword ptr [rip + global@GOTPCREL]
    mov eax, dword ptr [rax]
    pop rbp
    ret
  global:
    .long 10 # 0xa
  </code></pre>
  
  <p>As you can see the compiler added a layer of indirection with the Global Offset Table, which seems totally unnecessary in this case as the symbol is still defined inside the same library (and source file).</p>
  
  <p>If the symbol was defined in <strong>another</strong> shared library, the GOT would be necessary, but in this case it feels redundant. Why is the compiler still adding this symbol to the GOT? </p>
  
  <p>Note: I believe <a href="https://stackoverflow.com/questions/27449376/what-is-the-point-of-the-global-offset-table">this question</a> is similiar to this, however the answer was not pertinent maybe due to a lack of details.</p>