Thank you very much for your help Fāng-ruì Sòng. I've tried various things like linking directly to libm-2.32 but it didn't work, it seems that libm-2.32 still pulls libmvec. I have the following linker flags: CLANG_LDFLAGS="-fuse-ld=lld -static-libstdc++ -static-libgcc -fvisibility=hidden -fdata-sections -ffunction-sections" CLANG_LDFLAGS="$CLANG_LDFLAGS -Wl,--gc-sections -Wl,-O1 -Wl,--as-needed -Wl,--strip-all" CLANG_LDFLAGS="$CLANG_LDFLAGS -Wl,-y,exp,-y,exp at GLIBC_2.29,-y,exp at GLIBC_2.2.5" How to find what is pulling libmvec? On the other hand, I don't understand why I have to specify that I want exp from glibc 2.2 or 2.29, I just want the exp symbol, and if possible the latest version available on the system. Because I don't have a high precision requirement so they would all be fine. Is that possible? Regards, Alexandre Bique On Mon, Nov 9, 2020 at 7:06 PM Fāng-ruì Sòng <maskray at google.com> wrote:> > On Mon, Nov 9, 2020 at 10:04 AM Fāng-ruì Sòng <maskray at google.com> wrote: > > > > No. A shared object is needed if it is linked in (1)--no-as-needed > > mode or (2) after --gc-sections, a symbol referenced by a live input > > section is defined by the shared object. > > A shared object is needed if it is linked in (1) --no-as-needed mode > or (2) after --gc-sections, a symbol referenced by a live input > section is defined by the shared object as non-STB_WEAK. > > > You'll need to check whether a symbol is defined by libmvec.so.1 > > > > On Mon, Nov 9, 2020 at 9:57 AM Alexandre Bique > > <bique.alexandre at gmail.com> wrote: > > > > > > On Mon, Nov 9, 2020 at 6:52 PM Fāng-ruì Sòng <maskray at google.com> wrote: > > > > Recent libm.a and libm.so are actually linker scripts > > > > > > > > % cat /usr/lib/x86_64-linux-gnu/libm.a > > > > /* GNU ld script > > > > */ > > > > OUTPUT_FORMAT(elf64-x86-64) > > > > GROUP ( /usr/lib/x86_64-linux-gnu/libm-2.31.a > > > > /usr/lib/x86_64-linux-gnu/libmvec.a ) > > > > % cat /usr/lib/x86_64-linux-gnu/libm.so > > > > /* GNU ld script > > > > */ > > > > OUTPUT_FORMAT(elf64-x86-64) > > > > GROUP ( /lib/x86_64-linux-gnu/libm.so.6 AS_NEEDED ( > > > > /lib/x86_64-linux-gnu/libmvec.so.1 ) ) > > > > > > In this script the libmvec is mentioned as "AS_NEEDED", and it is not > > > needed in my case, yet lld pulls its dependency toward exp at GLIBC_2.29. > > > > > > Is it a bug in lld? > > > > > > Regards, > > > Alexandre > > > > > > > > -- > > 宋方睿 > > > > -- > 宋方睿
On Tue, Nov 10, 2020 at 12:27 AM Alexandre Bique <bique.alexandre at gmail.com> wrote:> > Thank you very much for your help Fāng-ruì Sòng. > > I've tried various things like linking directly to libm-2.32 but it > didn't work, it seems that libm-2.32 still pulls libmvec. > > I have the following linker flags: > > CLANG_LDFLAGS="-fuse-ld=lld -static-libstdc++ -static-libgcc > -fvisibility=hidden -fdata-sections -ffunction-sections" > CLANG_LDFLAGS="$CLANG_LDFLAGS -Wl,--gc-sections -Wl,-O1 > -Wl,--as-needed -Wl,--strip-all" > CLANG_LDFLAGS="$CLANG_LDFLAGS -Wl,-y,exp,-y,exp at GLIBC_2.29,-y,exp at GLIBC_2.2.5" > > How to find what is pulling libmvec?If you build a -DCMAKE_BUILD_TYPE=Debug lld, you can set a breakpoint on lld/ELF/MarkLive.cpp:114 (ss->getFile().isNeeded) and check which symbol makes libmvec.so needed.> On the other hand, I don't understand why I have to specify that I > want exp from glibc 2.2 or 2.29, I just want the exp symbol, and if > possible the latest version available on the system. > Because I don't have a high precision requirement so they would all be > fine. Is that possible?Symbol versioning is complex ;-) While the runtime behavior is documented by Linux Standard Base Core Specification, Generic Part, there is no good documentation on the linker behavior. LLD has evolved to the current state after contributors "observe GNU ld behaviors and patch LLD when needed" :( For an undefined symbol, there is only this form: sym at ver For a defined symbol, both sym at ver (non-default; sometimes called hidden) and sym@@ver (default) exist. For a defined symbol named sym at ver, it only resolves an undefined symbol sym at ver. For a defined symbol named sym@@ver, it resolves both undefined sym at ver and undefined sym. If you have glibc 2.29, there are exp at GLIBC_2.2.5 (non-default) and exp@@GLIBC_2.29 (default), your 'exp' undefined symbol will resolve to exp@@GLIBC_2.29 (default) and not work with older glibc. If you know that your translation unit does not define 'exp' (usual case), you can write .symver exp,exp at GLIBC_2.2.5 call exp or .symver exp,exp@@@GLIBC_2.2.5 call exp Then the undefined symbol 'exp' will be renamed to 'exp at GLIBC_2.2.5' and get bound to the old version at link time. It will thus work with old glibc.> Regards, > Alexandre Bique > > On Mon, Nov 9, 2020 at 7:06 PM Fāng-ruì Sòng <maskray at google.com> wrote: > > > > On Mon, Nov 9, 2020 at 10:04 AM Fāng-ruì Sòng <maskray at google.com> wrote: > > > > > > No. A shared object is needed if it is linked in (1)--no-as-needed > > > mode or (2) after --gc-sections, a symbol referenced by a live input > > > section is defined by the shared object. > > > > A shared object is needed if it is linked in (1) --no-as-needed mode > > or (2) after --gc-sections, a symbol referenced by a live input > > section is defined by the shared object as non-STB_WEAK. > > > > > You'll need to check whether a symbol is defined by libmvec.so.1 > > > > > > On Mon, Nov 9, 2020 at 9:57 AM Alexandre Bique > > > <bique.alexandre at gmail.com> wrote: > > > > > > > > On Mon, Nov 9, 2020 at 6:52 PM Fāng-ruì Sòng <maskray at google.com> wrote: > > > > > Recent libm.a and libm.so are actually linker scripts > > > > > > > > > > % cat /usr/lib/x86_64-linux-gnu/libm.a > > > > > /* GNU ld script > > > > > */ > > > > > OUTPUT_FORMAT(elf64-x86-64) > > > > > GROUP ( /usr/lib/x86_64-linux-gnu/libm-2.31.a > > > > > /usr/lib/x86_64-linux-gnu/libmvec.a ) > > > > > % cat /usr/lib/x86_64-linux-gnu/libm.so > > > > > /* GNU ld script > > > > > */ > > > > > OUTPUT_FORMAT(elf64-x86-64) > > > > > GROUP ( /lib/x86_64-linux-gnu/libm.so.6 AS_NEEDED ( > > > > > /lib/x86_64-linux-gnu/libmvec.so.1 ) ) > > > > > > > > In this script the libmvec is mentioned as "AS_NEEDED", and it is not > > > > needed in my case, yet lld pulls its dependency toward exp at GLIBC_2.29. > > > > > > > > Is it a bug in lld? > > > > > > > > Regards, > > > > Alexandre > > > > > > > > > > > > -- > > > 宋方睿 > > > > > > > > -- > > 宋方睿-- 宋方睿
On Tue, Nov 10, 2020 at 7:01 PM Fāng-ruì Sòng <maskray at google.com> wrote:> > How to find what is pulling libmvec? > > If you build a -DCMAKE_BUILD_TYPE=Debug lld, you can set a breakpoint > on lld/ELF/MarkLive.cpp:114 (ss->getFile().isNeeded) and check which > symbol makes > libmvec.so needed.I'm afraid this is going to far for me :)> > On the other hand, I don't understand why I have to specify that I > > want exp from glibc 2.2 or 2.29, I just want the exp symbol, and if > > possible the latest version available on the system. > > Because I don't have a high precision requirement so they would all be > > fine. Is that possible? > > Symbol versioning is complex ;-) While the runtime behavior is > documented by Linux Standard Base Core Specification, Generic Part, > there is no good documentation on the linker behavior. > LLD has evolved to the current state after contributors "observe GNU > ld behaviors and patch LLD when needed" :(I think there might be some discussions needed with glibc/coreutils/gcc/llvm because it is way too complicated. I believe that targeting an older glibc version should not be more complicated than -DGLIBC_COMPAT_LEVEL=0x020205 -Wl,compat=GLIBC_2.2.5 On OSX there is a target platform command line option, and I believe it is the right approach, yet I can't really comment on it.> For an undefined symbol, there is only this form: sym at ver > For a defined symbol, both sym at ver (non-default; sometimes called > hidden) and sym@@ver (default) exist. > > For a defined symbol named sym at ver, it only resolves an undefined > symbol sym at ver. > For a defined symbol named sym@@ver, it resolves both undefined > sym at ver and undefined sym. > > If you have glibc 2.29, there are exp at GLIBC_2.2.5 (non-default) and > exp@@GLIBC_2.29 (default), your 'exp' undefined symbol > will resolve to exp@@GLIBC_2.29 (default) and not work with older glibc. > > If you know that your translation unit does not define 'exp' (usual > case), you can write > > .symver exp,exp at GLIBC_2.2.5 > call exp > or > .symver exp,exp@@@GLIBC_2.2.5 > call exp > > Then the undefined symbol 'exp' will be renamed to 'exp at GLIBC_2.2.5' > and get bound to the old version at link time. It will thus work with > old glibc.I have one .cpp file with: __asm__(".symver powf,powf at GLIBC_2.2.5"); __asm__(".symver expf,expf at GLIBC_2.2.5"); __asm__(".symver exp2f,exp2f at GLIBC_2.2.5"); __asm__(".symver log2f,log2f at GLIBC_2.2.5"); __asm__(".symver logf,logf at GLIBC_2.2.5"); __asm__(".symver log,log at GLIBC_2.2.5"); __asm__(".symver log2,log2 at GLIBC_2.2.5"); __asm__(".symver exp,exp at GLIBC_2.2.5"); __asm__(".symver exp2,exp2 at GLIBC_2.2.5"); __asm__(".symver pow,pow at GLIBC_2.2.5"); But it does not solve the issue. I've tried many variations. Do you know if it is possible after the link, to edit the shared library and replace the dependency on GLIBC 2.29 to GLIBC 2.2.5? Regards, Alexandre