<!DOCTYPE HTML> <html lang="en" class="light" dir="ltr"> <head> <!-- Book generated using mdBook --> <meta charset="UTF-8"> <title>symbol versioning - Notes</title> <!-- Custom HTML head --> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="theme-color" content="#ffffff"> <link rel="icon" href="../favicon.svg"> <link rel="shortcut icon" href="../favicon.png"> <link rel="stylesheet" href="../css/variables.css"> <link rel="stylesheet" href="../css/general.css"> <link rel="stylesheet" href="../css/chrome.css"> <link rel="stylesheet" href="../css/print.css" media="print"> <!-- Fonts --> <link rel="stylesheet" href="../FontAwesome/css/font-awesome.css"> <link rel="stylesheet" href="../fonts/fonts.css"> <!-- Highlight.js Stylesheets --> <link rel="stylesheet" href="../highlight.css"> <link rel="stylesheet" href="../tomorrow-night.css"> <link rel="stylesheet" href="../ayu-highlight.css"> <!-- Custom theme stylesheets --> </head> <body class="sidebar-visible no-js"> <div id="body-container"> <!-- Provide site root to javascript --> <script> var path_to_root = "../"; var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light"; </script> <!-- Work around some values being stored in localStorage wrapped in quotes --> <script> try { var theme = localStorage.getItem('mdbook-theme'); var sidebar = localStorage.getItem('mdbook-sidebar'); if (theme.startsWith('"') && theme.endsWith('"')) { localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1)); } if (sidebar.startsWith('"') && sidebar.endsWith('"')) { localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1)); } } catch (e) { } </script> <!-- Set the theme before any content is loaded, prevents flash --> <script> var theme; try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { } if (theme === null || theme === undefined) { theme = default_theme; } var html = document.querySelector('html'); html.classList.remove('light') html.classList.add(theme); var body = document.querySelector('body'); body.classList.remove('no-js') body.classList.add('js'); </script> <input type="checkbox" id="sidebar-toggle-anchor" class="hidden"> <!-- Hide / unhide sidebar before it is displayed --> <script> var body = document.querySelector('body'); var sidebar = null; var sidebar_toggle = document.getElementById("sidebar-toggle-anchor"); if (document.body.clientWidth >= 1080) { try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { } sidebar = sidebar || 'visible'; } else { sidebar = 'hidden'; } sidebar_toggle.checked = sidebar === 'visible'; body.classList.remove('sidebar-visible'); body.classList.add("sidebar-" + sidebar); </script> <nav id="sidebar" class="sidebar" aria-label="Table of contents"> <div class="sidebar-scrollbox"> <ol class="chapter"><li class="chapter-item expanded affix "><a href="../intro.html">Introduction</a></li><li class="chapter-item expanded "><a href="../tools/index.html"><strong aria-hidden="true">1.</strong> Tools</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../tools/zsh.html"><strong aria-hidden="true">1.1.</strong> zsh</a></li><li class="chapter-item expanded "><a href="../tools/bash.html"><strong aria-hidden="true">1.2.</strong> bash</a></li><li class="chapter-item expanded "><a href="../tools/fish.html"><strong aria-hidden="true">1.3.</strong> fish</a></li><li class="chapter-item expanded "><a href="../tools/tmux.html"><strong aria-hidden="true">1.4.</strong> tmux</a></li><li class="chapter-item expanded "><a href="../tools/git.html"><strong aria-hidden="true">1.5.</strong> git</a></li><li class="chapter-item expanded "><a href="../tools/awk.html"><strong aria-hidden="true">1.6.</strong> awk</a></li><li class="chapter-item expanded "><a href="../tools/emacs.html"><strong aria-hidden="true">1.7.</strong> emacs</a></li><li class="chapter-item expanded "><a href="../tools/gpg.html"><strong aria-hidden="true">1.8.</strong> gpg</a></li><li class="chapter-item expanded "><a href="../tools/gdb.html"><strong aria-hidden="true">1.9.</strong> gdb</a></li><li class="chapter-item expanded "><a href="../tools/gdbserver.html"><strong aria-hidden="true">1.10.</strong> gdbserver</a></li><li class="chapter-item expanded "><a href="../tools/radare2.html"><strong aria-hidden="true">1.11.</strong> radare2</a></li><li class="chapter-item expanded "><a href="../tools/qemu.html"><strong aria-hidden="true">1.12.</strong> qemu</a></li><li class="chapter-item expanded "><a href="../tools/pacman.html"><strong aria-hidden="true">1.13.</strong> pacman</a></li><li class="chapter-item expanded "><a href="../tools/dot.html"><strong aria-hidden="true">1.14.</strong> dot</a></li><li class="chapter-item expanded "><a href="../tools/ffmpeg.html"><strong aria-hidden="true">1.15.</strong> ffmpeg</a></li><li class="chapter-item expanded "><a href="../tools/column.html"><strong aria-hidden="true">1.16.</strong> column</a></li><li class="chapter-item expanded "><a href="../tools/sort.html"><strong aria-hidden="true">1.17.</strong> sort</a></li><li class="chapter-item expanded "><a href="../tools/sed.html"><strong aria-hidden="true">1.18.</strong> sed</a></li><li class="chapter-item expanded "><a href="../tools/gnuplot.html"><strong aria-hidden="true">1.19.</strong> gnuplot</a></li></ol></li><li class="chapter-item expanded "><a href="../monitor/index.html"><strong aria-hidden="true">2.</strong> Resource analysis & monitor</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../monitor/lsof.html"><strong aria-hidden="true">2.1.</strong> lsof</a></li><li class="chapter-item expanded "><a href="../monitor/ss.html"><strong aria-hidden="true">2.2.</strong> ss</a></li><li class="chapter-item expanded "><a href="../monitor/pidstat.html"><strong aria-hidden="true">2.3.</strong> pidstat</a></li><li class="chapter-item expanded "><a href="../monitor/pgrep.html"><strong aria-hidden="true">2.4.</strong> pgrep</a></li><li class="chapter-item expanded "><a href="../monitor/ps.html"><strong aria-hidden="true">2.5.</strong> ps</a></li><li class="chapter-item expanded "><a href="../monitor/pmap.html"><strong aria-hidden="true">2.6.</strong> pmap</a></li><li class="chapter-item expanded "><a href="../monitor/pstack.html"><strong aria-hidden="true">2.7.</strong> pstack</a></li></ol></li><li class="chapter-item expanded "><a href="../trace_profile/index.html"><strong aria-hidden="true">3.</strong> Trace and Profile</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../trace_profile/time.html"><strong aria-hidden="true">3.1.</strong> time</a></li><li class="chapter-item expanded "><a href="../trace_profile/strace.html"><strong aria-hidden="true">3.2.</strong> strace</a></li><li class="chapter-item expanded "><a href="../trace_profile/ltrace.html"><strong aria-hidden="true">3.3.</strong> ltrace</a></li><li class="chapter-item expanded "><a href="../trace_profile/perf.html"><strong aria-hidden="true">3.4.</strong> perf</a></li><li class="chapter-item expanded "><a href="../trace_profile/oprofile.html"><strong aria-hidden="true">3.5.</strong> OProfile</a></li><li class="chapter-item expanded "><a href="../trace_profile/callgrind.html"><strong aria-hidden="true">3.6.</strong> callgrind</a></li></ol></li><li class="chapter-item expanded "><a href="../binary/index.html"><strong aria-hidden="true">4.</strong> Binary</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../binary/od.html"><strong aria-hidden="true">4.1.</strong> od</a></li><li class="chapter-item expanded "><a href="../binary/xxd.html"><strong aria-hidden="true">4.2.</strong> xxd</a></li><li class="chapter-item expanded "><a href="../binary/readelf.html"><strong aria-hidden="true">4.3.</strong> readelf</a></li><li class="chapter-item expanded "><a href="../binary/objdump.html"><strong aria-hidden="true">4.4.</strong> objdump</a></li><li class="chapter-item expanded "><a href="../binary/nm.html"><strong aria-hidden="true">4.5.</strong> nm</a></li></ol></li><li class="chapter-item expanded "><a href="../development/index.html"><strong aria-hidden="true">5.</strong> Development</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../development/c++filt.html"><strong aria-hidden="true">5.1.</strong> c++filt</a></li><li class="chapter-item expanded "><a href="../development/c++.html"><strong aria-hidden="true">5.2.</strong> c++</a></li><li class="chapter-item expanded "><a href="../development/glibc.html"><strong aria-hidden="true">5.3.</strong> glibc</a></li><li class="chapter-item expanded "><a href="../development/gcc.html"><strong aria-hidden="true">5.4.</strong> gcc</a></li><li class="chapter-item expanded "><a href="../development/cmake.html"><strong aria-hidden="true">5.5.</strong> cmake</a></li><li class="chapter-item expanded "><a href="../development/make.html"><strong aria-hidden="true">5.6.</strong> make</a></li><li class="chapter-item expanded "><a href="../development/ld.so.html"><strong aria-hidden="true">5.7.</strong> ld.so</a></li><li class="chapter-item expanded "><a href="../development/symbolver.html" class="active"><strong aria-hidden="true">5.8.</strong> symbol versioning</a></li><li class="chapter-item expanded "><a href="../development/python.html"><strong aria-hidden="true">5.9.</strong> python</a></li><li class="chapter-item expanded "><a href="../development/gcov.html"><strong aria-hidden="true">5.10.</strong> gcov</a></li><li class="chapter-item expanded "><a href="../development/pgo.html"><strong aria-hidden="true">5.11.</strong> pgo</a></li></ol></li><li class="chapter-item expanded "><a href="../linux/index.html"><strong aria-hidden="true">6.</strong> Linux</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../linux/systemd.html"><strong aria-hidden="true">6.1.</strong> systemd</a></li><li class="chapter-item expanded "><a href="../linux/coredump.html"><strong aria-hidden="true">6.2.</strong> coredump</a></li><li class="chapter-item expanded "><a href="../linux/ptrace_scope.html"><strong aria-hidden="true">6.3.</strong> ptrace_scope</a></li><li class="chapter-item expanded "><a href="../linux/cryptsetup.html"><strong aria-hidden="true">6.4.</strong> cryptsetup</a></li><li class="chapter-item expanded "><a href="../linux/swap.html"><strong aria-hidden="true">6.5.</strong> swap</a></li><li class="chapter-item expanded "><a href="../linux/input.html"><strong aria-hidden="true">6.6.</strong> input</a></li><li class="chapter-item expanded "><a href="../linux/acl.html"><strong aria-hidden="true">6.7.</strong> acl</a></li><li class="chapter-item expanded "><a href="../linux/zfs.html"><strong aria-hidden="true">6.8.</strong> zfs</a></li></ol></li><li class="chapter-item expanded "><a href="../network/index.html"><strong aria-hidden="true">7.</strong> Network</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../network/tcpdump.html"><strong aria-hidden="true">7.1.</strong> tcpdump</a></li><li class="chapter-item expanded "><a href="../network/tshark.html"><strong aria-hidden="true">7.2.</strong> tshark</a></li><li class="chapter-item expanded "><a href="../network/firewall-cmd.html"><strong aria-hidden="true">7.3.</strong> firewall-cmd</a></li><li class="chapter-item expanded "><a href="../network/nftables.html"><strong aria-hidden="true">7.4.</strong> nftables</a></li></ol></li><li class="chapter-item expanded "><a href="../web/index.html"><strong aria-hidden="true">8.</strong> Web</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../web/html.html"><strong aria-hidden="true">8.1.</strong> html</a></li><li class="chapter-item expanded "><a href="../web/css.html"><strong aria-hidden="true">8.2.</strong> css</a></li><li class="chapter-item expanded "><a href="../web/chartjs.html"><strong aria-hidden="true">8.3.</strong> chartjs</a></li></ol></li><li class="chapter-item expanded "><a href="../arch/index.html"><strong aria-hidden="true">9.</strong> Arch</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../arch/x86_64.html"><strong aria-hidden="true">9.1.</strong> x86_64</a></li><li class="chapter-item expanded "><a href="../arch/arm64.html"><strong aria-hidden="true">9.2.</strong> arm64</a></li><li class="chapter-item expanded "><a href="../arch/armv7.html"><strong aria-hidden="true">9.3.</strong> armv7</a></li><li class="chapter-item expanded "><a href="../arch/riscv.html"><strong aria-hidden="true">9.4.</strong> riscv</a></li></ol></li></ol> </div> <div id="sidebar-resize-handle" class="sidebar-resize-handle"> <div class="sidebar-resize-indicator"></div> </div> </nav> <!-- Track and set sidebar scroll position --> <script> var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox'); sidebarScrollbox.addEventListener('click', function(e) { if (e.target.tagName === 'A') { sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop); } }, { passive: true }); var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll'); sessionStorage.removeItem('sidebar-scroll'); if (sidebarScrollTop) { // preserve sidebar scroll position when navigating via links within sidebar sidebarScrollbox.scrollTop = sidebarScrollTop; } else { // scroll sidebar to current active section when navigating via "next/previous chapter" buttons var activeSection = document.querySelector('#sidebar .active'); if (activeSection) { activeSection.scrollIntoView({ block: 'center' }); } } </script> <div id="page-wrapper" class="page-wrapper"> <div class="page"> <div id="menu-bar-hover-placeholder"></div> <div id="menu-bar" class="menu-bar sticky"> <div class="left-buttons"> <label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar"> <i class="fa fa-bars"></i> </label> <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list"> <i class="fa fa-paint-brush"></i> </button> <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu"> <li role="none"><button role="menuitem" class="theme" id="light">Light</button></li> <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li> <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li> <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li> <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li> </ul> <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar"> <i class="fa fa-search"></i> </button> </div> <h1 class="menu-title">Notes</h1> <div class="right-buttons"> <a href="../print.html" title="Print this book" aria-label="Print this book"> <i id="print-button" class="fa fa-print"></i> </a> <a href="https://github.com/johannst/notes" title="Git repository" aria-label="Git repository"> <i id="git-repository-button" class="fa fa-github"></i> </a> </div> </div> <div id="search-wrapper" class="hidden"> <form id="searchbar-outer" class="searchbar-outer"> <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header"> </form> <div id="searchresults-outer" class="searchresults-outer hidden"> <div id="searchresults-header" class="searchresults-header"></div> <ul id="searchresults"> </ul> </div> </div> <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM --> <script> document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible'); document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible'); Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) { link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1); }); </script> <div id="content" class="content"> <main> <h1 id="elf-symbol-versioning"><a class="header" href="#elf-symbol-versioning">ELF Symbol Versioning</a></h1> <p>The <a href="https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/symversion.html">ELF symbol versioning</a> mechanism allows to attach version information to symbols. This can be used to express symbol version requirements or to provide certain symbols multiple times in the same ELF file with different versions (eg for backwards compatibility).</p> <p>The <code>libpthread.so</code> library is an example which provides the <code>pthread_cond_wait</code> symbol multiple times but in different versions. With readelf the version of the symbol can be seen after the <code>@</code>.</p> <pre><code class="language-bash">> readelf -W --dyn-syms /lib/libpthread.so Symbol table '.dynsym' contains 342 entries: Num: Value Size Type Bind Vis Ndx Name ... 141: 0000f080 696 FUNC GLOBAL DEFAULT 16 pthread_cond_wait@@GLIBC_2.3.2 142: 00010000 111 FUNC GLOBAL DEFAULT 16 pthread_cond_wait@GLIBC_2.2.5 </code></pre> <p>The <code>@@</code> denotes the <strong>default symbol version</strong> which will be used during static linking against the library. The following dump shows that the <code>tmp</code> program linked against <code>lpthread</code> will depend on the symbol version <code>GLIBC_2.3.2</code>, which is the default version.</p> <pre><code class="language-bash">> echo "#include <pthread.h> int main() { return pthread_cond_wait(0,0); }" | gcc -o tmp -xc - -lpthread; readelf -W --dyn-syms tmp | grep pthread_cond_wait; Symbol table '.dynsym' contains 7 entries: Num: Value Size Type Bind Vis Ndx Name ... 2: 00000000 0 FUNC GLOBAL DEFAULT UND pthread_cond_wait@GLIBC_2.3.2 (2) </code></pre> <blockquote> <p>Only <strong>one</strong> symbol can be annotated as the <code>@@</code> default version.</p> </blockquote> <p>Using the <code>--version-info</code> flag with readelf, more details on the symbol version info compiled into the <code>tmp</code> ELF file can be obtained.</p> <ul> <li>The <code>.gnu.version</code> section contains the version definition for each symbol in the <code>.dynsym</code> section. <code>pthread_cond_wait</code> is at index <code>2</code> in the <code>.dynsym</code> section, the corresponding symbol version is at index <code>2</code> in the <code>.gnu.version</code> section.</li> <li>The <code>.gnu.version_r</code> section contains symbol version requirements per shared library dependency (<code>DT_NEEDED</code> dynamic entry).</li> </ul> <pre><code class="language-bash">> readelf -W --version-info --dyn-syms tmp Symbol table '.dynsym' contains 7 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND pthread_cond_wait@GLIBC_2.3.2 (2) 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (3) 4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 5: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable 6: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.2.5 (3) Version symbols section '.gnu.version' contains 7 entries: Addr: 0x0000000000000534 Offset: 0x000534 Link: 6 (.dynsym) 000: 0 (*local*) 0 (*local*) 2 (GLIBC_2.3.2) 3 (GLIBC_2.2.5) 004: 0 (*local*) 0 (*local*) 3 (GLIBC_2.2.5) Version needs section '.gnu.version_r' contains 2 entries: Addr: 0x0000000000000548 Offset: 0x000548 Link: 7 (.dynstr) 000000: Version: 1 File: libc.so.6 Cnt: 1 0x0010: Name: GLIBC_2.2.5 Flags: none Version: 3 0x0020: Version: 1 File: libpthread.so.0 Cnt: 1 0x0030: Name: GLIBC_2.3.2 Flags: none Version: 2 </code></pre> <p>The gnu dynamic linker allows to inspect the version processing during runtime by setting the <code>LD_DEBUG</code> environment variable accordingly.</p> <pre><code class="language-text"># version: Display version dependencies. > LD_DEBUG=versions ./tmp 717904: checking for version `GLIBC_2.2.5' in file /usr/lib/libc.so.6 [0] required by file ./tmp [0] 717904: checking for version `GLIBC_2.3.2' in file /usr/lib/libpthread.so.0 [0] required by file ./tmp [0] ... # symbols : Display symbol table processing. # bindings: Display information about symbol binding. > LD_DEBUG=symbols,bindings ./tmp ... 718123: symbol=pthread_cond_wait; lookup in file=./tmp [0] 718123: symbol=pthread_cond_wait; lookup in file=/usr/lib/libpthread.so.0 [0] 718123: binding file ./tmp [0] to /usr/lib/libpthread.so.0 [0]: normal symbol `pthread_cond_wait' [GLIBC_2.3.2] </code></pre> <h2 id="example-version-script"><a class="header" href="#example-version-script">Example: version script</a></h2> <p>The following shows an example C++ library <code>libfoo</code> which provides the same symbol multiple times but in different versions.</p> <pre><code class="language-cpp">// file: libfoo.cc #include<stdio.h> // Bind function symbols to version nodes. // // ..@ -> Is the unversioned symbol. // ..@@.. -> Is the default symbol. __asm__(".symver func_v0,func@"); __asm__(".symver func_v1,func@LIB_V1"); __asm__(".symver func_v2,func@@LIB_V2"); extern "C" { void func_v0() { puts("func_v0"); } void func_v1() { puts("func_v1"); } void func_v2() { puts("func_v2"); } } __asm__(".symver _Z11func_cpp_v1i,_Z8func_cppi@LIB_V1"); __asm__(".symver _Z11func_cpp_v2i,_Z8func_cppi@@LIB_V2"); void func_cpp_v1(int) { puts("func_cpp_v1"); } void func_cpp_v2(int) { puts("func_cpp_v2"); } void func_cpp(int) { puts("func_cpp_v2"); } </code></pre> <p>Version script for <code>libfoo</code> which defines which symbols for which versions are exported from the ELF file.</p> <pre><code class="language-ld"># file: libfoo.ver LIB_V1 { global: func; extern "C++" { "func_cpp(int)"; }; local: *; }; LIB_V2 { global: func; extern "C++" { "func_cpp(int)"; }; } LIB_V1; </code></pre> <blockquote> <p>The <strong>local:</strong> section in <code>LIB_V1</code> is a catch all, that matches any symbol not explicitly specified, and defines that the symbol is local and therefore not exported from the ELF file.</p> </blockquote> <p>The library <code>libfoo</code> can be linked with the version definitions in <code>libfoo.ver</code> by passing the version script to the linker with the <code>--version-script</code> flag.</p> <pre><code class="language-bash">> g++ -shared -fPIC -o libfoo.so libfoo.cc -Wl,--version-script=libfoo.ver > readelf -W --dyn-syms libfoo.so | c++filt Symbol table '.dynsym' contains 14 entries: Num: Value Size Type Bind Vis Ndx Name ... 6: 0000000000000000 0 OBJECT GLOBAL DEFAULT ABS LIB_V1 7: 000000000000114b 29 FUNC GLOBAL DEFAULT 13 func_cpp(int)@LIB_V1 8: 0000000000001168 29 FUNC GLOBAL DEFAULT 13 func_cpp(int)@@LIB_V2 9: 0000000000001185 29 FUNC GLOBAL DEFAULT 13 func_cpp(int)@@LIB_V1 10: 0000000000000000 0 OBJECT GLOBAL DEFAULT ABS LIB_V2 11: 0000000000001109 22 FUNC GLOBAL DEFAULT 13 func 12: 000000000000111f 22 FUNC GLOBAL DEFAULT 13 func@LIB_V1 13: 0000000000001135 22 FUNC GLOBAL DEFAULT 13 func@@LIB_V2 </code></pre> <p>The following program demonstrates how to make use of the different versions:</p> <pre><code class="language-cpp">// file: main.cc #include <dlfcn.h> #include <assert.h> // Links against default symbol in the lib.so. extern "C" void func(); int main() { // Call the default version. func(); #ifdef _GNU_SOURCE typedef void (*fnptr)(); // Unversioned lookup. fnptr fn_v0 = (fnptr)dlsym(RTLD_DEFAULT, "func"); // Version lookup. fnptr fn_v1 = (fnptr)dlvsym(RTLD_DEFAULT, "func", "LIB_V1"); fnptr fn_v2 = (fnptr)dlvsym(RTLD_DEFAULT, "func", "LIB_V2"); assert(fn_v0 != 0); assert(fn_v1 != 0); assert(fn_v2 != 0); fn_v0(); fn_v1(); fn_v2(); #endif return 0; } </code></pre> <p>Compiling and running results in:</p> <pre><code class="language-bash">> g++ -o main main.cc -ldl ./libfoo.so && ./main func_v2 func_v0 func_v1 func_v2 </code></pre> <h2 id="references"><a class="header" href="#references">References</a></h2> <ul> <li><a href="https://akkadia.org/drepper/symbol-versioning">ELF Symbol Versioning</a></li> <li><a href="https://sourceware.org/binutils/docs/ld/VERSION.html">Binutils ld: Symbol Versioning</a></li> <li><a href="https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/symversion.html">LSB: Symbol Versioning</a></li> <li><a href="https://akkadia.org/drepper/dsohowto.pdf">How To Write Shared Libraries</a></li> <li><a href="https://refspecs.linuxbase.org/elf/elf.pdf">LSB: ELF File Format</a></li> </ul> </main> <nav class="nav-wrapper" aria-label="Page navigation"> <!-- Mobile navigation buttons --> <a rel="prev" href="../development/ld.so.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left"> <i class="fa fa-angle-left"></i> </a> <a rel="next prefetch" href="../development/python.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right"> <i class="fa fa-angle-right"></i> </a> <div style="clear: both"></div> </nav> </div> </div> <nav class="nav-wide-wrapper" aria-label="Page navigation"> <a rel="prev" href="../development/ld.so.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left"> <i class="fa fa-angle-left"></i> </a> <a rel="next prefetch" href="../development/python.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right"> <i class="fa fa-angle-right"></i> </a> </nav> </div> <script> window.playground_copyable = true; </script> <script src="../elasticlunr.min.js"></script> <script src="../mark.min.js"></script> <script src="../searcher.js"></script> <script src="../clipboard.min.js"></script> <script src="../highlight.js"></script> <script src="../book.js"></script> <!-- Custom JS scripts --> </div> </body> </html>