[13/13] string: Add errname_np and errdesc_np

Message ID 20200519180518.318733-14-adhemerval.zanella@linaro.org
State Dropped, archived
Headers
Series Signal and error list refactoring |

Commit Message

Adhemerval Zanella May 19, 2020, 6:05 p.m. UTC
  The errname_np returns error number name (i.g. "EINVAL" for EINVAL)
while errdescr_np returns string describing error number (i.g
"Invalid argument" for EINVAL).  Different than strerror, errdescr_np
does not attempt to translate the return description and both functions
return NULL for an invalid error number.

They should be used instead of sys_errlist and sys_nerr and both are
thread and async-signal safe.  These functions are GNU extensions.

Checked on x86-64-linux-gnu, i686-linux-gnu, powerpc64le-linux-gnu,
and s390x-linux-gnu.
---
 NEWS                                          | 10 ++++
 include/stdio.h                               |  5 ++
 manual/errno.texi                             | 22 +++++++
 scripts/gen-errlist.py                        | 23 +++++--
 stdio-common/Makefile                         | 14 ++++-
 stdio-common/errlist.c                        |  8 +++
 stdio-common/test-err_np.c                    | 60 +++++++++++++++++++
 string/Makefile                               |  2 +-
 string/Versions                               |  1 +
 string/_strerror.c                            |  6 +-
 string/errdescr_np.c                          | 32 ++++++++++
 string/errname_np.c                           | 30 ++++++++++
 string/strerror_l.c                           |  9 ++-
 string/string.h                               |  5 ++
 sysdeps/mach/hurd/errlist.c                   | 10 ++++
 sysdeps/mach/hurd/i386/libc.abilist           |  2 +
 sysdeps/mach/hurd/test-err_np.c               |  4 ++
 sysdeps/unix/sysv/linux/aarch64/libc.abilist  |  2 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist    |  2 +
 sysdeps/unix/sysv/linux/arm/be/libc.abilist   |  2 +
 sysdeps/unix/sysv/linux/arm/le/libc.abilist   |  2 +
 sysdeps/unix/sysv/linux/csky/libc.abilist     |  2 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist     |  2 +
 sysdeps/unix/sysv/linux/i386/libc.abilist     |  2 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist     |  2 +
 .../sysv/linux/m68k/coldfire/libc.abilist     |  2 +
 .../unix/sysv/linux/m68k/m680x0/libc.abilist  |  2 +
 .../sysv/linux/microblaze/be/libc.abilist     |  2 +
 .../sysv/linux/microblaze/le/libc.abilist     |  2 +
 .../sysv/linux/mips/mips32/fpu/libc.abilist   |  2 +
 .../sysv/linux/mips/mips32/nofpu/libc.abilist |  2 +
 .../sysv/linux/mips/mips64/n32/libc.abilist   |  2 +
 .../sysv/linux/mips/mips64/n64/libc.abilist   |  2 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist    |  2 +
 .../linux/powerpc/powerpc32/fpu/libc.abilist  |  2 +
 .../powerpc/powerpc32/nofpu/libc.abilist      |  2 +
 .../linux/powerpc/powerpc64/be/libc.abilist   |  2 +
 .../linux/powerpc/powerpc64/le/libc.abilist   |  2 +
 .../unix/sysv/linux/riscv/rv64/libc.abilist   |  2 +
 .../unix/sysv/linux/s390/s390-32/libc.abilist |  2 +
 .../unix/sysv/linux/s390/s390-64/libc.abilist |  2 +
 sysdeps/unix/sysv/linux/sh/be/libc.abilist    |  2 +
 sysdeps/unix/sysv/linux/sh/le/libc.abilist    |  2 +
 .../sysv/linux/sparc/sparc32/libc.abilist     |  2 +
 .../sysv/linux/sparc/sparc64/libc.abilist     |  2 +
 .../unix/sysv/linux/x86_64/64/libc.abilist    |  2 +
 .../unix/sysv/linux/x86_64/x32/libc.abilist   |  2 +
 47 files changed, 287 insertions(+), 16 deletions(-)
 create mode 100644 stdio-common/test-err_np.c
 create mode 100644 string/errdescr_np.c
 create mode 100644 string/errname_np.c
 create mode 100644 sysdeps/mach/hurd/test-err_np.c
  

Comments

Florian Weimer May 28, 2020, 12:28 p.m. UTC | #1
* Adhemerval Zanella via Libc-alpha:

> The errname_np returns error number name (i.g. "EINVAL" for EINVAL)
> while errdescr_np returns string describing error number (i.g
> "Invalid argument" for EINVAL).  Different than strerror, errdescr_np
> does not attempt to translate the return description and both functions
> return NULL for an invalid error number.

If you use a name that starts with "str", it's in the implementation
namespace, and you don't need the _np suffix.

