Bug 29651 - glibc can't handle IRELATIVE in .rel.plt only on ARM32 and PPC
Summary: glibc can't handle IRELATIVE in .rel.plt only on ARM32 and PPC
Status: RESOLVED WONTFIX
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-10-04 02:39 UTC by Rui Ueyama
Modified: 2022-10-15 02:06 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Rui Ueyama 2022-10-04 02:39:02 UTC
It looks like glibc is inconsistent in terms of whether it accepts IRELATIVE relocations in .rel.plt or not. The majority of its ports support it, though it rejects it with the "unexpected PLT reloc type" error on ARM32 and PPC64.

Compare 

https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/x86_64/dl-machine.h;h=005d089501fa78654e16103de9ec901af7be4ff2;hb=HEAD#l530

with

https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/arm/dl-machine.h;h=b0521c15496b9967a1c00a0ca7214bad2337be14;hb=HEAD#l498

as an example. ARM doesn't handle R_ARM_IRELATIVE in .rel.plt.

Among the targets that support GNU IFUNC, the following implementations accept IRELATIVE relocations in .rel.plt:

  sysdeps/aarch64/dl-machine.h
  sysdeps/i386/dl-machine.h
  sysdeps/s390/s390-32/dl-machine.h
  sysdeps/s390/s390-64/dl-machine.h
  sysdeps/sparc/sparc32/dl-machine.h
  sysdeps/sparc/sparc64/dl-machine.h
  sysdeps/x86_64/dl-machine.h

The following don't:

  sysdeps/arm/dl-machine.h
  sysdeps/powerpc/powerpc64/dl-machine.h

So I guess this is a bug in ARM32 and PPC64 ports of glibc?
Comment 1 Adhemerval Zanella 2022-10-13 17:41:55 UTC
It was already reported on binutils [1] and on lld [2]. The current behavior for ld on arm is to put IRELATIVE on .rel.dyn but I am not sure why exactly (Peter hinted it is a "legacy of ARM having a single .got section", and I am not sure if ld still have this limitation yet).

So 'fixing' it won't gain us anything with current supported static linkers.  It might improve support on arm ifunc itself (for instance to be able to call R_ARM_JUMP_SLOT functions, since ifunc will be reordered last), but what ifunc is able to do is not properly documented and has a lot of pitafalls that calling external functions (from current TU) is always 'tricky'.

And even if we change it, a static-linker that only emits IRELATIVE on .rel.plt will need to prevent to run on older glibc (as we did for DT_RELR with a extra symbol).

So the question is whether you need this changed.  Do you need it for your mold linker?

[1] https://sourceware.org/bugzilla/show_bug.cgi?id=19891
[2] https://reviews.llvm.org/D26029
[3] https://sourceware.org/glibc/wiki/GNU_IFUNC
Comment 2 Rui Ueyama 2022-10-14 01:48:43 UTC
I added support for ifunc this way to mold and found that although it worked perfectly fine on x86-64 and other targets, it didn't on arm32 and ppc64. I abandoned that change, so I no longer have a strong opinion on this. That said, I still think that it would have been better if glibc worked the same way across all targets.
Comment 3 Adhemerval Zanella 2022-10-14 12:16:35 UTC
Since IFUNC support was added in a most ad-hoc way for each architecture, there is no unified code to generate it with binutils or to handle on glibc.

We can implement your suggestion and add support for .rel.plt IRELATIVE handling on arm and PPC, however it will only work for linkes that implement it and there will be issues on how to avoid such binaries to run on older glibcs. 

The glibc now avoids random failures if there is missing support and instead dumps an error on why it has failed.

So essentially this change for ARM and PPC will be similar to what we have done for DT_RELR: we will need the static linker to advertise that IFUNC is now placed on .rel.plt instead of .rel.dyn so glibc can avoid starting the binary if it has no support.  For DT_RELR both binutils and lld now add an extra version tag GLIBC_ABI_DT_RELR on .gnu.version_r to indicate it.  For instance on a glibc binary built with DT_RELR support:

Version needs section '.gnu.version_r' contains 1 entry:
 Addr: 0x0000000000000998  Offset: 0x000998  Link: 7 (.dynstr)
  000000: Version: 1  File: libc.so.6  Cnt: 4
  0x0010:   Name: GLIBC_ABI_DT_RELR  Flags: none  Version: 5
  0x0020:   Name: GLIBC_2.4  Flags: none  Version: 4
  0x0030:   Name: GLIBC_2.34  Flags: none  Version: 3
  0x0040:   Name: GLIBC_2.2.5  Flags: none  Version: 2

Older glibcs will fails with a missing GLIBC_ABI_DT_RELR version trying to bind the version.

So if we want to add support for IRELATE on .rel.plt for ARM and PPC we need a similar change, where static linkers add a GLIBC_ABI_IFUNC_REL_PLT version tag.
Comment 4 Adhemerval Zanella 2022-10-14 13:40:27 UTC
(In reply to Adhemerval Zanella from comment #3)
> 
> So if we want to add support for IRELATE on .rel.plt for ARM and PPC we need
> a similar change, where static linkers add a GLIBC_ABI_IFUNC_REL_PLT version
> tag.

In fact, we already have the 'unexpected PLT reloc type' error so there is no need to add a new symbol version (although the error is not clear). 

So I do not really opposes it, but again the actual gain is quite minimal and a linker that only emits IRELATIVE on .rel.plt will create binaries that only work on very recent glibc.
Comment 5 Rui Ueyama 2022-10-15 02:06:27 UTC
I thought that the intention of glibc is to support that usage on all targets and somehow a few targets didn't support it. So, if it needs more work than just implementing it so that it will be usable someday in the future, I don't think it's worth to pursue. It's not that important anyway. I'll close this issue as "won't fix".