stdio: Remove the usage of $(fno-unit-at-a-time) for errlist.c

The errlist.c is built with -fno-toplevel-reorder to avoid compiler to
reorder the compat assembly directives due an assembler issue [1]
(fixed on 2.39).

This patch removes the compiler flags by split the compat symbol
generation in two phases.  First the _sys_errlist_internal internal
without any compat symbol directive is preprocessed to generate an
assembly source code.  This generate assembly is then used as input
on a platform agnostic errlist-data.S which then creates the compat
definitions.  This prevents compiler to move any compat directive
prior the _sys_errlist_internal definition itself.

Checked on a make check run-built-tests=no on all affected ABIs.

[1] https://sourceware.org/bugzilla/show_bug.cgi?id=29012
This commit is contained in:
Adhemerval Zanella 2022-04-06 12:09:42 -03:00
parent 111254f3e1
commit 900fa25736
16 changed files with 120 additions and 33 deletions

View File

@ -1030,7 +1030,8 @@ ifeq (yes,$(build-shared))
# Under --enable-shared, we will build a shared library of PIC objects. # Under --enable-shared, we will build a shared library of PIC objects.
# The PIC object files are named foo.os. # The PIC object files are named foo.os.
object-suffixes += .os object-suffixes += .os
CPPFLAGS-.os = -DPIC -DSHARED pic-cppflags = -DPIC -DSHARED
CPPFLAGS-.os = $(pic-cppflags)
CFLAGS-.os = $(filter %frame-pointer,$(+cflags)) $(pic-ccflag) CFLAGS-.os = $(filter %frame-pointer,$(+cflags)) $(pic-ccflag)
libtype.os := lib%_pic.a libtype.os := lib%_pic.a
# This can be changed by a sysdep makefile # This can be changed by a sysdep makefile

View File

