Proposal for STT_GNU_IFUNC and R_*_IRELATIVE

61 views
Skip to first unread message

H.J. Lu

unread,
May 25, 2009, 2:56:57 PM5/25/09
to Generic System V Application Binary Interface, GNU C Library, dis...@x86-64.org, Binutils, IA32 System V Application Binary Interface, Nick Clifton, Ulrich Drepper
Hi,

Here is a proposal for STT_GNU_IFUNC and R_*_IRELATIVE. It
has been implemented in the Linux binutils 2.19.51.0.5.


H.J.
----
STT_GNU_IFUNC

This symbol type is the same as STT_FUNC except that it always
points to a function or piece of executable code which takes no
arguments and returns a function pointer. If an STT_GNU_IFUNC
symbol is referred to by a relocation, then evaluation of that
relocation is delayed until load-time. The value used in the
relocation is the function pointer returned by an invocation
of the STT_GNU_IFUNC symbol.

The purpose of this symbol type is to allow the run-time to
select between multiple versions of the implementation of a
specific function. The selection made in general will take the
currently available hardware into account and select the most
appropriate version.

STT_GNU_IFUNC is defined in OS-specific range:

#define STT_LOOS 10 /* OS-specific semantics */
#define STT_GNU_IFUNC 10 /* Symbol is an indirect code object */
#define STT_HIOS 12 /* OS-specific semantics */

R_*_IRELATIVE

This relocation is similar to R_*_RELATIVE except that the
value used in this relocation is the program address returned
by the function, which takes no arguments, at the address of
the result of the corresponding R_*_RELATIVE relocation.

The purpose of this relocation to avoid name lookup for locally
defined STT_GNU_IFUNC symbols at load-time.

R_*_IRELATIVE is defined for i386 and x86-64:

#define R_386_IRELATIVE 42 /* Adjust indirectly by program base */
#define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */

Jan Beulich

unread,
May 26, 2009, 2:52:26 AM5/26/09
to H.J. Lu, Generic System V Application Binary Interface, IA32 System V Application Binary Interface, Ulrich Drepper, Nick Clifton, Binutils, GNU C Library, dis...@x86-64.org
I have to admit that I don't see why a new symbol type *and* a new
relocation type would be necessary here. If the to-be-relocated symbols'
name is to not appear in the original (dynamic) symbol table, then all that is
needed is a second relocation section referencing a second (in the case of
non-ET_REL objects perhaps the static) symbol table. Whether this split
would really be necessary in ET_REL objects I doubt in the first place, so
it's perhaps just a job of the static linker to separate the relocations
accordingly. The consequence would be the need for a new set of DT_*
tags, which, along with the symbol type, ought to be OS-specific (whereas
the new relocation type is OS-independent, and hence meaningless for
OSes not supporting STT_GNU_IFUNC).

Jan

>>> "H.J. Lu" <hjl....@gmail.com> 25.05.09 20:56 >>>

H.J. Lu

unread,
May 26, 2009, 10:39:09 AM5/26/09
to Jan Beulich, Generic System V Application Binary Interface, IA32 System V Application Binary Interface, Ulrich Drepper, Nick Clifton, Binutils, GNU C Library, dis...@x86-64.org
We have 2 issues:

1. Should the new type be generic or OS specific?

Since only Linux is interested in the new type, we make it OS specific.

2. How should locally defined symbols with the new type be handled?

I don't see the fundamental difference between the new relocation and
the new DT_* tags. The end result is the same. If your OS doesn't support
them, the application will crash if they are used. I will propose a new
x86-64 psABI extension, which will be optional. If an OS supports
STT_GNU_IFUNC, it must support R_X86_64_IRELATIVE.


H.J.

--
H.J.

H.J. Lu

unread,
May 26, 2009, 10:41:48 AM5/26/09
to Ulrich Drepper, Jan Beulich, Generic System V Application Binary Interface, IA32 System V Application Binary Interface, Nick Clifton, Binutils, GNU C Library, dis...@x86-64.org
>
> I don't know HJ's reasons for posting this on this list.  I don't
> consider any of this up for discussion.  If some OS wants to not
> implement this, by all means, don't do it.  This doesn't mean the rest
> can or should be held back.
>

