[PATCH] aarch64: Enable ifunc support.

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] aarch64: Enable ifunc support.

Will Newton

Add support for handling the R_AARCH64_IRELATIVE relocation and
STT_GNU_IFUNC symbols to the aarch64 port.

ports/ChangeLog.aarch64:

2013-11-25  Will Newton  <[hidden email]>

        * sysdeps/aarch64/dl-irel.h: Include ldsodefs.h.
        (ELF_MACHINE_IRELA): Define.  (elf_ifunc_invoke): Pass
        hwcap to ifunc resolver function.  (elf_irela): New function.
        * sysdeps/aarch64/dl-machine.h: Include dl-irel.h.
        (elf_machine_rela) Handle STT_GNU_IFUNC symbols and
        R_AARCH64_IRELATIVE relocations.  (elf_machine_lazy_rel):
        Handle R_AARCH64_IRELATIVE relocations.
---
 ports/sysdeps/aarch64/dl-irel.h    | 22 +++++++++++++++++++---
 ports/sysdeps/aarch64/dl-machine.h | 20 ++++++++++++++++++++
 2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/ports/sysdeps/aarch64/dl-irel.h b/ports/sysdeps/aarch64/dl-irel.h
index 1a3811e..f37ee39 100644
--- a/ports/sysdeps/aarch64/dl-irel.h
+++ b/ports/sysdeps/aarch64/dl-irel.h
@@ -22,15 +22,31 @@

 #include <stdio.h>
 #include <unistd.h>
+#include <ldsodefs.h>

-/* AArch64 does not yet implement IFUNC support.  However since
-   2011-06-20 provision of a elf_ifunc_invoke has been mandatory.  */
+#define ELF_MACHINE_IRELA 1

 static inline ElfW(Addr)
 __attribute ((always_inline))
 elf_ifunc_invoke (ElfW(Addr) addr)
 {
-  return ((ElfW(Addr) (*) (void)) (addr)) ();
+  return ((ElfW(Addr) (*) (unsigned long int)) (addr)) (GLRO(dl_hwcap));
+}
+
+static inline void
+__attribute ((always_inline))
+elf_irela (const ElfW(Rela) *reloc)
+{
+  ElfW(Addr) *const reloc_addr = (void *) reloc->r_offset;
+  const unsigned long int r_type = ELFW(R_TYPE) (reloc->r_info);
+
+  if (__glibc_likely (r_type == R_AARCH64_IRELATIVE))
+    {
+      ElfW(Addr) value = elf_ifunc_invoke (reloc->r_addend);
+      *reloc_addr = value;
+    }
+  else
+    __libc_fatal ("unexpected reloc type in static binary");
 }

 #endif
diff --git a/ports/sysdeps/aarch64/dl-machine.h b/ports/sysdeps/aarch64/dl-machine.h
index 71dd6b3..01a214f 100644
--- a/ports/sysdeps/aarch64/dl-machine.h
+++ b/ports/sysdeps/aarch64/dl-machine.h
@@ -23,6 +23,7 @@

 #include <tls.h>
 #include <dl-tlsdesc.h>
+#include <dl-irel.h>

 /* Return nonzero iff ELF header is compatible with the running host.  */
 static inline int __attribute__ ((unused))
@@ -243,6 +244,12 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
       struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
       ElfW(Addr) value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;

+      if (sym != NULL
+  && __glibc_unlikely (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC)
+  && __glibc_likely (sym->st_shndx != SHN_UNDEF)
+  && __glibc_likely (!skip_ifunc))
+ value = elf_ifunc_invoke (value);
+
       switch (r_type)
  {
  case R_AARCH64_COPY:
@@ -331,6 +338,12 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
     }
   break;

+ case R_AARCH64_IRELATIVE:
+  value = map->l_addr + reloc->r_addend;
+  value = elf_ifunc_invoke (value);
+  *reloc_addr = value;
+  break;
+
  default:
   _dl_reloc_bad_type (map, r_type, 0);
   break;
@@ -374,6 +387,13 @@ elf_machine_lazy_rel (struct link_map *map,
       td->entry = (void*)(D_PTR (map, l_info[ADDRIDX (DT_TLSDESC_PLT)])
   + map->l_addr);
     }