@ -180,6 +180,7 @@ int __vfxprintf (FILE *__fp, const char *__fmt, __gnuc_va_list,
attribute_hidden; attribute_hidden;
extern const char *const _sys_errlist_internal[] attribute_hidden; extern const char *const _sys_errlist_internal[] attribute_hidden;
extern const size_t _sys_errlist_internal_len attribute_hidden;
extern const char *__get_errlist (int) attribute_hidden; extern const char *__get_errlist (int) attribute_hidden;
extern const char *__get_errname (int) attribute_hidden; extern const char *__get_errname (int) attribute_hidden;

View File

@ -88,6 +88,7 @@ routines := \
aux := \ aux := \
errlist \ errlist \
errlist-data \
errname \ errname \
fxprintf \ fxprintf \
printf-parsemb \ printf-parsemb \
@ -211,6 +212,10 @@ tests := \
xbug \ xbug \
# tests # tests
generated += \
errlist-data-aux-shared.S \
errlist-data-aux.S \
# generated
test-srcs = tst-unbputc tst-printf tst-printfsz-islongdouble test-srcs = tst-unbputc tst-printf tst-printfsz-islongdouble
@ -246,6 +251,20 @@ tests-special += $(objpfx)tst-errno-manual.out
include ../Rules include ../Rules
# The errlist.c is built in two phases because compiler might reorder the
# compat_symbol directive prior the object itself and on binutils older
# than 2.29 it might generate object sizes different than the expected ones.
$(objpfx)errlist-data-aux-shared.S: errlist-data-gen.c
$(make-target-directory)
$(compile-command.c) $(pic-cppflags) $(pic-ccflag) $(no-stack-protector) -S
$(objpfx)errlist-data-aux.S: errlist-data-gen.c
$(make-target-directory)
$(compile-command.c) $(pie-default) $(no-stack-protector) -S
$(objpfx)errlist-data.os: $(objpfx)errlist-data-aux-shared.S
$(objpfx)errlist-data.o: $(objpfx)errlist-data-aux.S
ifeq ($(run-built-tests),yes) ifeq ($(run-built-tests),yes)
LOCALES := \ LOCALES := \
de_DE.ISO-8859-1 \ de_DE.ISO-8859-1 \
@ -334,7 +353,6 @@ CFLAGS-isoc99_vfscanf.c += -fexceptions
CFLAGS-isoc99_vscanf.c += -fexceptions CFLAGS-isoc99_vscanf.c += -fexceptions
CFLAGS-isoc99_fscanf.c += -fexceptions CFLAGS-isoc99_fscanf.c += -fexceptions
CFLAGS-isoc99_scanf.c += -fexceptions CFLAGS-isoc99_scanf.c += -fexceptions
CFLAGS-errlist.c += $(fno-unit-at-a-time)
CFLAGS-siglist.c += $(fno-unit-at-a-time) CFLAGS-siglist.c += $(fno-unit-at-a-time)
# scanf14a.c and scanf16a.c test a deprecated extension which is no # scanf14a.c and scanf16a.c test a deprecated extension which is no

24
stdio-common/err_map.h Normal file
View File

@ -0,0 +1,24 @@
/* Internal errno names mapping definition.
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 _ERR_MAP_H
#define _ERR_MAP_H
#define ERR_MAP(n) (n)
#endif

View File

@ -0,0 +1 @@
/* Empty */

View File

@ -1 +0,0 @@
/* Empty. */

View File

@ -0,0 +1,34 @@
/* Internal errno names mapping definition.
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/>. */
#include <array_length.h>
#include <err_map.h>
#include <errno.h>
#include <libintl.h>
#include <stdio.h>
const char *const _sys_errlist_internal[] =
{
#define _S(n, str) [ERR_MAP(n)] = str,
#include <errlist.h>
#undef _S
};
const size_t _sys_errlist_internal_len = array_length (_sys_errlist_internal);
/* Include to get the definitions for sys_nerr/_sys_nerr. */
#include <errlist-compat-data.h>

View File

@ -0,0 +1,7 @@
#ifdef SHARED
# include "errlist-data-aux-shared.S"
#else
# include "errlist-data-aux.S"
#endif
#include <errlist-compat-data.h>

View File

@ -16,29 +16,17 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */ <https://www.gnu.org/licenses/>. */
#include <stdio.h> #include <array_length.h>
#include <err_map.h>
#include <errno.h> #include <errno.h>
#include <libintl.h> #include <libintl.h>
#include <array_length.h> #include <stdio.h>
#ifndef ERR_MAP
# define ERR_MAP(n) n
#endif
const char *const _sys_errlist_internal[] =
{
#define _S(n, str) [ERR_MAP(n)] = str,
#include <errlist.h>
#undef _S
};
const char * const char *
__get_errlist (int errnum) __get_errlist (int errnum)
{ {
int mapped = ERR_MAP (errnum); int mapped = ERR_MAP (errnum);
if (mapped >= 0 && mapped < array_length (_sys_errlist_internal)) if (mapped >= 0 && mapped < _sys_errlist_internal_len)
return _sys_errlist_internal[mapped]; return _sys_errlist_internal[mapped];
return NULL; return NULL;
} }
#include <errlist-compat.c>

View File

@ -1,4 +1,5 @@
/* Copyright (C) 1998-2022 Free Software Foundation, Inc. /* Internal errno names mapping definition. Hurd version.
Copyright (C) 2022 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -15,7 +16,11 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */ <https://www.gnu.org/licenses/>. */
#ifndef _ERR_MAP_H
#define _ERR_MAP_H
#include <mach/error.h> #include <mach/error.h>
#define ERR_MAP(value) err_get_code (value) #define ERR_MAP(value) err_get_code (value)
#include <stdio-common/errlist.c>
#endif

View File

@ -20,6 +20,7 @@
#define _ERRLIST_COMPAT_H #define _ERRLIST_COMPAT_H
#include <shlib-compat.h> #include <shlib-compat.h>
#include <limits.h>
/* Define new compat symbols for symbols _sys_errlist, sys_errlist, /* Define new compat symbols for symbols _sys_errlist, sys_errlist,
_sys_nerr, and sys_nerr for version VERSION with NUMBERERR times number of _sys_nerr, and sys_nerr for version VERSION with NUMBERERR times number of
@ -27,17 +28,25 @@
Both _sys_errlist and sys_errlist alias to _sys_errlist_internal symbol Both _sys_errlist and sys_errlist alias to _sys_errlist_internal symbol
(defined on errlist.c) while _sys_nerr and sys_nerr created new variable (defined on errlist.c) while _sys_nerr and sys_nerr created new variable
with the expected size. */ with the expected size. */
#define DEFINE_COMPAT_ERRLIST(NUMBERERR, VERSION) \ #ifdef __ASSEMBLER__
# define DEFINE_COMPAT_ERRLIST(NUMBERERR, VERSION) \
declare_object_symbol_alias (__ ## VERSION ## _sys_errlist, \
_sys_errlist_internal, \
NUMBERERR * (ULONG_WIDTH / UCHAR_WIDTH)) \
ASM_LINE_SEP \
declare_object_symbol_alias (__ ## VERSION ## __sys_errlist, \
_sys_errlist_internal, \
NUMBERERR * (ULONG_WIDTH / UCHAR_WIDTH)) \
ASM_LINE_SEP \
compat_symbol (libc, __## VERSION ## _sys_errlist, sys_errlist, VERSION) \
ASM_LINE_SEP \
compat_symbol (libc, __## VERSION ## __sys_errlist, _sys_errlist, VERSION)
#else
# define DEFINE_COMPAT_ERRLIST(NUMBERERR, VERSION) \
const int __##VERSION##_sys_nerr = NUMBERERR; \ const int __##VERSION##_sys_nerr = NUMBERERR; \
strong_alias (__##VERSION##_sys_nerr, __##VERSION##__sys_nerr); \ strong_alias (__##VERSION##_sys_nerr, __##VERSION##__sys_nerr); \
declare_symbol_alias (__ ## VERSION ## _sys_errlist, _sys_errlist_internal,\
object, NUMBERERR * (ULONG_WIDTH / UCHAR_WIDTH)); \
declare_symbol_alias (__ ## VERSION ## __sys_errlist, \
_sys_errlist_internal, object, \
NUMBERERR * (ULONG_WIDTH / UCHAR_WIDTH)); \
compat_symbol (libc, __## VERSION ## _sys_nerr, sys_nerr, VERSION); \ compat_symbol (libc, __## VERSION ## _sys_nerr, sys_nerr, VERSION); \
compat_symbol (libc, __## VERSION ## __sys_nerr, _sys_nerr, VERSION); \ compat_symbol (libc, __## VERSION ## __sys_nerr, _sys_nerr, VERSION);
compat_symbol (libc, __## VERSION ## _sys_errlist, sys_errlist, VERSION); \ #endif
compat_symbol (libc, __## VERSION ## __sys_errlist, _sys_errlist, VERSION);\
#endif #endif