Proposal for STT_GNU_IFUNC and R_*_IRELATIVE

H.J. Lu hjl.tools@gmail.com
Wed May 27 19:40:00 GMT 2009


On Wed, May 27, 2009 at 10:54 AM, Ulrich Drepper <drepper@redhat.com> wrote:
>
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> H.J. Lu wrote:
>> How to do you handle R_*_PC32 relocation to a locally defined
>> STT_GNU_IFUNC symbol in dynamic and static executables?
>
> When I compile the test code you sent yesterday I see this in the
> executable:
>
> 000000000040050c <main>:
>  40050c:       55                      push   %rbp
>  40050d:       48 89 e5                mov    %rsp,%rbp
>  400510:       bf fd ff ff ff          mov    $0xfffffffd,%edi
>  400515:       e8 00 00 00 00          callq  40051a <main+0xe>
>  40051a:       b8 00 00 00 00          mov    $0x0,%eax
>  40051f:       c9                      leaveq
>  400520:       c3                      retq

I got

00000000004005ac <main>:
  4005ac:	55                   	push   %rbp
  4005ad:	48 89 e5             	mov    %rsp,%rbp
  4005b0:	bf fd ff ff ff       	mov    $0xfffffffd,%edi
  4005b5:	e8 00 00 00 00       	callq  4005ba <main+0xe>
  4005ba:	b8 00 00 00 00       	mov    $0x0,%eax
  4005bf:	c9                   	leaveq

Relocation section '.rela.ifunc.dyn' at offset 0x430 contains 1 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
0000004005b6  000400000002 R_X86_64_PC32     foo()            foo - 4

Dynamic linker will lookup STT_GNU_IFUNC foo and resolve
R_X86_64_PC32. But dynamic linker will segfaut as soon as
it tries to run foo () since the text segment isn't executable
when it is changed to PROT_READ|PROT_WRITE before
updating the text segment.

>
> This is of course not going to work.  The program doesn't even contain a
> R_*_IRELATIVE relocation.
>
> Every call to an IFUNC must be indirect somewhere.  You cannot change
> the relative jmp into an indirect one (opcode is too long).  Therefore,
> as I explained before, you allocate and jump to a PLT slot.  The PLT
> slot as a GOT entry and that GOT entry in modified by the R_*_IRELATIVE
> relocation.
>

The current linker doesn't do that. I will investigate if it is easy to fix,
especially for static executables where executable has to manage
PLT and GOT itself. Certain static executables like kernel may
have

call STT_GNU_IFUNC foo

where the best foo will be selected at boot time for a given hardware.
PLT/GOT isn't needed here.

-- 
H.J.



More information about the Libc-alpha mailing list