It is mainly informationally so that I can refer people to this post later
if someone is interested in it.


--
H.J.

Jan Beulich

unread,
May 26, 2009, 11:31:45 AM5/26/09
to H.J. Lu, Generic System V Application Binary Interface, IA32 System V Application Binary Interface, Ulrich Drepper, Nick Clifton, Binutils, GNU C Library, dis...@x86-64.org
>>> "H.J. Lu" <hjl....@gmail.com> 26.05.09 16:39 >>>

>2. How should locally defined symbols with the new type be handled?
>
>I don't see the fundamental difference between the new relocation and
>the new DT_* tags. The end result is the same. If your OS doesn't support
>them, the application will crash if they are used. I will propose a new
>x86-64 psABI extension, which will be optional. If an OS supports
>STT_GNU_IFUNC, it must support R_X86_64_IRELATIVE.

The fundamental difference is that the new-relocation-type approach is
not matching the general ELF idea, whereas the new dynamic-tag-approach
fits well with other ELF definitions.

Jan

H.J. Lu

unread,
May 26, 2009, 11:43:50 AM5/26/09
to Jan Beulich, Generic System V Application Binary Interface, IA32 System V Application Binary Interface, Ulrich Drepper, Nick Clifton, Binutils, GNU C Library, dis...@x86-64.org

Relocation types are defined in the psABI. I don't see any problems
with R_X86_64_IRELATIVE.

--
H.J.

H.J. Lu

unread,
May 26, 2009, 12:45:31 PM5/26/09
to Rod....@sun.com, gener...@googlegroups.com, GNU C Library, dis...@x86-64.org, Binutils, IA32 System V Application Binary Interface, Nick Clifton, Ulrich Drepper
On Tue, May 26, 2009 at 9:40 AM, Rod Evans <Rod....@sun.com> wrote:
> Late last year there was a discussion in regards STT_IFUNC, and we
> thought you'd settled on this name (no _GNU_) and the associated
> value of 7.
>
> I guess we jumped the gun.  Although we have no immediate plans to
> implement support for this, we did reserve the name-space, so that
> if nothing else we could identify new objects with this definition:
>
>  sys/elf.h:#define   STT_IFUNC   7   /* indirect code object (unused) */
>
>
> I assume we should now remove this dead-wood and reserve the STT_LOOS
> value instead.
>

Personally, I'd like to see

#define STT_IFUNC 7 /* indirect code object (unused) */

But since 7 is the last used generic symbol type and not all OSes
agree on STT_IFUNC, we moved it to OS specific range. We can't
wait forever on STT_IFUNC. If we want STT_IFUNC, we should
do it now. Otherwise we will use STT_GNU_IFUNC.

--
H.J.

H.J. Lu

unread,
May 26, 2009, 12:47:59 PM5/26/09
to Ian Lance Taylor, ia32...@googlegroups.com, Jan Beulich, Generic System V Application Binary Interface, Ulrich Drepper, Nick Clifton, Binutils, GNU C Library, dis...@x86-64.org
On Tue, May 26, 2009 at 9:30 AM, Ian Lance Taylor <ia...@google.com> wrote:
> "H.J. Lu" <hjl....@gmail.com> writes:
>
>> I don't see the fundamental difference between the new relocation and
>> the new DT_* tags. The end result is the same. If your OS doesn't support
>> them, the application will crash if they are used. I will propose a new
>> x86-64 psABI extension, which will be optional. If an OS supports
>> STT_GNU_IFUNC, it must support R_X86_64_IRELATIVE.
>
> One difference is that a new relocation has to be defined for every
> processor ABI separately.  New DT_* tags can be defined once.
>

Sure. But R_*_IRELATIVE is much simpler to implement in static and
dynamic linkers.

--
H.J.

Ian Lance Taylor

