Hi,

I'm working in the Linaro toolchain team on adding ARM support for GNU
indirect functions (STT_GNU_IFUNCs).  The indirect function feature
requires a new relocation type, which is typically called R_FOO_IRELATIVE.
I'd therefore like to propose a new R_ARM_IRELATIVE relocation type for
the ARM EABI.

This relocation is only used in ET_EXEC and ET_DYN objects.  If the
object has a PT_DYNAMIC tag, then the relocation may only appear in
the DT_REL(A) table; it cannot appear in the DT_JMPREL table.
(Note that this is a deliberate divergence from the x86 and x86_64
behaviour, which does allow the IRELATIVE relocation to be used in
DT_JMPREL table, but which requires it to be applied at load time,
regardless of bind-now vs. lazy semantics.  However, the proposed
ARM behaviour matches that of other targets like PowerPC.)

Static ET_EXEC objects may have R_ARM_IRELATIVE relocations.  In this
case, the relocations are stored in a relocation table that contains no
other type of relocation (not even R_ARM_NONE).  The static linker
defines two symbols:

  __rel_iplt_start, which the linker points to the start of this table
  __rel_iplt_end, which the linker points to the last byte of this table
    plus one.

The two symbols are equal if the executable has no R_ARM_IRELATIVE
relocations.  It is the executable's responsibility to apply these
relocations as appropriate.  If the static linker emits a symbol table,
then it is not defined whether the linker includes __rel_iplt_start and
__rel_iplt_end in that symbol table.

The static linker may (or may not) define __rel_iplt_start and
__rel_iplt_end in dynamic objects.  However, if it does define them,
the symbols must refer to part of the DT_REL(A) table, and it is still
the dynamic linker's responsibility to apply the relocations.

An R_ARM_IRELATIVE relocation applies to all bits of a 4-byte field.
There are no alignment restrictions on the field.  The relocation
value is:

  call(B(S) + A)

where call(X) represents the value of r0 after performing an indirect
branch-with-link-and-exchange (BLX) to address X.

The dynamic linker must have applied all earlier DT_REL(A) relocations
before calling X.  It is undefined whether later DT_REL(A) relocations
have been applied or not, and X must not make any assumptions about the
status of those relocations.

If there is an R_ARM_IRELATIVE relocation with symbol S and addend A,
then the relocation value:

  call(B(S) + A)

is considered to be a load-time constant.  It is possible for an object
to have more than one R_ARM_IRELATIVE relocation with the same value
of B(S) + A, and in such a case, it is not defined whether the dynamic
linker invokes the target function each time, or whether it caches the
results of earlier calls.

I realise this isn't the cleanest extension in the world.  As Alan Modra
noted on the binutils list, the choice of __rel_iplt_start and __rel_iplt_end
is particularly unfortunate, since the relocations are not specific to
"PLTs".  However, the GNU extension has been defined this way,
so unfortunately there isn't much room for target-specific variation.

Thanks,
Richard

_______________________________________________
linaro-toolchain mailing list
linaro-toolchain@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-toolchain

Reply via email to