Symbol versioning on Alpine Linux
Asked Answered
B

0

7

The musl C library has only an approximative implementation of symbol versioning. This can result in symbols being bound together that have different symbol versions, something which would not happen in a full implementation. Projects which expect to be built with musl are therefore better off with avoiding symbol versioning altogether. (Not supporting symbol versioning is by itself not necessarily a bad choice for a toolchain; it all depends on the target audience.)

However, the Alpine Linux toolchain compiles binutils with full symbol versioning support: GAS suppports the .symver directive, and the link editor handles version scripts and assigns symbol versions (just as it would on GNU/Linux). A simple compiler/assembler or linker check shows that symbol versioning is supported. As a result, some of the shared objects which Alpine Linux includes in the distribution do in fact use symbol versioning, although the musl dynamic loader will ignore this data. (The data just bloats the binaries.)

In some cases, software fails to run (after building just fine) because it uses compatibility symbols (symbols without a default version) in ways that are not supported by the musl dynamic linker. Here's a small example of what does not work:

cat > symver.c <<EOF
void
compat_function (void)
{
}
__asm__ (".symver compat_function,compat_function@SYMVER");

void
call_compat_function (void)
{
  return compat_function ();
}
EOF

echo "SYMVER { };" > symver.map

cat > main.c <<EOF
extern void call_compat_function (void);

int
main (void)
{
  call_compat_function ();
}
EOF

gcc -fpic -shared -o symver.so -Wl,--version-script=symver.map symver.c
gcc -Wl,--rpath=. -o main main.c symver.so
./main

Execution fails with Error relocating ./symver.so: compat_function: symbol not found. It runs successfully without the .symver directive.

How is this combination of binutils support for symbol versioning in combination with a dynamic linker that does not support it supposed to work in practice? Should projects check for a *-musl target triplet and disable symbol versioning?

A run-time check for dynamic linker support would do the job, but it would break cross-compiling. Should this be fixed in Alpine Linux itself, by disabling symbol versioning support in binutils?

Bartell answered 22/1, 2019 at 11:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.