unread,
May 26, 2009, 12:55:03 PM5/26/09
to H.J. Lu, ia32...@googlegroups.com, Jan Beulich, Generic System V Application Binary Interface, Ulrich Drepper, Nick Clifton, Binutils, GNU C Library, dis...@x86-64.org
"H.J. Lu" <hjl....@gmail.com> writes:

That is not a convincing argument when it comes to standardizing
something. The DT_* tags are not difficult to implement.

Jakub's comment about prelink seems relevant, however.

Ian

H.J. Lu

unread,
May 26, 2009, 1:07:36 PM5/26/09
to Jan Beulich, Generic System V Application Binary Interface, IA32 System V Application Binary Interface, Ulrich Drepper, Nick Clifton, Binutils, GNU C Library, dis...@x86-64.org

Here is the proposed update for x86-64 psABI.


--
H.J.

x86-64-psABI-ifunc-1.patch

H.J. Lu

unread,
May 27, 2009, 9:09:11 AM5/27/09
to Jan Beulich, Generic System V Application Binary Interface, IA32 System V Application Binary Interface, Ulrich Drepper, Nick Clifton, Binutils, GNU C Library, dis...@x86-64.org
On Mon, May 25, 2009 at 11:52 PM, Jan Beulich <JBeu...@novell.com> wrote:
> I have to admit that I don't see why a new symbol type *and* a new
> relocation type would be necessary here. If the to-be-relocated symbols'
> name is to not appear in the original (dynamic) symbol table, then all that is
> needed is a second relocation section referencing a second (in the case of
> non-ET_REL objects perhaps the static) symbol table. Whether this split
> would really be necessary in ET_REL objects I doubt in the first place, so
> it's perhaps just a job of the static linker to separate the relocations
> accordingly. The consequence would be the need for a new set of DT_*
> tags, which, along with the symbol type, ought to be OS-specific (whereas
> the new relocation type is OS-independent, and hence meaningless for
> OSes not supporting STT_GNU_IFUNC).

After looking another look, DT_* may be a good idea. STT_GNU_IFUNC
can be in DSO, dynamic executable and static executable. We need a way
to make it to work for all 3 cases. I think we can use DT_XXX to mark the
indirect relocation table for relocations against locally defined STT_GNU_IFUNC
symbols

DT_IRELA
This element holds the address of the indirect relocation table with
explicit addends, such as Elf32_Rela for the 32-bit file class or
Elf64_Rela for the 64-bit file class. If this element is present,
the dynamic
structure must also have DT_IRELASZ and DT_IRELAENT elements.

DT_IRELASZ
This element holds the total size, in bytes, of the DT_IRELA
relocation table.

DT_IRELAENT
This element holds the size, in bytes, of the DT_IRELA relocation entry.

DT_IREL
This element is similar to DT_IRELA, except its table has implicit
addends, such as Elf32_Rel for the 32-bit file class or Elf64_Rel for
the 64-bit file class. If this element is present, the dynamic structure
must also have DT_IRELSZ and DT_IRELENT elements.

DT_IRELSZ
This element holds the total size, in bytes, of the DT_IREL
relocation table.

DT_IRELENT
This element holds the size, in bytes, of the DT_IREL relocation entry.

Relocations in the indirect relocation table don't require name lookup
and their symbol values are zero. The value used in the relocation is


the program address returned by the function, which takes no arguments,

at the address of the result of the corresponding R_*_* relocation.

The purpose of the indirect relocation table to support executables and


avoid name lookup for locally defined STT_GNU_IFUNC symbols at load-time.

The indirect relocation table is optional. Either DT_IRELA or DT_IREL may
occur, not both. It should processed as soon as the object is relocated.


H.J.

--
H.J.

H.J. Lu

unread,
May 27, 2009, 1:31:23 PM5/27/09
to Ulrich Drepper, Jan Beulich, Generic System V Application Binary Interface, IA32 System V Application Binary Interface, Nick Clifton, Binutils, GNU C Library, dis...@x86-64.org
On Wed, May 27, 2009 at 10:27 AM, Ulrich Drepper <dre...@redhat.com> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1