Is errdescr_np really that useful?  If yes, maybe we should define a
global C locale object, similar to LC_GLOBAL_LOCALE, so that programmers
can simply use strerror_l for this instead (except that it won't be
async-signal-safe, hmm)?

> diff --git a/manual/errno.texi b/manual/errno.texi
> index 8cb4ce8b48..97ba3916ed 100644
> --- a/manual/errno.texi
> +++ b/manual/errno.texi
> @@ -1207,6 +1207,28 @@ to @code{errno}.
>  The function @code{perror} is declared in @file{stdio.h}.
>  @end deftypefun
>  
> +@deftypefun void errname_np (int @var{errnum})
> +@standards{GNU, string.h}
> +@safety{@prelim{}@mtsafe{@mtssigintr{}}@assafe{}@acsafe{}}
> +This function returns the name describing the error @var{errnum} or
> +@code{NULL} for invalid error number (i.g "EINVAL" for @code{EINVAL}).
> +
> +@pindex string.h
> +This function is a GNU extension, declared in the header file @file{string.h}.
> +@end deftypefun
> +
> +@deftypefun void errdesc_np (int @var{errnum})
> +@standards{GNU, string.h}
> +@safety{@prelim{}@mtsafe{@mtssigintr{}}@assafe{}@acsafe{}}
> +This function returns the message describing the error @var{errnum} or
> +@code{NULL} for invalid error number (i.g Invalid argument" for
> +@code{EINVAL}).  Different than @code{strerror} the returned description is
> +not translated.
> +
> +@pindex string.h
> +This function is a GNU extension, declared in the header file @file{string.h}.
> +@end deftypefun

Why @mtssigintr{} (twice)?

I think error numbers for which no constant exist are still valid (in
the C++ sense), so maybe we should phrase this differently: These
functions return NULL if there is no known E* constant with this value.

> diff --git a/stdio-common/errlist.c b/stdio-common/errlist.c
> index f7a49fbf35..dd078143f2 100644
> --- a/stdio-common/errlist.c
> +++ b/stdio-common/errlist.c
> @@ -28,4 +28,12 @@ const char *const _sys_errlist_internal[] =
>  
>  const int _sys_nerr_internal = array_length (_sys_errlist_internal);
>  
> +const char *const _sys_errname_internal[] =
> +  {
> +/* This file is auto-generated from errlist.def.  */
> +#include <errlist-name.h>
> +  };
> +
> +const int _sys_nname_internal = array_length (_sys_errname_internal);
> +
>  #include <errlist-compat.c>

There should not be a reason to emit a separate constant for the length
to the data segment.  And we should eliminate the extra relocations this
array adds.  But I think we can add these changes later as an
optimization.

> diff --git a/stdio-common/test-err_np.c b/stdio-common/test-err_np.c
> new file mode 100644
> index 0000000000..b463c9f3ef
> --- /dev/null
> +++ b/stdio-common/test-err_np.c

I would expect this test to compare against strerror and the E*
constants directly.  For the latter, we should generate a table
containing elements like:

  { EINVAL, "EINVAL" },
  
