On Sunday 26 May 2024 02:21:20 Pali Rohár wrote:
> GCC documentation for alias attribute for variables says:
> 
>   https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html
>   Using both the alias and the alias target to access the same object is
>   undefined in a translation unit without a declaration of the alias with
>   the attribute.
> 
> So declare also aliases of import symbols via alias attribute to prevent
> possible undefined behavior. This also reduce memory usage as all aliased
> symbols declared via __MINGW_IMP_SYMBOL will share same global variable.
> 
> Note that aliased symbol has to be declared with "extern" keyword even it
> is not extern and gcc will emit this symbol (as described in documentation).
> 
> So for example:
> 
>   int var_non_alias = 1;
>   int var_target = 2;
>   extern int __attribute__ ((alias ("var_target"))) var_alias;
> 
> Emits symbols:
> 
>   SYMBOL TABLE:
>   [  0](sec -2)(fl 0x00)(ty   0)(scl 103) (nx 1) 0x00000000 test.c
>   File
>   [  2](sec  1)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .text
>   AUX scnlen 0x0 nreloc 0 nlnno 0
>   [  4](sec  2)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .data
>   AUX scnlen 0x8 nreloc 0 nlnno 0
>   [  6](sec  3)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .bss
>   AUX scnlen 0x0 nreloc 0 nlnno 0
>   [  8](sec  4)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000 .rdata$zzz
>   AUX scnlen 0x1e nreloc 0 nlnno 0
>   [ 10](sec  2)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000000 _var_non_alias
>   [ 11](sec  2)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000004 _var_target
>   [ 12](sec  2)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000004 _var_alias
> 
>   Contents of section .data:
>    0000 01000000 02000000                    ........
> ---
>  mingw-w64-crt/misc/imaxabs.c   | 4 ++--
>  mingw-w64-crt/misc/imaxdiv.c   | 3 ++-
>  mingw-w64-crt/misc/strtoimax.c | 6 ++++--
>  mingw-w64-crt/misc/strtoumax.c | 6 ++++--
>  mingw-w64-crt/stdio/atoll.c    | 2 +-
>  5 files changed, 13 insertions(+), 8 deletions(-)
> 
> diff --git a/mingw-w64-crt/misc/imaxabs.c b/mingw-w64-crt/misc/imaxabs.c
> index 4f144a7ad56c..eae73b21f00b 100644
> --- a/mingw-w64-crt/misc/imaxabs.c
> +++ b/mingw-w64-crt/misc/imaxabs.c
> @@ -22,7 +22,7 @@ imaxabs (intmax_t _j)
>  intmax_t (__cdecl *__MINGW_IMP_SYMBOL(imaxabs))(intmax_t) = imaxabs;
>  
>  long long __attribute__ ((alias ("imaxabs"))) __cdecl llabs (long long);
> -long long (__cdecl *__MINGW_IMP_SYMBOL(llabs))(long long) = llabs;
> +extern long long __attribute__((alias 
> (__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(imaxabs))))) (__cdecl 
> *__MINGW_IMP_SYMBOL(llabs))(long long);
>  
>  __int64 __attribute__ ((alias ("imaxabs"))) __cdecl _abs64 (__int64);
> -__int64 (__cdecl *__MINGW_IMP_SYMBOL(_abs64))(__int64) = _abs64;
> +extern __int64 __attribute__((alias 
> (__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(imaxabs))))) (__cdecl 
> *__MINGW_IMP_SYMBOL(_abs64))(__int64);
> diff --git a/mingw-w64-crt/misc/imaxdiv.c b/mingw-w64-crt/misc/imaxdiv.c
> index 7db911fa940c..36800046f5a0 100644
> --- a/mingw-w64-crt/misc/imaxdiv.c
> +++ b/mingw-w64-crt/misc/imaxdiv.c
> @@ -32,4 +32,5 @@ imaxdiv_t (__cdecl *__MINGW_IMP_SYMBOL(imaxdiv))(intmax_t, 
> intmax_t) = imaxdiv;
>  lldiv_t __attribute__ ((alias ("imaxdiv")))
>  __cdecl
>  lldiv (long long, long long); 
> -lldiv_t (__cdecl *__MINGW_IMP_SYMBOL(lldiv))(long long, long long) = lldiv;
> +extern lldiv_t __attribute__ ((alias 
> (__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(imaxdiv)))))
> +(__cdecl *__MINGW_IMP_SYMBOL(lldiv))(long long, long long);
> diff --git a/mingw-w64-crt/misc/strtoimax.c b/mingw-w64-crt/misc/strtoimax.c
> index 7f09869cb0b1..a6a20c3e6244 100644
> --- a/mingw-w64-crt/misc/strtoimax.c
> +++ b/mingw-w64-crt/misc/strtoimax.c
> @@ -115,9 +115,11 @@ intmax_t (__cdecl *__MINGW_IMP_SYMBOL(strtoimax))(const 
> char* __restrict__, char
>  long long __attribute__ ((alias ("strtoimax")))
>  __cdecl
>  strtoll (const char* __restrict__ nptr, char ** __restrict__ endptr, int 
> base);
> -long long (__cdecl *__MINGW_IMP_SYMBOL(strtoll))(const char* __restrict__, 
> char ** __restrict__, int) = strtoll;
> +extern long long __attribute__ ((alias 
> (__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(strtoimax)))))
> +(__cdecl *__MINGW_IMP_SYMBOL(strtoll))(const char* __restrict__, char ** 
> __restrict__, int);
>  
>  __int64 __attribute__ ((alias ("strtoimax")))
>  __cdecl
>  _strtoi64 (const char* __restrict__ nptr, char ** __restrict__ endptr, int 
> base);
> -__int64 (__cdecl *__MINGW_IMP_SYMBOL(_strtoi64))(const char* __restrict__, 
> char ** __restrict__, int) = _strtoi64;
> +extern __int64 __attribute__ ((alias 
> (__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(strtoimax)))))
> +(__cdecl *__MINGW_IMP_SYMBOL(_strtoi64))(const char* __restrict__, char ** 
> __restrict__, int);
> diff --git a/mingw-w64-crt/misc/strtoumax.c b/mingw-w64-crt/misc/strtoumax.c
> index d47a7c90d8f1..f368f5eee128 100644
> --- a/mingw-w64-crt/misc/strtoumax.c
> +++ b/mingw-w64-crt/misc/strtoumax.c
> @@ -113,9 +113,11 @@ uintmax_t (__cdecl *__MINGW_IMP_SYMBOL(strtoumax))(const 
> char* __restrict__, cha
>  unsigned long long __attribute__ ((alias ("strtoumax")))
>  __cdecl
>  strtoull (const char* __restrict__ nptr, char ** __restrict__ endptr, int 
> base);
> -unsigned long long (__cdecl *__MINGW_IMP_SYMBOL(strtoull))(const char* 
> __restrict__, char ** __restrict__, int) = strtoull;
> +extern unsigned long long __attribute__ ((alias 
> (__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(strtoumax)))))
> +(__cdecl *__MINGW_IMP_SYMBOL(strtoull))(const char* __restrict__, char ** 
> __restrict__, int);
>  
>  unsigned __int64 __attribute__ ((alias ("strtoumax")))
>  __cdecl
>  _strtoui64 (const char* __restrict__ nptr, char ** __restrict__ endptr, int 
> base);
> -unsigned __int64 (__cdecl *__MINGW_IMP_SYMBOL(_strtoui64))(const char* 
> __restrict__, char ** __restrict__, int) = _strtoui64;
> +extern unsigned __int64 __attribute__ ((alias 
> (__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(strtoumax)))))
> +(__cdecl *__MINGW_IMP_SYMBOL(_strtoui64))(const char* __restrict__, char ** 
> __restrict__, int);
> diff --git a/mingw-w64-crt/stdio/atoll.c b/mingw-w64-crt/stdio/atoll.c
> index 278c01cf9257..90081a1776ed 100644
> --- a/mingw-w64-crt/stdio/atoll.c
> +++ b/mingw-w64-crt/stdio/atoll.c
> @@ -10,4 +10,4 @@ long long __cdecl atoll(const char * nptr) { return 
> strtoll(nptr, NULL, 10); }
>  long long (__cdecl *__MINGW_IMP_SYMBOL(atoll))(const char *) = atoll;
>  
>  __int64 __attribute__((alias("atoll"))) __cdecl _atoi64(const char * nptr);
> -__int64 (__cdecl *__MINGW_IMP_SYMBOL(_atoi64))(const char *) = _atoi64;
> +extern __int64 
> __attribute__((alias(__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(atoll))))) 
> (__cdecl *__MINGW_IMP_SYMBOL(_atoi64))(const char *);
> -- 
> 2.20.1
> 

