[PATCH v5 09/13] LoongArch: Linux ABI -- __ifunc_arg_t

caiyinyu caiyinyu@loongson.cn
Thu Jun 9 04:01:44 GMT 2022


Fixed. Thanks.

 >>>>>>>>>>>>>

diff --git a/sysdeps/loongarch/dl-irel.h b/sysdeps/loongarch/dl-irel.h
index 0dfe78c217..4440453f06 100644
--- a/sysdeps/loongarch/dl-irel.h
+++ b/sysdeps/loongarch/dl-irel.h
@@ -21,13 +21,19 @@

  #include <stdio.h>
  #include <unistd.h>
+#include <sys/ifunc.h>

  #define ELF_MACHINE_IRELA 1

  static inline ElfW (Addr) __attribute ((always_inline))
  elf_ifunc_invoke (ElfW (Addr) addr)
  {
-  return ((ElfW (Addr) (*) (void)) (addr)) ();
+  __ifunc_arg_t arg =
+  {
+    ._size = sizeof (__ifunc_arg_t),
+    ._hwcap = GLRO(dl_hwcap),
+  };
+  return ((ElfW(Addr) (*) (const __ifunc_arg_t *)) (addr)) (&arg);
  }

<<<<<<<<<<<<<<<<


在 2022/6/8 下午9:16, Adhemerval Zanella 写道:
>
> On 08/06/2022 03:01, caiyinyu wrote:
>> I made some changes:
>>
>> static inline ElfW (Addr) __attribute ((always_inline))
>> elf_ifunc_invoke (ElfW (Addr) addr)
>> {
>>    __ifunc_arg_t arg =
>>    {
>>      ._size = sizeof (__ifunc_arg_t),
>>      ._hwcap = GLRO(dl_hwcap),
>>    };
>>    return ((ElfW(Addr) (*) *(const __ifunc_arg_t *, void *)*) (addr))
>>           *(&arg, NULL)*;
>> }
>>
> Why would you need the extra argument if now you are passing a struct?
> The idea is if you need extra space (for instance to pack another
> hwcap or any other arch-specific information) you define a new
> __ifunc_arg_t with a different name.  The resolver function will then
> check the size before accessing the correct expected struct.
>
>> otherwise:
>>
>> static inline ElfW (Addr) __attribute ((always_inline))
>> elf_ifunc_invoke (ElfW (Addr) addr)
>> {
>>    __ifunc_arg_t arg =
>>    {
>>      ._size = sizeof (__ifunc_arg_t),
>>      ._hwcap = GLRO(dl_hwcap),
>>    };
>>    return ((ElfW(Addr) (*) *(uint64_t, void *)*) (addr))
>>           *((uint64_t) &arg, NULL)*;
>> }
>>
> I would prefer to avoid alising violations if possible (and uint64_t is
> not usually the correct type for pointer to integer conversion).
>
>> THANKS.
>>
>>
>> diff --git a/sysdeps/loongarch/sys/ifunc.h b/sysdeps/loongarch/sys/ifunc.h
>> new file mode 100644
>> index 0000000000..461df20c96
>> --- /dev/null
>> +++ b/sysdeps/loongarch/sys/ifunc.h
>> @@ -0,0 +1,30 @@
>> +/* Definitions used by LoongArch indirect function resolvers.
>> +   Copyright (C) 2022 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library; if not, see
>> +   <https://www.gnu.org/licenses/>.  */
>> +
>> +#ifndef _SYS_IFUNC_H
>> +#define _SYS_IFUNC_H
>> +
>> +struct __ifunc_arg_t
>> +{
>> +  unsigned long _size; /* Size of the struct, so it can grow.  */
>> +  unsigned long _hwcap;
>> +};
>> +
>> +typedef struct __ifunc_arg_t __ifunc_arg_t;
>> +
>> +#endif
>>
>> <<<<<<<<<<<<<<
>>
>>
>> 在 2022/6/7 下午9:56, Adhemerval Zanella 写道:
>>> On 07/06/2022 06:32, caiyinyu wrote:
>>>> +static inline ElfW (Addr) __attribute ((always_inline))
>>>> +elf_ifunc_invoke (ElfW (Addr) addr)
>>>> +{
>>>> +  return ((ElfW (Addr) (*) (void)) (addr)) ();
>>>>
>>>> At least for RISCV, sparc, aarch64, powerpc, arm; the ifunc resolver expects
>>>> a unsigned long int begin the hardware capability from kernelk (AT_HWCAP).
>>>>
>>>> AArch64 also extends it by passing both uint64_t and a struct with both
>>>> AT_HWCAP and AT_HWCAP2.  I am not sure if loongarch will ever use more
>>>> than the AT_HWCAP.
>>>> *Currently ifuncs (like __memchr_ifunc, __memcpy_ifunc ...) are not used in loongarch, and we will add these in future.*
>>>> *or we can add the following patch (now **AT_HWCAP only) though not woking: ****>>>>>>>>>>>*
>>>>
>>>> diff --git a/sysdeps/loongarch/dl-irel.h b/sysdeps/loongarch/dl-irel.h
>>>> index 0dfe78c217..ef248095b9 100644
>>>> --- a/sysdeps/loongarch/dl-irel.h
>>>> +++ b/sysdeps/loongarch/dl-irel.h
>>>> @@ -21,13 +21,18 @@
>>>>   
>>>>   #include <stdio.h>
>>>>   #include <unistd.h>
>>>> +#include <ldsodefs.h>
>>>> +#include <sysdep.h>
>>>>   
>>>>   #define ELF_MACHINE_IRELA 1
>>>>   
>>>>   static inline ElfW (Addr) __attribute ((always_inline))
>>>>   elf_ifunc_invoke (ElfW (Addr) addr)
>>>>   {
>>>> -  return ((ElfW (Addr) (*) (void)) (addr)) ();
>>>> +  /* The second argument is a void pointer to preserve the extension
>>>> +     fexibility.  */
>>>> +  return ((ElfW(Addr) (*) (uint64_t, void *)) (addr))
>>>> +        (GLRO(dl_hwcap), NULL);
>>>>   }
>>>>   
>>>>   static inline void __attribute ((always_inline))
>>>>
>>>> *<<<<<<<<<<<<<<<<<<*
>>> AArch64 added the extra argument to preserve backwards compatibility, which
>>> is not the case here.  Since ifunc is also used outside glibc, maybe it would
>>> be better to  use the extendable struct as default:
>>>
>>>
>>>   struct __ifunc_arg_t
>>>   {
>>>     unsigned long int _size; /* Size of the struct, so it can grow.  */
>>>     unsigned long int _hwcap;
>>>   };
>>>
>>>   static inline ElfW (Addr) __attribute ((always_inline))
>>>   elf_ifunc_invoke (ElfW (Addr) addr)
>>>   {
>>>     __ifunc_arg_t arg =
>>>     {
>>>       ._size = sizeof (__ifunc_arg_t),
>>>       ._hwcap = GLRO(dl_hwcap),
>>>     }
>>>     return ((ElfW(Addr) (*) (uint64_t, void *)) (addr)) (&arg);
>>>   }
>>>
>>> And then export __ifunc_arg_t on the sys/ifunc.h header like aarch64.



More information about the Libc-alpha mailing list