title: Symbol addresses during load-time linking vs run-time linking in Linux
body: <p>I am trying to understand the difference in the mechanisms underlying load-time linking (using <code>gcc -l</code>) versus run-time linking (using <code>dlopen(), dlsym()</code>) of dynamic libraries in Linux, and how these mechanisms affect the state of the library and the addresses of its symbols.</p>
  <h1>The experiment</h1>
  <p>I have three simple files:</p>
  <p>libhello.c:</p>
  <pre><code>int var;
  int func() {
      return 7;
  }
  </code></pre>
  <p>libhello.h:</p>
  <pre><code>extern int var;
  int func();
  </code></pre>
  <p>main.c:</p>
  <pre><code>#include &lt;inttypes.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdint.h&gt;
  #include &lt;dlfcn.h&gt;
  #include &quot;libhello.h&quot;
  
  int main() {
      void* h = dlopen(&quot;libhello.so&quot;, RTLD_NOW);
      printf(&quot;Address  Load-time linking    Run-time linking\n&quot;);
      printf(&quot;-------  -----------------    ----------------\n&quot;);
      printf(&quot;&amp;var     0x%016&quot; PRIxPTR &quot;   0x%016&quot; PRIxPTR &quot;\n&quot;, (uintptr_t)&amp;var , (uintptr_t)dlsym(h, &quot;var&quot; ));
      printf(&quot;&amp;func    0x%016&quot; PRIxPTR &quot;   0x%016&quot; PRIxPTR &quot;\n&quot;, (uintptr_t)&amp;func, (uintptr_t)dlsym(h, &quot;func&quot;));
  }
  </code></pre>
  <p>I compile libhello.c with the command <code>gcc -shared -o libhello.so -fPIC libhello.c</code></p>
  <p>I compile main.c with the command <code>gcc main.c -L. -lhello -ldl</code></p>
  <h1>The observation</h1>
  <p>Running the main.c executable prints something like this:</p>
  <pre><code>Address  Load-time linking    Run-time linking
  -------  -----------------    ----------------
  &amp;var     0x0000000000601060   0x00007fdb4acb1034
  &amp;func    0x0000000000400700   0x00007fdb4aab0695
  </code></pre>
  <p>The load-time linking addresses remain the same, but the run-time linking addresses change every run.</p>
  <h1>The questions</h1>
  <ol>
  <li>Why do the run-time addresses change every run? Do they change due to <a href="https://en.wikipedia.org/wiki/Address_space_layout_randomization" rel="noreferrer">Address space layout randomization</a>?</li>
  <li>If this is the case, why don't addresses change for load-time linking? Isn't load-time linking vulnerable to the same attacks that address randomization aims to protect against?</li>
  <li>In the above program, the same library is loaded twice - once at load-time and then at run-time using <code>dlopen()</code>. The second load does not copy the state of the first load. I.e. if the value of <code>var</code> is changed before <code>dlopen()</code>, this value isn't reflected in the version of <code>var</code> loaded via <code>dlsym()</code>. Is there any way to retain this state during the second load?</li>
  </ol>