> diff --git a/string/_strerror.c b/string/_strerror.c
> index 6ae8d47f0f..8bb9bfeaa9 100644
> --- a/string/_strerror.c
> +++ b/string/_strerror.c
> @@ -24,14 +24,14 @@
>  char *
>  __strerror_r (int errnum, char *buf, size_t buflen)
>  {
> -  if (__glibc_unlikely (errnum < 0 || errnum >= _sys_nerr_internal
> -			|| _sys_errlist_internal[errnum] == NULL))
> +  const char *r = __errdescr_np (errnum);
> +  if (r == NULL)
>      {
>        __snprintf (buf, buflen, "%s%d", _("Unknown error "), errnum);
>        return buf;
>      }
>  
> -  return (char *) _(_sys_errlist_internal[errnum]);
> +  return _(_sys_errlist_internal[errnum]);

Shouldn't the last line re-use r?

> diff --git a/string/errname_np.c b/string/errname_np.c
> new file mode 100644
> index 0000000000..61455da219
> --- /dev/null
> +++ b/string/errname_np.c

> +const char *const
> +errname_np (int errnum)
> +{
> +  const char *name = NULL;
> +
> +  if (errnum >= 0 && errnum < _sys_nname_internal)
> +    name = _sys_errname_internal[errnum];
> +
> +  return name;
> +}

I'm surprised that index 0 is looked up in the table.

It may make sense to move the definition of the array out ouf errlist.c,
so that it can be shared across all ports.

Thanks,
Florian
  
Adhemerval Zanella June 1, 2020, 8:52 p.m. UTC | #2
On 28/05/2020 09:28, Florian Weimer wrote:
> * Adhemerval Zanella via Libc-alpha:
> 
>> The errname_np returns error number name (i.g. "EINVAL" for EINVAL)
>> while errdescr_np returns string describing error number (i.g
>> "Invalid argument" for EINVAL).  Different than strerror, errdescr_np
>> does not attempt to translate the return description and both functions
>> return NULL for an invalid error number.
> 
> If you use a name that starts with "str", it's in the implementation
> namespace, and you don't need the _np suffix.

I don't have a strong preference here, maybe 'strerror_as'?

> 
> Is errdescr_np really that useful?  If yes, maybe we should define a
> global C locale object, similar to LC_GLOBAL_LOCALE, so that programmers
> can simply use strerror_l for this instead (except that it won't be
> async-signal-safe, hmm)?

The errdescr_np is added to provide the async-signal-safe strerror 
analogous of the patch deprecated sys_errlist.  The libSegfault itself
could use it, although I am not sure if async-safeness is really that
useful. It is way simpler than define a extra global C locale though.

> 
>> diff --git a/manual/errno.texi b/manual/errno.texi
>> index 8cb4ce8b48..97ba3916ed 100644
>> --- a/manual/errno.texi
>> +++ b/manual/errno.texi
>> @@ -1207,6 +1207,28 @@ to @code{errno}.
>>  The function @code{perror} is declared in @file{stdio.h}.
>>  @end deftypefun
>>  
>> +@deftypefun void errname_np (int @var{errnum})
>> +@standards{GNU, string.h}
>> +@safety{@prelim{}@mtsafe{@mtssigintr{}}@assafe{}@acsafe{}}
>> +This function returns the name describing the error @var{errnum} or
>> +@code{NULL} for invalid error number (i.g "EINVAL" for @code{EINVAL}).
>> +
>> +@pindex string.h
>> +This function is a GNU extension, declared in the header file @file{string.h}.
>> +@end deftypefun
>> +
>> +@deftypefun void errdesc_np (int @var{errnum})
>> +@standards{GNU, string.h}
>> +@safety{@prelim{}@mtsafe{@mtssigintr{}}@assafe{}@acsafe{}}
>> +This function returns the message describing the error @var{errnum} or
>> +@code{NULL} for invalid error number (i.g Invalid argument" for
>> +@code{EINVAL}).  Different than @code{strerror} the returned description is
>> +not translated.
>> +
>> +@pindex string.h
>> +This function is a GNU extension, declared in the header file @file{string.h}.
>> +@end deftypefun
> 
> Why @mtssigintr{} (twice)?

I am not following, each one annotates a different symbol (one for errname_np
and another for errdesc_np).

> 
> I think error numbers for which no constant exist are still valid (in
> the C++ sense), so maybe we should phrase this differently: These
> functions return NULL if there is no known E* constant with this value.

Ack.

> 
>> diff --git a/stdio-common/errlist.c b/stdio-common/errlist.c
>> index f7a49fbf35..dd078143f2 100644
>> --- a/stdio-common/errlist.c
>> +++ b/stdio-common/errlist.c
>> @@ -28,4 +28,12 @@ const char *const _sys_errlist_internal[] =
>>  
>>  const int _sys_nerr_internal = array_length (_sys_errlist_internal);
>>  
>> +const char *const _sys_errname_internal[] =
>> +  {
>> +/* This file is auto-generated from errlist.def.  */
>> +#include <errlist-name.h>
>> +  };
>> +
>> +const int _sys_nname_internal = array_length (_sys_errname_internal);
>> +
>>  #include <errlist-compat.c>
> 
> There should not be a reason to emit a separate constant for the length
> to the data segment.  And we should eliminate the extra relocations this
> array adds.  But I think we can add these changes later as an
> optimization.

Alright, I think it could be feasible to auto-generate both
_sys_errlist_internal and _sys_errname_internal with its expected size
(as we do for __sys_siglist_internal) and optimize the script to
emit the expected string size for each element.

> 
>> diff --git a/stdio-common/test-err_np.c b/stdio-common/test-err_np.c
>> new file mode 100644
>> index 0000000000..b463c9f3ef
>> --- /dev/null
>> +++ b/stdio-common/test-err_np.c
> 
> I would expect this test to compare against strerror and the E*
> constants directly.  For the latter, we should generate a table
> containing elements like:
> 
>   { EINVAL, "EINVAL" },

The 'errname' does have this mapping. Should I add an extra test for
strerror as well?

>   
>> diff --git a/string/_strerror.c b/string/_strerror.c
>> index 6ae8d47f0f..8bb9bfeaa9 100644
>> --- a/string/_strerror.c
>> +++ b/string/_strerror.c
>> @@ -24,14 +24,14 @@
>>  char *
>>  __strerror_r (int errnum, char *buf, size_t buflen)
>>  {
>> -  if (__glibc_unlikely (errnum < 0 || errnum >= _sys_nerr_internal
>> -			|| _sys_errlist_internal[errnum] == NULL))
>> +  const char *r = __errdescr_np (errnum);
>> +  if (r == NULL)
>>      {
>>        __snprintf (buf, buflen, "%s%d", _("Unknown error "), errnum);
>>        return buf;
>>      }
>>  
>> -  return (char *) _(_sys_errlist_internal[errnum]);
>> +  return _(_sys_errlist_internal[errnum]);
> 
> Shouldn't the last line re-use r?

It should, I have change it.

> 
>> diff --git a/string/errname_np.c b/string/errname_np.c
>> new file mode 100644
>> index 0000000000..61455da219
>> --- /dev/null
>> +++ b/string/errname_np.c
> 
>> +const char *const
>> +errname_np (int errnum)
>> +{
>> +  const char *name = NULL;
>> +
>> +  if (errnum >= 0 && errnum < _sys_nname_internal)
>> +    name = _sys_errname_internal[errnum];
>> +
>> +  return name;
>> +}
> 
> I'm surprised that index 0 is looked up in the table.

It is defined a no error ('Success').

> 
> It may make sense to move the definition of the array out ouf errlist.c,
> so that it can be shared across all ports.

On third patch on this set [1] I moved the generation to a script based
on errlist.def. Hurd requires its own version because it uses different
internal names (maybe we could cleanup this up later).

[1] https://sourceware.org/pipermail/libc-alpha/2020-May/113700.html

> 
> Thanks,
> Florian
>
  
Adhemerval Zanella June 2, 2020, 5:13 p.m. UTC | #3
On 28/05/2020 09:28, Florian Weimer wrote:
>> diff --git a/stdio-common/errlist.c b/stdio-common/errlist.c
>> index f7a49fbf35..dd078143f2 100644
>> --- a/stdio-common/errlist.c
>> +++ b/stdio-common/errlist.c
>> @@ -28,4 +28,12 @@ const char *const _sys_errlist_internal[] =
>>  
>>  const int _sys_nerr_internal = array_length (_sys_errlist_internal);
>>  
>> +const char *const _sys_errname_internal[] =
>> +  {
>> +/* This file is auto-generated from errlist.def.  */
>> +#include <errlist-name.h>
>> +  };
>> +
>> +const int _sys_nname_internal = array_length (_sys_errname_internal);
>> +
>>  #include <errlist-compat.c>
> 
> There should not be a reason to emit a separate constant for the length
> to the data segment.  And we should eliminate the extra relocations this
> array adds.  But I think we can add these changes later as an
> optimization.
I have removed the constant length variable, however for the extra relocations
from the string array I am not sure if this is really an improvement. The array
is exported as compat symbol (we can't skip its definition) and to fully 
optimize it would require to use a different data structure (such as string
containing all definitions plus a array of indexes) which would require to
duplicate some definition (at least the extra index map).

It might be a gain for architectures that does not have to provide the compat
symbols, but it increases memory usage a bit for the default case (without much
gain in relocation time spent).
  
Florian Weimer June 2, 2020, 5:19 p.m. UTC | #4
* Adhemerval Zanella:

> I have removed the constant length variable, however for the extra relocations

Thanks.

> from the string array I am not sure if this is really an
> improvement. The array is exported as compat symbol (we can't skip its
> definition) and to fully optimize it would require to use a different
> data structure (such as string containing all definitions plus a array
> of indexes) which would require to duplicate some definition (at least
> the extra index map).
>
> It might be a gain for architectures that does not have to provide the
> compat symbols, but it increases memory usage a bit for the default
> case (without much gain in relocation time spent).

Sure, for the description arrays.  But aren't the name arrays new?

Thanks,
Florian
  
Adhemerval Zanella June 2, 2020, 5:20 p.m. UTC | #5
On 02/06/2020 14:19, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>> I have removed the constant length variable, however for the extra relocations
> 
> Thanks.
> 
>> from the string array I am not sure if this is really an
>> improvement. The array is exported as compat symbol (we can't skip its
>> definition) and to fully optimize it would require to use a different
>> data structure (such as string containing all definitions plus a array
>> of indexes) which would require to duplicate some definition (at least
>> the extra index map).
>>
>> It might be a gain for architectures that does not have to provide the
>> compat symbols, but it increases memory usage a bit for the default
>> case (without much gain in relocation time spent).
> 
> Sure, for the description arrays.  But aren't the name arrays new?

Indeed, I think we can optimize it. I will send a new version.
  

Patch

diff --git a/NEWS b/NEWS
index 6328624bb2..53fc6f1a87 100644
--- a/NEWS
+++ b/NEWS
@@ -33,6 +33,16 @@  Major new features:
   They should be used instead of sys_siglist or sys_sigabbrev and they
   are both thread and async-signal safe.  These functions are GNU extensions.
 
+* The functions errname_np and errdescr_np have been added.  The errname_np
+  returns error number name (i.g. "EINVAL" for EINVAL) while errdescr_np
+  returns string describing error number (i.g "Invalid argument" for EINVAL).
+  Different than strerror, errdescr_np does not attempt to translate the
+  return description and both functions return NULL for an invalid error
+  number.
+
+  They should be used instead of sys_errlist and sys_nerr and both are
+  thread and async-signal safe.  These functions are GNU extensions.
+
 Deprecated and removed features, and other changes affecting compatibility:
 
 * The deprecated <sys/sysctl.h> header and the sysctl function have been
diff --git a/include/stdio.h b/include/stdio.h
index 3f65b7930c..3b72bbdf98 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -187,6 +187,11 @@  libc_hidden_proto (__libc_readline_unlocked);
 
 extern const char *const _sys_errlist_internal[] attribute_hidden;
 extern const int _sys_nerr_internal attribute_hidden;
+extern const char *const _sys_errname_internal[] attribute_hidden;
+extern const int _sys_nname_internal attribute_hidden;
+
+extern const char *const __errdescr_np (int errnum);
+libc_hidden_proto (__errdescr_np)
 
 libc_hidden_ldbl_proto (__asprintf)
 
diff --git a/manual/errno.texi b/manual/errno.texi
index 8cb4ce8b48..97ba3916ed 100644
--- a/manual/errno.texi
+++ b/manual/errno.texi
@@ -1207,6 +1207,28 @@  to @code{errno}.
 The function @code{perror} is declared in @file{stdio.h}.
 @end deftypefun
 
+@deftypefun void errname_np (int @var{errnum})
+@standards{GNU, string.h}
+@safety{@prelim{}@mtsafe{@mtssigintr{}}@assafe{}@acsafe{}}
+This function returns the name describing the error @var{errnum} or
+@code{NULL} for invalid error number (i.g "EINVAL" for @code{EINVAL}).
+
+@pindex string.h
+This function is a GNU extension, declared in the header file @file{string.h}.
+@end deftypefun
+
+@deftypefun void errdesc_np (int @var{errnum})
+@standards{GNU, string.h}
+@safety{@prelim{}@mtsafe{@mtssigintr{}}@assafe{}@acsafe{}}
+This function returns the message describing the error @var{errnum} or
+@code{NULL} for invalid error number (i.g Invalid argument" for
+@code{EINVAL}).  Different than @code{strerror} the returned description is
+not translated.
+
+@pindex string.h
+This function is a GNU extension, declared in the header file @file{string.h}.
+@end deftypefun
+
 @code{strerror} and @code{perror} produce the exact same message for any
 given error code; the precise text varies from system to system.  With
 @theglibc{}, the messages are fairly short; there are no multi-line
diff --git a/scripts/gen-errlist.py b/scripts/gen-errlist.py
index 6531d0f3df..c480597907 100755
--- a/scripts/gen-errlist.py
+++ b/scripts/gen-errlist.py
@@ -19,16 +19,26 @@ 
 
 import sys
 import argparse
+from enum import Enum
 
 # The input file should be in the form
 #
 #   VALUE, DESCRIPTION
 #
-# An entry for each will be created in the output file in the form:
+# An entry for each will be created in the output file in the form
+# for mode 'descr':
 #
 #   [VALUE] = "DESCRIPTION",
+#
+# or in the form for mode 'name':
+#
+#   [VALUE] = "VALUE",
+
+class Mode(Enum):
+    NAME  = 0
+    DESCR = 1
 
-def generate_errlist(input_file, output_file):
+def generate_errlist(mode, input_file, output_file):
     with open(input_file, 'r') as fin, open(output_file, 'w') as fout:
         fout.write("#ifndef ERR_MAP\n")
         fout.write("#define ERR_MAP(value) value\n")
@@ -38,16 +48,21 @@  def generate_errlist(input_file, output_file):
                 continue
             fields = [f.strip() for f in line.rstrip('\n').split(',')]
             fout.write("[ERR_MAP(%s)] = N_(\"%s\"),\n" % (fields[0],
-                                                          fields[1]))
+                                                          fields[mode.value]))
 
 def main():
     parser = argparse.ArgumentParser(description='Generate errlist.h')
+    parser.add_argument('-m', dest='mode',
+                        help='Output mode', default='name',
+                        choices=('name', 'desc'),
+                        required=True)
     parser.add_argument('-i', dest='input', metavar='FILE',
                         help='Error definitions')
     parser.add_argument('-o', dest='output', metavar='FILE',
                         help='Include file')
     args = parser.parse_args()
-    generate_errlist(args.input, args.output)
+    generate_errlist(Mode.NAME if args.mode == 'name' else Mode.DESCR,
+                     args.input, args.output)
 
 if __name__ == '__main__':
     main()
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index 48f3ba7c3a..98fa3e0305 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -66,7 +66,8 @@  tests := tstscanf test_rdwr test-popen tstgetln test-fseek \
 	 tst-scanf-round \
 	 tst-renameat2 tst-bz11319 tst-bz11319-fortify2 \
 	 scanf14a scanf16a \
-	 tst-printf-bz25691
+	 tst-printf-bz25691 \
+	 test-err_np
 
 
 test-srcs = tst-unbputc tst-printf tst-printfsz-islongdouble
@@ -92,10 +93,17 @@  errlist-def = $(firstword $(wildcard $(addsuffix /errlist.def,$(sysdirs) .)))
 
 $(objpfx)errlist.h: $(errlist-def) \
 		    $(..)scripts/gen-errlist.py
-	$(PYTHON) $(..)scripts/gen-errlist.py -i $(errlist-def) -o $@
+	$(PYTHON) $(..)scripts/gen-errlist.py -m desc -i $(errlist-def) -o $@
+
+$(objpfx)errlist-name.h: $(errlist-def) \
+		         $(..)scripts/gen-errlist.py
+	$(PYTHON) $(..)scripts/gen-errlist.py -m name -i $(errlist-def) -o $@
+
+$(foreach o,$(object-suffixes) $(object-suffixes:=.d),\
+          $(objpfx)errlist$o): $(objpfx)errlist.h $(objpfx)errlist-name.h
 
 $(foreach o,$(object-suffixes) $(object-suffixes:=.d),\
-          $(objpfx)errlist$o): $(objpfx)errlist.h
+          $(objpfx)test-err_np$o): $(objpfx)errlist.h $(objpfx)errlist-name.h
 
 ifeq ($(run-built-tests),yes)
 LOCALES := de_DE.ISO-8859-1 de_DE.UTF-8 en_US.ISO-8859-1 ja_JP.EUC-JP
