Compare commits

..

2 Commits

Author SHA1 Message Date
Florian Weimer
e2305da35c Fixup release 2016-01-14 12:12:37 +01:00
Florian Weimer
23dd0a4649 Import proposed upstream patch for AVX512 support in memcpy 2016-01-14 12:10:12 +01:00
63 changed files with 10868 additions and 4605 deletions

6
.gitignore vendored
View File

@ -1,6 +0,0 @@
# Release tarballs.
/glibc-*.tar.[gx]z
# Generated (source) RPMs.
/*.rpm
# Expanded source trees.
/glibc-*/

File diff suppressed because it is too large Load Diff

View File

@ -1,2 +0,0 @@
All of the useful glibc maintainer scripts are located at:
https://pagure.io/glibc-maintainer-scripts

494
SUPPORTED
View File

@ -1,494 +0,0 @@
# This file names the currently supported and somewhat tested locales.
# If you have any additions please file a glibc bug report.
SUPPORTED-LOCALES=\
C.UTF-8/UTF-8 \
aa_DJ.UTF-8/UTF-8 \
aa_DJ/ISO-8859-1 \
aa_ER/UTF-8 \
aa_ER@saaho/UTF-8 \
aa_ET/UTF-8 \
af_ZA.UTF-8/UTF-8 \
af_ZA/ISO-8859-1 \
agr_PE/UTF-8 \
ak_GH/UTF-8 \
am_ET/UTF-8 \
an_ES.UTF-8/UTF-8 \
an_ES/ISO-8859-15 \
anp_IN/UTF-8 \
ar_AE.UTF-8/UTF-8 \
ar_AE/ISO-8859-6 \
ar_BH.UTF-8/UTF-8 \
ar_BH/ISO-8859-6 \
ar_DZ.UTF-8/UTF-8 \
ar_DZ/ISO-8859-6 \
ar_EG.UTF-8/UTF-8 \
ar_EG/ISO-8859-6 \
ar_IN/UTF-8 \
ar_IQ.UTF-8/UTF-8 \
ar_IQ/ISO-8859-6 \
ar_JO.UTF-8/UTF-8 \
ar_JO/ISO-8859-6 \
ar_KW.UTF-8/UTF-8 \
ar_KW/ISO-8859-6 \
ar_LB.UTF-8/UTF-8 \
ar_LB/ISO-8859-6 \
ar_LY.UTF-8/UTF-8 \
ar_LY/ISO-8859-6 \
ar_MA.UTF-8/UTF-8 \
ar_MA/ISO-8859-6 \
ar_OM.UTF-8/UTF-8 \
ar_OM/ISO-8859-6 \
ar_QA.UTF-8/UTF-8 \
ar_QA/ISO-8859-6 \
ar_SA.UTF-8/UTF-8 \
ar_SA/ISO-8859-6 \
ar_SD.UTF-8/UTF-8 \
ar_SD/ISO-8859-6 \
ar_SS/UTF-8 \
ar_SY.UTF-8/UTF-8 \
ar_SY/ISO-8859-6 \
ar_TN.UTF-8/UTF-8 \
ar_TN/ISO-8859-6 \
ar_YE.UTF-8/UTF-8 \
ar_YE/ISO-8859-6 \
ayc_PE/UTF-8 \
az_AZ/UTF-8 \
az_IR/UTF-8 \
as_IN/UTF-8 \
ast_ES.UTF-8/UTF-8 \
ast_ES/ISO-8859-15 \
be_BY.UTF-8/UTF-8 \
be_BY/CP1251 \
be_BY@latin/UTF-8 \
bem_ZM/UTF-8 \
ber_DZ/UTF-8 \
ber_MA/UTF-8 \
bg_BG.UTF-8/UTF-8 \
bg_BG/CP1251 \
bhb_IN.UTF-8/UTF-8 \
bho_IN/UTF-8 \
bho_NP/UTF-8 \
bi_VU/UTF-8 \
bn_BD/UTF-8 \
bn_IN/UTF-8 \
bo_CN/UTF-8 \
bo_IN/UTF-8 \
br_FR.UTF-8/UTF-8 \
br_FR/ISO-8859-1 \
br_FR@euro/ISO-8859-15 \
brx_IN/UTF-8 \
bs_BA.UTF-8/UTF-8 \
bs_BA/ISO-8859-2 \
byn_ER/UTF-8 \
ca_AD.UTF-8/UTF-8 \
ca_AD/ISO-8859-15 \
ca_ES.UTF-8/UTF-8 \
ca_ES/ISO-8859-1 \
ca_ES@euro/ISO-8859-15 \
ca_ES@valencia/UTF-8 \
ca_FR.UTF-8/UTF-8 \
ca_FR/ISO-8859-15 \
ca_IT.UTF-8/UTF-8 \
ca_IT/ISO-8859-15 \
ce_RU/UTF-8 \
chr_US/UTF-8 \
cmn_TW/UTF-8 \
crh_UA/UTF-8 \
cs_CZ.UTF-8/UTF-8 \
cs_CZ/ISO-8859-2 \
csb_PL/UTF-8 \
cv_RU/UTF-8 \
cy_GB.UTF-8/UTF-8 \
cy_GB/ISO-8859-14 \
da_DK.UTF-8/UTF-8 \
da_DK/ISO-8859-1 \
da_DK.ISO-8859-15/ISO-8859-15 \
de_AT.UTF-8/UTF-8 \
de_AT/ISO-8859-1 \
de_AT@euro/ISO-8859-15 \
de_BE.UTF-8/UTF-8 \
de_BE/ISO-8859-1 \
de_BE@euro/ISO-8859-15 \
de_CH.UTF-8/UTF-8 \
de_CH/ISO-8859-1 \
de_DE.UTF-8/UTF-8 \
de_DE/ISO-8859-1 \
de_DE@euro/ISO-8859-15 \
de_IT.UTF-8/UTF-8 \
de_IT/ISO-8859-1 \
de_LI.UTF-8/UTF-8 \
de_LU.UTF-8/UTF-8 \
de_LU/ISO-8859-1 \
de_LU@euro/ISO-8859-15 \
doi_IN/UTF-8 \
dsb_DE/UTF-8 \
dv_MV/UTF-8 \
dz_BT/UTF-8 \
el_GR.UTF-8/UTF-8 \
el_GR/ISO-8859-7 \
el_GR@euro/ISO-8859-7 \
el_CY.UTF-8/UTF-8 \
el_CY/ISO-8859-7 \
en_AG/UTF-8 \
en_AU.UTF-8/UTF-8 \
en_AU/ISO-8859-1 \
en_BW.UTF-8/UTF-8 \
en_BW/ISO-8859-1 \
en_CA.UTF-8/UTF-8 \
en_CA/ISO-8859-1 \
en_DK.UTF-8/UTF-8 \
en_DK/ISO-8859-1 \
en_GB.UTF-8/UTF-8 \
en_GB/ISO-8859-1 \
en_GB.ISO-8859-15/ISO-8859-15 \
en_HK.UTF-8/UTF-8 \
en_HK/ISO-8859-1 \
en_IE.UTF-8/UTF-8 \
en_IE/ISO-8859-1 \
en_IE@euro/ISO-8859-15 \
en_IL/UTF-8 \
en_IN/UTF-8 \
en_NG/UTF-8 \
en_NZ.UTF-8/UTF-8 \
en_NZ/ISO-8859-1 \
en_PH.UTF-8/UTF-8 \
en_PH/ISO-8859-1 \
en_SC.UTF-8/UTF-8 \
en_SG.UTF-8/UTF-8 \
en_SG/ISO-8859-1 \
en_US.UTF-8/UTF-8 \
en_US/ISO-8859-1 \
en_US.ISO-8859-15/ISO-8859-15 \
en_ZA.UTF-8/UTF-8 \
en_ZA/ISO-8859-1 \
en_ZM/UTF-8 \
en_ZW.UTF-8/UTF-8 \
en_ZW/ISO-8859-1 \
eo/UTF-8 \
es_AR.UTF-8/UTF-8 \
es_AR/ISO-8859-1 \
es_BO.UTF-8/UTF-8 \
es_BO/ISO-8859-1 \
es_CL.UTF-8/UTF-8 \
es_CL/ISO-8859-1 \
es_CO.UTF-8/UTF-8 \
es_CO/ISO-8859-1 \
es_CR.UTF-8/UTF-8 \
es_CR/ISO-8859-1 \
es_CU/UTF-8 \
es_DO.UTF-8/UTF-8 \
es_DO/ISO-8859-1 \
es_EC.UTF-8/UTF-8 \
es_EC/ISO-8859-1 \
es_ES.UTF-8/UTF-8 \
es_ES/ISO-8859-1 \
es_ES@euro/ISO-8859-15 \
es_GT.UTF-8/UTF-8 \
es_GT/ISO-8859-1 \
es_HN.UTF-8/UTF-8 \
es_HN/ISO-8859-1 \
es_MX.UTF-8/UTF-8 \
es_MX/ISO-8859-1 \
es_NI.UTF-8/UTF-8 \
es_NI/ISO-8859-1 \
es_PA.UTF-8/UTF-8 \
es_PA/ISO-8859-1 \
es_PE.UTF-8/UTF-8 \
es_PE/ISO-8859-1 \
es_PR.UTF-8/UTF-8 \
es_PR/ISO-8859-1 \
es_PY.UTF-8/UTF-8 \
es_PY/ISO-8859-1 \
es_SV.UTF-8/UTF-8 \
es_SV/ISO-8859-1 \
es_US.UTF-8/UTF-8 \
es_US/ISO-8859-1 \
es_UY.UTF-8/UTF-8 \
es_UY/ISO-8859-1 \
es_VE.UTF-8/UTF-8 \
es_VE/ISO-8859-1 \
et_EE.UTF-8/UTF-8 \
et_EE/ISO-8859-1 \
et_EE.ISO-8859-15/ISO-8859-15 \
eu_ES.UTF-8/UTF-8 \
eu_ES/ISO-8859-1 \
eu_ES@euro/ISO-8859-15 \
fa_IR/UTF-8 \
ff_SN/UTF-8 \
fi_FI.UTF-8/UTF-8 \
fi_FI/ISO-8859-1 \
fi_FI@euro/ISO-8859-15 \
fil_PH/UTF-8 \
fo_FO.UTF-8/UTF-8 \
fo_FO/ISO-8859-1 \
fr_BE.UTF-8/UTF-8 \
fr_BE/ISO-8859-1 \
fr_BE@euro/ISO-8859-15 \
fr_CA.UTF-8/UTF-8 \
fr_CA/ISO-8859-1 \
fr_CH.UTF-8/UTF-8 \
fr_CH/ISO-8859-1 \
fr_FR.UTF-8/UTF-8 \
fr_FR/ISO-8859-1 \
fr_FR@euro/ISO-8859-15 \
fr_LU.UTF-8/UTF-8 \
fr_LU/ISO-8859-1 \
fr_LU@euro/ISO-8859-15 \
fur_IT/UTF-8 \
fy_NL/UTF-8 \
fy_DE/UTF-8 \
ga_IE.UTF-8/UTF-8 \
ga_IE/ISO-8859-1 \
ga_IE@euro/ISO-8859-15 \
gd_GB.UTF-8/UTF-8 \
gd_GB/ISO-8859-15 \
gez_ER/UTF-8 \
gez_ER@abegede/UTF-8 \
gez_ET/UTF-8 \
gez_ET@abegede/UTF-8 \
gl_ES.UTF-8/UTF-8 \
gl_ES/ISO-8859-1 \
gl_ES@euro/ISO-8859-15 \
gu_IN/UTF-8 \
gv_GB.UTF-8/UTF-8 \
gv_GB/ISO-8859-1 \
ha_NG/UTF-8 \
hak_TW/UTF-8 \
he_IL.UTF-8/UTF-8 \
he_IL/ISO-8859-8 \
hi_IN/UTF-8 \
hif_FJ/UTF-8 \
hne_IN/UTF-8 \
hr_HR.UTF-8/UTF-8 \
hr_HR/ISO-8859-2 \
hsb_DE/ISO-8859-2 \
hsb_DE.UTF-8/UTF-8 \
ht_HT/UTF-8 \
hu_HU.UTF-8/UTF-8 \
hu_HU/ISO-8859-2 \
hy_AM/UTF-8 \
hy_AM.ARMSCII-8/ARMSCII-8 \
ia_FR/UTF-8 \
id_ID.UTF-8/UTF-8 \
id_ID/ISO-8859-1 \
ig_NG/UTF-8 \
ik_CA/UTF-8 \
is_IS.UTF-8/UTF-8 \
is_IS/ISO-8859-1 \
it_CH.UTF-8/UTF-8 \
it_CH/ISO-8859-1 \
it_IT.UTF-8/UTF-8 \
it_IT/ISO-8859-1 \
it_IT@euro/ISO-8859-15 \
iu_CA/UTF-8 \
ja_JP.EUC-JP/EUC-JP \
ja_JP.UTF-8/UTF-8 \
ka_GE.UTF-8/UTF-8 \
ka_GE/GEORGIAN-PS \
kab_DZ/UTF-8 \
kk_KZ.UTF-8/UTF-8 \
kk_KZ/PT154 \
kl_GL.UTF-8/UTF-8 \
kl_GL/ISO-8859-1 \
km_KH/UTF-8 \
kn_IN/UTF-8 \
ko_KR.EUC-KR/EUC-KR \
ko_KR.UTF-8/UTF-8 \
kok_IN/UTF-8 \
ks_IN/UTF-8 \
ks_IN@devanagari/UTF-8 \
ku_TR.UTF-8/UTF-8 \
ku_TR/ISO-8859-9 \
kw_GB.UTF-8/UTF-8 \
kw_GB/ISO-8859-1 \
ky_KG/UTF-8 \
lb_LU/UTF-8 \
lg_UG.UTF-8/UTF-8 \
lg_UG/ISO-8859-10 \
li_BE/UTF-8 \
li_NL/UTF-8 \
lij_IT/UTF-8 \
ln_CD/UTF-8 \
lo_LA/UTF-8 \
lt_LT.UTF-8/UTF-8 \
lt_LT/ISO-8859-13 \
lv_LV.UTF-8/UTF-8 \
lv_LV/ISO-8859-13 \
lzh_TW/UTF-8 \
mag_IN/UTF-8 \
mai_IN/UTF-8 \
mai_NP/UTF-8 \
mfe_MU/UTF-8 \
mg_MG.UTF-8/UTF-8 \
mg_MG/ISO-8859-15 \
mhr_RU/UTF-8 \
mi_NZ.UTF-8/UTF-8 \
mi_NZ/ISO-8859-13 \
miq_NI/UTF-8 \
mjw_IN/UTF-8 \
mk_MK.UTF-8/UTF-8 \
mk_MK/ISO-8859-5 \
ml_IN/UTF-8 \
mn_MN/UTF-8 \
mni_IN/UTF-8 \
mr_IN/UTF-8 \
ms_MY.UTF-8/UTF-8 \
ms_MY/ISO-8859-1 \
mt_MT.UTF-8/UTF-8 \
mt_MT/ISO-8859-3 \
my_MM/UTF-8 \
nan_TW/UTF-8 \
nan_TW@latin/UTF-8 \
nb_NO.UTF-8/UTF-8 \
nb_NO/ISO-8859-1 \
nds_DE/UTF-8 \
nds_NL/UTF-8 \
ne_NP/UTF-8 \
nhn_MX/UTF-8 \
niu_NU/UTF-8 \
niu_NZ/UTF-8 \
nl_AW/UTF-8 \
nl_BE.UTF-8/UTF-8 \
nl_BE/ISO-8859-1 \
nl_BE@euro/ISO-8859-15 \
nl_NL.UTF-8/UTF-8 \
nl_NL/ISO-8859-1 \
nl_NL@euro/ISO-8859-15 \
nn_NO.UTF-8/UTF-8 \
nn_NO/ISO-8859-1 \
nr_ZA/UTF-8 \
nso_ZA/UTF-8 \
oc_FR.UTF-8/UTF-8 \
oc_FR/ISO-8859-1 \
om_ET/UTF-8 \
om_KE.UTF-8/UTF-8 \
om_KE/ISO-8859-1 \
or_IN/UTF-8 \
os_RU/UTF-8 \
pa_IN/UTF-8 \
pa_PK/UTF-8 \
pap_AW/UTF-8 \
pap_CW/UTF-8 \
pl_PL.UTF-8/UTF-8 \
pl_PL/ISO-8859-2 \
ps_AF/UTF-8 \
pt_BR.UTF-8/UTF-8 \
pt_BR/ISO-8859-1 \
pt_PT.UTF-8/UTF-8 \
pt_PT/ISO-8859-1 \
pt_PT@euro/ISO-8859-15 \
quz_PE/UTF-8 \
raj_IN/UTF-8 \
ro_RO.UTF-8/UTF-8 \
ro_RO/ISO-8859-2 \
ru_RU.KOI8-R/KOI8-R \
ru_RU.UTF-8/UTF-8 \
ru_RU/ISO-8859-5 \
ru_UA.UTF-8/UTF-8 \
ru_UA/KOI8-U \
rw_RW/UTF-8 \
sa_IN/UTF-8 \
sah_RU/UTF-8 \
sat_IN/UTF-8 \
sc_IT/UTF-8 \
sd_IN/UTF-8 \
sd_IN@devanagari/UTF-8 \
se_NO/UTF-8 \
sgs_LT/UTF-8 \
shn_MM/UTF-8 \
shs_CA/UTF-8 \
si_LK/UTF-8 \
sid_ET/UTF-8 \
sk_SK.UTF-8/UTF-8 \
sk_SK/ISO-8859-2 \
sl_SI.UTF-8/UTF-8 \
sl_SI/ISO-8859-2 \
sm_WS/UTF-8 \
so_DJ.UTF-8/UTF-8 \
so_DJ/ISO-8859-1 \
so_ET/UTF-8 \
so_KE.UTF-8/UTF-8 \
so_KE/ISO-8859-1 \
so_SO.UTF-8/UTF-8 \
so_SO/ISO-8859-1 \
sq_AL.UTF-8/UTF-8 \
sq_AL/ISO-8859-1 \
sq_MK/UTF-8 \
sr_ME/UTF-8 \
sr_RS/UTF-8 \
sr_RS@latin/UTF-8 \
ss_ZA/UTF-8 \
st_ZA.UTF-8/UTF-8 \
st_ZA/ISO-8859-1 \
sv_FI.UTF-8/UTF-8 \
sv_FI/ISO-8859-1 \
sv_FI@euro/ISO-8859-15 \
sv_SE.UTF-8/UTF-8 \
sv_SE/ISO-8859-1 \
sv_SE.ISO-8859-15/ISO-8859-15 \
sw_KE/UTF-8 \
sw_TZ/UTF-8 \
szl_PL/UTF-8 \
ta_IN/UTF-8 \
ta_LK/UTF-8 \
tcy_IN.UTF-8/UTF-8 \
te_IN/UTF-8 \
tg_TJ.UTF-8/UTF-8 \
tg_TJ/KOI8-T \
th_TH.UTF-8/UTF-8 \
th_TH/TIS-620 \
the_NP/UTF-8 \
ti_ER/UTF-8 \
ti_ET/UTF-8 \
tig_ER/UTF-8 \
tk_TM/UTF-8 \
tl_PH.UTF-8/UTF-8 \
tl_PH/ISO-8859-1 \
tn_ZA/UTF-8 \
to_TO/UTF-8 \
tpi_PG/UTF-8 \
tr_CY.UTF-8/UTF-8 \
tr_CY/ISO-8859-9 \
tr_TR.UTF-8/UTF-8 \
tr_TR/ISO-8859-9 \
ts_ZA/UTF-8 \
tt_RU/UTF-8 \
tt_RU@iqtelif/UTF-8 \
ug_CN/UTF-8 \
uk_UA.UTF-8/UTF-8 \
uk_UA/KOI8-U \
unm_US/UTF-8 \
ur_IN/UTF-8 \
ur_PK/UTF-8 \
uz_UZ.UTF-8/UTF-8 \
uz_UZ/ISO-8859-1 \
uz_UZ@cyrillic/UTF-8 \
ve_ZA/UTF-8 \
vi_VN/UTF-8 \
wa_BE/ISO-8859-1 \
wa_BE@euro/ISO-8859-15 \
wa_BE.UTF-8/UTF-8 \
wae_CH/UTF-8 \
wal_ET/UTF-8 \
wo_SN/UTF-8 \
xh_ZA.UTF-8/UTF-8 \
xh_ZA/ISO-8859-1 \
yi_US.UTF-8/UTF-8 \
yi_US/CP1255 \
yo_NG/UTF-8 \
yue_HK/UTF-8 \
yuw_PG/UTF-8 \
zh_CN.GB18030/GB18030 \
zh_CN.GBK/GBK \
zh_CN.UTF-8/UTF-8 \
zh_CN/GB2312 \
zh_HK.UTF-8/UTF-8 \
zh_HK/BIG5-HKSCS \
zh_SG.UTF-8/UTF-8 \
zh_SG.GBK/GBK \
zh_SG/GB2312 \
zh_TW.EUC-TW/EUC-TW \
zh_TW.UTF-8/UTF-8 \
zh_TW/BIG5 \
zu_ZA.UTF-8/UTF-8 \
zu_ZA/ISO-8859-1 \

857
build-locale-archive.c Normal file
View File

