title: Understanding Linker Version Scripts
body: <p>I am trying to understand version script that is being used for resolving duplicate symbol problem.</p>
  
  <p>I have created a main_demo.c file with the following content</p>
  
  <pre><code>#include&lt;stdio.h&gt;
  
  extern void fun1_std(void);
  extern void fun1_linux(void);
  
  
  int main ()
  {
      fun1_linux(); //defined under libfun1_linux.c
      fun1_std();   //defined under libfun2_std.c
      return 0;
  }
  </code></pre>
  
  <p>Content of libfun1_std.c </p>
  
  <pre><code>#include&lt;stdio.h&gt;
  
  extern void fun (void);
  void fun1_std()
  
  {
      fun();  
  }
  </code></pre>
  
  <p>Content of libfun1_linux.c</p>
  
  <pre><code>#include&lt;stdio.h&gt;
  
  extern void fun (void);
  void fun1_linux()
  
  {
      fun();
  }
  </code></pre>
  
  <p>Now , I have created shared object for both the above files (which are calling fun()) named as libfun1_std.so and libfun1_linux.so respectively. The function "fun()" is defined under two shared objects that looks like the following:</p>
  
  <pre><code>//library name ==&gt; libfun2_linux.so 
  #include &lt;stdio.h&gt;
  
  void fun()
  {
      printf("In fun of libfun2_linux\n");
      //Similarly libfun2_std.so is printing "In fun of libfun2_std" 
  }
  </code></pre>
  
  <p>My expectation is that symbol "fun" used in libfun1_linux.so is resolved by libfun2_linux.so and similarly "fun" used in libfun2_std.so is resolved by libfun2_std.so</p>
  
  <p>As we can see if we create a executable/process by linking the main program with all the above shared libraries, process will get duplicate symbol in it's address space i.e, fun(). SO the output look like this:</p>
  
  <pre><code>In fun of libfun2_std
  
  In fun of libfun2_std
  </code></pre>
  
  <p>To resolve this I have created a version script that will rename the symbol. 
  Content of version script:</p>
  
  <pre><code>LIBFUN2_STD_1.0 {
  global: *; //i.e, every symbol is global
  };
  </code></pre>
  
  <p>and compiled libfun2_std.so with this version script. 
  Let's see the symbol again:-</p>
  
  <pre><code> $ readelf -a libfun2_std.so | grep fun
  13: 0000000000000735    18 FUNC    GLOBAL DEFAULT   12 fun@@LIBFUN2_STD_1.0
  35: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS libfun2_std.c
  48: 0000000000000735    18 FUNC    GLOBAL DEFAULT   12 fun
  000000: Rev: 1  Flags: BASE   Index: 1  Cnt: 1  Name: libfun2_std.so
  </code></pre>
  
  <p>Also the content of caller library</p>
  
  <pre><code>nm libfun1_std.so | grep fun
  0000000000000705 T fun1_std
                   U fun@@LIBFUN2_STD_1.0.
  </code></pre>
  
  <p>So now it seems that we have resolved the duplicate symbol. Let's create the main executable again</p>
  
  <pre><code>gcc -Wall -o main_demo main_demo.c -lfun1_std -lfun2_std -lfun1_linux - 
  lfun2_linux
  </code></pre>
  
  <p>But during execution I got the follwing result again:</p>
  
  <pre><code>In fun of libfun2_std
  
  In fun of libfun2_std
  </code></pre>
  
  <p>Lets see the content of readelf for libfun2_linux.so </p>
  
  <pre><code> $ readelf -a libfun2_linux.so | grep fun
  13: 00000000000006b5    18 FUNC    GLOBAL DEFAULT   11 fun
  34: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS libfun2_linux.c
  47: 00000000000006b5    18 FUNC    GLOBAL DEFAULT   11 fun
  </code></pre>
  
  <p>Question:-</p>
  
  <ol>
  <li><p>Why having version script for one library is not sufficient as now symbols are different? If we create two version script (one for libfun2_linux.so) it is working fine.</p></li>
  <li><p>How version script works? (Read some links which explain that it works by creatig trees but didnot get it completely). Please suggest some link where it is clearly explained.</p></li>
  </ol>