diff --git a/stdio-common/errlist.c b/stdio-common/errlist.c
index f7a49fbf35..dd078143f2 100644
--- a/stdio-common/errlist.c
+++ b/stdio-common/errlist.c
@@ -28,4 +28,12 @@  const char *const _sys_errlist_internal[] =
 
 const int _sys_nerr_internal = array_length (_sys_errlist_internal);
 
+const char *const _sys_errname_internal[] =
+  {
+/* This file is auto-generated from errlist.def.  */
+#include <errlist-name.h>
+  };
+
+const int _sys_nname_internal = array_length (_sys_errname_internal);
+
 #include <errlist-compat.c>
diff --git a/stdio-common/test-err_np.c b/stdio-common/test-err_np.c
new file mode 100644
index 0000000000..b463c9f3ef
--- /dev/null
+++ b/stdio-common/test-err_np.c
@@ -0,0 +1,60 @@ 
+/* Test and errname_np and errdesc_np.
+   Copyright (C) 2020 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/>.  */
+
+#include <string.h>
+#include <errno.h>
+#include <array_length.h>
+
+#include <support/support.h>
+#include <support/check.h>
+
+#define N_(name)      name
+
+static const char *const errlist[] =
+  {
+/* This file is auto-generated from errlist.def.  */
+#include <errlist.h>
+  };
+
+static const char *const errname[] =
+  {
+/* This file is auto-generated from errlist.def.  */
+#include <errlist-name.h>
+  };
+
+static int
+do_test (void)
+{
+  for (size_t i = 0; i < array_length (errlist); i++)
+    {
+      if (errlist[i] == NULL)
+        continue;
+      TEST_COMPARE_STRING (errdescr_np (i), errlist[i]);
+    }
+
+  for (size_t i = 0; i < array_length (errname); i++)
+    {
+      if (errname[i] == NULL)
+        continue;
+      TEST_COMPARE_STRING (errname_np (i), errname[i]);
+    }
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/string/Makefile b/string/Makefile
index e5075521b7..58c6d5f183 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -45,7 +45,7 @@  routines	:= strcat strchr strcmp strcoll strcpy strcspn		\
 		   envz basename					\
 		   strcoll_l strxfrm_l string-inlines memrchr		\
 		   xpg-strerror strerror_l explicit_bzero		\
-		   sigdescr_np sigabbrev_np
+		   sigdescr_np sigabbrev_np errname_np errdescr_np
 
 strop-tests	:= memchr memcmp memcpy memmove mempcpy memset memccpy	\
 		   stpcpy stpncpy strcat strchr strcmp strcpy strcspn	\
diff --git a/string/Versions b/string/Versions
index 6f8dd2d372..aca554bc24 100644
--- a/string/Versions
+++ b/string/Versions
@@ -87,5 +87,6 @@  libc {
   }
   GLIBC_2.32 {
     sigdescr_np; sigabbrev_np;
+    errdescr_np; errname_np;
   }
 }