@ -0,0 +1,857 @@
#define _GNU_SOURCE
#include <assert.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <locale.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include "../locale/hashval.h"
#define __LC_LAST 13
#include "../locale/locarchive.h"
#include "../crypt/md5.h"
const char *alias_file = DATADIR "/locale/locale.alias";
const char *locar_file = PREFIX "/lib/locale/locale-archive";
const char *tmpl_file = PREFIX "/lib/locale/locale-archive.tmpl";
const char *loc_path = PREFIX "/lib/locale/";
/* Flags set by `--verbose` option. */
int be_quiet = 1;
int verbose = 0;
int max_locarchive_open_retry = 10;
const char *output_prefix;
/* Endianness should have been taken care of by localedef. We don't need to do
additional swapping. We need this variable exported however, since
locarchive.c uses it to determine if it needs to swap endianness of a value
before writing to or reading from the archive. */
bool swap_endianness_p = false;
static const char *locnames[] =
{
#define DEFINE_CATEGORY(category, category_name, items, a) \
[category] = category_name,
#include "../locale/categories.def"
#undef DEFINE_CATEGORY
};
static int
is_prime (unsigned long candidate)
{
/* No even number and none less than 10 will be passed here. */
unsigned long int divn = 3;
unsigned long int sq = divn * divn;
while (sq < candidate && candidate % divn != 0)
{
++divn;
sq += 4 * divn;
++divn;
}
return candidate % divn != 0;
}
unsigned long
next_prime (unsigned long seed)
{
/* Make it definitely odd. */
seed |= 1;
while (!is_prime (seed))
seed += 2;
return seed;
}
void
error (int status, int errnum, const char *message, ...)
{
va_list args;
va_start (args, message);
fflush (stdout);
fprintf (stderr, "%s: ", program_invocation_name);
vfprintf (stderr, message, args);
va_end (args);
if (errnum)
fprintf (stderr, ": %s", strerror (errnum));
putc ('\n', stderr);
fflush (stderr);
if (status)
exit (errnum == EROFS ? 0 : status);
}
void *
xmalloc (size_t size)
{
void *p = malloc (size);
if (p == NULL)
error (EXIT_FAILURE, errno, "could not allocate %zd bytes of memory", size);
return p;
}
static void
open_tmpl_archive (struct locarhandle *ah)
{
struct stat64 st;
int fd;
struct locarhead head;
const char *archivefname = ah->fname == NULL ? tmpl_file : ah->fname;
/* Open the archive. We must have exclusive write access. */
fd = open64 (archivefname, O_RDONLY);
if (fd == -1)
error (EXIT_FAILURE, errno, "cannot open locale archive template file \"%s\"",
archivefname);
if (fstat64 (fd, &st) < 0)
error (EXIT_FAILURE, errno, "cannot stat locale archive template file \"%s\"",
archivefname);
/* Read the header. */
if (TEMP_FAILURE_RETRY (read (fd, &head, sizeof (head))) != sizeof (head))
error (EXIT_FAILURE, errno, "cannot read archive header");
ah->fd = fd;
ah->mmaped = (head.sumhash_offset
+ head.sumhash_size * sizeof (struct sumhashent));
if (ah->mmaped > (unsigned long) st.st_size)
error (EXIT_FAILURE, 0, "locale archive template file truncated");
ah->mmaped = st.st_size;
ah->reserved = st.st_size;
/* Now we know how large the administrative information part is.
Map all of it. */
ah->addr = mmap64 (NULL, ah->mmaped, PROT_READ, MAP_SHARED, fd, 0);
if (ah->addr == MAP_FAILED)
error (EXIT_FAILURE, errno, "cannot map archive header");
}
/* Open the locale archive. */
extern void open_archive (struct locarhandle *ah, bool readonly);
/* Close the locale archive. */
extern void close_archive (struct locarhandle *ah);
/* Add given locale data to the archive. */
extern int add_locale_to_archive (struct locarhandle *ah, const char *name,
locale_data_t data, bool replace);
extern void add_alias (struct locarhandle *ah, const char *alias,
bool replace, const char *oldname,
uint32_t *locrec_offset_p);
extern struct namehashent *
insert_name (struct locarhandle *ah,
const char *name, size_t name_len, bool replace);
struct nameent
{
char *name;
struct locrecent *locrec;
};
struct dataent
{
const unsigned char *sum;
uint32_t file_offset;
};
static int
nameentcmp (const void *a, const void *b)
{
struct locrecent *la = ((const struct nameent *) a)->locrec;
struct locrecent *lb = ((const struct nameent *) b)->locrec;
uint32_t start_a = -1, end_a = 0;
uint32_t start_b = -1, end_b = 0;
int cnt;
for (cnt = 0; cnt < __LC_LAST; ++cnt)
if (cnt != LC_ALL)
{
if (la->record[cnt].offset < start_a)
start_a = la->record[cnt].offset;
if (la->record[cnt].offset + la->record[cnt].len > end_a)
end_a = la->record[cnt].offset + la->record[cnt].len;
}
assert (start_a != (uint32_t)-1);
assert (end_a != 0);
for (cnt = 0; cnt < __LC_LAST; ++cnt)
if (cnt != LC_ALL)
{
if (lb->record[cnt].offset < start_b)
start_b = lb->record[cnt].offset;
if (lb->record[cnt].offset + lb->record[cnt].len > end_b)
end_b = lb->record[cnt].offset + lb->record[cnt].len;
}
assert (start_b != (uint32_t)-1);
assert (end_b != 0);
if (start_a != start_b)
return (int)start_a - (int)start_b;
return (int)end_a - (int)end_b;
}
static int
dataentcmp (const void *a, const void *b)
{
if (((const struct dataent *) a)->file_offset
< ((const struct dataent *) b)->file_offset)
return -1;
if (((const struct dataent *) a)->file_offset
> ((const struct dataent *) b)->file_offset)
return 1;
return 0;
}
static int
sumsearchfn (const void *key, const void *ent)
{
uint32_t keyn = *(uint32_t *)key;
uint32_t entn = ((struct dataent *)ent)->file_offset;
if (keyn < entn)
return -1;
if (keyn > entn)
return 1;
return 0;
}
static void
compute_data (struct locarhandle *ah, struct nameent *name, size_t sumused,
struct dataent *files, locale_data_t data)
{
int cnt;
struct locrecent *locrec = name->locrec;
struct dataent *file;
data[LC_ALL].addr = ((char *) ah->addr) + locrec->record[LC_ALL].offset;
data[LC_ALL].size = locrec->record[LC_ALL].len;
for (cnt = 0; cnt < __LC_LAST; ++cnt)
if (cnt != LC_ALL)
{
data[cnt].addr = ((char *) ah->addr) + locrec->record[cnt].offset;
data[cnt].size = locrec->record[cnt].len;
if (data[cnt].addr >= data[LC_ALL].addr
&& data[cnt].addr + data[cnt].size
<= data[LC_ALL].addr + data[LC_ALL].size)
__md5_buffer (data[cnt].addr, data[cnt].size, data[cnt].sum);
else
{
file = bsearch (&locrec->record[cnt].offset, files, sumused,
sizeof (*files), sumsearchfn);
if (file == NULL)
error (EXIT_FAILURE, 0, "inconsistent template file");
memcpy (data[cnt].sum, file->sum, sizeof (data[cnt].sum));
}
}
}
static int
fill_archive (struct locarhandle *tmpl_ah,
const char *fname,
size_t install_langs_count, char *install_langs_list[],
size_t nlist, char *list[],
const char *primary)
{
struct locarhandle ah;
struct locarhead *head;
int result = 0;
struct nameent *names;
struct namehashent *namehashtab;
size_t cnt, used;
struct dataent *files;
struct sumhashent *sumhashtab;
size_t sumused;
struct locrecent *primary_locrec = NULL;
struct nameent *primary_nameent = NULL;
head = tmpl_ah->addr;
names = (struct nameent *) malloc (head->namehash_used
* sizeof (struct nameent));
files = (struct dataent *) malloc (head->sumhash_used
* sizeof (struct dataent));
if (names == NULL || files == NULL)
error (EXIT_FAILURE, errno, "could not allocate tables");
namehashtab = (struct namehashent *) ((char *) tmpl_ah->addr
+ head->namehash_offset);
sumhashtab = (struct sumhashent *) ((char *) tmpl_ah->addr
+ head->sumhash_offset);
for (cnt = used = 0; cnt < head->namehash_size; ++cnt)
if (namehashtab[cnt].locrec_offset != 0)
{
char * name;
int i;
assert (used < head->namehash_used);
name = tmpl_ah->addr + namehashtab[cnt].name_offset;
if (install_langs_count == 0)
{
/* Always intstall the entry. */
names[used].name = name;
names[used++].locrec
= (struct locrecent *) ((char *) tmpl_ah->addr +
namehashtab[cnt].locrec_offset);
}
else
{
/* Only install the entry if the user asked for it via
--install-langs. */
for (i = 0; i < install_langs_count; i++)
{
/* Add one for "_" and one for the null terminator. */
size_t len = strlen (install_langs_list[i]) + 2;
char *install_lang = (char *)xmalloc (len);
strcpy (install_lang, install_langs_list[i]);
if (strchr (install_lang, '_') == NULL)
strcat (install_lang, "_");
if (strncmp (name, install_lang, strlen (install_lang)) == 0)
{
names[used].name = name;
names[used++].locrec
= (struct locrecent *) ((char *)tmpl_ah->addr
+ namehashtab[cnt].locrec_offset);
}
free (install_lang);
}
}
}
/* Sort the names. */
qsort (names, used, sizeof (struct nameent), nameentcmp);
for (cnt = sumused = 0; cnt < head->sumhash_size; ++cnt)
if (sumhashtab[cnt].file_offset != 0)
{
assert (sumused < head->sumhash_used);
files[sumused].sum = (const unsigned char *) sumhashtab[cnt].sum;
files[sumused++].file_offset = sumhashtab[cnt].file_offset;
}
/* Sort by file locations. */
qsort (files, sumused, sizeof (struct dataent), dataentcmp);
/* Open the archive. This call never returns if we cannot
successfully open the archive. */
ah.fname = NULL;
if (fname != NULL)
ah.fname = fname;
open_archive (&ah, false);
if (primary != NULL)
{
for (cnt = 0; cnt < used; ++cnt)
if (strcmp (names[cnt].name, primary) == 0)
break;
if (cnt < used)
{
locale_data_t data;
compute_data (tmpl_ah, &names[cnt], sumused, files, data);
result |= add_locale_to_archive (&ah, primary, data, 0);
primary_locrec = names[cnt].locrec;
primary_nameent = &names[cnt];
}
}
for (cnt = 0; cnt < used; ++cnt)
if (&names[cnt] == primary_nameent)
continue;
else if ((cnt > 0 && names[cnt - 1].locrec == names[cnt].locrec)
|| names[cnt].locrec == primary_locrec)
{
const char *oldname;
struct namehashent *namehashent;
uint32_t locrec_offset;
if (names[cnt].locrec == primary_locrec)
oldname = primary;
else
oldname = names[cnt - 1].name;
namehashent = insert_name (&ah, oldname, strlen (oldname), true);
assert (namehashent->name_offset != 0);
assert (namehashent->locrec_offset != 0);
locrec_offset = namehashent->locrec_offset;
add_alias (&ah, names[cnt].name, 0, oldname, &locrec_offset);
}
else
{
locale_data_t data;
compute_data (tmpl_ah, &names[cnt], sumused, files, data);
result |= add_locale_to_archive (&ah, names[cnt].name, data, 0);
}
while (nlist-- > 0)
{
const char *fname = *list++;
size_t fnamelen = strlen (fname);
struct stat64 st;
DIR *dirp;
struct dirent64 *d;
int seen;
locale_data_t data;
int cnt;
/* First see whether this really is a directory and whether it
contains all the require locale category files. */
if (stat64 (fname, &st) < 0)
{
error (0, 0, "stat of \"%s\" failed: %s: ignored", fname,
strerror (errno));
continue;
}
if (!S_ISDIR (st.st_mode))
{
error (0, 0, "\"%s\" is no directory; ignored", fname);
continue;
}
dirp = opendir (fname);
if (dirp == NULL)
{
error (0, 0, "cannot open directory \"%s\": %s: ignored",
fname, strerror (errno));
continue;
}
seen = 0;
while ((d = readdir64 (dirp)) != NULL)
{
for (cnt = 0; cnt < __LC_LAST; ++cnt)
if (cnt != LC_ALL)
if (strcmp (d->d_name, locnames[cnt]) == 0)
{
unsigned char d_type;
/* We have an object of the required name. If it's
a directory we have to look at a file with the
prefix "SYS_". Otherwise we have found what we
are looking for. */
#ifdef _DIRENT_HAVE_D_TYPE
d_type = d->d_type;
if (d_type != DT_REG)
#endif
{
char fullname[fnamelen + 2 * strlen (d->d_name) + 7];
#ifdef _DIRENT_HAVE_D_TYPE
if (d_type == DT_UNKNOWN)
#endif
{
strcpy (stpcpy (stpcpy (fullname, fname), "/"),
d->d_name);
if (stat64 (fullname, &st) == -1)
/* We cannot stat the file, ignore it. */
break;
d_type = IFTODT (st.st_mode);
}
if (d_type == DT_DIR)
{
/* We have to do more tests. The file is a
directory and it therefore must contain a
regular file with the same name except a
"SYS_" prefix. */
char *t = stpcpy (stpcpy (fullname, fname), "/");
strcpy (stpcpy (stpcpy (t, d->d_name), "/SYS_"),
d->d_name);
if (stat64 (fullname, &st) == -1)
/* There is no SYS_* file or we cannot
access it. */
break;
d_type = IFTODT (st.st_mode);
}
}
/* If we found a regular file (eventually after
following a symlink) we are successful. */
if (d_type == DT_REG)
++seen;
break;
}
}
closedir (dirp);
if (seen != __LC_LAST - 1)
{
/* We don't have all locale category files. Ignore the name. */
error (0, 0, "incomplete set of locale files in \"%s\"",
fname);
continue;
}
/* Add the files to the archive. To do this we first compute
sizes and the MD5 sums of all the files. */
for (cnt = 0; cnt < __LC_LAST; ++cnt)
if (cnt != LC_ALL)
{
char fullname[fnamelen + 2 * strlen (locnames[cnt]) + 7];
int fd;
strcpy (stpcpy (stpcpy (fullname, fname), "/"), locnames[cnt]);
fd = open64 (fullname, O_RDONLY);
if (fd == -1 || fstat64 (fd, &st) == -1)
{
/* Cannot read the file. */
if (fd != -1)
close (fd);
break;
}
if (S_ISDIR (st.st_mode))
{
char *t;
close (fd);
t = stpcpy (stpcpy (fullname, fname), "/");
strcpy (stpcpy (stpcpy (t, locnames[cnt]), "/SYS_"),
locnames[cnt]);
fd = open64 (fullname, O_RDONLY);
if (fd == -1 || fstat64 (fd, &st) == -1
|| !S_ISREG (st.st_mode))
{
if (fd != -1)
close (fd);
break;
}
}
/* Map the file. */
data[cnt].addr = mmap64 (NULL, st.st_size, PROT_READ, MAP_SHARED,
fd, 0);
if (data[cnt].addr == MAP_FAILED)
{
/* Cannot map it. */
close (fd);
break;
}
data[cnt].size = st.st_size;
__md5_buffer (data[cnt].addr, st.st_size, data[cnt].sum);
/* We don't need the file descriptor anymore. */
close (fd);
}
if (cnt != __LC_LAST)
{
while (cnt-- > 0)
if (cnt != LC_ALL)
munmap (data[cnt].addr, data[cnt].size);
error (0, 0, "cannot read all files in \"%s\": ignored", fname);
continue;
}
result |= add_locale_to_archive (&ah, basename (fname), data, 0);
for (cnt = 0; cnt < __LC_LAST; ++cnt)
if (cnt != LC_ALL)
munmap (data[cnt].addr, data[cnt].size);
}
/* We are done. */
close_archive (&ah);
return result;
}
void usage()
{
printf ("\
Usage: build-locale-archive [OPTION]... [TEMPLATE-FILE] [ARCHIVE-FILE]\n\
Builds a locale archive from a template file.\n\
Options:\n\
-h, --help Print this usage message.\n\
-v, --verbose Verbose execution.\n\
-l, --install-langs=LIST Only include locales given in LIST into the \n\
locale archive. LIST is a colon separated list\n\
of locale prefixes, for example \"de:en:ja\".\n\
The special argument \"all\" means to install\n\
all languages and it must be present by itself.\n\
If \"all\" is present with any other language it\n\
will be treated as the name of a locale.\n\
If the --install-langs option is missing, all\n\
locales are installed. The colon separated list\n\
can contain any strings matching the beginning of\n\
locale names.\n\
If a string does not contain a \"_\", it is added.\n\
Examples:\n\
--install-langs=\"en\"\n\
installs en_US, en_US.iso88591,\n\
en_US.iso885915, en_US.utf8,\n\
en_GB ...\n\
--install-langs=\"en_US.utf8\"\n\
installs only en_US.utf8.\n\
--install-langs=\"ko\"\n\
installs ko_KR, ko_KR.euckr,\n\
ko_KR.utf8 but *not* kok_IN\n\
because \"ko\" does not contain\n\
\"_\" and it is silently added\n\
--install-langs\"ko:kok\"\n\
installs ko_KR, ko_KR.euckr,\n\
ko_KR.utf8, kok_IN, and\n\
kok_IN.utf8.\n\
--install-langs=\"POSIX\" will\n\
installs *no* locales at all\n\
because POSIX matches none of\n\
the locales. Actually, any string\n\
matching nothing will do that.\n\
POSIX and C will always be\n\
available because they are\n\
builtin.\n\
Aliases are installed as well,\n\
i.e. --install-langs=\"de\"\n\
will install not only every locale starting with\n\
\"de\" but also the aliases \"deutsch\"\n\
and and \"german\" although the latter does not\n\
start with \"de\".\n\
\n\
If the arguments TEMPLATE-FILE and ARCHIVE-FILE are not given the locations\n\
where the glibc used expects these files are used by default.\n\
");
}
int main (int argc, char *argv[])
{
char path[4096];
DIR *dirp;
struct dirent64 *d;
struct stat64 st;
char *list[16384], *primary;
char *lang;
int install_langs_count = 0;
int i;
char *install_langs_arg, *ila_start;
char **install_langs_list;
unsigned int cnt = 0;
struct locarhandle tmpl_ah;
char *new_locar_fname = NULL;
size_t loc_path_len = strlen (loc_path);
while (1)
{
int c;
static struct option long_options[] =
{
{"help", no_argument, 0, 'h'},
{"verbose", no_argument, 0, 'v'},
{"install-langs", required_argument, 0, 'l'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long (argc, argv, "vhl:",
long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c)
{
case 0:
printf ("unknown option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
usage ();
exit (1);
case 'v':
verbose = 1;
be_quiet = 0;
break;
case 'h':
usage ();
exit (0);
case 'l':
install_langs_arg = ila_start = strdup (optarg);
/* If the argument to --install-lang is "all", do
not limit the list of languages to install and install
them all. We do not support installing a single locale
called "all". */
#define MAGIC_INSTALL_ALL "all"
if (install_langs_arg != NULL
&& install_langs_arg[0] != '\0'
&& !(strncmp(install_langs_arg, MAGIC_INSTALL_ALL,
strlen(MAGIC_INSTALL_ALL)) == 0
&& strlen (install_langs_arg) == 3))
{
/* Count the number of languages we will install. */
while (true)
{
lang = strtok(install_langs_arg, ":;,");
if (lang == NULL)
break;
install_langs_count++;
install_langs_arg = NULL;
}
free (ila_start);
/* Copy the list. */
install_langs_list = (char **)xmalloc (sizeof(char *) * install_langs_count);
install_langs_arg = ila_start = strdup (optarg);
install_langs_count = 0;
while (true)
{
lang = strtok(install_langs_arg, ":;,");
if (lang == NULL)
break;
install_langs_list[install_langs_count] = lang;
install_langs_count++;
install_langs_arg = NULL;
}
}
break;
case '?':
/* getopt_long already printed an error message. */
usage ();
exit (0);
default:
abort ();
}
}
tmpl_ah.fname = NULL;
if (optind < argc)
tmpl_ah.fname = argv[optind];
if (optind + 1 < argc)
new_locar_fname = argv[optind + 1];
if (verbose)
{
if (tmpl_ah.fname)
printf("input archive file specified on command line: %s\n",
tmpl_ah.fname);
else
printf("using default input archive file.\n");
if (new_locar_fname)
printf("output archive file specified on command line: %s\n",
new_locar_fname);
else
printf("using default output archive file.\n");
}
dirp = opendir (loc_path);
if (dirp == NULL)
error (EXIT_FAILURE, errno, "cannot open directory \"%s\"", loc_path);
open_tmpl_archive (&tmpl_ah);
if (new_locar_fname)
unlink (new_locar_fname);
else
unlink (locar_file);
primary = getenv ("LC_ALL");
if (primary == NULL)
primary = getenv ("LANG");
if (primary != NULL)
{
if (strncmp (primary, "ja", 2) != 0
&& strncmp (primary, "ko", 2) != 0
&& strncmp (primary, "zh", 2) != 0)
{
char *ptr = malloc (strlen (primary) + strlen (".utf8") + 1), *p, *q;
/* This leads to invalid locales sometimes:
de_DE.iso885915@euro -> de_DE.utf8@euro */
if (ptr != NULL)
{
p = ptr;
q = primary;
while (*q && *q != '.' && *q != '@')
*p++ = *q++;
if (*q == '.')
while (*q && *q != '@')
q++;
p = stpcpy (p, ".utf8");
strcpy (p, q);
primary = ptr;
}
else
primary = NULL;
}
}
memcpy (path, loc_path, loc_path_len);
while ((d = readdir64 (dirp)) != NULL)
{
if (strcmp (d->d_name, ".") == 0 || strcmp (d->d_name, "..") == 0)
continue;
if (strchr (d->d_name, '_') == NULL)
continue;
size_t d_name_len = strlen (d->d_name);
if (loc_path_len + d_name_len + 1 > sizeof (path))
{
error (0, 0, "too long filename \"%s\"", d->d_name);
continue;
}
memcpy (path + loc_path_len, d->d_name, d_name_len + 1);
if (stat64 (path, &st) < 0)
{
error (0, errno, "cannot stat \"%s\"", path);
continue;
}
if (! S_ISDIR (st.st_mode))
continue;
if (cnt == 16384)
{
error (0, 0, "too many directories in \"%s\"", loc_path);
break;
}
list[cnt] = strdup (path);
if (list[cnt] == NULL)
{
error (0, errno, "cannot add file to list \"%s\"", path);
continue;
}
if (primary != NULL && cnt > 0 && strcmp (primary, d->d_name) == 0)
{
char *p = list[0];
list[0] = list[cnt];
list[cnt] = p;
}
cnt++;
}
closedir (dirp);
/* Store the archive to the file specified as the second argument on the
command line or the default locale archive. */
fill_archive (&tmpl_ah, new_locar_fname,
install_langs_count, install_langs_list,
cnt, list, primary);
close_archive (&tmpl_ah);
truncate (tmpl_file, 0);
if (install_langs_count > 0)
{
free (ila_start);
free (install_langs_list);
}
char *tz_argv[] = { "/usr/sbin/tzdata-update", NULL };
execve (tz_argv[0], (char *const *)tz_argv, (char *const *)&tz_argv[1]);
exit (0);
}

View File

@ -5,10 +5,30 @@ component="glibc"
rm -f series.new
extra_args="--fuzz=0"
count=0
# Transform patches into series file.
grep '^Patch.*:' glibc.spec | sed -e 's,Patch.*: ,,g' > series.new
count=`wc -l series.new | sed -e 's, .*$,,g'`
# Filter out the patches, and use `_` as our pseudo-IFS to prevent expansion.
for i in `grep '^%patch' glibc.spec | sed -e 's,%patch,,g' -e 's, ,_,g'`; do
# Split the patch into number and arguments.
# 1 - Patch number.
# 2-N - Patch arguments.
# Get back our elements by undoing pseudo-IFS change.
elements=(`echo $i | sed -e 's,_, ,g'`)
num=${elements[0]}
args=${elements[@]:1}
# Find the next patch that applies in order and write it out.
# This way we transform the patch # list into a patch file list in order.
grep "Patch${num}: " glibc.spec \
| sed -e 's,Patch.*: ,,g' -e "s,\$, ${args[@]} ${extra_args},g" \
| sed -e "s,%{name},${component},g" \
>> series.new
((count++))
done
# Double check we processed the correct number of patches.
fcount=`wc -l series.new | sed -e 's, .*$,,g'`
if [ $fcount -ne $count ]; then
echo "Error! Processed patch count doesn't match spec file count ($fcount != $count)."
exit 1
fi
echo "Processed $count patches."
mv series.new series
echo "Generated quilt ./series file. Please do not commit."
echo "Generated quilt ./series file, please commit."
exit 0

View File

@ -0,0 +1,13 @@
diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h
index 997c860..50b37b0 100644
--- a/sysdeps/aarch64/dl-machine.h
+++ b/sysdeps/aarch64/dl-machine.h
@@ -295,7 +295,7 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
# ifndef SHARED
CHECK_STATIC_TLS (map, sym_map);
# else
- if (!TRY_STATIC_TLS (map, sym_map))
+ if (1)
{
td->arg = _dl_make_tlsdesc_dynamic
(sym_map, sym->st_value + reloc->r_addend);

View File

@ -0,0 +1,33 @@
diff --git a/sysdeps/aarch64/dl-tlsdesc.S b/sysdeps/aarch64/dl-tlsdesc.S
index ded5471..7d28496 100644
--- a/sysdeps/aarch64/dl-tlsdesc.S
+++ b/sysdeps/aarch64/dl-tlsdesc.S
@@ -140,7 +140,7 @@ _dl_tlsdesc_undefweak:
cfi_startproc
.align 2
_dl_tlsdesc_dynamic:
-# define NSAVEXREGPAIRS 2
+# define NSAVEXREGPAIRS 3
stp x29, x30, [sp,#-(32+16*NSAVEXREGPAIRS)]!
cfi_adjust_cfa_offset (32+16*NSAVEXREGPAIRS)
mov x29, sp
@@ -151,6 +151,10 @@ _dl_tlsdesc_dynamic:
stp x1, x2, [sp, #32+16*0]
stp x3, x4, [sp, #32+16*1]
+ /* Work around GCC rescheduling compares across tlsdesc calls. */
+ mrs x30, nzcv
+ stp xzr, x30, [sp, #32+16*2]
+
mrs x4, tpidr_el0
/* The ldar here happens after the load from [x0] at the call site
(that is generated by the compiler as part of the TLS access ABI),
@@ -169,6 +173,8 @@ _dl_tlsdesc_dynamic:
1:
ldp x1, x2, [sp, #32+16*0]
ldp x3, x4, [sp, #32+16*1]
+ ldp xzr, x30, [sp, #32+16*2]
+ msr nzcv, x30
ldp x29, x30, [sp], #(32+16*NSAVEXREGPAIRS)
cfi_adjust_cfa_offset (-32-16*NSAVEXREGPAIRS)

View File

@ -0,0 +1,20 @@
diff -Nrup a/elf/dl-load.c b/elf/dl-load.c
--- a/elf/dl-load.c 2012-06-06 13:07:41.727524312 -0600
+++ b/elf/dl-load.c 2012-06-06 13:11:19.308681002 -0600
@@ -2093,10 +2093,14 @@ _dl_map_object (struct link_map *loader,
soname = ((const char *) D_PTR (l, l_info[DT_STRTAB])
+ l->l_info[DT_SONAME]->d_un.d_val);
if (strcmp (name, soname) != 0)
- continue;
+#ifdef __arm__
+ if (strcmp (name, "ld-linux.so.3")
+ || strcmp (soname, "ld-linux-armhf.so.3"))
+#endif
+ continue;
/* We have a match on a new name -- cache it. */
- add_name_to_object (l, soname);
+ add_name_to_object (l, name);
l->l_soname_added = 1;
}

41
glibc-bench-build.patch Normal file
View File

@ -0,0 +1,41 @@
diff --git a/Makefile.in b/Makefile.in
index 710ce7e..3fe9e73 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -12,7 +12,7 @@ install:
LC_ALL=C; export LC_ALL; \
$(MAKE) -r PARALLELMFLAGS="$(PARALLELMFLAGS)" -C $(srcdir) objdir=`pwd` $@
-bench bench-clean:
+bench bench-clean bench-build:
$(MAKE) -C $(srcdir)/benchtests $(PARALLELMFLAGS) objdir=`pwd` $@
# Convenience target to rebuild ULPs for all math tests.
diff --git a/Rules b/Rules
index 4f9cdf3..42d0368 100644
--- a/Rules
+++ b/Rules
@@ -83,7 +83,7 @@ common-generated += dummy.o dummy.c
# This makes all the auxiliary and test programs.
-.PHONY: others tests bench
+.PHONY: others tests bench bench-build
ifeq ($(build-programs),yes)
others: $(addprefix $(objpfx),$(others) $(sysdep-others) $(extra-objs))
diff --git a/benchtests/Makefile b/benchtests/Makefile
index fd3036d..7cbceaa 100644
--- a/benchtests/Makefile
+++ b/benchtests/Makefile
@@ -103,6 +103,10 @@ bench-clean:
bench: $(timing-type) $(gen-locales) bench-set bench-func bench-malloc
+bench-build: bench-set-build bench-func-build
+bench-set-build: $(binaries-benchset)
+bench-func-build: $(binaries-bench) $(binaries-bench-malloc)
+
bench-set: $(binaries-benchset)
for run in $^; do \
echo "Running $${run}"; \

140
glibc-bug-regex-gcc5.patch Normal file
View File

@ -0,0 +1,140 @@
Index: glibc-2.22-193-g315267a/posix/bug-regex11.c
===================================================================
--- glibc-2.22-193-g315267a.orig/posix/bug-regex11.c
+++ glibc-2.22-193-g315267a/posix/bug-regex11.c
@@ -22,6 +22,7 @@
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
+#include <libc-internal.h>
/* Tests supposed to match. */
struct
@@ -119,6 +120,14 @@ main (void)
continue;
}
+ DIAG_PUSH_NEEDS_COMMENT
+#if __GNUC_PREREQ (5, 0)
+ /* GCC 5.0 warns about array subscript being above array bounds,
+ but that's not entirely possible since n is limited to
+ static nmatch which is limited to at most 5 (see tests above).
+ This is likely PR/59124 which is still not fixed. */
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
+#endif
for (n = 0; n < tests[i].nmatch; ++n)
if (rm[n].rm_so != tests[i].rm[n].rm_so
|| rm[n].rm_eo != tests[i].rm[n].rm_eo)
@@ -130,6 +139,7 @@ main (void)
ret = 1;
break;
}
+ DIAG_POP_NEEDS_COMMENT
regfree (&re);
}
Index: glibc-2.22-193-g315267a/posix/bug-regex17.c
===================================================================
--- glibc-2.22-193-g315267a.orig/posix/bug-regex17.c
+++ glibc-2.22-193-g315267a/posix/bug-regex17.c
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
+#include <libc-internal.h>
/* Tests supposed to match. */
struct
@@ -87,6 +88,14 @@ do_test (void)
continue;
}
+ DIAG_PUSH_NEEDS_COMMENT
+#if __GNUC_PREREQ (5, 0)
+ /* GCC 5.0 warns about array subscript being above array bounds,
+ but that's not entirely possible since n is limited to
+ static nmatch which is limited to at most 5 (see tests above).
+ This is likely PR/59124 which is still not fixed. */
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
+#endif
for (n = 0; n < tests[i].nmatch; ++n)
if (rm[n].rm_so != tests[i].rm[n].rm_so
|| rm[n].rm_eo != tests[i].rm[n].rm_eo)
@@ -98,6 +107,7 @@ do_test (void)
ret = 1;
break;
}
+ DIAG_POP_NEEDS_COMMENT
regfree (&re);
}
Index: glibc-2.22-193-g315267a/posix/bug-regex18.c
===================================================================
--- glibc-2.22-193-g315267a.orig/posix/bug-regex18.c
+++ glibc-2.22-193-g315267a/posix/bug-regex18.c
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
+#include <libc-internal.h>
/* Tests supposed to match. */
struct
@@ -80,6 +81,14 @@ main (void)
continue;
}
+ DIAG_PUSH_NEEDS_COMMENT
+#if __GNUC_PREREQ (5, 0)
+ /* GCC 5.0 warns about array subscript being above array bounds,
+ but that's not entirely possible since n is limited to
+ static nmatch which is limited to at most 5 (see tests above).
+ This is likely PR/59124 which is still not fixed. */
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
+#endif
for (n = 0; n < tests[i].nmatch; ++n)
if (rm[n].rm_so != tests[i].rm[n].rm_so
|| rm[n].rm_eo != tests[i].rm[n].rm_eo)
@@ -91,6 +100,7 @@ main (void)
ret = 1;
break;
}
+ DIAG_POP_NEEDS_COMMENT
regfree (&re);
}
Index: glibc-2.22-193-g315267a/posix/bug-regex30.c
===================================================================
--- glibc-2.22-193-g315267a.orig/posix/bug-regex30.c
+++ glibc-2.22-193-g315267a/posix/bug-regex30.c
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
+#include <libc-internal.h>
/* Tests supposed to match. */
struct
@@ -80,6 +81,14 @@ do_test (void)
continue;
}
+ DIAG_PUSH_NEEDS_COMMENT
+#if __GNUC_PREREQ (5, 0)
+ /* GCC 5.0 warns about array subscript being above array bounds,
+ but that's not entirely possible since n is limited to
+ static nmatch which is limited to at most 5 (see tests above).
+ This is likely PR/59124 which is still not fixed. */
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
+#endif
for (n = 0; n < tests[i].nmatch; ++n)
if (rm[n].rm_so != tests[i].rm[n].rm_so
|| rm[n].rm_eo != tests[i].rm[n].rm_eo)
@@ -91,6 +100,7 @@ do_test (void)
ret = 1;
break;
}
+ DIAG_POP_NEEDS_COMMENT
regfree (&re);
}

View File

@ -1,19 +1,3 @@
Short description: Add C.UTF-8 support.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Upstream status: not-submitted
This patch needs to upstream as part of Carlos O'Donell
<carlos@redhat.com>'s work on enabling upstream C.UTF-8 support. This
work is currently blocked on cleaning up the test results to prove that
full code-point sorting is working as intended.
Note that this patch does not provide full code-point sorting as
expected.
This patch needs to upstream as soon as possible since it would be nice
to have this in F29 and fixed.
From 2eda7b462b415105f5a05c1323372d4e39d46439 Mon Sep 17 00:00:00 2001
From: Mike FABIAN <mfabian@redhat.com>
Date: Mon, 10 Aug 2015 15:58:12 +0200
@ -60,18 +44,18 @@ index 0000000..fdf460e
+revision "1.0"
+date "2015-08-10"
+%
+category "i18n:2012";LC_IDENTIFICATION
+category "i18n:2012";LC_CTYPE
+category "i18n:2012";LC_COLLATE
+category "i18n:2012";LC_TIME
+category "i18n:2012";LC_NUMERIC
+category "i18n:2012";LC_MONETARY
+category "i18n:2012";LC_MESSAGES
+category "i18n:2012";LC_PAPER
+category "i18n:2012";LC_NAME
+category "i18n:2012";LC_ADDRESS
+category "i18n:2012";LC_TELEPHONE
+category "i18n:2012";LC_MEASUREMENT
+category "C:2015";LC_IDENTIFICATION
+category "C:2015";LC_CTYPE
+category "C:2015";LC_COLLATE
+category "C:2015";LC_TIME
+category "C:2015";LC_NUMERIC
+category "C:2015";LC_MONETARY
+category "C:2015";LC_MESSAGES
+category "C:2015";LC_PAPER
+category "C:2015";LC_NAME
+category "C:2015";LC_ADDRESS
+category "C:2015";LC_TELEPHONE
+category "C:2015";LC_MEASUREMENT
+END LC_IDENTIFICATION
+
+LC_CTYPE
@ -88,21 +72,21 @@ index 0000000..fdf460e
+<U0000>
+..
+<UFFFF>
+<U00010000>
+<U10000>
+..
+<U0001FFFF>
+<U00020000>
+<U1FFFF>
+<U20000>
+..
+<U0002FFFF>
+<U000E0000>
+<U2FFFF>
+<UE0000>
+..
+<U000EFFFF>
+<U000F0000>
+<UEFFFF>
+<UF0000>
+..
+<U000FFFFF>
+<U00100000>
+<UFFFFF>
+<U100000>
+..
+<U0010FFFF>
+<U10FFFF>
+UNDEFINED
+order_end
+END LC_COLLATE

View File

@ -1,12 +1,3 @@
Short description: Adjust CS_PATH return value.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Upstream status: not-needed
In Fedora we should return only /usr/bin because /bin is just a symlink
to /usr/bin after MoveToUsr transition (which glibc has not really
completed).
diff -pruN a/sysdeps/unix/confstr.h b/sysdeps/unix/confstr.h
--- a/sysdeps/unix/confstr.h 2012-12-25 08:32:13.000000000 +0530
+++ b/sysdeps/unix/confstr.h 2014-09-05 20:02:55.698275219 +0530

View File

@ -0,0 +1,22 @@
diff -urN glibc-2.20.mod/sysdeps/unix/sysv/linux/x86/elision-conf.c glibc-2.20/sysdeps/unix/sysv/linux/x86/elision-conf.c
--- glibc-2.20.mod/sysdeps/unix/sysv/linux/x86/elision-conf.c 2014-09-27 00:25:46.443462345 -0400
+++ glibc-2.20/sysdeps/unix/sysv/linux/x86/elision-conf.c 2014-09-27 00:29:53.586615813 -0400
@@ -62,12 +62,16 @@
char **argv __attribute__ ((unused)),
char **environ)
{
- __elision_available = HAS_CPU_FEATURE (RTM);
#ifdef ENABLE_LOCK_ELISION
+ __elision_available = HAS_CPU_FEATURE (RTM);
__pthread_force_elision = __libc_enable_secure ? 0 : __elision_available;
-#endif
if (!HAS_CPU_FEATURE (RTM))
__elision_aconf.retry_try_xbegin = 0; /* Disable elision on rwlocks */
+#else
+ __elision_available = 0;
+ __pthread_force_elision = 0;
+ __elision_aconf.retry_try_xbegin = 0;
+#endif
}
#ifdef SHARED

32
glibc-dns-host-gcc5.patch Normal file
View File