+  else if (__glibc_unlikely (r_type == R_AARCH64_IRELATIVE))
+    {
+      ElfW(Addr) value = map->l_addr + reloc->r_addend;
+      if (__glibc_likely (!skip_ifunc))
+ value = elf_ifunc_invoke (value);
+      *reloc_addr = value;
+    }
   else
     _dl_reloc_bad_type (map, r_type, 1);
 }
--
1.8.1.4

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] aarch64: Enable ifunc support.

Marcus
On 26 November 2013 08:57, Will Newton <[hidden email]> wrote:

> diff --git a/ports/sysdeps/aarch64/dl-irel.h b/ports/sysdeps/aarch64/dl-irel.h
> index 1a3811e..f37ee39 100644
> --- a/ports/sysdeps/aarch64/dl-irel.h
> +++ b/ports/sysdeps/aarch64/dl-irel.h
> @@ -22,15 +22,31 @@
>
>  #include <stdio.h>
>  #include <unistd.h>
> +#include <ldsodefs.h>

Will, is this include needed?

/Marcus
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] aarch64: Enable ifunc support.

Will Newton
On 26 November 2013 14:51, Marcus Shawcroft <[hidden email]> wrote:

> On 26 November 2013 08:57, Will Newton <[hidden email]> wrote:
>
>> diff --git a/ports/sysdeps/aarch64/dl-irel.h b/ports/sysdeps/aarch64/dl-irel.h
>> index 1a3811e..f37ee39 100644
>> --- a/ports/sysdeps/aarch64/dl-irel.h
>> +++ b/ports/sysdeps/aarch64/dl-irel.h
>> @@ -22,15 +22,31 @@
>>
>>  #include <stdio.h>
>>  #include <unistd.h>
>> +#include <ldsodefs.h>
>
> Will, is this include needed?

Yes, I believe it is needed for GLRO and ELFW, although everything
builds without it as ldsodefs.h is included all over the place.
stdio.h is required for __libc_fatal, not sure about unistd.h.

--
Will Newton
Toolchain Working Group, Linaro
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] aarch64: Enable ifunc support.

Marcus
In reply to this post by Will Newton
On 26 November 2013 08:57, Will Newton <[hidden email]> wrote:

>
> Add support for handling the R_AARCH64_IRELATIVE relocation and
> STT_GNU_IFUNC symbols to the aarch64 port.
>
> ports/ChangeLog.aarch64:
>
> 2013-11-25  Will Newton  <[hidden email]>
>
>         * sysdeps/aarch64/dl-irel.h: Include ldsodefs.h.
>         (ELF_MACHINE_IRELA): Define.  (elf_ifunc_invoke): Pass
>         hwcap to ifunc resolver function.  (elf_irela): New function.
>         * sysdeps/aarch64/dl-machine.h: Include dl-irel.h.
>         (elf_machine_rela) Handle STT_GNU_IFUNC symbols and
>         R_AARCH64_IRELATIVE relocations.  (elf_machine_lazy_rel):
>         Handle R_AARCH64_IRELATIVE relocations.

OK /Marcus
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] aarch64: Enable ifunc support.

Carlos O'Donell-6
In reply to this post by Will Newton
On 11/26/2013 03:57 AM, Will Newton wrote:

>
> Add support for handling the R_AARCH64_IRELATIVE relocation and
> STT_GNU_IFUNC symbols to the aarch64 port.
>
> ports/ChangeLog.aarch64:
>
> 2013-11-25  Will Newton  <[hidden email]>
>
> * sysdeps/aarch64/dl-irel.h: Include ldsodefs.h.
> (ELF_MACHINE_IRELA): Define.  (elf_ifunc_invoke): Pass
> hwcap to ifunc resolver function.  (elf_irela): New function.
> * sysdeps/aarch64/dl-machine.h: Include dl-irel.h.
> (elf_machine_rela) Handle STT_GNU_IFUNC symbols and
> R_AARCH64_IRELATIVE relocations.  (elf_machine_lazy_rel):
> Handle R_AARCH64_IRELATIVE relocations.

You don't appear to fix elf_ifunc_invoke to pass dl_hwcap to the
resolver which will need this to detect the different kinds of
hardware?