diff --git a/string/_strerror.c b/string/_strerror.c
index 6ae8d47f0f..8bb9bfeaa9 100644
--- a/string/_strerror.c
+++ b/string/_strerror.c
@@ -24,14 +24,14 @@ 
 char *
 __strerror_r (int errnum, char *buf, size_t buflen)
 {
-  if (__glibc_unlikely (errnum < 0 || errnum >= _sys_nerr_internal
-			|| _sys_errlist_internal[errnum] == NULL))
+  const char *r = __errdescr_np (errnum);
+  if (r == NULL)
     {
       __snprintf (buf, buflen, "%s%d", _("Unknown error "), errnum);
       return buf;
     }
 
-  return (char *) _(_sys_errlist_internal[errnum]);
+  return _(_sys_errlist_internal[errnum]);
 }
 weak_alias (__strerror_r, strerror_r)
 libc_hidden_def (__strerror_r)
diff --git a/string/errdescr_np.c b/string/errdescr_np.c
new file mode 100644
index 0000000000..138b1c0285
--- /dev/null
+++ b/string/errdescr_np.c
@@ -0,0 +1,32 @@ 
+/* Return string describing error number.
+   Copyright (C) 2020 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/>.  */
+
+#include <stdio.h>
+
+const char *const
+__errdescr_np (int errnum)
+{
+  const char *descr = NULL;
+
+  if (errnum >= 0 && errnum < _sys_nerr_internal)
+    descr = _sys_errlist_internal[errnum];
+
+  return descr;
+}
+libc_hidden_def (__errdescr_np)
+weak_alias (__errdescr_np, errdescr_np)
diff --git a/string/errname_np.c b/string/errname_np.c
new file mode 100644
index 0000000000..61455da219
--- /dev/null
+++ b/string/errname_np.c
@@ -0,0 +1,30 @@ 
+/* Return string describing signal abbreviation.
+   Copyright (C) 2020 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/>.  */
+
+#include <stdio.h>
+
+const char *const
+errname_np (int errnum)
+{
+  const char *name = NULL;
+
+  if (errnum >= 0 && errnum < _sys_nname_internal)
+    name = _sys_errname_internal[errnum];
+
+  return name;
+}
diff --git a/string/strerror_l.c b/string/strerror_l.c
index dcbf605560..86df088193 100644
--- a/string/strerror_l.c
+++ b/string/strerror_l.c
@@ -37,10 +37,9 @@  char *
 __strerror_l (int errnum, locale_t loc)
 {
   int saved_errno = errno;
-  char *r;
 
-  if (__glibc_unlikely (errnum < 0 || errnum >= _sys_nerr_internal
-			|| _sys_errlist_internal[errnum] == NULL))
+  const char *r = __errdescr_np (errnum);
+  if (r == NULL)
     {
       struct tls_internal_t *tls_internal = __glibc_tls_internal ();
       free (tls_internal->strerror_l_buf);
@@ -51,10 +50,10 @@  __strerror_l (int errnum, locale_t loc)
       r = tls_internal->strerror_l_buf;
     }
   else
-    r = (char *) translate (_sys_errlist_internal[errnum], loc);
+    r = translate (_sys_errlist_internal[errnum], loc);
 
   __set_errno (saved_errno);
-  return r;
+  return (char *) r;
 }
 weak_alias (__strerror_l, strerror_l)
 libc_hidden_def (__strerror_l)
