1

I'm using gcc to build a portable shared object. I'm applying the technique outlined in this answer to ensure that my binary will work on systems with older versions of glibc.

For the symbol pthread_getattr_np, I use

extern "C" {
__asm__(".symver pthread_getattr_np,pthread_getattr_np@GLIBC_2.2.5");

int __wrap_pthread_getattr_np(pthread_t thread, pthread_attr_t* attr) {
  return pthread_getattr_np(thread, attr);
}
}

along with the option -Wl,--wrap=pthread_getattr_np to link to a specific portable version. However, pthread_getattr_np recently migrated from libpthread to libc for newer version of glibc. Even though the versioned symbol pthread_getattr_np@GLIBC_2.2.5 is the same, it's defined in a different library.

When I try to load my binary on an older system, I get the error

error: unable to load shared object
symbol pthread_getattr_np version GLIBC_2.2.5 not defined in file libc.so.6 with link time reference

If I run

objdump -T /lib/x86_64-linux-gnu/libpthread.so.0 | grep pthread_getattr_np
0000000000009420 g    DF .text  000000000000035e  GLIBC_2.2.5 pthread_getattr_np

I see that the symbol is defined in libpthread.so; and if I run ldd on my binary, I see that libpthread is a dependency

    linux-vdso.so.1 (0x00007ffec17fc000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa3725cd000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa3723c9000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa37202b000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa371c3a000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fa3735dd000)

but the symbol won't resolve correctly.

Is there a way to set up the linking for my shared library so that pthread_getattr_np will resolve to either libpthread or libc depending on where it's defined?

Ryan Burn
  • 2,126
  • 1
  • 14
  • 35
  • You might use [GNU autoconf](https://www.gnu.org/software/autoconf/) with [GNU automake](https://www.gnu.org/software/automake/) – Basile Starynkevitch Dec 17 '20 at 07:25
  • This is a precompiled binary. I'm building on one machine but using it on multiple targets. – Ryan Burn Dec 17 '20 at 07:26
  • That should be mentioned in your question. Things then become more complex, and could be technically possible but illegal to deploy. Be sure to consult your lawyer about software license issues and mention him/her the [GCC runtime library exception](https://www.gnu.org/licenses/gcc-exception-3.1.en.html) or contact the [FSF](https://www.fsf.org/) – Basile Starynkevitch Dec 17 '20 at 07:28
  • 1
    Note that the `_np` suffix means 'not portable'. Be cautious. – Jonathan Leffler Dec 17 '20 at 07:33
  • If on Linux, you might consider using [dlopen(3)](https://man7.org/linux/man-pages/man3/dlopen.3.html) and read the [*Program library howto*](https://tldp.org/HOWTO/Program-Library-HOWTO/). I am not a lawyer, but I would believe you might violate the [LGPLv3](https://www.gnu.org/licenses/lgpl-3.0.en.html) license of [GNU libc](https://www.gnu.org/software/libc/). – Basile Starynkevitch Dec 17 '20 at 07:34
  • @JonathanLeffler - I believe np is there because it's a GNU extension and not a posix function. It should still be portable across different versions of glibc. – Ryan Burn Dec 17 '20 at 08:01
  • 2
    @RyanBurn — 'non-portable' also means 'not POSIX', and it isn't standardized, hence the suffix. Yes, it probably is more or less portable across versions of GNU LibC, but it is clearly causing problems for the OP, so even across GNU LibC versions, it is not wholly portable. – Jonathan Leffler Dec 17 '20 at 08:06
  • I'm the OP and yes it's causing problems, but that's to do with the symbol having moved between libraries rather than the function itself causing problems. I assume since glibc explicitly includes an additional versioned symbol @2.2.5 that they indent to provide some portability. – Ryan Burn Dec 17 '20 at 08:09
  • Could the down voter explain why they think this is not a valid question? And why it doesn't fit into [this](https://stackoverflow.com/a/20065096/4447365) commonly used pattern for building portable binaries. – Ryan Burn Dec 17 '20 at 18:30
  • You did not provide any [mre] in your question: that would mean some self-contained C code (with a `main`) and the *exact* compilation and building commands. You may want to read [*Advanced Linux Programming*](https://mentorembedded.github.io/advancedlinuxprogramming/) and [syscalls(2)](https://man7.org/linux/man-pages/man2/syscalls.2.html). I also believe that you won't be able to build a portable binary, but you don't give your definition of [software portability](https://en.wikipedia.org/wiki/Software_portability). Is it at source code level or at binary level? – Basile Starynkevitch Dec 18 '20 at 09:57
  • I tend to believe that there is no portable software, only some source code which has been successfully and painfully ported to several target platforms (a [RaspberryPi](https://raspberrypi.org/) is different of most Linux-running [supercomputers](https://en.wikipedia.org/wiki/Supercomputer) listed in [top500](https://top500.org/)... and both could run a Linux [kernel](https://kernel.org/) with a [GNU libc](https://www.gnu.org/software/libc/)) – Basile Starynkevitch Dec 18 '20 at 10:00
  • @BasileStarynkevitch - For those with the domain knowledge to be able to answer this, the question was sufficiently worded and I was able to get an answer on the glibc [mailing list](https://sourceware.org/pipermail/libc-help/2020-December/005602.html) (no thanks to stack overflow): – Ryan Burn Dec 18 '20 at 20:03

0 Answers0