@ -0,0 +1,32 @@
Index: glibc-2.22-193-g315267a/resolv/nss_dns/dns-host.c
===================================================================
--- glibc-2.22-193-g315267a.orig/resolv/nss_dns/dns-host.c
+++ glibc-2.22-193-g315267a/resolv/nss_dns/dns-host.c
@@ -79,6 +79,7 @@
#include <stddef.h>
#include <string.h>
#include <sys/syslog.h>
+#include <libc-internal.h>
#include "nsswitch.h"
@@ -561,10 +562,19 @@ addrsort (char **ap, int num)
num = MAX_NR_ADDRS;
for (i = 0; i < num; i++, p++)
{
+ DIAG_PUSH_NEEDS_COMMENT
+#if __GNUC_PREREQ (5, 0)
+ /* GCC 5.0 warns about array subscript being above array bounds,
+ but that's not entirely possible since i is limited to
+ _res.nsort which is limited to MAXRESOLVSORT. This
+ is likely PR/59124 which is still not fixed. */
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
+#endif
for (j = 0 ; (unsigned)j < _res.nsort; j++)
if (_res.sort_list[j].addr.s_addr ==
(((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
break;
+ DIAG_POP_NEEDS_COMMENT
aval[i] = j;
if (needsort == 0 && i > 0 && j < aval[i-1])
needsort = i;

View File

@ -1,40 +1,30 @@
Short description: Cleanup use of _dl_starting_up.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Upstream status: https://sourceware.org/ml/libc-alpha/2014-02/msg00589.html
Upstream discussions:
https://sourceware.org/ml/libc-alpha/2014-02/msg00580.html
Based on the following commit:
~~~
From 16552c01a66633c9e412984d9d92616bd4e5303c Mon Sep 17 00:00:00 2001
From: Andreas Schwab <schwab@redhat.com>
Date: Fri, 11 Jun 2010 11:04:11 +0200
Subject: [PATCH] Properly set __libc_multiple_libcs
* elf/rtld.c (_dl_starting_up): Always define.
(dl_main): Always set _dl_starting_up.
* elf/dl-support.c (_dl_starting_up): Always define.
* elf/dl-init.c (_dl_init): Always clear _dl_starting_up.
---
ChangeLog | 7 +++++++
elf/dl-init.c | 4 ----
elf/dl-support.c | 2 --
elf/rtld.c | 4 ----
4 files changed, 7 insertions(+), 10 deletions(-)
~~~
This patch needs to go upstream to get cleaned up, but has always involed
analysis of the GNU/Hurd parts of the change and that stalled out, but
perhaps with build-many-glibcs we can now test these changes more easily.
Index: b/elf/dl-init.c
===================================================================
--- a/elf/dl-init.c
+++ b/elf/dl-init.c
@@ -119,8 +119,6 @@ _dl_init (struct link_map *main_map, int
#
# Upstream discussions:
# https://sourceware.org/ml/libc-alpha/2014-02/msg00580.html
#
# Based on the following commit:
#
# From 16552c01a66633c9e412984d9d92616bd4e5303c Mon Sep 17 00:00:00 2001
# From: Andreas Schwab <schwab@redhat.com>
# Date: Fri, 11 Jun 2010 11:04:11 +0200
# Subject: [PATCH] Properly set __libc_multiple_libcs
#
# * elf/rtld.c (_dl_starting_up): Always define.
# (dl_main): Always set _dl_starting_up.
# * elf/dl-support.c (_dl_starting_up): Always define.
# * elf/dl-init.c (_dl_init): Always clear _dl_starting_up.
#
# ---
# ChangeLog | 7 +++++++
# elf/dl-init.c | 4 ----
# elf/dl-support.c | 2 --
# elf/rtld.c | 4 ----
# 4 files changed, 7 insertions(+), 10 deletions(-)
#
diff -urN glibc-2.20-205-ga39208b/elf/dl-init.c glibc-2.20-205-ga39208b.mod/elf/dl-init.c
--- glibc-2.20-205-ga39208b/elf/dl-init.c 2014-11-21 16:08:32.744913590 -0500
+++ glibc-2.20-205-ga39208b.mod/elf/dl-init.c 2014-11-21 16:09:42.485708197 -0500
@@ -119,8 +119,6 @@
while (i-- > 0)
call_init (main_map->l_initfini[i], argc, argv, env);
@ -43,11 +33,10 @@ Index: b/elf/dl-init.c
_dl_starting_up = 0;
-#endif
}
Index: b/elf/dl-support.c
===================================================================
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -117,10 +117,8 @@ struct r_scope_elem _dl_initial_searchli
diff -urN glibc-2.20-205-ga39208b/elf/dl-support.c glibc-2.20-205-ga39208b.mod/elf/dl-support.c
--- glibc-2.20-205-ga39208b/elf/dl-support.c 2014-11-19 14:35:03.000000000 -0500
+++ glibc-2.20-205-ga39208b.mod/elf/dl-support.c 2014-11-21 16:09:54.829671843 -0500
@@ -118,10 +118,8 @@
.r_nlist = 1,
};
@ -58,19 +47,18 @@ Index: b/elf/dl-support.c
/* Random data provided by the kernel. */
void *_dl_random;
Index: b/elf/rtld.c
===================================================================
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -214,7 +214,6 @@ audit_list_iter_next (struct audit_list_
return iter->previous->name;
}
diff -urN glibc-2.20-205-ga39208b/elf/rtld.c glibc-2.20-205-ga39208b.mod/elf/rtld.c
--- glibc-2.20-205-ga39208b/elf/rtld.c 2014-11-21 16:08:32.745913587 -0500
+++ glibc-2.20-205-ga39208b.mod/elf/rtld.c 2014-11-21 16:09:05.614816785 -0500
@@ -107,7 +107,6 @@
struct audit_list *next;
} *audit_list;
-#ifndef HAVE_INLINED_SYSCALLS
/* Set nonzero during loading and initialization of executable and
libraries, cleared before the executable's entry point runs. This
must not be initialized to nonzero, because the unused dynamic
@@ -224,7 +223,6 @@ audit_list_iter_next (struct audit_list_
@@ -117,7 +116,6 @@
never be called. */
int _dl_starting_up = 0;
rtld_hidden_def (_dl_starting_up)
@ -78,7 +66,7 @@ Index: b/elf/rtld.c
/* This is the structure which defines all variables global to ld.so
(except those which cannot be added for some reason). */
@@ -898,10 +896,8 @@ dl_main (const ElfW(Phdr) *phdr,
@@ -776,10 +774,8 @@
/* Process the environment variable which control the behaviour. */
process_envvars (&mode);

View File

@ -0,0 +1,101 @@
From 207e77fd3f0a94acdf0557608dd4f10ce0e0f22f Mon Sep 17 00:00:00 2001
From: Andreas Schwab <schwab@redhat.com>
Date: Mon, 9 May 2011 10:55:58 +0200
Subject: [PATCH] Never leave $ORIGIN unexpanded
* elf/dl-load.c (is_dst): Remove parameter secure, all callers
changed. Move check for valid use of $ORIGIN ...
(_dl_dst_substitute): ... here. Reset check_for_trusted when a
path element is skipped.
---
ChangeLog | 7 +++++++
elf/dl-load.c | 34 ++++++++++++++++------------------
2 files changed, 23 insertions(+), 18 deletions(-)
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 18a83d2..6e16a9a 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -249,8 +249,7 @@ is_trusted_path_normalize (const char *path, size_t len)
static size_t
-is_dst (const char *start, const char *name, const char *str,
- int is_path, int secure)
+is_dst (const char *start, const char *name, const char *str, int is_path)
{
size_t len;
bool is_curly = false;
@@ -279,12 +278,6 @@ is_dst (const char *start, const char *name, const char *str,
&& (!is_path || name[len] != ':'))
return 0;
- if (__glibc_unlikely (secure)
- && ((name[len] != '\0' && name[len] != '/'
- && (!is_path || name[len] != ':'))
- || (name != start + 1 && (!is_path || name[-2] != ':'))))
- return 0;
-
return len;
}
@@ -299,13 +292,10 @@ _dl_dst_count (const char *name, int is_path)
{
size_t len;
- /* $ORIGIN is not expanded for SUID/GUID programs (except if it
- is $ORIGIN alone) and it must always appear first in path. */
++name;
- if ((len = is_dst (start, name, "ORIGIN", is_path,
- __libc_enable_secure)) != 0
- || (len = is_dst (start, name, "PLATFORM", is_path, 0)) != 0
- || (len = is_dst (start, name, "LIB", is_path, 0)) != 0)
+ if ((len = is_dst (start, name, "ORIGIN", is_path)) != 0
+ || (len = is_dst (start, name, "PLATFORM", is_path)) != 0
+ || (len = is_dst (start, name, "LIB", is_path)) != 0)
++cnt;
name = strchr (name + len, '$');
@@ -338,10 +328,18 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
size_t len;
++name;
- if ((len = is_dst (start, name, "ORIGIN", is_path,
- __libc_enable_secure)) != 0)
+ if ((len = is_dst (start, name, "ORIGIN", is_path)) != 0)
{
- repl = l->l_origin;
+ /* For SUID/GUID programs $ORIGIN must always appear
+ first in a path element. */
+ if (__glibc_unlikely (__libc_enable_secure)
+ && ((name[len] != '\0' && name[len] != '/'
+ && (!is_path || name[len] != ':'))
+ || (name != start + 1 && (!is_path || name[-2] != ':'))))
+ repl = (const char *) -1;
+ else
+ repl = l->l_origin;
+
check_for_trusted = (__libc_enable_secure
&& l->l_type == lt_executable);
}
@@ -351,9 +348,9 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
check_for_trusted = (__libc_enable_secure
&& l->l_type == lt_executable);
}
- else if ((len = is_dst (start, name, "PLATFORM", is_path, 0)) != 0)
+ else if ((len = is_dst (start, name, "PLATFORM", is_path)) != 0)
repl = GLRO(dl_platform);
- else if ((len = is_dst (start, name, "LIB", is_path, 0)) != 0)
+ else if ((len = is_dst (start, name, "LIB", is_path)) != 0)
repl = DL_DST_LIB;
if (repl != NULL && repl != (const char *) -1)
@@ -373,6 +370,7 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
element, but keep an empty element at the end. */
if (wp == result && is_path && *name == ':' && name[1] != '\0')
++name;
+ check_for_trusted = false;
}
else
/* No DST we recognize. */

View File

@ -0,0 +1,18 @@
diff -Nrup a/sysdeps/i386/Makefile b/sysdeps/i386/Makefile
--- a/sysdeps/i386/Makefile 2012-06-05 07:42:49.000000000 -0600
+++ b/sysdeps/i386/Makefile 2012-06-07 12:15:21.826318641 -0600
@@ -62,6 +64,14 @@ endif
ifneq (,$(filter -mno-tls-direct-seg-refs,$(CFLAGS)))
defines += -DNO_TLS_DIRECT_SEG_REFS
+else
+# .a libraries are not performance critical and so we
+# build them without direct TLS segment references
+# always.
+CPPFLAGS-.o += -DNO_TLS_DIRECT_SEG_REFS
+CFLAGS-.o += -mno-tls-direct-seg-refs
+CPPFLAGS-.oS += -DNO_TLS_DIRECT_SEG_REFS
+CFLAGS-.oS += -mno-tls-direct-seg-refs
endif
ifeq ($(subdir),elf)

View File

@ -0,0 +1,30 @@
From 5eb4509a6651d19c7a28c4506d6aa582c9ee095a Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Wed, 1 Feb 2006 09:30:43 +0000
Subject: [PATCH] 128-bit long double fixes
* include/bits/stdlib-ldbl.h: New file.
* include/bits/wchar-ldbl.h: New file.
---
ChangeLog | 5 +++++
include/bits/stdlib-ldbl.h | 1 +
include/bits/wchar-ldbl.h | 1 +
3 files changed, 7 insertions(+), 0 deletions(-)
create mode 100644 include/bits/stdlib-ldbl.h
create mode 100644 include/bits/wchar-ldbl.h
diff --git a/include/bits/stdlib-ldbl.h b/include/bits/stdlib-ldbl.h
new file mode 100644
index 0000000..6250949
--- /dev/null
+++ b/include/bits/stdlib-ldbl.h
@@ -0,0 +1 @@
+#include <stdlib/bits/stdlib-ldbl.h>
diff --git a/include/bits/wchar-ldbl.h b/include/bits/wchar-ldbl.h
new file mode 100644
index 0000000..29baa2f
--- /dev/null
+++ b/include/bits/wchar-ldbl.h
@@ -0,0 +1 @@
+#include <wcsmbs/bits/wchar-ldbl.h>

42
glibc-fedora-ldd.patch Normal file
View File

@ -0,0 +1,42 @@
From 83e5edd390eabe8f8e8e0d051f929b77a30c0767 Mon Sep 17 00:00:00 2001
From: Andreas Schwab <schwab@redhat.com>
Date: Fri, 18 Mar 2011 16:22:52 +0100
Subject: [PATCH] ldd: never run file directly
* elf/ldd.bash.in: Never run file directly.
---
ChangeLog | 4 ++++
elf/ldd.bash.in | 14 +-------------
2 files changed, 5 insertions(+), 13 deletions(-)
--- a/elf/ldd.bash.in
+++ b/elf/ldd.bash.in
@@ -166,18 +166,6 @@ warning: you do not have execution permission for" "\`$file'" >&2
fi
done
case $ret in
- 0)
- # If the program exits with exit code 5, it means the process has been
- # invoked with __libc_enable_secure. Fall back to running it through
- # the dynamic linker.
- try_trace "$file"
- rc=$?
- if [ $rc = 5 ]; then
- try_trace "$RTLD" "$file"
- rc=$?
- fi
- [ $rc = 0 ] || result=1
- ;;
1)
# This can be a non-ELF binary or no binary at all.
nonelf "$file" || {
@@ -185,7 +173,7 @@ warning: you do not have execution permission for" "\`$file'" >&2
result=1
}
;;
- 2)
+ 0|2)
try_trace "$RTLD" "$file" || result=1
;;
*)

View File

@ -1,19 +1,7 @@
Short description: Fedora-specific workaround for kernel pty bug.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Upstream status: not-submitted
This is a Fedora-specific workaround for a kernel bug where calling
ioctl on a pty will silently ignore the invalid c_cflag. The
workaround is to use TCGETS to verify the setting matches. This is
not upstream and needs to either be removed or submitted upstream
after analysis.
Index: b/sysdeps/unix/sysv/linux/tcsetattr.c
===================================================================
--- a/sysdeps/unix/sysv/linux/tcsetattr.c
+++ b/sysdeps/unix/sysv/linux/tcsetattr.c
@@ -45,6 +45,7 @@ __tcsetattr (int fd, int optional_action
diff -Nrup a/sysdeps/unix/sysv/linux/tcsetattr.c b/sysdeps/unix/sysv/linux/tcsetattr.c
--- a/sysdeps/unix/sysv/linux/tcsetattr.c 2012-06-05 07:42:49.000000000 -0600
+++ b/sysdeps/unix/sysv/linux/tcsetattr.c 2012-06-07 12:15:21.831318623 -0600
@@ -48,6 +48,7 @@ tcsetattr (fd, optional_actions, termios
{
struct __kernel_termios k_termios;
unsigned long int cmd;
@ -21,7 +9,7 @@ Index: b/sysdeps/unix/sysv/linux/tcsetattr.c
switch (optional_actions)
{
@@ -75,7 +76,36 @@ __tcsetattr (int fd, int optional_action
@@ -79,6 +80,35 @@ tcsetattr (fd, optional_actions, termios
memcpy (&k_termios.c_cc[0], &termios_p->c_cc[0],
__KERNEL_NCCS * sizeof (cc_t));
@ -57,5 +45,4 @@ Index: b/sysdeps/unix/sysv/linux/tcsetattr.c
+
+ return retval;
}
weak_alias (__tcsetattr, tcsetattr)
libc_hidden_def (tcsetattr)

View File

@ -1,14 +1,3 @@
Short description: Add 4 ISO-8859-15 locales to SUPPORTED for Euro symbol.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Bug-RHEL: #61908
Upstream status: not-needed
Very early RHL 7.3 requirement to add these locales so users can
get access to Euro symbol. We should review this bug and decide if
the UTF-8 locales are now serving the same purpose and drop the
additional locales.
* Tue Mar 26 2002 Jakub Jelinek <jakub@redhat.com> 2.2.5-28
- add a couple of .ISO-8859-15 locales (#61908)

View File

@ -1,21 +1,11 @@
Short description: Fedora-specific glibc install locale changes.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Upstream status: not-needed
The Fedora glibc build and install does not need the normal install
behaviour which updates the locale archive. The Fedora install phase
in the spec file of the rpm will handle this manually.
diff --git a/localedata/Makefile b/localedata/Makefile
index 0eea396ad86da956..54caabda33728207 100644
--- a/localedata/Makefile
+++ b/localedata/Makefile
@@ -413,6 +413,7 @@ define build-one-locale
diff -Nrup a/localedata/Makefile b/localedata/Makefile
--- a/localedata/Makefile 2012-06-05 07:42:49.000000000 -0600
+++ b/localedata/Makefile 2012-06-07 12:15:21.776318827 -0600
@@ -211,6 +211,7 @@ $(INSTALL-SUPPORTED-LOCALES): install-lo
echo -n '...'; \
input=`echo $$locale | sed 's/\([^.]*\)[^@]*\(.*\)/\1\2/'`; \
$(LOCALEDEF) $$flags --alias-file=../intl/locale.alias \
$(LOCALEDEF) --alias-file=../intl/locale.alias \
+ --no-archive \
-i locales/$$input -f charmaps/$$charset \
-i locales/$$input -c -f charmaps/$$charset \
$(addprefix --prefix=,$(install_root)) $$locale \
&& echo ' done';
&& echo ' done'; \

View File

@ -0,0 +1,51 @@
This is a part of commit glibc-2.3.3-1492-ga891c7b,
needed for fedora/build-locale-archive.c only.
diff -Nrup a/ChangeLog.17 b/ChangeLog.17
--- a/ChangeLog.17 2012-06-05 07:42:49.000000000 -0600
+++ b/ChangeLog.17 2012-06-07 12:15:21.564319619 -0600
@@ -11818,6 +11829,10 @@ d2009-10-30 Ulrich Drepper <drepper@re
[BZ #4368]
* stdlib/stdlib.h: Remove obsolete part of comment for realpath.
+2007-04-16 Jakub Jelinek <jakub@redhat.com>
+
+ * locale/programs/locarchive.c (add_alias, insert_name): Remove static.
+
2007-04-16 Ulrich Drepper <drepper@redhat.com>
[BZ #4364]
diff -Nrup a/locale/programs/locarchive.c b/locale/programs/locarchive.c
--- a/locale/programs/locarchive.c 2012-06-05 07:42:49.000000000 -0600
+++ b/locale/programs/locarchive.c 2012-06-07 12:15:21.585319540 -0600
@@ -252,9 +252,9 @@ oldlocrecentcmp (const void *a, const vo
/* forward decls for below */
static uint32_t add_locale (struct locarhandle *ah, const char *name,
locale_data_t data, bool replace);
-static void add_alias (struct locarhandle *ah, const char *alias,
- bool replace, const char *oldname,
- uint32_t *locrec_offset_p);
+void add_alias (struct locarhandle *ah, const char *alias,
+ bool replace, const char *oldname,
+ uint32_t *locrec_offset_p);
static bool
@@ -635,7 +635,7 @@ close_archive (struct locarhandle *ah)
#include "../../intl/explodename.c"
#include "../../intl/l10nflist.c"
-static struct namehashent *
+struct namehashent *
insert_name (struct locarhandle *ah,
const char *name, size_t name_len, bool replace)
{
@@ -693,7 +693,7 @@ insert_name (struct locarhandle *ah,
return &namehashtab[idx];
}
-static void
+void
add_alias (struct locarhandle *ah, const char *alias, bool replace,
const char *oldname, uint32_t *locrec_offset_p)
{

View File

@ -1,14 +1,3 @@
Short description: Place glibc info into "Libraries" category.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Upstream status: not-needed
The category names for libraries is completely random including
"Libraries", "GNU Libraries", "GNU libraries", and "Software libraries."
In the GNU info manual the "Software libraries" category is given as an
example, but really we need to standardize on a category for upstream.
I suggest we drop this change after some upstream discussion.
From 4820b9175535e13df79ce816106016040014916e Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Fri, 3 Nov 2006 16:31:21 +0000

View File

@ -1,13 +1,3 @@
Short description: Fedora-specific enabling batch read in NSS.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Bug-RHEL: #188246
Upstream status: not-submitted
Enable batch read in NSS. It's not clear if this is always a win or
just a win for NIS+, this needs to be analyzed and sent upstream or
removed.
From baba5d9461d4e8a581ac26fe4412ad783ffc73e7 Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Mon, 1 May 2006 08:02:53 +0000

View File

@ -0,0 +1,25 @@
diff -Nrup a/nptl/Makefile b/nptl/Makefile
--- a/nptl/Makefile 2012-06-05 07:42:49.000000000 -0600
+++ b/nptl/Makefile 2012-06-07 12:15:21.816318678 -0600
@@ -529,15 +529,19 @@ $(addprefix $(objpfx), \
$(tests) $(xtests) $(test-srcs))): $(objpfx)libpthread.so \
$(objpfx)libpthread_nonshared.a
$(objpfx)tst-unload: $(libdl)
-# $(objpfx)../libc.so is used instead of $(common-objpfx)libc.so,
+# $(objpfx)linklibc.so is used instead of $(common-objpfx)libc.so,
# since otherwise libpthread.so comes before libc.so when linking.
$(addprefix $(objpfx), $(tests-reverse)): \
- $(objpfx)../libc.so $(objpfx)libpthread.so \
+ $(objpfx)linklibc.so $(objpfx)libpthread.so \
$(objpfx)libpthread_nonshared.a
$(objpfx)../libc.so: $(common-objpfx)libc.so ;
$(addprefix $(objpfx),$(tests-static) $(xtests-static)): $(objpfx)libpthread.a
$(objpfx)tst-atfork2.out: $(objpfx)tst-atfork2mod.so
+
+$(objpfx)linklibc.so: $(common-objpfx)libc.so
+ ln -s ../libc.so $@
+generated += libclink.so
else
$(addprefix $(objpfx),$(tests) $(test-srcs)): $(objpfx)libpthread.a
endif

View File

@ -1,11 +1,3 @@
Short description: NSCD must use nscd user.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Upstream status: not-needed
Fedora-specific configuration adjustment to introduce the nscd user.
(Upstream does not assume this user exists.)
diff -Nrup a/nscd/nscd.conf b/nscd/nscd.conf
--- a/nscd/nscd.conf 2012-06-05 07:42:49.000000000 -0600
+++ b/nscd/nscd.conf 2012-06-07 12:15:21.818318670 -0600

View File

@ -1,45 +0,0 @@
The Fedora /etc/nsswitch.conf is based largely on the upstream
version with minor downstream distribution modifications for
use with SSSD and systemd.
diff --git a/nss/nsswitch.conf b/nss/nsswitch.conf
index f55358811495c9f1..14c3cde8080a848c 100644
--- a/nss/nsswitch.conf
+++ b/nss/nsswitch.conf
@@ -1,7 +1,7 @@
#
# /etc/nsswitch.conf
#
-# An example Name Service Switch config file. This file should be
+# Name Service Switch config file. This file should be
# sorted with the most-used services at the beginning.
#
# Valid databases are: aliases, ethers, group, gshadow, hosts,
@@ -52,18 +52,20 @@
# shadow: db files
# group: db files
-# In alphabetical order. Re-order as required to optimize peformance.
+# In order of likelihood of use to accelerate lookup.
+passwd: sss files
+shadow: files sss
+group: sss files
+hosts: files dns myhostname
+services: files sss
+netgroup: sss
+automount: files sss
+
aliases: files
ethers: files
-group: files
gshadow: files
-hosts: files dns
initgroups: files
-netgroup: files
networks: files dns
-passwd: files
protocols: files
publickey: files
rpc: files
-shadow: files
-services: files

View File

@ -0,0 +1,20 @@
glibc-2.3.3-1478-g37582bc
* Thu Nov 30 2006 Jakub Jelinek <jakub@redhat.com> 2.5.90-9
- on ppc64 build __libc_start_main without unwind info,
as it breaks MD_FROB_UPDATE_CONTEXT (#217729, #217775; in the
future that could be fixable just by providing .cfi_undefined r2
in __libc_start_main instead)
diff -Nrup a/sysdeps/powerpc/powerpc64/Makefile b/sysdeps/powerpc/powerpc64/Makefile
--- a/sysdeps/powerpc/powerpc64/Makefile 2012-06-05 07:42:49.000000000 -0600
+++ b/sysdeps/powerpc/powerpc64/Makefile 2012-06-07 12:15:21.828318633 -0600
@@ -35,6 +35,8 @@ CFLAGS-rtld-memmove.os = $(no-special-re
CFLAGS-rtld-memchr.os = $(no-special-regs)
CFLAGS-rtld-strnlen.os = $(no-special-regs)
+CFLAGS-libc-start.c += -fno-asynchronous-unwind-tables
+
ifeq ($(subdir),elf)
# help gcc inline asm code from dl-machine.h
+cflags += -finline-limit=2000

View File

@ -0,0 +1,28 @@
This is part of commit glibc-2.3.3-1564-gd0b6ac6
* Fri Mar 14 2008 Jakub Jelinek <jakub@redhat.com> 2.7.90-11
- remove <stropts.h>, define _XOPEN_STREAMS -1 (#436349)
diff -Nrup a/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h
--- a/sysdeps/unix/sysv/linux/bits/posix_opt.h 2012-06-05 07:42:49.000000000 -0600
+++ b/sysdeps/unix/sysv/linux/bits/posix_opt.h 2012-06-07 12:15:21.817318674 -0600
@@ -188,4 +188,7 @@
/* Typed memory objects are not available. */
#define _POSIX_TYPED_MEMORY_OBJECTS -1
+/* Streams are not available. */
+#define _XOPEN_STREAMS -1
+
#endif /* bits/posix_opt.h */
diff -Nrup a/streams/Makefile b/streams/Makefile
--- a/streams/Makefile 2012-06-05 07:42:49.000000000 -0600
+++ b/streams/Makefile 2012-06-07 12:15:21.824318649 -0600
@@ -20,7 +20,7 @@
include ../Makeconfig
-headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h
+#headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h
routines = isastream getmsg getpmsg putmsg putpmsg fattach fdetach
include ../Rules

View File

@ -0,0 +1,50 @@
From cde99cd2b7b16a6113acb054e89d490047932a9f Mon Sep 17 00:00:00 2001
From: Andreas Schwab <schwab@redhat.com>
Date: Thu, 8 Apr 2010 11:18:26 +0200
Subject: [PATCH] Don't call uname or getrlimit in libpthread init function
* sysdeps/unix/sysv/linux/i386/Versions: Export __uname under
GLIBC_PRIVATE.
* nptl/Versions: Export __getrlimit under GLIBC_PRIVATE.
* sysdeps/unix/sysv/linux/i386/smp.h: Call __uname instead of uname.
* nptl/nptl-init.c: Call __getrlimit instead of getrlimit.
---
ChangeLog | 8 ++++++++
nptl/Versions | 1 +
nptl/nptl-init.c | 2 +-
sysdeps/unix/sysv/linux/i386/Versions | 6 ++++++
sysdeps/unix/sysv/linux/i386/smp.h | 2 +-
5 files changed, 17 insertions(+), 2 deletions(-)
create mode 100644 sysdeps/unix/sysv/linux/i386/Versions
--- a/nptl/Version
+++ b/nptl/Versions
@@ -30,6 +30,7 @@ libc {
__libc_pthread_init;
__libc_current_sigrtmin_private; __libc_current_sigrtmax_private;
__libc_allocate_rtsig_private;
+ __getrlimit;
}
}
--- a/sysdeps/unix/sysv/linux/i386/Versions
+++ b/sysdeps/unix/sysv/linux/i386/Versions
@@ -53,5 +53,6 @@
}
GLIBC_PRIVATE {
__modify_ldt;
+ __uname;
}
}
--- a/sysdeps/unix/sysv/linux/i386/smp.h
+++ b/sysdeps/unix/sysv/linux/i386/smp.h
@@ -36,7 +36,7 @@ is_smp_system (void)
char *cp;
/* Try reading the number using `sysctl' first. */
- if (uname (&u.uts) == 0)
+ if (__uname (&u.uts) == 0)
cp = u.uts.version;
else
{

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,32 @@
Index: glibc-2.22-193-g315267a/resolv/gethnamaddr.c
===================================================================
--- glibc-2.22-193-g315267a.orig/resolv/gethnamaddr.c
+++ glibc-2.22-193-g315267a/resolv/gethnamaddr.c
@@ -71,6 +71,7 @@ static char sccsid[] = "@(#)gethostnamad
#include <ctype.h>
#include <errno.h>
#include <syslog.h>
+#include <libc-internal.h>
#define RESOLVSORT
@@ -986,10 +987,19 @@ addrsort(ap, num)
p = ap;
for (i = 0; i < num; i++, p++) {
+ DIAG_PUSH_NEEDS_COMMENT
+#if __GNUC_PREREQ (5, 0)
+ /* GCC 5.0 warns about array subscript being above array bounds,
+ but that's not entirely possible since i is limited to
+ _res.nsort which is limited to MAXRESOLVSORT. This
+ is likely PR/59124 which is still not fixed. */
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
+#endif
for (j = 0 ; (unsigned)j < _res.nsort; j++)
if (_res.sort_list[j].addr.s_addr ==
(((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
break;
+ DIAG_POP_NEEDS_COMMENT
aval[i] = j;
if (needsort == 0 && i > 0 && j < aval[i-1])
needsort = i;

72
glibc-ld-ctype-gcc5.patch Normal file
View File

@ -0,0 +1,72 @@
Index: glibc-2.22-193-g315267a/locale/programs/ld-ctype.c
===================================================================
--- glibc-2.22-193-g315267a.orig/locale/programs/ld-ctype.c
+++ glibc-2.22-193-g315267a/locale/programs/ld-ctype.c
@@ -31,6 +31,7 @@
#include <wctype.h>
#include <stdint.h>
#include <sys/uio.h>
+#include <libc-internal.h>
#include "localedef.h"
#include "charmap.h"
@@ -2534,9 +2535,19 @@ with character code range values one mus
{
size_t cnt;
+ DIAG_PUSH_NEEDS_COMMENT
+#if __GNUC_PREREQ (5, 0)
+ /* GCC 5.0 warns about array subscript being above array bounds,
+ but that's not possible since ctype_map_new prevents
+ map_collection_nr from being greater than MAX_NR_CHARMP which
+ is the size of mapnames. This is likely PR/59124 which is still
+ not fixed. */
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
+#endif
for (cnt = 2; cnt < ctype->map_collection_nr; ++cnt)
if (strcmp (now->val.str.startmb, ctype->mapnames[cnt]) == 0)
break;
+ DIAG_POP_NEEDS_COMMENT
if (cnt < ctype->map_collection_nr)
free (now->val.str.startmb);
@@ -2807,9 +2818,19 @@ previous definition was here")));
/* This could mean one of several things. First test whether
it's a character class name. */
+ DIAG_PUSH_NEEDS_COMMENT
+#if __GNUC_PREREQ (5, 0)
+ /* GCC 5.0 warns about array subscript being above array bounds,
+ but that's not possible since ctype_class_new prevents
+ nr_charclass from being greater than MAX_NR_CHARCLASS which
+ is the size of classnames. This is likely PR/59124 which is still
+ not fixed. */
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
+#endif
for (cnt = 0; cnt < ctype->nr_charclass; ++cnt)
if (strcmp (now->val.str.startmb, ctype->classnames[cnt]) == 0)
break;
+ DIAG_POP_NEEDS_COMMENT
if (cnt < ctype->nr_charclass)
{
class_bit = _ISwbit (cnt);
@@ -2817,9 +2838,19 @@ previous definition was here")));
free (now->val.str.startmb);
goto read_charclass;
}
+ DIAG_PUSH_NEEDS_COMMENT
+#if __GNUC_PREREQ (5, 0)
+ /* GCC 5.0 warns about array subscript being above array bounds,
+ but that's not possible since ctype_map_new prevents
+ map_collection_nr from being greater than MAX_NR_CHARMP which
+ is the size of mapnames. This is likely PR/59124 which is still
+ not fixed. */
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
+#endif
for (cnt = 0; cnt < ctype->map_collection_nr; ++cnt)
if (strcmp (now->val.str.startmb, ctype->mapnames[cnt]) == 0)
break;
+ DIAG_POP_NEEDS_COMMENT
if (cnt < ctype->map_collection_nr)
{
mapidx = cnt;

View File

@ -1,10 +1,3 @@
Short description: Provide options to nscd startup.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Upstream status: not-needed
Fedora-specific nscd startup configuration file.
diff --git a/nscd/nscd.service b/nscd/nscd.service
index b7428a3..19ba185 100644
--- a/nscd/nscd.service

View File

@ -0,0 +1,858 @@
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: nsswitch: Add group merging support
From: Stephen Gallagher <sgallagh@redhat.com>
X-Patchwork-Id: 10289
Message-Id: <1452213991-6499-1-git-send-email-sgallagh@redhat.com>
To: libc-alpha@sourceware.org
Date: Thu, 7 Jan 2016 19:46:31 -0500
https://sourceware.org/glibc/wiki/Proposals/GroupMerging
== Justification ==
It is common today for users to rely on centrally-managed user stores for
handling their user accounts. However, much software existing today does
not have an innate understanding of such accounts. Instead, they commonly
rely on membership in known groups for managing access-control (for
example the "wheel" group on Fedora and RHEL systems or the "adm" group
on Debian-derived systems). In the present incarnation of nsswitch, the
only way to have such groups managed by a remote user store such as
FreeIPA or Active Directory would be to manually remove the groups from
/etc/group on the clients so that nsswitch would then move past nss_files
and into the SSSD, nss-ldap or other remote user database.
== Solution ==
With this patch, a new action is introduced for nsswitch:
NSS_ACTION_MERGE. To take advantage of it, one will add [SUCCESS=merge]
between two database entries in the nsswitch.conf file. When a group is
located in the first of the two group entries, processing will continue
on to the next one. If the group is also found in the next entry (and the
group name and GID are an exact match), the member list of the second
entry will be added to the group object to be returned.
== Implementation ==
After each DL_LOOKUP_FN() returns, the next action is checked. If the
function returned NSS_STATUS_SUCCESS and the next action is
NSS_ACTION_MERGE, a copy of the result buffer is saved for the next pass
through the loop. If on this next pass through the loop the database
returns another instance of a group matching both the group name and GID,
the member list is added to the previous list and it is returned as a
single object. If the following database does not contain the same group,
then the original is copied back into the destination buffer.
This patch implements merge functionality only for the group database.
For other databases, there is a default implementation that will return
the EINVAL errno if a merge is requested. The merge functionality can be
implemented for other databases at a later time if such is needed. Each
database must provide a unique implementation of the deep-copy and merge
functions.
If [SUCCESS=merge] is present in nsswitch.conf for a glibc version that
does not support it, glibc will process results up until that operation,
at which time it will return results if it has found them or else will
simply return an error. In practical terms, this ends up behaving like
the remainder of the nsswitch.conf line does not exist.
== Iterators ==
This feature does not modify the iterator functionality from its current
behavior. If getgrnam() or getgrgid() is called, glibc will iterate
through all entries in the `group` line in nsswitch.conf and display the
list of members without attempting to merge them. This is consistent with
the behavior of nss_files where if two separate lines are specified for
the same group in /etc/groups, getgrnam()/getgrgid() will display both.
Clients are already expected to handle this gracefully.
== No Premature Optimizations ==
The following is a list of places that might be eligible for
optimization, but were not overengineered for this initial contribution:
* Any situation where a merge may occur will result in one malloc() of
the same size as the input buffer.
* Any situation where a merge does occur will result in a second
malloc() to hold the list of pointers to member name strings.
* The list of members is simply concatenated together and is not tested
for uniqueness (which is identical to the behavior for nss_files,
which will simply return identical values if they both exist on the
line in the file. This could potentially be optimized to reduce space
usage in the buffer, but it is both complex and computationally
expensive to do so.
== Testing ==
I performed testing by running the getent utility against my newly-built
glibc and configuring /etc/nsswitch.conf with the following entry:
group: group: files [SUCCESS=merge] sss
In /etc/group I included the line:
wheel:x:10:sgallagh
I then configured my local SSSD using the id_provider=local to respond
with:
wheel:*:10:localuser,localuser2
I then ran `getent group wheel` against the newly-built glibc in
multiple situations and received the expected output as described
above:
* When SSSD was running.
* When SSSD was configured in nsswitch.conf but the daemon was not
running.
* When SSSD was configured in nsswitch.conf but nss_sss.so.2 was not
installed on the system.
* When the order of 'sss' and 'files' was reversed.
* All of the above with the [SUCCESS=merge] removed (to ensure no
regressions).
* All of the above with `getent group 10`.
* All of the above with `getent group` with and without
`enumerate=true` set in SSSD.
* All of the above with and without nscd enabled on the system.
== NEWS ==
* A new NSS action is added to facilitate large distribution system
administration. The action, MERGE, allows remote user stores like
LDAP to be merged into local user stores like /etc/groups in order
to provide easy to use, updated, and managed sets of merged
credentials. The new action can be used by configuring it in
/etc/nsswitch.conf:
group: files [SUCCESS=merge] nis
Implemented by Stephen Gallagher (Red Hat).
== ChangeLog ==
2015-12-16 Stephen Gallagher <sgallagh@redhat.com>
[BZ #19072]
* grp/Makefile (headers): Add grp-merge.h
(routines): Add grp-merge.
* grp/getgrgid_r.c: Include grp-merge.h.
(DEEPCOPY_FN): Define.
(MERGE_FN): Define.
* grp/getgrname_r.c: Include grp-merge.h.
(DEEPCOPY_FN): Define.
(MERGE_FN): Define.
* grp/grp-merge.c: New file.
* grp/grp-merge.h: New file.
* manual/nss.texi (Actions in the NSS configuration): Describe
return, continue, and merge.
* nscd/Makefile: Add vpath to find grp-merge.c
(nscd-modules): Add grp-merge.
* nscd/getgrgid_r.c: Include grp/grp-merge.h.
(DEEPCOPY_FN): Define.
(MERGE_FN): Define.
* nscd/getgrnam_r.c: Include grp/grp-merge.h.
(DEEPCOPY_FN): Define.
(MERGE_FN): Define.
* nss/getXXbyYY_r.c [!DEEPCOPY_FN]: Define __copy_einval.
[!MERGE_FN]: Define __merge_einval.
(CHECK_MERGE): Define.
(REENTRANT_NAME): Process merge if do_merge is true.
* nss/getnssent_r.c (__nss_setent): Process NSS_ACTION_MERGE.
(__nss_getent_r): Likewise.
* nss/nsswitch.c (nss_parse_service_list): Likewise.
* nss/nsswitch.h (lookup_actions): Define NSS_ACTION_MERGE.
Resolves BZ #19072
---
grp/Makefile | 5 +-
grp/getgrgid_r.c | 3 +
grp/getgrnam_r.c | 4 ++
grp/grp-merge.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
grp/grp-merge.h | 35 +++++++++++
manual/nss.texi | 46 +++++++++++++-
nscd/Makefile | 5 +-
nscd/getgrgid_r.c | 4 ++
nscd/getgrnam_r.c | 4 ++
nss/getXXbyYY_r.c | 105 +++++++++++++++++++++++++++++++-
nss/getnssent_r.c | 34 ++++++++++-
nss/nsswitch.c | 3 +
nss/nsswitch.h | 3 +-
13 files changed, 419 insertions(+), 10 deletions(-)
create mode 100644 grp/grp-merge.c
create mode 100644 grp/grp-merge.h
diff --git a/grp/Makefile b/grp/Makefile
index ed8cc2b0564f0e3842cd78f24a4e0788d659bbc4..52af992365268aae8cf8a80cd7216160b1431e84 100644
--- a/grp/Makefile
+++ b/grp/Makefile
@@ -20,15 +20,16 @@
#
subdir := grp
include ../Makeconfig
-headers := grp.h
+headers := grp.h grp-merge.h
routines := fgetgrent initgroups setgroups \
getgrent getgrgid getgrnam putgrent \
- getgrent_r getgrgid_r getgrnam_r fgetgrent_r
+ getgrent_r getgrgid_r getgrnam_r fgetgrent_r \
+ grp-merge
tests := testgrp tst-putgrent
ifeq (yes,$(build-shared))
test-srcs := tst_fgetgrent
diff --git a/grp/getgrgid_r.c b/grp/getgrgid_r.c
index 05d4d772d3ef0bfae8f9375387c41310885ce41a..447fa633807deec8f26d654ebeb6386a150d3a37 100644
--- a/grp/getgrgid_r.c
+++ b/grp/getgrgid_r.c
@@ -16,14 +16,17 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <grp.h>
+#include "grp-merge.h"
#define LOOKUP_TYPE struct group
#define FUNCTION_NAME getgrgid
#define DATABASE_NAME group
#define ADD_PARAMS gid_t gid
#define ADD_VARIABLES gid
#define BUFLEN NSS_BUFLEN_GROUP
+#define DEEPCOPY_FN __copy_grp
+#define MERGE_FN __merge_grp
#include <nss/getXXbyYY_r.c>
diff --git a/grp/getgrnam_r.c b/grp/getgrnam_r.c
index 0061cb2f7e0bd311d19775e49eb3fdd8a93447f1..c5535f4057ddfc40965f27789c34345045c8bf3b 100644
--- a/grp/getgrnam_r.c
+++ b/grp/getgrnam_r.c
@@ -16,13 +16,17 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <grp.h>
+#include "grp-merge.h"
#define LOOKUP_TYPE struct group
#define FUNCTION_NAME getgrnam
#define DATABASE_NAME group
#define ADD_PARAMS const char *name
#define ADD_VARIABLES name
+#define DEEPCOPY_FN __copy_grp
+#define MERGE_FN __merge_grp
+
#include <nss/getXXbyYY_r.c>
diff --git a/grp/grp-merge.c b/grp/grp-merge.c
new file mode 100644
index 0000000000000000000000000000000000000000..ca959dbfe403c89d6f3184f2b361b0c6488c9182
--- /dev/null
+++ b/grp/grp-merge.c
@@ -0,0 +1,178 @@
+/* Group merging implementation.
+ Copyright (C) 2016 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <grp.h>
+#include "grp-merge.h"
+
+#define BUFCHECK(size) \
+ do { \
+ if (c + size > buflen) \
+ { \
+ free (members); \
+ return ERANGE; \
+ } \
+ } while(0)
+
+int
+__copy_grp (const struct group srcgrp, const size_t buflen,
+ struct group *destgrp, char *destbuf, char **endptr)
+{
+ size_t i;
+ size_t c = 0;
+ size_t len;
+ size_t memcount;
+ char **members = NULL;
+
+ /* Copy the GID. */
+ destgrp->gr_gid = srcgrp.gr_gid;
+
+ /* Copy the name. */
+ len = strlen (srcgrp.gr_name) + 1;
+ BUFCHECK (len);
+ memcpy (&destbuf[c], srcgrp.gr_name, len);
+ destgrp->gr_name = &destbuf[c];
+ c += len;
+
+ /* Copy the password. */
+ len = strlen (srcgrp.gr_passwd) + 1;
+ BUFCHECK (len);
+ memcpy (&destbuf[c], srcgrp.gr_passwd, len);
+ destgrp->gr_passwd = &destbuf[c];
+ c += len;
+
+ /* Count all of the members. */
+ for (memcount = 0; srcgrp.gr_mem[memcount]; memcount++)
+ ;
+
+ /* Allocate a temporary holding area for the pointers to the member
+ contents, including space for a NULL-terminator. */
+ members = malloc (sizeof (char *) * (memcount + 1));
+ if (members == NULL)
+ return ENOMEM;
+
+ /* Copy all of the group members to destbuf and add a pointer to each of
+ them into the 'members' array. */
+ for (i = 0; srcgrp.gr_mem[i]; i++)
+ {
+ len = strlen (srcgrp.gr_mem[i]) + 1;
+ BUFCHECK (len);
+ memcpy (&destbuf[c], srcgrp.gr_mem[i], len);
+ members[i] = &destbuf[c];
+ c += len;
+ }
+ members[i] = NULL;
+
+ /* Copy the pointers from the members array into the buffer and assign them
+ to the gr_mem member of destgrp. */
+ destgrp->gr_mem = (char **) &destbuf[c];
+ len = sizeof (char *) * (memcount + 1);
+ BUFCHECK (len);
+ memcpy (&destbuf[c], members, len);
+ c += len;
+ free (members);
+ members = NULL;
+
+ /* Save the count of members at the end. */
+ BUFCHECK (sizeof (size_t));
+ memcpy (&destbuf[c], &memcount, sizeof (size_t));
+ c += sizeof (size_t);
+
+ if (endptr)
+ *endptr = destbuf + c;
+ return 0;
+}
+
+/* Check that the name, GID and passwd fields match, then
+ copy in the gr_mem array. */
+int
+__merge_grp (struct group *savedgrp, char *savedbuf, char *savedend,
+ size_t buflen, struct group *mergegrp, char *mergebuf)
+{
+ size_t c, i, len;
+ size_t savedmemcount;
+ size_t memcount;
+ size_t membersize;
+ char **members = NULL;
+
+ /* We only support merging members of groups with identical names and
+ GID values. If we hit this case, we need to overwrite the current
+ buffer with the saved one (which is functionally equivalent to
+ treating the new lookup as NSS_STATUS NOTFOUND. */
+ if (mergegrp->gr_gid != savedgrp->gr_gid
+ || strcmp (mergegrp->gr_name, savedgrp->gr_name))
+ return __copy_grp (*savedgrp, buflen, mergegrp, mergebuf, NULL);
+
+ /* Get the count of group members from the last sizeof (size_t) bytes in the
+ mergegrp buffer. */
+ savedmemcount = (size_t) *(savedend - sizeof (size_t));
+
+ /* Get the count of new members to add. */
+ for (memcount = 0; mergegrp->gr_mem[memcount]; memcount++)
+ ;
+
+ /* Create a temporary array to hold the pointers to the member values from
+ both the saved and merge groups. */
+ membersize = savedmemcount + memcount + 1;
+ members = malloc (sizeof (char *) * membersize);
+ if (members == NULL)
+ return ENOMEM;
+
+ /* Copy in the existing member pointers from the saved group
+ Note: this is not NULL-terminated yet. */
+ memcpy (members, savedgrp->gr_mem, sizeof (char *) * savedmemcount);
+
+ /* Back up into the savedbuf until we get back to the NULL-terminator of the
+ group member list. (This means walking back savedmemcount + 1 (char *) pointers
+ and the member count value.
+ The value of c is going to be the used length of the buffer backed up by
+ the member count and further backed up by the size of the pointers. */
+ c = savedend - savedbuf
+ - sizeof (size_t)
+ - sizeof (char *) * (savedmemcount + 1);
+
+ /* Add all the new group members, overwriting the old NULL-terminator while
+ adding the new pointers to the temporary array. */
+ for (i = 0; mergegrp->gr_mem[i]; i++)
+ {
+ len = strlen (mergegrp->gr_mem[i]) + 1;
+ BUFCHECK (len);
+ memcpy (&savedbuf[c], mergegrp->gr_mem[i], len);
+ members[savedmemcount + i] = &savedbuf[c];
+ c += len;
+ }
+ /* Add the NULL-terminator. */
+ members[savedmemcount + memcount] = NULL;
+
+ /* Copy the member array back into the buffer after the member list and free
+ the member array. */
+ savedgrp->gr_mem = (char **) &savedbuf[c];
+ len = sizeof (char *) * membersize;
+ BUFCHECK (len);
+ memcpy (&savedbuf[c], members, len);
+ c += len;
+
+ free (members);
+ members = NULL;
+
+ /* Finally, copy the results back into mergebuf, since that's the buffer
+ that we were provided by the caller. */
+ return __copy_grp (*savedgrp, buflen, mergegrp, mergebuf, NULL);
+}
diff --git a/grp/grp-merge.h b/grp/grp-merge.h
new file mode 100644
index 0000000000000000000000000000000000000000..59013487d0d907c76521ab504e265077937bfb5e
--- /dev/null
+++ b/grp/grp-merge.h
@@ -0,0 +1,35 @@
+/* Group merging implementation.
+ Copyright (C) 2016 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
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _GRP_MERGE_H
+#define _GRP_MERGE_H 1
+
+#include <grp.h>
+
+/* Duplicate a grp struct (and its members). When no longer needed, the
+ calling function must free(newbuf). */
+int
+__copy_grp (const struct group srcgrp, const size_t buflen,
+ struct group *destgrp, char *destbuf, char **endptr);
+
+/* Merge the member lists of two grp structs together. */
+int
+__merge_grp (struct group *savedgrp, char *savedbuf, char *savedend,
+ size_t buflen, struct group *mergegrp, char *mergebuf);
+
+#endif /* _GRP_MERGE_H */
diff --git a/manual/nss.texi b/manual/nss.texi
index 66dcceffe01f225f078e88dd006bb90e80c85723..95e3544bcd97995720e7154ec43df4090154bf4c 100644
--- a/manual/nss.texi
+++ b/manual/nss.texi
@@ -178,11 +178,11 @@ where
@var{action} @result{} return | continue
@end smallexample
The case of the keywords is insignificant. The @var{status}
values are the results of a call to a lookup function of a specific
-service. They mean
+service. They mean:
@ftable @samp
@item success
No error occurred and the wanted entry is returned. The default action
for this is @code{return}.
@@ -202,10 +202,54 @@ The service is temporarily unavailable. This could mean a file is
locked or a server currently cannot accept more connections. The
default action is @code{continue}.
@end ftable
@noindent
+The @var{action} values mean:
+
+@ftable @samp
+@item return
+
+If the status matches, stop the lookup process at this service
+specification. If an entry is available, provide it to the application.
+If an error occurred, report it to the application. In case of a prior
+@samp{merge} action, the data is combined with previous lookup results,
+as explained below.
+
+@item continue
+
+If the status matches, proceed with the lookup process at the next
+entry, discarding the result of the current lookup (and any merged
+data). An exception is the @samp{initgroups} database and the
+@samp{success} status, where @samp{continue} acts like @code{merge}
+below.
+
+@item merge
+
+Proceed with the lookup process, retaining the current lookup result.
+This action is useful only with the @samp{success} status. If a
+subsequent service lookup succeeds and has a matching @samp{return}
+specification, the results are merged, the lookup process ends, and the
+merged results are returned to the application. If the following service
+has a matching @samp{merge} action, the lookup process continues,
+retaining the combined data from this and any previous lookups.
+
+After a @code{merge} action, errors from subsequent lookups are ignored,
+and the data gathered so far will be returned.
+
+The @samp{merge} only applies to the @samp{success} status. It is
+currently implemented for the @samp{group} database and its group
+members field, @samp{gr_mem}. If specified for other databases, it
+causes the lookup to fail (if the @var{status} matches).
+
+When processing @samp{merge} for @samp{group} membership, the group GID
+and name must be identical for both entries. If only one or the other is
+a match, the behavior is undefined.
+
+@end ftable
+
+@noindent
If we have a line like
@smallexample
ethers: nisplus [NOTFOUND=return] db files
@end smallexample
diff --git a/nscd/Makefile b/nscd/Makefile
index e1a1aa92fc699aa132f7192da49f698a078e5910..3e6895573ae33221c728617f4c95bb3e8c5d5c47 100644
--- a/nscd/Makefile
+++ b/nscd/Makefile
@@ -29,16 +29,19 @@ aux := nscd_helper
endif
# To find xmalloc.c
vpath %.c ../locale/programs
+# To find grp-merge.c
+vpath %.c ../grp
+
nscd-modules := nscd connections pwdcache getpwnam_r getpwuid_r grpcache \
getgrnam_r getgrgid_r hstcache gethstbyad_r gethstbynm3_r \
getsrvbynm_r getsrvbypt_r servicescache \
dbg_log nscd_conf nscd_stat cache mem nscd_setup_thread \
xmalloc xstrdup aicache initgrcache gai res_hconf \
- netgroupcache
+ netgroupcache grp-merge
ifeq ($(build-nscd)$(have-thread-library),yesyes)
others += nscd
others-pie += nscd
diff --git a/nscd/getgrgid_r.c b/nscd/getgrgid_r.c
index fe5bda424169d56f642f125ef1f2df77a84de221..25de4a3b0b74841c44844a0541cf4d2365b22515 100644
--- a/nscd/getgrgid_r.c
+++ b/nscd/getgrgid_r.c
@@ -15,17 +15,21 @@
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>. */
#include <grp.h>
+#include "grp/grp-merge.h"
#define LOOKUP_TYPE struct group
#define FUNCTION_NAME getgrgid
#define DATABASE_NAME group
#define ADD_PARAMS gid_t gid
#define ADD_VARIABLES gid
#define BUFLEN NSS_BUFLEN_GROUP
+#define DEEPCOPY_FN __copy_grp
+#define MERGE_FN __merge_grp
+
/* We are nscd, so we don't want to be talking to ourselves. */
#undef USE_NSCD
#include <nss/getXXbyYY_r.c>
diff --git a/nscd/getgrnam_r.c b/nscd/getgrnam_r.c
index 5ec56877f5798ca34c2e0074d5093cc22b6d58dc..386d66c5832ffee68e95195f6e34b723f41d0984 100644
--- a/nscd/getgrnam_r.c
+++ b/nscd/getgrnam_r.c
@@ -15,16 +15,20 @@
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>. */
#include <grp.h>
+#include "grp/grp-merge.h"
#define LOOKUP_TYPE struct group
#define FUNCTION_NAME getgrnam
#define DATABASE_NAME group
#define ADD_PARAMS const char *name
#define ADD_VARIABLES name
+#define DEEPCOPY_FN __copy_grp
+#define MERGE_FN __merge_grp
+
/* We are nscd, so we don't want to be talking to ourselves. */
#undef USE_NSCD
#include <nss/getXXbyYY_r.c>
diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c
index 198f8cfebd51be9c738f03f950f093b0855ab3cb..5f49ae8b828fce6dc30c7ccc9606319bffc52d5b 100644
--- a/nss/getXXbyYY_r.c
+++ b/nss/getXXbyYY_r.c
@@ -129,10 +129,52 @@
# define AF_VAL af
#else
# define AF_VAL AF_INET
#endif
+
+/* Set defaults for merge functions that haven't been defined. */
+#ifndef DEEPCOPY_FN
+static inline int
+__copy_einval (LOOKUP_TYPE a,
+ const size_t b,
+ LOOKUP_TYPE *c,
+ char *d,
+ char **e)
+{
+ return EINVAL;
+}
+# define DEEPCOPY_FN __copy_einval
+#endif
+
+#ifndef MERGE_FN
+static inline int
+__merge_einval (LOOKUP_TYPE *a,
+ char *b,
+ char *c,
+ size_t d,
+ LOOKUP_TYPE *e,
+ char *f)
+{
+ return EINVAL;
+}
+# define MERGE_FN __merge_einval
+#endif
+
+#define CHECK_MERGE(err, status) \
+do { \
+ if (err) \
+ { \
+ __set_errno (err); \
+ if (err == ERANGE) \
+ status = NSS_STATUS_TRYAGAIN; \
+ else \
+ status = NSS_STATUS_UNAVAIL; \
+ break; \
+ } \
+} while(0)
+
/* Type of the lookup function we need here. */
typedef enum nss_status (*lookup_function) (ADD_PARAMS, LOOKUP_TYPE *, char *,
size_t, int * H_ERRNO_PARM
EXTRA_PARAMS);
@@ -150,17 +192,20 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
{
static bool startp_initialized;
static service_user *startp;
static lookup_function start_fct;
service_user *nip;
+ int do_merge = 0;
+ LOOKUP_TYPE mergegrp;
+ char *mergebuf = NULL;
+ char *endptr = NULL;
union
{
lookup_function l;
void *ptr;
} fct;
-
- int no_more;
+ int no_more, err;
enum nss_status status = NSS_STATUS_UNAVAIL;
#ifdef USE_NSCD
int nscd_status;
#endif
#ifdef NEED_H_ERRNO
@@ -276,13 +321,69 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
&& *h_errnop == NETDB_INTERNAL
#endif
&& errno == ERANGE)
break;
+ if (do_merge)
+ {
+
+ if (status == NSS_STATUS_SUCCESS)
+ {
+ /* The previous loop saved a buffer for merging.
+ Perform the merge now. */
+ err = MERGE_FN (&mergegrp, mergebuf, endptr, buflen, resbuf,
+ buffer);
+ CHECK_MERGE (err,status);
+ do_merge = 0;
+ }
+ else
+ {
+ /* If the result wasn't SUCCESS, copy the saved buffer back
+ into the result buffer and set the status back to
+ NSS_STATUS_SUCCESS to match the previous pass through the loop.
+ * If the next action is CONTINUE, it will overwrite the value
+ currently in the buffer and return the new value.
+ * If the next action is RETURN, we'll return the previously-
+ acquired values.
+ * If the next action is MERGE, then it will be added to the buffer
+ saved from the previous source. */
+ err = DEEPCOPY_FN (mergegrp, buflen, resbuf, buffer, NULL);
+ CHECK_MERGE (err, status);
+ status = NSS_STATUS_SUCCESS;
+ }
+ }
+
+ /* If we were are configured to merge this value with the next one,
+ save the current value of the group struct. */
+ if (nss_next_action (nip, status) == NSS_ACTION_MERGE
+ && status == NSS_STATUS_SUCCESS)
+ {
+ /* Copy the current values into a buffer to be merged with the next
+ set of retrieved values. */
+ if (!mergebuf)
+ {
+ /* Only allocate once and reuse it for as many merges as we need
+ to perform. */
+ mergebuf = malloc (buflen);
+ if (!mergebuf)
+ {
+ __set_errno (ENOMEM);
+ status = NSS_STATUS_UNAVAIL;
+ break;
+ }
+ }
+
+ err = DEEPCOPY_FN (*resbuf, buflen, &mergegrp, mergebuf, &endptr);
+ CHECK_MERGE (err, status);
+ do_merge = 1;
+ }
+
no_more = __nss_next2 (&nip, REENTRANT_NAME_STRING,
REENTRANT2_NAME_STRING, &fct.ptr, status, 0);
}
+ free(mergebuf);
+ mergebuf = NULL;
#ifdef HANDLE_DIGITS_DOTS
done:
#endif
*result = status == NSS_STATUS_SUCCESS ? resbuf : NULL;
diff --git a/nss/getnssent_r.c b/nss/getnssent_r.c
index f5b903671ca53ccad108eeb4e49ea40a45fa5cdf..c0743436f661d4d83045a6353b49291a4c0f220b 100644
--- a/nss/getnssent_r.c
+++ b/nss/getnssent_r.c
@@ -77,11 +77,25 @@ __nss_setent (const char *func_name, db_lookup_function lookup_fct,
if (stayopen_tmp)
status = DL_CALL_FCT (fct.f, (*stayopen_tmp));
else
status = DL_CALL_FCT (fct.f, (0));
- no_more = __nss_next2 (nip, func_name, NULL, &fct.ptr, status, 0);
+ if (nss_next_action (*nip, status) == NSS_ACTION_MERGE)
+ {
+ /* This is a special-case. When [SUCCESS=merge] is in play,
+ _nss_next2() will skip to the next database. Due to the
+ implementation of that function, we can't know whether we're
+ in an enumeration or an individual lookup, which behaves
+ differently with regards to merging. We'll treat SUCCESS as
+ an indication to start the enumeration at this database. */
+ no_more = 1;
+ }
+ else
+ {
+ no_more = __nss_next2 (nip, func_name, NULL, &fct.ptr, status, 0);
+ }
+
if (is_last_nip)
*last_nip = *nip;
}
if (stayopen_tmp)
@@ -173,12 +187,26 @@ __nss_getent_r (const char *getent_func_name,
&& errno == ERANGE)
break;
do
{
- no_more = __nss_next2 (nip, getent_func_name, NULL, &fct.ptr,
- status, 0);
+ if (status == NSS_STATUS_SUCCESS
+ && nss_next_action (*nip, status) == NSS_ACTION_MERGE)
+ {
+ /* This is a special-case. When [SUCCESS=merge] is in play,
+ _nss_next2() will skip to the next database. Due to the
+ implementation of that function, we can't know whether we're
+ in an enumeration or an individual lookup, which behaves
+ differently with regards to merging. We'll treat SUCCESS as
+ an indication to return the results here. */
+ no_more = 1;
+ }
+ else
+ {
+ no_more = __nss_next2 (nip, getent_func_name, NULL, &fct.ptr,
+ status, 0);
+ }
if (is_last_nip)
*last_nip = *nip;
if (! no_more)
diff --git a/nss/nsswitch.c b/nss/nsswitch.c
index faf9d1a0d5680aa79e88b2dfeea18da371c336fb..f8f60ba05aad9a571f928a3ea7d3b14f908ccb2d 100644
--- a/nss/nsswitch.c
+++ b/nss/nsswitch.c
@@ -710,10 +710,13 @@ nss_parse_service_list (const char *line)
if (line - name == 6 && __strncasecmp (name, "RETURN", 6) == 0)
action = NSS_ACTION_RETURN;
else if (line - name == 8
&& __strncasecmp (name, "CONTINUE", 8) == 0)
action = NSS_ACTION_CONTINUE;
+ else if (line - name == 5
+ && __strncasecmp (name, "MERGE", 5) == 0)
+ action = NSS_ACTION_MERGE;
else
goto finish;
if (not)
{
diff --git a/nss/nsswitch.h b/nss/nsswitch.h
index a5318fa82be43c8314807ad76de231e572e91c06..5bc2de3b1d82978102ac7a129c0ba5b7eb3cfd25 100644
--- a/nss/nsswitch.h
+++ b/nss/nsswitch.h
@@ -30,11 +30,12 @@
/* Actions performed after lookup finished. */
typedef enum
{
NSS_ACTION_CONTINUE,
- NSS_ACTION_RETURN
+ NSS_ACTION_RETURN,
+ NSS_ACTION_MERGE
} lookup_actions;
typedef struct service_library
{

987
glibc-pthread-barrier.patch Normal file
View File

@ -0,0 +1,987 @@
Short description: New pthread_barrier algorithm to fulfill barrier destruction requirements.
Author(s): Torvald Riegel <triegel@redhat.com>
Origin: PATCH
Bug-RHEL: NA
Bug-Fedora: NA
Bug-Upstream: #13065
Upstream status: http://patchwork.sourceware.org/patch/10062/
# commit d6533b39f004789e0de4b7d58a29f8282ee95f7b
# Author: Torvald Riegel <triegel@redhat.com>
# Date: Wed Jun 24 14:37:32 2015 +0200
#
# New pthread_barrier algorithm to fulfill barrier destruction requirements.
#
# The previous barrier implementation did not fulfill the POSIX requirements
# for when a barrier can be destroyed. Specifically, it was possible that
# threads that haven't noticed yet that their round is complete still access
# the barrier's memory, and that those accesses can happen after the barrier
# has been legally destroyed.
# The new algorithm does not have this issue, and it avoids using a lock
# internally.
#
Index: glibc-2.22-621-g90c400b/nptl/Makefile
===================================================================
--- glibc-2.22-621-g90c400b.orig/nptl/Makefile
+++ glibc-2.22-621-g90c400b/nptl/Makefile
@@ -243,7 +243,7 @@ tests = tst-typesizes \
tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \
tst-sem8 tst-sem9 tst-sem10 tst-sem11 tst-sem12 tst-sem13 tst-sem14 \
tst-sem15 \
- tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \
+ tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 tst-barrier5 \
tst-align tst-align3 \
tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \
tst-basic7 \
@@ -304,7 +304,7 @@ tests-nolibpthread = tst-unload
gen-as-const-headers = pthread-errnos.sym \
lowlevelcond.sym lowlevelrwlock.sym \
- lowlevelbarrier.sym unwindbuf.sym \
+ unwindbuf.sym \
lowlevelrobustlock.sym pthread-pi-defines.sym
Index: glibc-2.22-621-g90c400b/nptl/lowlevelbarrier.sym
===================================================================
--- glibc-2.22-621-g90c400b.orig/nptl/lowlevelbarrier.sym
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <stddef.h>
-#include <sched.h>
-#include <bits/pthreadtypes.h>
-#include "internaltypes.h"
-
---
-
-CURR_EVENT offsetof (struct pthread_barrier, curr_event)
-MUTEX offsetof (struct pthread_barrier, lock)
-LEFT offsetof (struct pthread_barrier, left)
-INIT_COUNT offsetof (struct pthread_barrier, init_count)
-PRIVATE offsetof (struct pthread_barrier, private)
Index: glibc-2.22-621-g90c400b/nptl/pthread_barrier_destroy.c
===================================================================
--- glibc-2.22-621-g90c400b.orig/nptl/pthread_barrier_destroy.c
+++ glibc-2.22-621-g90c400b/nptl/pthread_barrier_destroy.c
@@ -18,25 +18,44 @@
#include <errno.h>
#include "pthreadP.h"
-#include <lowlevellock.h>
+#include <atomic.h>
+#include <futex-internal.h>
int
pthread_barrier_destroy (pthread_barrier_t *barrier)
{
- struct pthread_barrier *ibarrier;
- int result = EBUSY;
+ struct pthread_barrier *bar = (struct pthread_barrier *) barrier;
- ibarrier = (struct pthread_barrier *) barrier;
+ /* Destroying a barrier is only allowed if no thread is blocked on it.
+ Thus, there is no unfinished round, and all modifications to IN will
+ have happened before us (either because the calling thread took part
+ in the most recent round and thus synchronized-with all other threads
+ entering, or the program ensured this through other synchronization).
+ We must wait until all threads that entered so far have confirmed that
+ they have exited as well. To get the notification, pretend that we have
+ reached the reset threshold. */
+ unsigned int count = bar->count;
+ unsigned int max_in_before_reset = BARRIER_IN_THRESHOLD
+ - BARRIER_IN_THRESHOLD % count;
+ /* Relaxed MO sufficient because the program must have ensured that all
+ modifications happen-before this load (see above). */
+ unsigned int in = atomic_load_relaxed (&bar->in);
+ /* Trigger reset. The required acquire MO is below. */
+ if (atomic_fetch_add_relaxed (&bar->out, max_in_before_reset - in) < in)
+ {
+ /* Not all threads confirmed yet that they have exited, so another
+ thread will perform a reset. Wait until that has happened. */
+ while (in != 0)
+ {
+ futex_wait_simple (&bar->in, in, bar->shared);
+ in = atomic_load_relaxed (&bar->in);
+ }
+ }
+ /* We must ensure that memory reuse happens after all prior use of the
+ barrier (specifically, synchronize-with the reset of the barrier or the
+ confirmation of threads leaving the barrier). */
+ atomic_thread_fence_acquire ();
- lll_lock (ibarrier->lock, ibarrier->private ^ FUTEX_PRIVATE_FLAG);
-
- if (__glibc_likely (ibarrier->left == ibarrier->init_count))
- /* The barrier is not used anymore. */
- result = 0;
- else
- /* Still used, return with an error. */
- lll_unlock (ibarrier->lock, ibarrier->private ^ FUTEX_PRIVATE_FLAG);
-
- return result;
+ return 0;
}
Index: glibc-2.22-621-g90c400b/nptl/pthread_barrier_init.c
===================================================================
--- glibc-2.22-621-g90c400b.orig/nptl/pthread_barrier_init.c
+++ glibc-2.22-621-g90c400b/nptl/pthread_barrier_init.c
@@ -18,7 +18,7 @@
#include <errno.h>
#include "pthreadP.h"
-#include <lowlevellock.h>
+#include <futex-internal.h>
#include <kernel-features.h>
@@ -34,8 +34,10 @@ __pthread_barrier_init (pthread_barrier_
{
struct pthread_barrier *ibarrier;
- /* XXX EINVAL is not specified by POSIX as a possible error code. */
- if (__glibc_unlikely (count == 0))
+ /* XXX EINVAL is not specified by POSIX as a possible error code. See
+ pthread_barrier_wait for the reason for the comparison with
+ BARRIER_IN_THRESHOLD. */
+ if (__glibc_unlikely (count == 0 || count >= BARRIER_IN_THRESHOLD))
return EINVAL;
const struct pthread_barrierattr *iattr
@@ -46,15 +48,12 @@ __pthread_barrier_init (pthread_barrier_
ibarrier = (struct pthread_barrier *) barrier;
/* Initialize the individual fields. */
- ibarrier->lock = LLL_LOCK_INITIALIZER;
- ibarrier->left = count;
- ibarrier->init_count = count;
- ibarrier->curr_event = 0;
-
- /* XXX Don't use FUTEX_SHARED or FUTEX_PRIVATE as long as there are still
- assembly implementations that expect the value determined below. */
- ibarrier->private = (iattr->pshared != PTHREAD_PROCESS_PRIVATE
- ? 0 : FUTEX_PRIVATE_FLAG);
+ ibarrier->in = 0;
+ ibarrier->out = 0;
+ ibarrier->count = count;
+ ibarrier->current_round = 0;
+ ibarrier->shared = (iattr->pshared == PTHREAD_PROCESS_PRIVATE
+ ? FUTEX_PRIVATE : FUTEX_SHARED);
return 0;
}
Index: glibc-2.22-621-g90c400b/nptl/pthread_barrier_wait.c
===================================================================
--- glibc-2.22-621-g90c400b.orig/nptl/pthread_barrier_wait.c
+++ glibc-2.22-621-g90c400b/nptl/pthread_barrier_wait.c
@@ -18,63 +18,206 @@
#include <errno.h>
#include <sysdep.h>
-#include <lowlevellock.h>
#include <futex-internal.h>
#include <pthreadP.h>
-/* Wait on barrier. */
+/* Wait on the barrier.
+
+ In each round, we wait for a fixed number of threads to enter the barrier
+ (COUNT). Once that has happened, exactly these threads are allowed to
+ leave the barrier. Note that POSIX does not require that only COUNT
+ threads can attempt to block using the barrier concurrently.
+
+ We count the number of threads that have entered (IN). Each thread
+ increments IN when entering, thus getting a position in the sequence of
+ threads that are or have been waiting (starting with 1, so the position
+ is the number of threads that have entered so far including the current
+ thread).
+ CURRENT_ROUND designates the most recent thread whose round has been
+ detected as complete. When a thread detects that enough threads have
+ entered to make a round complete, it finishes this round by effectively
+ adding COUNT to CURRENT_ROUND atomically. Threads that believe that their
+ round is not complete yet wait until CURRENT_ROUND is not smaller than
+ their position anymore.
+
+ A barrier can be destroyed as soon as no threads are blocked on the
+ barrier. This is already the case if just one thread from the last round
+ has stopped waiting and returned to the caller; the assumption is that
+ all threads from the round are unblocked atomically, even though they may
+ return at different times from the respective calls to
+ pthread_barrier_wait). Thus, a valid call to pthread_barrier_destroy can
+ be concurrent with other threads still figuring out that their round has
+ been completed. Therefore, threads need to confirm that they have left
+ the barrier by incrementing OUT, and pthread_barrier_destroy needs to wait
+ until OUT equals IN.
+
+ To avoid an ABA issue for futex_wait on CURRENT_ROUND and for archs with
+ 32b-only atomics, we additionally reset the barrier when IN reaches
+ a threshold to avoid overflow. We assume that the total number of threads
+ is less than INT_MAX/2, and set the threshold accordingly so that we can
+ use a simple atomic_fetch_add on IN instead of a CAS when entering. The
+ threshold is always set to the end of a round, so all threads that have
+ entered are either pre-reset threads or post-reset threads (i.e., have a
+ position larger than the threshold).
+ Pre-reset threads just run the algorithm explained above. Post-reset
+ threads wait until IN is reset to a pre-threshold value.
+ When the last pre-reset thread leaves the barrier (i.e., OUT equals the
+ threshold), it resets the barrier to its initial state. Other (post-reset)
+ threads wait for the reset to have finished by waiting until IN is less
+ than the threshold and then restart by trying to enter the barrier again.
+
+ We reuse the reset mechanism in pthread_barrier_destroy to get notified
+ when all threads have left the barrier: We trigger an artificial reset and
+ wait for the last pre-reset thread to finish reset, thus notifying the
+ thread that is about to destroy the barrier.
+
+ Blocking using futexes is straightforward: pre-reset threads wait for
+ completion of their round using CURRENT_ROUND as futex word, and post-reset
+ threads and pthread_barrier_destroy use IN as futex word.
+
+ Further notes:
+ * It is not simple to let some of the post-reset threads help with the
+ reset because of the ABA issues that arise; therefore, we simply make
+ the last thread to leave responsible for the reset.
+ * POSIX leaves it unspecified whether a signal handler running in a thread
+ that has been unblocked (because its round is complete) can stall all
+ other threads and prevent them from returning from the barrier. In this
+ implementation, other threads will return. However,
+ pthread_barrier_destroy will of course wait for the signal handler thread
+ to confirm that it left the barrier.
+
+ TODO We should add spinning with back-off. Once we do that, we could also
+ try to avoid the futex_wake syscall when a round is detected as finished.
+ If we do not spin, it is quite likely that at least some other threads will
+ have called futex_wait already. */
int
__pthread_barrier_wait (pthread_barrier_t *barrier)
{
- struct pthread_barrier *ibarrier = (struct pthread_barrier *) barrier;
- int result = 0;
- int lll_private = ibarrier->private ^ FUTEX_PRIVATE_FLAG;
- int futex_private = (lll_private == LLL_PRIVATE
- ? FUTEX_PRIVATE : FUTEX_SHARED);
+ struct pthread_barrier *bar = (struct pthread_barrier *) barrier;
- /* Make sure we are alone. */
- lll_lock (ibarrier->lock, lll_private);
+ /* How many threads entered so far, including ourself. */
+ unsigned int i;
- /* One more arrival. */
- --ibarrier->left;
+ reset_restart:
+ /* Try to enter the barrier. We need acquire MO to (1) ensure that if we
+ observe that our round can be completed (see below for our attempt to do
+ so), all pre-barrier-entry effects of all threads in our round happen
+ before us completing the round, and (2) to make our use of the barrier
+ happen after a potential reset. We need release MO to make sure that our
+ pre-barrier-entry effects happen before threads in this round leaving the
+ barrier. */
+ i = atomic_fetch_add_acq_rel (&bar->in, 1) + 1;
+ /* These loads are after the fetch_add so that we're less likely to first
+ pull in the cache line as shared. */
+ unsigned int count = bar->count;
+ /* This is the number of threads that can enter before we need to reset.
+ Always at the end of a round. */
+ unsigned int max_in_before_reset = BARRIER_IN_THRESHOLD
+ - BARRIER_IN_THRESHOLD % count;
- /* Are these all? */
- if (ibarrier->left == 0)
+ if (i > max_in_before_reset)
{
- /* Yes. Increment the event counter to avoid invalid wake-ups and
- tell the current waiters that it is their turn. */
- ++ibarrier->curr_event;
-
- /* Wake up everybody. */
- futex_wake (&ibarrier->curr_event, INT_MAX, futex_private);
+ /* We're in a reset round. Just wait for a reset to finish; do not
+ help finishing previous rounds because this could happen
+ concurrently with a reset. */
+ while (i > max_in_before_reset)
+ {
+ futex_wait_simple (&bar->in, i, bar->shared);
+ /* Relaxed MO is fine here because we just need an indication for
+ when we should retry to enter (which will use acquire MO, see
+ above). */
+ i = atomic_load_relaxed (&bar->in);
+ }
+ goto reset_restart;
+ }
- /* This is the thread which finished the serialization. */
- result = PTHREAD_BARRIER_SERIAL_THREAD;
+ /* Look at the current round. At this point, we are just interested in
+ whether we can complete rounds, based on the information we obtained
+ through our acquire-MO load of IN. Nonetheless, if we notice that
+ our round has been completed using this load, we use the acquire-MO
+ fence below to make sure that all pre-barrier-entry effects of all
+ threads in our round happen before us leaving the barrier. Therefore,
+ relaxed MO is sufficient. */
+ unsigned cr = atomic_load_relaxed (&bar->current_round);
+
+ /* Try to finish previous rounds and/or the current round. We simply
+ consider just our position here and do not try to do the work of threads
+ that entered more recently. */
+ while (cr + count <= i)
+ {
+ /* Calculate the new current round based on how many threads entered.
+ NEWCR must be larger than CR because CR+COUNT ends a round. */
+ unsigned int newcr = i - i % count;
+ /* Try to complete previous and/or the current round. We need release
+ MO to propagate the happens-before that we observed through reading
+ with acquire MO from IN to other threads. If the CAS fails, it
+ is like the relaxed-MO load of CURRENT_ROUND above. */
+ if (atomic_compare_exchange_weak_release (&bar->current_round, &cr,
+ newcr))
+ {
+ /* Update CR with the modification we just did. */
+ cr = newcr;
+ /* Wake threads belonging to the rounds we just finished. We may
+ wake more threads than necessary if more than COUNT threads try
+ to block concurrently on the barrier, but this is not a typical
+ use of barriers.
+ Note that we can still access SHARED because we haven't yet
+ confirmed to have left the barrier. */
+ futex_wake (&bar->current_round, INT_MAX, bar->shared);
+ /* We did as much as we could based on our position. If we advanced
+ the current round to a round sufficient for us, do not wait for
+ that to happen and skip the acquire fence (we already
+ synchronize-with all other threads in our round through the
+ initial acquire MO fetch_add of IN. */
+ if (i <= cr)
+ goto ready_to_leave;
+ else
+ break;
+ }
}
- else
+
+ /* Wait until the current round is more recent than the round we are in. */
+ while (i > cr)
{
- /* The number of the event we are waiting for. The barrier's event
- number must be bumped before we continue. */
- unsigned int event = ibarrier->curr_event;
-
- /* Before suspending, make the barrier available to others. */
- lll_unlock (ibarrier->lock, lll_private);
-
- /* Wait for the event counter of the barrier to change. */
- do
- futex_wait_simple (&ibarrier->curr_event, event, futex_private);
- while (event == ibarrier->curr_event);
+ /* Wait for the current round to finish. */
+ futex_wait_simple (&bar->current_round, cr, bar->shared);
+ /* See the fence below. */
+ cr = atomic_load_relaxed (&bar->current_round);
}
- /* Make sure the init_count is stored locally or in a register. */
- unsigned int init_count = ibarrier->init_count;
+ /* Our round finished. Use the acquire MO fence to synchronize-with the
+ thread that finished the round, either through the initial load of
+ CURRENT_ROUND above or a failed CAS in the loop above. */
+ atomic_thread_fence_acquire ();
+
+ /* Now signal that we left. */
+ unsigned int o;
+ ready_to_leave:
+ /* We need release MO here so that our use of the barrier happens before
+ reset or memory reuse after pthread_barrier_destroy. */
+ o = atomic_fetch_add_release (&bar->out, 1) + 1;
+ if (o == max_in_before_reset)
+ {
+ /* Perform a reset if we are the last pre-reset thread leaving. All
+ other threads accessing the barrier are post-reset threads and are
+ incrementing or spinning on IN. Thus, resetting IN as the last step
+ of reset ensures that the reset is not concurrent with actual use of
+ the barrier. We need the acquire MO fence so that the reset happens
+ after use of the barrier by all earlier pre-reset threads. */
+ atomic_thread_fence_acquire ();
+ atomic_store_relaxed (&bar->current_round, 0);
+ atomic_store_relaxed (&bar->out, 0);
+ /* When destroying the barrier, we wait for a reset to happen. Thus,
+ we must load SHARED now so that this happens before the barrier is
+ destroyed. */
+ int shared = bar->shared;
+ atomic_store_release (&bar->in, 0);
+ futex_wake (&bar->in, INT_MAX, shared);
- /* If this was the last woken thread, unlock. */
- if (atomic_increment_val (&ibarrier->left) == init_count)
- /* We are done. */
- lll_unlock (ibarrier->lock, lll_private);
+ }
- return result;
+ /* Return a special value for exactly one thread per round. */
+ return i % count == 0 ? PTHREAD_BARRIER_SERIAL_THREAD : 0;
}
weak_alias (__pthread_barrier_wait, pthread_barrier_wait)
Index: glibc-2.22-621-g90c400b/nptl/pthread_barrierattr_setpshared.c
===================================================================
--- glibc-2.22-621-g90c400b.orig/nptl/pthread_barrierattr_setpshared.c
+++ glibc-2.22-621-g90c400b/nptl/pthread_barrierattr_setpshared.c
@@ -24,15 +24,11 @@
int
pthread_barrierattr_setpshared (pthread_barrierattr_t *attr, int pshared)
{
- struct pthread_barrierattr *iattr;
-
int err = futex_supports_pshared (pshared);
if (err != 0)
return err;
- iattr = (struct pthread_barrierattr *) attr;
-
- iattr->pshared = pshared;
+ ((struct pthread_barrierattr *) attr)->pshared = pshared;
return 0;
}
Index: glibc-2.22-621-g90c400b/nptl/tst-barrier4.c
===================================================================
--- glibc-2.22-621-g90c400b.orig/nptl/tst-barrier4.c
+++ glibc-2.22-621-g90c400b/nptl/tst-barrier4.c
@@ -16,7 +16,7 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-/* This is a test for behavior not guaranteed by POSIX. */
+/* This tests destruction of a barrier right after waiting on it. */
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
Index: glibc-2.22-621-g90c400b/nptl/tst-barrier5.c
===================================================================
--- /dev/null
+++ glibc-2.22-621-g90c400b/nptl/tst-barrier5.c
@@ -0,0 +1,145 @@
+/* Copyright (C) 2004-2015 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
+ <http://www.gnu.org/licenses/>. */
+
+/* This tests the barrier reset mechanism. */
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <internaltypes.h>
+
+
+static pthread_barrier_t b1;
+static pthread_barrier_t b2;
+
+
+#define N 20
+#define ROUNDS_PER_RUN 20
+#define START ((BARRIER_IN_THRESHOLD / N - ROUNDS_PER_RUN / 2) * N)
+
+static void *
+tf (void *arg)
+{
+ int runs = 0;
+
+ while (runs++ < 30)
+ {
+ /* In each run, we execute a number of rounds and initialize the barrier
+ so that we will go over the reset threshold with those rounds. */
+ for (int rounds = 0; rounds < ROUNDS_PER_RUN; rounds++)
+ pthread_barrier_wait (&b1);
+
+ if (pthread_barrier_wait (&b1) == PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ pthread_barrier_destroy (&b1);
+ if (pthread_barrier_init (&b1, NULL, N) != 0)
+ {
+ puts ("tf: 1st barrier_init failed");
+ exit (1);
+ }
+ puts ("b1 reinitialized");
+ /* Trigger a reset. */
+ struct pthread_barrier *bar = (struct pthread_barrier *) &b1;
+ bar->in = START;
+ bar->out = START;
+ /* We deliberately don't set bar->current_round so that we also
+ test whether the helping for the updates of current_round
+ works correctly. */
+ }
+
+ /* Same as above, just for b2. */
+ for (int rounds = 0; rounds < ROUNDS_PER_RUN; rounds++)
+ pthread_barrier_wait (&b2);
+
+ if (pthread_barrier_wait (&b2) == PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ pthread_barrier_destroy (&b2);
+ if (pthread_barrier_init (&b2, NULL, N) != 0)
+ {
+ puts ("tf: 2nd barrier_init failed");
+ exit (1);
+ }
+ puts ("b2 reinitialized");
+ /* Trigger a reset. See above. */
+ struct pthread_barrier *bar = (struct pthread_barrier *) &b2;
+ bar->in = START;
+ bar->out = START;
+ }
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_attr_t at;
+ int cnt;
+
+ if (pthread_attr_init (&at) != 0)
+ {
+ puts ("attr_init failed");
+ return 1;
+ }
+
+ if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ if (pthread_barrier_init (&b1, NULL, N) != 0)
+ {
+ puts ("1st barrier_init failed");
+ return 1;
+ }
+
+ if (pthread_barrier_init (&b2, NULL, N) != 0)
+ {
+ puts ("2nd barrier_init failed");
+ return 1;
+ }
+
+ pthread_t th[N - 1];
+ for (cnt = 0; cnt < N - 1; ++cnt)
+ if (pthread_create (&th[cnt], &at, tf, NULL) != 0)
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+
+ if (pthread_attr_destroy (&at) != 0)
+ {
+ puts ("attr_destroy failed");
+ return 1;
+ }
+
+ tf (NULL);
+
+ for (cnt = 0; cnt < N - 1; ++cnt)
+ if (pthread_join (th[cnt], NULL) != 0)
+ {
+ puts ("pthread_join failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
Index: glibc-2.22-621-g90c400b/sysdeps/nptl/internaltypes.h
===================================================================
--- glibc-2.22-621-g90c400b.orig/sysdeps/nptl/internaltypes.h
+++ glibc-2.22-621-g90c400b/sysdeps/nptl/internaltypes.h
@@ -95,12 +95,13 @@ struct pthread_rwlockattr
/* Barrier data structure. */
struct pthread_barrier
{
- unsigned int curr_event;
- int lock;
- unsigned int left;
- unsigned int init_count;
- int private;
+ unsigned int in;
+ unsigned int current_round;
+ unsigned int count;
+ int shared;
+ unsigned int out;
};
+#define BARRIER_IN_THRESHOLD (UINT_MAX/2)
/* Barrier variable attribute data structure. */
Index: glibc-2.22-621-g90c400b/sysdeps/unix/sysv/linux/i386/pthread_barrier_wait.S
===================================================================
--- glibc-2.22-621-g90c400b.orig/sysdeps/unix/sysv/linux/i386/pthread_barrier_wait.S
+++ /dev/null
@@ -1,187 +0,0 @@
-/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
- 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
- <http://www.gnu.org/licenses/>. */
-
-#include <sysdep.h>
-#include <lowlevellock.h>
-#include <lowlevelbarrier.h>
-
- .text
-
- .globl __pthread_barrier_wait
- .type __pthread_barrier_wait,@function
- .align 16
-__pthread_barrier_wait:
- cfi_startproc
- pushl %ebx
- cfi_adjust_cfa_offset(4)
- cfi_offset(%ebx, -8)
-
- movl 8(%esp), %ebx
-
- /* Get the mutex. */
- movl $1, %edx
- xorl %eax, %eax
- LOCK
- cmpxchgl %edx, MUTEX(%ebx)
- jnz 1f
-
- /* One less waiter. If this was the last one needed wake
- everybody. */
-2: subl $1, LEFT(%ebx)
- je 3f
-
- /* There are more threads to come. */
- pushl %esi
- cfi_adjust_cfa_offset(4)
- cfi_offset(%esi, -12)
-
-#if CURR_EVENT == 0
- movl (%ebx), %edx
-#else
- movl CURR_EVENT(%ebx), %edx
-#endif
-
- /* Release the mutex. */
- LOCK
- subl $1, MUTEX(%ebx)
- jne 6f
-
- /* Wait for the remaining threads. The call will return immediately
- if the CURR_EVENT memory has meanwhile been changed. */
-7:
-#if FUTEX_WAIT == 0
- movl PRIVATE(%ebx), %ecx
-#else
- movl $FUTEX_WAIT, %ecx
- orl PRIVATE(%ebx), %ecx
-#endif
- xorl %esi, %esi
-8: movl $SYS_futex, %eax
- ENTER_KERNEL
-
- /* Don't return on spurious wakeups. The syscall does not change
- any register except %eax so there is no need to reload any of
- them. */
-#if CURR_EVENT == 0
- cmpl %edx, (%ebx)
-#else
- cmpl %edx, CURR_EVENT(%ebx)
-#endif
- je 8b
-
- /* Increment LEFT. If this brings the count back to the
- initial count unlock the object. */
- movl $1, %edx
- movl INIT_COUNT(%ebx), %ecx
- LOCK
- xaddl %edx, LEFT(%ebx)
- subl $1, %ecx
- cmpl %ecx, %edx
- jne 10f
-
- /* Release the mutex. We cannot release the lock before
- waking the waiting threads since otherwise a new thread might
- arrive and gets waken up, too. */
- LOCK
- subl $1, MUTEX(%ebx)
- jne 9f
-
- /* Note: %esi is still zero. */
-10: movl %esi, %eax /* != PTHREAD_BARRIER_SERIAL_THREAD */
-
- popl %esi
- cfi_adjust_cfa_offset(-4)
- cfi_restore(%esi)
- popl %ebx
- cfi_adjust_cfa_offset(-4)
- cfi_restore(%ebx)
- ret
-
- cfi_adjust_cfa_offset(4)
- cfi_offset(%ebx, -8)
-
- /* The necessary number of threads arrived. */
-3:
-#if CURR_EVENT == 0
- addl $1, (%ebx)
-#else
- addl $1, CURR_EVENT(%ebx)
-#endif
-
- /* Wake up all waiters. The count is a signed number in the kernel
- so 0x7fffffff is the highest value. */
- movl $0x7fffffff, %edx
- movl $FUTEX_WAKE, %ecx
- orl PRIVATE(%ebx), %ecx
- movl $SYS_futex, %eax
- ENTER_KERNEL
-
- /* Increment LEFT. If this brings the count back to the
- initial count unlock the object. */
- movl $1, %edx
- movl INIT_COUNT(%ebx), %ecx
- LOCK
- xaddl %edx, LEFT(%ebx)
- subl $1, %ecx
- cmpl %ecx, %edx
- jne 5f
-
- /* Release the mutex. We cannot release the lock before
- waking the waiting threads since otherwise a new thread might
- arrive and gets waken up, too. */
- LOCK
- subl $1, MUTEX(%ebx)
- jne 4f
-
-5: orl $-1, %eax /* == PTHREAD_BARRIER_SERIAL_THREAD */
-
- popl %ebx
- cfi_adjust_cfa_offset(-4)
- cfi_restore(%ebx)
- ret
-
- cfi_adjust_cfa_offset(4)
- cfi_offset(%ebx, -8)
-1: movl PRIVATE(%ebx), %ecx
- leal MUTEX(%ebx), %edx
- xorl $LLL_SHARED, %ecx
- call __lll_lock_wait
- jmp 2b
-
-4: movl PRIVATE(%ebx), %ecx
- leal MUTEX(%ebx), %eax
- xorl $LLL_SHARED, %ecx
- call __lll_unlock_wake
- jmp 5b
-
- cfi_adjust_cfa_offset(4)
- cfi_offset(%esi, -12)
-6: movl PRIVATE(%ebx), %ecx
- leal MUTEX(%ebx), %eax
- xorl $LLL_SHARED, %ecx
- call __lll_unlock_wake
- jmp 7b
-
-9: movl PRIVATE(%ebx), %ecx
- leal MUTEX(%ebx), %eax
- xorl $LLL_SHARED, %ecx
- call __lll_unlock_wake
- jmp 10b
- cfi_endproc
- .size __pthread_barrier_wait,.-__pthread_barrier_wait
-weak_alias (__pthread_barrier_wait, pthread_barrier_wait)
Index: glibc-2.22-621-g90c400b/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S
===================================================================
--- glibc-2.22-621-g90c400b.orig/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S
+++ /dev/null
@@ -1,161 +0,0 @@
-/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
- 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
- <http://www.gnu.org/licenses/>. */
-
-#include <sysdep.h>
-#include <lowlevellock.h>
-#include <lowlevelbarrier.h>
-
-
- .text
-
- .globl __pthread_barrier_wait
- .type __pthread_barrier_wait,@function
- .align 16
-__pthread_barrier_wait:
- /* Get the mutex. */
- xorl %eax, %eax
- movl $1, %esi
- LOCK
- cmpxchgl %esi, MUTEX(%rdi)
- jnz 1f
-
- /* One less waiter. If this was the last one needed wake
- everybody. */
-2: decl LEFT(%rdi)
- je 3f
-
- /* There are more threads to come. */
-#if CURR_EVENT == 0
- movl (%rdi), %edx
-#else
- movl CURR_EVENT(%rdi), %edx
-#endif
-
- /* Release the mutex. */
- LOCK
- decl MUTEX(%rdi)
- jne 6f
-
- /* Wait for the remaining threads. The call will return immediately
- if the CURR_EVENT memory has meanwhile been changed. */
-7:
-#if FUTEX_WAIT == 0
- movl PRIVATE(%rdi), %esi
-#else
- movl $FUTEX_WAIT, %esi
- orl PRIVATE(%rdi), %esi
-#endif
- xorq %r10, %r10
-8: movl $SYS_futex, %eax
- syscall
-
- /* Don't return on spurious wakeups. The syscall does not change
- any register except %eax so there is no need to reload any of
- them. */
-#if CURR_EVENT == 0
- cmpl %edx, (%rdi)
-#else
- cmpl %edx, CURR_EVENT(%rdi)
-#endif
- je 8b
-
- /* Increment LEFT. If this brings the count back to the
- initial count unlock the object. */
- movl $1, %edx
- movl INIT_COUNT(%rdi), %eax
- LOCK
- xaddl %edx, LEFT(%rdi)
- subl $1, %eax
- cmpl %eax, %edx
- jne,pt 10f
-
- /* Release the mutex. We cannot release the lock before
- waking the waiting threads since otherwise a new thread might
- arrive and gets waken up, too. */
- LOCK
- decl MUTEX(%rdi)
- jne 9f
-
-10: xorl %eax, %eax /* != PTHREAD_BARRIER_SERIAL_THREAD */
-
- retq
-
- /* The necessary number of threads arrived. */
-3:
-#if CURR_EVENT == 0
- incl (%rdi)
-#else
- incl CURR_EVENT(%rdi)
-#endif
-
- /* Wake up all waiters. The count is a signed number in the kernel
- so 0x7fffffff is the highest value. */
- movl $0x7fffffff, %edx
- movl $FUTEX_WAKE, %esi
- orl PRIVATE(%rdi), %esi
- movl $SYS_futex, %eax
- syscall
-
- /* Increment LEFT. If this brings the count back to the
- initial count unlock the object. */
- movl $1, %edx
- movl INIT_COUNT(%rdi), %eax
- LOCK
- xaddl %edx, LEFT(%rdi)
- subl $1, %eax
- cmpl %eax, %edx
- jne,pt 5f
-
- /* Release the mutex. We cannot release the lock before
- waking the waiting threads since otherwise a new thread might
- arrive and gets waken up, too. */
- LOCK
- decl MUTEX(%rdi)
- jne 4f
-
-5: orl $-1, %eax /* == PTHREAD_BARRIER_SERIAL_THREAD */
-
- retq
-
-1: movl PRIVATE(%rdi), %esi
- addq $MUTEX, %rdi
- xorl $LLL_SHARED, %esi
- callq __lll_lock_wait
- subq $MUTEX, %rdi
- jmp 2b
-
-4: movl PRIVATE(%rdi), %esi
- addq $MUTEX, %rdi
- xorl $LLL_SHARED, %esi
- callq __lll_unlock_wake
- jmp 5b
-
-6: movl PRIVATE(%rdi), %esi
- addq $MUTEX, %rdi
- xorl $LLL_SHARED, %esi
- callq __lll_unlock_wake
- subq $MUTEX, %rdi
- jmp 7b
-
-9: movl PRIVATE(%rdi), %esi
- addq $MUTEX, %rdi
- xorl $LLL_SHARED, %esi
- callq __lll_unlock_wake
- jmp 10b
- .size __pthread_barrier_wait,.-__pthread_barrier_wait
-weak_alias (__pthread_barrier_wait, pthread_barrier_wait)

View File

@ -1,40 +0,0 @@
Use python3 for installed executable python scripts.
Fedora is a Python3-only distribution:
https://fedoraproject.org/wiki/FinalizingFedoraSwitchtoPython3
This fixes build failures where builders may strictly enforce only
python3 during a transitional phase.
Author: Carlos O'Donell <carlos@redhat.com>
diff --git a/benchtests/scripts/compare_bench.py b/benchtests/scripts/compare_bench.py
index c1c438a1c9f0eae6..b7d3d7bcee87969d 100755
--- a/benchtests/scripts/compare_bench.py
+++ b/benchtests/scripts/compare_bench.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
# Copyright (C) 2015-2019 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
#
diff --git a/benchtests/scripts/import_bench.py b/benchtests/scripts/import_bench.py
index 7a55d19f038e64d4..72e6034243a8c9b6 100644
--- a/benchtests/scripts/import_bench.py
+++ b/benchtests/scripts/import_bench.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
# Copyright (C) 2015-2019 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
#
diff --git a/benchtests/scripts/validate_benchout.py b/benchtests/scripts/validate_benchout.py
index 55d07c6bce5b5184..04129f9c26c2874c 100755
--- a/benchtests/scripts/validate_benchout.py
+++ b/benchtests/scripts/validate_benchout.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
# Copyright (C) 2014-2019 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
#

View File

@ -0,0 +1,29 @@
Index: glibc-2.22-386-g95e8397/resolv/res_hconf.c
===================================================================
--- glibc-2.22-386-g95e8397.orig/resolv/res_hconf.c
+++ glibc-2.22-386-g95e8397/resolv/res_hconf.c
@@ -46,6 +46,7 @@
#include "res_hconf.h"
#include <wchar.h>
#include <atomic.h>
+#include <libc-internal.h>
#if IS_IN (libc)
# define fgets_unlocked __fgets_unlocked
@@ -577,7 +578,16 @@ _res_hconf_trim_domain (char *hostname)
for (i = 0; i < _res_hconf.num_trimdomains; ++i)
{
+ DIAG_PUSH_NEEDS_COMMENT
+#if __GNUC_PREREQ (5, 0)
+ /* GCC 5.0 warns about array subscript being above array bounds,
+ but that's not entirely possible since i is limited to
+ num_trimdomains which is limited to <= TRIMDOMAINS_MAX. This
+ is likely PR/59124 which is still not fixed. */
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
+#endif
const char *trim = _res_hconf.trimdomain[i];
+ DIAG_POP_NEEDS_COMMENT
trim_len = strlen (trim);
if (hostname_len > trim_len

19
glibc-rh1009145.patch Normal file
View File

@ -0,0 +1,19 @@
--- glibc-2.18-151-g303e567.orig/elf/ldconfig.c 2013-09-25 14:01:01.522446341 -0400
+++ glibc-2.18-151-g303e567/elf/ldconfig.c 2013-09-25 14:06:31.094218857 -0400
@@ -959,6 +959,16 @@
|| dlib_ptr->flag == FLAG_ELF_LIBC6)
&& flag == FLAG_ELF)
dlib_ptr->flag = flag;
+#ifdef __arm__
+ /* In Fedora 20 binutils regressed temporarily and failed to
+ mark hard ABI objects with the correct flag. Therefore we
+ must accept unmarked objects that were previously marked
+ hard ABI. We can remove this check once the entire distribution
+ has been rebuilt. */
+ else if (dlib_ptr->flag & FLAG_ARM_LIBHF &&
+ (flag == FLAG_ELF_LIBC6))
+ ;
+#endif
else
error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."),
dlib_ptr->name, direntry->d_name,

90
glibc-rh1013801.patch Normal file
View File

@ -0,0 +1,90 @@
#
# Posted upstream:
# https://sourceware.org/ml/libc-alpha/2013-10/msg00065.html
#
# This is related to bug 1013801 in that it fixes the problem
# by modifying the runtime. In bug 1013801 we have libselinux
# using pthread_atfork which pulls in libpthread, but we don't
# want that, we want libpthread to be pulled in only when
# actually needed by the application. This patch makes it
# possible to avoid requiring libpthread and still use
# pthread_atfork.
#
# The general idea for the design is in the leading comment
# in the source code.
#
diff --git a/nptl/sysdeps/unix/sysv/linux/Makefile b/nptl/sysdeps/unix/sysv/linux/Makefile
index 6078e2d..36fd50b 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -18,7 +18,9 @@
routines = alloca_cutoff forward libc-lowlevellock libc-cancellation \
libc-cleanup libc_pthread_init libc_multiple_threads \
- register-atfork unregister-atfork
+ register-atfork unregister-atfork libc_pthread_atfork
+
+static-only-routines += libc_pthread_atfork
shared-only-routines = forward
libpthread-routines = nptl-init vars events version pt-interp \
diff --git a/nptl/libc_pthread_atfork.c b/nptl/libc_pthread_atfork.c
new file mode 100644
index 0000000..667049a
--- /dev/null
+++ b/nptl/libc_pthread_atfork.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+/* The standard design pattern for making it optional to link against
+ libpthread is to mark the function weak, test if the function
+ address is non-zero and call the function, otherwise use a fallback.
+ The problem with pthread_atfork is that there is no viable
+ fallback. If you need to do something during fork it has to be done
+ via pthread_atfork. This makes having libpthread optional and using
+ pthread_atfork impossible. We make it possible by providing
+ pthread_atfork in libc_nonshared.a. The real work of pthread_atfork
+ is done by __register_atfork which is already provided in
+ libc_nonshared.a. It's included in libc_nonshared.a because
+ __dso_handle has to be unique to each DSO such that unloading the DSO
+ can unregister the atfork handlers. We build pthread_atfork again
+ under a different file name and include it into libc_nonshared.a and
+ libc.a. We keep pthread_atfork in libpthread_nonshared.a and
+ libpthread.a for compatibility and completeness.
+
+ Applications that can't rely on a new glibc should use the following
+ code to optionally include libpthread and still register a function
+ via pthread_atfork i.e. use __register_atfork directly:
+
+ extern void *__dso_handle __attribute__ ((__weak__, __visibility__ ("hidden")));
+ extern int __register_atfork (void (*) (void), void (*) (void), void (*) (void), void *);
+
+ static int __app_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void))
+ {
+ return __register_atfork (prepare, parent, child,
+ &__dso_handle == NULL ? NULL : __dso_handle);
+ }
+
+ This code requires glibc 2.3.2 or newer. Previous to 2.3.2 no such
+ interfaces exist and at that point is is impossible to have an
+ optional libpthread and call pthread_atfork.
+
+ This code adds no more ABI requirements than already exist since
+ __dso_handle and __register_atfork are already part of the ABI. */
+#include <pthread_atfork.c>

47
glibc-rh1052846.patch Normal file
View File

@ -0,0 +1,47 @@
commit 403ce35141da511898cde550f48ebc68a2a3ac82
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date: Mon Jan 6 14:37:21 2014 +0530
Fix infinite loop in ftell when writing wide char data (BZ #16398)
ftell tries to avoid flushing the buffer when it is in write mode by
converting the wide char data and placing it into the binary buffer.
If the output buffer space is full and there is data to write, the
code reverts to flushing the buffer. This breaks when there is space
in the buffer but it is not enough to convert the next character in
the wide data buffer, due to which __codecvt_do_out returns a
__codecvt_partial status. In this case, ftell keeps running in an
infinite loop.
The fix here is to detect the __codecvt_partial status in addition to
checking if the buffer is full.
diff --git a/libio/wfileops.c b/libio/wfileops.c
index 87d3cdc..877fc1f 100644
--- a/libio/wfileops.c
+++ b/libio/wfileops.c
@@ -715,7 +715,7 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
- fp->_wide_data->_IO_write_base) / clen;
else
{
- enum __codecvt_result status;
+ enum __codecvt_result status = __codecvt_ok;
delta = (fp->_wide_data->_IO_write_ptr
- fp->_wide_data->_IO_write_base);
const wchar_t *write_base = fp->_wide_data->_IO_write_base;
@@ -728,9 +728,12 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
flush buffers for every ftell. */
do
{
- /* Ugh, no point trying to avoid the flush. Just do it
- and go back to how it was with the read mode. */
- if (delta > 0 && new_write_ptr == fp->_IO_buf_end)
+ /* There is not enough space in the buffer to do the entire
+ conversion, so there is no point trying to avoid the
+ buffer flush. Just do it and go back to how it was with
+ the read mode. */
+ if (status == __codecvt_partial
+ || (delta > 0 && new_write_ptr == fp->_IO_buf_end))
{
if (_IO_switch_to_wget_mode (fp))
return WEOF;

836
glibc-rh1069559-1.patch Normal file
View File

@ -0,0 +1,836 @@
commit 03425ba6ab17b87b2c64f0d7b47fb0b86add9993
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date: Thu Feb 20 15:41:18 2014 +0530
Separate ftell from fseek logic and avoid modifying FILE data (#16532)
ftell semantics are distinct from fseek(SEEK_CUR) especially when it
is called on a file handler that is not yet active. Due to this
caveat, much care needs to be taken while modifying the handler data
and hence, this first iteration on separating out ftell focusses on
maintaining handler data integrity at all times while it figures out
the current stream offset. The result is that it makes a syscall for
every offset request.
There is scope for optimizing this by caching offsets when we know
that the handler is active. A simple way to find out is when the
buffers have data. It is not so simple to find this out when the
buffer is empty without adding some kind of flag.
diff --git a/libio/Makefile b/libio/Makefile
index 8c333ce..8ccd80f 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -60,7 +60,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
tst-wmemstream1 tst-wmemstream2 \
bug-memstream1 bug-wmemstream1 \
tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \
- tst-fwrite-error tst-ftell-partial-wide
+ tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler
ifeq (yes,$(build-shared))
# Add test-fopenloc only if shared library is enabled since it depends on
# shared localedata objects.
diff --git a/libio/fileops.c b/libio/fileops.c
index a3499be..a177302 100644
--- a/libio/fileops.c
+++ b/libio/fileops.c
@@ -931,6 +931,59 @@ _IO_file_sync_mmap (_IO_FILE *fp)
_IO_off64_t
+get_file_offset (_IO_FILE *fp)
+{
+ if ((fp->_flags & _IO_IS_APPENDING) == _IO_IS_APPENDING)
+ {
+ struct stat64 st;
+ bool ret = (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode));
+ if (ret)
+ return st.st_size;
+ else
+ return EOF;
+ }
+ else
+ return _IO_SYSSEEK (fp, 0, _IO_seek_cur);
+}
+
+
+/* ftell{,o} implementation. Don't modify any state of the file pointer while
+ we try to get the current state of the stream. */
+static _IO_off64_t
+do_ftell (_IO_FILE *fp)
+{
+ _IO_off64_t result;
+
+ result = get_file_offset (fp);
+
+ if (result == EOF)
+ return result;
+
+ /* No point looking at unflushed data if we haven't allocated buffers
+ yet. */
+ if (fp->_IO_buf_base != NULL)
+ {
+ bool was_writing = (fp->_IO_write_ptr > fp->_IO_write_base
+ || _IO_in_put_mode (fp));
+
+ /* Adjust for unflushed data. */
+ if (!was_writing)
+ result -= fp->_IO_read_end - fp->_IO_read_ptr;
+ else
+ result += fp->_IO_write_ptr - fp->_IO_read_end;
+ }
+
+ if (result < 0)
+ {
+ __set_errno (EINVAL);
+ return EOF;
+ }
+
+ return result;
+}
+
+
+_IO_off64_t
_IO_new_file_seekoff (fp, offset, dir, mode)
_IO_FILE *fp;
_IO_off64_t offset;
@@ -940,6 +993,13 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
_IO_off64_t result;
_IO_off64_t delta, new_offset;
long count;
+
+ /* Short-circuit into a separate function. We don't want to mix any
+ functionality and we don't want to touch anything inside the FILE
+ object. */
+ if (mode == 0)
+ return do_ftell (fp);
+
/* POSIX.1 8.2.3.7 says that after a call the fflush() the file
offset of the underlying file must be exact. */
int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
@@ -948,9 +1008,6 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
bool was_writing = (fp->_IO_write_ptr > fp->_IO_write_base
|| _IO_in_put_mode (fp));
- if (mode == 0)
- dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
-
/* Flush unwritten characters.
(This may do an unneeded write if we seek within the buffer.
But to be able to switch to reading, we would need to set
@@ -958,7 +1015,7 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
which assumes file_ptr() is eGptr. Anyway, since we probably
end up flushing when we close(), it doesn't make much difference.)
FIXME: simulate mem-mapped files. */
- else if (was_writing && _IO_switch_to_get_mode (fp))
+ if (was_writing && _IO_switch_to_get_mode (fp))
return EOF;
if (fp->_IO_buf_base == NULL)
@@ -978,30 +1035,10 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
{
case _IO_seek_cur:
/* Adjust for read-ahead (bytes is buffer). */
- if (mode != 0 || !was_writing)
- offset -= fp->_IO_read_end - fp->_IO_read_ptr;
- else
- {
- /* _IO_read_end coincides with fp._offset, so the actual file position
- is fp._offset - (_IO_read_end - new_write_ptr). This is fine
- even if fp._offset is not set, since fp->_IO_read_end is then at
- _IO_buf_base and this adjustment is for unbuffered output. */
- offset -= fp->_IO_read_end - fp->_IO_write_ptr;
- }
+ offset -= fp->_IO_read_end - fp->_IO_read_ptr;
if (fp->_offset == _IO_pos_BAD)
- {
- if (mode != 0)
- goto dumb;
- else
- {
- result = _IO_SYSSEEK (fp, 0, dir);
- if (result == EOF)
- return result;
-
- fp->_offset = result;
- }
- }
+ goto dumb;
/* Make offset absolute, assuming current pointer is file_ptr(). */
offset += fp->_offset;
if (offset < 0)
@@ -1028,10 +1065,6 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
}
/* At this point, dir==_IO_seek_set. */
- /* If we are only interested in the current position we've found it now. */
- if (mode == 0)
- return offset;
-
/* If destination is within current buffer, optimize: */
if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
&& !_IO_in_backup (fp))
diff --git a/libio/libioP.h b/libio/libioP.h
index 4ca723c..8a7b85b 100644
--- a/libio/libioP.h
+++ b/libio/libioP.h
@@ -397,6 +397,7 @@ extern void _IO_wdoallocbuf (_IO_FILE *) __THROW;
libc_hidden_proto (_IO_wdoallocbuf)
extern void _IO_unsave_wmarkers (_IO_FILE *) __THROW;
extern unsigned _IO_adjust_wcolumn (unsigned, const wchar_t *, int) __THROW;
+extern _IO_off64_t get_file_offset (_IO_FILE *fp);
/* Marker-related function. */
diff --git a/libio/tst-ftell-active-handler.c b/libio/tst-ftell-active-handler.c
new file mode 100644
index 0000000..aac2923
--- /dev/null
+++ b/libio/tst-ftell-active-handler.c
@@ -0,0 +1,366 @@
+/* Verify that ftell returns the correct value at various points before and
+ after the handler on which it is called becomes active.
+ Copyright (C) 2014 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <wchar.h>
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+#define get_handles_fdopen(filename, fd, fp, fd_mode, mode) \
+({ \
+ int ret = 0; \
+ (fd) = open ((filename), (fd_mode), 0); \
+ if ((fd) == -1) \
+ { \
+ printf ("open failed: %m\n"); \
+ ret = 1; \
+ } \
+ else \
+ { \
+ (fp) = fdopen ((fd), (mode)); \
+ if ((fp) == NULL) \
+ { \
+ printf ("fdopen failed: %m\n"); \
+ close (fd); \
+ ret = 1; \
+ } \
+ } \
+ ret; \
+})
+
+#define get_handles_fopen(filename, fd, fp, mode) \
+({ \
+ int ret = 0; \
+ (fp) = fopen ((filename), (mode)); \
+ if ((fp) == NULL) \
+ { \
+ printf ("fopen failed: %m\n"); \
+ ret = 1; \
+ } \
+ else \
+ { \
+ (fd) = fileno (fp); \
+ if ((fd) == -1) \
+ { \
+ printf ("fileno failed: %m\n"); \
+ ret = 1; \
+ } \
+ } \
+ ret; \
+})
+
+static const void *data;
+static const char *char_data = "abcdef";
+static const wchar_t *wide_data = L"abcdef";
+static size_t data_len;
+/* Maintain the current file length for validation. */
+static size_t file_len;
+
+typedef int (*fputs_func_t) (const void *data, FILE *fp);
+fputs_func_t fputs_func;
+
+/* Test that the value of ftell is not cached when the stream handle is not
+ active. */
+static int
+do_ftell_test (const char *filename)
+{
+ int ret = 0;
+ struct test
+ {
+ const char *mode;
+ int fd_mode;
+ size_t old_off;
+ size_t new_off;
+ } test_modes[] = {
+ {"w", O_WRONLY, 0, data_len},
+ {"w+", O_RDWR, 0, data_len},
+ {"r+", O_RDWR, 0, data_len},
+ {"a", O_WRONLY, data_len, 2 * data_len},
+ {"a+", O_RDWR, 2 * data_len, 3 * data_len},
+ };
+ for (int j = 0; j < 2; j++)
+ {
+ for (int i = 0; i < sizeof (test_modes) / sizeof (struct test); i++)
+ {
+ FILE *fp;
+ int fd;
+ printf ("\tftell: %s (file, \"%s\"): ", j == 0 ? "fdopen" : "fopen",
+ test_modes[i].mode);
+
+ if (j == 0)
+ ret = get_handles_fdopen (filename, fd, fp, test_modes[i].fd_mode,
+ test_modes[i].mode);
+ else
+ ret = get_handles_fopen (filename, fd, fp, test_modes[i].mode);
+
+ if (ret != 0)
+ return 1;
+
+ long off = ftell (fp);
+ if (off != test_modes[i].old_off)
+ {
+ printf ("Incorrect old offset. Expected %zu but got %ld, ",
+ test_modes[i].old_off, off);
+ ret |= 1;
+ }
+ else
+ printf ("old offset = %ld, ", off);
+
+ int ret = write (fd, data, data_len);
+ off = ftell (fp);
+
+ if (off != test_modes[i].new_off)
+ {
+ printf ("Incorrect new offset. Expected %zu but got %ld\n",
+ test_modes[i].old_off, off);
+ ret |= 1;
+ }
+ else
+ printf ("new offset = %ld\n", off);
+
+ fclose (fp);
+ }
+ }
+
+ return ret;
+}
+
+/* This test opens the file for writing, moves the file offset of the
+ underlying file, writes out data and then checks if ftell trips on it. */
+static int
+do_write_test (const char *filename)
+{
+ FILE *fp = NULL;
+ int fd;
+ int ret = 0;
+ struct test
+ {
+ const char *mode;
+ int fd_mode;
+ } test_modes[] = {
+ {"w", O_WRONLY},
+ {"w+", O_RDWR},
+ {"r+", O_RDWR}
+ };
+
+ for (int j = 0; j < 2; j++)
+ {
+ for (int i = 0; i < sizeof (test_modes) / sizeof (struct test); i++)
+ {
+ printf ("\twrite: %s (file, \"%s\"): ", j == 0 ? "fopen" : "fdopen",
+ test_modes[i].mode);
+
+ if (j == 0)
+ ret = get_handles_fopen (filename, fd, fp, test_modes[i].mode);
+ else
+ ret = get_handles_fdopen (filename, fd, fp, test_modes[i].fd_mode,
+ test_modes[i].mode);
+
+ if (ret != 0)
+ return ret;
+
+ /* Move offset to just before the end of the file. */
+ off_t ret = lseek (fd, file_len - 1, SEEK_SET);
+ if (ret == -1)
+ {
+ printf ("lseek failed: %m\n");
+ ret |= 1;
+ }
+
+ /* Write some data. */
+ size_t written = fputs_func (data, fp);
+
+ if (written == EOF)
+ {
+ printf ("fputs[1] failed to write data\n");
+ ret |= 1;
+ }
+
+ /* Verify that the offset points to the end of the file. */
+ long offset = ftell (fp);
+ file_len = file_len - 1 + data_len;
+
+ if (offset != file_len)
+ {
+ printf ("Incorrect offset. Expected %zu, but got %ld\n",
+ file_len, offset);
+
+ ret |= 1;
+ }
+
+ printf ("offset = %ld\n", offset);
+ fclose (fp);
+ }
+ }
+
+ return ret;
+}
+
+/* This test opens a file in append mode, writes some data, and then verifies
+ that ftell does not trip over it. */
+static int
+do_append_test (const char *filename)
+{
+ FILE *fp = NULL;
+ int ret = 0;
+ int fd;
+
+ struct test
+ {
+ const char *mode;
+ int fd_mode;
+ } test_modes[] = {
+ {"a", O_WRONLY},
+ {"a+", O_RDWR}
+ };
+
+ for (int j = 0; j < 2; j++)
+ {
+ for (int i = 0; i < sizeof (test_modes) / sizeof (struct test); i++)
+ {
+ printf ("\tappend: %s (file, \"%s\"): ", j == 0 ? "fopen" : "fdopen",
+ test_modes[i].mode);
+
+ if (j == 0)
+ ret = get_handles_fopen (filename, fd, fp, test_modes[i].mode);
+ else
+ ret = get_handles_fdopen (filename, fd, fp, test_modes[i].fd_mode,
+ test_modes[i].mode);
+
+ if (ret != 0)
+ return ret;
+
+ /* Write some data. */
+ size_t written = fputs_func (data, fp);
+
+ if (written == EOF)
+ {
+ printf ("fputs[1] failed to write all data\n");
+ ret |= 1;
+ }
+
+ /* Verify that the offset points to the end of the file. */
+ long offset = ftell (fp);
+ file_len += data_len;
+
+ if (offset != file_len)
+ {
+ printf ("Incorrect offset. Expected %zu, but got %ld\n",
+ file_len, offset);
+
+ ret |= 1;
+ }
+
+ printf ("offset = %ld\n", offset);
+ fclose (fp);
+ }
+ }
+
+ return ret;
+}
+
+static int
+do_one_test (const char *filename)
+{
+ int ret = 0;
+
+ ret |= do_ftell_test (filename);
+ ret |= do_write_test (filename);
+ ret |= do_append_test (filename);
+
+ return ret;
+}
+
+static int
+do_test (void)
+{
+ int ret = 0;
+ FILE *fp = NULL;
+ char *filename;
+ size_t written;
+ int fd = create_temp_file ("tst-active-handler-tmp.", &filename);
+
+ if (fd == -1)
+ {
+ printf ("create_temp_file: %m\n");
+ return 1;
+ }
+
+ fp = fdopen (fd, "w");
+ if (fp == NULL)
+ {
+ printf ("fdopen[0]: %m\n");
+ close (fd);
+ return 1;
+ }
+
+ data = char_data;
+ data_len = strlen (char_data);
+ file_len = strlen (char_data);
+ written = fputs (data, fp);
+
+ if (written == EOF)
+ {
+ printf ("fputs[1] failed to write data\n");
+ ret = 1;
+ }
+
+ fclose (fp);
+ if (ret)
+ return ret;
+
+ /* Tests for regular files. */
+ puts ("Regular mode:");
+ fputs_func = (fputs_func_t) fputs;
+ data = char_data;
+ data_len = strlen (char_data);
+ ret |= do_one_test (filename);
+
+ /* Truncate the file before repeating the tests in wide mode. */
+ fp = fopen (filename, "w");
+ if (fp == NULL)
+ {
+ printf ("fopen failed %m\n");
+ return 1;
+ }
+ fclose (fp);
+
+ /* Tests for wide files. */
+ puts ("Wide mode:");
+ if (setlocale (LC_ALL, "en_US.UTF-8") == NULL)
+ {
+ printf ("Cannot set en_US.UTF-8 locale.\n");
+ return 1;
+ }
+ fputs_func = (fputs_func_t) fputws;
+ data = wide_data;
+ data_len = wcslen (wide_data);
+ ret |= do_one_test (filename);
+
+ return ret;
+}
diff --git a/libio/wfileops.c b/libio/wfileops.c
index 9cebe77..eda7828 100644
--- a/libio/wfileops.c
+++ b/libio/wfileops.c
@@ -596,29 +596,22 @@ done:
return 0;
}
-_IO_off64_t
-_IO_wfile_seekoff (fp, offset, dir, mode)
- _IO_FILE *fp;
- _IO_off64_t offset;
- int dir;
- int mode;
+static _IO_off64_t
+do_ftell_wide (_IO_FILE *fp)
{
- _IO_off64_t result;
- _IO_off64_t delta, new_offset;
- long int count;
- /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
- offset of the underlying file must be exact. */
- int must_be_exact = ((fp->_wide_data->_IO_read_base
- == fp->_wide_data->_IO_read_end)
- && (fp->_wide_data->_IO_write_base
- == fp->_wide_data->_IO_write_ptr));
+ _IO_off64_t result, offset = 0;
- bool was_writing = ((fp->_wide_data->_IO_write_ptr
- > fp->_wide_data->_IO_write_base)
- || _IO_in_put_mode (fp));
-
- if (mode == 0)
+ /* No point looking for offsets in the buffer if it hasn't even been
+ allocated. */
+ if (fp->_wide_data->_IO_buf_base != NULL)
{
+ const wchar_t *wide_read_base;
+ const wchar_t *wide_read_ptr;
+ const wchar_t *wide_read_end;
+ bool was_writing = ((fp->_wide_data->_IO_write_ptr
+ > fp->_wide_data->_IO_write_base)
+ || _IO_in_put_mode (fp));
+
/* XXX For wide stream with backup store it is not very
reasonable to determine the offset. The pushed-back
character might require a state change and we need not be
@@ -633,14 +626,117 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
return -1;
}
- /* There is no more data in the backup buffer. We can
- switch back. */
- _IO_switch_to_main_wget_area (fp);
+ /* Nothing in the backup store, so note the backed up pointers
+ without changing the state. */
+ wide_read_base = fp->_wide_data->_IO_save_base;
+ wide_read_ptr = wide_read_base;
+ wide_read_end = fp->_wide_data->_IO_save_end;
+ }
+ else
+ {
+ wide_read_base = fp->_wide_data->_IO_read_base;
+ wide_read_ptr = fp->_wide_data->_IO_read_ptr;
+ wide_read_end = fp->_wide_data->_IO_read_end;
}
- dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
+ struct _IO_codecvt *cv = fp->_codecvt;
+ int clen = (*cv->__codecvt_do_encoding) (cv);
+
+ if (!was_writing)
+ {
+ if (clen > 0)
+ {
+ offset -= (wide_read_end - wide_read_ptr) * clen;
+ offset -= fp->_IO_read_end - fp->_IO_read_ptr;
+ }
+ else
+ {
+ int nread;
+
+ size_t delta = wide_read_ptr - wide_read_base;
+ __mbstate_t state = fp->_wide_data->_IO_last_state;
+ nread = (*cv->__codecvt_do_length) (cv, &state,
+ fp->_IO_read_base,
+ fp->_IO_read_end, delta);
+ offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
+ }
+ }
+ else
+ {
+ if (clen > 0)
+ offset += (fp->_wide_data->_IO_write_ptr
+ - fp->_wide_data->_IO_write_base) * clen;
+ else
+ {
+ size_t delta = (fp->_wide_data->_IO_write_ptr
+ - fp->_wide_data->_IO_write_base);
+
+ /* Allocate enough space for the conversion. */
+ size_t outsize = delta * sizeof (wchar_t);
+ char *out = malloc (outsize);
+ char *outstop = out;
+ const wchar_t *in = fp->_wide_data->_IO_write_base;
+
+ enum __codecvt_result status;
+
+ __mbstate_t state = fp->_wide_data->_IO_last_state;
+ status = (*cv->__codecvt_do_out) (cv, &state,
+ in, in + delta, &in,
+ out, out + outsize, &outstop);
+
+ /* We don't check for __codecvt_partial because it can be
+ returned on one of two conditions: either the output
+ buffer is full or the input sequence is incomplete. We
+ take care to allocate enough buffer and our input
+ sequences must be complete since they are accepted as
+ wchar_t; if not, then that is an error. */
+ if (__glibc_unlikely (status != __codecvt_ok))
+ return WEOF;
+
+ offset += outstop - out;
+ }
+
+ /* _IO_read_end coincides with fp._offset, so the actual file position
+ is fp._offset - (_IO_read_end - new_write_ptr). */
+ offset -= fp->_IO_read_end - fp->_IO_write_ptr;
+ }
}
+ result = get_file_offset (fp);
+
+ if (result == EOF)
+ return result;
+
+ result += offset;
+
+ return result;
+}
+
+_IO_off64_t
+_IO_wfile_seekoff (fp, offset, dir, mode)
+ _IO_FILE *fp;
+ _IO_off64_t offset;
+ int dir;
+ int mode;
+{
+ _IO_off64_t result;
+ _IO_off64_t delta, new_offset;
+ long int count;
+
+ if (mode == 0)
+ return do_ftell_wide (fp);
+
+ /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
+ offset of the underlying file must be exact. */
+ int must_be_exact = ((fp->_wide_data->_IO_read_base
+ == fp->_wide_data->_IO_read_end)
+ && (fp->_wide_data->_IO_write_base
+ == fp->_wide_data->_IO_write_ptr));
+
+ bool was_writing = ((fp->_wide_data->_IO_write_ptr
+ > fp->_wide_data->_IO_write_base)
+ || _IO_in_put_mode (fp));
+
/* Flush unwritten characters.
(This may do an unneeded write if we seek within the buffer.
But to be able to switch to reading, we would need to set
@@ -648,7 +744,7 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
which assumes file_ptr() is eGptr. Anyway, since we probably
end up flushing when we close(), it doesn't make much difference.)
FIXME: simulate mem-mapped files. */
- else if (was_writing && _IO_switch_to_wget_mode (fp))
+ if (was_writing && _IO_switch_to_wget_mode (fp))
return WEOF;
if (fp->_wide_data->_IO_buf_base == NULL)
@@ -693,7 +789,6 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
{
int nread;
- flushed:
delta = (fp->_wide_data->_IO_read_ptr
- fp->_wide_data->_IO_read_base);
fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
@@ -706,80 +801,9 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
}
}
- else
- {
- char *new_write_ptr = fp->_IO_write_ptr;
-
- if (clen > 0)
- offset += (fp->_wide_data->_IO_write_ptr
- - fp->_wide_data->_IO_write_base) / clen;
- else
- {
- enum __codecvt_result status = __codecvt_ok;
- delta = (fp->_wide_data->_IO_write_ptr
- - fp->_wide_data->_IO_write_base);
- const wchar_t *write_base = fp->_wide_data->_IO_write_base;
-
- /* FIXME: This actually ends up in two iterations of conversion,
- one here and the next when the buffer actually gets flushed.
- It may be possible to optimize this in future so that
- wdo_write identifies already converted content and does not
- redo it. In any case, this is much better than having to
- flush buffers for every ftell. */
- do
- {
- /* There is not enough space in the buffer to do the entire
- conversion, so there is no point trying to avoid the
- buffer flush. Just do it and go back to how it was with
- the read mode. */
- if (status == __codecvt_partial
- || (delta > 0 && new_write_ptr == fp->_IO_buf_end))
- {
- if (_IO_switch_to_wget_mode (fp))
- return WEOF;
- goto flushed;
- }
-
- const wchar_t *new_wbase = fp->_wide_data->_IO_write_base;
- fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
- status = (*cv->__codecvt_do_out) (cv,
- &fp->_wide_data->_IO_state,
- write_base,
- write_base + delta,
- &new_wbase,
- new_write_ptr,
- fp->_IO_buf_end,
- &new_write_ptr);
-
- delta -= new_wbase - write_base;
-
- /* If there was an error, then return WEOF.
- TODO: set buffer state. */
- if (__glibc_unlikely (status == __codecvt_error))
- return WEOF;
- }
- while (delta > 0);
- }
-
- /* _IO_read_end coincides with fp._offset, so the actual file position
- is fp._offset - (_IO_read_end - new_write_ptr). This is fine
- even if fp._offset is not set, since fp->_IO_read_end is then at
- _IO_buf_base and this adjustment is for unbuffered output. */
- offset -= fp->_IO_read_end - new_write_ptr;
- }
if (fp->_offset == _IO_pos_BAD)
- {
- if (mode != 0)
- goto dumb;
- else
- {
- result = _IO_SYSSEEK (fp, 0, dir);
- if (result == EOF)
- return result;
- fp->_offset = result;
- }
- }
+ goto dumb;
/* Make offset absolute, assuming current pointer is file_ptr(). */
offset += fp->_offset;
@@ -802,10 +826,6 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
}
/* At this point, dir==_IO_seek_set. */
- /* If we are only interested in the current position we've found it now. */
- if (mode == 0)
- return offset;
-
/* If destination is within current buffer, optimize: */
if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
&& !_IO_in_backup (fp))

183
glibc-rh1069559-2.patch Normal file
View File

@ -0,0 +1,183 @@
commit 4a68e8ded4fef2b00fbfc6baf1e79e46389871ca
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date: Thu Feb 20 15:55:16 2014 +0530
Use cached offset in ftell when reliable
The cached offset is reliable to use in ftell when the stream handle
is active. We can consider a stream as being active when there is
unbuffered data. However, even in this case, we can use the cached
offset only when the stream is not being written to in a+ mode,
because this case may have unbuffered data and a stale offset; the
previous read could have sent it off somewhere other than the end of
the file.
There were a couple of adjustments necessary to get this to work.
Firstly, fdopen now ceases to use _IO_attach_fd because it sets the
offset cache to the current file position. This is not correct
because there could be changes to the file descriptor before the
stream handle is activated, which would not get reflected.
A similar offset caching action is done in _IO_fwide, claiming that
wide streams have 'problems' with the file offsets. There don't seem
to be any obvious problems with not having the offset cache available,
other than that it will have to be queried in a subsequent
read/write/seek. I have removed this as well.
The testsuite passes successfully with these changes on x86_64.
diff --git a/libio/fileops.c b/libio/fileops.c
index a177302..c44a5da 100644
--- a/libio/fileops.c
+++ b/libio/fileops.c
@@ -952,12 +952,8 @@ get_file_offset (_IO_FILE *fp)
static _IO_off64_t
do_ftell (_IO_FILE *fp)
{
- _IO_off64_t result;
-
- result = get_file_offset (fp);
-
- if (result == EOF)
- return result;
+ _IO_off64_t result = 0;
+ bool use_cached_offset = false;
/* No point looking at unflushed data if we haven't allocated buffers
yet. */
@@ -971,8 +967,34 @@ do_ftell (_IO_FILE *fp)
result -= fp->_IO_read_end - fp->_IO_read_ptr;
else
result += fp->_IO_write_ptr - fp->_IO_read_end;
+
+ /* It is safe to use the cached offset when available if there is
+ unbuffered data (indicating that the file handle is active) and the
+ handle is not for a file open in a+ mode. The latter condition is
+ because there could be a scenario where there is a switch from read
+ mode to write mode using an fseek to an arbitrary position. In this
+ case, there would be unbuffered data due to be appended to the end of
+ the file, but the offset may not necessarily be the end of the
+ file. It is fine to use the cached offset when the a+ stream is in
+ read mode though, since the offset is maintained correctly in that
+ case. Note that this is not a comprehensive set of cases when the
+ offset is reliable. The offset may be reliable even in some cases
+ where there is no buffered input and the handle is active, but it's
+ just that we don't have a way to identify that condition reliably. */
+ use_cached_offset = (result != 0 && fp->_offset != _IO_pos_BAD
+ && ((fp->_flags & (_IO_IS_APPENDING | _IO_NO_READS))
+ == (_IO_IS_APPENDING | _IO_NO_READS)
+ && was_writing));
}
+ if (use_cached_offset)
+ result += fp->_offset;
+ else
+ result += get_file_offset (fp);
+
+ if (result == EOF)
+ return result;
+
if (result < 0)
{
__set_errno (EINVAL);
diff --git a/libio/iofdopen.c b/libio/iofdopen.c
index 066ff19..4525f0f 100644
--- a/libio/iofdopen.c
+++ b/libio/iofdopen.c
@@ -141,9 +141,6 @@ _IO_new_fdopen (fd, mode)
#ifdef _IO_MTSAFE_IO
new_f->fp.file._lock = &new_f->lock;
#endif
- /* Set up initially to use the `maybe_mmap' jump tables rather than using
- __fopen_maybe_mmap to do it, because we need them in place before we
- call _IO_file_attach or else it will allocate a buffer immediately. */
_IO_no_init (&new_f->fp.file, 0, 0, &new_f->wd,
#ifdef _G_HAVE_MMAP
(use_mmap && (read_write & _IO_NO_WRITES))
@@ -159,13 +156,10 @@ _IO_new_fdopen (fd, mode)
#if !_IO_UNIFIED_JUMPTABLES
new_f->fp.vtable = NULL;
#endif
- if (_IO_file_attach ((_IO_FILE *) &new_f->fp, fd) == NULL)
- {
- _IO_setb (&new_f->fp.file, NULL, NULL, 0);
- _IO_un_link (&new_f->fp);
- free (new_f);
- return NULL;
- }
+ /* We only record the fd because _IO_file_init will have unset the offset.
+ We don't need to get the current offset in the file now since it could
+ change between now and when the handle is activated. */
+ new_f->fp.file._fileno = fd;
new_f->fp.file._flags &= ~_IO_DELETE_DONT_CLOSE;
_IO_mask_flags (&new_f->fp.file, read_write,
diff --git a/libio/iofwide.c b/libio/iofwide.c
index 5cff632..64187e4 100644
--- a/libio/iofwide.c
+++ b/libio/iofwide.c
@@ -199,12 +199,6 @@ _IO_fwide (fp, mode)
/* From now on use the wide character callback functions. */
((struct _IO_FILE_plus *) fp)->vtable = fp->_wide_data->_wide_vtable;
-
- /* One last twist: we get the current stream position. The wide
- char streams have much more problems with not knowing the
- current position and so we should disable the optimization
- which allows the functions without knowing the position. */
- fp->_offset = _IO_SYSSEEK (fp, 0, _IO_seek_cur);
}
/* Set the mode now. */
diff --git a/libio/wfileops.c b/libio/wfileops.c
index eda7828..651f5ce 100644
--- a/libio/wfileops.c
+++ b/libio/wfileops.c
@@ -600,6 +600,7 @@ static _IO_off64_t
do_ftell_wide (_IO_FILE *fp)
{
_IO_off64_t result, offset = 0;
+ bool use_cached_offset = false;
/* No point looking for offsets in the buffer if it hasn't even been
allocated. */
@@ -696,13 +697,36 @@ do_ftell_wide (_IO_FILE *fp)
offset += outstop - out;
}
- /* _IO_read_end coincides with fp._offset, so the actual file position
- is fp._offset - (_IO_read_end - new_write_ptr). */
+ /* _IO_read_end coincides with fp._offset, so the actual file
+ position is fp._offset - (_IO_read_end - new_write_ptr). */
offset -= fp->_IO_read_end - fp->_IO_write_ptr;
+
}
+
+ /* It is safe to use the cached offset when available if there is
+ unbuffered data (indicating that the file handle is active) and
+ the handle is not for a file open in a+ mode. The latter
+ condition is because there could be a scenario where there is a
+ switch from read mode to write mode using an fseek to an arbitrary
+ position. In this case, there would be unbuffered data due to be
+ appended to the end of the file, but the offset may not
+ necessarily be the end of the file. It is fine to use the cached
+ offset when the a+ stream is in read mode though, since the offset
+ is maintained correctly in that case. Note that this is not a
+ comprehensive set of cases when the offset is reliable. The
+ offset may be reliable even in some cases where there is no
+ buffered input and the handle is active, but it's just that we
+ don't have a way to identify that condition reliably. */
+ use_cached_offset = (offset != 0 && fp->_offset != _IO_pos_BAD
+ && ((fp->_flags & (_IO_IS_APPENDING | _IO_NO_READS))
+ == (_IO_IS_APPENDING | _IO_NO_READS)
+ && was_writing));
}
- result = get_file_offset (fp);
+ if (use_cached_offset)
+ result = fp->_offset;
+ else
+ result = get_file_offset (fp);
if (result == EOF)
return result;

View File

@ -1,12 +1,3 @@
Short description: Add syslog.target dependency.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Bug-Fedora: #1070416
Upstream status: not-needed
Fedora-specific changes to the nscd.service file.
See also: glibc-nscd-sysconfig.patch.
--- a/nscd/nscd.service
+++ b/nscd/nscd.service
@@ -2,6 +2,7 @@

View File

@ -1,22 +0,0 @@
Please see the following bug for a complete summary:
https://bugzilla.redhat.com/show_bug.cgi?id=1615608
Index: glibc-2.28/manual/startup.texi
===================================================================
--- glibc-2.28.orig/manual/startup.texi
+++ glibc-2.28/manual/startup.texi
@@ -1005,14 +1005,6 @@ This function actually terminates the pr
intercept this signal; see @ref{Signal Handling}.
@end deftypefun
-@c Put in by rms. Don't remove.
-@cartouche
-@strong{Future Change Warning:} Proposed Federal censorship regulations
-may prohibit us from giving you information about the possibility of
-calling this function. We would be required to say that this is not an
-acceptable way of terminating a program.
-@end cartouche
-
@node Termination Internals
@subsection Termination Internals

View File

@ -1,14 +1,3 @@
Short description: Add UCS-2 aliases.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Bug-RHEL: #697421
Upstream status: https://sourceware.org/ml/libc-alpha/2012-12/msg00103.html
This is a Fedora-specific change to include new aliases for UCS-2
data for gconv used by a certain class of users. This should be
revisited at some point to determine if those users are just using
UTF-8 at this point.
diff -rup a/iconvdata/gconv-modules b/iconvdata/gconv-modules
--- a/iconvdata/gconv-modules 2010-05-04 05:27:23.000000000 -0600
+++ b/iconvdata/gconv-modules 2012-01-26 10:58:24.181895489 -0700

View File

@ -1,14 +1,3 @@
Short description: Work ld.so --verify crash on debuginfo files.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Bug-RHEL: #741105, #767146
Upstream status: not-needed
This change is designed to work around running ld.so on a debuginfo
file. This is the wrong fix for this problem and should be dropped.
The correct solution is to mark debuginfo files as new types of
ELF files.
Index: glibc-2.22-386-g95e8397/elf/dl-load.c
===================================================================
--- glibc-2.22-386-g95e8397.orig/elf/dl-load.c

View File

@ -1,16 +1,3 @@
Short description: fnmatch() fails with MBCS.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Bug-RHEL: #819430, #826149, #826151
Bug-Upstream: #14185
Upstream status: not-submitted
fnmatch() fails when '*' wildcard is applied on the file name
containing multi-byte character(s)
This needs to be reviewed thoroughly and go upstream with a
new test case.
diff -Nrup a/posix/fnmatch.c b/posix/fnmatch.c
--- a/posix/fnmatch.c 2012-01-01 07:16:32.000000000 -0500
+++ b/posix/fnmatch.c 2012-05-23 14:14:29.099461189 -0400

13
glibc-rh825061.patch Normal file
View File

@ -0,0 +1,13 @@
diff -rup a/manual/Makefile b/manual/Makefile
--- a/manual/Makefile 2012-05-20 19:47:38.000000000 -0600
+++ b/manual/Makefile 2012-05-29 22:23:33.920428631 -0600
@@ -129,7 +129,8 @@ $(objpfx)%.c.texi: examples/%.c
mv -f $@.new $@
$(objpfx)%.info: %.texinfo
- LANGUAGE=C LC_ALL=C $(MAKEINFO) -P $(objpfx) --output=$@ $<
+ LANGUAGE=C LC_ALL=C $(MAKEINFO) -P $(objpfx) --output=`basename $@` $<
+ mv `basename $@`* $(objpfx)
$(objpfx)%.dvi: %.texinfo
cd $(objpfx);$(TEXI2DVI) -I $(shell cd $(<D) && pwd) --output=$@ \

View File

@ -1,16 +1,6 @@
Short description: Fix newlocale error return.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Bug-RHEL: #832516
Bug-Fedora: #827510
Bug-Upstream: #14247
Upstream status: not-submitted
This needs to go upstream right away to fix the error case for
newlocale not correctly returning an error.
2012-06-14 Jeff Law <law@redhat.com>
* locale/loadlocale.c (_nl_load_locale): Delay setting
file->decided until we have successfully loaded the file's
data.
@ -26,7 +16,7 @@ index e3fa187..9fd9216 100644
- file->decided = 1;
file->data = NULL;
fd = __open_nocancel (file->filename, O_RDONLY | O_CLOEXEC);
fd = open_not_cancel_2 (file->filename, O_RDONLY | O_CLOEXEC);
@@ -278,6 +277,7 @@ _nl_load_locale (struct loaded_l10nfile *file, int category)
newdata->alloc = alloc;

181
glibc-rh952799.patch Normal file
View File

@ -0,0 +1,181 @@
#
# Red Hat BZ:
# https://bugzilla.redhat.com/show_bug.cgi?id=816647
#
# ChangeLog
#
#2013-04-30 Patsy Franklin <pfrankli@redhat.com>
#
# * iconv/gconv_cache.c (find_module): Demangle init_fct before
# checking for NULL. Mangle __btowc_fct if init_fct is non-NULL.
# * iconv/gconv_db.c (free_derivation): Check that __shlib_handle
# is non-NULL before demangling the end_fct. Check for NULL
# end_fct after demangling.
# (__gconv_release_step): Demangle the end_fct before checking
# it for NULL. Remove assert on __shlibc_handle != NULL.
# (gen_steps): Don't check btowc_fct for NULL before mangling.
# Demangle init_fct before checking for NULL.
# (increment_counter): Likewise
# * gconv_dl.c (__gconv_find_shlib): Don't check init_fct or
# end_fct for NULL before mangling.
# * wcsmbs/btowc.c (__btowc): Demangle btowc_fct before checking
# for NULL.
#
diff -Nrup a/iconv/gconv_cache.c b/iconv/gconv_cache.c
--- a/iconv/gconv_cache.c 2012-12-24 22:02:13.000000000 -0500
+++ b/iconv/gconv_cache.c 2013-04-30 06:43:24.788684270 -0400
@@ -207,17 +207,16 @@ find_module (const char *directory, cons
result->__data = NULL;
/* Call the init function. */
- if (result->__init_fct != NULL)
- {
- __gconv_init_fct init_fct = result->__init_fct;
+ __gconv_init_fct init_fct = result->__init_fct;
#ifdef PTR_DEMANGLE
- PTR_DEMANGLE (init_fct);
+ PTR_DEMANGLE (init_fct);
#endif
+ if (init_fct != NULL)
+ {
status = DL_CALL_FCT (init_fct, (result));
#ifdef PTR_MANGLE
- if (result->__btowc_fct != NULL)
- PTR_MANGLE (result->__btowc_fct);
+ PTR_MANGLE (result->__btowc_fct);
#endif
}
}
diff -Nrup a/iconv/gconv_db.c b/iconv/gconv_db.c
--- a/iconv/gconv_db.c 2012-12-24 22:02:13.000000000 -0500
+++ b/iconv/gconv_db.c 2013-04-30 06:37:16.886521576 -0400
@@ -179,16 +179,15 @@ free_derivation (void *p)
size_t cnt;
for (cnt = 0; cnt < deriv->nsteps; ++cnt)
- if (deriv->steps[cnt].__counter > 0
- && deriv->steps[cnt].__end_fct != NULL)
+ if ((deriv->steps[cnt].__counter > 0)
+ && (deriv->steps[cnt].__shlib_handle != NULL))
{
- assert (deriv->steps[cnt].__shlib_handle != NULL);
-
__gconv_end_fct end_fct = deriv->steps[cnt].__end_fct;
#ifdef PTR_DEMANGLE
PTR_DEMANGLE (end_fct);
#endif
- DL_CALL_FCT (end_fct, (&deriv->steps[cnt]));
+ if (end_fct != NULL)
+ DL_CALL_FCT (end_fct, (&deriv->steps[cnt]));
}
/* Free the name strings. */
@@ -212,16 +211,12 @@ __gconv_release_step (struct __gconv_ste
if (step->__shlib_handle != NULL && --step->__counter == 0)
{
/* Call the destructor. */
- if (step->__end_fct != NULL)
- {
- assert (step->__shlib_handle != NULL);
-
- __gconv_end_fct end_fct = step->__end_fct;
+ __gconv_end_fct end_fct = step->__end_fct;
#ifdef PTR_DEMANGLE
- PTR_DEMANGLE (end_fct);
+ PTR_DEMANGLE (end_fct);
#endif
- DL_CALL_FCT (end_fct, (step));
- }
+ if (end_fct != NULL)
+ DL_CALL_FCT (end_fct, (step));
#ifndef STATIC_GCONV
/* Release the loaded module. */
@@ -293,13 +288,11 @@ gen_steps (struct derivation_step *best,
/* Call the init function. */
__gconv_init_fct init_fct = result[step_cnt].__init_fct;
- if (init_fct != NULL)
- {
- assert (result[step_cnt].__shlib_handle != NULL);
-
# ifdef PTR_DEMANGLE
- PTR_DEMANGLE (init_fct);
+ PTR_DEMANGLE (init_fct);
# endif
+ if (init_fct != NULL)
+ {
status = DL_CALL_FCT (init_fct, (&result[step_cnt]));
if (__builtin_expect (status, __GCONV_OK) != __GCONV_OK)
@@ -312,8 +305,7 @@ gen_steps (struct derivation_step *best,
}
# ifdef PTR_MANGLE
- if (result[step_cnt].__btowc_fct != NULL)
- PTR_MANGLE (result[step_cnt].__btowc_fct);
+ PTR_MANGLE (result[step_cnt].__btowc_fct);
# endif
}
}
@@ -393,16 +385,15 @@ increment_counter (struct __gconv_step *
/* Call the init function. */
__gconv_init_fct init_fct = step->__init_fct;
- if (init_fct != NULL)
- {
#ifdef PTR_DEMANGLE
- PTR_DEMANGLE (init_fct);
+ PTR_DEMANGLE (init_fct);
#endif
+ if (init_fct != NULL)
+ {
DL_CALL_FCT (init_fct, (step));
#ifdef PTR_MANGLE
- if (step->__btowc_fct != NULL)
- PTR_MANGLE (step->__btowc_fct);
+ PTR_MANGLE (step->__btowc_fct);
#endif
}
}
diff -Nrup a/iconv/gconv_dl.c b/iconv/gconv_dl.c
--- a/iconv/gconv_dl.c 2012-12-24 22:02:13.000000000 -0500
+++ b/iconv/gconv_dl.c 2013-04-30 06:37:16.889521601 -0400
@@ -132,10 +132,8 @@ __gconv_find_shlib (const char *name)
#ifdef PTR_MANGLE
PTR_MANGLE (found->fct);
- if (found->init_fct != NULL)
- PTR_MANGLE (found->init_fct);
- if (found->end_fct != NULL)
- PTR_MANGLE (found->end_fct);
+ PTR_MANGLE (found->init_fct);
+ PTR_MANGLE (found->end_fct);
#endif
/* We have succeeded in loading the shared object. */
diff -Nrup a/wcsmbs/btowc.c b/wcsmbs/btowc.c
--- a/wcsmbs/btowc.c 2012-12-24 22:02:13.000000000 -0500
+++ b/wcsmbs/btowc.c 2013-04-30 06:37:16.891521619 -0400
@@ -47,15 +47,15 @@ __btowc (c)
/* Get the conversion functions. */
fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE));
__gconv_btowc_fct btowc_fct = fcts->towc->__btowc_fct;
+#ifdef PTR_DEMANGLE
+ if (fcts->towc->__shlib_handle != NULL)
+ PTR_DEMANGLE (btowc_fct);
+#endif
if (__builtin_expect (fcts->towc_nsteps == 1, 1)
&& __builtin_expect (btowc_fct != NULL, 1))
{
/* Use the shortcut function. */
-#ifdef PTR_DEMANGLE
- if (fcts->towc->__shlib_handle != NULL)
- PTR_DEMANGLE (btowc_fct);
-#endif
return DL_CALL_FCT (btowc_fct, (fcts->towc, (unsigned char) c));
}
else

4264
glibc.spec

File diff suppressed because it is too large Load Diff

340
glibc_post_upgrade.c Normal file
View File

@ -0,0 +1,340 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/time.h>
#include <dirent.h>
#include <stddef.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <elf.h>
#define verbose_exec(failcode, path...) \
do \
{ \
char *const arr[] = { path, NULL }; \
vexec (failcode, arr); \
} while (0)
__attribute__((noinline)) void vexec (int failcode, char *const path[]);
__attribute__((noinline)) void says (const char *str);
__attribute__((noinline)) void sayn (long num);
__attribute__((noinline)) void message (char *const path[]);
__attribute__((noinline)) int check_elf (const char *name);
#ifdef __i386__
static int
is_ia64 (void)
{
unsigned int fl1, fl2;
/* See if we can use cpuid. */
__asm__ ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
"pushl %0; popfl; pushfl; popl %0; popfl"
: "=&r" (fl1), "=&r" (fl2)
: "i" (0x00200000));
if (((fl1 ^ fl2) & 0x00200000) == 0)
return 0;
/* Host supports cpuid. See if cpuid gives capabilities, try
CPUID(0). Preserve %ebx and %ecx; cpuid insn clobbers these, we
don't need their CPUID values here, and %ebx may be the PIC
register. */
__asm__ ("pushl %%ecx; pushl %%ebx; cpuid; popl %%ebx; popl %%ecx"
: "=a" (fl1) : "0" (0) : "edx", "cc");
if (fl1 == 0)
return 0;
/* Invoke CPUID(1), return %edx; caller can examine bits to
determine what's supported. */
__asm__ ("pushl %%ecx; pushl %%ebx; cpuid; popl %%ebx; popl %%ecx"
: "=d" (fl2), "=a" (fl1) : "1" (1) : "cc");
return (fl2 & (1 << 30)) != 0;
}
#else
#define is_ia64() 0
#endif
int
main (void)
{
struct stat statbuf;
char initpath[256];
char buffer[4096];
struct pref {
char *p;
int len;
} prefix[] = { { "libc-", 5 }, { "libm-", 5 },
{ "librt-", 6 }, { "libpthread-", 11 },
{ "librtkaio-", 10 }, { "libthread_db-", 13 } };
int i, j, fd;
off_t base;
ssize_t ret;
#ifdef __i386__
const char *remove_dirs[] = { "/lib/tls", "/lib/i686", "/lib/tls/i486", "/lib/tls/i586", "/lib/tls/i686" };
#else
#ifndef LIBTLS
#define LIBTLS "/lib/tls"
#endif
const char *remove_dirs[] = { LIBTLS };
#endif
for (j = 0; j < sizeof (remove_dirs) / sizeof (remove_dirs[0]); ++j)
{
size_t rmlen = strlen (remove_dirs[j]);
fd = open (remove_dirs[j], O_RDONLY);
if (fd >= 0
&& (ret = getdirentries (fd, buffer, sizeof (buffer), &base))
>= (ssize_t) offsetof (struct dirent, d_name))
{
for (base = 0; base + offsetof (struct dirent, d_name) < ret; )
{
struct dirent *d = (struct dirent *) (buffer + base);
for (i = 0; i < sizeof (prefix) / sizeof (prefix[0]); i++)
if (! strncmp (d->d_name, prefix[i].p, prefix[i].len))
{
char *p = d->d_name + prefix[i].len;
while (*p == '.' || (*p >= '0' && *p <= '9')) p++;
if (p[0] == 's' && p[1] == 'o' && p[2] == '\0'
&& p + 3 - d->d_name
< sizeof (initpath) - rmlen - 1)
{
memcpy (initpath, remove_dirs[j], rmlen);
initpath[rmlen] = '/';
strcpy (initpath + rmlen + 1, d->d_name);
unlink (initpath);
break;
}
}
base += d->d_reclen;
}
close (fd);
}
}
int ldsocfd = open (LD_SO_CONF, O_RDONLY);
struct stat ldsocst;
if (ldsocfd >= 0 && fstat (ldsocfd, &ldsocst) >= 0)
{
char p[ldsocst.st_size + 1];
if (read (ldsocfd, p, ldsocst.st_size) == ldsocst.st_size)
{
p[ldsocst.st_size] = '\0';
if (strstr (p, "include ld.so.conf.d/*.conf") == NULL)
{
close (ldsocfd);
ldsocfd = open (LD_SO_CONF, O_WRONLY | O_TRUNC);
if (ldsocfd >= 0)
{
size_t slen = strlen ("include ld.so.conf.d/*.conf\n");
if (write (ldsocfd, "include ld.so.conf.d/*.conf\n", slen)
!= slen
|| write (ldsocfd, p, ldsocst.st_size) != ldsocst.st_size)
_exit (109);
}
}
}
if (ldsocfd >= 0)
close (ldsocfd);
}
/* If installing bi-arch glibc, rpm sometimes doesn't unpack all files
before running one of the lib's %post scriptlet. /sbin/ldconfig will
then be run by the other arch's %post. */
if (! access ("/sbin/ldconfig", X_OK))
verbose_exec (110, "/sbin/ldconfig", "/sbin/ldconfig");
if (! utimes (GCONV_MODULES_DIR "/gconv-modules.cache", NULL))
{
#ifndef ICONVCONFIG
#define ICONVCONFIG "/usr/sbin/iconvconfig"
#endif
char *iconv_cache = GCONV_MODULES_DIR"/gconv-modules.cache";
char *iconv_dir = GCONV_MODULES_DIR;
if (is_ia64 ())
{
iconv_cache = "/emul/ia32-linux"GCONV_MODULES_DIR"/gconv-modules.cache";
iconv_dir = "/emul/ia32-linux"GCONV_MODULES_DIR;
}
verbose_exec (113, ICONVCONFIG, "/usr/sbin/iconvconfig",
"-o", iconv_cache,
"--nostdlib", iconv_dir);
}
/* Check if telinit is available and either SysVInit fifo,
or upstart telinit. */
if (access ("/sbin/telinit", X_OK)
|| ((!!access ("/dev/initctl", F_OK))
^ !access ("/sbin/initctl", X_OK)))
_exit (0);
/* Check if we are not inside of some chroot, because we'd just
timeout and leave /etc/initrunlvl.
On more modern systems this test is not sufficient to detect
if we're in a chroot. */
if (readlink ("/proc/1/exe", initpath, 256) <= 0 ||
readlink ("/proc/1/root", initpath, 256) <= 0)
_exit (0);
/* Here's another well known way to detect chroot, at least on an
ext and xfs filesystems and assuming nothing mounted on the chroot's
root. */
if (stat ("/", &statbuf) != 0
|| (statbuf.st_ino != 2
&& statbuf.st_ino != 128))
_exit (0);
if (check_elf ("/proc/1/exe"))
verbose_exec (116, "/sbin/telinit", "/sbin/telinit", "u");
/* Check if we can safely condrestart sshd. */
if (access ("/sbin/service", X_OK) == 0
&& access ("/usr/sbin/sshd", X_OK) == 0
&& access ("/etc/rc.d/init.d/sshd", X_OK) == 0
&& access ("/bin/bash", X_OK) == 0)
{
if (check_elf ("/usr/sbin/sshd"))
verbose_exec (-121, "/sbin/service", "/sbin/service", "sshd", "condrestart");
}
_exit(0);
}
void
vexec (int failcode, char *const path[])
{
pid_t pid;
int status, save_errno;
int devnull = 0;
if (failcode < 0)
{
devnull = 1;
failcode = -failcode;
}
pid = vfork ();
if (pid == 0)
{
int fd;
if (devnull && (fd = open ("/dev/null", O_WRONLY)) >= 0)
{
dup2 (fd, 1);
dup2 (fd, 2);
close (fd);
}
execv (path[0], path + 1);
save_errno = errno;
message (path);
says (" exec failed with errno ");
sayn (save_errno);
says ("\n");
_exit (failcode);
}
else if (pid < 0)
{
save_errno = errno;
message (path);
says (" fork failed with errno ");
sayn (save_errno);
says ("\n");
_exit (failcode + 1);
}
if (waitpid (0, &status, 0) != pid || !WIFEXITED (status))
{
message (path);
says (" child terminated abnormally\n");
_exit (failcode + 2);
}
if (WEXITSTATUS (status))
{
message (path);
says (" child exited with exit code ");
sayn (WEXITSTATUS (status));
says ("\n");
_exit (WEXITSTATUS (status));
}
}
void
says (const char *str)
{
write (1, str, strlen (str));
}
void
sayn (long num)
{
char string[sizeof (long) * 3 + 1];
char *p = string + sizeof (string) - 1;
*p = '\0';
if (num == 0)
*--p = '0';
else
while (num)
{
*--p = '0' + num % 10;
num = num / 10;
}
says (p);
}
void
message (char *const path[])
{
says ("/usr/sbin/glibc_post_upgrade: While trying to execute ");
says (path[0]);
}
int
check_elf (const char *name)
{
/* Play safe, if we can't open or read, assume it might be
ELF for the current arch. */
int ret = 1;
int fd = open (name, O_RDONLY);
if (fd >= 0)
{
Elf32_Ehdr ehdr;
if (read (fd, &ehdr, offsetof (Elf32_Ehdr, e_version))
== offsetof (Elf32_Ehdr, e_version))
{
ret = 0;
if (ehdr.e_ident[EI_CLASS]
== (sizeof (long) == 8 ? ELFCLASS64 : ELFCLASS32))
{
#if defined __i386__
ret = ehdr.e_machine == EM_386;
#elif defined __x86_64__
ret = ehdr.e_machine == EM_X86_64;
#elif defined __ia64__
ret = ehdr.e_machine == EM_IA_64;
#elif defined __powerpc64__
ret = ehdr.e_machine == EM_PPC64;
#elif defined __powerpc__
ret = ehdr.e_machine == EM_PPC;
#elif defined __s390__ || defined __s390x__
ret = ehdr.e_machine == EM_S390;
#elif defined __x86_64__
ret = ehdr.e_machine == EM_X86_64;
#elif defined __sparc__
if (sizeof (long) == 8)
ret = ehdr.e_machine == EM_SPARCV9;
else
ret = (ehdr.e_machine == EM_SPARC
|| ehdr.e_machine == EM_SPARC32PLUS);
#else
ret = 1;
#endif
}
}
close (fd);
}
return ret;
}

340
libc-lock.h Normal file
View File

@ -0,0 +1,340 @@
/* libc-internal interface for mutex locks. LinuxThreads version.
Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003
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; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _BITS_LIBC_LOCK_H
#define _BITS_LIBC_LOCK_H 1
#include <pthread.h>
/* Mutex type. */
#ifdef _IO_MTSAFE_IO
typedef pthread_mutex_t __libc_lock_t;
typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t;
# ifdef __USE_UNIX98
typedef pthread_rwlock_t __libc_rwlock_t;
# else
typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
# endif
typedef __libc_lock_recursive_t __rtld_lock_recursive_t;
#else
typedef struct __libc_lock_opaque__ __libc_lock_t;
typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
#endif
/* Type for key to thread-specific data. */
typedef pthread_key_t __libc_key_t;
/* Define a lock variable NAME with storage class CLASS. The lock must be
initialized with __libc_lock_init before it can be used (or define it
with __libc_lock_define_initialized, below). Use `extern' for CLASS to
declare a lock defined in another module. In public structure
definitions you must use a pointer to the lock structure (i.e., NAME
begins with a `*'), because its storage size will not be known outside
of libc. */
#define __libc_lock_define(CLASS,NAME) \
CLASS __libc_lock_t NAME;
#define __libc_rwlock_define(CLASS,NAME) \
CLASS __libc_rwlock_t NAME;
#define __libc_lock_define_recursive(CLASS,NAME) \
CLASS __libc_lock_recursive_t NAME;
#define __rtld_lock_define_recursive(CLASS,NAME) \
CLASS __rtld_lock_recursive_t NAME;
/* Define an initialized lock variable NAME with storage class CLASS.
For the C library we take a deeper look at the initializer. For
this implementation all fields are initialized to zero. Therefore
we don't initialize the variable which allows putting it into the
BSS section. (Except on PA-RISC and other odd architectures, where
initialized locks must be set to one due to the lack of normal
atomic operations.) */
#if __LT_SPINLOCK_INIT == 0
# define __libc_lock_define_initialized(CLASS,NAME) \
CLASS __libc_lock_t NAME;
#else
# define __libc_lock_define_initialized(CLASS,NAME) \
CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER;
#endif
#define __libc_rwlock_define_initialized(CLASS,NAME) \
CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
/* Define an initialized recursive lock variable NAME with storage
class CLASS. */
#define __libc_lock_define_initialized_recursive(CLASS,NAME) \
CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
#define _LIBC_LOCK_RECURSIVE_INITIALIZER \
{PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \
CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER;
#define _RTLD_LOCK_RECURSIVE_INITIALIZER \
{PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
#if defined __PIC__
# define __libc_maybe_call(FUNC, ARGS, ELSE) \
(__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \
_fn != NULL ? (*_fn) ARGS : ELSE; }))
#else
# define __libc_maybe_call(FUNC, ARGS, ELSE) \
(FUNC != NULL ? FUNC ARGS : ELSE)
#endif
#define __libc_maybe_call2(FUNC, ARGS, ELSE) __libc_maybe_call (__##FUNC, ARGS, ELSE)
/* Initialize the named lock variable, leaving it in a consistent, unlocked
state. */
#define __libc_lock_init(NAME) \
(__libc_maybe_call2 (pthread_mutex_init, (&(NAME), NULL), 0))
#define __libc_rwlock_init(NAME) \
(__libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0));
/* Same as last but this time we initialize a recursive mutex. */
#define __libc_lock_init_recursive(NAME) \
do { \
if (__pthread_mutex_init != NULL) \
{ \
pthread_mutexattr_t __attr; \
__pthread_mutexattr_init (&__attr); \
__pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \
__pthread_mutex_init (&(NAME).mutex, &__attr); \
__pthread_mutexattr_destroy (&__attr); \
} \
} while (0);
#define __rtld_lock_init_recursive(NAME) \
__libc_lock_init_recursive (NAME)
/* Finalize the named lock variable, which must be locked. It cannot be
used again until __libc_lock_init is called again on it. This must be
called on a lock variable before the containing storage is reused. */
#define __libc_lock_fini(NAME) \
(__libc_maybe_call2 (pthread_mutex_destroy, (&(NAME)), 0));
#define __libc_rwlock_fini(NAME) \
(__libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0));
/* Finalize recursive named lock. */
#define __libc_lock_fini_recursive(NAME) __libc_lock_fini ((NAME).mutex)
#define __rtld_lock_fini_recursive(NAME) __libc_lock_fini_recursive (NAME)
/* Lock the named lock variable. */
#define __libc_lock_lock(NAME) \
(__libc_maybe_call2 (pthread_mutex_lock, (&(NAME)), 0));
#define __libc_rwlock_rdlock(NAME) \
(__libc_maybe_call (__pthread_rwlock_rdlock, (&(NAME)), 0));
#define __libc_rwlock_wrlock(NAME) \
(__libc_maybe_call (__pthread_rwlock_wrlock, (&(NAME)), 0));
/* Lock the recursive named lock variable. */
#define __libc_lock_lock_recursive(NAME) __libc_lock_lock ((NAME).mutex)
/* Try to lock the named lock variable. */
#define __libc_lock_trylock(NAME) \
(__libc_maybe_call2 (pthread_mutex_trylock, (&(NAME)), 0))
#define __libc_rwlock_tryrdlock(NAME) \
(__libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0))
#define __libc_rwlock_trywrlock(NAME) \
(__libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0))
/* Try to lock the recursive named lock variable. */
#define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock ((NAME).mutex)
#define __rtld_lock_trylock_recursive(NAME) \
__libc_lock_trylock_recursive (NAME)
/* Unlock the named lock variable. */
#define __libc_lock_unlock(NAME) \
(__libc_maybe_call2 (pthread_mutex_unlock, (&(NAME)), 0));
#define __libc_rwlock_unlock(NAME) \
(__libc_maybe_call (__pthread_rwlock_unlock, (&(NAME)), 0));
/* Unlock the recursive named lock variable. */
#define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock ((NAME).mutex)
#define __rtld_lock_lock_recursive(NAME) __libc_lock_lock_recursive (NAME)
#define __rtld_lock_unlock_recursive(NAME) __libc_lock_unlock_recursive (NAME)
/* Define once control variable. */
#if PTHREAD_ONCE_INIT == 0
/* Special case for static variables where we can avoid the initialization
if it is zero. */
# define __libc_once_define(CLASS, NAME) \
CLASS pthread_once_t NAME
#else
# define __libc_once_define(CLASS, NAME) \
CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT
#endif
/* Call handler iff the first call. */
#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
do { \
if (__pthread_once != NULL) \
__pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION)); \
else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \
INIT_FUNCTION (); \
(ONCE_CONTROL) = 2; \
} \
} while (0)
/* Start critical region with cleanup. */
#define __libc_cleanup_region_start(DOIT, FCT, ARG) \
{ struct _pthread_cleanup_buffer _buffer; \
int _avail = (DOIT) && _pthread_cleanup_push_defer != NULL; \
if (_avail) { \
_pthread_cleanup_push_defer (&_buffer, (FCT), (ARG)); \
}
/* End critical region with cleanup. */
#define __libc_cleanup_region_end(DOIT) \
if (_avail) { \
_pthread_cleanup_pop_restore (&_buffer, (DOIT)); \
} \
}
/* Sometimes we have to exit the block in the middle. */
#define __libc_cleanup_end(DOIT) \
if (_avail) { \
_pthread_cleanup_pop_restore (&_buffer, (DOIT)); \
}
#define __libc_cleanup_push(fct, arg) \
{ struct _pthread_cleanup_buffer _buffer; \
__libc_maybe_call (_pthread_cleanup_push, (&_buffer, (fct), (arg)), 0)
#define __libc_cleanup_pop(execute) \
__libc_maybe_call (_pthread_cleanup_pop, (&_buffer, execute), 0); \
}
/* Create thread-specific key. */
#define __libc_key_create(KEY, DESTRUCTOR) \
(__libc_maybe_call (__pthread_key_create, (KEY, DESTRUCTOR), 1))
/* Get thread-specific data. */
#define __libc_getspecific(KEY) \
(__libc_maybe_call (__pthread_getspecific, (KEY), NULL))
/* Set thread-specific data. */
#define __libc_setspecific(KEY, VALUE) \
(__libc_maybe_call (__pthread_setspecific, (KEY, VALUE), 0))
/* Register handlers to execute before and after `fork'. */
#define __libc_atfork(PREPARE, PARENT, CHILD) \
(__libc_maybe_call (__pthread_atfork, (PREPARE, PARENT, CHILD), 0))
__BEGIN_DECLS
extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
void (*__routine) (void *),
void *__arg) __THROW;
extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
int __execute) __THROW;
/* Functions that are used by this file and are internal to the GNU C
library. */
extern int __pthread_mutex_init (pthread_mutex_t *__mutex,
__const pthread_mutexattr_t *__mutex_attr);
extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex);
extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex);
extern int __pthread_mutex_lock (pthread_mutex_t *__mutex);
extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex);
extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr);
extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr);
extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr,
int __kind);
#ifdef __USE_UNIX98
extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock,
__const pthread_rwlockattr_t *__attr);
extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock);
extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock);
extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock);
extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock);
extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock);
extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock);
#endif
extern int __pthread_key_create (pthread_key_t *__key,
void (*__destr_function) (void *));
extern int __pthread_setspecific (pthread_key_t __key,
__const void *__pointer);
extern void *__pthread_getspecific (pthread_key_t __key);
extern int __pthread_once (pthread_once_t *__once_control,
void (*__init_routine) (void));
extern int __pthread_atfork (void (*__prepare) (void),
void (*__parent) (void),
void (*__child) (void));
__END_DECLS
/* Make the pthread functions weak so that we can elide them from
single-threaded processes. */
#ifndef __NO_WEAK_PTHREAD_ALIASES
# pragma weak __pthread_mutex_init
# pragma weak __pthread_mutex_destroy
# pragma weak __pthread_mutex_lock
# pragma weak __pthread_mutex_trylock
# pragma weak __pthread_mutex_unlock
# pragma weak __pthread_mutexattr_init
# pragma weak __pthread_mutexattr_destroy
# pragma weak __pthread_mutexattr_settype
# pragma weak __pthread_rwlock_destroy
# pragma weak __pthread_rwlock_rdlock
# pragma weak __pthread_rwlock_tryrdlock
# pragma weak __pthread_rwlock_wrlock
# pragma weak __pthread_rwlock_trywrlock
# pragma weak __pthread_rwlock_unlock
# pragma weak __pthread_key_create
# pragma weak __pthread_setspecific
# pragma weak __pthread_getspecific
# pragma weak __pthread_once
# pragma weak __pthread_initialize
# pragma weak __pthread_atfork
# pragma weak _pthread_cleanup_push_defer
# pragma weak _pthread_cleanup_pop_restore
# pragma weak _pthread_cleanup_push
# pragma weak _pthread_cleanup_pop
#endif
/* We need portable names for some functions. E.g., when they are
used as argument to __libc_cleanup_region_start. */
#define __libc_mutex_unlock __pthread_mutex_unlock
#endif /* bits/libc-lock.h */

