Bug 27206 - .symver overrides .weak
Summary: .symver overrides .weak
Status: WAITING
Alias: None
Product: binutils
Classification: Unclassified
Component: binutils (show other bugs)
Version: 2.36
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on: 3351
Blocks:
  Show dependency treegraph
 
Reported: 2021-01-19 17:38 UTC by Tom Kacvinsky
Modified: 2021-01-19 21:42 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed: 2021-01-19 00:00:00


Attachments
Reproducer code (205 bytes, text/plain)
2021-01-19 17:38 UTC, Tom Kacvinsky
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Tom Kacvinsky 2021-01-19 17:38:10 UTC
Created attachment 13134 [details]
Reproducer code

The attached code, when built with

 gcc -fPIC -o thread.so -shared thread.c

(using GCC 8.3.0 and binutils 2.36) produces the following error:

ld: thread.so: no symbol version section for versioned symbol `pthread_key_create@GLIBC_2.2.5'

I am not sure if .symver is supposed to override .weak, or vice versa.  IF the latter, it would appears to me that this is a bug in binutils.

Regards,

Tom
Comment 1 H.J. Lu 2021-01-19 18:24:06 UTC
(In reply to Tom Kacvinsky from comment #0)
> Created attachment 13134 [details]
> Reproducer code
> 
> The attached code, when built with
> 
>  gcc -fPIC -o thread.so -shared thread.c
> 
> (using GCC 8.3.0 and binutils 2.36) produces the following error:
> 
> ld: thread.so: no symbol version section for versioned symbol
> `pthread_key_create@GLIBC_2.2.5'

This linker message is due to PR 3351.
Comment 2 Tom Kacvinsky 2021-01-19 18:32:05 UTC
I know you mentioned this message comes from the referenced PR, but is what I am seeing an unintended consequence of the change made in this PR, or is this expected behavior?
Comment 3 H.J. Lu 2021-01-19 18:53:00 UTC
---
__asm__(".symver pthread_key_create,pthread_key_create@GLIBC_2.2.5,remove");
---

A versioned symbol must be defined in an object.  Try this 

[hjl@gnu-cfl-2 pr27206]$ cat libfoo.map 
GLIBC_2.2.5 {
  global: pthread_key_create;
};
libfoo {
  global: *;
};
[hjl@gnu-cfl-2 pr27206]$ cat foo.c
#include <pthread.h>

__attribute__ ((weak))
int
pthread_key_create (pthread_key_t *key, void (*fun) (void *))
{
  return 0;
}

__asm__(".symver pthread_key_create,pthread_key_create@GLIBC_2.2.5");

void destructor(void* arg) { return; }

void thread_func() {
  pthread_key_t key;

  pthread_key_create(&key, destructor);
}
[hjl@gnu-cfl-2 pr27206]$ make
gcc -B./ -fPIC   -c -o foo.o foo.c
gcc -B./ -Wl,--version-script=libfoo.map -shared -o libfoo.so foo.o
[hjl@gnu-cfl-2 pr27206]$ readelf -rW --dyn-syms libfoo.so | grep pthread_key_create
0000000000004018  0000000600000007 R_X86_64_JUMP_SLOT     0000000000001109 pthread_key_create@GLIBC_2.2.5 + 0
     6: 0000000000001109    19 FUNC    WEAK   DEFAULT   14 pthread_key_create@GLIBC_2.2.5
[hjl@gnu-cfl-2 pr27206]$
Comment 4 Tom Kacvinsky 2021-01-19 20:02:28 UTC
This worked for me in my simple reproducer, but unfortunately we are doing "naughty" things with third party code build such that a linker map is not an option, unless we hack that library's build process.
Comment 5 Fangrui Song 2021-01-19 20:47:14 UTC
#c0 should be flagged. ld errors for an undefined versioned symbol.

If a versioned symbol is defined, it requires a version node defined in a version script
(unless not -shared).

Whether as should error for `.symver ... local` + `weak`? It is not clear.
Personally I'd like a directive which just renames the symbol to a @ form,
then such issues would not arise.
https://maskray.me/blog/2020-11-26-all-about-symbol-versioning#assembler-behavior

Tom, how did you notice .symver ... local and start to use it?
Comment 6 Tom Kacvinsky 2021-01-19 21:03:20 UTC
For compatibility reasons, I want to update my automated build machine, but build GCC and auxiliary support libraries in such a fashion that we can target older Linux distributions That is, build on a machine with a newer glibc, but still be able to run the resulting binaries on a system with an older glibc, which is reverse of building on an older system and running on a newer system.

So, I first went to build GCC 8.3.0 on a newer system (CentOS 7) using a custom assembly file (one that contains a .symver for each older version symbol we want, to target older versions of glibc).  That is injected into compiler generated assembly files via an indirect assembler - named as, which opens any .s/.S files on the command line, inserts the custom assembly file into them, then calls gas, the _real_ assembler.

But libgcc.so.1 failed to build with the pthread_key_create error I mentioned in this bug.  The reproducer I sent is a stripped down version of the code from libgcc.

This is why I am somewhat concerned about the link map trick, etc...  It would create many problems while trying to sort out the GCC build configuration and code.  The code in GCC that utilizes pthread_key_create marks it as extern and weak, which is different from what is in pthread.h.  And the reason for that, as commented in the libgcc code, is so that pthread_key_create is weak, which leads libggc.so.1 not having a run time dependency on libpthread.so.0.


Tom
Comment 7 H.J. Lu 2021-01-19 21:42:07 UTC
(In reply to Tom Kacvinsky from comment #6)
> For compatibility reasons, I want to update my automated build machine, but
> build GCC and auxiliary support libraries in such a fashion that we can
> target older Linux distributions That is, build on a machine with a newer
> glibc, but still be able to run the resulting binaries on a system with an
> older glibc, which is reverse of building on an older system and running on
> a newer system.
> 

You can use a cross compiler to that.  Check scripts/build-many-glibcs.py
in glibc source to see how to build a toolchain with a different glibc.