Please see the 32-bit ARM port.

Cheers,
Carlos.

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] aarch64: Enable ifunc support.

Carlos O'Donell-6
On 11/26/2013 10:16 AM, Carlos O'Donell wrote:

> On 11/26/2013 03:57 AM, Will Newton wrote:
>>
>> Add support for handling the R_AARCH64_IRELATIVE relocation and
>> STT_GNU_IFUNC symbols to the aarch64 port.
>>
>> ports/ChangeLog.aarch64:
>>
>> 2013-11-25  Will Newton  <[hidden email]>
>>
>> * sysdeps/aarch64/dl-irel.h: Include ldsodefs.h.
>> (ELF_MACHINE_IRELA): Define.  (elf_ifunc_invoke): Pass
>> hwcap to ifunc resolver function.  (elf_irela): New function.
>> * sysdeps/aarch64/dl-machine.h: Include dl-irel.h.
>> (elf_machine_rela) Handle STT_GNU_IFUNC symbols and
>> R_AARCH64_IRELATIVE relocations.  (elf_machine_lazy_rel):
>> Handle R_AARCH64_IRELATIVE relocations.
>
> You don't appear to fix elf_ifunc_invoke to pass dl_hwcap to the
> resolver which will need this to detect the different kinds of
> hardware?

Sorry, I'm wrong, I missed that line in your patch. You do pass
dl_hwcap.

c.

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] aarch64: Enable ifunc support.

Carlos O'Donell-6
In reply to this post by Will Newton
On 11/26/2013 03:57 AM, Will Newton wrote:
>
> Add support for handling the R_AARCH64_IRELATIVE relocation and
> STT_GNU_IFUNC symbols to the aarch64 port.

How did you test this?

> ports/ChangeLog.aarch64:
>
> 2013-11-25  Will Newton  <[hidden email]>
>
> * sysdeps/aarch64/dl-irel.h: Include ldsodefs.h.
> (ELF_MACHINE_IRELA): Define.  (elf_ifunc_invoke): Pass
> hwcap to ifunc resolver function.  (elf_irela): New function.
> * sysdeps/aarch64/dl-machine.h: Include dl-irel.h.
> (elf_machine_rela) Handle STT_GNU_IFUNC symbols and
> R_AARCH64_IRELATIVE relocations.  (elf_machine_lazy_rel):
> Handle R_AARCH64_IRELATIVE relocations.
> ---
>  ports/sysdeps/aarch64/dl-irel.h    | 22 +++++++++++++++++++---
>  ports/sysdeps/aarch64/dl-machine.h | 20 ++++++++++++++++++++
>  2 files changed, 39 insertions(+), 3 deletions(-)
>
> diff --git a/ports/sysdeps/aarch64/dl-irel.h b/ports/sysdeps/aarch64/dl-irel.h
> index 1a3811e..f37ee39 100644
> --- a/ports/sysdeps/aarch64/dl-irel.h
> +++ b/ports/sysdeps/aarch64/dl-irel.h
> @@ -22,15 +22,31 @@
>
>  #include <stdio.h>
>  #include <unistd.h>
> +#include <ldsodefs.h>
>
> -/* AArch64 does not yet implement IFUNC support.  However since
> -   2011-06-20 provision of a elf_ifunc_invoke has been mandatory.  */
> +#define ELF_MACHINE_IRELA 1

OK.

>
>  static inline ElfW(Addr)
>  __attribute ((always_inline))
>  elf_ifunc_invoke (ElfW(Addr) addr)
>  {
> -  return ((ElfW(Addr) (*) (void)) (addr)) ();
> +  return ((ElfW(Addr) (*) (unsigned long int)) (addr)) (GLRO(dl_hwcap));

OK.

> +}
> +
> +static inline void
> +__attribute ((always_inline))
> +elf_irela (const ElfW(Rela) *reloc)
> +{
> +  ElfW(Addr) *const reloc_addr = (void *) reloc->r_offset;
> +  const unsigned long int r_type = ELFW(R_TYPE) (reloc->r_info);
> +
> +  if (__glibc_likely (r_type == R_AARCH64_IRELATIVE))
> +    {
> +      ElfW(Addr) value = elf_ifunc_invoke (reloc->r_addend);
> +      *reloc_addr = value;
> +    }
> +  else
> +    __libc_fatal ("unexpected reloc type in static binary");
>  }