>
> H.J. Lu wrote:
>> After looking another look, DT_* may be a good idea. STT_GNU_IFUNC
>> can be in DSO, dynamic executable and static executable. We need a way
>> to make it to work for all 3 cases.
>
> And?  Relocations of course also work in all the cases.
>
> It is a braindead idea to invent a new data structure every time some
> gets added.  Especially if there is already one which perfectly fits the
> bill.  There is no reason whatsoever to not use a relocation.  The
> introduction of a DT_* described data structure just makes things more
> complicated at runtime.
>
> The argument that only one thing for all architectures has to be changed
> is irrelevant.  The amount of work needed in the linker in negligible.
> On the other hand, there have to be completely different implementations
> for the fancy new data structure for different architectures if the
> function pointer implementation differs.
>
>
> Using R_*_IRELATIVE relocations is the right way to handle this.
>

How to do you handle R_*_PC32 relocation to a locally defined
STT_GNU_IFUNC symbol in dynamic and static executables?


--
H.J.

H.J. Lu

unread,
Jun 1, 2009, 3:46:26 PM6/1/09
to Generic System V Application Binary Interface, GNU C Library, dis...@x86-64.org, Binutils, IA32 System V Application Binary Interface, Nick Clifton, Ulrich Drepper
Hi,

Here is the current proposal implemented in the Linux binutils
2.19.51.0.7.

H.J.
---
STT_GNU_IFUNC

R_*_IRELATIVE

All references to a STT_GNU_IFUNC symbol, including function call and
function pointer, will go through a PLT slot, which jumps to the address
stored in the GOT entry. If the STT_GNU_IFUNC symbol is locally defined,
a R_*_IRELATIVE relocation will be applied to the GOT entry at load time.
Otherwise, dynamic linker will lookup the symbol at the first call to the
function and update the GOT entry. This applies to all usages of
STT_GNU_IFUNC symbols in shared library, dynamic executable and static
executable.

Ian Lance Taylor

unread,
Jun 1, 2009, 4:07:23 PM6/1/09
to ia32...@googlegroups.com, Generic System V Application Binary Interface, GNU C Library, dis...@x86-64.org, Binutils, Nick Clifton, Ulrich Drepper
"H.J. Lu" <hjl....@gmail.com> writes:

> R_*_IRELATIVE
>
> This relocation is similar to R_*_RELATIVE except that the
> value used in this relocation is the program address returned
> by the function, which takes no arguments, at the address of
> the result of the corresponding R_*_RELATIVE relocation.
>
> The purpose of this relocation to avoid name lookup for locally
> defined STT_GNU_IFUNC symbols at load-time.

How is the "corresponding R_*_RELATIVE relocation" determined?

Ian

H.J. Lu

unread,
Jun 1, 2009, 4:12:44 PM6/1/09
to ia32...@googlegroups.com, Generic System V Application Binary Interface, GNU C Library, dis...@x86-64.org, Binutils, Nick Clifton, Ulrich Drepper

I added "as specified in the processor-specific ABI":

R_*_IRELATIVE

This relocation is similar to R_*_RELATIVE except that the
value used in this relocation is the program address returned
by the function, which takes no arguments, at the address of

the result of the corresponding R_*_RELATIVE relocation as
specified in the processor-specific ABI.


--
H.J.

H.J. Lu

unread,
Jun 1, 2009, 4:14:43 PM6/1/09
to gener...@googlegroups.com, GNU C Library, dis...@x86-64.org, Binutils, IA32 System V Application Binary Interface, Nick Clifton, Ulrich Drepper
On Mon, Jun 1, 2009 at 1:00 PM, Roland McGrath <rol...@redhat.com> wrote:
>
> To be a full description, it should say something about the ABI of the
> entry-point that returns the function pointer.  Is it "the prevailing
> normal ABI" for a function of no arguments returning a pointer to function?
> i.e., with whatever call-clobbered registers et al that generically entails.
> Or is it a special-case ABI to be defined precisely in the
> processor-specific spec?  However much or little the specification of the
> ELF feature per se wants to say about this, it should be explicit about
> what it does or doesn't specify for it.
>
>