diff --git a/string/string.h b/string/string.h
index c01a78495a..dc861eb644 100644
--- a/string/string.h
+++ b/string/string.h
@@ -428,6 +428,11 @@  extern int __xpg_strerror_r (int __errnum, char *__buf, size_t __buflen)
 extern char *strerror_r (int __errnum, char *__buf, size_t __buflen)
      __THROW __nonnull ((2)) __wur  __attr_access ((__write_only__, 2, 3));
 # endif
+
+# ifdef __USE_GNU
+extern const char *errdescr_np (int __err) __THROW;
+extern const char *errname_np (int __err) __THROW;
+# endif
 #endif
 
 #ifdef __USE_XOPEN2K8
diff --git a/sysdeps/mach/hurd/errlist.c b/sysdeps/mach/hurd/errlist.c
index b6b0a03fbe..87c3a88f6d 100644
--- a/sysdeps/mach/hurd/errlist.c
+++ b/sysdeps/mach/hurd/errlist.c
@@ -30,5 +30,15 @@  const char *const _hurd_errlist[] =
   {
 #include <errlist.h>
   };
+strong_alias (_hurd_errlist, _sys_errlist_internal)
 
 const int _hurd_nerr = array_length (_hurd_errlist);
+strong_alias (_hurd_nerr, _sys_nerr_internal)
+
+const char *const _sys_errname_internal[] =
+  {
+/* This file is auto-generated from errlist.def.  */
+#include <errlist-name.h>
+  };
+
+const int _sys_nname_internal = array_length (_sys_errname_internal);
diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist
index ff8ad98d03..193ceba987 100644
--- a/sysdeps/mach/hurd/i386/libc.abilist
+++ b/sysdeps/mach/hurd/i386/libc.abilist
@@ -2181,6 +2181,8 @@  GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 mach_print F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/mach/hurd/test-err_np.c b/sysdeps/mach/hurd/test-err_np.c
new file mode 100644
index 0000000000..3127141128
--- /dev/null
+++ b/sysdeps/mach/hurd/test-err_np.c
@@ -0,0 +1,4 @@ 
+#include <mach/error.h>
+
+#define ERR_MAP(value) err_get_code (value)
+#include <stdio-common/test-err_np.c>
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 6df0cd1777..ee82487a17 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2146,6 +2146,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 7569c33c71..72be24dfe1 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2226,6 +2226,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
index facc97e16d..e4fde72b02 100644
--- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
@@ -133,6 +133,8 @@  GLIBC_2.30 twalk_r F
 GLIBC_2.31 msgctl F
 GLIBC_2.31 semctl F
 GLIBC_2.31 shmctl F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