OK.

>
>  #endif
> diff --git a/ports/sysdeps/aarch64/dl-machine.h b/ports/sysdeps/aarch64/dl-machine.h
> index 71dd6b3..01a214f 100644
> --- a/ports/sysdeps/aarch64/dl-machine.h
> +++ b/ports/sysdeps/aarch64/dl-machine.h
> @@ -23,6 +23,7 @@
>
>  #include <tls.h>
>  #include <dl-tlsdesc.h>
> +#include <dl-irel.h>
>
>  /* Return nonzero iff ELF header is compatible with the running host.  */
>  static inline int __attribute__ ((unused))
> @@ -243,6 +244,12 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
>        struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
>        ElfW(Addr) value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
>
> +      if (sym != NULL
> +  && __glibc_unlikely (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC)
> +  && __glibc_likely (sym->st_shndx != SHN_UNDEF)
> +  && __glibc_likely (!skip_ifunc))
> + value = elf_ifunc_invoke (value);

OK.

> +
>        switch (r_type)
>   {
>   case R_AARCH64_COPY:
> @@ -331,6 +338,12 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
>      }
>    break;
>
> + case R_AARCH64_IRELATIVE:
> +  value = map->l_addr + reloc->r_addend;
> +  value = elf_ifunc_invoke (value);
> +  *reloc_addr = value;
> +  break;

OK.

> +
>   default:
>    _dl_reloc_bad_type (map, r_type, 0);
>    break;
> @@ -374,6 +387,13 @@ elf_machine_lazy_rel (struct link_map *map,
>        td->entry = (void*)(D_PTR (map, l_info[ADDRIDX (DT_TLSDESC_PLT)])
>    + map->l_addr);
>      }
> +  else if (__glibc_unlikely (r_type == R_AARCH64_IRELATIVE))
> +    {
> +      ElfW(Addr) value = map->l_addr + reloc->r_addend;
> +      if (__glibc_likely (!skip_ifunc))
> + value = elf_ifunc_invoke (value);
> +      *reloc_addr = value;

OK.

> +    }
>    else
>      _dl_reloc_bad_type (map, r_type, 1);
>  }
>

Looks good to me as long as your testing makes sense.

Cheers,
Carlos.
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] aarch64: Enable ifunc support.

Will Newton
On 26 November 2013 15:24, Carlos O'Donell <[hidden email]> wrote:
> On 11/26/2013 03:57 AM, Will Newton wrote:
>>
>> Add support for handling the R_AARCH64_IRELATIVE relocation and
>> STT_GNU_IFUNC symbols to the aarch64 port.
>
> How did you test this?

Running the glibc testsuite - which is actually a pretty good test for
the ifunc code. There's no functionality in the aarch64 port yet that
actually uses this yet so I couldn't test that. The only screw up that
the testsuite does not find is failing to pass hwcap correctly to the
resover, but I pretty intensively stared at that code and seen as
everything goes through elf_ifunc_invoke I am happy that it should
work in practice.

--
Will Newton
Toolchain Working Group, Linaro
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] aarch64: Enable ifunc support.

Carlos O'Donell-6
On 11/26/2013 10:39 AM, Will Newton wrote:

> On 26 November 2013 15:24, Carlos O'Donell <[hidden email]> wrote:
>> On 11/26/2013 03:57 AM, Will Newton wrote:
>>>
>>> Add support for handling the R_AARCH64_IRELATIVE relocation and
>>> STT_GNU_IFUNC symbols to the aarch64 port.
>>
>> How did you test this?
>
> Running the glibc testsuite - which is actually a pretty good test for
> the ifunc code. There's no functionality in the aarch64 port yet that
> actually uses this yet so I couldn't test that. The only screw up that
> the testsuite does not find is failing to pass hwcap correctly to the
> resover, but I pretty intensively stared at that code and seen as
> everything goes through elf_ifunc_invoke I am happy that it should
> work in practice.

Perfect, then I'm happy with the patch.

If Marcus is happy then I think you get to check this in.

Cheers,
Carlos.