How about this:

The calling convention of the STT_GNU_IFUNC function, which takes no
arguments and returns a function pointer, should follow the
processor-specific ABI. All rules for caller-saved and callee-saved
registers apply.


--
H.J.

H.J. Lu

unread,
Jun 3, 2009, 6:02:40 PM6/3/09
to Administrator, GNU C Library, dis...@x86-64.org, Binutils, IA32 System V Application Binary Interface, Nick Clifton, Ulrich Drepper

H.J. Lu

unread,
Jun 3, 2009, 6:02:51 PM6/3/09
to Administrator, GNU C Library, dis...@x86-64.org, Binutils, IA32 System V Application Binary Interface, Nick Clifton, Ulrich Drepper
Hi,

Here is the current proposal implemented in the Linux binutils
2.19.51.0.7.

H.J.
---
STT_GNU_IFUNC

R_*_IRELATIVE

All references to a STT_GNU_IFUNC symbol, including function call and

H.J. Lu

unread,
Jun 4, 2009, 4:34:04 PM6/4/09
to ia32...@googlegroups.com, Generic System V Application Binary Interface, GNU C Library, dis...@x86-64.org, Binutils, Nick Clifton, Ulrich Drepper

There is an issue with STT_GNU_IFUNC symbols.

For branch, it is easy to understand. But it is unclear what the value
of STT_GNU_IFUNC symbol should be. In a non-shared object, the value
of the undefined STT_GNU_IFUNC symbol is the address of the PLT entry
since it will only be resolved at run-time. In a shared object,
the value of the STT_GNU_IFUNC symbol will be the address of the
real function. We can't use the address of the PLT entry since
the PLT entry in a shared object may not be usable in non-shared object.

So the undefined STT_GNU_IFUNC symbol will have 2 different values.
Will it be a problem?


--
H.J.

H.J. Lu

unread,
Jun 6, 2009, 8:11:09 AM6/6/09
to ia32...@googlegroups.com, Generic System V Application Binary Interface, GNU C Library, dis...@x86-64.org, Binutils, Nick Clifton, Ulrich Drepper
Hi,

There is an ordering issue on STT_GNU_IFUNC functions. In shared object,
we need dynamic relocation to get the real function address when there is a
non-GOT reference against a STT_GNU_IFUNC symbols. A STT_GNU_IFUNC
function may use some data which need to be relocated first. Possible solutions:

1. A STT_GNU_IFUNC function should never access any data which need
relocation. Or
2. Dynamic relocations against STT_GNU_INFUNC symbols should be
placed after all other relocations.

Any comments?

Thanks.


H.J.

H.J. Lu

unread,
Jun 6, 2009, 11:21:44 AM6/6/09
to gener...@googlegroups.com, ia32...@googlegroups.com, GNU C Library, dis...@x86-64.org, Binutils, Nick Clifton, Ulrich Drepper
On Sat, Jun 6, 2009 at 5:55 AM, Roland McGrath <rol...@redhat.com> wrote:
>
>> 1. A STT_GNU_IFUNC function should never access any data which need
>> relocation.
>
> This does not seem like too much of a constraint, given that it also
> unavoidably has to work before the DSO's initializers have run.
> i.e., it is always special-purpose code that has to be written very
> carefully.  Being PIC code it should not be relying on much to have been
> done before.  It just has to avoid any PLT calls or other GOT use itself.

>
>> 2. Dynamic relocations against STT_GNU_INFUNC symbols should be
>> placed after all other relocations.
>
> This is not possible, is it?  Some DSO has a reference to "&strlen".
> It has no idea that libc's definition will be STT_GNU_IFUNC.
> The DSO might even have been linked against a libc.so that did
> not use STT_GNU_IFUNC to define "strlen".
>
> The only other alternative to #1 that I see is some scheme whereby "&func"
> will in all cases resolve to a PLT entry rather than the actual
> STT_GNU_IFUNC symbol's st_value.  i.e., the ifunc resolver is only called
> for PLT resolution (and you can do all those last for BIND_NOW).
>
> e.g. in the defining DSO make ld generate a PLT entry with second symbol a
> la executables' PLT entries, and then have rtld ignore the STT_GNU_IFUNC
> symbol when resolving non-PLT relocs.  (Seems highly dubious.)
>
> But in fact any scheme with that result might be undesireable in practice.
> If the executable does not refer to "&func", then we don't have the pointer
> equality issue and so DSOs with function pointer tables pointing to other
> DSOs' entry points would do the extra indirection of a PLT jump when it
> could be avoided except for this initialization order question.
>
>

