[llvm-dev] Targeting old glibc

Fāng-ruì Sòng via llvm-dev llvm-dev at lists.llvm.org
Wed Nov 11 13:37:42 PST 2020


On 2020-11-11, Alexandre Bique wrote:
>It did partially fix the issue but there is still one problem:
>
>llvm-objdump -sx gives:
>
>Version References:
>  required from libpthread.so.0:
>    0x09691a75 0x00 05 GLIBC_2.2.5
>    0x09691972 0x00 09 GLIBC_2.3.2
>    0x09691973 0x00 07 GLIBC_2.3.3
>    0x06969192 0x00 12 GLIBC_2.12
>  required from libdl.so.2:
>    0x09691a75 0x00 21 GLIBC_2.2.5
>  required from libuuid.so.1:
>    0x09da27b0 0x00 19 UUID_1.0
>  required from libm.so.6:
>    0x09691a75 0x00 04 GLIBC_2.2.5
>    0x06969187 0x00 06 GLIBC_2.27
>    0x06969189 0x00 11 GLIBC_2.29
>  required from libc.so.6:
>    0x09691a75 0x00 03 GLIBC_2.2.5
>    0x0d696913 0x00 14 GLIBC_2.3
>    0x09691972 0x00 08 GLIBC_2.3.2
>    0x09691974 0x00 17 GLIBC_2.3.4
>    0x0d696914 0x00 16 GLIBC_2.4
>    0x0d696917 0x00 13 GLIBC_2.7
>    0x06969191 0x00 18 GLIBC_2.11
>    0x06969194 0x00 15 GLIBC_2.14
>    0x06969197 0x00 10 GLIBC_2.17
>  required from ld-linux-x86-64.so.2:
>    0x0d696913 0x00 20 GLIBC_2.3
>
>So there are still some references to GLIBC_2.29 from libm.
>It is in the VERSION_NEED or something similar I think.
>
>Could llvm-strip figure that it can get rid of it?
>
>Regards,
>Alexandre Bique

If you want to drop symbol versioning with llvm-objcopy:

* llvm-objcopy -R .gnu.version -R .gnu.version_r in.so out.so
* However, llvm-objcopy zeroes out the section content so at runtime glibc ld.so will error
   "unsupported version 0 of Verneed record".
   Thus we need to drop the DT_VERNEED tag as well.
   To achieve this, we can rewrite the DT_VERNEED tag to DT_NULL (0), terminating
   the dynamic table, effectively deleting all DT_VER* tags. DT_RELACOUNT is also
   deleted. Fortunately its absence does not affect correctness.
   This requires binary patching

   ...
   0x000000006ffffffb (FLAGS_1)            Flags: NOW
- 0x000000006ffffffe (VERNEED)            0x8ef0
- 0x000000006fffffff (VERNEEDNUM)         5
- 0x000000006ffffff0 (VERSYM)             0x89c0
- 0x000000006ffffff9 (RELACOUNT)          1536
   0x0000000000000000 (NULL)               0x0


In the end, the solution is:

r2 -wqc '/x feffff6f00000000 @ section..dynamic; w0 16 @ hit0_0' a.so; llvm-objcopy -R .gnu.version -R .gnu.version_r a.so

>On Wed, Nov 11, 2020 at 2:25 PM Alexandre Bique
><bique.alexandre at gmail.com> wrote:
>>
>> This did the job:
>>
>> patchelf --clear-symbol-version log Podolski.64.so
>>
>> Alexandre Bique
>>
>> On Wed, Nov 11, 2020 at 2:19 PM Alexandre Bique
>> <bique.alexandre at gmail.com> wrote:
>> >
>> > 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


More information about the llvm-dev mailing list