Just to note. I'm not sure how many developers have used this alias
attribute on variable because:

1) It is documented since GCC 9.3.0. But I have tested that it works
correctly on all gcc versions available on godbolt.org. It works even
with GCC 3.4.6.

2) It is different syntax for variable which is a pointer to the function
which returns non-pointer type or returns pointer type but function does
not have explicit calling convention AND for variable which is a pointer
to the function which returns pointer type with explicit calling
convention.

This is really not obvious.

In this patch all global variables are just pointers to functions with
explicit calling convention and which returns non-pointer type. For this
it has syntax:

extern ret_type __attribute__((alias("variable"))) (__cdecl 
*alias_variable)(args...);

For the case when return type is pointer and function has explicit
calling convention (e.g. __cdecl) then the syntax is:

extern ret_type* (__cdecl * __attribute__((alias("variable"))) 
alias_variable)(args...);

When the __attribute__((alias("..."))) is before the * then gcc throws:

  warning: ‘alias’ attribute does not apply to types [-Wattributes]

and treats the variable as attribute was not specified, so it has
external linkage and so, gcc does not emit symbol for this variable.

I figured it out during preparing another patch for declaration of
symbol __MINGW_IMP_SYMBOL(__iob_func) which represents function which
returns FILE* (so pointer).

I guess that it is not so common to declare alias for some variable
which is pointer to function. But mingw-w64 has real usecase for it.


_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to