index f9e5c8b31b..f634d0f7fb 100644
--- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
@@ -130,6 +130,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
index 523645e9f8..7eed70c092 100644
--- a/sysdeps/unix/sysv/linux/csky/libc.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
@@ -2090,6 +2090,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index f5d166397d..1826f0be3e 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -2047,6 +2047,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index c6925f7662..04aa8fa708 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2213,6 +2213,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index 6f2bf190e7..62715d6ebd 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -2079,6 +2079,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index fef15864ce..0b91e2dcf3 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -134,6 +134,8 @@  GLIBC_2.30 twalk_r F
 GLIBC_2.31 msgctl F
 GLIBC_2.31 semctl F
 GLIBC_2.31 shmctl F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 285ef179d0..1956e9757b 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -2159,6 +2159,8 @@  GLIBC_2.30 twalk_r F
 GLIBC_2.31 msgctl F
 GLIBC_2.31 semctl F
 GLIBC_2.31 shmctl F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
index 8ce666a00f..8169946e0a 100644
--- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
@@ -2141,6 +2141,8 @@  GLIBC_2.30 twalk_r F
 GLIBC_2.31 msgctl F
 GLIBC_2.31 semctl F
 GLIBC_2.31 shmctl F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
index d096655d5d..399eedd79d 100644
--- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
@@ -2138,6 +2138,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index bbbc2e6877..0bcb5378ad 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -2130,6 +2130,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 18556a2054..93dab83030 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -2128,6 +2128,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index ae1057c337..9f3610312a 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -2136,6 +2136,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 03b1fe8a19..ab2d4940da 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -2130,6 +2130,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index d8d9583b1b..88706ec647 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2179,6 +2179,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 8d8e111f51..650f5ec75e 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -2186,6 +2186,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 89cc16d3c7..6835369919 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -2219,6 +2219,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
index 06d43c3ecc..d1ce817e69 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
@@ -2049,6 +2049,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
index e427acc65f..12cdc17b78 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
@@ -2341,6 +2341,8 @@  GLIBC_2.32 __wcstoieee128_l F
 GLIBC_2.32 __wprintf_chkieee128 F
 GLIBC_2.32 __wprintfieee128 F
 GLIBC_2.32 __wscanfieee128 F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