This patch implements #2. It may not solve all the problems. But it
works for my simple testcase.

--
H.J.
----
bfd/

2009-06-06 H.J. Lu <hongj...@intel.com>

* elf32-i386.c (elf_i386_link_hash_table): Add irelifunc.
(elf_i386_link_hash_table_create): Initialize irelifunc.
(elf_i386_check_relocs): Updated. Set up irelifunc for
shared objects.
(elf_i386_allocate_dynrelocs): Use irelifunc for dynamic
relocation for non-GOT reference of STT_GNU_IFUNC symbol in
shared objects.
(elf_i386_relocate_section): Likewise.

* elf64-x86-64.c (elf64_x86_64_link_hash_table): Add irelifunc.
(elf64_x86_64_link_hash_table_create): Initialize irelifunc.
(elf64_x86_64_check_relocs): Updated. Set up irelifunc for
shared objects.
(elf64_x86_64_allocate_dynrelocs): Use irelifunc for dynamic
relocation for non-GOT reference of STT_GNU_IFUNC symbol in
shared objects.
(elf64_x86_64_relocate_section): Likewise.

* elf-bfd.h (_bfd_elf_create_static_ifunc_sections): Renamed to
...
(_bfd_elf_create_ifunc_sections): This.

* elflink.c (_bfd_elf_create_static_ifunc_sections): Renamd to
...
(_bfd_elf_create_ifunc_sections): This. Create .rel[a].ifunc
for shared objects.

ld/

2009-06-06 H.J. Lu <hongj...@intel.com>

* scripttempl/elf.sc: Add .rel.ifunc and .rela.ifunc.

binutils-ifunc-reloc-1.patch

H.J. Lu

unread,
Jun 6, 2009, 11:30:18 AM6/6/09
to Administrator, ia32...@googlegroups.com, GNU C Library, dis...@x86-64.org, Binutils, Nick Clifton, Ulrich Drepper
On Sat, Jun 6, 2009 at 5:55 AM, Roland McGrath <rol...@redhat.com> wrote:
>
>> 1. A STT_GNU_IFUNC function should never access any data which need
>> relocation.
>
> This does not seem like too much of a constraint, given that it also
> unavoidably has to work before the DSO's initializers have run.
> i.e., it is always special-purpose code that has to be written very
> carefully.  Being PIC code it should not be relying on much to have been
> done before.  It just has to avoid any PLT calls or other GOT use itself.
>
>> 2. Dynamic relocations against STT_GNU_INFUNC symbols should be
>> placed after all other relocations.
>
binutils-ifunc-reloc-1.patch

H.J. Lu

unread,
Jun 8, 2009, 9:57:25 AM6/8/09
to Paul Brook, Admini...@x86-64.org, dis...@x86-64.org, GNU C Library, Nick Clifton, gener...@googlegroups.com, Ulrich Drepper, ia32...@googlegroups.com, Roland McGrath
On Mon, Jun 8, 2009 at 6:30 AM, Paul Brook<pa...@codesourcery.com> wrote:
>> The only other alternative to #1 that I see is some scheme whereby "&func"
>> will in all cases resolve to a PLT entry rather than the actual
>> STT_GNU_IFUNC symbol's st_value.  i.e., the ifunc resolver is only called
>> for PLT resolution (and you can do all those last for BIND_NOW).
>
> This will break pointer comparisons across modules.
>

Please try the current binutils in CVS. I think I have fixed all
problems. If not,
please open a bug report with a testcase.

Thanks.


--
H.J.

Reply all
Reply to author
Forward
0 new messages