739
mem-avx512-2016-v4.patch Normal file
View File

@ -0,0 +1,739 @@
Posted upstream by Intel:
https://sourceware.org/ml/libc-alpha/2016-01/msg00337.html
diff --git a/sysdeps/x86_64/multiarch/Makefile b/sysdeps/x86_64/multiarch/Makefile
index b2e31ef..d234f4a 100644
--- a/sysdeps/x86_64/multiarch/Makefile
+++ b/sysdeps/x86_64/multiarch/Makefile
@@ -7,11 +7,12 @@ ifeq ($(subdir),string)
sysdep_routines += strncat-c stpncpy-c strncpy-c strcmp-ssse3 \
strcmp-sse2-unaligned strncmp-ssse3 \
- memcmp-sse4 memcpy-ssse3 \
- memcpy-sse2-unaligned mempcpy-ssse3 \
- memmove-ssse3 memcpy-ssse3-back mempcpy-ssse3-back \
- memmove-avx-unaligned memcpy-avx-unaligned mempcpy-avx-unaligned \
- memmove-ssse3-back strcasecmp_l-ssse3 \
+ memcmp-sse4 memcpy-ssse3 memcpy-sse2-unaligned \
+ memcpy-avx512-no-vzeroupper mempcpy-ssse3 memmove-ssse3 \
+ memcpy-ssse3-back mempcpy-ssse3-back memmove-avx-unaligned \
+ memcpy-avx-unaligned mempcpy-avx-unaligned \
+ mempcpy-avx512-no-vzeroupper memmove-ssse3-back \
+ memmove-avx512-no-vzeroupper strcasecmp_l-ssse3 \
strncase_l-ssse3 strcat-ssse3 strncat-ssse3\
strcpy-ssse3 strncpy-ssse3 stpcpy-ssse3 stpncpy-ssse3 \
strcpy-sse2-unaligned strncpy-sse2-unaligned \
diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
index 5f600dc..d9ff016 100644
--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c
+++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
@@ -24,7 +24,7 @@
#include "init-arch.h"
/* Maximum number of IFUNC implementations. */
-#define MAX_IFUNC 4
+#define MAX_IFUNC 5
/* Fill ARRAY of MAX elements with IFUNC implementations for function
NAME supported on target machine and return the number of valid
@@ -46,9 +46,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
__memcmp_ssse3)
IFUNC_IMPL_ADD (array, i, memcmp, 1, __memcmp_sse2))
- /* Support sysdeps/x86_64/multiarch/memmove_chk.S. */
+ /* Support sysdeps/x86_64/multiarch/memmove_chk.c. */
IFUNC_IMPL (i, name, __memmove_chk,
IFUNC_IMPL_ADD (array, i, __memmove_chk,
+ HAS_ARCH_FEATURE (AVX512F_Usable),
+ __memmove_chk_avx512_no_vzeroupper)
+ IFUNC_IMPL_ADD (array, i, __memmove_chk,
HAS_ARCH_FEATURE (AVX_Usable),
__memmove_chk_avx_unaligned)
IFUNC_IMPL_ADD (array, i, __memmove_chk,
@@ -65,6 +68,9 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
IFUNC_IMPL_ADD (array, i, memmove,
HAS_ARCH_FEATURE (AVX_Usable),
__memmove_avx_unaligned)
+ IFUNC_IMPL_ADD (array, i, memmove,
+ HAS_ARCH_FEATURE (AVX512F_Usable),
+ __memmove_avx512_no_vzeroupper)
IFUNC_IMPL_ADD (array, i, memmove, HAS_CPU_FEATURE (SSSE3),
__memmove_ssse3_back)
IFUNC_IMPL_ADD (array, i, memmove, HAS_CPU_FEATURE (SSSE3),
@@ -254,6 +260,9 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
/* Support sysdeps/x86_64/multiarch/memcpy_chk.S. */
IFUNC_IMPL (i, name, __memcpy_chk,
IFUNC_IMPL_ADD (array, i, __memcpy_chk,
+ HAS_ARCH_FEATURE (AVX512F_Usable),
+ __memcpy_chk_avx512_no_vzeroupper)
+ IFUNC_IMPL_ADD (array, i, __memcpy_chk,
HAS_ARCH_FEATURE (AVX_Usable),
__memcpy_chk_avx_unaligned)
IFUNC_IMPL_ADD (array, i, __memcpy_chk,
@@ -274,12 +283,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
__memcpy_ssse3_back)
IFUNC_IMPL_ADD (array, i, memcpy, HAS_CPU_FEATURE (SSSE3),
__memcpy_ssse3)
+ IFUNC_IMPL_ADD (array, i, memcpy,
+ HAS_ARCH_FEATURE (AVX512F_Usable),
+ __memcpy_avx512_no_vzeroupper)
IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_sse2_unaligned)
IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_sse2))
/* Support sysdeps/x86_64/multiarch/mempcpy_chk.S. */
IFUNC_IMPL (i, name, __mempcpy_chk,
IFUNC_IMPL_ADD (array, i, __mempcpy_chk,
+ HAS_ARCH_FEATURE (AVX512F_Usable),
+ __mempcpy_chk_avx512_no_vzeroupper)
+ IFUNC_IMPL_ADD (array, i, __mempcpy_chk,
HAS_ARCH_FEATURE (AVX_Usable),
__mempcpy_chk_avx_unaligned)
IFUNC_IMPL_ADD (array, i, __mempcpy_chk,
@@ -294,6 +309,9 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
/* Support sysdeps/x86_64/multiarch/mempcpy.S. */
IFUNC_IMPL (i, name, mempcpy,
IFUNC_IMPL_ADD (array, i, mempcpy,
+ HAS_ARCH_FEATURE (AVX512F_Usable),
+ __mempcpy_avx512_no_vzeroupper)
+ IFUNC_IMPL_ADD (array, i, mempcpy,
HAS_ARCH_FEATURE (AVX_Usable),
__mempcpy_avx_unaligned)
IFUNC_IMPL_ADD (array, i, mempcpy, HAS_CPU_FEATURE (SSSE3),
diff --git a/sysdeps/x86_64/multiarch/memcpy-avx512-no-vzeroupper.S b/sysdeps/x86_64/multiarch/memcpy-avx512-no-vzeroupper.S
new file mode 100644
index 0000000..1b2eb6d
--- /dev/null
+++ b/sysdeps/x86_64/multiarch/memcpy-avx512-no-vzeroupper.S
@@ -0,0 +1,414 @@
+/* memcpy optimized with AVX512 for KNL hardware.
+ Copyright (C) 2016 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+#if defined HAVE_AVX512_ASM_SUPPORT && IS_IN (libc) \
+ && (defined SHARED \
+ || defined USE_AS_MEMMOVE \
+ || !defined USE_MULTIARCH)
+
+#include "asm-syntax.h"
+#ifndef MEMCPY
+# define MEMCPY __memcpy_avx512_no_vzeroupper
+# define MEMCPY_CHK __memcpy_chk_avx512_no_vzeroupper
+#endif
+
+ .section .text,"ax",@progbits
+#if !defined USE_AS_BCOPY
+ENTRY (MEMCPY_CHK)
+ cmpq %rdx, %rcx
+ jb HIDDEN_JUMPTARGET (__chk_fail)
+END (MEMCPY_CHK)
+#endif
+
+ENTRY (MEMCPY)
+ mov %rdi, %rax
+#ifdef USE_AS_MEMPCPY
+ add %rdx, %rax
+#endif
+ lea (%rsi, %rdx), %rcx
+ lea (%rdi, %rdx), %r9
+ cmp $512, %rdx
+ ja L(512bytesormore)
+
+L(check):
+ cmp $16, %rdx
+ jbe L(less_16bytes)
+ cmp $256, %rdx
+ jb L(less_256bytes)
+ vmovups (%rsi), %zmm0
+ vmovups 0x40(%rsi), %zmm1
+ vmovups 0x80(%rsi), %zmm2
+ vmovups 0xC0(%rsi), %zmm3
+ vmovups -0x100(%rcx), %zmm4
+ vmovups -0xC0(%rcx), %zmm5
+ vmovups -0x80(%rcx), %zmm6
+ vmovups -0x40(%rcx), %zmm7
+ vmovups %zmm0, (%rdi)
+ vmovups %zmm1, 0x40(%rdi)
+ vmovups %zmm2, 0x80(%rdi)
+ vmovups %zmm3, 0xC0(%rdi)
+ vmovups %zmm4, -0x100(%r9)
+ vmovups %zmm5, -0xC0(%r9)
+ vmovups %zmm6, -0x80(%r9)
+ vmovups %zmm7, -0x40(%r9)
+ ret
+
+L(less_256bytes):
+ cmp $128, %dl
+ jb L(less_128bytes)
+ vmovups (%rsi), %zmm0
+ vmovups 0x40(%rsi), %zmm1
+ vmovups -0x80(%rcx), %zmm2
+ vmovups -0x40(%rcx), %zmm3
+ vmovups %zmm0, (%rdi)
+ vmovups %zmm1, 0x40(%rdi)
+ vmovups %zmm2, -0x80(%r9)
+ vmovups %zmm3, -0x40(%r9)
+ ret
+
+L(less_128bytes):
+ cmp $64, %dl
+ jb L(less_64bytes)
+ vmovups (%rsi), %zmm0
+ vmovups -0x40(%rcx), %zmm1
+ vmovups %zmm0, (%rdi)
+ vmovups %zmm1, -0x40(%r9)
+ ret
+
+L(less_64bytes):
+ cmp $32, %dl
+ jb L(less_32bytes)
+ vmovdqu (%rsi), %ymm0
+ vmovdqu -0x20(%rcx), %ymm1
+ vmovdqu %ymm0, (%rdi)
+ vmovdqu %ymm1, -0x20(%r9)
+ ret
+
+L(less_32bytes):
+ vmovdqu (%rsi), %xmm0
+ vmovdqu -0x10(%rcx), %xmm1
+ vmovdqu %xmm0, (%rdi)
+ vmovdqu %xmm1, -0x10(%r9)
+ ret
+
+L(less_16bytes):
+ cmp $8, %dl
+ jb L(less_8bytes)
+ movq (%rsi), %rsi
+ movq -0x8(%rcx), %rcx
+ movq %rsi, (%rdi)
+ movq %rcx, -0x8(%r9)
+ ret
+
+L(less_8bytes):
+ cmp $4, %dl
+ jb L(less_4bytes)
+ mov (%rsi), %esi
+ mov -0x4(%rcx), %ecx
+ mov %esi, (%rdi)
+ mov %ecx, -0x4(%r9)
+ ret
+
+L(less_4bytes):
+ cmp $2, %dl
+ jb L(less_2bytes)
+ mov (%rsi), %si
+ mov -0x2(%rcx), %cx
+ mov %si, (%rdi)
+ mov %cx, -0x2(%r9)
+ ret
+
+L(less_2bytes):
+ cmp $1, %dl
+ jb L(less_1bytes)
+ mov (%rsi), %cl
+ mov %cl, (%rdi)
+L(less_1bytes):
+ ret
+
+L(512bytesormore):
+#ifdef SHARED_CACHE_SIZE_HALF
+ mov $SHARED_CACHE_SIZE_HALF, %r8
+#else
+ mov __x86_shared_cache_size_half(%rip), %r8
+#endif
+ cmp %r8, %rdx
+ jae L(preloop_large)
+ cmp $1024, %rdx
+ ja L(1024bytesormore)
+ vmovups (%rsi), %zmm0
+ vmovups 0x40(%rsi), %zmm1
+ vmovups 0x80(%rsi), %zmm2
+ vmovups 0xC0(%rsi), %zmm3
+ vmovups 0x100(%rsi), %zmm4
+ vmovups 0x140(%rsi), %zmm5
+ vmovups 0x180(%rsi), %zmm6
+ vmovups 0x1C0(%rsi), %zmm7
+ vmovups -0x200(%rcx), %zmm8
+ vmovups -0x1C0(%rcx), %zmm9
+ vmovups -0x180(%rcx), %zmm10
+ vmovups -0x140(%rcx), %zmm11
+ vmovups -0x100(%rcx), %zmm12
+ vmovups -0xC0(%rcx), %zmm13
+ vmovups -0x80(%rcx), %zmm14
+ vmovups -0x40(%rcx), %zmm15
+ vmovups %zmm0, (%rdi)
+ vmovups %zmm1, 0x40(%rdi)
+ vmovups %zmm2, 0x80(%rdi)
+ vmovups %zmm3, 0xC0(%rdi)
+ vmovups %zmm4, 0x100(%rdi)
+ vmovups %zmm5, 0x140(%rdi)
+ vmovups %zmm6, 0x180(%rdi)
+ vmovups %zmm7, 0x1C0(%rdi)
+ vmovups %zmm8, -0x200(%r9)
+ vmovups %zmm9, -0x1C0(%r9)
+ vmovups %zmm10, -0x180(%r9)
+ vmovups %zmm11, -0x140(%r9)
+ vmovups %zmm12, -0x100(%r9)
+ vmovups %zmm13, -0xC0(%r9)
+ vmovups %zmm14, -0x80(%r9)
+ vmovups %zmm15, -0x40(%r9)
+ ret
+
+#ifndef USE_AS_MEMMOVE
+L(1024bytesormore):
+ sub $0x200, %r9
+
+/* Loop with unaligned memory access. */
+L(gobble_512bytes_loop):
+ vmovups (%rsi), %zmm0
+ vmovups 0x40(%rsi), %zmm1
+ vmovups 0x80(%rsi), %zmm2
+ vmovups 0xC0(%rsi), %zmm3
+ vmovups 0x100(%rsi), %zmm4
+ vmovups 0x140(%rsi), %zmm5
+ vmovups 0x180(%rsi), %zmm6
+ vmovups 0x1C0(%rsi), %zmm7
+ add $0x200, %rsi
+ vmovups %zmm0, (%rdi)
+ vmovups %zmm1, 0x40(%rdi)
+ vmovups %zmm2, 0x80(%rdi)
+ vmovups %zmm3, 0xC0(%rdi)
+ vmovups %zmm4, 0x100(%rdi)
+ vmovups %zmm5, 0x140(%rdi)
+ vmovups %zmm6, 0x180(%rdi)
+ vmovups %zmm7, 0x1C0(%rdi)
+ add $0x200, %rdi
+ cmp %r9, %rdi
+ jb L(gobble_512bytes_loop)
+ vmovups -0x200(%rcx), %zmm0
+ vmovups -0x1C0(%rcx), %zmm1
+ vmovups -0x180(%rcx), %zmm2
+ vmovups -0x140(%rcx), %zmm3
+ vmovups -0x100(%rcx), %zmm4
+ vmovups -0xC0(%rcx), %zmm5
+ vmovups -0x80(%rcx), %zmm6
+ vmovups -0x40(%rcx), %zmm7
+ vmovups %zmm0, (%r9)
+ vmovups %zmm1, 0x40(%r9)
+ vmovups %zmm2, 0x80(%r9)
+ vmovups %zmm3, 0xC0(%r9)
+ vmovups %zmm4, 0x100(%r9)
+ vmovups %zmm5, 0x140(%r9)
+ vmovups %zmm6, 0x180(%r9)
+ vmovups %zmm7, 0x1C0(%r9)
+ ret
+
+/* Align destination for access with non-temporal stores in the loop. */
+L(preloop_large):
+ mov %rdi, %r8
+ and $-0x80, %rdi
+ add $0x80, %rdi
+ sub %rdi, %r8
+ vmovups (%rsi), %zmm0
+ vmovups 0x40(%rsi), %zmm1
+ vmovups %zmm0, (%rax)
+ vmovups %zmm1, 0x40(%rax)
+ sub %r8, %rsi
+ sub $0x100, %r9
+ prefetcht1 (%rsi)
+ prefetcht1 0x40(%rsi)
+ prefetcht1 0x80(%rsi)
+ prefetcht1 0xC0(%rsi)
+L(gobble_256bytes_nt_loop):
+ prefetcht1 0x100(%rsi)
+ prefetcht1 0x140(%rsi)
+ prefetcht1 0x180(%rsi)
+ prefetcht1 0x1C0(%rsi)
+ vmovups (%rsi), %zmm0
+ vmovups 0x40(%rsi), %zmm1
+ vmovups 0x80(%rsi), %zmm2
+ vmovups 0xC0(%rsi), %zmm3
+ add $0x100, %rsi
+ vmovntdq %zmm0, (%rdi)
+ vmovntdq %zmm1, 0x40(%rdi)
+ vmovntdq %zmm2, 0x80(%rdi)
+ vmovntdq %zmm3, 0xC0(%rdi)
+ add $0x100, %rdi
+ cmp %r9, %rdi
+ jb L(gobble_256bytes_nt_loop)
+ sfence
+ vmovups -0x100(%rcx), %zmm0
+ vmovups -0xC0(%rcx), %zmm1
+ vmovups -0x80(%rcx), %zmm2
+ vmovups -0x40(%rcx), %zmm3
+ vmovups %zmm0, (%r9)
+ vmovups %zmm1, 0x40(%r9)
+ vmovups %zmm2, 0x80(%r9)
+ vmovups %zmm3, 0xC0(%r9)
+ ret
+#else
+/* Memmove implementation. */
+L(1024bytesormore):
+ cmp %rsi, %rdi
+ ja L(1024bytesormore_bkw)
+ prefetcht1 (%rsi)
+ prefetcht1 0x40(%rsi)
+ prefetcht1 0x80(%rsi)
+ prefetcht1 0xC0(%rsi)
+
+/* Loop with unaligned memory access. */
+L(gobble_256bytes_loop):
+ vmovups (%rsi), %zmm0
+ prefetcht1 0x100(%rsi)
+ vmovups 0x40(%rsi), %zmm1
+ prefetcht1 0x140(%rsi)
+ vmovups 0x80(%rsi), %zmm2
+ prefetcht1 0x180(%rsi)
+ vmovups 0xC0(%rsi), %zmm3
+ prefetcht1 0x1C0(%rsi)
+ vmovups %zmm0, (%rdi)
+ vmovups %zmm1, 0x40(%rdi)
+ vmovups %zmm2, 0x80(%rdi)
+ vmovups %zmm3, 0xC0(%rdi)
+ sub $256, %rdx
+ add $256, %rsi
+ add $256, %rdi
+ cmp $256, %rdx
+ jae L(gobble_256bytes_loop)
+ jmp L(check)
+
+L(1024bytesormore_bkw):
+ prefetcht1 -0x100(%rcx)
+ prefetcht1 -0xC0(%rcx)
+ prefetcht1 -0x80(%rcx)
+ prefetcht1 -0x40(%rcx)
+
+/* Loop with unaligned memory access. */
+L(gobble_256bytes_loop_bkw):
+ vmovups -0x100(%rcx), %zmm0
+ prefetcht1 -0x200(%rcx)
+ vmovups -0xC0(%rcx), %zmm1
+ prefetcht1 -0x1C0(%rcx)
+ vmovups -0x80(%rcx), %zmm2
+ prefetcht1 -0x180(%rcx)
+ vmovups -0x40(%rcx), %zmm3
+ prefetcht1 -0x140(%rcx)
+ vmovups %zmm0, -0x100(%r9)
+ vmovups %zmm1, -0xC0(%r9)
+ vmovups %zmm2, -0x80(%r9)
+ vmovups %zmm3, -0x40(%r9)
+ sub $256, %rdx
+ sub $256, %rcx
+ sub $256, %r9
+ cmp $256, %rdx
+ jae L(gobble_256bytes_loop_bkw)
+ jmp L(check)
+
+L(preloop_large):
+ cmp %rsi, %rdi
+ ja L(preloop_large_bkw)
+ vmovups (%rsi), %zmm4
+ vmovups 0x40(%rsi), %zmm5
+
+/* Align destination for access with non-temporal stores in the loop. */
+ mov %rdi, %r8
+ and $-0x80, %rdi
+ add $0x80, %rdi
+ sub %rdi, %r8
+ sub %r8, %rsi
+ add %r8, %rdx
+ prefetcht1 (%rsi)
+ prefetcht1 0x40(%rsi)
+ prefetcht1 0x80(%rsi)
+ prefetcht1 0xC0(%rsi)
+L(gobble_256bytes_nt_loop):
+ vmovups (%rsi), %zmm0
+ prefetcht1 0x100(%rsi)
+ vmovups 0x40(%rsi), %zmm1
+ prefetcht1 0x140(%rsi)
+ vmovups 0x80(%rsi), %zmm2
+ prefetcht1 0x180(%rsi)
+ vmovups 0xC0(%rsi), %zmm3
+ prefetcht1 0x1C0(%rsi)
+ vmovntdq %zmm0, (%rdi)
+ vmovntdq %zmm1, 0x40(%rdi)
+ vmovntdq %zmm2, 0x80(%rdi)
+ vmovntdq %zmm3, 0xC0(%rdi)
+ sub $256, %rdx
+ add $256, %rsi
+ add $256, %rdi
+ cmp $256, %rdx
+ ja L(gobble_256bytes_nt_loop)
+ sfence
+ vmovups %zmm4, (%rax)
+ vmovups %zmm5, 0x40(%rax)
+ jmp L(check)
+
+L(preloop_large_bkw):
+ vmovups -0x80(%rcx), %zmm4
+ vmovups -0x40(%rcx), %zmm5
+
+/* Align end of destination for access with non-temporal stores. */
+ mov %r9, %r8
+ and $-0x80, %r9
+ sub %r9, %r8
+ sub %r8, %rcx
+ sub %r8, %rdx
+ add %r9, %r8
+ prefetcht1 -0x100(%rcx)
+ prefetcht1 -0xC0(%rcx)
+ prefetcht1 -0x80(%rcx)
+ prefetcht1 -0x40(%rcx)
+L(gobble_256bytes_nt_loop_bkw):
+ vmovups -0x100(%rcx), %zmm0
+ prefetcht1 -0x200(%rcx)
+ vmovups -0xC0(%rcx), %zmm1
+ prefetcht1 -0x1C0(%rcx)
+ vmovups -0x80(%rcx), %zmm2
+ prefetcht1 -0x180(%rcx)
+ vmovups -0x40(%rcx), %zmm3
+ prefetcht1 -0x140(%rcx)
+ vmovntdq %zmm0, -0x100(%r9)
+ vmovntdq %zmm1, -0xC0(%r9)
+ vmovntdq %zmm2, -0x80(%r9)
+ vmovntdq %zmm3, -0x40(%r9)
+ sub $256, %rdx
+ sub $256, %rcx
+ sub $256, %r9
+ cmp $256, %rdx
+ ja L(gobble_256bytes_nt_loop_bkw)
+ sfence
+ vmovups %zmm4, -0x80(%r8)
+ vmovups %zmm5, -0x40(%r8)
+ jmp L(check)
+#endif
+END (MEMCPY)
+#endif
diff --git a/sysdeps/x86_64/multiarch/memcpy.S b/sysdeps/x86_64/multiarch/memcpy.S
index 27fca29..64a1bcd 100644
--- a/sysdeps/x86_64/multiarch/memcpy.S
+++ b/sysdeps/x86_64/multiarch/memcpy.S
@@ -30,19 +30,27 @@
ENTRY(__new_memcpy)
.type __new_memcpy, @gnu_indirect_function
LOAD_RTLD_GLOBAL_RO_RDX
- leaq __memcpy_avx_unaligned(%rip), %rax
+#ifdef HAVE_AVX512_ASM_SUPPORT
+ HAS_ARCH_FEATURE (AVX512F_Usable)
+ jz 1f
+ HAS_ARCH_FEATURE (Prefer_No_VZEROUPPER)
+ jz 1f
+ leaq __memcpy_avx512_no_vzeroupper(%rip), %rax
+ ret
+#endif
+1: leaq __memcpy_avx_unaligned(%rip), %rax
HAS_ARCH_FEATURE (AVX_Fast_Unaligned_Load)
- jz 1f
+ jz 2f
ret
-1: leaq __memcpy_sse2(%rip), %rax
+2: leaq __memcpy_sse2(%rip), %rax
HAS_ARCH_FEATURE (Slow_BSF)
- jnz 2f
+ jnz 3f
leaq __memcpy_sse2_unaligned(%rip), %rax
ret
-2: HAS_CPU_FEATURE (SSSE3)
- jz 3f
+3: HAS_CPU_FEATURE (SSSE3)
+ jz 4f
leaq __memcpy_ssse3(%rip), %rax
-3: ret
+4: ret
END(__new_memcpy)
# undef ENTRY
diff --git a/sysdeps/x86_64/multiarch/memcpy_chk.S b/sysdeps/x86_64/multiarch/memcpy_chk.S
index 6476c62..a0d56d4 100644
--- a/sysdeps/x86_64/multiarch/memcpy_chk.S
+++ b/sysdeps/x86_64/multiarch/memcpy_chk.S
@@ -30,7 +30,15 @@
ENTRY(__memcpy_chk)
.type __memcpy_chk, @gnu_indirect_function
LOAD_RTLD_GLOBAL_RO_RDX
- leaq __memcpy_chk_sse2(%rip), %rax
+#ifdef HAVE_AVX512_ASM_SUPPORT
+ HAS_ARCH_FEATURE (AVX512F_Usable)
+ jz 1f
+# HAS_ARCH_FEATURE (Prefer_No_VZEROUPPER)
+# jz 1f
+ leaq __memcpy_avx512_no_vzeroupper(%rip), %rax
+ ret
+#endif
+1: leaq __memcpy_chk_sse2(%rip), %rax
HAS_CPU_FEATURE (SSSE3)
jz 2f
leaq __memcpy_chk_ssse3(%rip), %rax
diff --git a/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S b/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S
new file mode 100644
index 0000000..518d1fe
--- /dev/null
+++ b/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S
@@ -0,0 +1,22 @@
+/* memmove optimized with AVX512 for KNL hardware.
+ Copyright (C) 2016 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
+ <http://www.gnu.org/licenses/>. */
+
+#define USE_AS_MEMMOVE
+#define MEMCPY __memmove_avx512_no_vzeroupper
+#define MEMCPY_CHK __memmove_chk_avx512_no_vzeroupper
+#include "memcpy-avx512-no-vzeroupper.S"
diff --git a/sysdeps/x86_64/multiarch/memmove.c b/sysdeps/x86_64/multiarch/memmove.c
index e844531..8da5640 100644
--- a/sysdeps/x86_64/multiarch/memmove.c
+++ b/sysdeps/x86_64/multiarch/memmove.c
@@ -36,6 +36,9 @@ extern __typeof (__redirect_memmove) __memmove_sse2 attribute_hidden;
extern __typeof (__redirect_memmove) __memmove_ssse3 attribute_hidden;
extern __typeof (__redirect_memmove) __memmove_ssse3_back attribute_hidden;
extern __typeof (__redirect_memmove) __memmove_avx_unaligned attribute_hidden;
+# ifdef HAVE_AVX512_ASM_SUPPORT
+ extern __typeof (__redirect_memmove) __memmove_avx512_no_vzeroupper attribute_hidden;
+# endif
#endif
@@ -49,12 +52,18 @@ extern __typeof (__redirect_memmove) __memmove_avx_unaligned attribute_hidden;
ifunc symbol properly. */
extern __typeof (__redirect_memmove) __libc_memmove;
libc_ifunc (__libc_memmove,
- HAS_ARCH_FEATURE (AVX_Fast_Unaligned_Load)
+#ifdef HAVE_AVX512_ASM_SUPPORT
+ HAS_ARCH_FEATURE (AVX512F_Usable)
+ && HAS_ARCH_FEATURE (Prefer_No_VZEROUPPER)
+ ? __memmove_avx512_no_vzeroupper
+ :
+#endif
+ (HAS_ARCH_FEATURE (AVX_Fast_Unaligned_Load)
? __memmove_avx_unaligned
: (HAS_CPU_FEATURE (SSSE3)
? (HAS_ARCH_FEATURE (Fast_Copy_Backward)
? __memmove_ssse3_back : __memmove_ssse3)
- : __memmove_sse2));
+ : __memmove_sse2)));
strong_alias (__libc_memmove, memmove)
diff --git a/sysdeps/x86_64/multiarch/memmove_chk.c b/sysdeps/x86_64/multiarch/memmove_chk.c
index 60ed98f..f64da63 100644
--- a/sysdeps/x86_64/multiarch/memmove_chk.c
+++ b/sysdeps/x86_64/multiarch/memmove_chk.c
@@ -26,10 +26,19 @@ extern __typeof (__memmove_chk) __memmove_chk_sse2 attribute_hidden;
extern __typeof (__memmove_chk) __memmove_chk_ssse3 attribute_hidden;
extern __typeof (__memmove_chk) __memmove_chk_ssse3_back attribute_hidden;
extern __typeof (__memmove_chk) __memmove_chk_avx_unaligned attribute_hidden;
+# ifdef HAVE_AVX512_ASM_SUPPORT
+ extern __typeof (__memmove_chk) __memmove_chk_avx512_no_vzeroupper attribute_hidden;
+# endif
#include "debug/memmove_chk.c"
libc_ifunc (__memmove_chk,
+#ifdef HAVE_AVX512_ASM_SUPPORT
+ HAS_ARCH_FEATURE (AVX512F_Usable)
+ && HAS_ARCH_FEATURE (Prefer_No_VZEROUPPER)
+ ? __memmove_chk_avx512_no_vzeroupper
+ :
+#endif
HAS_ARCH_FEATURE (AVX_Fast_Unaligned_Load) ? __memmove_chk_avx_unaligned :
(HAS_CPU_FEATURE (SSSE3)
? (HAS_ARCH_FEATURE (Fast_Copy_Backward)
diff --git a/sysdeps/x86_64/multiarch/mempcpy-avx512-no-vzeroupper.S b/sysdeps/x86_64/multiarch/mempcpy-avx512-no-vzeroupper.S
new file mode 100644
index 0000000..ccffb31
--- /dev/null
+++ b/sysdeps/x86_64/multiarch/mempcpy-avx512-no-vzeroupper.S
@@ -0,0 +1,22 @@
+/* mempcpy optimized with AVX512 for KNL hardware.
+ Copyright (C) 2016 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
+ <http://www.gnu.org/licenses/>. */
+
+#define USE_AS_MEMPCPY
+#define MEMCPY __mempcpy_avx512_no_vzeroupper
+#define MEMCPY_CHK __mempcpy_chk_avx512_no_vzeroupper
+#include "memcpy-avx512-no-vzeroupper.S"
diff --git a/sysdeps/x86_64/multiarch/mempcpy.S b/sysdeps/x86_64/multiarch/mempcpy.S
index 96ffb28..ed78623 100644
--- a/sysdeps/x86_64/multiarch/mempcpy.S
+++ b/sysdeps/x86_64/multiarch/mempcpy.S
@@ -28,7 +28,15 @@
ENTRY(__mempcpy)
.type __mempcpy, @gnu_indirect_function
LOAD_RTLD_GLOBAL_RO_RDX
- leaq __mempcpy_sse2(%rip), %rax
+#ifdef HAVE_AVX512_ASM_SUPPORT
+ HAS_ARCH_FEATURE (AVX512F_Usable)
+ jz 1f
+ HAS_ARCH_FEATURE (Prefer_No_VZEROUPPER)
+ jz 1f
+ leaq __mempcpy_avx512_no_vzeroupper(%rip), %rax
+ ret
+#endif
+1: leaq __mempcpy_sse2(%rip), %rax
HAS_CPU_FEATURE (SSSE3)
jz 2f
leaq __mempcpy_ssse3(%rip), %rax
diff --git a/sysdeps/x86_64/multiarch/mempcpy_chk.S b/sysdeps/x86_64/multiarch/mempcpy_chk.S
index ae7a765..6e8a89d 100644
--- a/sysdeps/x86_64/multiarch/mempcpy_chk.S
+++ b/sysdeps/x86_64/multiarch/mempcpy_chk.S
@@ -30,7 +30,15 @@
ENTRY(__mempcpy_chk)
.type __mempcpy_chk, @gnu_indirect_function
LOAD_RTLD_GLOBAL_RO_RDX
- leaq __mempcpy_chk_sse2(%rip), %rax
+#ifdef HAVE_AVX512_ASM_SUPPORT
+ HAS_ARCH_FEATURE (AVX512F_Usable)
+ jz 1f
+ HAS_ARCH_FEATURE (Prefer_No_VZEROUPPER)
+ jz 1f
+ leaq __mempcpy_chk_avx512_no_vzeroupper(%rip), %rax
+ ret
+#endif
+1: leaq __mempcpy_chk_sse2(%rip), %rax
HAS_CPU_FEATURE (SSSE3)
jz 2f
leaq __mempcpy_chk_ssse3(%rip), %rax

62
nsswitch.conf Normal file
View File

@ -0,0 +1,62 @@
#
# /etc/nsswitch.conf
#
# An example Name Service Switch config file. This file should be
# sorted with the most-used services at the beginning.
#
# The entry '[NOTFOUND=return]' means that the search for an
# entry should stop if the search in the previous entry turned
# up nothing. Note that if the search failed due to some other reason
# (like no NIS server responding) then the search continues with the
# next entry.
#
# Valid entries include:
#
# nisplus Use NIS+ (NIS version 3)
# nis Use NIS (NIS version 2), also called YP
# dns Use DNS (Domain Name Service)
# files Use the local files
# db Use the local database (.db) files
# compat Use NIS on compat mode
# hesiod Use Hesiod for user lookups
# [NOTFOUND=return] Stop searching if not found so far
#
# To use db, put the "db" in front of "files" for entries you want to be
# looked up first in the databases
#
# Example:
#passwd: db files nisplus nis
#shadow: db files nisplus nis
#group: db files nisplus nis
passwd: files sss
shadow: files sss
group: files sss
#hosts: db files nisplus nis dns
hosts: files dns
# Example - obey only what nisplus tells us...
#services: nisplus [NOTFOUND=return] files
#networks: nisplus [NOTFOUND=return] files
#protocols: nisplus [NOTFOUND=return] files
#rpc: nisplus [NOTFOUND=return] files
#ethers: nisplus [NOTFOUND=return] files
#netmasks: nisplus [NOTFOUND=return] files
bootparams: nisplus [NOTFOUND=return] files
ethers: files
netmasks: files
networks: files
protocols: files
rpc: files
services: files sss
netgroup: nisplus sss
publickey: nisplus
automount: files nisplus
aliases: files nisplus

View File

@ -3,8 +3,8 @@
export QUILT_PATCHES=$PWD
# Extract source file name from sources file,
# and assume it's the same name as the directory.
source=`awk -F '[() ]+' '/^[A-Z0-9]+ /{print $2}; /^[0-9a-f]+ /{print $2}' sources`
srcdir=${source%.tar.xz}
source=`cat sources | sed -e 's,^.* ,,g'`
srcdir=${source%.tar.gz}
if [ "$1" == "-f" ] && [ -d "$srcdir" ]; then
echo Cleaning up $srcdir
rm -rf $srcdir
@ -14,7 +14,7 @@ if [ -d "$srcdir" ]; then
echo "ERROR: Source directory $srcdir already exists. Use -f to force cleanup step."
exit 1
fi
tar Jxvf $source
tar zxvf $source
echo "Entering $srcdir"
pushd $srcdir
# Apply all patches.

41
series Normal file
View File

@ -0,0 +1,41 @@
glibc-fedora-nscd.patch -p1 --fuzz=0
glibc-fedora-ldd.patch -p1 --fuzz=0
glibc-fedora-ppc-unwind.patch -p1 --fuzz=0
glibc-rh825061.patch -p1 --fuzz=0
glibc-arm-hardfloat-3.patch -p1 --fuzz=0
glibc-rh697421.patch -p1 --fuzz=0
glibc-fedora-include-bits-ldbl.patch -p1 --fuzz=0
glibc-fedora-linux-tcsetattr.patch -p1 --fuzz=0
glibc-rh741105.patch -p1 --fuzz=0
glibc-fedora-nptl-linklibc.patch -p1 --fuzz=0
glibc-fedora-localedef.patch -p1 --fuzz=0
glibc-fedora-i386-tls-direct-seg-refs.patch -p1 --fuzz=0
glibc-fedora-nis-rh188246.patch -p1 --fuzz=0
glibc-fedora-manual-dircategory.patch -p1 --fuzz=0
glibc-rh827510.patch -p1 --fuzz=0
glibc-fedora-locarchive.patch -p1 --fuzz=0
glibc-fedora-streams-rh436349.patch -p1 --fuzz=0
glibc-rh819430.patch -p1 --fuzz=0
glibc-fedora-localedata-rh61908.patch -p1 --fuzz=0
glibc-fedora-uname-getrlimit.patch -p1 --fuzz=0
glibc-fedora-__libc_multiple_libcs.patch -p1 --fuzz=0
glibc-fedora-elf-ORIGIN.patch -p1 --fuzz=0
glibc-rh952799.patch -p1 --fuzz=0
glibc-rh1009145.patch -p1 --fuzz=0
glibc-rh1013801.patch -p1 --fuzz=0
glibc-rh1070416.patch -p1 --fuzz=0
glibc-nscd-sysconfig.patch -p1 --fuzz=0
glibc-aarch64-tls-fixes.patch -p1 --fuzz=0
glibc-aarch64-workaround-nzcv-clobber-in-tlsdesc.patch -p1 --fuzz=0
glibc-disable-rwlock-elision.patch -p1 --fuzz=0
glibc-cs-path.patch -p1 --fuzz=0
glibc-bench-build.patch -p1 --fuzz=0
glibc-res-hconf-gcc5.patch -p1 --fuzz=0
glibc-ld-ctype-gcc5.patch -p1 --fuzz=0
glibc-gethnamaddr-gcc5.patch -p1 --fuzz=0
glibc-dns-host-gcc5.patch -p1 --fuzz=0
glibc-bug-regex-gcc5.patch -p1 --fuzz=0
glibc-c-utf8-locale.patch -p1 --fuzz=0
glibc-nsswitch-Add-group-merging-support.patch -p1 --fuzz=0
glibc-pthread-barrier.patch -p1 --fuzz=0
mem-avx512-2016-v4.patch

View File

@ -1 +1 @@
SHA512 (glibc-2.30.9000-100-g1a6566094d.tar.xz) = e6054a8f1367fde262f023c76f7eaf5ce588613c4894b8d577c7e1c3159a2dfcefb7c60e301340b823cd8e6d2f8d264d7da83e61034b9180836d392d5db4c5ba
f7b4240a89702c8f04967310b8384fec glibc-2.22-621-g90c400b.tar.gz

97
sync-upstream.sh Executable file
View File

@ -0,0 +1,97 @@
#!/bin/sh
# Given a git source repo, generate a tarball from the desired branch, modify
# the spec file and upload it to lookaside cache if the tarball unpacks and
# gets patched cleanly.
#
# Usage:
#
# 1. Invoke the script as follows:
#
# ./sync-upstream.sh upstream-repo
#
# where upstream-repo is the path to the synced upstream git repo.
#
# 2. Watch the script run. If it proceeds to building the package, then
# everything seems good and you just need to test the build after it
# is complete. If it exits before the build (you'll know if you read
# the output of the script) then manual intervention is required to
# complete the sync. This will typically happen when a patch fails
# to apply on the new sources.
set -e
# We want to sync from master by default. Change this if you want to sync from
# another branch.
branch=master
# We can't do anything without an upstream repo
if [ $# -ne 1 ]; then
echo "Usage: $0 <path-to-upstream-repo>" 1>&2
exit 1
fi
upstream=$1
srcdir=$(git --git-dir=$upstream/.git describe $branch)
cursrc=$(sed -ne 's/^%define glibcsrcdir \(.*\)/\1/p' glibc.spec)
# Upstream has not moved forward since the last sync.
# TODO: Some time in the future, we might want to only sync when upstream has
# advanced more than a certain number of commits, say, 42.
if [ "$cursrc" = "$srcdir" ]; then
echo "+ Already in sync with upstream."
exit 0
fi
# Generate and gzip the tarball from the desired branch of the repository.
echo "+ Generating tarball."
git --git-dir="$upstream/.git" archive --prefix="$srcdir/" "$branch" \
> "$srcdir.tar"
gzip -9 "$srcdir.tar"
echo "+ Created $srcdir.tar.gz"
# Our changelog header
cldate=$(date +'%a %b %d %Y')
clname=$(git config --get user.name)
clemail=$(git config --get user.email | sed 's/@/\\@/')
# Getting our version and release number from the spec file.
nv=$(perl -ne 's/^%define glibcversion (.+)/printf("%s-", $1)/e;' \
-e 's/^%define glibcrelease ([0-9]+).*/printf("%d\n", $1 + 1)/e;' \
glibc.spec)
# Our changelog entry.
changelog="* $cldate $clname <$clemail> - $nv\n- Auto-sync with upstream $branch.\n"
# Change the glibcsrcdir variable, bump up the release number and add an extra
# entry to the changelog.
echo "+ Updating spec file."
perl -pi \
-e "s/^(%define glibcsrcdir ).+/\$1$srcdir/;
s/^(%define glibcrelease )(\d+)/print(\$1); print(\$2 + 1);'';/e;
s/^(%changelog)$/\$1\n$changelog/" \
glibc.spec
function prep_failed {
# fedpkg prep failed.
if [ $? -ne 0 ]; then
echo "+ Source prep failed."
echo "+ Check the output in $tmpfile and fix things before committing."
false
fi
}
echo "+ Testing if fedpkg prep works."
tmpfile=$(mktemp fedpkg-prep.out-XXXX)
trap prep_failed EXIT
fedpkg prep > "$tmpfile" 2>&1
# Remove mess created by fedpkg prep
rm -f "$tmpfile"
rm -rf "$srcdir"
echo "+ Source prep is clean, so we're good to go."
fedpkg new-sources "$srcdir.tar.gz"
git commit -a -m "Auto-sync with upstream $branch."
fedpkg push
fedpkg build
echo "+ Done!"

View File

@ -5,7 +5,7 @@ Origin: <Source repo(s) where it came from or keyword "PATCH" if this is simply
Bug-RHEL: <Rhel bug #'s, comma separated e.g. #XXX, #YYY, #ZZZ>
Bug-Fedora: <Fedora bug #'s, comma separated e.g. #XXX, #YYY, #ZZZ>
Bug-Upstream: <Upstream bug#'s, comma separated e.g. #XXX, #YYY, #ZZZ>
Upstream status: <[Patchwork URL|libc-alpha URL|not-needed|not-submitted|committed] for each commit>
# <Additional descriptive text follows 'Upstream status:' line>
Upstream status: <[Patchwork URL|not-needed|not-submitted|committed] for each commit>
# <Additional descriptive text in comment block>
<If upstream status == committed then a copy of the upstream commit log follows>
<Patch>