index b5e5ac500b..6ab7056c84 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
@@ -2108,6 +2108,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 6b044b3a46..9e3a7a89b1 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -2184,6 +2184,8 @@  GLIBC_2.30 twalk_r F
 GLIBC_2.31 msgctl F
 GLIBC_2.31 semctl F
 GLIBC_2.31 shmctl F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index 717ea318a2..279dc8d67e 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -2085,6 +2085,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
index 5ae7f7c7ae..78403a7229 100644
--- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
@@ -2054,6 +2054,8 @@  GLIBC_2.30 twalk_r F
 GLIBC_2.31 msgctl F
 GLIBC_2.31 semctl F
 GLIBC_2.31 shmctl F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
index a9629d8edf..1cd86f412b 100644
--- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
@@ -2051,6 +2051,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 48b8a470d4..24a6701653 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -2175,6 +2175,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index 45cff4f5e7..9e8df17c20 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -2102,6 +2102,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 3f2eb568c9..50bff82c1a 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -2060,6 +2060,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 7cb85af008..e7cbc773d4 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2159,6 +2159,8 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.32 errdescr_np F
+GLIBC_2.32 errname_np F
 GLIBC_2.32 pthread_sigmask F
 GLIBC_2.32 sigabbrev_np F
 GLIBC_2.32 sigdescr_np F