Browse Source

dubhe: glibc: Update glibc version to 2.35

Updated glibc to the newer 2.35 version.

Signed-off-by: Jun Yuan Tan <junyuan.tan@starfivetech.com>
Jun Yuan Tan 2 years ago
parent
commit
a9bc735026
68 changed files with 9297 additions and 0 deletions
  1. 52 0
      recipes-core/glibc/cross-localedef-native_2.35.bb
  2. 12 0
      recipes-core/glibc/glibc-collateral.inc
  3. 25 0
      recipes-core/glibc/glibc-common.inc
  4. 20 0
      recipes-core/glibc/glibc-ld.inc
  5. 103 0
      recipes-core/glibc/glibc-locale.inc
  6. 1 0
      recipes-core/glibc/glibc-locale_2.35.bb
  7. 16 0
      recipes-core/glibc/glibc-mtrace.inc
  8. 1 0
      recipes-core/glibc/glibc-mtrace_2.35.bb
  9. 16 0
      recipes-core/glibc/glibc-package.inc
  10. 23 0
      recipes-core/glibc/glibc-scripts.inc
  11. 1 0
      recipes-core/glibc/glibc-scripts_2.35.bb
  12. 32 0
      recipes-core/glibc/glibc-tests.inc
  13. 35 0
      recipes-core/glibc/glibc-testsuite_2.35.bb
  14. 8 0
      recipes-core/glibc/glibc-version.inc
  15. 52 0
      recipes-core/glibc/glibc.inc
  16. 59 0
      recipes-core/glibc/glibc/0001-Add-array_length-support.patch
  17. 43 0
      recipes-core/glibc/glibc/0001-CVE-2021-38604.patch
  18. 79 0
      recipes-core/glibc/glibc/0001-fix-create-thread-failed-in-unprivileged-process-BZ-.patch
  19. 1130 0
      recipes-core/glibc/glibc/0001-localedef-Add-hardlink-resolver-from-util-linux.patch
  20. 150 0
      recipes-core/glibc/glibc/0002-CVE-2021-38604.patch
  21. 238 0
      recipes-core/glibc/glibc/0002-localedef-fix-ups-hardlink-to-make-it-compile.patch
  22. 65 0
      recipes-core/glibc/glibc/0003-nativesdk-glibc-Look-for-host-system-ld.so.cache-as-.patch
  23. 46 0
      recipes-core/glibc/glibc/0004-nativesdk-glibc-Fix-buffer-overrun-with-a-relocated-.patch
  24. 153 0
      recipes-core/glibc/glibc/0005-nativesdk-glibc-Raise-the-size-of-arrays-containing-.patch
  25. 39 0
      recipes-core/glibc/glibc/0006-nativesdk-glibc-Allow-64-bit-atomics-for-x86.patch
  26. 100 0
      recipes-core/glibc/glibc/0007-nativesdk-glibc-Make-relocatable-install-for-locales.patch
  27. 32 0
      recipes-core/glibc/glibc/0008-nativesdk-glibc-Fall-back-to-faccessat-on-faccess2-r.patch
  28. 1581 0
      recipes-core/glibc/glibc/0009-fsl-e500-e5500-e6500-603e-fsqrt-implementation.patch
  29. 205 0
      recipes-core/glibc/glibc/0010-ppc-sqrt-Fix-undefined-reference-to-__sqrt_finite.patch
  30. 384 0
      recipes-core/glibc/glibc/0011-__ieee754_sqrt-f-are-now-inline-functions-and-call-o.patch
  31. 58 0
      recipes-core/glibc/glibc/0012-Quote-from-bug-1443-which-explains-what-the-patch-do.patch
  32. 33 0
      recipes-core/glibc/glibc/0013-eglibc-run-libm-err-tab.pl-with-specific-dirs-in-S.patch
  33. 58 0
      recipes-core/glibc/glibc/0014-__ieee754_sqrt-f-are-now-inline-functions-and-call-o.patch
  34. 39 0
      recipes-core/glibc/glibc/0015-sysdeps-gnu-configure.ac-handle-correctly-libc_cv_ro.patch
  35. 260 0
      recipes-core/glibc/glibc/0016-yes-within-the-path-sets-wrong-config-variables.patch
  36. 34 0
      recipes-core/glibc/glibc/0017-timezone-re-written-tzselect-as-posix-sh.patch
  37. 72 0
      recipes-core/glibc/glibc/0018-Remove-bash-dependency-for-nscd-init-script.patch
  38. 616 0
      recipes-core/glibc/glibc/0019-eglibc-Cross-building-and-testing-instructions.patch
  39. 97 0
      recipes-core/glibc/glibc/0020-eglibc-Help-bootstrap-cross-toolchain.patch
  40. 53 0
      recipes-core/glibc/glibc/0021-eglibc-Resolve-__fpscr_values-on-SH4.patch
  41. 560 0
      recipes-core/glibc/glibc/0022-eglibc-Forward-port-cross-locale-generation-support.patch
  42. 80 0
      recipes-core/glibc/glibc/0024-localedef-add-to-archive-uses-a-hard-coded-locale-pa.patch
  43. 53 0
      recipes-core/glibc/glibc/0025-elf-dl-deps.c-Make-_dl_build_local_scope-breadth-fir.patch
  44. 31 0
      recipes-core/glibc/glibc/0026-intl-Emit-no-lines-in-bison-generated-files.patch
  45. 53 0
      recipes-core/glibc/glibc/0027-locale-prevent-maybe-uninitialized-errors-with-Os-BZ.patch
  46. 29 0
      recipes-core/glibc/glibc/0028-readlib-Add-OECORE_KNOWN_INTERPRETER_NAMES-to-known-.patch
  47. 67 0
      recipes-core/glibc/glibc/0029-wordsize.h-Unify-the-header-between-arm-and-aarch64.patch
  48. 48 0
      recipes-core/glibc/glibc/0030-powerpc-Do-not-ask-compiler-for-finding-arch.patch
  49. 184 0
      recipes-core/glibc/glibc/CVE-2021-43396.patch
  50. 80 0
      recipes-core/glibc/glibc/check-test-wrapper
  51. 1 0
      recipes-core/glibc/glibc/etc/ld.so.conf
  52. 11 0
      recipes-core/glibc/glibc/generate-supported.mk
  53. 177 0
      recipes-core/glibc/glibc/makedbs.sh
  54. 131 0
      recipes-core/glibc/glibc_2.35.bb
  55. 331 0
      recipes-core/glibc/ldconfig-native-2.12.1/32and64bit.patch
  56. 8 0
      recipes-core/glibc/ldconfig-native-2.12.1/README
  57. 116 0
      recipes-core/glibc/ldconfig-native-2.12.1/add-64-bit-flag-for-ELF64-entries.patch
  58. 79 0
      recipes-core/glibc/ldconfig-native-2.12.1/add-riscv-support.patch
  59. 454 0
      recipes-core/glibc/ldconfig-native-2.12.1/endian-ness_handling.patch
  60. 47 0
      recipes-core/glibc/ldconfig-native-2.12.1/endian-ness_handling_fix.patch
  61. 113 0
      recipes-core/glibc/ldconfig-native-2.12.1/endianess-header.patch
  62. 24 0
      recipes-core/glibc/ldconfig-native-2.12.1/flag_fix.patch
  63. 37 0
      recipes-core/glibc/ldconfig-native-2.12.1/ldconfig-default-to-all-multilib-dirs.patch
  64. BIN
      recipes-core/glibc/ldconfig-native-2.12.1/ldconfig-native-2.12.1.tar.bz2
  65. 471 0
      recipes-core/glibc/ldconfig-native-2.12.1/ldconfig.patch
  66. 36 0
      recipes-core/glibc/ldconfig-native-2.12.1/ldconfig_aux-cache_path_fix.patch
  67. 19 0
      recipes-core/glibc/ldconfig-native-2.12.1/no-aux-cache.patch
  68. 36 0
      recipes-core/glibc/ldconfig-native_2.12.1.bb

+ 52 - 0
recipes-core/glibc/cross-localedef-native_2.35.bb

@@ -0,0 +1,52 @@
+SUMMARY = "Cross locale generation tool for glibc"
+HOMEPAGE = "http://www.gnu.org/software/libc/libc.html"
+SECTION = "libs"
+LICENSE = "LGPL-2.1"
+
+LIC_FILES_CHKSUM = "file://LICENSES;md5=1541fd8f5e8f1579512bf05f533371ba \
+      file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \
+      file://posix/rxspencer/COPYRIGHT;md5=dc5485bb394a13b2332ec1c785f5d83a \
+      file://COPYING.LIB;md5=4fbd65380cdd255951079008b364516c"
+
+require glibc-version.inc
+
+# Tell autotools that we're working in the localedef directory
+#
+AUTOTOOLS_SCRIPT_PATH = "${S}/localedef"
+
+inherit autotools
+inherit native
+
+FILESEXTRAPATHS =. "${FILE_DIRNAME}/${PN}:${FILE_DIRNAME}/glibc:"
+
+SRC_URI = "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \
+           git://github.com/kraj/localedef;branch=master;name=localedef;destsuffix=git/localedef;protocol=https \
+           \
+           file://0001-localedef-Add-hardlink-resolver-from-util-linux.patch \
+           file://0002-localedef-fix-ups-hardlink-to-make-it-compile.patch \
+           \
+           file://0017-timezone-re-written-tzselect-as-posix-sh.patch \
+           file://0018-Remove-bash-dependency-for-nscd-init-script.patch \
+           file://0019-eglibc-Cross-building-and-testing-instructions.patch \
+           file://0020-eglibc-Help-bootstrap-cross-toolchain.patch \
+           file://0021-eglibc-Resolve-__fpscr_values-on-SH4.patch \
+           file://0022-eglibc-Forward-port-cross-locale-generation-support.patch \
+           file://0024-localedef-add-to-archive-uses-a-hard-coded-locale-pa.patch \
+           file://0001-Add-array_length-support.patch \
+"
+# Makes for a rather long rev (22 characters), but...
+#
+SRCREV_FORMAT = "glibc_localedef"
+
+S = "${WORKDIR}/git"
+
+EXTRA_OECONF = "--with-glibc=${S}"
+CFLAGS += "-fgnu89-inline -std=gnu99 -DIS_IN\(x\)='0'"
+
+
+
+do_install() {
+	install -d ${D}${bindir}
+	install -m 0755 ${B}/localedef ${D}${bindir}/cross-localedef
+	install -m 0755 ${B}/cross-localedef-hardlink ${D}${bindir}/cross-localedef-hardlink
+}

+ 12 - 0
recipes-core/glibc/glibc-collateral.inc

@@ -0,0 +1,12 @@
+require glibc-common.inc
+
+LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0-only;md5=801f80980d171dd6425610833a22dbe6 \
+                     file://${COMMON_LICENSE_DIR}/LGPL-2.1-only;md5=1a6d268fd218675ffea8be556788b780"
+
+deltask do_fetch
+deltask do_unpack
+deltask do_patch
+do_configure[noexec] = "1"
+do_compile[noexec] = "1"
+
+do_install[depends] += "virtual/${MLPREFIX}libc:do_stash_locale"

+ 25 - 0
recipes-core/glibc/glibc-common.inc

@@ -0,0 +1,25 @@
+SUMMARY = "GLIBC (GNU C Library)"
+DESCRIPTION = "The GNU C Library is used as the system C library in most systems with the Linux kernel."
+HOMEPAGE = "http://www.gnu.org/software/libc/libc.html"
+SECTION = "libs"
+LICENSE = "GPLv2 & LGPLv2.1"
+
+LIC_FILES_CHKSUM ?= "file://LICENSES;md5=1541fd8f5e8f1579512bf05f533371ba \
+      file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \
+      file://posix/rxspencer/COPYRIGHT;md5=dc5485bb394a13b2332ec1c785f5d83a \
+      file://COPYING.LIB;md5=4fbd65380cdd255951079008b364516c"
+
+CVE_PRODUCT = "glibc"
+
+INHIBIT_DEFAULT_DEPS = "1"
+
+ARM_INSTRUCTION_SET:armv4 = "arm"
+ARM_INSTRUCTION_SET:armv5 = "arm"
+ARM_INSTRUCTION_SET:armv6 = "arm"
+#
+# We will skip parsing glibc when target system C library selection is not glibc
+# this helps in easing out parsing for non-glibc system libraries
+#
+COMPATIBLE_HOST:libc-musl:class-target = "null"
+
+PV = "2.35"

+ 20 - 0
recipes-core/glibc/glibc-ld.inc

@@ -0,0 +1,20 @@
+inherit linuxloader
+
+GLIBC_GETLOADER = "${@get_linuxloader(d)}"
+
+def glibc_dl_info(d):
+    infos = {'ldconfig':set(), 'lddrewrite':set()}
+
+    loaders = all_multilib_tune_values(d, "GLIBC_GETLOADER").split()
+    for loader in loaders:
+        infos['ldconfig'].add('{"' + loader + '",' + "FLAG_ELF_LIBC6" + ' }')
+        infos['lddrewrite'].add(loader)
+
+    infos['ldconfig'] = ','.join(sorted(infos['ldconfig']))
+    infos['lddrewrite'] = ' '.join(sorted(infos['lddrewrite']))
+    return infos
+
+EGLIBC_KNOWN_INTERPRETER_NAMES = "${@glibc_dl_info(d)['ldconfig']}"
+RTLDLIST = "${@glibc_dl_info(d)['lddrewrite']}"
+RTLDLIST:class-nativesdk = "${base_libdir}/${@bb.utils.contains('SDK_ARCH', 'x86_64', 'ld-linux-x86-64.so.2', 'ld-linux.so.2', d)}"
+glibc_dl_info[vardepsexclude] = "OVERRIDES"

+ 103 - 0
recipes-core/glibc/glibc-locale.inc

@@ -0,0 +1,103 @@
+require glibc-collateral.inc
+
+SUMMARY = "Locale data from glibc"
+
+BPN = "glibc"
+LOCALEBASEPN = "${MLPREFIX}glibc"
+
+# glibc-collateral.inc inhibits all default deps, but do_package needs objcopy
+# ERROR: objcopy failed with exit code 127 (cmd was 'i586-webos-linux-objcopy' --only-keep-debug 'glibc-locale/2.17-r0/package/usr/lib/gconv/IBM1166.so' 'glibc-locale/2.17-r0/package/usr/lib/gconv/.debug/IBM1166.so')
+# ERROR: Function failed: split_and_strip_files
+BINUTILSDEP = "virtual/${MLPREFIX}${TARGET_PREFIX}binutils:do_populate_sysroot"
+BINUTILSDEP:class-nativesdk = "virtual/${TARGET_PREFIX}binutils-crosssdk:do_populate_sysroot"
+do_package[depends] += "${BINUTILSDEP}"
+
+DEPENDS += "virtual/libc"
+
+# Binary locales are generated at build time if ENABLE_BINARY_LOCALE_GENERATION
+# is set. The idea is to avoid running localedef on the target (at first boot)
+# to decrease initial boot time and avoid localedef being killed by the OOM
+# killer which used to effectively break i18n on machines with < 128MB RAM.
+
+# default to disabled
+ENABLE_BINARY_LOCALE_GENERATION ?= "0"
+ENABLE_BINARY_LOCALE_GENERATION:pn-nativesdk-glibc-locale = "1"
+
+#enable locale generation on these arches
+# BINARY_LOCALE_ARCHES is a space separated list of regular expressions
+BINARY_LOCALE_ARCHES ?= "arc arm.* aarch64 i[3-6]86 x86_64 powerpc mips mips64 riscv32 riscv64"
+
+# set "1" to use cross-localedef for locale generation
+# set "0" for qemu emulation of native localedef for locale generation
+LOCALE_GENERATION_WITH_CROSS-LOCALEDEF = "1"
+
+PROVIDES = "virtual/libc-locale"
+
+PACKAGES = "localedef ${PN}-dbg"
+
+PACKAGES_DYNAMIC = "^locale-base-.* \
+                    ^glibc-gconv-.* ^glibc-charmap-.* ^glibc-localedata-.* ^glibc-binary-localedata-.* \
+                    ^${MLPREFIX}glibc-gconv$"
+
+# Create a glibc-binaries package
+ALLOW_EMPTY:${BPN}-binaries = "1"
+PACKAGES += "${BPN}-binaries"
+RRECOMMENDS:${BPN}-binaries =  "${@" ".join([p for p in d.getVar('PACKAGES').split() if p.find("glibc-binary") != -1])}"
+
+# Create a glibc-charmaps package
+ALLOW_EMPTY:${BPN}-charmaps = "1"
+PACKAGES += "${BPN}-charmaps"
+RRECOMMENDS:${BPN}-charmaps =  "${@" ".join([p for p in d.getVar('PACKAGES').split() if p.find("glibc-charmap") != -1])}"
+
+# Create a glibc-gconvs package
+ALLOW_EMPTY:${BPN}-gconvs = "1"
+PACKAGES += "${BPN}-gconvs"
+RRECOMMENDS:${BPN}-gconvs =  "${@" ".join([p for p in d.getVar('PACKAGES').split() if p.find("glibc-gconv") != -1])}"
+
+# Create a glibc-localedatas package
+ALLOW_EMPTY:${BPN}-localedatas = "1"
+PACKAGES += "${BPN}-localedatas"
+RRECOMMENDS:${BPN}-localedatas =  "${@" ".join([p for p in d.getVar('PACKAGES').split() if p.find("glibc-localedata") != -1])}"
+
+DESCRIPTION:localedef = "glibc: compile locale definition files"
+
+# glibc-gconv is dynamically added into PACKAGES, thus
+# FILES:glibc-gconv will not be automatically extended in multilib.
+# Explicitly add ${MLPREFIX} for FILES:glibc-gconv.
+FILES:${MLPREFIX}glibc-gconv = "${libdir}/gconv/*"
+FILES:localedef = "${bindir}/localedef"
+
+LOCALETREESRC = "${COMPONENTS_DIR}/${PACKAGE_ARCH}/glibc-stash-locale"
+
+copy_locale_files() {
+	local dir=$1 mode=$2
+
+	[ -e "${LOCALETREESRC}$dir" ] || return 0
+
+	for d in . $(find "${LOCALETREESRC}$dir" -type d -printf '%P '); do
+		install -d ${D}$dir/$d
+		find "${LOCALETREESRC}$dir/$d" -maxdepth 1 -type f \
+			-exec install -m $mode -t "${D}$dir/$d" {} \;
+	done
+}
+
+do_install() {
+	copy_locale_files ${bindir} 0755
+	copy_locale_files ${localedir} 0644
+	if [ ${PACKAGE_NO_GCONV} -eq 0 ]; then
+		copy_locale_files ${libdir}/gconv 0755
+		copy_locale_files ${datadir}/i18n 0644
+	else
+		# Remove the libdir if it is empty when gconv is not copied
+		find ${D}${libdir} -type d -empty -delete
+	fi
+	copy_locale_files ${datadir}/locale 0644
+	install -m 0644 ${LOCALETREESRC}/SUPPORTED ${WORKDIR}/SUPPORTED
+}
+
+inherit libc-package
+
+BBCLASSEXTEND = "nativesdk"
+
+# Don't scan for CVEs as glibc will be scanned
+CVE_PRODUCT = ""

+ 1 - 0
recipes-core/glibc/glibc-locale_2.35.bb

@@ -0,0 +1 @@
+require glibc-locale.inc

+ 16 - 0
recipes-core/glibc/glibc-mtrace.inc

@@ -0,0 +1,16 @@
+require glibc-collateral.inc
+
+SUMMARY = "mtrace utility provided by glibc"
+DESCRIPTION = "mtrace utility provided by glibc"
+RDEPENDS:${PN} = "perl"
+RPROVIDES:${PN} = "libc-mtrace"
+
+SRC = "${COMPONENTS_DIR}/${PACKAGE_ARCH}/glibc-stash-locale/scripts"
+
+do_install() {
+	install -d -m 0755 ${D}${bindir}
+	install -m 0755 ${SRC}/mtrace ${D}${bindir}/
+}
+
+# Don't scan for CVEs as glibc will be scanned
+CVE_PRODUCT = ""

+ 1 - 0
recipes-core/glibc/glibc-mtrace_2.35.bb

@@ -0,0 +1 @@
+require glibc-mtrace.inc

File diff suppressed because it is too large
+ 16 - 0
recipes-core/glibc/glibc-package.inc


+ 23 - 0
recipes-core/glibc/glibc-scripts.inc

@@ -0,0 +1,23 @@
+require glibc-collateral.inc
+
+SUMMARY = "utility scripts provided by glibc"
+DESCRIPTION = "utility scripts provided by glibc"
+RDEPENDS:${PN} = "bash glibc-mtrace"
+
+SRC = "${COMPONENTS_DIR}/${PACKAGE_ARCH}/glibc-stash-locale/scripts"
+
+bashscripts = "sotruss xtrace"
+
+do_install() {
+	install -d -m 0755 ${D}${bindir}
+	for i in ${bashscripts}; do
+		install -m 0755 ${SRC}/$i ${D}${bindir}/
+	done
+}
+
+# sotruss script requires sotruss-lib.so (given by libsotruss package), 
+# to produce trace of the library calls.
+RDEPENDS:${PN} += "libsotruss"
+
+# Don't scan for CVEs as glibc will be scanned
+CVE_PRODUCT = ""

+ 1 - 0
recipes-core/glibc/glibc-scripts_2.35.bb

@@ -0,0 +1 @@
+require glibc-scripts.inc

+ 32 - 0
recipes-core/glibc/glibc-tests.inc

@@ -0,0 +1,32 @@
+EXCLUDE_FROM_WORLD = "1"
+
+# handle PN differences
+FILESEXTRAPATHS:prepend := "${THISDIR}/glibc:"
+
+# setup depends
+INHIBIT_DEFAULT_DEPS = ""
+
+python () {
+    libc = d.getVar("PREFERRED_PROVIDER_virtual/libc")
+    libclocale = d.getVar("PREFERRED_PROVIDER_virtual/libc-locale")
+    if libc != "glibc" or libclocale != "glibc-locale":
+        raise bb.parse.SkipRecipe("glibc-testsuite requires that virtual/libc is glibc")
+}
+
+DEPENDS += "glibc-locale libgcc gcc-runtime"
+
+# remove the initial depends
+DEPENDS:remove = "libgcc-initial"
+
+do_check[dirs] += "${B}"
+do_check () {
+    # clean out previous test results
+    oe_runmake tests-clean
+    # makefiles don't clean entirely (and also sometimes fails due to too many args)
+    find ${B} -type f -name "*.out" -delete
+    find ${B} -type f -name "*.test-result" -delete
+    find ${B}/catgets -name "*.cat" -delete
+    find ${B}/conform -name "symlist-*" -delete
+    [ ! -e ${B}/timezone/testdata ] || rm -rf ${B}/timezone/testdata
+}
+addtask do_check after do_compile

+ 35 - 0
recipes-core/glibc/glibc-testsuite_2.35.bb

@@ -0,0 +1,35 @@
+require glibc_${PV}.bb
+require glibc-tests.inc
+
+inherit qemu
+
+SRC_URI += "file://check-test-wrapper"
+
+# strip provides
+PROVIDES = ""
+
+DEPENDS += "${@'qemu-native' if d.getVar('TOOLCHAIN_TEST_TARGET') == 'user' else ''}"
+
+TOOLCHAIN_TEST_TARGET ??= "user"
+TOOLCHAIN_TEST_HOST ??= "localhost"
+TOOLCHAIN_TEST_HOST_USER ??= "root"
+TOOLCHAIN_TEST_HOST_PORT ??= "2222"
+
+do_check[nostamp] = "1"
+do_check:append () {
+    chmod 0755 ${WORKDIR}/check-test-wrapper
+
+    oe_runmake -i \
+        QEMU_SYSROOT="${RECIPE_SYSROOT}" \
+        QEMU_OPTIONS="${@qemu_target_binary(d)} ${QEMU_OPTIONS}" \
+        SSH_HOST="${TOOLCHAIN_TEST_HOST}" \
+        SSH_HOST_USER="${TOOLCHAIN_TEST_HOST_USER}" \
+        SSH_HOST_PORT="${TOOLCHAIN_TEST_HOST_PORT}" \
+        test-wrapper="${WORKDIR}/check-test-wrapper ${TOOLCHAIN_TEST_TARGET}" \
+        check
+}
+
+inherit nopackages
+deltask do_stash_locale
+deltask do_install
+deltask do_populate_sysroot

+ 8 - 0
recipes-core/glibc/glibc-version.inc

@@ -0,0 +1,8 @@
+SRCBRANCH ?= "master"
+PV = "2.35"
+SRCREV_glibc ?= "90f0ac10a74b2d43b5a65aab4be40565e359be43"
+SRCREV_localedef ?= "95c0221703ad970a52445e9eaf91c4aff35eebef"
+
+GLIBC_GIT_URI ?= "git://sourceware.org/git/glibc.git"
+
+UPSTREAM_CHECK_GITTAGREGEX = "(?P<pver>\d+\.\d+(\.(?!90)\d+)*)"

+ 52 - 0
recipes-core/glibc/glibc.inc

@@ -0,0 +1,52 @@
+require glibc-common.inc
+require glibc-ld.inc
+
+DEPENDS = "virtual/${TARGET_PREFIX}gcc libgcc-initial linux-libc-headers"
+
+PROVIDES = "virtual/libc"
+PROVIDES += "virtual/libintl virtual/libiconv"
+inherit autotools texinfo systemd
+
+LEAD_SONAME = "libc.so"
+
+# msgfmt could come from gettext-native but we don't depend on that and
+# disable for reproducibility
+CACHED_CONFIGUREVARS += " \
+  ac_cv_path_BASH_SHELL=${base_bindir}/bash \
+  ac_cv_prog_MSGFMT= \
+  libc_cv_slibdir=${base_libdir} \
+  libc_cv_rootsbindir=${base_sbindir} \
+  libc_cv_localedir=${localedir} \
+  libc_cv_ssp_strong=no \
+  libc_cv_ssp_all=no \
+  libc_cv_ssp=no \
+  libc_cv_include_x86_isa_level=no \
+"
+
+# ifunc doesn't appear to work on mips, casuses libbfd assertion failures
+CACHED_CONFIGUREVARS:append:mipsarch = " libc_cv_ld_gnu_indirect_function=no"
+
+GLIBC_EXTRA_OECONF ?= ""
+GLIBC_EXTRA_OECONF:class-nativesdk = ""
+
+# glibc uses PARALLELMFLAGS variable to pass parallel build info so transfer
+# PARALLEL_MAKE into PARALLELMFLAGS and empty out PARALLEL_MAKE
+EGLIBCPARALLELISM := "PARALLELMFLAGS="${PARALLEL_MAKE}""
+EXTRA_OEMAKE[vardepsexclude] += "EGLIBCPARALLELISM"
+EXTRA_OEMAKE += "${EGLIBCPARALLELISM}"
+PARALLEL_MAKE = ""
+
+# glibc make-syscalls.sh has a number of issues with /bin/dash and
+# it's output which make calls via the SHELL also has issues, so
+# ensure make uses /bin/bash
+EXTRA_OEMAKE += "SHELL=/bin/bash"
+
+do_configure:prepend() {
+	sed -e "s#/bin/bash#/bin/sh#" -i ${S}/elf/ldd.bash.in
+}
+
+# Enable backtrace from abort()
+do_configure:append:arm () {
+	echo "CFLAGS-abort.c = -fasynchronous-unwind-tables" >> ${B}/configparms
+	echo "CFLAGS-raise.c = -fasynchronous-unwind-tables" >> ${B}/configparms
+}

+ 59 - 0
recipes-core/glibc/glibc/0001-Add-array_length-support.patch

@@ -0,0 +1,59 @@
+From ce34f0e215324455bbb1e4b18f5723b081cae801 Mon Sep 17 00:00:00 2001
+From: Jun Yuan Tan <junyuan.tan@starfivetech.com>
+Date: Tue, 23 Nov 2021 12:08:27 +0800
+Subject: [PATCH 1/1] Add array_length support
+
+This is needed to build localedef from glibc 2.35 in master branch.
+(Commit f5117c6504888fab5423282a4607c552b90fd3f9)
+
+Signed-off-by: Jun Yuan Tan <junyuan.tan@starfivetech.com>
+---
+ localedef/include/array_length.h | 36 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+ create mode 100644 localedef/include/array_length.h
+
+diff --git a/localedef/include/array_length.h b/localedef/include/array_length.h
+new file mode 100644
+index 0000000..12c5126
+--- /dev/null
++++ b/localedef/include/array_length.h
+@@ -0,0 +1,36 @@
++/* The array_length and array_end macros.
++   Copyright (C) 2017-2021 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#ifndef _ARRAY_LENGTH_H
++#define _ARRAY_LENGTH_H
++
++/* array_length (VAR) is the number of elements in the array VAR.  VAR
++   must evaluate to an array, not a pointer.  */
++#define array_length(var)                                               \
++  (sizeof (var) / sizeof ((var)[0])                                     \
++   + 0 * sizeof (struct {                                               \
++       _Static_assert (!__builtin_types_compatible_p                    \
++                       (__typeof (var), __typeof (&(var)[0])),          \
++                       "argument must be an array");                    \
++   }))
++
++/* array_end (VAR) is a pointer one past the end of the array VAR.
++   VAR must evaluate to an array, not a pointer.  */
++#define array_end(var) (&(var)[array_length (var)])
++
++#endif /* _ARRAY_LENGTH_H */
+-- 
+2.33.1
+

+ 43 - 0
recipes-core/glibc/glibc/0001-CVE-2021-38604.patch

@@ -0,0 +1,43 @@
+From b805aebd42364fe696e417808a700fdb9800c9e8 Mon Sep 17 00:00:00 2001
+From: Nikita Popov <npv1310@gmail.com>
+Date: Mon, 9 Aug 2021 20:17:34 +0530
+Subject: [PATCH] librt: fix NULL pointer dereference (bug 28213)
+
+Helper thread frees copied attribute on NOTIFY_REMOVED message
+received from the OS kernel.  Unfortunately, it fails to check whether
+copied attribute actually exists (data.attr != NULL).  This worked
+earlier because free() checks passed pointer before actually
+attempting to release corresponding memory.  But
+__pthread_attr_destroy assumes pointer is not NULL.
+
+So passing NULL pointer to __pthread_attr_destroy will result in
+segmentation fault.  This scenario is possible if
+notification->sigev_notify_attributes == NULL (which means default
+thread attributes should be used).
+
+Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commit;h=b805aebd42364fe696e417808a700fdb9800c9e8]
+CVE: CVE-2021-38604
+
+Signed-off-by: Nikita Popov <npv1310@gmail.com>
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Signed-off-by: Vinay Kumar <vinay.m.engg@gmail.com>
+---
+ sysdeps/unix/sysv/linux/mq_notify.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sysdeps/unix/sysv/linux/mq_notify.c b/sysdeps/unix/sysv/linux/mq_notify.c
+index 9799dcdaa4..eccae2e4c6 100644
+--- a/sysdeps/unix/sysv/linux/mq_notify.c
++++ b/sysdeps/unix/sysv/linux/mq_notify.c
+@@ -131,7 +131,7 @@ helper_thread (void *arg)
+ 	       to wait until it is done with it.  */
+ 	    (void) __pthread_barrier_wait (&notify_barrier);
+ 	}
+-      else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED)
++      else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED && data.attr != NULL)
+ 	{
+ 	  /* The only state we keep is the copy of the thread attributes.  */
+ 	  __pthread_attr_destroy (data.attr);
+-- 
+2.31.1
+

+ 79 - 0
recipes-core/glibc/glibc/0001-fix-create-thread-failed-in-unprivileged-process-BZ-.patch

@@ -0,0 +1,79 @@
+From a8bc44936202692edcd82a48c07d7cf27d6ed8ee Mon Sep 17 00:00:00 2001
+From: Hongxu Jia <hongxu.jia@windriver.com>
+Date: Sun, 29 Aug 2021 20:49:16 +0800
+Subject: [PATCH] fix create thread failed in unprivileged process [BZ #28287]
+
+Since commit [d8ea0d0168 Add an internal wrapper for clone, clone2 and clone3]
+applied, start a unprivileged container (docker run without --privileged),
+it creates a thread failed in container.
+
+In commit d8ea0d0168, it calls __clone3 if HAVE_CLONE3_WAPPER is defined.  If
+__clone3 returns -1 with ENOSYS, fall back to clone or clone2.
+
+As known from [1], cloneXXX fails with EPERM if CLONE_NEWCGROUP,
+CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWNS, CLONE_NEWPID, or CLONE_NEWUTS
+was specified by an unprivileged process (process without CAP_SYS_ADMIN)
+
+[1] https://man7.org/linux/man-pages/man2/clone3.2.html
+
+So if __clone3 returns -1 with EPERM, fall back to clone or clone2 could
+fix the issue. Here are the test steps:
+
+1) Prepare test code
+cat > conftest.c <<ENDOF
+ #include <pthread.h>
+ #include <stdio.h>
+
+int check_me = 0;
+void* func(void* data) {check_me = 42; printf("start thread: check_me %d\n", check_me); return &check_me;}
+int main()
+{
+  pthread_t t;
+  void *ret;
+  pthread_create (&t, 0, func, 0);
+  pthread_join (t, &ret);
+  printf("check_me %d, p %p\n", check_me, &ret);
+  return (check_me != 42 || ret != &check_me);
+}
+
+ENDOF
+
+2) Compile
+gcc -o conftest -pthread conftest.c
+
+3) Start a container with glibc 2.34 installed
+[skip details]
+docker run -it <container-image-name> bash
+
+4) Run conftest without this patch
+$ ./conftest
+check_me 0, p 0x7ffd91ccd400
+
+5) Run conftest with this patch
+$ ./conftest
+start thread: check_me 42
+check_me 42, p 0x7ffe253c6f20
+
+Upstream-Status: Submitted [libc-alpha@sourceware.org]
+
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ sysdeps/unix/sysv/linux/clone-internal.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sysdeps/unix/sysv/linux/clone-internal.c b/sysdeps/unix/sysv/linux/clone-internal.c
+index 979f7880be..97101994e8 100644
+--- a/sysdeps/unix/sysv/linux/clone-internal.c
++++ b/sysdeps/unix/sysv/linux/clone-internal.c
+@@ -52,7 +52,7 @@ __clone_internal (struct clone_args *cl_args,
+   /* Try clone3 first.  */
+   int saved_errno = errno;
+   ret = __clone3 (cl_args, sizeof (*cl_args), func, arg);
+-  if (ret != -1 || errno != ENOSYS)
++  if (ret != -1 || (errno != ENOSYS && errno != EPERM))
+     return ret;
+ 
+   /* NB: Restore errno since errno may be checked against non-zero
+-- 
+2.30.2
+

+ 1130 - 0
recipes-core/glibc/glibc/0001-localedef-Add-hardlink-resolver-from-util-linux.patch

@@ -0,0 +1,1130 @@
+From d34ba0833cd811f8869a6262044af55f9e7b59d8 Mon Sep 17 00:00:00 2001
+From: Jason Wessel <jason.wessel@windriver.com>
+Date: Sat, 7 Dec 2019 09:59:22 -0800
+Subject: [PATCH] localedef: Add hardlink resolver from util-linux
+
+The hard link resolver that is built into localedef cannot be run in
+parallel.  It will search sibling directories (which are be processed
+in parallel) and perform a creation of a .tmp file and remove the
+original and move the .tmp file in.  The problem is that if a probe
+occurs a hard link can be requested to the file that is being removed.
+This will lead to a stray copy or potentially, on a loaded system
+cause race condition which pseudo cannot deal with, where it is left
+with a hard link request to a file that no longer exists.  In this
+situation psuedo will inherit the permissions of what ever the target
+inode had to offer.
+
+In short, there are two problems:
+
+1) You will be left with stray copies when using the hard link
+resolution that is built in while running in parallel with
+localedef.
+
+2) When running under pseudo the possibility exists for uid/gid
+leakage when the source file is removed before the hard link can
+be completed.
+
+The solution is to call localedef with --no-hard-links and separately
+process the hardlinks at a later point.  To do this requires the
+inclusion of the hardlink utility found in modern versions of
+util-linux.  Most host systems do not have this, so it will be
+included with the cross-localedef binary.
+
+[YOCTO #11299]
+[YOCTO #12434]
+
+Upstream-Status: Pending
+
+Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ locale/programs/c.h                        | 407 ++++++++++++++++
+ locale/programs/cross-localedef-hardlink.c | 528 +++++++++++++++++++++
+ locale/programs/xalloc.h                   | 129 +++++
+ 3 files changed, 1064 insertions(+)
+ create mode 100644 locale/programs/c.h
+ create mode 100644 locale/programs/cross-localedef-hardlink.c
+ create mode 100644 locale/programs/xalloc.h
+
+diff --git a/locale/programs/c.h b/locale/programs/c.h
+new file mode 100644
+index 0000000000..d0a402e90e
+--- /dev/null
++++ b/locale/programs/c.h
+@@ -0,0 +1,407 @@
++/*
++ * Fundamental C definitions.
++ */
++
++#ifndef UTIL_LINUX_C_H
++#define UTIL_LINUX_C_H
++
++#include <limits.h>
++#include <stddef.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <unistd.h>
++#include <stdarg.h>
++#include <stdlib.h>
++#include <string.h>
++#include <errno.h>
++
++#include <assert.h>
++
++#ifdef HAVE_ERR_H
++# include <err.h>
++#endif
++
++#ifdef HAVE_SYS_SYSMACROS_H
++# include <sys/sysmacros.h>     /* for major, minor */
++#endif
++
++#ifndef LOGIN_NAME_MAX
++# define LOGIN_NAME_MAX 256
++#endif
++
++#ifndef NAME_MAX
++# define NAME_MAX PATH_MAX
++#endif
++
++/*
++ * __GNUC_PREREQ is deprecated in favour of __has_attribute() and
++ * __has_feature(). The __has macros are supported by clang and gcc>=5.
++ */
++#ifndef __GNUC_PREREQ
++# if defined __GNUC__ && defined __GNUC_MINOR__
++#  define __GNUC_PREREQ(maj, min) \
++	((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
++# else
++#  define __GNUC_PREREQ(maj, min) 0
++# endif
++#endif
++
++#ifdef __GNUC__
++
++/* &a[0] degrades to a pointer: a different type from an array */
++# define __must_be_array(a) \
++	UL_BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(__typeof__(a), __typeof__(&a[0])))
++
++# define ignore_result(x) __extension__ ({ \
++	__typeof__(x) __dummy __attribute__((__unused__)) = (x); (void) __dummy; \
++})
++
++#else /* !__GNUC__ */
++# define __must_be_array(a)	0
++# define __attribute__(_arg_)
++# define ignore_result(x) ((void) (x))
++#endif /* !__GNUC__ */
++
++/*
++ * It evaluates to 1 if the attribute/feature is supported by the current
++ * compilation targed. Fallback for old compilers.
++ */
++#ifndef __has_attribute
++  #define __has_attribute(x) 0
++#endif
++
++#ifndef __has_feature
++  #define __has_feature(x) 0
++#endif
++
++/*
++ * Function attributes
++ */
++#ifndef __ul_alloc_size
++# if (__has_attribute(alloc_size) && __has_attribute(warn_unused_result)) || __GNUC_PREREQ (4, 3)
++#  define __ul_alloc_size(s) __attribute__((alloc_size(s), warn_unused_result))
++# else
++#  define __ul_alloc_size(s)
++# endif
++#endif
++
++#ifndef __ul_calloc_size
++# if (__has_attribute(alloc_size) && __has_attribute(warn_unused_result)) || __GNUC_PREREQ (4, 3)
++#  define __ul_calloc_size(n, s) __attribute__((alloc_size(n, s), warn_unused_result))
++# else
++#  define __ul_calloc_size(n, s)
++# endif
++#endif
++
++#if __has_attribute(returns_nonnull) || __GNUC_PREREQ (4, 9)
++# define __ul_returns_nonnull __attribute__((returns_nonnull))
++#else
++# define __ul_returns_nonnull
++#endif
++
++/*
++ * Force a compilation error if condition is true, but also produce a
++ * result (of value 0 and type size_t), so the expression can be used
++ * e.g. in a structure initializer (or wherever else comma expressions
++ * aren't permitted).
++ */
++#define UL_BUILD_BUG_ON_ZERO(e) __extension__ (sizeof(struct { int:-!!(e); }))
++#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
++
++#ifndef ARRAY_SIZE
++# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
++#endif
++
++#ifndef PATH_MAX
++# define PATH_MAX 4096
++#endif
++
++#ifndef TRUE
++# define TRUE 1
++#endif
++
++#ifndef FALSE
++# define FALSE 0
++#endif
++
++#ifndef min
++# define min(x, y) __extension__ ({		\
++	__typeof__(x) _min1 = (x);		\
++	__typeof__(y) _min2 = (y);		\
++	(void) (&_min1 == &_min2);		\
++	_min1 < _min2 ? _min1 : _min2; })
++#endif
++
++#ifndef max
++# define max(x, y) __extension__ ({		\
++	__typeof__(x) _max1 = (x);		\
++	__typeof__(y) _max2 = (y);		\
++	(void) (&_max1 == &_max2);		\
++	_max1 > _max2 ? _max1 : _max2; })
++#endif
++
++#ifndef cmp_numbers
++# define cmp_numbers(x, y) __extension__ ({	\
++	__typeof__(x) _a = (x);			\
++	__typeof__(y) _b = (y);			\
++	(void) (&_a == &_b);			\
++	_a == _b ? 0 : _a > _b ? 1 : -1; })
++#endif
++
++#ifndef offsetof
++#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
++#endif
++
++/*
++ * container_of - cast a member of a structure out to the containing structure
++ * @ptr:	the pointer to the member.
++ * @type:	the type of the container struct this is embedded in.
++ * @member:	the name of the member within the struct.
++ */
++#ifndef container_of
++#define container_of(ptr, type, member) __extension__ ({	\
++	const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
++	(type *)( (char *)__mptr - offsetof(type,member) );})
++#endif
++
++#ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME
++# ifdef HAVE___PROGNAME
++extern char *__progname;
++#  define program_invocation_short_name __progname
++# else
++#  ifdef HAVE_GETEXECNAME
++#   define program_invocation_short_name \
++		prog_inv_sh_nm_from_file(getexecname(), 0)
++#  else
++#   define program_invocation_short_name \
++		prog_inv_sh_nm_from_file(__FILE__, 1)
++#  endif
++static char prog_inv_sh_nm_buf[256];
++static inline char *
++prog_inv_sh_nm_from_file(char *f, char stripext)
++{
++	char *t;
++
++	if ((t = strrchr(f, '/')) != NULL)
++		t++;
++	else
++		t = f;
++
++	strncpy(prog_inv_sh_nm_buf, t, sizeof(prog_inv_sh_nm_buf) - 1);
++	prog_inv_sh_nm_buf[sizeof(prog_inv_sh_nm_buf) - 1] = '\0';
++
++	if (stripext && (t = strrchr(prog_inv_sh_nm_buf, '.')) != NULL)
++		*t = '\0';
++
++	return prog_inv_sh_nm_buf;
++}
++# endif
++#endif
++
++
++#ifndef HAVE_ERR_H
++static inline void
++errmsg(char doexit, int excode, char adderr, const char *fmt, ...)
++{
++	fprintf(stderr, "%s: ", program_invocation_short_name);
++	if (fmt != NULL) {
++		va_list argp;
++		va_start(argp, fmt);
++		vfprintf(stderr, fmt, argp);
++		va_end(argp);
++		if (adderr)
++			fprintf(stderr, ": ");
++	}
++	if (adderr)
++		fprintf(stderr, "%m");
++	fprintf(stderr, "\n");
++	if (doexit)
++		exit(excode);
++}
++
++#ifndef HAVE_ERR
++# define err(E, FMT...) errmsg(1, E, 1, FMT)
++#endif
++
++#ifndef HAVE_ERRX
++# define errx(E, FMT...) errmsg(1, E, 0, FMT)
++#endif
++
++#ifndef HAVE_WARN
++# define warn(FMT...) errmsg(0, 0, 1, FMT)
++#endif
++
++#ifndef HAVE_WARNX
++# define warnx(FMT...) errmsg(0, 0, 0, FMT)
++#endif
++#endif /* !HAVE_ERR_H */
++
++
++/* Don't use inline function to avoid '#include "nls.h"' in c.h
++ */
++#define errtryhelp(eval) __extension__ ({ \
++	fprintf(stderr, _("Try '%s --help' for more information.\n"), \
++			program_invocation_short_name); \
++	exit(eval); \
++})
++
++/* After failed execvp() */
++#define EX_EXEC_FAILED		126	/* Program located, but not usable. */
++#define EX_EXEC_ENOENT		127	/* Could not find program to exec.  */
++#define errexec(name)	err(errno == ENOENT ? EX_EXEC_ENOENT : EX_EXEC_FAILED, \
++			_("failed to execute %s"), name)
++
++
++static inline __attribute__((const)) int is_power_of_2(unsigned long num)
++{
++	return (num != 0 && ((num & (num - 1)) == 0));
++}
++
++#ifndef HAVE_LOFF_T
++typedef int64_t loff_t;
++#endif
++
++#if !defined(HAVE_DIRFD) && (!defined(HAVE_DECL_DIRFD) || HAVE_DECL_DIRFD == 0) && defined(HAVE_DIR_DD_FD)
++#include <sys/types.h>
++#include <dirent.h>
++static inline int dirfd(DIR *d)
++{
++	return d->dd_fd;
++}
++#endif
++
++/*
++ * Fallback defines for old versions of glibc
++ */
++#include <fcntl.h>
++
++#ifdef O_CLOEXEC
++#define UL_CLOEXECSTR	"e"
++#else
++#define UL_CLOEXECSTR	""
++#endif
++
++#ifndef O_CLOEXEC
++#define O_CLOEXEC 0
++#endif
++
++#ifdef __FreeBSD_kernel__
++#ifndef F_DUPFD_CLOEXEC
++#define F_DUPFD_CLOEXEC	17	/* Like F_DUPFD, but FD_CLOEXEC is set */
++#endif
++#endif
++
++
++#ifndef AI_ADDRCONFIG
++#define AI_ADDRCONFIG 0x0020
++#endif
++
++#ifndef IUTF8
++#define IUTF8 0040000
++#endif
++
++/*
++ * MAXHOSTNAMELEN replacement
++ */
++static inline size_t get_hostname_max(void)
++{
++	long len = sysconf(_SC_HOST_NAME_MAX);
++
++	if (0 < len)
++		return len;
++
++#ifdef MAXHOSTNAMELEN
++	return MAXHOSTNAMELEN;
++#elif HOST_NAME_MAX
++	return HOST_NAME_MAX;
++#endif
++	return 64;
++}
++
++
++/*
++ * Constant strings for usage() functions. For more info see
++ * Documentation/{howto-usage-function.txt,boilerplate.c}
++ */
++#define USAGE_HEADER     ("\nUsage:\n")
++#define USAGE_OPTIONS    ("\nOptions:\n")
++#define USAGE_FUNCTIONS  ("\nFunctions:\n")
++#define USAGE_COMMANDS   ("\nCommands:\n")
++#define USAGE_COLUMNS    ("\nAvailable output columns:\n")
++#define USAGE_SEPARATOR    "\n"
++
++#define USAGE_OPTSTR_HELP     ("display this help")
++#define USAGE_OPTSTR_VERSION  ("display version")
++
++#define USAGE_HELP_OPTIONS(marg_dsc) \
++		"%-" #marg_dsc "s%s\n" \
++		"%-" #marg_dsc "s%s\n" \
++		, " -h, --help",    USAGE_OPTSTR_HELP \
++		, " -V, --version", USAGE_OPTSTR_VERSION
++
++#define USAGE_MAN_TAIL(_man)   ("\nFor more details see %s.\n"), _man
++
++#define UTIL_LINUX_VERSION ("%s from %s\n"), program_invocation_short_name, PACKAGE_STRING
++
++#define print_version(eval) __extension__ ({ \
++		printf(UTIL_LINUX_VERSION); \
++		exit(eval); \
++})
++
++/*
++ * scanf modifiers for "strings allocation"
++ */
++#ifdef HAVE_SCANF_MS_MODIFIER
++#define UL_SCNsA	"%ms"
++#elif defined(HAVE_SCANF_AS_MODIFIER)
++#define UL_SCNsA	"%as"
++#endif
++
++/*
++ * seek stuff
++ */
++#ifndef SEEK_DATA
++# define SEEK_DATA	3
++#endif
++#ifndef SEEK_HOLE
++# define SEEK_HOLE	4
++#endif
++
++
++/*
++ * Macros to convert #define'itions to strings, for example
++ * #define XYXXY 42
++ * printf ("%s=%s\n", stringify(XYXXY), stringify_value(XYXXY));
++ */
++#define stringify_value(s) stringify(s)
++#define stringify(s) #s
++
++/*
++ * UL_ASAN_BLACKLIST is a macro to tell AddressSanitizer (a compile-time
++ * instrumentation shipped with Clang and GCC) to not instrument the
++ * annotated function.  Furthermore, it will prevent the compiler from
++ * inlining the function because inlining currently breaks the blacklisting
++ * mechanism of AddressSanitizer.
++ */
++#if __has_feature(address_sanitizer) && __has_attribute(no_sanitize_memory) && __has_attribute(no_sanitize_address)
++# define UL_ASAN_BLACKLIST __attribute__((noinline)) __attribute__((no_sanitize_memory)) __attribute__((no_sanitize_address))
++#else
++# define UL_ASAN_BLACKLIST	/* nothing */
++#endif
++
++/*
++ * Note that sysconf(_SC_GETPW_R_SIZE_MAX) returns *initial* suggested size for
++ * pwd buffer and in some cases it is not large enough. See POSIX and
++ * getpwnam_r man page for more details.
++ */
++#define UL_GETPW_BUFSIZ	(16 * 1024)
++
++/*
++ * Darwin or other BSDs may only have MAP_ANON. To get it on Darwin we must
++ * define _DARWIN_C_SOURCE before including sys/mman.h. We do this in config.h.
++ */
++#if !defined MAP_ANONYMOUS && defined MAP_ANON
++# define MAP_ANONYMOUS  (MAP_ANON)
++#endif
++
++#endif /* UTIL_LINUX_C_H */
+diff --git a/locale/programs/cross-localedef-hardlink.c b/locale/programs/cross-localedef-hardlink.c
+new file mode 100644
+index 0000000000..63615896b0
+--- /dev/null
++++ b/locale/programs/cross-localedef-hardlink.c
+@@ -0,0 +1,528 @@
++/*
++ * hardlink - consolidate duplicate files via hardlinks
++ *
++ * Copyright (C) 2018 Red Hat, Inc. All rights reserved.
++ * Written by Jakub Jelinek <jakub@redhat.com>
++ *
++ * Copyright (C) 2019 Karel Zak <kzak@redhat.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it would be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++#include <sys/types.h>
++#include <stdlib.h>
++#include <getopt.h>
++#include <stdio.h>
++#include <unistd.h>
++#include <sys/stat.h>
++#include <sys/mman.h>
++#include <string.h>
++#include <dirent.h>
++#include <fcntl.h>
++#include <errno.h>
++#ifdef HAVE_PCRE
++# define PCRE2_CODE_UNIT_WIDTH 8
++# include <pcre2.h>
++#endif
++
++#include "c.h"
++#include "xalloc.h"
++#include "nls.h"
++#include "closestream.h"
++
++#define NHASH   (1<<17)  /* Must be a power of 2! */
++#define NBUF    64
++
++struct hardlink_file;
++
++struct hardlink_hash {
++	struct hardlink_hash *next;
++	struct hardlink_file *chain;
++	off_t size;
++	time_t mtime;
++};
++
++struct hardlink_dir {
++	struct hardlink_dir *next;
++	char name[];
++};
++
++struct hardlink_file {
++	struct hardlink_file *next;
++	ino_t ino;
++	dev_t dev;
++	unsigned int cksum;
++	char name[];
++};
++
++struct hardlink_dynstr {
++	char *buf;
++	size_t alloc;
++};
++
++struct hardlink_ctl {
++	struct hardlink_dir *dirs;
++	struct hardlink_hash *hps[NHASH];
++	char iobuf1[BUFSIZ];
++	char iobuf2[BUFSIZ];
++	/* summary counters */
++	unsigned long long ndirs;
++	unsigned long long nobjects;
++	unsigned long long nregfiles;
++	unsigned long long ncomp;
++	unsigned long long nlinks;
++	unsigned long long nsaved;
++	/* current device */
++	dev_t dev;
++	/* flags */
++	unsigned int verbose;
++	unsigned int
++		no_link:1,
++		content_only:1,
++		force:1;
++};
++/* ctl is in global scope due use in atexit() */
++struct hardlink_ctl global_ctl;
++
++__attribute__ ((always_inline))
++static inline unsigned int hash(off_t size, time_t mtime)
++{
++	return (size ^ mtime) & (NHASH - 1);
++}
++
++__attribute__ ((always_inline))
++static inline int stcmp(struct stat *st1, struct stat *st2, int content_scope)
++{
++	if (content_scope)
++		return st1->st_size != st2->st_size;
++
++	return st1->st_mode != st2->st_mode
++		|| st1->st_uid != st2->st_uid
++		|| st1->st_gid != st2->st_gid
++		|| st1->st_size != st2->st_size
++		|| st1->st_mtime != st2->st_mtime;
++}
++
++static void print_summary(void)
++{
++	struct hardlink_ctl const *const ctl = &global_ctl;
++
++	if (!ctl->verbose)
++		return;
++
++	if (ctl->verbose > 1 && ctl->nlinks)
++		fputc('\n', stdout);
++
++	printf(_("Directories:   %9lld\n"), ctl->ndirs);
++	printf(_("Objects:       %9lld\n"), ctl->nobjects);
++	printf(_("Regular files: %9lld\n"), ctl->nregfiles);
++	printf(_("Comparisons:   %9lld\n"), ctl->ncomp);
++	printf(  "%s%9lld\n", (ctl->no_link ?
++	       _("Would link:    ") :
++	       _("Linked:        ")), ctl->nlinks);
++	printf(  "%s %9lld\n", (ctl->no_link ?
++	       _("Would save:   ") :
++	       _("Saved:        ")), ctl->nsaved);
++}
++
++static void __attribute__((__noreturn__)) usage(void)
++{
++	fputs(USAGE_HEADER, stdout);
++	printf(_(" %s [options] directory...\n"), program_invocation_short_name);
++
++	fputs(USAGE_SEPARATOR, stdout);
++	puts(_("Consolidate duplicate files using hardlinks."));
++
++	fputs(USAGE_OPTIONS, stdout);
++	puts(_(" -c, --content          compare only contents, ignore permission, etc."));
++	puts(_(" -n, --dry-run          don't actually link anything"));
++	puts(_(" -v, --verbose          print summary after hardlinking"));
++	puts(_(" -vv                    print every hardlinked file and summary"));
++	puts(_(" -f, --force            force hardlinking across filesystems"));
++	puts(_(" -x, --exclude <regex>  exclude files matching pattern"));
++
++	fputs(USAGE_SEPARATOR, stdout);
++	printf(USAGE_HELP_OPTIONS(16)); /* char offset to align option descriptions */
++	printf(USAGE_MAN_TAIL("hardlink(1)"));
++	exit(EXIT_SUCCESS);
++}
++
++__attribute__ ((always_inline))
++static inline size_t add2(size_t a, size_t b)
++{
++	size_t sum = a + b;
++
++	if (sum < a)
++		errx(EXIT_FAILURE, _("integer overflow"));
++	return sum;
++}
++
++__attribute__ ((always_inline))
++static inline size_t add3(size_t a, size_t b, size_t c)
++{
++	return add2(add2(a, b), c);
++}
++
++static void growstr(struct hardlink_dynstr *str, size_t newlen)
++{
++	if (newlen < str->alloc)
++		return;
++	str->buf = xrealloc(str->buf, str->alloc = add2(newlen, 1));
++}
++
++static void process_path(struct hardlink_ctl *ctl, const char *name)
++{
++	struct stat st, st2, st3;
++	const size_t namelen = strlen(name);
++
++	ctl->nobjects++;
++	if (lstat(name, &st))
++		return;
++
++	if (st.st_dev != ctl->dev && !ctl->force) {
++		if (ctl->dev)
++			errx(EXIT_FAILURE,
++			     _("%s is on different filesystem than the rest "
++			       "(use -f option to override)."), name);
++		ctl->dev = st.st_dev;
++	}
++	if (S_ISDIR(st.st_mode)) {
++		struct hardlink_dir *dp = xmalloc(add3(sizeof(*dp), namelen, 1));
++		memcpy(dp->name, name, namelen + 1);
++		dp->next = ctl->dirs;
++		ctl->dirs = dp;
++
++	} else if (S_ISREG(st.st_mode)) {
++		int fd, i;
++		struct hardlink_file *fp, *fp2;
++		struct hardlink_hash *hp;
++		const char *n1, *n2;
++		unsigned int buf[NBUF];
++		int cksumsize = sizeof(buf);
++		unsigned int cksum;
++		time_t mtime = ctl->content_only ? 0 : st.st_mtime;
++		unsigned int hsh = hash(st.st_size, mtime);
++		off_t fsize;
++
++		ctl->nregfiles++;
++		if (ctl->verbose > 1)
++			printf("%s\n", name);
++
++		fd = open(name, O_RDONLY);
++		if (fd < 0)
++			return;
++
++		if ((size_t)st.st_size < sizeof(buf)) {
++			cksumsize = st.st_size;
++			memset(((char *)buf) + cksumsize, 0,
++			       (sizeof(buf) - cksumsize) % sizeof(buf[0]));
++		}
++		if (read(fd, buf, cksumsize) != cksumsize) {
++			close(fd);
++			return;
++		}
++		cksumsize = (cksumsize + sizeof(buf[0]) - 1) / sizeof(buf[0]);
++		for (i = 0, cksum = 0; i < cksumsize; i++) {
++			if (cksum + buf[i] < cksum)
++				cksum += buf[i] + 1;
++			else
++				cksum += buf[i];
++		}
++		for (hp = ctl->hps[hsh]; hp; hp = hp->next) {
++			if (hp->size == st.st_size && hp->mtime == mtime)
++				break;
++		}
++		if (!hp) {
++			hp = xmalloc(sizeof(*hp));
++			hp->size = st.st_size;
++			hp->mtime = mtime;
++			hp->chain = NULL;
++			hp->next = ctl->hps[hsh];
++			ctl->hps[hsh] = hp;
++		}
++		for (fp = hp->chain; fp; fp = fp->next) {
++			if (fp->cksum == cksum)
++				break;
++		}
++		for (fp2 = fp; fp2 && fp2->cksum == cksum; fp2 = fp2->next) {
++			if (fp2->ino == st.st_ino && fp2->dev == st.st_dev) {
++				close(fd);
++				return;
++			}
++		}
++		for (fp2 = fp; fp2 && fp2->cksum == cksum; fp2 = fp2->next) {
++
++			if (!lstat(fp2->name, &st2) && S_ISREG(st2.st_mode) &&
++			    !stcmp(&st, &st2, ctl->content_only) &&
++			    st2.st_ino != st.st_ino &&
++			    st2.st_dev == st.st_dev) {
++
++				int fd2 = open(fp2->name, O_RDONLY);
++				if (fd2 < 0)
++					continue;
++
++				if (fstat(fd2, &st2) || !S_ISREG(st2.st_mode)
++				    || st2.st_size == 0) {
++					close(fd2);
++					continue;
++				}
++				ctl->ncomp++;
++				lseek(fd, 0, SEEK_SET);
++
++				for (fsize = st.st_size; fsize > 0;
++				     fsize -= (off_t)sizeof(ctl->iobuf1)) {
++					ssize_t xsz;
++					ssize_t rsize = fsize > (ssize_t) sizeof(ctl->iobuf1) ?
++							(ssize_t) sizeof(ctl->iobuf1) : fsize;
++
++					if ((xsz = read(fd, ctl->iobuf1, rsize)) != rsize)
++						warn(_("cannot read %s"), name);
++					else if ((xsz = read(fd2, ctl->iobuf2, rsize)) != rsize)
++						warn(_("cannot read %s"), fp2->name);
++
++					if (xsz != rsize) {
++						close(fd);
++						close(fd2);
++						return;
++					}
++					if (memcmp(ctl->iobuf1, ctl->iobuf2, rsize))
++						break;
++				}
++				close(fd2);
++				if (fsize > 0)
++					continue;
++				if (lstat(name, &st3)) {
++					warn(_("cannot stat %s"), name);
++					close(fd);
++					return;
++				}
++				st3.st_atime = st.st_atime;
++				if (stcmp(&st, &st3, 0)) {
++					warnx(_("file %s changed underneath us"), name);
++					close(fd);
++					return;
++				}
++				n1 = fp2->name;
++				n2 = name;
++
++				if (!ctl->no_link) {
++					const char *suffix =
++					    ".$$$___cleanit___$$$";
++					const size_t suffixlen = strlen(suffix);
++					size_t n2len = strlen(n2);
++					struct hardlink_dynstr nam2 = { NULL, 0 };
++
++					growstr(&nam2, add2(n2len, suffixlen));
++					memcpy(nam2.buf, n2, n2len);
++					memcpy(&nam2.buf[n2len], suffix,
++					       suffixlen + 1);
++					/* First create a temporary link to n1 under a new name */
++					if (link(n1, nam2.buf)) {
++						warn(_("failed to hardlink %s to %s (create temporary link as %s failed)"),
++							n1, n2, nam2.buf);
++						free(nam2.buf);
++						continue;
++					}
++					/* Then rename into place over the existing n2 */
++					if (rename(nam2.buf, n2)) {
++						warn(_("failed to hardlink %s to %s (rename temporary link to %s failed)"),
++							n1, n2, n2);
++						/* Something went wrong, try to remove the now redundant temporary link */
++						if (unlink(nam2.buf))
++							warn(_("failed to remove temporary link %s"), nam2.buf);
++						free(nam2.buf);
++						continue;
++					}
++					free(nam2.buf);
++				}
++				ctl->nlinks++;
++				if (st3.st_nlink > 1) {
++					/* We actually did not save anything this time, since the link second argument
++					   had some other links as well.  */
++					if (ctl->verbose > 1)
++						printf(_(" %s %s to %s\n"),
++							(ctl->no_link ? _("Would link") : _("Linked")),
++							n1, n2);
++				} else {
++					ctl->nsaved += ((st.st_size + 4095) / 4096) * 4096;
++					if (ctl->verbose > 1)
++						printf(_(" %s %s to %s, %s %jd\n"),
++							(ctl->no_link ? _("Would link") : _("Linked")),
++							n1, n2,
++							(ctl->no_link ? _("would save") : _("saved")),
++							(intmax_t)st.st_size);
++				}
++				close(fd);
++				return;
++			}
++		}
++		fp2 = xmalloc(add3(sizeof(*fp2), namelen, 1));
++		close(fd);
++		fp2->ino = st.st_ino;
++		fp2->dev = st.st_dev;
++		fp2->cksum = cksum;
++		memcpy(fp2->name, name, namelen + 1);
++
++		if (fp) {
++			fp2->next = fp->next;
++			fp->next = fp2;
++		} else {
++			fp2->next = hp->chain;
++			hp->chain = fp2;
++		}
++		return;
++	}
++}
++
++int main(int argc, char **argv)
++{
++	int ch;
++	int i;
++#ifdef HAVE_PCRE
++	int errornumber;
++	PCRE2_SIZE erroroffset;
++	pcre2_code *re = NULL;
++	PCRE2_SPTR exclude_pattern = NULL;
++	pcre2_match_data *match_data = NULL;
++#endif
++	struct hardlink_dynstr nam1 = { NULL, 0 };
++	struct hardlink_ctl *ctl = &global_ctl;
++
++	static const struct option longopts[] = {
++		{ "content",    no_argument, NULL, 'c' },
++		{ "dry-run",    no_argument, NULL, 'n' },
++		{ "exclude",    required_argument, NULL, 'x' },
++		{ "force",      no_argument, NULL, 'f' },
++		{ "help",       no_argument, NULL, 'h' },
++		{ "verbose",    no_argument, NULL, 'v' },
++		{ "version",    no_argument, NULL, 'V' },
++		{ NULL, 0, NULL, 0 },
++	};
++
++	setlocale(LC_ALL, "");
++	bindtextdomain(PACKAGE, LOCALEDIR);
++	textdomain(PACKAGE);
++	close_stdout_atexit();
++
++	while ((ch = getopt_long(argc, argv, "cnvfx:Vh", longopts, NULL)) != -1) {
++		switch (ch) {
++		case 'n':
++			ctl->no_link = 1;
++			break;
++		case 'v':
++			ctl->verbose++;
++			break;
++		case 'c':
++			ctl->content_only = 1;
++			break;
++		case 'f':
++			ctl->force = 1;
++			break;
++		case 'x':
++#ifdef HAVE_PCRE
++			exclude_pattern = (PCRE2_SPTR) optarg;
++#else
++			errx(EXIT_FAILURE,
++			     _("option --exclude not supported (built without pcre2)"));
++#endif
++			break;
++		case 'V':
++			print_version(EXIT_SUCCESS);
++		case 'h':
++			usage();
++		default:
++			errtryhelp(EXIT_FAILURE);
++		}
++	}
++
++	if (optind == argc) {
++		warnx(_("no directory specified"));
++		errtryhelp(EXIT_FAILURE);
++	}
++
++#ifdef HAVE_PCRE
++	if (exclude_pattern) {
++		re = pcre2_compile(exclude_pattern, /* the pattern */
++				   PCRE2_ZERO_TERMINATED, /* indicates pattern is zero-terminate */
++				   0, /* default options */
++				   &errornumber, &erroroffset, NULL); /* use default compile context */
++		if (!re) {
++			PCRE2_UCHAR buffer[256];
++			pcre2_get_error_message(errornumber, buffer,
++						sizeof(buffer));
++			errx(EXIT_FAILURE, _("pattern error at offset %d: %s"),
++				(int)erroroffset, buffer);
++		}
++		match_data = pcre2_match_data_create_from_pattern(re, NULL);
++	}
++#endif
++	atexit(print_summary);
++
++	for (i = optind; i < argc; i++)
++		process_path(ctl, argv[i]);
++
++	while (ctl->dirs) {
++		DIR *dh;
++		struct dirent *di;
++		struct hardlink_dir *dp = ctl->dirs;
++		size_t nam1baselen = strlen(dp->name);
++
++		ctl->dirs = dp->next;
++		growstr(&nam1, add2(nam1baselen, 1));
++		memcpy(nam1.buf, dp->name, nam1baselen);
++		free(dp);
++		nam1.buf[nam1baselen++] = '/';
++		nam1.buf[nam1baselen] = 0;
++		dh = opendir(nam1.buf);
++
++		if (dh == NULL)
++			continue;
++		ctl->ndirs++;
++
++		while ((di = readdir(dh)) != NULL) {
++			if (!di->d_name[0])
++				continue;
++			if (di->d_name[0] == '.') {
++				if (!di->d_name[1] || !strcmp(di->d_name, ".."))
++					continue;
++			}
++#ifdef HAVE_PCRE
++			if (re && pcre2_match(re, /* compiled regex */
++					      (PCRE2_SPTR) di->d_name, strlen(di->d_name), 0, /* start at offset 0 */
++					      0, /* default options */
++					      match_data, /* block for storing the result */
++					      NULL) /* use default match context */
++			    >=0) {
++				if (ctl->verbose) {
++					nam1.buf[nam1baselen] = 0;
++					printf(_("Skipping %s%s\n"), nam1.buf, di->d_name);
++				}
++				continue;
++			}
++#endif
++			{
++				size_t subdirlen;
++				growstr(&nam1,
++					add2(nam1baselen, subdirlen =
++					     strlen(di->d_name)));
++				memcpy(&nam1.buf[nam1baselen], di->d_name,
++				       add2(subdirlen, 1));
++			}
++			process_path(ctl, nam1.buf);
++		}
++		closedir(dh);
++	}
++
++	return 0;
++}
+diff --git a/locale/programs/xalloc.h b/locale/programs/xalloc.h
+new file mode 100644
+index 0000000000..0129a85e2e
+--- /dev/null
++++ b/locale/programs/xalloc.h
+@@ -0,0 +1,129 @@
++/*
++ * Copyright (C) 2010 Davidlohr Bueso <dave@gnu.org>
++ *
++ * This file may be redistributed under the terms of the
++ * GNU Lesser General Public License.
++ *
++ * General memory allocation wrappers for malloc, realloc, calloc and strdup
++ */
++
++#ifndef UTIL_LINUX_XALLOC_H
++#define UTIL_LINUX_XALLOC_H
++
++#include <stdlib.h>
++#include <string.h>
++
++#include "c.h"
++
++#ifndef XALLOC_EXIT_CODE
++# define XALLOC_EXIT_CODE EXIT_FAILURE
++#endif
++
++static inline void __attribute__((__noreturn__))
++__err_oom(const char *file, unsigned int line)
++{
++	err(XALLOC_EXIT_CODE, "%s: %u: cannot allocate memory", file, line);
++}
++
++#define err_oom()	__err_oom(__FILE__, __LINE__)
++
++static inline __ul_alloc_size(1) __ul_returns_nonnull
++void *xmalloc(const size_t size)
++{
++        void *ret = malloc(size);
++
++        if (!ret && size)
++                err(XALLOC_EXIT_CODE, "cannot allocate %zu bytes", size);
++        return ret;
++}
++
++static inline __ul_alloc_size(2) __ul_returns_nonnull
++void *xrealloc(void *ptr, const size_t size)
++{
++        void *ret = realloc(ptr, size);
++
++        if (!ret && size)
++                err(XALLOC_EXIT_CODE, "cannot allocate %zu bytes", size);
++        return ret;
++}
++
++static inline __ul_calloc_size(1, 2) __ul_returns_nonnull
++void *xcalloc(const size_t nelems, const size_t size)
++{
++        void *ret = calloc(nelems, size);
++
++        if (!ret && size && nelems)
++                err(XALLOC_EXIT_CODE, "cannot allocate %zu bytes", size);
++        return ret;
++}
++
++static inline char __attribute__((warn_unused_result)) __ul_returns_nonnull
++*xstrdup(const char *str)
++{
++        char *ret;
++
++        if (!str)
++                return NULL;
++
++        ret = strdup(str);
++
++        if (!ret)
++                err(XALLOC_EXIT_CODE, "cannot duplicate string");
++        return ret;
++}
++
++static inline char * __attribute__((warn_unused_result)) __ul_returns_nonnull
++xstrndup(const char *str, size_t size)
++{
++        char *ret;
++
++        if (!str)
++                return NULL;
++
++        ret = strndup(str, size);
++
++        if (!ret)
++                err(XALLOC_EXIT_CODE, "cannot duplicate string");
++        return ret;
++}
++
++
++static inline int __attribute__ ((__format__(printf, 2, 3)))
++    xasprintf(char **strp, const char *fmt, ...)
++{
++	int ret;
++	va_list args;
++	va_start(args, fmt);
++	ret = vasprintf(&(*strp), fmt, args);
++	va_end(args);
++	if (ret < 0)
++		err(XALLOC_EXIT_CODE, "cannot allocate string");
++	return ret;
++}
++
++static inline int  __attribute__ ((__format__(printf, 2, 0)))
++xvasprintf(char **strp, const char *fmt, va_list ap)
++{
++	int ret = vasprintf(&(*strp), fmt, ap);
++	if (ret < 0)
++		err(XALLOC_EXIT_CODE, "cannot allocate string");
++	return ret;
++}
++
++
++static inline char * __attribute__((warn_unused_result)) xgethostname(void)
++{
++	char *name;
++	size_t sz = get_hostname_max() + 1;
++
++	name = xmalloc(sizeof(char) * sz);
++
++	if (gethostname(name, sz) != 0) {
++		free(name);
++		return NULL;
++	}
++	name[sz - 1] = '\0';
++	return name;
++}
++
++#endif

+ 150 - 0
recipes-core/glibc/glibc/0002-CVE-2021-38604.patch

@@ -0,0 +1,150 @@
+From 4cc79c217744743077bf7a0ec5e0a4318f1e6641 Mon Sep 17 00:00:00 2001
+From: Nikita Popov <npv1310@gmail.com>
+Date: Thu, 12 Aug 2021 16:09:50 +0530
+Subject: [PATCH] librt: add test (bug 28213)
+
+This test implements following logic:
+1) Create POSIX message queue.
+   Register a notification with mq_notify (using NULL attributes).
+   Then immediately unregister the notification with mq_notify.
+   Helper thread in a vulnerable version of glibc
+   should cause NULL pointer dereference after these steps.
+2) Once again, register the same notification.
+   Try to send a dummy message.
+   Test is considered successfulif the dummy message
+   is successfully received by the callback function.
+
+Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commit;h=4cc79c217744743077bf7a0ec5e0a4318f1e6641]
+CVE: CVE-2021-38604
+
+Signed-off-by: Nikita Popov <npv1310@gmail.com>
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Signed-off-by: Vinay Kumar <vinay.m.engg@gmail.com>
+---
+ rt/Makefile      |   1 +
+ rt/tst-bz28213.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 102 insertions(+)
+ create mode 100644 rt/tst-bz28213.c
+
+diff --git a/rt/Makefile b/rt/Makefile
+index 113cea03a5..910e775995 100644
+--- a/rt/Makefile
++++ b/rt/Makefile
+@@ -74,6 +74,7 @@ tests := tst-shm tst-timer tst-timer2 \
+ 	 tst-aio7 tst-aio8 tst-aio9 tst-aio10 \
+ 	 tst-mqueue1 tst-mqueue2 tst-mqueue3 tst-mqueue4 \
+ 	 tst-mqueue5 tst-mqueue6 tst-mqueue7 tst-mqueue8 tst-mqueue9 \
++	 tst-bz28213 \
+ 	 tst-timer3 tst-timer4 tst-timer5 \
+ 	 tst-cpuclock2 tst-cputimer1 tst-cputimer2 tst-cputimer3 \
+ 	 tst-shm-cancel \
+diff --git a/rt/tst-bz28213.c b/rt/tst-bz28213.c
+new file mode 100644
+index 0000000000..0c096b5a0a
+--- /dev/null
++++ b/rt/tst-bz28213.c
+@@ -0,0 +1,101 @@
++/* Bug 28213: test for NULL pointer dereference in mq_notify.
++   Copyright (C) The GNU Toolchain Authors.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#include <errno.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <unistd.h>
++#include <mqueue.h>
++#include <signal.h>
++#include <stdlib.h>
++#include <string.h>
++#include <support/check.h>
++
++static mqd_t m = -1;
++static const char msg[] = "hello";
++
++static void
++check_bz28213_cb (union sigval sv)
++{
++  char buf[sizeof (msg)];
++
++  (void) sv;
++
++  TEST_VERIFY_EXIT ((size_t) mq_receive (m, buf, sizeof (buf), NULL)
++		    == sizeof (buf));
++  TEST_VERIFY_EXIT (memcmp (buf, msg, sizeof (buf)) == 0);
++
++  exit (0);
++}
++
++static void
++check_bz28213 (void)
++{
++  struct sigevent sev;
++
++  memset (&sev, '\0', sizeof (sev));
++  sev.sigev_notify = SIGEV_THREAD;
++  sev.sigev_notify_function = check_bz28213_cb;
++
++  /* Step 1: Register & unregister notifier.
++     Helper thread should receive NOTIFY_REMOVED notification.
++     In a vulnerable version of glibc, NULL pointer dereference follows. */
++  TEST_VERIFY_EXIT (mq_notify (m, &sev) == 0);
++  TEST_VERIFY_EXIT (mq_notify (m, NULL) == 0);
++
++  /* Step 2: Once again, register notification.
++     Try to send one message.
++     Test is considered successful, if the callback does exit (0). */
++  TEST_VERIFY_EXIT (mq_notify (m, &sev) == 0);
++  TEST_VERIFY_EXIT (mq_send (m, msg, sizeof (msg), 1) == 0);
++
++  /* Wait... */
++  pause ();
++}
++
++static int
++do_test (void)
++{
++  static const char m_name[] = "/bz28213_queue";
++  struct mq_attr m_attr;
++
++  memset (&m_attr, '\0', sizeof (m_attr));
++  m_attr.mq_maxmsg = 1;
++  m_attr.mq_msgsize = sizeof (msg);
++
++  m = mq_open (m_name,
++               O_RDWR | O_CREAT | O_EXCL,
++               0600,
++               &m_attr);
++
++  if (m < 0)
++    {
++      if (errno == ENOSYS)
++        FAIL_UNSUPPORTED ("POSIX message queues are not implemented\n");
++      FAIL_EXIT1 ("Failed to create POSIX message queue: %m\n");
++    }
++
++  TEST_VERIFY_EXIT (mq_unlink (m_name) == 0);
++
++  check_bz28213 ();
++
++  return 0;
++}
++
++#include <support/test-driver.c>
+-- 
+2.31.1
+

+ 238 - 0
recipes-core/glibc/glibc/0002-localedef-fix-ups-hardlink-to-make-it-compile.patch

@@ -0,0 +1,238 @@
+From d7bb36a9a27e5e4c3be6378493b41286513750e9 Mon Sep 17 00:00:00 2001
+From: Jason Wessel <jason.wessel@windriver.com>
+Date: Sat, 7 Dec 2019 10:01:37 -0800
+Subject: [PATCH] localedef: fix-ups hardlink to make it compile
+
+Upstream-Status: Pending
+Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ locale/programs/c.h                        |  2 +-
+ locale/programs/cross-localedef-hardlink.c | 79 +++++++++++-----------
+ 2 files changed, 39 insertions(+), 42 deletions(-)
+
+diff --git a/locale/programs/c.h b/locale/programs/c.h
+index d0a402e90e..1804d31c73 100644
+--- a/locale/programs/c.h
++++ b/locale/programs/c.h
+@@ -240,7 +240,7 @@ errmsg(char doexit, int excode, char adderr, const char *fmt, ...)
+ /* Don't use inline function to avoid '#include "nls.h"' in c.h
+  */
+ #define errtryhelp(eval) __extension__ ({ \
+-	fprintf(stderr, _("Try '%s --help' for more information.\n"), \
++	fprintf(stderr, ("Try '%s --help' for more information.\n"), \
+ 			program_invocation_short_name); \
+ 	exit(eval); \
+ })
+diff --git a/locale/programs/cross-localedef-hardlink.c b/locale/programs/cross-localedef-hardlink.c
+index 63615896b0..726e6dd948 100644
+--- a/locale/programs/cross-localedef-hardlink.c
++++ b/locale/programs/cross-localedef-hardlink.c
+@@ -20,6 +20,8 @@
+  * with this program; if not, write to the Free Software Foundation, Inc.,
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+  */
++
++#undef HAVE_PCRE
+ #include <sys/types.h>
+ #include <stdlib.h>
+ #include <getopt.h>
+@@ -38,8 +40,8 @@
+ 
+ #include "c.h"
+ #include "xalloc.h"
+-#include "nls.h"
+-#include "closestream.h"
++//#include "nls.h"
++//#include "closestream.h"
+ 
+ #define NHASH   (1<<17)  /* Must be a power of 2! */
+ #define NBUF    64
+@@ -124,33 +126,33 @@ static void print_summary(void)
+ 	if (ctl->verbose > 1 && ctl->nlinks)
+ 		fputc('\n', stdout);
+ 
+-	printf(_("Directories:   %9lld\n"), ctl->ndirs);
+-	printf(_("Objects:       %9lld\n"), ctl->nobjects);
+-	printf(_("Regular files: %9lld\n"), ctl->nregfiles);
+-	printf(_("Comparisons:   %9lld\n"), ctl->ncomp);
++	printf(("Directories:   %9lld\n"), ctl->ndirs);
++	printf(("Objects:       %9lld\n"), ctl->nobjects);
++	printf(("Regular files: %9lld\n"), ctl->nregfiles);
++	printf(("Comparisons:   %9lld\n"), ctl->ncomp);
+ 	printf(  "%s%9lld\n", (ctl->no_link ?
+-	       _("Would link:    ") :
+-	       _("Linked:        ")), ctl->nlinks);
++	       ("Would link:    ") :
++	       ("Linked:        ")), ctl->nlinks);
+ 	printf(  "%s %9lld\n", (ctl->no_link ?
+-	       _("Would save:   ") :
+-	       _("Saved:        ")), ctl->nsaved);
++	       ("Would save:   ") :
++	       ("Saved:        ")), ctl->nsaved);
+ }
+ 
+ static void __attribute__((__noreturn__)) usage(void)
+ {
+ 	fputs(USAGE_HEADER, stdout);
+-	printf(_(" %s [options] directory...\n"), program_invocation_short_name);
++	printf((" %s [options] directory...\n"), program_invocation_short_name);
+ 
+ 	fputs(USAGE_SEPARATOR, stdout);
+-	puts(_("Consolidate duplicate files using hardlinks."));
++	puts(("Consolidate duplicate files using hardlinks."));
+ 
+ 	fputs(USAGE_OPTIONS, stdout);
+-	puts(_(" -c, --content          compare only contents, ignore permission, etc."));
+-	puts(_(" -n, --dry-run          don't actually link anything"));
+-	puts(_(" -v, --verbose          print summary after hardlinking"));
+-	puts(_(" -vv                    print every hardlinked file and summary"));
+-	puts(_(" -f, --force            force hardlinking across filesystems"));
+-	puts(_(" -x, --exclude <regex>  exclude files matching pattern"));
++	puts((" -c, --content          compare only contents, ignore permission, etc."));
++	puts((" -n, --dry-run          don't actually link anything"));
++	puts((" -v, --verbose          print summary after hardlinking"));
++	puts((" -vv                    print every hardlinked file and summary"));
++	puts((" -f, --force            force hardlinking across filesystems"));
++	puts((" -x, --exclude <regex>  exclude files matching pattern"));
+ 
+ 	fputs(USAGE_SEPARATOR, stdout);
+ 	printf(USAGE_HELP_OPTIONS(16)); /* char offset to align option descriptions */
+@@ -164,7 +166,7 @@ static inline size_t add2(size_t a, size_t b)
+ 	size_t sum = a + b;
+ 
+ 	if (sum < a)
+-		errx(EXIT_FAILURE, _("integer overflow"));
++		errx(EXIT_FAILURE, ("integer overflow"));
+ 	return sum;
+ }
+ 
+@@ -193,7 +195,7 @@ static void process_path(struct hardlink_ctl *ctl, const char *name)
+ 	if (st.st_dev != ctl->dev && !ctl->force) {
+ 		if (ctl->dev)
+ 			errx(EXIT_FAILURE,
+-			     _("%s is on different filesystem than the rest "
++			     ("%s is on different filesystem than the rest "
+ 			       "(use -f option to override)."), name);
+ 		ctl->dev = st.st_dev;
+ 	}
+@@ -287,9 +289,9 @@ static void process_path(struct hardlink_ctl *ctl, const char *name)
+ 							(ssize_t) sizeof(ctl->iobuf1) : fsize;
+ 
+ 					if ((xsz = read(fd, ctl->iobuf1, rsize)) != rsize)
+-						warn(_("cannot read %s"), name);
++						warn(("cannot read %s"), name);
+ 					else if ((xsz = read(fd2, ctl->iobuf2, rsize)) != rsize)
+-						warn(_("cannot read %s"), fp2->name);
++						warn(("cannot read %s"), fp2->name);
+ 
+ 					if (xsz != rsize) {
+ 						close(fd);
+@@ -303,13 +305,13 @@ static void process_path(struct hardlink_ctl *ctl, const char *name)
+ 				if (fsize > 0)
+ 					continue;
+ 				if (lstat(name, &st3)) {
+-					warn(_("cannot stat %s"), name);
++					warn(("cannot stat %s"), name);
+ 					close(fd);
+ 					return;
+ 				}
+ 				st3.st_atime = st.st_atime;
+ 				if (stcmp(&st, &st3, 0)) {
+-					warnx(_("file %s changed underneath us"), name);
++					warnx(("file %s changed underneath us"), name);
+ 					close(fd);
+ 					return;
+ 				}
+@@ -329,18 +331,18 @@ static void process_path(struct hardlink_ctl *ctl, const char *name)
+ 					       suffixlen + 1);
+ 					/* First create a temporary link to n1 under a new name */
+ 					if (link(n1, nam2.buf)) {
+-						warn(_("failed to hardlink %s to %s (create temporary link as %s failed)"),
++						warn(("failed to hardlink %s to %s (create temporary link as %s failed)"),
+ 							n1, n2, nam2.buf);
+ 						free(nam2.buf);
+ 						continue;
+ 					}
+ 					/* Then rename into place over the existing n2 */
+ 					if (rename(nam2.buf, n2)) {
+-						warn(_("failed to hardlink %s to %s (rename temporary link to %s failed)"),
++						warn(("failed to hardlink %s to %s (rename temporary link to %s failed)"),
+ 							n1, n2, n2);
+ 						/* Something went wrong, try to remove the now redundant temporary link */
+ 						if (unlink(nam2.buf))
+-							warn(_("failed to remove temporary link %s"), nam2.buf);
++							warn(("failed to remove temporary link %s"), nam2.buf);
+ 						free(nam2.buf);
+ 						continue;
+ 					}
+@@ -351,16 +353,16 @@ static void process_path(struct hardlink_ctl *ctl, const char *name)
+ 					/* We actually did not save anything this time, since the link second argument
+ 					   had some other links as well.  */
+ 					if (ctl->verbose > 1)
+-						printf(_(" %s %s to %s\n"),
+-							(ctl->no_link ? _("Would link") : _("Linked")),
++						printf((" %s %s to %s\n"),
++							(ctl->no_link ? ("Would link") : ("Linked")),
+ 							n1, n2);
+ 				} else {
+ 					ctl->nsaved += ((st.st_size + 4095) / 4096) * 4096;
+ 					if (ctl->verbose > 1)
+-						printf(_(" %s %s to %s, %s %jd\n"),
+-							(ctl->no_link ? _("Would link") : _("Linked")),
++						printf((" %s %s to %s, %s %jd\n"),
++							(ctl->no_link ? ("Would link") : ("Linked")),
+ 							n1, n2,
+-							(ctl->no_link ? _("would save") : _("saved")),
++							(ctl->no_link ? ("would save") : ("saved")),
+ 							(intmax_t)st.st_size);
+ 				}
+ 				close(fd);
+@@ -410,11 +412,6 @@ int main(int argc, char **argv)
+ 		{ NULL, 0, NULL, 0 },
+ 	};
+ 
+-	setlocale(LC_ALL, "");
+-	bindtextdomain(PACKAGE, LOCALEDIR);
+-	textdomain(PACKAGE);
+-	close_stdout_atexit();
+-
+ 	while ((ch = getopt_long(argc, argv, "cnvfx:Vh", longopts, NULL)) != -1) {
+ 		switch (ch) {
+ 		case 'n':
+@@ -434,7 +431,7 @@ int main(int argc, char **argv)
+ 			exclude_pattern = (PCRE2_SPTR) optarg;
+ #else
+ 			errx(EXIT_FAILURE,
+-			     _("option --exclude not supported (built without pcre2)"));
++			     ("option --exclude not supported (built without pcre2)"));
+ #endif
+ 			break;
+ 		case 'V':
+@@ -447,7 +444,7 @@ int main(int argc, char **argv)
+ 	}
+ 
+ 	if (optind == argc) {
+-		warnx(_("no directory specified"));
++		warnx(("no directory specified"));
+ 		errtryhelp(EXIT_FAILURE);
+ 	}
+ 
+@@ -461,7 +458,7 @@ int main(int argc, char **argv)
+ 			PCRE2_UCHAR buffer[256];
+ 			pcre2_get_error_message(errornumber, buffer,
+ 						sizeof(buffer));
+-			errx(EXIT_FAILURE, _("pattern error at offset %d: %s"),
++			errx(EXIT_FAILURE, ("pattern error at offset %d: %s"),
+ 				(int)erroroffset, buffer);
+ 		}
+ 		match_data = pcre2_match_data_create_from_pattern(re, NULL);
+@@ -506,7 +503,7 @@ int main(int argc, char **argv)
+ 			    >=0) {
+ 				if (ctl->verbose) {
+ 					nam1.buf[nam1baselen] = 0;
+-					printf(_("Skipping %s%s\n"), nam1.buf, di->d_name);
++					printf(("Skipping %s%s\n"), nam1.buf, di->d_name);
+ 				}
+ 				continue;
+ 			}

+ 65 - 0
recipes-core/glibc/glibc/0003-nativesdk-glibc-Look-for-host-system-ld.so.cache-as-.patch

@@ -0,0 +1,65 @@
+From 776a53db6afba8a7ff4412aba88b0679227877f9 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Wed, 18 Mar 2015 01:48:24 +0000
+Subject: [PATCH] nativesdk-glibc: Look for host system ld.so.cache as well
+
+Upstream-Status: Inappropriate [embedded specific]
+
+The default lib search path order is:
+
+  1) LD_LIBRARY_PATH
+  2) RPATH from the binary
+  3) ld.so.cache
+  4) default search paths embedded in the linker
+
+For nativesdk binaries which are being used alongside binaries on a host system, we
+need the search paths to firstly search the shipped nativesdk libs but then also
+cover the host system. For example we want the host system's libGL and this may be
+in a non-standard location like /usr/lib/mesa. The only place the location is know
+about is in the ld.so.cache of the host system.
+
+Since nativesdk has a simple structure and doesn't need to use a cache itself, we
+repurpose the cache for use as a last resort in finding host system binaries. This
+means we need to switch the order of 3 and 4 above to make this work effectively.
+
+RP 14/10/2010
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ elf/dl-load.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/elf/dl-load.c b/elf/dl-load.c
+index a08df001af..d09daf9e41 100644
+--- a/elf/dl-load.c
++++ b/elf/dl-load.c
+@@ -2196,6 +2196,14 @@ _dl_map_object (struct link_map *loader, const char *name,
+             }
+         }
+ 
++      /* try the default path.  */
++      if (fd == -1
++	  && ((l = loader ?: GL(dl_ns)[nsid]._ns_loaded) == NULL
++	   || __builtin_expect (!(l->l_flags_1 & DF_1_NODEFLIB), 1))
++	 && __rtld_search_dirs.dirs != (void *) -1)
++	fd = open_path (name, namelen, mode & __RTLD_SECURE, &__rtld_search_dirs,
++			&realname, &fb, l, LA_SER_DEFAULT, &found_other_class);
++      /* Finally try ld.so.cache */
+ #ifdef USE_LDCONFIG
+       if (fd == -1
+ 	  && (__glibc_likely ((mode & __RTLD_SECURE) == 0)
+@@ -2254,14 +2262,6 @@ _dl_map_object (struct link_map *loader, const char *name,
+ 	}
+ #endif
+ 
+-      /* Finally, try the default path.  */
+-      if (fd == -1
+-	  && ((l = loader ?: GL(dl_ns)[nsid]._ns_loaded) == NULL
+-	      || __glibc_likely (!(l->l_flags_1 & DF_1_NODEFLIB)))
+-	  && __rtld_search_dirs.dirs != (void *) -1)
+-	fd = open_path (name, namelen, mode, &__rtld_search_dirs,
+-			&realname, &fb, l, LA_SER_DEFAULT, &found_other_class);
+-
+       /* Add another newline when we are tracing the library loading.  */
+       if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
+ 	_dl_debug_printf ("\n");

+ 46 - 0
recipes-core/glibc/glibc/0004-nativesdk-glibc-Fix-buffer-overrun-with-a-relocated-.patch

@@ -0,0 +1,46 @@
+From df18bae1eeee55ecb9db36d13fe67c58355682eb Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Wed, 18 Mar 2015 01:50:00 +0000
+Subject: [PATCH] nativesdk-glibc: Fix buffer overrun with a relocated SDK
+
+When ld-linux-*.so.2 is relocated to a path that is longer than the
+original fixed location, the dynamic loader will crash in open_path
+because it implicitly assumes that max_dirnamelen is a fixed size that
+never changes.
+
+The allocated buffer will not be large enough to contain the directory
+path string which is larger than the fixed location provided at build
+time.
+
+Upstream-Status: Inappropriate [OE SDK specific]
+
+Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ elf/dl-load.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/elf/dl-load.c b/elf/dl-load.c
+index d09daf9e41..2c6270e2a7 100644
+--- a/elf/dl-load.c
++++ b/elf/dl-load.c
+@@ -1892,7 +1892,19 @@ open_path (const char *name, size_t namelen, int mode,
+        given on the command line when rtld is run directly.  */
+     return -1;
+ 
++  do
++    {
++      struct r_search_path_elem *this_dir = *dirs;
++      if (this_dir->dirnamelen > max_dirnamelen)
++	{
++	  max_dirnamelen = this_dir->dirnamelen;
++	}
++    }
++  while (*++dirs != NULL);
++
+   buf = alloca (max_dirnamelen + max_capstrlen + namelen);
++
++  dirs = sps->dirs;
+   do
+     {
+       struct r_search_path_elem *this_dir = *dirs;

+ 153 - 0
recipes-core/glibc/glibc/0005-nativesdk-glibc-Raise-the-size-of-arrays-containing-.patch

@@ -0,0 +1,153 @@
+From 6af8ce8eceed86addbc188f773a2d36d83ee4042 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Wed, 18 Mar 2015 01:51:38 +0000
+Subject: [PATCH] nativesdk-glibc: Raise the size of arrays containing dl paths
+
+This patch puts the dynamic loader path in the binaries, SYSTEM_DIRS strings
+and lengths as well as ld.so.cache path in the dynamic loader to specific
+sections in memory. The sections that contain paths have been allocated a 4096
+byte section, which is the maximum path length in linux. This will allow the
+relocating script to parse the ELF binary, detect the section and easily replace
+the strings in a certain path.
+
+Upstream-Status: Inappropriate [SDK specific]
+
+Signed-off-by: Laurentiu Palcu <laurentiu.palcu@intel.com>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ elf/dl-cache.c             | 4 ++++
+ elf/dl-load.c              | 4 ++--
+ elf/dl-usage.c             | 6 ++++--
+ elf/interp.c               | 2 +-
+ elf/ldconfig.c             | 3 +++
+ elf/rtld.c                 | 1 +
+ iconv/gconv_conf.c         | 2 +-
+ sysdeps/generic/dl-cache.h | 4 ----
+ 8 files changed, 16 insertions(+), 10 deletions(-)
+
+diff --git a/elf/dl-cache.c b/elf/dl-cache.c
+index 2b8da8650d..3d9787bda4 100644
+--- a/elf/dl-cache.c
++++ b/elf/dl-cache.c
+@@ -355,6 +355,10 @@ search_cache (const char *string_table, uint32_t string_table_size,
+   return best;
+ }
+ 
++const char LD_SO_CACHE[4096] __attribute__ ((section (".ldsocache"))) =
++		SYSCONFDIR "/ld.so.cache";
++
++
+ int
+ _dl_cache_libcmp (const char *p1, const char *p2)
+ {
+diff --git a/elf/dl-load.c b/elf/dl-load.c
+index 2c6270e2a7..23018d2f7e 100644
+--- a/elf/dl-load.c
++++ b/elf/dl-load.c
+@@ -115,8 +115,8 @@ enum { ncapstr = 1, max_capstrlen = 0 };
+    gen-trusted-dirs.awk.  */
+ #include "trusted-dirs.h"
+ 
+-static const char system_dirs[] = SYSTEM_DIRS;
+-static const size_t system_dirs_len[] =
++static const char system_dirs[4096] __attribute__ ((section (".sysdirs"))) = SYSTEM_DIRS;
++volatile static const size_t system_dirs_len[] __attribute__ ((section (".sysdirslen"))) =
+ {
+   SYSTEM_DIRS_LEN
+ };
+diff --git a/elf/dl-usage.c b/elf/dl-usage.c
+index 5ad3a72559..88f26d3692 100644
+--- a/elf/dl-usage.c
++++ b/elf/dl-usage.c
+@@ -25,6 +25,8 @@
+ #include <dl-procinfo.h>
+ #include <dl-hwcaps.h>
+ 
++extern const char LD_SO_CACHE[4096] __attribute__ ((section (".ldsocache")));
++
+ void
+ _dl_usage (const char *argv0, const char *wrong_option)
+ {
+@@ -244,7 +246,7 @@ setting environment variables (which would be inherited by subprocesses).\n\
+   --list                list all dependencies and how they are resolved\n\
+   --verify              verify that given object really is a dynamically linked\n\
+                         object we can handle\n\
+-  --inhibit-cache       Do not use " LD_SO_CACHE "\n\
++  --inhibit-cache       Do not use %s\n\
+   --library-path PATH   use given PATH instead of content of the environment\n\
+                         variable LD_LIBRARY_PATH\n\
+   --glibc-hwcaps-prepend LIST\n\
+@@ -267,7 +269,7 @@ setting environment variables (which would be inherited by subprocesses).\n\
+ \n\
+ This program interpreter self-identifies as: " RTLD "\n\
+ ",
+-              argv0);
++              argv0, LD_SO_CACHE);
+   print_search_path_for_help (state);
+   print_hwcaps_subdirectories (state);
+   print_legacy_hwcap_directories ();
+diff --git a/elf/interp.c b/elf/interp.c
+index 91966702ca..dc86c20e83 100644
+--- a/elf/interp.c
++++ b/elf/interp.c
+@@ -18,5 +18,5 @@
+ 
+ #include <runtime-linker.h>
+ 
+-const char __invoke_dynamic_linker__[] __attribute__ ((section (".interp")))
++const char __invoke_dynamic_linker__[4096] __attribute__ ((section (".interp")))
+   = RUNTIME_LINKER;
+diff --git a/elf/ldconfig.c b/elf/ldconfig.c
+index 1037e8d0cf..ffdac84952 100644
+--- a/elf/ldconfig.c
++++ b/elf/ldconfig.c
+@@ -177,6 +177,9 @@ static struct argp argp =
+   options, parse_opt, NULL, doc, NULL, more_help, NULL
+ };
+ 
++
++extern const char LD_SO_CACHE[4096] __attribute__ ((section (".ldsocache")));
++
+ /* Check if string corresponds to an important hardware capability or
+    a platform.  */
+ static int
+diff --git a/elf/rtld.c b/elf/rtld.c
+index fbbd60b446..fce9940f80 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -185,6 +185,7 @@ dso_name_valid_for_suid (const char *p)
+     }
+   return *p != '\0';
+ }
++extern const char LD_SO_CACHE[4096] __attribute__ ((section (".ldsocache")));
+ 
+ static void
+ audit_list_init (struct audit_list *list)
+diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c
+index 62bee28769..67b60dc88c 100644
+--- a/iconv/gconv_conf.c
++++ b/iconv/gconv_conf.c
+@@ -36,7 +36,7 @@
+ #include <gconv_parseconfdir.h>
+ 
+ /* This is the default path where we look for module lists.  */
+-static const char default_gconv_path[] = GCONV_PATH;
++static char default_gconv_path[4096] __attribute__ ((section (".gccrelocprefix"))) = GCONV_PATH;
+ 
+ /* Type to represent search path.  */
+ struct path_elem
+diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h
+index 964d50a486..94bf68ca9d 100644
+--- a/sysdeps/generic/dl-cache.h
++++ b/sysdeps/generic/dl-cache.h
+@@ -34,10 +34,6 @@
+   ((flags) == 1 || (flags) == _DL_CACHE_DEFAULT_ID)
+ #endif
+ 
+-#ifndef LD_SO_CACHE
+-# define LD_SO_CACHE SYSCONFDIR "/ld.so.cache"
+-#endif
+-
+ #ifndef add_system_dir
+ # define add_system_dir(dir) add_dir (dir)
+ #endif

+ 39 - 0
recipes-core/glibc/glibc/0006-nativesdk-glibc-Allow-64-bit-atomics-for-x86.patch

@@ -0,0 +1,39 @@
+From b30f380cd88ae181a4a6a3a4784206ffe3ccd19b Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Thu, 31 Dec 2015 14:35:35 -0800
+Subject: [PATCH] nativesdk-glibc: Allow 64 bit atomics for x86
+
+The fix consist of allowing 64bit atomic ops for x86.
+This should be safe for i586 and newer CPUs.
+It also makes the synchronization more efficient.
+
+Upstream-Status: Inappropriate [OE-Specific]
+
+Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
+Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ sysdeps/x86/atomic-machine.h | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/sysdeps/x86/atomic-machine.h b/sysdeps/x86/atomic-machine.h
+index 695222e4fa..9d39bfdbd5 100644
+--- a/sysdeps/x86/atomic-machine.h
++++ b/sysdeps/x86/atomic-machine.h
+@@ -52,15 +52,14 @@ typedef uintmax_t uatomic_max_t;
+ #define LOCK_PREFIX "lock;"
+ 
+ #define USE_ATOMIC_COMPILER_BUILTINS	1
++# define __HAVE_64B_ATOMICS		1
+ 
+ #ifdef __x86_64__
+-# define __HAVE_64B_ATOMICS		1
+ # define SP_REG				"rsp"
+ # define SEG_REG			"fs"
+ # define BR_CONSTRAINT			"q"
+ # define IBR_CONSTRAINT			"iq"
+ #else
+-# define __HAVE_64B_ATOMICS		0
+ # define SP_REG				"esp"
+ # define SEG_REG			"gs"
+ # define BR_CONSTRAINT			"r"

+ 100 - 0
recipes-core/glibc/glibc/0007-nativesdk-glibc-Make-relocatable-install-for-locales.patch

@@ -0,0 +1,100 @@
+From 24bffe9c2645cd6542e29cb57786dc703cced07b Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Fri, 3 Aug 2018 09:55:12 -0700
+Subject: [PATCH] nativesdk-glibc: Make relocatable install for locales
+
+The glibc locale path is hard-coded to the install prefix, but in SDKs we need
+to be able to relocate the binaries.  Expand the strings to 4K and put them in a
+magic segment that we can relocate at install time.
+
+Upstream-Status: Inappropriate (OE-specific)
+
+Signed-off-by: Ross Burton <ross.burton@intel.com>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ locale/findlocale.c      | 4 ++--
+ locale/loadarchive.c     | 2 +-
+ locale/localeinfo.h      | 2 +-
+ locale/programs/locale.c | 7 ++++---
+ 4 files changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/locale/findlocale.c b/locale/findlocale.c
+index ab09122b0c..f42cc75780 100644
+--- a/locale/findlocale.c
++++ b/locale/findlocale.c
+@@ -56,7 +56,7 @@ struct __locale_data *const _nl_C[] attribute_hidden =
+    which are somehow addressed.  */
+ struct loaded_l10nfile *_nl_locale_file_list[__LC_LAST];
+ 
+-const char _nl_default_locale_path[] attribute_hidden = COMPLOCALEDIR;
++char _nl_default_locale_path[4096] attribute_hidden __attribute__ ((section (".gccrelocprefix"))) = COMPLOCALEDIR;
+ 
+ /* Checks if the name is actually present, that is, not NULL and not
+    empty.  */
+@@ -166,7 +166,7 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len,
+ 
+       /* Nothing in the archive.  Set the default path to search below.  */
+       locale_path = _nl_default_locale_path;
+-      locale_path_len = sizeof _nl_default_locale_path;
++      locale_path_len = strlen(locale_path) + 1;
+     }
+   else
+     /* We really have to load some data.  First see whether the name is
+diff --git a/locale/loadarchive.c b/locale/loadarchive.c
+index 512769eaec..436619091b 100644
+--- a/locale/loadarchive.c
++++ b/locale/loadarchive.c
+@@ -42,7 +42,7 @@
+ 
+ 
+ /* Name of the locale archive file.  */
+-static const char archfname[] = COMPLOCALEDIR "/locale-archive";
++static const char archfname[4096] __attribute__ ((section (".gccrelocprefix"))) = COMPLOCALEDIR "/locale-archive";
+ 
+ /* Size of initial mapping window, optimal if large enough to
+    cover the header plus the initial locale.  */
+diff --git a/locale/localeinfo.h b/locale/localeinfo.h
+index b3d4da0185..22f9dc1140 100644
+--- a/locale/localeinfo.h
++++ b/locale/localeinfo.h
+@@ -331,7 +331,7 @@ _nl_lookup_word (locale_t l, int category, int item)
+ }
+ 
+ /* Default search path if no LOCPATH environment variable.  */
+-extern const char _nl_default_locale_path[] attribute_hidden;
++extern char _nl_default_locale_path[4096] attribute_hidden;
+ 
+ /* Load the locale data for CATEGORY from the file specified by *NAME.
+    If *NAME is "", use environment variables as specified by POSIX, and
+diff --git a/locale/programs/locale.c b/locale/programs/locale.c
+index ca0a95be99..6b98895203 100644
+--- a/locale/programs/locale.c
++++ b/locale/programs/locale.c
+@@ -632,6 +632,7 @@ nameentcmp (const void *a, const void *b)
+ 		  ((const struct nameent *) b)->name);
+ }
+ 
++static char _write_archive_locales_path[4096] attribute_hidden __attribute__ ((section (".gccrelocprefix"))) = ARCHIVE_NAME;
+ 
+ static int
+ write_archive_locales (void **all_datap, char *linebuf)
+@@ -645,7 +646,7 @@ write_archive_locales (void **all_datap, char *linebuf)
+   int fd, ret = 0;
+   uint32_t cnt;
+ 
+-  fd = open64 (ARCHIVE_NAME, O_RDONLY);
++  fd = open64 (_write_archive_locales_path, O_RDONLY);
+   if (fd < 0)
+     return 0;
+ 
+@@ -700,8 +701,8 @@ write_archive_locales (void **all_datap, char *linebuf)
+ 	  if (cnt)
+ 	    putchar_unlocked ('\n');
+ 
+-	  printf ("locale: %-15.15s archive: " ARCHIVE_NAME "\n%s\n",
+-		  names[cnt].name, linebuf);
++	  printf ("locale: %-15.15s archive: %s\n%s\n",
++		  names[cnt].name, _write_archive_locales_path, linebuf);
+ 
+ 	  locrec = (struct locrecent *) (addr + names[cnt].locrec_offset);
+ 

+ 32 - 0
recipes-core/glibc/glibc/0008-nativesdk-glibc-Fall-back-to-faccessat-on-faccess2-r.patch

@@ -0,0 +1,32 @@
+From 2761400989bcbf11e10bc85f90c3a2ba1305c4ae Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sat, 6 Mar 2021 14:48:56 -0800
+Subject: [PATCH] nativesdk-glibc: Fall back to faccessat on faccess2 returns
+ EPERM
+
+Fedora-specific workaround for systemd-nspawn
+
+Upstream-Status: Inappropriate [Distro Specific]
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ sysdeps/unix/sysv/linux/faccessat.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/sysdeps/unix/sysv/linux/faccessat.c b/sysdeps/unix/sysv/linux/faccessat.c
+index 13160d3249..ee3ddc9b79 100644
+--- a/sysdeps/unix/sysv/linux/faccessat.c
++++ b/sysdeps/unix/sysv/linux/faccessat.c
+@@ -30,7 +30,11 @@ __faccessat (int fd, const char *file, int mode, int flag)
+ #if __ASSUME_FACCESSAT2
+   return ret;
+ #else
+-  if (ret == 0 || errno != ENOSYS)
++  /* Fedora-specific workaround:
++     As a workround for a broken systemd-nspawn that returns
++     EPERM when a syscall is not allowed instead of ENOSYS
++     we must check for EPERM here and fall back to faccessat.  */
++  if (ret == 0 || !(errno == ENOSYS || errno == EPERM))
+     return ret;
+ 
+   if (flag & ~(AT_SYMLINK_NOFOLLOW | AT_EACCESS))

+ 1581 - 0
recipes-core/glibc/glibc/0009-fsl-e500-e5500-e6500-603e-fsqrt-implementation.patch

@@ -0,0 +1,1581 @@
+From 74923ca4b1ae0ed5a2478e7d265b37534f6815d7 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Wed, 18 Mar 2015 00:01:50 +0000
+Subject: [PATCH] fsl e500/e5500/e6500/603e fsqrt implementation
+
+Upstream-Status: Pending
+Signed-off-by: Edmar Wienskoski <edmar@freescale.com>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c   | 134 ++++++++++++++++++
+ sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c  | 101 +++++++++++++
+ sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c | 134 ++++++++++++++++++
+ .../powerpc/powerpc32/e500mc/fpu/e_sqrtf.c    | 101 +++++++++++++
+ sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c  | 134 ++++++++++++++++++
+ sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c | 101 +++++++++++++
+ sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c  | 134 ++++++++++++++++++
+ sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c | 101 +++++++++++++
+ sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c  | 134 ++++++++++++++++++
+ sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c | 101 +++++++++++++
+ sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c  | 134 ++++++++++++++++++
+ sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c | 101 +++++++++++++
+ .../linux/powerpc/powerpc32/603e/fpu/Implies  |   1 +
+ .../powerpc/powerpc32/e300c3/fpu/Implies      |   2 +
+ .../powerpc/powerpc32/e500mc/fpu/Implies      |   1 +
+ .../linux/powerpc/powerpc32/e5500/fpu/Implies |   1 +
+ .../linux/powerpc/powerpc32/e6500/fpu/Implies |   1 +
+ .../linux/powerpc/powerpc64/e5500/fpu/Implies |   1 +
+ .../linux/powerpc/powerpc64/e6500/fpu/Implies |   1 +
+ 19 files changed, 1418 insertions(+)
+ create mode 100644 sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c
+ create mode 100644 sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c
+ create mode 100644 sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c
+ create mode 100644 sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c
+ create mode 100644 sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c
+ create mode 100644 sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c
+ create mode 100644 sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
+ create mode 100644 sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
+ create mode 100644 sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c
+ create mode 100644 sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c
+ create mode 100644 sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c
+ create mode 100644 sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c
+ create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/603e/fpu/Implies
+ create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/e300c3/fpu/Implies
+ create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/e500mc/fpu/Implies
+ create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/e5500/fpu/Implies
+ create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc32/e6500/fpu/Implies
+ create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc64/e5500/fpu/Implies
+ create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc64/e6500/fpu/Implies
+
+diff --git a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c
+new file mode 100644
+index 0000000000..71e516d1c8
+--- /dev/null
++++ b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c
+@@ -0,0 +1,134 @@
++/* Double-precision floating point square root.
++   Copyright (C) 2010 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, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++#include <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float two108 = 3.245185536584267269e+32;
++static const float twom54 = 5.551115123125782702e-17;
++static const float half = 0.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the actual square root and half of its reciprocal
++   simultaneously.  */
++
++#ifdef __STDC__
++double
++__ieee754_sqrt (double b)
++#else
++double
++__ieee754_sqrt (b)
++     double b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++      double y, g, h, d, r;
++      ieee_double_shape_type u;
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          u.value = b;
++
++          relax_fenv_state ();
++
++          __asm__ ("frsqrte %[estimate], %[x]\n"
++                   : [estimate] "=f" (y) : [x] "f" (b));
++
++          /* Following Muller et al, page 168, equation 5.20.
++
++             h goes to 1/(2*sqrt(b))
++             g goes to sqrt(b).
++
++             We need three iterations to get within 1ulp.  */
++
++          /* Indicate that these can be performed prior to the branch.  GCC
++             insists on sinking them below the branch, however; it seems like
++             they'd be better before the branch so that we can cover any latency
++             from storing the argument and loading its high word.  Oh well.  */
++
++          g = b * y;
++          h = 0.5 * y;
++
++          /* Handle small numbers by scaling.  */
++          if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
++            return __ieee754_sqrt (b * two108) * twom54;
++
++#define FMADD(a_, c_, b_)                                               \
++          ({ double __r;                                                \
++          __asm__ ("fmadd %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++#define FNMSUB(a_, c_, b_)                                          \
++          ({ double __r;                                                \
++          __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          /* g is now +/- 1ulp, or exactly equal to, the square root of b.  */
++
++          /* Final refinement.  */
++          d = FNMSUB (g, g, b);
++
++          fesetenv_register (fe);
++          return FMADD (d, h, g);
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_wash (b);
++}
+diff --git a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c
+new file mode 100644
+index 0000000000..26fa067abf
+--- /dev/null
++++ b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c
+@@ -0,0 +1,101 @@
++/* Single-precision floating point square root.
++   Copyright (C) 2010 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, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++#include <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float threehalf = 1.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the reciprocal square root and use that to compute the actual
++   square root.  */
++
++#ifdef __STDC__
++float
++__ieee754_sqrtf (float b)
++#else
++float
++__ieee754_sqrtf (b)
++     float b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++#define FMSUB(a_, c_, b_)                                               \
++      ({ double __r;                                                    \
++        __asm__ ("fmsub %[r], %[a], %[c], %[b]\n"                       \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++#define FNMSUB(a_, c_, b_)                                              \
++      ({ double __r;                                                    \
++        __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                      \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          double y, x;
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          relax_fenv_state ();
++
++          /* Compute y = 1.5 * b - b.  Uses fewer constants than y = 0.5 * b.  */
++          y = FMSUB (threehalf, b, b);
++
++          /* Initial estimate.  */
++          __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b));
++
++          /* Iterate.  x_{n+1} = x_n * (1.5 - y * (x_n * x_n)).  */
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++
++          /* All done.  */
++          fesetenv_register (fe);
++          return x * b;
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_washf (b);
++}
+diff --git a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c
+new file mode 100644
+index 0000000000..71e516d1c8
+--- /dev/null
++++ b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c
+@@ -0,0 +1,134 @@
++/* Double-precision floating point square root.
++   Copyright (C) 2010 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, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++#include <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float two108 = 3.245185536584267269e+32;
++static const float twom54 = 5.551115123125782702e-17;
++static const float half = 0.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the actual square root and half of its reciprocal
++   simultaneously.  */
++
++#ifdef __STDC__
++double
++__ieee754_sqrt (double b)
++#else
++double
++__ieee754_sqrt (b)
++     double b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++      double y, g, h, d, r;
++      ieee_double_shape_type u;
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          u.value = b;
++
++          relax_fenv_state ();
++
++          __asm__ ("frsqrte %[estimate], %[x]\n"
++                   : [estimate] "=f" (y) : [x] "f" (b));
++
++          /* Following Muller et al, page 168, equation 5.20.
++
++             h goes to 1/(2*sqrt(b))
++             g goes to sqrt(b).
++
++             We need three iterations to get within 1ulp.  */
++
++          /* Indicate that these can be performed prior to the branch.  GCC
++             insists on sinking them below the branch, however; it seems like
++             they'd be better before the branch so that we can cover any latency
++             from storing the argument and loading its high word.  Oh well.  */
++
++          g = b * y;
++          h = 0.5 * y;
++
++          /* Handle small numbers by scaling.  */
++          if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
++            return __ieee754_sqrt (b * two108) * twom54;
++
++#define FMADD(a_, c_, b_)                                               \
++          ({ double __r;                                                \
++          __asm__ ("fmadd %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++#define FNMSUB(a_, c_, b_)                                          \
++          ({ double __r;                                                \
++          __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          /* g is now +/- 1ulp, or exactly equal to, the square root of b.  */
++
++          /* Final refinement.  */
++          d = FNMSUB (g, g, b);
++
++          fesetenv_register (fe);
++          return FMADD (d, h, g);
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_wash (b);
++}
+diff --git a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c
+new file mode 100644
+index 0000000000..26fa067abf
+--- /dev/null
++++ b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c
+@@ -0,0 +1,101 @@
++/* Single-precision floating point square root.
++   Copyright (C) 2010 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, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++#include <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float threehalf = 1.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the reciprocal square root and use that to compute the actual
++   square root.  */
++
++#ifdef __STDC__
++float
++__ieee754_sqrtf (float b)
++#else
++float
++__ieee754_sqrtf (b)
++     float b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++#define FMSUB(a_, c_, b_)                                               \
++      ({ double __r;                                                    \
++        __asm__ ("fmsub %[r], %[a], %[c], %[b]\n"                       \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++#define FNMSUB(a_, c_, b_)                                              \
++      ({ double __r;                                                    \
++        __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                      \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          double y, x;
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          relax_fenv_state ();
++
++          /* Compute y = 1.5 * b - b.  Uses fewer constants than y = 0.5 * b.  */
++          y = FMSUB (threehalf, b, b);
++
++          /* Initial estimate.  */
++          __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b));
++
++          /* Iterate.  x_{n+1} = x_n * (1.5 - y * (x_n * x_n)).  */
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++
++          /* All done.  */
++          fesetenv_register (fe);
++          return x * b;
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_washf (b);
++}
+diff --git a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c
+new file mode 100644
+index 0000000000..71e516d1c8
+--- /dev/null
++++ b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c
+@@ -0,0 +1,134 @@
++/* Double-precision floating point square root.
++   Copyright (C) 2010 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, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++#include <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float two108 = 3.245185536584267269e+32;
++static const float twom54 = 5.551115123125782702e-17;
++static const float half = 0.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the actual square root and half of its reciprocal
++   simultaneously.  */
++
++#ifdef __STDC__
++double
++__ieee754_sqrt (double b)
++#else
++double
++__ieee754_sqrt (b)
++     double b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++      double y, g, h, d, r;
++      ieee_double_shape_type u;
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          u.value = b;
++
++          relax_fenv_state ();
++
++          __asm__ ("frsqrte %[estimate], %[x]\n"
++                   : [estimate] "=f" (y) : [x] "f" (b));
++
++          /* Following Muller et al, page 168, equation 5.20.
++
++             h goes to 1/(2*sqrt(b))
++             g goes to sqrt(b).
++
++             We need three iterations to get within 1ulp.  */
++
++          /* Indicate that these can be performed prior to the branch.  GCC
++             insists on sinking them below the branch, however; it seems like
++             they'd be better before the branch so that we can cover any latency
++             from storing the argument and loading its high word.  Oh well.  */
++
++          g = b * y;
++          h = 0.5 * y;
++
++          /* Handle small numbers by scaling.  */
++          if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
++            return __ieee754_sqrt (b * two108) * twom54;
++
++#define FMADD(a_, c_, b_)                                               \
++          ({ double __r;                                                \
++          __asm__ ("fmadd %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++#define FNMSUB(a_, c_, b_)                                          \
++          ({ double __r;                                                \
++          __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          /* g is now +/- 1ulp, or exactly equal to, the square root of b.  */
++
++          /* Final refinement.  */
++          d = FNMSUB (g, g, b);
++
++          fesetenv_register (fe);
++          return FMADD (d, h, g);
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_wash (b);
++}
+diff --git a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c
+new file mode 100644
+index 0000000000..26fa067abf
+--- /dev/null
++++ b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c
+@@ -0,0 +1,101 @@
++/* Single-precision floating point square root.
++   Copyright (C) 2010 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, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++#include <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float threehalf = 1.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the reciprocal square root and use that to compute the actual
++   square root.  */
++
++#ifdef __STDC__
++float
++__ieee754_sqrtf (float b)
++#else
++float
++__ieee754_sqrtf (b)
++     float b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++#define FMSUB(a_, c_, b_)                                               \
++      ({ double __r;                                                    \
++        __asm__ ("fmsub %[r], %[a], %[c], %[b]\n"                       \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++#define FNMSUB(a_, c_, b_)                                              \
++      ({ double __r;                                                    \
++        __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                      \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          double y, x;
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          relax_fenv_state ();
++
++          /* Compute y = 1.5 * b - b.  Uses fewer constants than y = 0.5 * b.  */
++          y = FMSUB (threehalf, b, b);
++
++          /* Initial estimate.  */
++          __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b));
++
++          /* Iterate.  x_{n+1} = x_n * (1.5 - y * (x_n * x_n)).  */
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++
++          /* All done.  */
++          fesetenv_register (fe);
++          return x * b;
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_washf (b);
++}
+diff --git a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
+new file mode 100644
+index 0000000000..71e516d1c8
+--- /dev/null
++++ b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
+@@ -0,0 +1,134 @@
++/* Double-precision floating point square root.
++   Copyright (C) 2010 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, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++#include <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float two108 = 3.245185536584267269e+32;
++static const float twom54 = 5.551115123125782702e-17;
++static const float half = 0.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the actual square root and half of its reciprocal
++   simultaneously.  */
++
++#ifdef __STDC__
++double
++__ieee754_sqrt (double b)
++#else
++double
++__ieee754_sqrt (b)
++     double b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++      double y, g, h, d, r;
++      ieee_double_shape_type u;
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          u.value = b;
++
++          relax_fenv_state ();
++
++          __asm__ ("frsqrte %[estimate], %[x]\n"
++                   : [estimate] "=f" (y) : [x] "f" (b));
++
++          /* Following Muller et al, page 168, equation 5.20.
++
++             h goes to 1/(2*sqrt(b))
++             g goes to sqrt(b).
++
++             We need three iterations to get within 1ulp.  */
++
++          /* Indicate that these can be performed prior to the branch.  GCC
++             insists on sinking them below the branch, however; it seems like
++             they'd be better before the branch so that we can cover any latency
++             from storing the argument and loading its high word.  Oh well.  */
++
++          g = b * y;
++          h = 0.5 * y;
++
++          /* Handle small numbers by scaling.  */
++          if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
++            return __ieee754_sqrt (b * two108) * twom54;
++
++#define FMADD(a_, c_, b_)                                               \
++          ({ double __r;                                                \
++          __asm__ ("fmadd %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++#define FNMSUB(a_, c_, b_)                                          \
++          ({ double __r;                                                \
++          __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          /* g is now +/- 1ulp, or exactly equal to, the square root of b.  */
++
++          /* Final refinement.  */
++          d = FNMSUB (g, g, b);
++
++          fesetenv_register (fe);
++          return FMADD (d, h, g);
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_wash (b);
++}
+diff --git a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
+new file mode 100644
+index 0000000000..26fa067abf
+--- /dev/null
++++ b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
+@@ -0,0 +1,101 @@
++/* Single-precision floating point square root.
++   Copyright (C) 2010 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, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++#include <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float threehalf = 1.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the reciprocal square root and use that to compute the actual
++   square root.  */
++
++#ifdef __STDC__
++float
++__ieee754_sqrtf (float b)
++#else
++float
++__ieee754_sqrtf (b)
++     float b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++#define FMSUB(a_, c_, b_)                                               \
++      ({ double __r;                                                    \
++        __asm__ ("fmsub %[r], %[a], %[c], %[b]\n"                       \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++#define FNMSUB(a_, c_, b_)                                              \
++      ({ double __r;                                                    \
++        __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                      \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          double y, x;
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          relax_fenv_state ();
++
++          /* Compute y = 1.5 * b - b.  Uses fewer constants than y = 0.5 * b.  */
++          y = FMSUB (threehalf, b, b);
++
++          /* Initial estimate.  */
++          __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b));
++
++          /* Iterate.  x_{n+1} = x_n * (1.5 - y * (x_n * x_n)).  */
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++
++          /* All done.  */
++          fesetenv_register (fe);
++          return x * b;
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_washf (b);
++}
+diff --git a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c
+new file mode 100644
+index 0000000000..71e516d1c8
+--- /dev/null
++++ b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c
+@@ -0,0 +1,134 @@
++/* Double-precision floating point square root.
++   Copyright (C) 2010 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, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++#include <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float two108 = 3.245185536584267269e+32;
++static const float twom54 = 5.551115123125782702e-17;
++static const float half = 0.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the actual square root and half of its reciprocal
++   simultaneously.  */
++
++#ifdef __STDC__
++double
++__ieee754_sqrt (double b)
++#else
++double
++__ieee754_sqrt (b)
++     double b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++      double y, g, h, d, r;
++      ieee_double_shape_type u;
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          u.value = b;
++
++          relax_fenv_state ();
++
++          __asm__ ("frsqrte %[estimate], %[x]\n"
++                   : [estimate] "=f" (y) : [x] "f" (b));
++
++          /* Following Muller et al, page 168, equation 5.20.
++
++             h goes to 1/(2*sqrt(b))
++             g goes to sqrt(b).
++
++             We need three iterations to get within 1ulp.  */
++
++          /* Indicate that these can be performed prior to the branch.  GCC
++             insists on sinking them below the branch, however; it seems like
++             they'd be better before the branch so that we can cover any latency
++             from storing the argument and loading its high word.  Oh well.  */
++
++          g = b * y;
++          h = 0.5 * y;
++
++          /* Handle small numbers by scaling.  */
++          if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
++            return __ieee754_sqrt (b * two108) * twom54;
++
++#define FMADD(a_, c_, b_)                                               \
++          ({ double __r;                                                \
++          __asm__ ("fmadd %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++#define FNMSUB(a_, c_, b_)                                          \
++          ({ double __r;                                                \
++          __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          /* g is now +/- 1ulp, or exactly equal to, the square root of b.  */
++
++          /* Final refinement.  */
++          d = FNMSUB (g, g, b);
++
++          fesetenv_register (fe);
++          return FMADD (d, h, g);
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_wash (b);
++}
+diff --git a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c
+new file mode 100644
+index 0000000000..26fa067abf
+--- /dev/null
++++ b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c
+@@ -0,0 +1,101 @@
++/* Single-precision floating point square root.
++   Copyright (C) 2010 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, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++#include <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float threehalf = 1.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the reciprocal square root and use that to compute the actual
++   square root.  */
++
++#ifdef __STDC__
++float
++__ieee754_sqrtf (float b)
++#else
++float
++__ieee754_sqrtf (b)
++     float b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++#define FMSUB(a_, c_, b_)                                               \
++      ({ double __r;                                                    \
++        __asm__ ("fmsub %[r], %[a], %[c], %[b]\n"                       \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++#define FNMSUB(a_, c_, b_)                                              \
++      ({ double __r;                                                    \
++        __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                      \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          double y, x;
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          relax_fenv_state ();
++
++          /* Compute y = 1.5 * b - b.  Uses fewer constants than y = 0.5 * b.  */
++          y = FMSUB (threehalf, b, b);
++
++          /* Initial estimate.  */
++          __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b));
++
++          /* Iterate.  x_{n+1} = x_n * (1.5 - y * (x_n * x_n)).  */
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++
++          /* All done.  */
++          fesetenv_register (fe);
++          return x * b;
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_washf (b);
++}
+diff --git a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c
+new file mode 100644
+index 0000000000..71e516d1c8
+--- /dev/null
++++ b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c
+@@ -0,0 +1,134 @@
++/* Double-precision floating point square root.
++   Copyright (C) 2010 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, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++#include <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float two108 = 3.245185536584267269e+32;
++static const float twom54 = 5.551115123125782702e-17;
++static const float half = 0.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the actual square root and half of its reciprocal
++   simultaneously.  */
++
++#ifdef __STDC__
++double
++__ieee754_sqrt (double b)
++#else
++double
++__ieee754_sqrt (b)
++     double b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++      double y, g, h, d, r;
++      ieee_double_shape_type u;
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          u.value = b;
++
++          relax_fenv_state ();
++
++          __asm__ ("frsqrte %[estimate], %[x]\n"
++                   : [estimate] "=f" (y) : [x] "f" (b));
++
++          /* Following Muller et al, page 168, equation 5.20.
++
++             h goes to 1/(2*sqrt(b))
++             g goes to sqrt(b).
++
++             We need three iterations to get within 1ulp.  */
++
++          /* Indicate that these can be performed prior to the branch.  GCC
++             insists on sinking them below the branch, however; it seems like
++             they'd be better before the branch so that we can cover any latency
++             from storing the argument and loading its high word.  Oh well.  */
++
++          g = b * y;
++          h = 0.5 * y;
++
++          /* Handle small numbers by scaling.  */
++          if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
++            return __ieee754_sqrt (b * two108) * twom54;
++
++#define FMADD(a_, c_, b_)                                               \
++          ({ double __r;                                                \
++          __asm__ ("fmadd %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++#define FNMSUB(a_, c_, b_)                                          \
++          ({ double __r;                                                \
++          __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                     \
++                   : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++          __r;})
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          r = FNMSUB (g, h, half);
++          g = FMADD (g, r, g);
++          h = FMADD (h, r, h);
++
++          /* g is now +/- 1ulp, or exactly equal to, the square root of b.  */
++
++          /* Final refinement.  */
++          d = FNMSUB (g, g, b);
++
++          fesetenv_register (fe);
++          return FMADD (d, h, g);
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_wash (b);
++}
+diff --git a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c
+new file mode 100644
+index 0000000000..26fa067abf
+--- /dev/null
++++ b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c
+@@ -0,0 +1,101 @@
++/* Single-precision floating point square root.
++   Copyright (C) 2010 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, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++#include <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float threehalf = 1.5;
++
++/* The method is based on the descriptions in:
++
++   _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++   _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++   We find the reciprocal square root and use that to compute the actual
++   square root.  */
++
++#ifdef __STDC__
++float
++__ieee754_sqrtf (float b)
++#else
++float
++__ieee754_sqrtf (b)
++     float b;
++#endif
++{
++  if (__builtin_expect (b > 0, 1))
++    {
++#define FMSUB(a_, c_, b_)                                               \
++      ({ double __r;                                                    \
++        __asm__ ("fmsub %[r], %[a], %[c], %[b]\n"                       \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++#define FNMSUB(a_, c_, b_)                                              \
++      ({ double __r;                                                    \
++        __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n"                      \
++                 : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++        __r;})
++
++      if (__builtin_expect (b != a_inf.value, 1))
++        {
++          double y, x;
++          fenv_t fe;
++
++          fe = fegetenv_register ();
++
++          relax_fenv_state ();
++
++          /* Compute y = 1.5 * b - b.  Uses fewer constants than y = 0.5 * b.  */
++          y = FMSUB (threehalf, b, b);
++
++          /* Initial estimate.  */
++          __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b));
++
++          /* Iterate.  x_{n+1} = x_n * (1.5 - y * (x_n * x_n)).  */
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++          x = x * FNMSUB (y, x * x, threehalf);
++
++          /* All done.  */
++          fesetenv_register (fe);
++          return x * b;
++        }
++    }
++  else if (b < 0)
++    {
++      /* For some reason, some PowerPC32 processors don't implement
++         FE_INVALID_SQRT.  */
++#ifdef FE_INVALID_SQRT
++      feraiseexcept (FE_INVALID_SQRT);
++
++      fenv_union_t u = { .fenv = fegetenv_register () };
++      if ((u.l & FE_INVALID) == 0)
++#endif
++	feraiseexcept (FE_INVALID);
++      b = a_nan.value;
++    }
++  return f_washf (b);
++}
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/603e/fpu/Implies b/sysdeps/unix/sysv/linux/powerpc/powerpc32/603e/fpu/Implies
+new file mode 100644
+index 0000000000..b103b4dea5
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/603e/fpu/Implies
+@@ -0,0 +1 @@
++powerpc/powerpc32/603e/fpu
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/e300c3/fpu/Implies b/sysdeps/unix/sysv/linux/powerpc/powerpc32/e300c3/fpu/Implies
+new file mode 100644
+index 0000000000..64db17fada
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/e300c3/fpu/Implies
+@@ -0,0 +1,2 @@
++# e300c3 is a variant of 603e so use the same optimizations for sqrt
++powerpc/powerpc32/603e/fpu
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500mc/fpu/Implies b/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500mc/fpu/Implies
+new file mode 100644
+index 0000000000..7eac5fcf02
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/e500mc/fpu/Implies
+@@ -0,0 +1 @@
++powerpc/powerpc32/e500mc/fpu
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/e5500/fpu/Implies b/sysdeps/unix/sysv/linux/powerpc/powerpc32/e5500/fpu/Implies
+new file mode 100644
+index 0000000000..264b2a7700
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/e5500/fpu/Implies
+@@ -0,0 +1 @@
++powerpc/powerpc32/e5500/fpu
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/e6500/fpu/Implies b/sysdeps/unix/sysv/linux/powerpc/powerpc32/e6500/fpu/Implies
+new file mode 100644
+index 0000000000..a25934467b
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/e6500/fpu/Implies
+@@ -0,0 +1 @@
++powerpc/powerpc32/e6500/fpu
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/e5500/fpu/Implies b/sysdeps/unix/sysv/linux/powerpc/powerpc64/e5500/fpu/Implies
+new file mode 100644
+index 0000000000..a7bc854be8
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/e5500/fpu/Implies
+@@ -0,0 +1 @@
++powerpc/powerpc64/e5500/fpu
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/e6500/fpu/Implies b/sysdeps/unix/sysv/linux/powerpc/powerpc64/e6500/fpu/Implies
+new file mode 100644
+index 0000000000..04ff8cc181
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/e6500/fpu/Implies
+@@ -0,0 +1 @@
++powerpc/powerpc64/e6500/fpu

+ 205 - 0
recipes-core/glibc/glibc/0010-ppc-sqrt-Fix-undefined-reference-to-__sqrt_finite.patch

@@ -0,0 +1,205 @@
+From 5da3da7f2d276c2a6ae1b04419b28e96953803ec Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Wed, 18 Mar 2015 00:15:07 +0000
+Subject: [PATCH] ppc/sqrt: Fix undefined reference to `__sqrt_finite'
+
+on ppc fixes the errors like below
+| ./.libs/libpulsecore-1.1.so: undefined reference to `__sqrt_finite'
+| collect2: ld returned 1 exit status
+
+Upstream-Status: Pending
+
+ChangeLog
+
+2012-01-06  Khem Raj  <raj.khem@gmail.com>
+
+        * sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c: Add __*_finite alias.
+        Remove cruft.
+        * sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c: Ditto.
+        * sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c: Ditto.
+        * sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c: Ditto.
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c    | 7 +------
+ sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c   | 7 +------
+ sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c  | 1 +
+ sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c | 1 +
+ sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c   | 1 +
+ sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c  | 1 +
+ sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c   | 1 +
+ sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c  | 1 +
+ sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c   | 7 +------
+ sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c  | 7 +------
+ sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c   | 1 +
+ sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c  | 1 +
+ 12 files changed, 12 insertions(+), 24 deletions(-)
+
+diff --git a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c
+index 71e516d1c8..1795fd6c3e 100644
+--- a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c
++++ b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c
+@@ -39,14 +39,8 @@ static const float half = 0.5;
+    We find the actual square root and half of its reciprocal
+    simultaneously.  */
+ 
+-#ifdef __STDC__
+ double
+ __ieee754_sqrt (double b)
+-#else
+-double
+-__ieee754_sqrt (b)
+-     double b;
+-#endif
+ {
+   if (__builtin_expect (b > 0, 1))
+     {
+@@ -132,3 +126,4 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++strong_alias (__ieee754_sqrt, __sqrt_finite)
+diff --git a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c
+index 26fa067abf..a917f313ab 100644
+--- a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c
++++ b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c
+@@ -37,14 +37,8 @@ static const float threehalf = 1.5;
+    We find the reciprocal square root and use that to compute the actual
+    square root.  */
+ 
+-#ifdef __STDC__
+ float
+ __ieee754_sqrtf (float b)
+-#else
+-float
+-__ieee754_sqrtf (b)
+-     float b;
+-#endif
+ {
+   if (__builtin_expect (b > 0, 1))
+     {
+@@ -99,3 +93,4 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+diff --git a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c
+index 71e516d1c8..fc4a74990e 100644
+--- a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c
++++ b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c
+@@ -132,3 +132,4 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++strong_alias (__ieee754_sqrt, __sqrt_finite)
+diff --git a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c
+index 26fa067abf..9d175122a8 100644
+--- a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c
++++ b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c
+@@ -99,3 +99,4 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+diff --git a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c
+index 71e516d1c8..fc4a74990e 100644
+--- a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c
++++ b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c
+@@ -132,3 +132,4 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++strong_alias (__ieee754_sqrt, __sqrt_finite)
+diff --git a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c
+index 26fa067abf..9d175122a8 100644
+--- a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c
++++ b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c
+@@ -99,3 +99,4 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+diff --git a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
+index 71e516d1c8..fc4a74990e 100644
+--- a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
++++ b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
+@@ -132,3 +132,4 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++strong_alias (__ieee754_sqrt, __sqrt_finite)
+diff --git a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
+index 26fa067abf..9d175122a8 100644
+--- a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
++++ b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
+@@ -99,3 +99,4 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+diff --git a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c
+index 71e516d1c8..1795fd6c3e 100644
+--- a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c
++++ b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c
+@@ -39,14 +39,8 @@ static const float half = 0.5;
+    We find the actual square root and half of its reciprocal
+    simultaneously.  */
+ 
+-#ifdef __STDC__
+ double
+ __ieee754_sqrt (double b)
+-#else
+-double
+-__ieee754_sqrt (b)
+-     double b;
+-#endif
+ {
+   if (__builtin_expect (b > 0, 1))
+     {
+@@ -132,3 +126,4 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++strong_alias (__ieee754_sqrt, __sqrt_finite)
+diff --git a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c
+index 26fa067abf..a917f313ab 100644
+--- a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c
++++ b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c
+@@ -37,14 +37,8 @@ static const float threehalf = 1.5;
+    We find the reciprocal square root and use that to compute the actual
+    square root.  */
+ 
+-#ifdef __STDC__
+ float
+ __ieee754_sqrtf (float b)
+-#else
+-float
+-__ieee754_sqrtf (b)
+-     float b;
+-#endif
+ {
+   if (__builtin_expect (b > 0, 1))
+     {
+@@ -99,3 +93,4 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+diff --git a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c
+index 71e516d1c8..fc4a74990e 100644
+--- a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c
++++ b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c
+@@ -132,3 +132,4 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++strong_alias (__ieee754_sqrt, __sqrt_finite)
+diff --git a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c
+index 26fa067abf..9d175122a8 100644
+--- a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c
++++ b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c
+@@ -99,3 +99,4 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++strong_alias (__ieee754_sqrtf, __sqrtf_finite)

+ 384 - 0
recipes-core/glibc/glibc/0011-__ieee754_sqrt-f-are-now-inline-functions-and-call-o.patch

@@ -0,0 +1,384 @@
+From 77f1c90d67a2f8852184fb8fd95cb0ed63065dc7 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Wed, 18 Mar 2015 00:16:38 +0000
+Subject: [PATCH] __ieee754_sqrt{,f} are now inline functions and call out
+ __slow versions
+
+Upstream-Status: Pending
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c    | 12 ++++++++++--
+ sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c   |  8 +++++++-
+ sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c  | 14 +++++++++++---
+ sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c | 12 ++++++++++--
+ sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c   | 14 +++++++++++---
+ sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c  | 12 ++++++++++--
+ sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c   |  8 ++++++++
+ sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c  |  8 ++++++++
+ sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c   | 12 ++++++++++--
+ sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c  |  9 ++++++++-
+ sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c   | 14 +++++++++++---
+ sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c  | 12 ++++++++++--
+ 12 files changed, 114 insertions(+), 21 deletions(-)
+
+diff --git a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c
+index 1795fd6c3e..daa83f3fe8 100644
+--- a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c
++++ b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c
+@@ -40,7 +40,7 @@ static const float half = 0.5;
+    simultaneously.  */
+ 
+ double
+-__ieee754_sqrt (double b)
++__slow_ieee754_sqrt (double b)
+ {
+   if (__builtin_expect (b > 0, 1))
+     {
+@@ -77,7 +77,7 @@ __ieee754_sqrt (double b)
+ 
+           /* Handle small numbers by scaling.  */
+           if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
+-            return __ieee754_sqrt (b * two108) * twom54;
++            return __slow_ieee754_sqrt (b * two108) * twom54;
+ 
+ #define FMADD(a_, c_, b_)                                               \
+           ({ double __r;                                                \
+@@ -126,4 +126,12 @@ __ieee754_sqrt (double b)
+     }
+   return f_wash (b);
+ }
++
++#undef __ieee754_sqrt
++double
++__ieee754_sqrt (double x)
++{
++   return __slow_ieee754_sqrt (x);
++}
++
+ strong_alias (__ieee754_sqrt, __sqrt_finite)
+diff --git a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c
+index a917f313ab..b812cf1705 100644
+--- a/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c
++++ b/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c
+@@ -38,7 +38,7 @@ static const float threehalf = 1.5;
+    square root.  */
+ 
+ float
+-__ieee754_sqrtf (float b)
++__slow_ieee754_sqrtf (float b)
+ {
+   if (__builtin_expect (b > 0, 1))
+     {
+@@ -93,4 +93,10 @@ __ieee754_sqrtf (float b)
+     }
+   return f_washf (b);
+ }
++#undef __ieee754_sqrtf
++float
++__ieee754_sqrtf (float x)
++{
++  return __slow_ieee754_sqrtf (x);
++}
+ strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+diff --git a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c
+index fc4a74990e..7038a70b47 100644
+--- a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c
++++ b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrt.c
+@@ -41,10 +41,10 @@ static const float half = 0.5;
+ 
+ #ifdef __STDC__
+ double
+-__ieee754_sqrt (double b)
++__slow_ieee754_sqrt (double b)
+ #else
+ double
+-__ieee754_sqrt (b)
++__slow_ieee754_sqrt (b)
+      double b;
+ #endif
+ {
+@@ -83,7 +83,7 @@ __ieee754_sqrt (b)
+ 
+           /* Handle small numbers by scaling.  */
+           if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
+-            return __ieee754_sqrt (b * two108) * twom54;
++            return __slow_ieee754_sqrt (b * two108) * twom54;
+ 
+ #define FMADD(a_, c_, b_)                                               \
+           ({ double __r;                                                \
+@@ -132,4 +132,12 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++
++#undef __ieee754_sqrt
++double
++__ieee754_sqrt (double x)
++{
++   return __slow_ieee754_sqrt (x);
++}
++
+ strong_alias (__ieee754_sqrt, __sqrt_finite)
+diff --git a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c
+index 9d175122a8..10de1f0cc3 100644
+--- a/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c
++++ b/sysdeps/powerpc/powerpc32/e500mc/fpu/e_sqrtf.c
+@@ -39,10 +39,10 @@ static const float threehalf = 1.5;
+ 
+ #ifdef __STDC__
+ float
+-__ieee754_sqrtf (float b)
++__slow_ieee754_sqrtf (float b)
+ #else
+ float
+-__ieee754_sqrtf (b)
++__slow_ieee754_sqrtf (b)
+      float b;
+ #endif
+ {
+@@ -99,4 +99,12 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++
++#undef __ieee754_sqrtf
++float
++__ieee754_sqrtf (float x)
++{
++  return __slow_ieee754_sqrtf (x);
++}
++
+ strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+diff --git a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c
+index fc4a74990e..7038a70b47 100644
+--- a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c
++++ b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrt.c
+@@ -41,10 +41,10 @@ static const float half = 0.5;
+ 
+ #ifdef __STDC__
+ double
+-__ieee754_sqrt (double b)
++__slow_ieee754_sqrt (double b)
+ #else
+ double
+-__ieee754_sqrt (b)
++__slow_ieee754_sqrt (b)
+      double b;
+ #endif
+ {
+@@ -83,7 +83,7 @@ __ieee754_sqrt (b)
+ 
+           /* Handle small numbers by scaling.  */
+           if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
+-            return __ieee754_sqrt (b * two108) * twom54;
++            return __slow_ieee754_sqrt (b * two108) * twom54;
+ 
+ #define FMADD(a_, c_, b_)                                               \
+           ({ double __r;                                                \
+@@ -132,4 +132,12 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++
++#undef __ieee754_sqrt
++double
++__ieee754_sqrt (double x)
++{
++   return __slow_ieee754_sqrt (x);
++}
++
+ strong_alias (__ieee754_sqrt, __sqrt_finite)
+diff --git a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c
+index 9d175122a8..10de1f0cc3 100644
+--- a/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c
++++ b/sysdeps/powerpc/powerpc32/e5500/fpu/e_sqrtf.c
+@@ -39,10 +39,10 @@ static const float threehalf = 1.5;
+ 
+ #ifdef __STDC__
+ float
+-__ieee754_sqrtf (float b)
++__slow_ieee754_sqrtf (float b)
+ #else
+ float
+-__ieee754_sqrtf (b)
++__slow_ieee754_sqrtf (b)
+      float b;
+ #endif
+ {
+@@ -99,4 +99,12 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++
++#undef __ieee754_sqrtf
++float
++__ieee754_sqrtf (float x)
++{
++  return __slow_ieee754_sqrtf (x);
++}
++
+ strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+diff --git a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
+index fc4a74990e..1c34244bd8 100644
+--- a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
++++ b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
+@@ -132,4 +132,12 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++
++#undef __ieee754_sqrt
++double
++__ieee754_sqrt (double x)
++{
++   return __slow_ieee754_sqrt (x);
++}
++
+ strong_alias (__ieee754_sqrt, __sqrt_finite)
+diff --git a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
+index 9d175122a8..812653558f 100644
+--- a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
++++ b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
+@@ -99,4 +99,12 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++
++#undef __ieee754_sqrtf
++float
++__ieee754_sqrtf (float x)
++{
++  return __slow_ieee754_sqrtf (x);
++}
++
+ strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+diff --git a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c
+index 1795fd6c3e..13a81973e3 100644
+--- a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c
++++ b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c
+@@ -40,7 +40,7 @@ static const float half = 0.5;
+    simultaneously.  */
+ 
+ double
+-__ieee754_sqrt (double b)
++__slow_ieee754_sqrt (double b)
+ {
+   if (__builtin_expect (b > 0, 1))
+     {
+@@ -77,7 +77,7 @@ __ieee754_sqrt (double b)
+ 
+           /* Handle small numbers by scaling.  */
+           if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
+-            return __ieee754_sqrt (b * two108) * twom54;
++            return __slow_ieee754_sqrt (b * two108) * twom54;
+ 
+ #define FMADD(a_, c_, b_)                                               \
+           ({ double __r;                                                \
+@@ -126,4 +126,12 @@ __ieee754_sqrt (double b)
+     }
+   return f_wash (b);
+ }
++
++#undef __ieee754_sqrt
++double
++__ieee754_sqrt (double x)
++{
++  return __slow_ieee754_sqrt (x);
++}
++
+ strong_alias (__ieee754_sqrt, __sqrt_finite)
+diff --git a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c
+index a917f313ab..fae2d81210 100644
+--- a/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c
++++ b/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c
+@@ -38,7 +38,7 @@ static const float threehalf = 1.5;
+    square root.  */
+ 
+ float
+-__ieee754_sqrtf (float b)
++__slow_ieee754_sqrtf (float b)
+ {
+   if (__builtin_expect (b > 0, 1))
+     {
+@@ -93,4 +93,11 @@ __ieee754_sqrtf (float b)
+     }
+   return f_washf (b);
+ }
++#undef __ieee754_sqrtf
++float
++__ieee754_sqrtf (float x)
++{
++  return __slow_ieee754_sqrtf (x);
++}
++
+ strong_alias (__ieee754_sqrtf, __sqrtf_finite)
+diff --git a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c
+index fc4a74990e..7038a70b47 100644
+--- a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c
++++ b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrt.c
+@@ -41,10 +41,10 @@ static const float half = 0.5;
+ 
+ #ifdef __STDC__
+ double
+-__ieee754_sqrt (double b)
++__slow_ieee754_sqrt (double b)
+ #else
+ double
+-__ieee754_sqrt (b)
++__slow_ieee754_sqrt (b)
+      double b;
+ #endif
+ {
+@@ -83,7 +83,7 @@ __ieee754_sqrt (b)
+ 
+           /* Handle small numbers by scaling.  */
+           if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
+-            return __ieee754_sqrt (b * two108) * twom54;
++            return __slow_ieee754_sqrt (b * two108) * twom54;
+ 
+ #define FMADD(a_, c_, b_)                                               \
+           ({ double __r;                                                \
+@@ -132,4 +132,12 @@ __ieee754_sqrt (b)
+     }
+   return f_wash (b);
+ }
++
++#undef __ieee754_sqrt
++double
++__ieee754_sqrt (double x)
++{
++   return __slow_ieee754_sqrt (x);
++}
++
+ strong_alias (__ieee754_sqrt, __sqrt_finite)
+diff --git a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c
+index 9d175122a8..10de1f0cc3 100644
+--- a/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c
++++ b/sysdeps/powerpc/powerpc64/e6500/fpu/e_sqrtf.c
+@@ -39,10 +39,10 @@ static const float threehalf = 1.5;
+ 
+ #ifdef __STDC__
+ float
+-__ieee754_sqrtf (float b)
++__slow_ieee754_sqrtf (float b)
+ #else
+ float
+-__ieee754_sqrtf (b)
++__slow_ieee754_sqrtf (b)
+      float b;
+ #endif
+ {
+@@ -99,4 +99,12 @@ __ieee754_sqrtf (b)
+     }
+   return f_washf (b);
+ }
++
++#undef __ieee754_sqrtf
++float
++__ieee754_sqrtf (float x)
++{
++  return __slow_ieee754_sqrtf (x);
++}
++
+ strong_alias (__ieee754_sqrtf, __sqrtf_finite)

+ 58 - 0
recipes-core/glibc/glibc/0012-Quote-from-bug-1443-which-explains-what-the-patch-do.patch

@@ -0,0 +1,58 @@
+From add514edf4299d1bf540d85d0aa0bd5fe0d46b78 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Wed, 18 Mar 2015 00:20:09 +0000
+Subject: [PATCH] Quote from bug 1443 which explains what the patch does :
+
+  We build some random program and link it with -lust.  When we run it,
+  it dies with a SIGSEGV before reaching main().
+
+  Libust.so depends on liburcu-bp.so from the usermode-rcu package.
+  Although libust.so is not prelinked, liburcu-bp.so IS prelinked; this
+  is critical.
+
+  Libust.so uses a TLS / __thread variable that is defined in liburcu-
+  bp.so.  There are special ARM-specific relocation types that allow two
+  shared libraries to share thread-specific data.  This is critical too.
+
+  One more critical issue: although liburcu-bp.so is prelinked, we can't
+  load it at its prelinked address, because we also link against
+  librt.so, and librt.so uses that address.
+
+  The dynamic linker is forced to relink liburcu-bp.so at a different
+  address.  In the course of relinking, it processes the special ARM
+  relocation record mentioned above.  The prelinker has already filled
+  in the information, which is a short offset into a table of thread-
+  specific data that is allocated per-thread for each library that uses
+  TLS.  Because the normal behavior of a relocation is to add the symbol
+  value to an addend stored at the address being relocated, we end up
+  adding the short offset to itself, doubling it.
+
+  Now we have an awkward situation.  The libust.so library doesn't know
+  about the addend, so its TLS data for this element is correct.  The
+  liburcu-bp.so library has a different offset for the element.  When we
+  go to initialize the element for the first time in liburcu-bp.so, we
+  write the address of the result at the doubled (broken) offset.
+  Later, when we refer to the address from libust.so, we check the value
+  at the correct offset, but it's NULL, so we eat hot SIGSEGV.
+
+Upstream-Status: Pending
+
+Signed-off-by: Andrei Dinu <andrei.adrianx.dinu@intel.com>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ sysdeps/arm/dl-machine.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h
+index ff5e09e207..d68bfe5cbe 100644
+--- a/sysdeps/arm/dl-machine.h
++++ b/sysdeps/arm/dl-machine.h
+@@ -510,7 +510,7 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
+ 
+ 	case R_ARM_TLS_DTPOFF32:
+ 	  if (sym != NULL)
+-	    *reloc_addr += sym->st_value;
++	    *reloc_addr = sym->st_value;
+ 	  break;
+ 
+ 	case R_ARM_TLS_TPOFF32:

+ 33 - 0
recipes-core/glibc/glibc/0013-eglibc-run-libm-err-tab.pl-with-specific-dirs-in-S.patch

@@ -0,0 +1,33 @@
+From c5047b8f7d1a17324cfa02b99f07a70ebcec2cf2 Mon Sep 17 00:00:00 2001
+From: Ting Liu <b28495@freescale.com>
+Date: Wed, 19 Dec 2012 04:39:57 -0600
+Subject: [PATCH] eglibc: run libm-err-tab.pl with specific dirs in ${S}
+
+libm-err-tab.pl will parse all the files named "libm-test-ulps"
+in the given dir recursively. To avoid parsing the one in
+${S}/.pc/ (it does exist after eglibc adds aarch64 support,
+${S}/.pc/aarch64-0001-glibc-fsf-v1-eaf6f205.patch/ports/sysdeps/
+aarch64/libm-test-ulps), run libm-err-tab.pl with specific dirs
+in ${S}.
+
+Upstream-Status: inappropriate [OE specific]
+
+Signed-off-by: Ting Liu <b28495@freescale.com>
+---
+ manual/Makefile | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/manual/Makefile b/manual/Makefile
+index e83444341e..aa2645bc55 100644
+--- a/manual/Makefile
++++ b/manual/Makefile
+@@ -103,7 +103,8 @@ $(objpfx)stamp-libm-err: $(..)math/gen-libm-test.py \
+ 			 $(wildcard $(foreach dir,$(sysdirs),\
+ 						  $(dir)/libm-test-ulps))
+ 	pwd=`pwd`; \
+-	$(PYTHON) $< -s $$pwd/.. -m $(objpfx)libm-err-tmp
++	$(PYTHON) $< -s $$pwd/../ports -m $(objpfx)libm-err-tmp
++	$(PYTHON) $< -s $$pwd/../sysdeps -m $(objpfx)libm-err-tmp
+ 	$(move-if-change) $(objpfx)libm-err-tmp $(objpfx)libm-err.texi
+ 	touch $@
+ 

+ 58 - 0
recipes-core/glibc/glibc/0014-__ieee754_sqrt-f-are-now-inline-functions-and-call-o.patch

@@ -0,0 +1,58 @@
+From 133870f12ba36686dd8df1311fac32a4c5b28579 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Wed, 18 Mar 2015 00:24:46 +0000
+Subject: [PATCH] __ieee754_sqrt{,f} are now inline functions and call out
+ __slow versions
+
+Upstream-Status: Pending
+
+Signed-off-by: chunrong guo <B40290@freescale.com>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c  | 6 +++---
+ sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c | 4 ++--
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
+index 1c34244bd8..7038a70b47 100644
+--- a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
++++ b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrt.c
+@@ -41,10 +41,10 @@ static const float half = 0.5;
+ 
+ #ifdef __STDC__
+ double
+-__ieee754_sqrt (double b)
++__slow_ieee754_sqrt (double b)
+ #else
+ double
+-__ieee754_sqrt (b)
++__slow_ieee754_sqrt (b)
+      double b;
+ #endif
+ {
+@@ -83,7 +83,7 @@ __ieee754_sqrt (b)
+ 
+           /* Handle small numbers by scaling.  */
+           if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
+-            return __ieee754_sqrt (b * two108) * twom54;
++            return __slow_ieee754_sqrt (b * two108) * twom54;
+ 
+ #define FMADD(a_, c_, b_)                                               \
+           ({ double __r;                                                \
+diff --git a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
+index 812653558f..10de1f0cc3 100644
+--- a/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
++++ b/sysdeps/powerpc/powerpc32/e6500/fpu/e_sqrtf.c
+@@ -39,10 +39,10 @@ static const float threehalf = 1.5;
+ 
+ #ifdef __STDC__
+ float
+-__ieee754_sqrtf (float b)
++__slow_ieee754_sqrtf (float b)
+ #else
+ float
+-__ieee754_sqrtf (b)
++__slow_ieee754_sqrtf (b)
+      float b;
+ #endif
+ {

+ 39 - 0
recipes-core/glibc/glibc/0015-sysdeps-gnu-configure.ac-handle-correctly-libc_cv_ro.patch

@@ -0,0 +1,39 @@
+From b4613f814ba7ba5db95d18116172f81a83ac8f5b Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Wed, 18 Mar 2015 00:27:10 +0000
+Subject: [PATCH] sysdeps/gnu/configure.ac: handle correctly
+ $libc_cv_rootsbindir
+
+Upstream-Status:Pending
+
+Signed-off-by: Matthieu Crapet <Matthieu.Crapet@ingenico.com>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ sysdeps/gnu/configure    | 2 +-
+ sysdeps/gnu/configure.ac | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sysdeps/gnu/configure b/sysdeps/gnu/configure
+index c15d1087e8..37cc983f2a 100644
+--- a/sysdeps/gnu/configure
++++ b/sysdeps/gnu/configure
+@@ -32,6 +32,6 @@ case "$prefix" in
+   else
+     libc_cv_localstatedir=$localstatedir
+    fi
+-  libc_cv_rootsbindir=/sbin
++  test -n "$libc_cv_rootsbindir" || libc_cv_rootsbindir=/sbin
+   ;;
+ esac
+diff --git a/sysdeps/gnu/configure.ac b/sysdeps/gnu/configure.ac
+index 634fe4de2a..3db1697f4f 100644
+--- a/sysdeps/gnu/configure.ac
++++ b/sysdeps/gnu/configure.ac
+@@ -21,6 +21,6 @@ case "$prefix" in
+   else
+     libc_cv_localstatedir=$localstatedir
+    fi
+-  libc_cv_rootsbindir=/sbin
++  test -n "$libc_cv_rootsbindir" || libc_cv_rootsbindir=/sbin
+   ;;
+ esac

+ 260 - 0
recipes-core/glibc/glibc/0016-yes-within-the-path-sets-wrong-config-variables.patch

@@ -0,0 +1,260 @@
+From 7be3e82b66394a7b242e56c6fc609e858b8e2436 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Wed, 18 Mar 2015 00:31:06 +0000
+Subject: [PATCH] 'yes' within the path sets wrong config variables
+
+It seems that the 'AC_EGREP_CPP(yes...' example is quite popular
+but being such a short word to grep it is likely to produce
+false-positive matches with the path it is configured into.
+
+The change is to use a more elaborated string to grep for.
+
+Upstream-Status: Submitted [libc-alpha@sourceware.org]
+
+Signed-off-by: Benjamin Esquivel <benjamin.esquivel@linux.intel.com>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ sysdeps/aarch64/configure                              | 4 ++--
+ sysdeps/aarch64/configure.ac                           | 4 ++--
+ sysdeps/arm/configure                                  | 4 ++--
+ sysdeps/arm/configure.ac                               | 4 ++--
+ sysdeps/mips/configure                                 | 4 ++--
+ sysdeps/mips/configure.ac                              | 4 ++--
+ sysdeps/nios2/configure                                | 4 ++--
+ sysdeps/nios2/configure.ac                             | 4 ++--
+ sysdeps/unix/sysv/linux/mips/configure                 | 4 ++--
+ sysdeps/unix/sysv/linux/mips/configure.ac              | 4 ++--
+ sysdeps/unix/sysv/linux/powerpc/powerpc64/configure    | 8 ++++----
+ sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac | 8 ++++----
+ 12 files changed, 28 insertions(+), 28 deletions(-)
+
+diff --git a/sysdeps/aarch64/configure b/sysdeps/aarch64/configure
+index 4c1fac49f3..597314f476 100644
+--- a/sysdeps/aarch64/configure
++++ b/sysdeps/aarch64/configure
+@@ -157,12 +157,12 @@ else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ #ifdef __AARCH64EB__
+-                      yes
++                      is_aarch64_be
+                      #endif
+ 
+ _ACEOF
+ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+-  $EGREP "yes" >/dev/null 2>&1; then :
++  $EGREP "is_aarch64_be" >/dev/null 2>&1; then :
+   libc_cv_aarch64_be=yes
+ else
+   libc_cv_aarch64_be=no
+diff --git a/sysdeps/aarch64/configure.ac b/sysdeps/aarch64/configure.ac
+index 3347c13fa1..4af163c0b6 100644
+--- a/sysdeps/aarch64/configure.ac
++++ b/sysdeps/aarch64/configure.ac
+@@ -17,8 +17,8 @@ AC_DEFINE(SUPPORT_STATIC_PIE)
+ # the dynamic linker via %ifdef.
+ AC_CACHE_CHECK([for big endian],
+   [libc_cv_aarch64_be],
+-  [AC_EGREP_CPP(yes,[#ifdef __AARCH64EB__
+-                      yes
++  [AC_EGREP_CPP(is_aarch64_be,[#ifdef __AARCH64EB__
++                      is_aarch64_be
+                      #endif
+   ], libc_cv_aarch64_be=yes, libc_cv_aarch64_be=no)])
+ if test $libc_cv_aarch64_be = yes; then
+diff --git a/sysdeps/arm/configure b/sysdeps/arm/configure
+index 431e843b2b..e152461138 100644
+--- a/sysdeps/arm/configure
++++ b/sysdeps/arm/configure
+@@ -151,12 +151,12 @@ else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ #ifdef __ARM_PCS_VFP
+-		      yes
++		      use_arm_pcs_vfp
+ 		     #endif
+ 
+ _ACEOF
+ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+-  $EGREP "yes" >/dev/null 2>&1; then :
++  $EGREP "use_arm_pcs_vfp" >/dev/null 2>&1; then :
+   libc_cv_arm_pcs_vfp=yes
+ else
+   libc_cv_arm_pcs_vfp=no
+diff --git a/sysdeps/arm/configure.ac b/sysdeps/arm/configure.ac
+index 90cdd69c75..05a262ba00 100644
+--- a/sysdeps/arm/configure.ac
++++ b/sysdeps/arm/configure.ac
+@@ -15,8 +15,8 @@ AC_DEFINE(PI_STATIC_AND_HIDDEN)
+ # the dynamic linker via %ifdef.
+ AC_CACHE_CHECK([whether the compiler is using the ARM hard-float ABI],
+   [libc_cv_arm_pcs_vfp],
+-  [AC_EGREP_CPP(yes,[#ifdef __ARM_PCS_VFP
+-		      yes
++  [AC_EGREP_CPP(use_arm_pcs_vfp,[#ifdef __ARM_PCS_VFP
++		      use_arm_pcs_vfp
+ 		     #endif
+   ], libc_cv_arm_pcs_vfp=yes, libc_cv_arm_pcs_vfp=no)])
+ if test $libc_cv_arm_pcs_vfp = yes; then
+diff --git a/sysdeps/mips/configure b/sysdeps/mips/configure
+index 4e13248c03..f14af952d0 100644
+--- a/sysdeps/mips/configure
++++ b/sysdeps/mips/configure
+@@ -143,11 +143,11 @@ else
+ /* end confdefs.h.  */
+ dnl
+ #ifdef __mips_nan2008
+-yes
++use_mips_nan2008
+ #endif
+ _ACEOF
+ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+-  $EGREP "yes" >/dev/null 2>&1; then :
++  $EGREP "use_mips_nan2008" >/dev/null 2>&1; then :
+   libc_cv_mips_nan2008=yes
+ else
+   libc_cv_mips_nan2008=no
+diff --git a/sysdeps/mips/configure.ac b/sysdeps/mips/configure.ac
+index bcbdaffd9f..ad3057f4cc 100644
+--- a/sysdeps/mips/configure.ac
++++ b/sysdeps/mips/configure.ac
+@@ -6,9 +6,9 @@ dnl position independent way.
+ dnl AC_DEFINE(PI_STATIC_AND_HIDDEN)
+ 
+ AC_CACHE_CHECK([whether the compiler is using the 2008 NaN encoding],
+-  libc_cv_mips_nan2008, [AC_EGREP_CPP(yes, [dnl
++  libc_cv_mips_nan2008, [AC_EGREP_CPP(use_mips_nan2008, [dnl
+ #ifdef __mips_nan2008
+-yes
++use_mips_nan2008
+ #endif], libc_cv_mips_nan2008=yes, libc_cv_mips_nan2008=no)])
+ if test x$libc_cv_mips_nan2008 = xyes; then
+   AC_DEFINE(HAVE_MIPS_NAN2008)
+diff --git a/sysdeps/nios2/configure b/sysdeps/nios2/configure
+index 14c8a3a014..dde3814ef2 100644
+--- a/sysdeps/nios2/configure
++++ b/sysdeps/nios2/configure
+@@ -142,12 +142,12 @@ else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ #ifdef __nios2_big_endian__
+-                      yes
++                      is_nios2_be
+                      #endif
+ 
+ _ACEOF
+ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+-  $EGREP "yes" >/dev/null 2>&1; then :
++  $EGREP "is_nios2_be" >/dev/null 2>&1; then :
+   libc_cv_nios2_be=yes
+ else
+   libc_cv_nios2_be=no
+diff --git a/sysdeps/nios2/configure.ac b/sysdeps/nios2/configure.ac
+index f05f43802b..dc8639902d 100644
+--- a/sysdeps/nios2/configure.ac
++++ b/sysdeps/nios2/configure.ac
+@@ -4,8 +4,8 @@ GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+ # Nios II big endian is not yet supported.
+ AC_CACHE_CHECK([for big endian],
+   [libc_cv_nios2_be],
+-  [AC_EGREP_CPP(yes,[#ifdef __nios2_big_endian__
+-                      yes
++  [AC_EGREP_CPP(is_nios2_be,[#ifdef __nios2_big_endian__
++                      is_nios2_be
+                      #endif
+   ], libc_cv_nios2_be=yes, libc_cv_nios2_be=no)])
+ if test $libc_cv_nios2_be = yes; then
+diff --git a/sysdeps/unix/sysv/linux/mips/configure b/sysdeps/unix/sysv/linux/mips/configure
+index f25f2a3a65..1b7483e6c6 100644
+--- a/sysdeps/unix/sysv/linux/mips/configure
++++ b/sysdeps/unix/sysv/linux/mips/configure
+@@ -414,11 +414,11 @@ else
+ /* end confdefs.h.  */
+ dnl
+ #ifdef __mips_nan2008
+-yes
++use_mips_nan2008
+ #endif
+ _ACEOF
+ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+-  $EGREP "yes" >/dev/null 2>&1; then :
++  $EGREP "use_mips_nan2008" >/dev/null 2>&1; then :
+   libc_cv_mips_nan2008=yes
+ else
+   libc_cv_mips_nan2008=no
+diff --git a/sysdeps/unix/sysv/linux/mips/configure.ac b/sysdeps/unix/sysv/linux/mips/configure.ac
+index 049a0f4bdf..005526d4e8 100644
+--- a/sysdeps/unix/sysv/linux/mips/configure.ac
++++ b/sysdeps/unix/sysv/linux/mips/configure.ac
+@@ -105,9 +105,9 @@ AC_COMPILE_IFELSE(
+ LIBC_CONFIG_VAR([mips-mode-switch],[${libc_mips_mode_switch}])
+ 
+ AC_CACHE_CHECK([whether the compiler is using the 2008 NaN encoding],
+-  libc_cv_mips_nan2008, [AC_EGREP_CPP(yes, [dnl
++  libc_cv_mips_nan2008, [AC_EGREP_CPP(use_mips_nan2008, [dnl
+ #ifdef __mips_nan2008
+-yes
++use_mips_nan2008
+ #endif], libc_cv_mips_nan2008=yes, libc_cv_mips_nan2008=no)])
+ 
+ libc_mips_nan=
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure b/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure
+index ae7f254da4..874519000b 100644
+--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure
+@@ -155,12 +155,12 @@ else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ #if _CALL_ELF == 2
+-                      yes
++                      use_ppc_elfv2_abi
+                      #endif
+ 
+ _ACEOF
+ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+-  $EGREP "yes" >/dev/null 2>&1; then :
++  $EGREP "use_ppc_elfv2_abi" >/dev/null 2>&1; then :
+   libc_cv_ppc64_elfv2_abi=yes
+ else
+   libc_cv_ppc64_elfv2_abi=no
+@@ -188,12 +188,12 @@ else
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ #ifdef _CALL_ELF
+-                         yes
++                         is_def_call_elf
+                        #endif
+ 
+ _ACEOF
+ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+-  $EGREP "yes" >/dev/null 2>&1; then :
++  $EGREP "is_def_call_elf" >/dev/null 2>&1; then :
+   libc_cv_ppc64_def_call_elf=yes
+ else
+   libc_cv_ppc64_def_call_elf=no
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac b/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac
+index f9cba6e15d..b21f72f1e4 100644
+--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac
+@@ -6,8 +6,8 @@ LIBC_SLIBDIR_RTLDDIR([lib64], [lib64])
+ # Define default-abi according to compiler flags.
+ AC_CACHE_CHECK([whether the compiler is using the PowerPC64 ELFv2 ABI],
+   [libc_cv_ppc64_elfv2_abi],
+-  [AC_EGREP_CPP(yes,[#if _CALL_ELF == 2
+-                      yes
++  [AC_EGREP_CPP(use_ppc_elfv2_abi,[#if _CALL_ELF == 2
++                      use_ppc_elfv2_abi
+                      #endif
+   ], libc_cv_ppc64_elfv2_abi=yes, libc_cv_ppc64_elfv2_abi=no)])
+ if test $libc_cv_ppc64_elfv2_abi = yes; then
+@@ -19,8 +19,8 @@ else
+   # Compiler that do not support ELFv2 ABI does not define _CALL_ELF
+   AC_CACHE_CHECK([whether the compiler defines _CALL_ELF],
+     [libc_cv_ppc64_def_call_elf],
+-    [AC_EGREP_CPP(yes,[#ifdef _CALL_ELF
+-                         yes
++    [AC_EGREP_CPP(is_def_call_elf,[#ifdef _CALL_ELF
++                         is_def_call_elf
+                        #endif
+     ], libc_cv_ppc64_def_call_elf=yes, libc_cv_ppc64_def_call_elf=no)])
+   if test $libc_cv_ppc64_def_call_elf = no; then

+ 34 - 0
recipes-core/glibc/glibc/0017-timezone-re-written-tzselect-as-posix-sh.patch

@@ -0,0 +1,34 @@
+From 2731fa0c7463cd160361a8ac92f3bd7f984d953d Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Wed, 18 Mar 2015 00:33:03 +0000
+Subject: [PATCH] timezone: re-written tzselect as posix sh
+
+To avoid the bash dependency.
+
+Upstream-Status: Pending
+
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ timezone/tzselect.ksh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/timezone/tzselect.ksh b/timezone/tzselect.ksh
+index 18fce27e24..7705df83d7 100755
+--- a/timezone/tzselect.ksh
++++ b/timezone/tzselect.ksh
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ # Ask the user about the time zone, and output the resulting TZ value to stdout.
+ # Interact with the user via stderr and stdin.
+ 
+@@ -34,7 +34,7 @@ REPORT_BUGS_TO=tz@iana.org
+ 
+ # Specify default values for environment variables if they are unset.
+ : ${AWK=awk}
+-: ${TZDIR=`pwd`}
++: ${TZDIR=$(pwd)}
+ 
+ # Output one argument as-is to standard output.
+ # Safer than 'echo', which can mishandle '\' or leading '-'.

+ 72 - 0
recipes-core/glibc/glibc/0018-Remove-bash-dependency-for-nscd-init-script.patch

@@ -0,0 +1,72 @@
+From 412d33bbfe42a10a9b1f62afcc73fe121a0363b0 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Thu, 31 Dec 2015 14:33:02 -0800
+Subject: [PATCH] Remove bash dependency for nscd init script
+
+The nscd init script uses #! /bin/bash but only really uses one bashism
+(translated strings), so remove them and switch the shell to #!/bin/sh.
+
+Upstream-Status: Pending
+
+Signed-off-by: Ross Burton <ross.burton@intel.com>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ nscd/nscd.init | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/nscd/nscd.init b/nscd/nscd.init
+index a882da7d8b..b02986ec15 100644
+--- a/nscd/nscd.init
++++ b/nscd/nscd.init
+@@ -1,4 +1,4 @@
+-#!/bin/bash
++#!/bin/sh
+ #
+ # nscd:		Starts the Name Switch Cache Daemon
+ #
+@@ -49,7 +49,7 @@ prog=nscd
+ start () {
+     [ -d /var/run/nscd ] || mkdir /var/run/nscd
+     [ -d /var/db/nscd ] || mkdir /var/db/nscd
+-    echo -n $"Starting $prog: "
++    echo -n "Starting $prog: "
+     daemon /usr/sbin/nscd
+     RETVAL=$?
+     echo
+@@ -58,7 +58,7 @@ start () {
+ }
+ 
+ stop () {
+-    echo -n $"Stopping $prog: "
++    echo -n "Stopping $prog: "
+     /usr/sbin/nscd -K
+     RETVAL=$?
+     if [ $RETVAL -eq 0 ]; then
+@@ -67,9 +67,9 @@ stop () {
+ 	# a non-privileged user
+ 	rm -f /var/run/nscd/nscd.pid
+ 	rm -f /var/run/nscd/socket
+-       	success $"$prog shutdown"
++	success "$prog shutdown"
+     else
+-       	failure $"$prog shutdown"
++	failure "$prog shutdown"
+     fi
+     echo
+     return $RETVAL
+@@ -103,13 +103,13 @@ case "$1" in
+ 	RETVAL=$?
+ 	;;
+     force-reload | reload)
+-    	echo -n $"Reloading $prog: "
++	echo -n "Reloading $prog: "
+ 	killproc /usr/sbin/nscd -HUP
+ 	RETVAL=$?
+ 	echo
+ 	;;
+     *)
+-	echo $"Usage: $0 {start|stop|status|restart|reload|condrestart}"
++	echo "Usage: $0 {start|stop|status|restart|reload|condrestart}"
+ 	RETVAL=1
+ 	;;
+ esac

+ 616 - 0
recipes-core/glibc/glibc/0019-eglibc-Cross-building-and-testing-instructions.patch

@@ -0,0 +1,616 @@
+From db9674ffc6583a508da1a3cb044c3ccf3febaea1 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Wed, 18 Mar 2015 00:42:58 +0000
+Subject: [PATCH] eglibc: Cross building and testing instructions
+
+Ported from eglibc
+Upstream-Status: Pending
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ GLIBC.cross-building | 383 +++++++++++++++++++++++++++++++++++++++++++
+ GLIBC.cross-testing  | 205 +++++++++++++++++++++++
+ 2 files changed, 588 insertions(+)
+ create mode 100644 GLIBC.cross-building
+ create mode 100644 GLIBC.cross-testing
+
+diff --git a/GLIBC.cross-building b/GLIBC.cross-building
+new file mode 100644
+index 0000000000..e6e0da1aaf
+--- /dev/null
++++ b/GLIBC.cross-building
+@@ -0,0 +1,383 @@
++                                                        -*- mode: text -*-
++
++                        Cross-Compiling GLIBC
++                  Jim Blandy <jimb@codesourcery.com>
++
++
++Introduction
++
++Most GNU tools have a simple build procedure: you run their
++'configure' script, and then you run 'make'.  Unfortunately, the
++process of cross-compiling the GNU C library is quite a bit more
++involved:
++
++1) Build a cross-compiler, with certain facilities disabled.
++
++2) Configure the C library using the compiler you built in step 1).
++   Build a few of the C run-time object files, but not the rest of the
++   library.  Install the library's header files and the run-time
++   object files, and create a dummy libc.so.
++
++3) Build a second cross-compiler, using the header files and object
++   files you installed in step 2.
++
++4) Configure, build, and install a fresh C library, using the compiler
++   built in step 3.
++
++5) Build a third cross-compiler, based on the C library built in step 4.
++
++The reason for this complexity is that, although GCC and the GNU C
++library are distributed separately, they are not actually independent
++of each other: GCC requires the C library's headers and some object
++files to compile its own libraries, while the C library depends on
++GCC's libraries.  GLIBC includes features and bug fixes to the stock
++GNU C library that simplify this process, but the fundamental
++interdependency stands.
++
++In this document, we explain how to cross-compile an GLIBC/GCC pair
++from source.  Our intended audience is developers who are already
++familiar with the GNU toolchain and comfortable working with
++cross-development tools.  While we do present a worked example to
++accompany the explanation, for clarity's sake we do not cover many of
++the options available to cross-toolchain users.
++
++
++Preparation
++
++GLIBC requires recent versions of the GNU binutils, GCC, and the
++Linux kernel.  The web page <http://www.eglibc.org/prerequisites>
++documents the current requirements, and lists patches needed for
++certain target architectures.  As of this writing, these build
++instructions have been tested with binutils 2.22.51, GCC 4.6.2,
++and Linux 3.1.
++
++First, let's set some variables, to simplify later commands.  We'll
++build GLIBC and GCC for an ARM target, known to the Linux kernel
++as 'arm', and we'll do the build on an Intel x86_64 Linux box:
++
++    $ build=x86_64-pc-linux-gnu
++    $ host=$build
++    $ target=arm-none-linux-gnueabi
++    $ linux_arch=arm
++
++We're using the aforementioned versions of Binutils, GCC, and Linux:
++
++    $ binutilsv=binutils-2.22.51
++    $ gccv=gcc-4.6.2
++    $ linuxv=linux-3.1
++
++We're carrying out the entire process under '~/cross-build', which
++contains unpacked source trees for binutils, gcc, and linux kernel,
++along with GLIBC svn trunk (which can be checked-out with
++'svn co http://www.eglibc.org/svn/trunk eglibc'):
++
++    $ top=$HOME/cross-build/$target
++    $ src=$HOME/cross-build/src
++    $ ls $src
++    binutils-2.22.51  glibc  gcc-4.6.2  linux-3.1
++
++We're going to place our build directories in a subdirectory 'obj',
++we'll install the cross-development toolchain in 'tools', and we'll
++place our sysroot (containing files to be installed on the target
++system) in 'sysroot':
++
++    $ obj=$top/obj
++    $ tools=$top/tools
++    $ sysroot=$top/sysroot
++
++
++Binutils
++
++Configuring and building binutils for the target is straightforward:
++
++    $ mkdir -p $obj/binutils
++    $ cd $obj/binutils
++    $ $src/$binutilsv/configure \
++    >     --target=$target \
++    >     --prefix=$tools \
++    >     --with-sysroot=$sysroot
++    $ make
++    $ make install
++
++
++The First GCC
++
++For our work, we need a cross-compiler targeting an ARM Linux
++system.  However, that configuration includes the shared library
++'libgcc_s.so', which is compiled against the GLIBC headers (which we
++haven't installed yet) and linked against 'libc.so' (which we haven't
++built yet).
++
++Fortunately, there are configuration options for GCC which tell it not
++to build 'libgcc_s.so'.  The '--without-headers' option is supposed to
++take care of this, but its implementation is incomplete, so you must
++also configure with the '--with-newlib' option.  While '--with-newlib'
++appears to mean "Use the Newlib C library", its effect is to tell the
++GCC build machinery, "Don't assume there is a C library available."
++
++We also need to disable some of the libraries that would normally be
++built along with GCC, and specify that only the compiler for the C
++language is needed.
++
++So, we create a build directory, configure, make, and install.
++
++    $ mkdir -p $obj/gcc1
++    $ cd $obj/gcc1
++    $ $src/$gccv/configure \
++    >     --target=$target \
++    >     --prefix=$tools \
++    >     --without-headers --with-newlib \
++    >     --disable-shared --disable-threads --disable-libssp \
++    >     --disable-libgomp --disable-libmudflap --disable-libquadmath \
++    >     --disable-decimal-float --disable-libffi \
++    >     --enable-languages=c
++    $ PATH=$tools/bin:$PATH make
++    $ PATH=$tools/bin:$PATH make install
++
++
++Linux Kernel Headers
++
++To configure GLIBC, we also need Linux kernel headers in place.
++Fortunately, the Linux makefiles have a target that installs them for
++us.  Since the process does modify the source tree a bit, we make a
++copy first:
++
++    $ cp -r $src/$linuxv $obj/linux
++    $ cd $obj/linux
++
++Now we're ready to install the headers into the sysroot:
++
++    $ PATH=$tools/bin:$PATH \
++    > make headers_install \
++    >      ARCH=$linux_arch CROSS_COMPILE=$target- \
++    >      INSTALL_HDR_PATH=$sysroot/usr
++
++
++GLIBC Headers and Preliminary Objects
++
++Using the cross-compiler we've just built, we can now configure GLIBC
++well enough to install the headers and build the object files that the
++full cross-compiler will need:
++
++    $ mkdir -p $obj/glibc-headers
++    $ cd $obj/glibc-headers
++    $ BUILD_CC=gcc \
++    > CC=$tools/bin/$target-gcc \
++    > CXX=$tools/bin/$target-g++ \
++    > AR=$tools/bin/$target-ar \
++    > RANLIB=$tools/bin/$target-ranlib \
++    > $src/glibc/libc/configure \
++    >     --prefix=/usr \
++    >     --with-headers=$sysroot/usr/include \
++    >     --build=$build \
++    >     --host=$target \
++    >     --disable-profile --without-gd --without-cvs \
++    >     --enable-add-ons=nptl,libidn,../ports
++
++The option '--prefix=/usr' may look strange, but you should never
++configure GLIBC with a prefix other than '/usr': in various places,
++GLIBC's build system checks whether the prefix is '/usr', and does
++special handling only if that is the case.  Unless you use this
++prefix, you will get a sysroot that does not use the standard Linux
++directory layouts and cannot be used as a basis for the root
++filesystem on your target system compatibly with normal GLIBC
++installations.
++
++The '--with-headers' option tells GLIBC where the Linux headers have
++been installed.
++
++The '--enable-add-ons=nptl,libidn,../ports' option tells GLIBC to look
++for the listed glibc add-ons. Most notably the ports add-on (located
++just above the libc sources in the GLIBC svn tree) is required to
++support ARM targets.
++
++We can now use the 'install-headers' makefile target to install the
++headers:
++
++    $ make install-headers install_root=$sysroot \
++    >                      install-bootstrap-headers=yes
++
++The 'install_root' variable indicates where the files should actually
++be installed; its value is treated as the parent of the '--prefix'
++directory we passed to the configure script, so the headers will go in
++'$sysroot/usr/include'.  The 'install-bootstrap-headers' variable
++requests special handling for certain tricky header files.
++
++Next, there are a few object files needed to link shared libraries,
++which we build and install by hand:
++
++    $ mkdir -p $sysroot/usr/lib
++    $ make csu/subdir_lib
++    $ cp csu/crt1.o csu/crti.o csu/crtn.o $sysroot/usr/lib
++
++Finally, 'libgcc_s.so' requires a 'libc.so' to link against.  However,
++since we will never actually execute its code, it doesn't matter what
++it contains.  So, treating '/dev/null' as a C source file, we produce
++a dummy 'libc.so' in one step:
++
++    $ $tools/bin/$target-gcc -nostdlib -nostartfiles -shared -x c /dev/null \
++    >                        -o $sysroot/usr/lib/libc.so
++
++
++The Second GCC
++
++With the GLIBC headers and selected object files installed, we can
++now build a GCC that is capable of compiling GLIBC.  We configure,
++build, and install the second GCC, again building only the C compiler,
++and avoiding libraries we won't use:
++
++    $ mkdir -p $obj/gcc2
++    $ cd $obj/gcc2
++    $ $src/$gccv/configure \
++    >     --target=$target \
++    >     --prefix=$tools \
++    >     --with-sysroot=$sysroot \
++    >     --disable-libssp --disable-libgomp --disable-libmudflap \
++    >     --disable-libffi --disable-libquadmath \
++    >     --enable-languages=c
++    $ PATH=$tools/bin:$PATH make
++    $ PATH=$tools/bin:$PATH make install
++
++
++GLIBC, Complete
++
++With the second compiler built and installed, we're now ready for the
++full GLIBC build:
++
++    $ mkdir -p $obj/glibc
++    $ cd $obj/glibc
++    $ BUILD_CC=gcc \
++    > CC=$tools/bin/$target-gcc \
++    > CXX=$tools/bin/$target-g++ \
++    > AR=$tools/bin/$target-ar \
++    > RANLIB=$tools/bin/$target-ranlib \
++    > $src/glibc/libc/configure \
++    >     --prefix=/usr \
++    >     --with-headers=$sysroot/usr/include \
++    >     --with-kconfig=$obj/linux/scripts/kconfig \
++    >     --build=$build \
++    >     --host=$target \
++    >     --disable-profile --without-gd --without-cvs \
++    >     --enable-add-ons=nptl,libidn,../ports
++
++Note the additional '--with-kconfig' option. This tells GLIBC where to
++find the host config tools used by the kernel 'make config' and 'make
++menuconfig'.  These tools can be re-used by GLIBC for its own 'make
++*config' support, which will create 'option-groups.config' for you.
++But first make sure those tools have been built by running some
++dummy 'make *config' calls in the kernel directory:
++
++    $ cd $obj/linux
++    $ PATH=$tools/bin:$PATH make config \
++    >      ARCH=$linux_arch CROSS_COMPILE=$target- \
++    $ PATH=$tools/bin:$PATH make menuconfig \
++    >      ARCH=$linux_arch CROSS_COMPILE=$target- \
++
++Now we can configure and build the full GLIBC:
++
++    $ cd $obj/glibc
++    $ PATH=$tools/bin:$PATH make defconfig
++    $ PATH=$tools/bin:$PATH make menuconfig
++    $ PATH=$tools/bin:$PATH make
++    $ PATH=$tools/bin:$PATH make install install_root=$sysroot
++
++At this point, we have a complete GLIBC installation in '$sysroot',
++with header files, library files, and most of the C runtime startup
++files in place.
++
++
++The Third GCC
++
++Finally, we recompile GCC against this full installation, enabling
++whatever languages and libraries we would like to use:
++
++    $ mkdir -p $obj/gcc3
++    $ cd $obj/gcc3
++    $ $src/$gccv/configure \
++    >     --target=$target \
++    >     --prefix=$tools \
++    >     --with-sysroot=$sysroot \
++    >     --enable-__cxa_atexit \
++    >     --disable-libssp --disable-libgomp --disable-libmudflap \
++    >     --enable-languages=c,c++
++    $ PATH=$tools/bin:$PATH make
++    $ PATH=$tools/bin:$PATH make install
++
++The '--enable-__cxa_atexit' option tells GCC what sort of C++
++destructor support to expect from the C library; it's required with
++GLIBC.
++
++And since GCC's installation process isn't designed to help construct
++sysroot trees, we must manually copy certain libraries into place in
++the sysroot.
++
++    $ cp -d $tools/$target/lib/libgcc_s.so* $sysroot/lib
++    $ cp -d $tools/$target/lib/libstdc++.so* $sysroot/usr/lib
++
++
++Trying Things Out
++
++At this point, '$tools' contains a cross toolchain ready to use
++the GLIBC installation in '$sysroot':
++
++    $ cat > hello.c <<EOF
++    > #include <stdio.h>
++    > int
++    > main (int argc, char **argv)
++    > {
++    >   puts ("Hello, world!");
++    >   return 0;
++    > }
++    > EOF
++    $ $tools/bin/$target-gcc -Wall hello.c -o hello
++    $ cat > c++-hello.cc <<EOF
++    > #include <iostream>
++    > int
++    > main (int argc, char **argv)
++    > {
++    >   std::cout << "Hello, C++ world!" << std::endl;
++    >   return 0;
++    > }
++    > EOF
++    $ $tools/bin/$target-g++ -Wall c++-hello.cc -o c++-hello
++
++
++We can use 'readelf' to verify that these are indeed executables for
++our target, using our dynamic linker:
++
++    $ $tools/bin/$target-readelf -hl hello
++    ELF Header:
++    ...
++      Type:                              EXEC (Executable file)
++      Machine:                           ARM
++
++    ...
++    Program Headers:
++      Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
++      PHDR           0x000034 0x10000034 0x10000034 0x00100 0x00100 R E 0x4
++      INTERP         0x000134 0x00008134 0x00008134 0x00013 0x00013 R   0x1
++          [Requesting program interpreter: /lib/ld-linux.so.3]
++      LOAD           0x000000 0x00008000 0x00008000 0x0042c 0x0042c R E 0x8000
++    ...
++
++Looking at the dynamic section of the installed 'libgcc_s.so', we see
++that the 'NEEDED' entry for the C library does include the '.6'
++suffix, indicating that was linked against our fully build GLIBC, and
++not our dummy 'libc.so':
++
++    $ $tools/bin/$target-readelf -d $sysroot/lib/libgcc_s.so.1
++    Dynamic section at offset 0x1083c contains 24 entries:
++      Tag        Type                         Name/Value
++     0x00000001 (NEEDED)                     Shared library: [libc.so.6]
++     0x0000000e (SONAME)                     Library soname: [libgcc_s.so.1]
++    ...
++
++
++And on the target machine, we can run our programs:
++
++    $ $sysroot/lib/ld.so.1 --library-path $sysroot/lib:$sysroot/usr/lib \
++    > ./hello
++    Hello, world!
++    $ $sysroot/lib/ld.so.1 --library-path $sysroot/lib:$sysroot/usr/lib \
++    > ./c++-hello
++    Hello, C++ world!
+diff --git a/GLIBC.cross-testing b/GLIBC.cross-testing
+new file mode 100644
+index 0000000000..b67b468466
+--- /dev/null
++++ b/GLIBC.cross-testing
+@@ -0,0 +1,205 @@
++                                                        -*- mode: text -*-
++
++                      Cross-Testing With GLIBC
++                  Jim Blandy <jimb@codesourcery.com>
++
++
++Introduction
++
++Developers writing software for embedded systems often use a desktop
++or other similarly capable computer for development, but need to run
++tests on the embedded system, or perhaps on a simulator.  When
++configured for cross-compilation, the stock GNU C library simply
++disables running tests altogether: the command 'make tests' builds
++test programs, but does not run them.  GLIBC, however, provides
++facilities for compiling tests and generating data files on the build
++system, but running the test programs themselves on a remote system or
++simulator.
++
++
++Test environment requirements
++
++The test environment must meet certain conditions for GLIBC's
++cross-testing facilities to work:
++
++- Shared filesystems.  The 'build' system, on which you configure and
++  compile GLIBC, and the 'host' system, on which you intend to run
++  GLIBC, must share a filesystem containing the GLIBC build and
++  source trees.  Files must appear at the same paths on both systems.
++
++- Remote-shell like invocation.  There must be a way to run a program
++  on the host system from the build system, passing it properly quoted
++  command-line arguments, setting environment variables, and
++  inheriting the caller's standard input and output.
++
++
++Usage
++
++To use GLIBC's cross-testing support, provide values for the
++following Make variables when you invoke 'make':
++
++- cross-test-wrapper
++
++  This should be the name of the cross-testing wrapper command, along
++  with any arguments.
++
++- cross-localedef
++
++  This should be the name of a cross-capable localedef program, like
++  that included in the GLIBC 'localedef' module, along with any
++  arguments needed.
++
++These are each explained in detail below.
++
++
++The Cross-Testing Wrapper
++
++To run test programs reliably, the stock GNU C library takes care to
++ensure that test programs use the newly compiled dynamic linker and
++shared libraries, and never the host system's installed libraries.  To
++accomplish this, it runs the tests by explicitly invoking the dynamic
++linker from the build tree, passing it a list of build tree
++directories to search for shared libraries, followed by the name of
++the executable to run and its arguments.
++
++For example, where one might normally run a test program like this:
++
++    $ ./tst-foo arg1 arg2
++
++the GNU C library might run that program like this:
++
++    $ $objdir/elf/ld-linux.so.3 --library-path $objdir \
++      ./tst-foo arg1 arg2
++
++(where $objdir is the path to the top of the build tree, and the
++trailing backslash indicates a continuation of the command).  In other
++words, each test program invocation is 'wrapped up' inside an explicit
++invocation of the dynamic linker, which must itself execute the test
++program, having loaded shared libraries from the appropriate
++directories.
++
++To support cross-testing, GLIBC allows the developer to optionally
++set the 'cross-test-wrapper' Make variable to another wrapper command,
++to which it passes the entire dynamic linker invocation shown above as
++arguments.  For example, if the developer supplies a wrapper of
++'my-wrapper hostname', then GLIBC would run the test above as
++follows:
++
++    $ my-wrapper hostname \
++      $objdir/elf/ld-linux.so.3 --library-path $objdir \
++      ./tst-foo arg1 arg2
++
++The 'my-wrapper' command is responsible for executing the command
++given on the host system.
++
++Since tests are run in varying directories, the wrapper should either
++be in your command search path, or 'cross-test-wrapper' should give an
++absolute path for the wrapper.
++
++The wrapper must meet several requirements:
++
++- It must preserve the current directory.  As explained above, the
++  build directory tree must be visible on both the build and host
++  systems, at the same path.  The test wrapper must ensure that the
++  current directory it inherits is also inherited by the dynamic
++  linker (and thus the test program itself).
++
++- It must preserve environment variables' values.  Many GLIBC tests
++  set environment variables for test runs; in native testing, it
++  invokes programs like this:
++
++    $ GCONV_PATH=$objdir/iconvdata \
++      $objdir/elf/ld-linux.so.3 --library-path $objdir \
++      ./tst-foo arg1 arg2
++
++  With the cross-testing wrapper, that invocation becomes:
++
++    $ GCONV_PATH=$objdir/iconvdata \
++      my-wrapper hostname \
++      $objdir/elf/ld-linux.so.3 --library-path $objdir \
++      ./tst-foo arg1 arg2
++
++  Here, 'my-wrapper' must ensure that the value it sees for
++  'GCONV_PATH' will be seen by the dynamic linker, and thus 'tst-foo'
++  itself.  (The wrapper supplied with GLIBC simply preserves the
++  values of *all* enviroment variables, with a fixed set of
++  exceptions.)
++
++  If your wrapper is a shell script, take care to correctly propagate
++  environment variables whose values contain spaces and shell
++  metacharacters.
++
++- It must pass the command's arguments, unmodified.  The arguments
++  seen by the test program should be exactly those seen by the wrapper
++  (after whatever arguments are given to the wrapper itself).  The
++  GLIBC test framework performs all needed shell word splitting and
++  expansion (wildcard expansion, parameter substitution, and so on)
++  before invoking the wrapper; further expansion may break the tests.
++
++
++The 'cross-test-ssh.sh' script
++
++If you want to use 'ssh' (or something sufficiently similar) to run
++test programs on your host system, GLIBC includes a shell script,
++'scripts/cross-test-ssh.sh', which you can use as your wrapper
++command.  This script takes care of setting the test command's current
++directory, propagating environment variable values, and carrying
++command-line arguments, all across an 'ssh' connection.  You may even
++supply an alternative to 'ssh' on the command line, if needed.
++
++For more details, pass 'cross-test-ssh.sh' the '--help' option.
++
++
++The Cross-Compiling Locale Definition Command
++
++Some GLIBC tests rely on locales generated especially for the test
++process.  In a native configuration, these tests simply run the
++'localedef' command built by the normal GLIBC build process,
++'locale/localedef', to process and install their locales.  However, in
++a cross-compiling configuration, this 'localedef' is built for the
++host system, not the build system, and since it requires quite a bit
++of memory to run (we have seen it fail on systems with 64MiB of
++memory), it may not be practical to run it on the host system.
++
++If set, GLIBC uses the 'cross-localedef' Make variable as the command
++to run on the build system to process and install locales.  The
++localedef program built from the GLIBC 'localedef' module is
++suitable.
++
++The value of 'cross-localedef' may also include command-line arguments
++to be passed to the program; if you are using GLIBC's 'localedef',
++you may include endianness and 'uint32_t' alignment arguments here.
++
++
++Example
++
++In developing GLIBC's cross-testing facility, we invoked 'make' with
++the following script:
++
++    #!/bin/sh
++
++    srcdir=...
++    test_hostname=...
++    localedefdir=...
++    cross_gxx=...-g++
++
++    wrapper="$srcdir/scripts/cross-test-ssh.sh $test_hostname"
++    localedef="$localedefdir/localedef --little-endian --uint32-align=4"
++
++    make cross-test-wrapper="$wrapper" \
++         cross-localedef="$localedef" \
++         CXX="$cross_gxx" \
++         "$@"
++
++
++Other Cross-Testing Concerns
++
++Here are notes on some other issues which you may encounter in running
++the GLIBC tests in a cross-compiling environment:
++
++- Some tests require a C++ cross-compiler; you should set the 'CXX'
++  Make variable to the name of an appropriate cross-compiler.
++
++- Some tests require access to libstdc++.so.6 and libgcc_s.so.1; we
++  simply place copies of these libraries in the top GLIBC build
++  directory.

+ 97 - 0
recipes-core/glibc/glibc/0020-eglibc-Help-bootstrap-cross-toolchain.patch

@@ -0,0 +1,97 @@
+From 7856684f76c100155cad11b5b236fb31234b6e28 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Wed, 18 Mar 2015 00:49:28 +0000
+Subject: [PATCH] eglibc: Help bootstrap cross toolchain
+
+Taken from EGLIBC, r1484 + r1525
+
+        2007-02-20  Jim Blandy  <jimb@codesourcery.com>
+
+                * Makefile (install-headers): Preserve old behavior: depend on
+                $(inst_includedir)/gnu/stubs.h only if install-bootstrap-headers
+                is set; otherwise, place gnu/stubs.h on the 'install-others' list.
+
+        2007-02-16  Jim Blandy  <jimb@codesourcery.com>
+
+                * Makefile: Amend make install-headers to install everything
+                necessary for building a cross-compiler.  Install gnu/stubs.h as
+                part of 'install-headers', not 'install-others'.
+                If install-bootstrap-headers is 'yes', install a dummy copy of
+                gnu/stubs.h, instead of computing the real thing.
+                * include/stubs-bootstrap.h: New file.
+
+Upstream-Status: Pending
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ Makefile                  | 22 +++++++++++++++++++++-
+ include/stubs-bootstrap.h | 12 ++++++++++++
+ 2 files changed, 33 insertions(+), 1 deletion(-)
+ create mode 100644 include/stubs-bootstrap.h
+
+diff --git a/Makefile b/Makefile
+index f98d5a9e67..c36d04da0f 100644
+--- a/Makefile
++++ b/Makefile
+@@ -79,9 +79,18 @@ subdir-dirs = include
+ vpath %.h $(subdir-dirs)
+ 
+ # What to install.
+-install-others = $(inst_includedir)/gnu/stubs.h
+ install-bin-script =
+ 
++# If we're bootstrapping, install a dummy gnu/stubs.h along with the
++# other headers, so 'make install-headers' produces a useable include
++# tree.  Otherwise, install gnu/stubs.h later, after the rest of the
++# build is done.
++ifeq ($(install-bootstrap-headers),yes)
++install-headers: $(inst_includedir)/gnu/stubs.h
++else
++install-others = $(inst_includedir)/gnu/stubs.h
++endif
++
+ ifeq (yes,$(build-shared))
+ headers += gnu/lib-names.h
+ endif
+@@ -415,6 +424,16 @@ others: $(common-objpfx)testrun.sh $(common-objpfx)debugglibc.sh
+ 
+ subdir-stubs := $(foreach dir,$(subdirs),$(common-objpfx)$(dir)/stubs)
+ 
++# gnu/stubs.h depends (via the subdir 'stubs' targets) on all the .o
++# files in EGLIBC.  For bootstrapping a GCC/EGLIBC pair, an empty
++# gnu/stubs.h is good enough.
++ifeq ($(install-bootstrap-headers),yes)
++$(inst_includedir)/gnu/stubs.h: include/stubs-bootstrap.h $(+force)
++	$(make-target-directory)
++	$(INSTALL_DATA) $< $@
++
++installed-stubs =
++else
+ ifndef abi-variants
+ installed-stubs = $(inst_includedir)/gnu/stubs.h
+ else
+@@ -441,6 +460,7 @@ $(inst_includedir)/gnu/stubs.h: $(+force)
+ 
+ install-others-nosubdir: $(installed-stubs)
+ endif
++endif
+ 
+ 
+ # Since stubs.h is never needed when building the library, we simplify the
+diff --git a/include/stubs-bootstrap.h b/include/stubs-bootstrap.h
+new file mode 100644
+index 0000000000..1d2b669aff
+--- /dev/null
++++ b/include/stubs-bootstrap.h
+@@ -0,0 +1,12 @@
++/* Placeholder stubs.h file for bootstrapping.
++
++   When bootstrapping a GCC/EGLIBC pair, GCC requires that the EGLIBC
++   headers be installed, but we can't fully build EGLIBC without that
++   GCC.  So we run the command:
++
++      make install-headers install-bootstrap-headers=yes
++
++   to install the headers GCC needs, but avoid building certain
++   difficult headers.  The <gnu/stubs.h> header depends, via the
++   EGLIBC subdir 'stubs' make targets, on every .o file in EGLIBC, but
++   an empty stubs.h like this will do fine for GCC.  */

+ 53 - 0
recipes-core/glibc/glibc/0021-eglibc-Resolve-__fpscr_values-on-SH4.patch

@@ -0,0 +1,53 @@
+From 111ab95a85314d1e70fb159a14250354cc69d899 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Wed, 18 Mar 2015 00:55:53 +0000
+Subject: [PATCH] eglibc: Resolve __fpscr_values on SH4
+
+2010-09-29  Nobuhiro Iwamatsu  <iwamatsu@nigauri.org>
+            Andrew Stubbs  <ams@codesourcery.com>
+
+        Resolve SH's __fpscr_values to symbol in libc.so.
+
+        * sysdeps/sh/sh4/fpu/fpu_control.h: Add C++ __set_fpscr prototype.
+        * sysdeps/unix/sysv/linux/sh/Versions (GLIBC_2.2): Add __fpscr_values.
+        * sysdeps/unix/sysv/linux/sh/sysdep.S (___fpscr_values): New constant.
+
+Upstream-Status: Pending
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ sysdeps/unix/sysv/linux/sh/Versions |  1 +
+ sysdeps/unix/sysv/linux/sh/sysdep.S | 11 +++++++++++
+ 2 files changed, 12 insertions(+)
+
+diff --git a/sysdeps/unix/sysv/linux/sh/Versions b/sysdeps/unix/sysv/linux/sh/Versions
+index 9c734ff755..974e33b4b1 100644
+--- a/sysdeps/unix/sysv/linux/sh/Versions
++++ b/sysdeps/unix/sysv/linux/sh/Versions
+@@ -3,6 +3,7 @@ libc {
+   GLIBC_2.2 {
+     # functions used in other libraries
+     __xstat64; __fxstat64; __lxstat64;
++    __fpscr_values;
+ 
+     # a*
+     alphasort64;
+diff --git a/sysdeps/unix/sysv/linux/sh/sysdep.S b/sysdeps/unix/sysv/linux/sh/sysdep.S
+index a18fbb2e8b..59421bfbb0 100644
+--- a/sysdeps/unix/sysv/linux/sh/sysdep.S
++++ b/sysdeps/unix/sysv/linux/sh/sysdep.S
+@@ -30,3 +30,14 @@ ENTRY (__syscall_error)
+ 
+ #define __syscall_error __syscall_error_1
+ #include <sysdeps/unix/sh/sysdep.S>
++
++       .data
++       .align 3
++       .globl ___fpscr_values
++       .type ___fpscr_values, @object
++       .size ___fpscr_values, 8
++___fpscr_values:
++       .long 0
++       .long 0x80000
++weak_alias (___fpscr_values, __fpscr_values)
++

+ 560 - 0
recipes-core/glibc/glibc/0022-eglibc-Forward-port-cross-locale-generation-support.patch

@@ -0,0 +1,560 @@
+From 4e5de801a39d66b8bd93d09f5912dcbe5db4ef04 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Wed, 18 Mar 2015 01:33:49 +0000
+Subject: [PATCH] eglibc: Forward port cross locale generation support
+
+Upstream-Status: Pending
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ locale/Makefile               |  3 +-
+ locale/catnames.c             | 46 +++++++++++++++++++++++++++
+ locale/localeinfo.h           |  2 +-
+ locale/programs/charmap-dir.c |  6 ++++
+ locale/programs/ld-collate.c  | 17 +++++-----
+ locale/programs/ld-ctype.c    | 27 ++++++++--------
+ locale/programs/ld-time.c     | 31 ++++++++++++------
+ locale/programs/linereader.c  |  2 +-
+ locale/programs/localedef.c   |  8 +++++
+ locale/programs/locfile.c     |  5 ++-
+ locale/programs/locfile.h     | 59 +++++++++++++++++++++++++++++++++--
+ locale/setlocale.c            | 29 -----------------
+ 12 files changed, 167 insertions(+), 68 deletions(-)
+ create mode 100644 locale/catnames.c
+
+diff --git a/locale/Makefile b/locale/Makefile
+index b7c60681fa..07c606cde3 100644
+--- a/locale/Makefile
++++ b/locale/Makefile
+@@ -26,7 +26,8 @@ headers		= langinfo.h locale.h bits/locale.h \
+ 		  bits/types/locale_t.h bits/types/__locale_t.h
+ routines	= setlocale findlocale loadlocale loadarchive \
+ 		  localeconv nl_langinfo nl_langinfo_l mb_cur_max \
+-		  newlocale duplocale freelocale uselocale
++		  newlocale duplocale freelocale uselocale \
++		  catnames
+ tests		= tst-C-locale tst-locname tst-duplocale
+ tests-container	= tst-localedef-path-norm
+ categories	= ctype messages monetary numeric time paper name \
+diff --git a/locale/catnames.c b/locale/catnames.c
+new file mode 100644
+index 0000000000..538f3f5edb
+--- /dev/null
++++ b/locale/catnames.c
+@@ -0,0 +1,46 @@
++/* Copyright (C) 2006  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, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++#include "localeinfo.h"
++
++/* Define an array of category names (also the environment variable names).  */
++const struct catnamestr_t _nl_category_names attribute_hidden =
++  {
++#define DEFINE_CATEGORY(category, category_name, items, a) \
++    category_name,
++#include "categories.def"
++#undef DEFINE_CATEGORY
++  };
++
++const uint8_t _nl_category_name_idxs[__LC_LAST] attribute_hidden =
++  {
++#define DEFINE_CATEGORY(category, category_name, items, a) \
++    [category] = offsetof (struct catnamestr_t, CATNAMEMF (__LINE__)),
++#include "categories.def"
++#undef DEFINE_CATEGORY
++  };
++
++/* An array of their lengths, for convenience.  */
++const uint8_t _nl_category_name_sizes[] attribute_hidden =
++  {
++#define DEFINE_CATEGORY(category, category_name, items, a) \
++    [category] = sizeof (category_name) - 1,
++#include "categories.def"
++#undef	DEFINE_CATEGORY
++    [LC_ALL] = sizeof ("LC_ALL") - 1
++  };
+diff --git a/locale/localeinfo.h b/locale/localeinfo.h
+index 22f9dc1140..fa31b3c5ea 100644
+--- a/locale/localeinfo.h
++++ b/locale/localeinfo.h
+@@ -230,7 +230,7 @@ __libc_tsd_define (extern, locale_t, LOCALE)
+    unused.  We can manage this playing some tricks with weak references.
+    But with thread-local locale settings, it becomes quite ungainly unless
+    we can use __thread variables.  So only in that case do we attempt this.  */
+-#ifndef SHARED
++#if !defined SHARED && !defined IN_GLIBC_LOCALEDEF
+ # include <tls.h>
+ # define NL_CURRENT_INDIRECT	1
+ #endif
+diff --git a/locale/programs/charmap-dir.c b/locale/programs/charmap-dir.c
+index 4841bfd05d..ffcba1fd79 100644
+--- a/locale/programs/charmap-dir.c
++++ b/locale/programs/charmap-dir.c
+@@ -18,7 +18,9 @@
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <libintl.h>
++#ifndef NO_UNCOMPRESS
+ #include <spawn.h>
++#endif
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -154,6 +156,7 @@ charmap_closedir (CHARMAP_DIR *cdir)
+   return closedir (dir);
+ }
+ 
++#ifndef NO_UNCOMPRESS
+ /* Creates a subprocess decompressing the given pathname, and returns
+    a stream reading its output (the decompressed data).  */
+ static
+@@ -202,6 +205,7 @@ fopen_uncompressed (const char *pathname, const char *compressor)
+     }
+   return NULL;
+ }
++#endif
+ 
+ /* Opens a charmap for reading, given its name (not an alias name).  */
+ FILE *
+@@ -224,6 +228,7 @@ charmap_open (const char *directory, const char *name)
+   if (stream != NULL)
+     return stream;
+ 
++#ifndef NO_UNCOMPRESS
+   memcpy (p, ".gz", 4);
+   stream = fopen_uncompressed (pathname, "gzip");
+   if (stream != NULL)
+@@ -233,6 +238,7 @@ charmap_open (const char *directory, const char *name)
+   stream = fopen_uncompressed (pathname, "bzip2");
+   if (stream != NULL)
+     return stream;
++#endif
+ 
+   return NULL;
+ }
+diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c
+index b6406b775d..bfa4adba9c 100644
+--- a/locale/programs/ld-collate.c
++++ b/locale/programs/ld-collate.c
+@@ -349,7 +349,7 @@ new_element (struct locale_collate_t *collate, const char *mbs, size_t mbslen,
+     }
+   if (wcs != NULL)
+     {
+-      size_t nwcs = wcslen ((wchar_t *) wcs);
++      size_t nwcs = wcslen_uint32 (wcs);
+       uint32_t zero = 0;
+       /* Handle <U0000> as a single character.  */
+       if (nwcs == 0)
+@@ -1775,8 +1775,7 @@ symbol `%s' has the same encoding as"), (*eptr)->name);
+ 
+ 	      if ((*eptr)->nwcs == runp->nwcs)
+ 		{
+-		  int c = wmemcmp ((wchar_t *) (*eptr)->wcs,
+-				   (wchar_t *) runp->wcs, runp->nwcs);
++		  int c = wmemcmp_uint32 ((*eptr)->wcs, runp->wcs, runp->nwcs);
+ 
+ 		  if (c == 0)
+ 		    {
+@@ -2003,9 +2002,9 @@ add_to_tablewc (uint32_t ch, struct element_t *runp)
+ 	     one consecutive entry.  */
+ 	  if (runp->wcnext != NULL
+ 	      && runp->nwcs == runp->wcnext->nwcs
+-	      && wmemcmp ((wchar_t *) runp->wcs,
+-			  (wchar_t *)runp->wcnext->wcs,
+-			  runp->nwcs - 1) == 0
++	      && wmemcmp_uint32 (runp->wcs,
++				 runp->wcnext->wcs,
++				 runp->nwcs - 1) == 0
+ 	      && (runp->wcs[runp->nwcs - 1]
+ 		  == runp->wcnext->wcs[runp->nwcs - 1] + 1))
+ 	    {
+@@ -2029,9 +2028,9 @@ add_to_tablewc (uint32_t ch, struct element_t *runp)
+ 		runp = runp->wcnext;
+ 	      while (runp->wcnext != NULL
+ 		     && runp->nwcs == runp->wcnext->nwcs
+-		     && wmemcmp ((wchar_t *) runp->wcs,
+-				 (wchar_t *)runp->wcnext->wcs,
+-				 runp->nwcs - 1) == 0
++		     && wmemcmp_uint32 (runp->wcs,
++					runp->wcnext->wcs,
++					runp->nwcs - 1) == 0
+ 		     && (runp->wcs[runp->nwcs - 1]
+ 			 == runp->wcnext->wcs[runp->nwcs - 1] + 1));
+ 
+diff --git a/locale/programs/ld-ctype.c b/locale/programs/ld-ctype.c
+index 2fb579bbbf..d0be99581c 100644
+--- a/locale/programs/ld-ctype.c
++++ b/locale/programs/ld-ctype.c
+@@ -915,7 +915,7 @@ ctype_output (struct localedef_t *locale, const struct charmap_t *charmap,
+   allocate_arrays (ctype, charmap, ctype->repertoire);
+ 
+   default_missing_len = (ctype->default_missing
+-			 ? wcslen ((wchar_t *) ctype->default_missing)
++			 ? wcslen_uint32 (ctype->default_missing)
+ 			 : 0);
+ 
+   init_locale_data (&file, nelems);
+@@ -1927,7 +1927,7 @@ read_translit_entry (struct linereader *ldfile, struct locale_ctype_t *ctype,
+ 	    ignore = 1;
+ 	  else
+ 	    /* This value is usable.  */
+-	    obstack_grow (ob, to_wstr, wcslen ((wchar_t *) to_wstr) * 4);
++	    obstack_grow (ob, to_wstr, wcslen_uint32 (to_wstr) * 4);
+ 
+ 	  first = 0;
+ 	}
+@@ -2461,8 +2461,8 @@ with character code range values one must use the absolute ellipsis `...'"));
+ 	    }
+ 
+ 	handle_tok_digit:
+-	  class_bit = _ISwdigit;
+-	  class256_bit = _ISdigit;
++	  class_bit = BITw (tok_digit);
++	  class256_bit = BIT (tok_digit);
+ 	  handle_digits = 1;
+ 	  goto read_charclass;
+ 
+@@ -3904,8 +3904,7 @@ allocate_arrays (struct locale_ctype_t *ctype, const struct charmap_t *charmap,
+ 
+ 	  while (idx < number)
+ 	    {
+-	      int res = wcscmp ((const wchar_t *) sorted[idx]->from,
+-				(const wchar_t *) runp->from);
++	      int res = wcscmp_uint32 (sorted[idx]->from, runp->from);
+ 	      if (res == 0)
+ 		{
+ 		  replace = 1;
+@@ -3942,11 +3941,11 @@ allocate_arrays (struct locale_ctype_t *ctype, const struct charmap_t *charmap,
+       for (size_t cnt = 0; cnt < number; ++cnt)
+ 	{
+ 	  struct translit_to_t *srunp;
+-	  from_len += wcslen ((const wchar_t *) sorted[cnt]->from) + 1;
++	  from_len += wcslen_uint32 (sorted[cnt]->from) + 1;
+ 	  srunp = sorted[cnt]->to;
+ 	  while (srunp != NULL)
+ 	    {
+-	      to_len += wcslen ((const wchar_t *) srunp->str) + 1;
++	      to_len += wcslen_uint32 (srunp->str) + 1;
+ 	      srunp = srunp->next;
+ 	    }
+ 	  /* Plus one for the extra NUL character marking the end of
+@@ -3970,18 +3969,18 @@ allocate_arrays (struct locale_ctype_t *ctype, const struct charmap_t *charmap,
+ 	  ctype->translit_from_idx[cnt] = from_len;
+ 	  ctype->translit_to_idx[cnt] = to_len;
+ 
+-	  len = wcslen ((const wchar_t *) sorted[cnt]->from) + 1;
+-	  wmemcpy ((wchar_t *) &ctype->translit_from_tbl[from_len],
+-		   (const wchar_t *) sorted[cnt]->from, len);
++	  len = wcslen_uint32 (sorted[cnt]->from) + 1;
++	  wmemcpy_uint32 (&ctype->translit_from_tbl[from_len],
++			  sorted[cnt]->from, len);
+ 	  from_len += len;
+ 
+ 	  ctype->translit_to_idx[cnt] = to_len;
+ 	  srunp = sorted[cnt]->to;
+ 	  while (srunp != NULL)
+ 	    {
+-	      len = wcslen ((const wchar_t *) srunp->str) + 1;
+-	      wmemcpy ((wchar_t *) &ctype->translit_to_tbl[to_len],
+-		       (const wchar_t *) srunp->str, len);
++	      len = wcslen_uint32 (srunp->str) + 1;
++	      wmemcpy_uint32 (&ctype->translit_to_tbl[to_len],
++			      srunp->str, len);
+ 	      to_len += len;
+ 	      srunp = srunp->next;
+ 	    }
+diff --git a/locale/programs/ld-time.c b/locale/programs/ld-time.c
+index dcd2a2386d..6814740325 100644
+--- a/locale/programs/ld-time.c
++++ b/locale/programs/ld-time.c
+@@ -220,8 +220,10 @@ No definition for %s category found"), "LC_TIME");
+ 	}
+       else
+ 	{
++	  static const uint32_t wt_fmt_ampm[]
++	    = { '%','I',':','%','M',':','%','S',' ','%','p',0 };
+ 	  time->t_fmt_ampm = "%I:%M:%S %p";
+-	  time->wt_fmt_ampm = (const uint32_t *) L"%I:%M:%S %p";
++	  time->wt_fmt_ampm = wt_fmt_ampm;
+ 	}
+     }
+ 
+@@ -231,7 +233,7 @@ No definition for %s category found"), "LC_TIME");
+       const int days_per_month[12] = { 31, 29, 31, 30, 31, 30,
+ 				       31, 31, 30, 31 ,30, 31 };
+       size_t idx;
+-      wchar_t *wstr;
++      uint32_t *wstr;
+ 
+       time->era_entries =
+ 	(struct era_data *) xmalloc (time->num_era
+@@ -457,18 +459,18 @@ No definition for %s category found"), "LC_TIME");
+ 	    }
+ 
+ 	  /* Now generate the wide character name and format.  */
+-	  wstr = wcschr ((wchar_t *) time->wera[idx], L':');/* end direction */
+-	  wstr = wstr ? wcschr (wstr + 1, L':') : NULL;	/* end offset */
+-	  wstr = wstr ? wcschr (wstr + 1, L':') : NULL;	/* end start */
+-	  wstr = wstr ? wcschr (wstr + 1, L':') : NULL;	/* end end */
++	  wstr = wcschr_uint32 (time->wera[idx], L':'); /* end direction */
++	  wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end offset */
++	  wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end start */
++	  wstr = wstr ? wcschr_uint32 (wstr + 1, L':') : NULL; /* end end */
+ 	  if (wstr != NULL)
+ 	    {
+-	      time->era_entries[idx].wname = (uint32_t *) wstr + 1;
+-	      wstr = wcschr (wstr + 1, L':');	/* end name */
++	      time->era_entries[idx].wname = wstr + 1;
++	      wstr = wcschr_uint32 (wstr + 1, L':'); /* end name */
+ 	      if (wstr != NULL)
+ 		{
+ 		  *wstr = L'\0';
+-		  time->era_entries[idx].wformat = (uint32_t *) wstr + 1;
++		  time->era_entries[idx].wformat = wstr + 1;
+ 		}
+ 	      else
+ 		time->era_entries[idx].wname =
+@@ -527,7 +529,16 @@ No definition for %s category found"), "LC_TIME");
+   if (time->date_fmt == NULL)
+     time->date_fmt = "%a %b %e %H:%M:%S %Z %Y";
+   if (time->wdate_fmt == NULL)
+-    time->wdate_fmt = (const uint32_t *) L"%a %b %e %H:%M:%S %Z %Y";
++    {
++      static const uint32_t wdate_fmt[] =
++	{ '%','a',' ',
++	  '%','b',' ',
++	  '%','e',' ',
++	  '%','H',':','%','M',':','%','S',' ',
++	  '%','Z',' ',
++	  '%','Y',0 };
++      time->wdate_fmt = wdate_fmt;
++    }
+ }
+ 
+ 
+diff --git a/locale/programs/linereader.c b/locale/programs/linereader.c
+index 96d3ab66db..3af379d2c3 100644
+--- a/locale/programs/linereader.c
++++ b/locale/programs/linereader.c
+@@ -595,7 +595,7 @@ get_string (struct linereader *lr, const struct charmap_t *charmap,
+ {
+   int return_widestr = lr->return_widestr;
+   char *buf;
+-  wchar_t *buf2 = NULL;
++  uint32_t *buf2 = NULL;
+   size_t bufact;
+   size_t bufmax = 56;
+ 
+diff --git a/locale/programs/localedef.c b/locale/programs/localedef.c
+index 832c8fd1fc..fe689b3ae1 100644
+--- a/locale/programs/localedef.c
++++ b/locale/programs/localedef.c
+@@ -109,6 +109,7 @@ void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+ #define OPT_NO_WARN 402
+ #define OPT_WARN 403
+ #define OPT_NO_HARD_LINKS 404
++#define OPT_UINT32_ALIGN 405
+ 
+ /* Definitions of arguments for argp functions.  */
+ static const struct argp_option options[] =
+@@ -153,6 +154,8 @@ static const struct argp_option options[] =
+     N_("Generate little-endian output") },
+   { "big-endian", OPT_BIG_ENDIAN, NULL, 0,
+     N_("Generate big-endian output") },
++  { "uint32-align", OPT_UINT32_ALIGN, "ALIGNMENT", 0,
++    N_("Set the target's uint32_t alignment in bytes (default 4)") },
+   { NULL, 0, NULL, 0, NULL }
+ };
+ 
+@@ -243,12 +246,14 @@ main (int argc, char *argv[])
+      ctype locale.  (P1003.2 4.35.5.2)  */
+   setlocale (LC_CTYPE, "POSIX");
+ 
++#ifndef NO_SYSCONF
+   /* Look whether the system really allows locale definitions.  POSIX
+      defines error code 3 for this situation so I think it must be
+      a fatal error (see P1003.2 4.35.8).  */
+   if (sysconf (_SC_2_LOCALEDEF) < 0)
+     record_error (3, 0, _("\
+ FATAL: system does not define `_POSIX2_LOCALEDEF'"));
++#endif
+ 
+   /* Process charmap file.  */
+   charmap = charmap_read (charmap_file, verbose, 1, be_quiet, 1);
+@@ -400,6 +405,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
+       /* Do not hard link to other locales.  */
+       hard_links = false;
+       break;
++    case OPT_UINT32_ALIGN:
++      uint32_align_mask = strtol (arg, NULL, 0) - 1;
++      break;
+     case 'c':
+       force_output = 1;
+       break;
+diff --git a/locale/programs/locfile.c b/locale/programs/locfile.c
+index 0f1affa1d4..7d86fae801 100644
+--- a/locale/programs/locfile.c
++++ b/locale/programs/locfile.c
+@@ -544,6 +544,9 @@ compare_files (const char *filename1, const char *filename2, size_t size,
+    machine running localedef.  */
+ bool swap_endianness_p;
+ 
++/* The target's value of __align__(uint32_t) - 1.  */
++unsigned int uint32_align_mask = 3;
++
+ /* When called outside a start_locale_structure/end_locale_structure
+    or start_locale_prelude/end_locale_prelude block, record that the
+    next byte in FILE's obstack will be the first byte of a new element.
+@@ -621,7 +624,7 @@ add_locale_string (struct locale_file *file, const char *string)
+ void
+ add_locale_wstring (struct locale_file *file, const uint32_t *string)
+ {
+-  add_locale_uint32_array (file, string, wcslen ((const wchar_t *) string) + 1);
++  add_locale_uint32_array (file, string, wcslen_uint32 (string) + 1);
+ }
+ 
+ /* Record that FILE's next element is the 32-bit integer VALUE.  */
+diff --git a/locale/programs/locfile.h b/locale/programs/locfile.h
+index c986d599ec..222a779176 100644
+--- a/locale/programs/locfile.h
++++ b/locale/programs/locfile.h
+@@ -71,6 +71,8 @@ extern void write_all_categories (struct localedef_t *definitions,
+ 
+ extern bool swap_endianness_p;
+ 
++extern unsigned int uint32_align_mask;
++
+ /* Change the output to be big-endian if BIG_ENDIAN is true and
+    little-endian otherwise.  */
+ static inline void
+@@ -89,7 +91,8 @@ maybe_swap_uint32 (uint32_t value)
+ }
+ 
+ /* Likewise, but munge an array of N uint32_ts starting at ARRAY.  */
+-static inline void
++static void
++__attribute__ ((unused))
+ maybe_swap_uint32_array (uint32_t *array, size_t n)
+ {
+   if (swap_endianness_p)
+@@ -99,7 +102,8 @@ maybe_swap_uint32_array (uint32_t *array, size_t n)
+ 
+ /* Like maybe_swap_uint32_array, but the array of N elements is at
+    the end of OBSTACK's current object.  */
+-static inline void
++static void
++__attribute__ ((unused))
+ maybe_swap_uint32_obstack (struct obstack *obstack, size_t n)
+ {
+   maybe_swap_uint32_array ((uint32_t *) obstack_next_free (obstack) - n, n);
+@@ -276,4 +280,55 @@ extern void identification_output (struct localedef_t *locale,
+ 				   const struct charmap_t *charmap,
+ 				   const char *output_path);
+ 
++static size_t wcslen_uint32 (const uint32_t *str) __attribute__ ((unused));
++static uint32_t * wmemcpy_uint32 (uint32_t *s1, const uint32_t *s2, size_t n) __attribute__ ((unused));
++static uint32_t * wcschr_uint32 (const uint32_t *s, uint32_t ch) __attribute__ ((unused));
++static int wcscmp_uint32 (const uint32_t *s1, const uint32_t *s2) __attribute__ ((unused));
++static int wmemcmp_uint32 (const uint32_t *s1, const uint32_t *s2, size_t n) __attribute__ ((unused));
++
++static size_t
++wcslen_uint32 (const uint32_t *str)
++{
++  size_t len = 0;
++  while (str[len] != 0)
++    len++;
++  return len;
++}
++
++static  int
++wmemcmp_uint32 (const uint32_t *s1, const uint32_t *s2, size_t n)
++{
++  while (n-- != 0)
++    {
++      int diff = *s1++ - *s2++;
++      if (diff != 0)
++	return diff;
++    }
++  return 0;
++}
++
++static int
++wcscmp_uint32 (const uint32_t *s1, const uint32_t *s2)
++{
++  while (*s1 != 0 && *s1 == *s2)
++    s1++, s2++;
++  return *s1 - *s2;
++}
++
++static uint32_t *
++wmemcpy_uint32 (uint32_t *s1, const uint32_t *s2, size_t n)
++{
++  return memcpy (s1, s2, n * sizeof (uint32_t));
++}
++
++static uint32_t *
++wcschr_uint32 (const uint32_t *s, uint32_t ch)
++{
++  do
++    if (*s == ch)
++      return (uint32_t *) s;
++  while (*s++ != 0);
++  return 0;
++}
++
+ #endif /* locfile.h */
+diff --git a/locale/setlocale.c b/locale/setlocale.c
+index 19ed85ae8e..f28ca11446 100644
+--- a/locale/setlocale.c
++++ b/locale/setlocale.c
+@@ -63,35 +63,6 @@ static char *const _nl_current_used[] =
+ 
+ #endif
+ 
+-
+-/* Define an array of category names (also the environment variable names).  */
+-const struct catnamestr_t _nl_category_names attribute_hidden =
+-  {
+-#define DEFINE_CATEGORY(category, category_name, items, a) \
+-    category_name,
+-#include "categories.def"
+-#undef DEFINE_CATEGORY
+-  };
+-
+-const uint8_t _nl_category_name_idxs[__LC_LAST] attribute_hidden =
+-  {
+-#define DEFINE_CATEGORY(category, category_name, items, a) \
+-    [category] = offsetof (struct catnamestr_t, CATNAMEMF (__LINE__)),
+-#include "categories.def"
+-#undef DEFINE_CATEGORY
+-  };
+-
+-/* An array of their lengths, for convenience.  */
+-const uint8_t _nl_category_name_sizes[] attribute_hidden =
+-  {
+-#define DEFINE_CATEGORY(category, category_name, items, a) \
+-    [category] = sizeof (category_name) - 1,
+-#include "categories.def"
+-#undef	DEFINE_CATEGORY
+-    [LC_ALL] = sizeof ("LC_ALL") - 1
+-  };
+-
+-
+ #ifdef NL_CURRENT_INDIRECT
+ # define WEAK_POSTLOAD(postload) weak_extern (postload)
+ #else

+ 80 - 0
recipes-core/glibc/glibc/0024-localedef-add-to-archive-uses-a-hard-coded-locale-pa.patch

@@ -0,0 +1,80 @@
+From 13bc0e53cc91e102472d532f28b3d44c30d291fc Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Fri, 3 Aug 2018 09:42:06 -0700
+Subject: [PATCH] localedef --add-to-archive uses a hard-coded locale path
+
+it doesn't exist in normal use, and there's no way to pass an
+alternative filename.
+
+Add a fallback of $LOCALEARCHIVE from the environment, and allow
+creation of new locale archives that are not the system archive.
+
+Upstream-Status: Inappropriate (OE-specific)
+
+Signed-off-by: Ross Burton <ross.burton@intel.com>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ locale/programs/locarchive.c | 35 +++++++++++++++++++++++++----------
+ 1 file changed, 25 insertions(+), 10 deletions(-)
+
+diff --git a/locale/programs/locarchive.c b/locale/programs/locarchive.c
+index f38e835c52..8d8f8699b2 100644
+--- a/locale/programs/locarchive.c
++++ b/locale/programs/locarchive.c
+@@ -340,12 +340,24 @@ enlarge_archive (struct locarhandle *ah, const struct locarhead *head)
+   struct namehashent *oldnamehashtab;
+   struct locarhandle new_ah;
+   size_t prefix_len = output_prefix ? strlen (output_prefix) : 0;
+-  char archivefname[prefix_len + sizeof (ARCHIVE_NAME)];
+-  char fname[prefix_len + sizeof (ARCHIVE_NAME) + sizeof (".XXXXXX") - 1];
++  char *archivefname;
++  char *fname;
++  char *envarchive = getenv("LOCALEARCHIVE");
+ 
+-  if (output_prefix)
+-    memcpy (archivefname, output_prefix, prefix_len);
+-  strcpy (archivefname + prefix_len, ARCHIVE_NAME);
++  if (envarchive != NULL)
++    {
++      archivefname = xmalloc(strlen(envarchive) + 1);
++      fname = xmalloc(strlen(envarchive) + sizeof (".XXXXXX"));
++      strcpy (archivefname, envarchive);
++    }
++  else
++    {
++      archivefname = xmalloc(prefix_len + sizeof (ARCHIVE_NAME));
++      fname = xmalloc(prefix_len + sizeof (ARCHIVE_NAME) + sizeof (".XXXXXX") - 1);
++      if (output_prefix)
++        memcpy (archivefname, output_prefix, prefix_len);
++      strcpy (archivefname + prefix_len, ARCHIVE_NAME);
++    }
+   strcpy (stpcpy (fname, archivefname), ".XXXXXX");
+ 
+   /* Not all of the old file has to be mapped.  Change this now this
+@@ -569,10 +581,13 @@ open_archive (struct locarhandle *ah, bool readonly)
+   /* If ah has a non-NULL fname open that otherwise open the default.  */
+   if (archivefname == NULL)
+     {
+-      archivefname = default_fname;
+-      if (output_prefix)
+-        memcpy (default_fname, output_prefix, prefix_len);
+-      strcpy (default_fname + prefix_len, ARCHIVE_NAME);
++      archivefname = getenv("LOCALEARCHIVE");
++      if (archivefname == NULL) {
++              archivefname = default_fname;
++              if (output_prefix)
++                memcpy (default_fname, output_prefix, prefix_len);
++              strcpy (default_fname + prefix_len, ARCHIVE_NAME);
++      }
+     }
+ 
+   while (1)
+@@ -585,7 +600,7 @@ open_archive (struct locarhandle *ah, bool readonly)
+ 	     the default locale archive we ignore the failure and
+ 	     list an empty archive, otherwise we print an error
+ 	     and exit.  */
+-	  if (errno == ENOENT && archivefname == default_fname)
++	  if (errno == ENOENT)
+ 	    {
+ 	      if (readonly)
+ 		{

+ 53 - 0
recipes-core/glibc/glibc/0025-elf-dl-deps.c-Make-_dl_build_local_scope-breadth-fir.patch

@@ -0,0 +1,53 @@
+From 50b605dece16606dd9d1c737e579c13725eab11d Mon Sep 17 00:00:00 2001
+From: Mark Hatle <mark.hatle@windriver.com>
+Date: Thu, 18 Aug 2016 14:07:58 -0500
+Subject: [PATCH] elf/dl-deps.c: Make _dl_build_local_scope breadth first
+
+According to the ELF specification:
+
+When resolving symbolic references, the dynamic linker examines the symbol
+tables with a breadth-first search.
+
+This function was using a depth first search.  By doing so the conflict
+resolution reported to the prelinker (when LD_TRACE_PRELINKING=1 is set)
+was incorrect.  This caused problems when their were various circular
+dependencies between libraries.  The problem usually manifested itself by
+the wrong IFUNC being executed.
+
+[BZ# 20488]
+
+Upstream-Status: Submitted [libc-alpha]
+
+Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
+---
+ elf/dl-deps.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/elf/dl-deps.c b/elf/dl-deps.c
+index 087a49b212..c09f9334f2 100644
+--- a/elf/dl-deps.c
++++ b/elf/dl-deps.c
+@@ -73,13 +73,19 @@ _dl_build_local_scope (struct link_map **list, struct link_map *map)
+ {
+   struct link_map **p = list;
+   struct link_map **q;
++  struct link_map **r;
+ 
+   *p++ = map;
+   map->l_reserved = 1;
+-  if (map->l_initfini)
+-    for (q = map->l_initfini + 1; *q; ++q)
+-      if (! (*q)->l_reserved)
+-	p += _dl_build_local_scope (p, *q);
++
++  for (r = list; r < p; ++r)
++    if ((*r)->l_initfini)
++      for (q = (*r)->l_initfini + 1; *q; ++q)
++	if (! (*q)->l_reserved)
++	  {
++	    *p++ = *q;
++	    (*q)->l_reserved = 1;
++	  }
+   return p - list;
+ }
+ 

+ 31 - 0
recipes-core/glibc/glibc/0026-intl-Emit-no-lines-in-bison-generated-files.patch

@@ -0,0 +1,31 @@
+From 99ab34278a6ebec134267412b4f619f43e278dea Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Fri, 3 Aug 2018 09:44:00 -0700
+Subject: [PATCH] intl: Emit no lines in bison generated files
+
+Improve reproducibility:
+Do not put any #line preprocessor commands in bison generated files.
+These lines contain absolute paths containing file locations on
+the host build machine.
+
+Upstream-Status: Pending
+
+Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ intl/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/intl/Makefile b/intl/Makefile
+index 93478d87e8..b27a7935eb 100644
+--- a/intl/Makefile
++++ b/intl/Makefile
+@@ -155,7 +155,7 @@ $(objpfx)tst-gettext6.out: $(objpfx)tst-gettext.out
+ 
+ CPPFLAGS += -D'LOCALEDIR="$(localedir)"' \
+ 	    -D'LOCALE_ALIAS_PATH="$(localedir)"'
+-BISONFLAGS = --yacc --name-prefix=__gettext --output
++BISONFLAGS = --yacc --no-lines --name-prefix=__gettext --output
+ 
+ $(inst_localedir)/locale.alias: locale.alias $(+force)
+ 	$(do-install)

+ 53 - 0
recipes-core/glibc/glibc/0027-locale-prevent-maybe-uninitialized-errors-with-Os-BZ.patch

@@ -0,0 +1,53 @@
+From 3190ada9ecaec915794886a608221655c120f90c Mon Sep 17 00:00:00 2001
+From: Martin Jansa <martin.jansa@gmail.com>
+Date: Mon, 17 Dec 2018 21:36:18 +0000
+Subject: [PATCH] locale: prevent maybe-uninitialized errors with -Os [BZ
+ #19444]
+
+Fixes following error when building for aarch64 with -Os:
+| In file included from strcoll_l.c:43:
+| strcoll_l.c: In function '__strcoll_l':
+| ../locale/weight.h:31:26: error: 'seq2.back_us' may be used uninitialized in this function [-Werror=maybe-uninitialized]
+|    int_fast32_t i = table[*(*cpp)++];
+|                           ^~~~~~~~~
+| strcoll_l.c:304:18: note: 'seq2.back_us' was declared here
+|    coll_seq seq1, seq2;
+|                   ^~~~
+| In file included from strcoll_l.c:43:
+| ../locale/weight.h:31:26: error: 'seq1.back_us' may be used uninitialized in this function [-Werror=maybe-uninitialized]
+|    int_fast32_t i = table[*(*cpp)++];
+|                           ^~~~~~~~~
+| strcoll_l.c:304:12: note: 'seq1.back_us' was declared here
+|    coll_seq seq1, seq2;
+|             ^~~~
+
+        Partial fix for [BZ #19444]
+        * locale/weight.h: Fix build with -Os.
+
+Upstream-Status: Submitted [https://patchwork.ozlabs.org/patch/1014766]
+
+Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ locale/weight.h | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/locale/weight.h b/locale/weight.h
+index 723e1fefda..f5798d379a 100644
+--- a/locale/weight.h
++++ b/locale/weight.h
+@@ -28,7 +28,14 @@ findidx (const int32_t *table,
+ 	 const unsigned char *extra,
+ 	 const unsigned char **cpp, size_t len)
+ {
++  /* With GCC 8 when compiling with -Os the compiler warns that
++     seq1.back_us and seq2.back_us might be used uninitialized.
++     This uninitialized use is impossible for the same reason
++     as described in comments in locale/weightwc.h.  */
++  DIAG_PUSH_NEEDS_COMMENT;
++  DIAG_IGNORE_Os_NEEDS_COMMENT (8, "-Wmaybe-uninitialized");
+   int_fast32_t i = table[*(*cpp)++];
++  DIAG_POP_NEEDS_COMMENT;
+   const unsigned char *cp;
+   const unsigned char *usrc;
+ 

+ 29 - 0
recipes-core/glibc/glibc/0028-readlib-Add-OECORE_KNOWN_INTERPRETER_NAMES-to-known-.patch

@@ -0,0 +1,29 @@
+From 5d201a75918a0e181ee6206f701901fdb91baf81 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Wed, 18 Mar 2015 00:11:22 +0000
+Subject: [PATCH] readlib: Add OECORE_KNOWN_INTERPRETER_NAMES to known names
+
+This bolts in a hook for OE to pass its own version of interpreter
+names into glibc especially for multilib case, where it differs from any
+other distros
+
+Upstream-Status: Inappropriate [OE specific]
+
+Signed-off-by: Lianhao Lu <lianhao.lu@intel.com>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ elf/readlib.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/elf/readlib.c b/elf/readlib.c
+index 7383c23249..e97ea9449d 100644
+--- a/elf/readlib.c
++++ b/elf/readlib.c
+@@ -51,6 +51,7 @@ static struct known_names interpreters[] =
+ #ifdef SYSDEP_KNOWN_INTERPRETER_NAMES
+   SYSDEP_KNOWN_INTERPRETER_NAMES
+ #endif
++  OECORE_KNOWN_INTERPRETER_NAMES
+ };
+ 
+ static struct known_names known_libs[] =

+ 67 - 0
recipes-core/glibc/glibc/0029-wordsize.h-Unify-the-header-between-arm-and-aarch64.patch

@@ -0,0 +1,67 @@
+From baba3c6021340a9070b734f931a15cea4cfe6c31 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Fri, 15 May 2020 17:05:45 -0700
+Subject: [PATCH] wordsize.h: Unify the header between arm and aarch64
+
+This helps OE multilibs to not sythesize this header which causes all
+kind of recursions and other issues since wordsize is fundamental header
+and ends up including itself in many case e.g. clang tidy, bpf etc.
+
+Upstream-Status: Inappropriate [ OE-Specific ]
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ sysdeps/aarch64/bits/wordsize.h          |  8 ++++++--
+ sysdeps/{aarch64 => arm}/bits/wordsize.h | 10 +++++++---
+ 2 files changed, 13 insertions(+), 5 deletions(-)
+ copy sysdeps/{aarch64 => arm}/bits/wordsize.h (80%)
+
+diff --git a/sysdeps/aarch64/bits/wordsize.h b/sysdeps/aarch64/bits/wordsize.h
+index 91da566b74..9a754514b3 100644
+--- a/sysdeps/aarch64/bits/wordsize.h
++++ b/sysdeps/aarch64/bits/wordsize.h
+@@ -17,12 +17,16 @@
+    License along with the GNU C Library; if not, see
+    <https://www.gnu.org/licenses/>.  */
+ 
+-#ifdef __LP64__
++#if defined (__aarch64__) && defined (__LP64__)
+ # define __WORDSIZE			64
+-#else
++#elif defined (__aarch64__)
+ # define __WORDSIZE			32
+ # define __WORDSIZE32_SIZE_ULONG	1
+ # define __WORDSIZE32_PTRDIFF_LONG	1
++#else
++# define __WORDSIZE			32
++# define __WORDSIZE32_SIZE_ULONG	0
++# define __WORDSIZE32_PTRDIFF_LONG	0
+ #endif
+ 
+ #define __WORDSIZE_TIME64_COMPAT32	0
+diff --git a/sysdeps/aarch64/bits/wordsize.h b/sysdeps/arm/bits/wordsize.h
+similarity index 80%
+copy from sysdeps/aarch64/bits/wordsize.h
+copy to sysdeps/arm/bits/wordsize.h
+index 91da566b74..34fcdef1f1 100644
+--- a/sysdeps/aarch64/bits/wordsize.h
++++ b/sysdeps/arm/bits/wordsize.h
+@@ -17,12 +17,16 @@
+    License along with the GNU C Library; if not, see
+    <https://www.gnu.org/licenses/>.  */
+ 
+-#ifdef __LP64__
++#if defined (__aarch64__) && defined (__LP64__)
+ # define __WORDSIZE			64
+-#else
++#elif defined (__aarch64__)
+ # define __WORDSIZE			32
+ # define __WORDSIZE32_SIZE_ULONG	1
+ # define __WORDSIZE32_PTRDIFF_LONG	1
++#else
++# define __WORDSIZE			32
++# define __WORDSIZE32_SIZE_ULONG	0
++# define __WORDSIZE32_PTRDIFF_LONG	0
+ #endif
+ 
+ #define __WORDSIZE_TIME64_COMPAT32	0

+ 48 - 0
recipes-core/glibc/glibc/0030-powerpc-Do-not-ask-compiler-for-finding-arch.patch

@@ -0,0 +1,48 @@
+From 60aa53f547911163b42a1c436d695a15c87f34ee Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Fri, 7 Aug 2020 14:31:16 -0700
+Subject: [PATCH] powerpc: Do not ask compiler for finding arch
+
+This does not work well in cross compiling environments like OE
+and moreover it uses its own -mcpu/-march options via cflags
+
+Upstream-Status: Inappropriate [ OE-Specific]
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ sysdeps/powerpc/preconfigure    | 5 +----
+ sysdeps/powerpc/preconfigure.ac | 5 +----
+ 2 files changed, 2 insertions(+), 8 deletions(-)
+
+diff --git a/sysdeps/powerpc/preconfigure b/sysdeps/powerpc/preconfigure
+index dfe8e20399..bbff040f0f 100644
+--- a/sysdeps/powerpc/preconfigure
++++ b/sysdeps/powerpc/preconfigure
+@@ -29,10 +29,7 @@ esac
+ # directive which shows up, and try using it.
+ case "${machine}:${submachine}" in
+ *powerpc*:)
+-  archcpu=`echo "int foo () { return 0; }" \
+-	   | $CC $CFLAGS $CPPFLAGS -S -frecord-gcc-switches -xc -o - - \
+-	   | grep -E "mcpu=|.machine" -m 1 \
+-	   | sed -e "s/.*machine //" -e "s/.*mcpu=\(.*\)\"/\1/"`
++  archcpu=''
+   # Note if you add patterns here you must ensure that an appropriate
+   # directory exists in sysdeps/powerpc.  Likewise, if we find a
+   # cpu, don't let the generic configure append extra compiler options.
+diff --git a/sysdeps/powerpc/preconfigure.ac b/sysdeps/powerpc/preconfigure.ac
+index 6c63bd8257..3e925f1d48 100644
+--- a/sysdeps/powerpc/preconfigure.ac
++++ b/sysdeps/powerpc/preconfigure.ac
+@@ -29,10 +29,7 @@ esac
+ # directive which shows up, and try using it.
+ case "${machine}:${submachine}" in
+ *powerpc*:)
+-  archcpu=`echo "int foo () { return 0; }" \
+-	   | $CC $CFLAGS $CPPFLAGS -S -frecord-gcc-switches -xc -o - - \
+-	   | grep -E "mcpu=|[.]machine" -m 1 \
+-	   | sed -e "s/.*machine //" -e "s/.*mcpu=\(.*\)\"/\1/"`
++  archcpu=''
+   # Note if you add patterns here you must ensure that an appropriate
+   # directory exists in sysdeps/powerpc.  Likewise, if we find a
+   # cpu, don't let the generic configure append extra compiler options.

+ 184 - 0
recipes-core/glibc/glibc/CVE-2021-43396.patch

@@ -0,0 +1,184 @@
+From ff012870b2c02a62598c04daa1e54632e020fd7d Mon Sep 17 00:00:00 2001
+From: Nikita Popov <npv1310@gmail.com>
+Date: Tue, 2 Nov 2021 13:21:42 +0500
+Subject: [PATCH] gconv: Do not emit spurious NUL character in ISO-2022-JP-3
+ (bug 28524)
+
+Bugfix 27256 has introduced another issue:
+In conversion from ISO-2022-JP-3 encoding, it is possible
+to force iconv to emit extra NUL character on internal state reset.
+To do this, it is sufficient to feed iconv with escape sequence
+which switches active character set.
+The simplified check 'data->__statep->__count != ASCII_set'
+introduced by the aforementioned bugfix picks that case and
+behaves as if '\0' character has been queued thus emitting it.
+
+To eliminate this issue, these steps are taken:
+* Restore original condition
+'(data->__statep->__count & ~7) != ASCII_set'.
+It is necessary since bits 0-2 may contain
+number of buffered input characters.
+* Check that queued character is not NUL.
+Similar step is taken for main conversion loop.
+
+Bundled test case follows following logic:
+* Try to convert ISO-2022-JP-3 escape sequence
+switching active character set
+* Reset internal state by providing NULL as input buffer
+* Ensure that nothing has been converted.
+
+Signed-off-by: Nikita Popov <npv1310@gmail.com>
+
+CVE: CVE-2021-43396
+Upstream-Status: Backport [ff012870b2c02a62598c04daa1e54632e020fd7d]
+---
+ iconvdata/Makefile        |  5 +++-
+ iconvdata/bug-iconv15.c   | 60 +++++++++++++++++++++++++++++++++++++++
+ iconvdata/iso-2022-jp-3.c | 28 ++++++++++++------
+ 3 files changed, 84 insertions(+), 9 deletions(-)
+ create mode 100644 iconvdata/bug-iconv15.c
+
+Index: git/iconvdata/Makefile
+===================================================================
+--- git.orig/iconvdata/Makefile
++++ git/iconvdata/Makefile
+@@ -1,4 +1,5 @@
+ # Copyright (C) 1997-2021 Free Software Foundation, Inc.
++# Copyright (C) The GNU Toolchain Authors.
+ # This file is part of the GNU C Library.
+ 
+ # The GNU C Library is free software; you can redistribute it and/or
+@@ -74,7 +75,7 @@ ifeq (yes,$(build-shared))
+ tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
+ 	tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \
+ 	bug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 \
+-	bug-iconv13 bug-iconv14
++	bug-iconv13 bug-iconv14 bug-iconv15
+ ifeq ($(have-thread-library),yes)
+ tests += bug-iconv3
+ endif
+@@ -327,6 +328,8 @@ $(objpfx)bug-iconv12.out: $(addprefix $(
+ 			  $(addprefix $(objpfx),$(modules.so))
+ $(objpfx)bug-iconv14.out: $(addprefix $(objpfx), $(gconv-modules)) \
+ 			  $(addprefix $(objpfx),$(modules.so))
++$(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \
++			  $(addprefix $(objpfx),$(modules.so))
+ 
+ $(objpfx)iconv-test.out: run-iconv-test.sh \
+ 			 $(addprefix $(objpfx), $(gconv-modules)) \
+Index: git/iconvdata/bug-iconv15.c
+===================================================================
+--- /dev/null
++++ git/iconvdata/bug-iconv15.c
+@@ -0,0 +1,60 @@
++/* Bug 28524: Conversion from ISO-2022-JP-3 with iconv
++   may emit spurious NUL character on state reset.
++   Copyright (C) The GNU Toolchain Authors.
++   This file is part of the GNU C Library.
++
++   The GNU C Library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   The GNU C Library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, see
++   <https://www.gnu.org/licenses/>.  */
++
++#include <stddef.h>
++#include <iconv.h>
++#include <support/check.h>
++
++static int
++do_test (void)
++{
++  char in[] = "\x1b(I";
++  char *inbuf = in;
++  size_t inleft = sizeof (in) - 1;
++  char out[1];
++  char *outbuf = out;
++  size_t outleft = sizeof (out);
++  iconv_t cd;
++
++  cd = iconv_open ("UTF8", "ISO-2022-JP-3");
++  TEST_VERIFY_EXIT (cd != (iconv_t) -1);
++
++  /* First call to iconv should alter internal state.
++     Now, JISX0201_Kana_set is selected and
++     state value != ASCII_set.  */
++  TEST_VERIFY (iconv (cd, &inbuf, &inleft, &outbuf, &outleft) != (size_t) -1);
++
++  /* No bytes should have been added to
++     the output buffer at this point.  */
++  TEST_VERIFY (outbuf == out);
++  TEST_VERIFY (outleft == sizeof (out));
++
++  /* Second call shall emit spurious NUL character in unpatched glibc.  */
++  TEST_VERIFY (iconv (cd, NULL, NULL, &outbuf, &outleft) != (size_t) -1);
++
++  /* No characters are expected to be produced.  */
++  TEST_VERIFY (outbuf == out);
++  TEST_VERIFY (outleft == sizeof (out));
++
++  TEST_VERIFY_EXIT (iconv_close (cd) != -1);
++
++  return 0;
++}
++
++#include <support/test-driver.c>
+Index: git/iconvdata/iso-2022-jp-3.c
+===================================================================
+--- git.orig/iconvdata/iso-2022-jp-3.c
++++ git/iconvdata/iso-2022-jp-3.c
+@@ -1,5 +1,6 @@
+ /* Conversion module for ISO-2022-JP-3.
+    Copyright (C) 1998-2021 Free Software Foundation, Inc.
++   Copyright (C) The GNU Toolchain Authors.
+    This file is part of the GNU C Library.
+    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998,
+    and Bruno Haible <bruno@clisp.org>, 2002.
+@@ -81,20 +82,31 @@ enum
+    the output state to the initial state.  This has to be done during the
+    flushing.  */
+ #define EMIT_SHIFT_TO_INIT \
+-  if (data->__statep->__count != ASCII_set)			      \
++  if ((data->__statep->__count & ~7) != ASCII_set)			      \
+     {									      \
+       if (FROM_DIRECTION)						      \
+ 	{								      \
+-	  if (__glibc_likely (outbuf + 4 <= outend))			      \
++	  uint32_t ch = data->__statep->__count >> 6;			      \
++									      \
++	  if (__glibc_unlikely (ch != 0))				      \
+ 	    {								      \
+-	      /* Write out the last character.  */			      \
+-	      *((uint32_t *) outbuf) = data->__statep->__count >> 6;	      \
+-	      outbuf += sizeof (uint32_t);				      \
+-	      data->__statep->__count = ASCII_set;			\
++	      if (__glibc_likely (outbuf + 4 <= outend))		      \
++		{							      \
++		  /* Write out the last character.  */			      \
++		  put32u (outbuf, ch);					      \
++		  outbuf += 4;						      \
++		  data->__statep->__count &= 7;				      \
++		  data->__statep->__count |= ASCII_set;			      \
++		}							      \
++	      else							      \
++		/* We don't have enough room in the output buffer.  */	      \
++		status = __GCONV_FULL_OUTPUT;				      \
+ 	    }								      \
+ 	  else								      \
+-	    /* We don't have enough room in the output buffer.  */	      \
+-	    status = __GCONV_FULL_OUTPUT;				      \
++	    {								      \
++	      data->__statep->__count &= 7;				      \
++	      data->__statep->__count |= ASCII_set;			      \
++	    }								      \
+ 	}								      \
+       else								      \
+ 	{								      \

+ 80 - 0
recipes-core/glibc/glibc/check-test-wrapper

@@ -0,0 +1,80 @@
+#!/usr/bin/env python3
+import sys
+import os
+import subprocess
+import resource
+
+env = os.environ.copy()
+args = sys.argv[1:]
+targettype = args.pop(0)
+
+if targettype == "user":
+    qemuargs = os.environ.get("QEMU_OPTIONS", "").split()
+    if not os.path.exists(qemuargs[0]):
+        # ensure qemu args has a valid absolute path
+        for i in os.environ.get("PATH", "").split(":"):
+            if os.path.exists(os.path.join(i, qemuargs[0])):
+                qemuargs[0] = os.path.join(i, qemuargs[0])
+                break
+    sysroot = os.environ.get("QEMU_SYSROOT", None)
+    if not sysroot:
+        sys.exit(-1)
+    libpaths = [sysroot + "/usr/lib", sysroot + "/lib"]
+
+    if args[0] == "env":
+        args.pop(0)
+        if len(args) == 0:
+            args = ["env"]
+        else:
+            # process options
+            while args[0].startswith("-"):
+                opt = args.pop(0).lstrip("-")
+                if "i" in opt:
+                    env.clear()
+            # process environment vars
+            while "=" in args[0]:
+                key, val = args.pop(0).split("=", 1)
+                if key == "LD_LIBRARY_PATH":
+                    libpaths += val.split(":")
+                else:
+                    env[key] = val
+    if args[0] == "cp":
+        # ignore copies, the filesystem is the same
+        sys.exit(0)
+
+    qemuargs += ["-L", sysroot]
+    qemuargs += ["-E", "LD_LIBRARY_PATH={}".format(":".join(libpaths))]
+    command = qemuargs + args
+
+    # We've seen qemu-arm using up all system memory for some glibc
+    # tests e.g. nptl/tst-pthread-timedlock-lockloop
+    # Cap at 8GB since no test should need more than that
+    # (5GB adds 7 failures for qemuarm glibc test run)
+    limit = 8*1024*1024*1024
+    resource.setrlimit(resource.RLIMIT_AS, (limit, limit))
+
+elif targettype == "ssh":
+    host = os.environ.get("SSH_HOST", None)
+    user = os.environ.get("SSH_HOST_USER", None)
+    port = os.environ.get("SSH_HOST_PORT", None)
+
+    command = ["ssh", "-o", "UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no"]
+    if port:
+        command += ["-p", str(port)]
+    if not host:
+        sys.exit(-1)
+    command += ["{}@{}".format(user, host) if user else host]
+
+    # wrap and replace quotes for correct transformation on ssh
+    wrapped = " ".join(["'{0}'".format(i.replace("'", r"'\''")) for i in ["cd", os.getcwd()]]) + "; "
+    wrapped += " ".join(["'{0}'".format(i.replace("'", r"'\''")) for i in args])
+    command += ["sh", "-c", "\"{}\"".format(wrapped)]
+else:
+    sys.exit(-1)
+
+try:
+    r = subprocess.run(command, timeout = 1800, env = env)
+    sys.exit(r.returncode)
+except subprocess.TimeoutExpired:
+    sys.exit(-1)
+

+ 1 - 0
recipes-core/glibc/glibc/etc/ld.so.conf

@@ -0,0 +1 @@
+include /etc/ld.so.conf.d/*.conf

+ 11 - 0
recipes-core/glibc/glibc/generate-supported.mk

@@ -0,0 +1,11 @@
+#!/usr/bin/make
+
+include $(IN)
+
+all:
+	rm -f $(OUT)
+	touch $(OUT)
+	for locale in $(SUPPORTED-LOCALES); do \
+		[ $$locale = true ] && continue; \
+		echo $$locale | sed 's,/, ,' >> $(OUT); \
+	done

+ 177 - 0
recipes-core/glibc/glibc/makedbs.sh

@@ -0,0 +1,177 @@
+#!/bin/sh
+
+#
+# Make passwd.db, group.db, etc.
+#
+
+VAR_DB=/var/db
+
+# Use make if available
+if [ -x /usr/bin/make -o -x /bin/make ]; then
+	make -C $VAR_DB
+	exit 0
+fi
+
+# No make available, do it in hard way
+
+# passwd.db
+if [ -e /etc/passwd ]; then
+target=$VAR_DB/passwd.db
+echo -n "passwd... "
+awk 'BEGIN { FS=":"; OFS=":" } \
+ /^[ \t]*$$/ { next } \
+ /^[ \t]*#/ { next } \
+ /^[^#]/ { printf ".%s ", $$1; print; \
+	   printf "=%s ", $$3; print }' /etc/passwd | \
+makedb --quiet -o $target -
+echo "done."
+fi
+
+# group.db
+if [ -e /etc/group ]; then
+target=$VAR_DB/group.db
+echo -n "group... "
+awk 'BEGIN { FS=":"; OFS=":" } \
+ /^[ \t]*$$/ { next } \
+ /^[ \t]*#/ { next } \
+ /^[^#]/ { printf ".%s ", $$1; print; \
+	   printf "=%s ", $$3; print; \
+	   if ($$4 != "") { \
+	     split($$4, grmems, ","); \
+	     for (memidx in grmems) { \
+	       mem=grmems[memidx]; \
+	       if (members[mem] == "") \
+		 members[mem]=$$3; \
+	       else \
+		 members[mem]=members[mem] "," $$3; \
+	     } \
+	     delete grmems; } } \
+ END { for (mem in members) \
+	 printf ":%s %s %s\n", mem, mem, members[mem]; }' /etc/group | \
+makedb --quiet -o $target -
+echo "done."
+fi
+
+# ethers.db
+if [ -e /etc/ethers ]; then
+target=$VAR_DB/ethers.db
+echo -n "ethers... "
+awk '/^[ \t]*$$/ { next } \
+ /^[ \t]*#/ { next } \
+ /^[^#]/ { printf ".%s ", $$1; print; \
+	   printf "=%s ", $$2; print }' /etc/ethers | \
+makedb --quiet -o $target -
+echo "done."
+fi
+
+# protocols.db
+if [ -e /etc/protocols ]; then
+target=$VAR_DB/protocols.db
+echo -n "protocols... "
+awk '/^[ \t]*$$/ { next } \
+ /^[ \t]*#/ { next } \
+ /^[^#]/ { printf ".%s ", $$1; print; \
+	   printf "=%s ", $$2; print; \
+	   for (i = 3; i <= NF && !($$i ~ /^#/); ++i) \
+	     { printf ".%s ", $$i; print } }' /etc/protocols | \
+makedb --quiet -o $target -
+echo "done."
+fi
+
+# rpc.db
+if [ -e /etc/rpc ]; then
+target=$VAR_DB/rpc.db
+echo -n "rpc... "
+awk '/^[ \t]*$$/ { next } \
+ /^[ \t]*#/ { next } \
+ /^[^#]/ { printf ".%s ", $$1; print; \
+	   printf "=%s ", $$2; print; \
+	   for (i = 3; i <= NF && !($$i ~ /^#/); ++i) \
+	     { printf ".%s ", $$i; print } }' /etc/rpc | \
+makedb --quiet -o $target -
+echo "done."
+fi
+
+# services.db
+if [ -e /etc/services ]; then
+target=$VAR_DB/services.db
+echo -n "services... "
+awk 'BEGIN { FS="[ \t/]+" } \
+ /^[ \t]*$$/ { next } \
+ /^[ \t]*#/ { next } \
+ /^[^#]/ { sub(/[ \t]*#.*$$/, "");\
+	   printf ":%s/%s ", $$1, $$3; print; \
+	   printf ":%s/ ", $$1; print; \
+	   printf "=%s/%s ", $$2, $$3; print; \
+	   printf "=%s/ ", $$2; print; \
+	   for (i = 4; i <= NF && !($$i ~ /^#/); ++i) \
+	     { printf ":%s/%s ", $$i, $$3; print; \
+	       printf ":%s/ ", $$i; print } }' /etc/services | \
+makedb --quiet -o $target -
+echo "done."
+fi
+
+# shadow.db
+if [ -e /etc/shadow ]; then
+target=$VAR_DB/shadow.db
+echo -n "shadow... "
+awk 'BEGIN { FS=":"; OFS=":" } \
+ /^[ \t]*$$/ { next } \
+ /^[ \t]*#/ { next } \
+ /^[^#]/ { printf ".%s ", $$1; print }' /etc/shadow | \
+(umask 077 && makedb --quiet -o $target -)
+echo "done."
+if chgrp shadow $target 2>/dev/null; then
+	chmod g+r $target
+else
+	chown 0 $target; chgrp 0 $target; chmod 600 $target;
+	echo
+	echo "Warning: The shadow password database $target"
+	echo "has been set to be readable only by root.  You may want"
+	echo "to make it readable by the \`shadow' group depending"
+	echo "on your configuration."
+	echo
+fi
+fi
+
+# gshadow.db
+if [ -e /etc/gshadow ]; then
+target=$VAR_DB/gshadow.db
+echo -n "gshadow... "
+awk 'BEGIN { FS=":"; OFS=":" } \
+ /^[ \t]*$$/ { next } \
+ /^[ \t]*#/ { next } \
+ /^[^#]/ { printf ".%s ", $$1; print }' /etc/gshadow | \
+(umask 077 && makedb --quiet -o $target -)
+echo "done."
+if chgrp shadow $target 2>/dev/null; then
+	chmod g+r $target
+else
+	chown 0 $target; chgrp 0 $target; chmod 600 $target
+	echo
+	echo "Warning: The shadow group database $target"
+	echo "has been set to be readable only by root.  You may want"
+	echo "to make it readable by the \`shadow' group depending"
+	echo "on your configuration."
+	echo
+fi
+fi
+
+# netgroup.db
+if [ -e /etc/netgroup ]; then
+target=$VAR_DB/netgroup.db
+echo -n "netgroup... "
+awk 'BEGIN { ini=1 } \
+ /^[ \t]*$$/ { next } \
+ /^[ \t]*#/ { next } \
+ /^[^#]/ { if (sub(/[ \t]*\\$$/, " ") == 0) end="\n"; \
+	   else end=""; \
+	   gsub(/[ \t]+/, " "); \
+	   sub(/^[ \t]*/, ""); \
+	   if (ini == 0) printf "%s%s", $$0, end; \
+	   else printf ".%s %s%s", $$1, $$0, end; \
+	   ini=end == "" ? 0 : 1; } \
+ END { if (ini==0) printf "\n" }' /etc/netgroup | \
+makedb --quiet -o $target
+echo "done."
+fi

+ 131 - 0
recipes-core/glibc/glibc_2.35.bb

@@ -0,0 +1,131 @@
+require glibc.inc
+require glibc-version.inc
+
+CVE_CHECK_WHITELIST += "CVE-2020-10029 CVE-2021-27645"
+
+# glibc https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2019-1010022
+# glibc https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2019-1010023
+# glibc https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2019-1010024
+# Upstream glibc maintainers dispute there is any issue and have no plans to address it further.
+# "this is being treated as a non-security bug and no real threat."
+CVE_CHECK_WHITELIST += "CVE-2019-1010022 CVE-2019-1010023 CVE-2019-1010024"
+
+# glibc https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2019-1010025
+# Allows for ASLR bypass so can bypass some hardening, not an exploit in itself, may allow
+# easier access for another. "ASLR bypass itself is not a vulnerability."
+# Potential patch at https://sourceware.org/bugzilla/show_bug.cgi?id=22853
+CVE_CHECK_WHITELIST += "CVE-2019-1010025"
+
+DEPENDS += "gperf-native bison-native make-native"
+
+NATIVESDKFIXES ?= ""
+NATIVESDKFIXES:class-nativesdk = "\
+           file://0003-nativesdk-glibc-Look-for-host-system-ld.so.cache-as-.patch \
+           file://0004-nativesdk-glibc-Fix-buffer-overrun-with-a-relocated-.patch \
+           file://0005-nativesdk-glibc-Raise-the-size-of-arrays-containing-.patch \
+           file://0006-nativesdk-glibc-Allow-64-bit-atomics-for-x86.patch \
+           file://0007-nativesdk-glibc-Make-relocatable-install-for-locales.patch \
+           file://0008-nativesdk-glibc-Fall-back-to-faccessat-on-faccess2-r.patch \
+"
+
+SRC_URI =  "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \
+           file://etc/ld.so.conf \
+           file://generate-supported.mk \
+           file://makedbs.sh \
+           \
+           ${NATIVESDKFIXES} \
+           file://0009-fsl-e500-e5500-e6500-603e-fsqrt-implementation.patch \
+           file://0010-ppc-sqrt-Fix-undefined-reference-to-__sqrt_finite.patch \
+           file://0011-__ieee754_sqrt-f-are-now-inline-functions-and-call-o.patch \
+           file://0012-Quote-from-bug-1443-which-explains-what-the-patch-do.patch \
+           file://0013-eglibc-run-libm-err-tab.pl-with-specific-dirs-in-S.patch \
+           file://0014-__ieee754_sqrt-f-are-now-inline-functions-and-call-o.patch \
+           file://0015-sysdeps-gnu-configure.ac-handle-correctly-libc_cv_ro.patch \
+           file://0016-yes-within-the-path-sets-wrong-config-variables.patch \
+           file://0017-timezone-re-written-tzselect-as-posix-sh.patch \
+           file://0018-Remove-bash-dependency-for-nscd-init-script.patch \
+           file://0019-eglibc-Cross-building-and-testing-instructions.patch \
+           file://0020-eglibc-Help-bootstrap-cross-toolchain.patch \
+           file://0021-eglibc-Resolve-__fpscr_values-on-SH4.patch \
+           file://0022-eglibc-Forward-port-cross-locale-generation-support.patch \
+           file://0024-localedef-add-to-archive-uses-a-hard-coded-locale-pa.patch \
+           file://0025-elf-dl-deps.c-Make-_dl_build_local_scope-breadth-fir.patch \
+           file://0026-intl-Emit-no-lines-in-bison-generated-files.patch \
+           file://0027-locale-prevent-maybe-uninitialized-errors-with-Os-BZ.patch \
+           file://0028-readlib-Add-OECORE_KNOWN_INTERPRETER_NAMES-to-known-.patch \
+           file://0029-wordsize.h-Unify-the-header-between-arm-and-aarch64.patch \
+           file://0030-powerpc-Do-not-ask-compiler-for-finding-arch.patch \
+           file://0001-fix-create-thread-failed-in-unprivileged-process-BZ-.patch \
+           "
+S = "${WORKDIR}/git"
+B = "${WORKDIR}/build-${TARGET_SYS}"
+
+PACKAGES_DYNAMIC = ""
+
+# the -isystem in bitbake.conf screws up glibc do_stage
+BUILD_CPPFLAGS = "-I${STAGING_INCDIR_NATIVE}"
+TARGET_CPPFLAGS = "-I${STAGING_DIR_TARGET}${includedir}"
+
+GLIBC_BROKEN_LOCALES = ""
+
+GLIBCPIE ??= ""
+
+EXTRA_OECONF = "--enable-kernel=${OLDEST_KERNEL} \
+                --disable-profile \
+                --disable-debug --without-gd \
+                --enable-clocale=gnu \
+                --with-headers=${STAGING_INCDIR} \
+                --without-selinux \
+                --enable-tunables \
+                --enable-bind-now \
+                --enable-stack-protector=strong \
+                --disable-crypt \
+                --with-default-link \
+                ${@bb.utils.contains_any('SELECTED_OPTIMIZATION', '-O0 -Og', '--disable-werror', '', d)} \
+                ${GLIBCPIE} \
+                ${GLIBC_EXTRA_OECONF}"
+
+EXTRA_OECONF += "${@get_libc_fpu_setting(bb, d)}"
+
+EXTRA_OECONF:append:x86 = " --enable-cet"
+EXTRA_OECONF:append:x86-64 = " --enable-cet"
+
+PACKAGECONFIG ??= "nscd memory-tagging"
+PACKAGECONFIG[nscd] = "--enable-nscd,--disable-nscd"
+PACKAGECONFIG[memory-tagging] = "--enable-memory-tagging,--disable-memory-tagging"
+
+do_patch:append() {
+    bb.build.exec_func('do_fix_readlib_c', d)
+}
+
+do_fix_readlib_c () {
+	sed -i -e 's#OECORE_KNOWN_INTERPRETER_NAMES#${EGLIBC_KNOWN_INTERPRETER_NAMES}#' ${S}/elf/readlib.c
+}
+
+do_configure () {
+# override this function to avoid the autoconf/automake/aclocal/autoheader
+# calls for now
+# don't pass CPPFLAGS into configure, since it upsets the kernel-headers
+# version check and doesn't really help with anything
+        (cd ${S} && gnu-configize) || die "failure in running gnu-configize"
+        find ${S} -name "configure" | xargs touch
+        CPPFLAGS="" oe_runconf
+}
+
+LDFLAGS += "-fuse-ld=bfd"
+do_compile () {
+	base_do_compile
+	echo "Adjust ldd script"
+	if [ -n "${RTLDLIST}" ]
+	then
+		prevrtld=`cat ${B}/elf/ldd | grep "^RTLDLIST=" | sed 's#^RTLDLIST="\?\([^"]*\)"\?$#\1#'`
+		# remove duplicate entries
+		newrtld=`echo $(printf '%s\n' ${prevrtld} ${RTLDLIST} | LC_ALL=C sort -u)`
+		echo "ldd \"${prevrtld} ${RTLDLIST}\" -> \"${newrtld}\""
+		sed -i ${B}/elf/ldd -e "s#^RTLDLIST=.*\$#RTLDLIST=\"${newrtld}\"#"
+	fi
+}
+
+require glibc-package.inc
+
+BBCLASSEXTEND = "nativesdk"

+ 331 - 0
recipes-core/glibc/ldconfig-native-2.12.1/32and64bit.patch

@@ -0,0 +1,331 @@
+Upstream-Status: Inappropriate [embedded specific]
+
+We run the ldconfig in the cross fashion. make the code bitsize aware so that 
+we can cross build ldconfig cache for various architectures.
+
+Richard Purdie <richard.purdie@linuxfoundation.org> 2009/05/19
+Nitin A Kamble <nitin.a.kamble@intel.com> 2009/03/29
+
+Index: ldconfig-native-2.12.1/readelflib.c
+===================================================================
+--- ldconfig-native-2.12.1.orig/readelflib.c
++++ ldconfig-native-2.12.1/readelflib.c
+@@ -40,39 +40,212 @@ do								\
+ 
+ /* Returns 0 if everything is ok, != 0 in case of error.  */
+ int
+-process_elf_file (const char *file_name, const char *lib, int *flag,
++process_elf_file32 (const char *file_name, const char *lib, int *flag,
+ 		  unsigned int *osversion, char **soname, void *file_contents,
+ 		  size_t file_length)
+ {
+   int i;
+   unsigned int j;
+-  ElfW(Addr) loadaddr;
++  Elf32_Addr loadaddr;
+   unsigned int dynamic_addr;
+   size_t dynamic_size;
+   char *program_interpreter;
+ 
+-  ElfW(Ehdr) *elf_header;
+-  ElfW(Phdr) *elf_pheader, *segment;
+-  ElfW(Dyn) *dynamic_segment, *dyn_entry;
++  Elf32_Ehdr *elf_header;
++  Elf32_Phdr *elf_pheader, *segment;
++  Elf32_Dyn *dynamic_segment, *dyn_entry;
+   char *dynamic_strings;
+ 
+-  elf_header = (ElfW(Ehdr) *) file_contents;
++  elf_header = (Elf32_Ehdr *) file_contents;
+   *osversion = 0;
+ 
+-  if (elf_header->e_ident [EI_CLASS] != ElfW (CLASS))
++  if (elf_header->e_type != ET_DYN)
+     {
+-      if (opt_verbose)
++      error (0, 0, _("%s is not a shared object file (Type: %d).\n"), file_name,
++	     elf_header->e_type);
++      return 1;
++    }
++
++  /* Get information from elf program header.  */
++  elf_pheader = (Elf32_Phdr *) (elf_header->e_phoff + file_contents);
++  check_ptr (elf_pheader);
++
++  /* The library is an elf library, now search for soname and
++     libc5/libc6.  */
++  *flag = FLAG_ELF;
++
++  loadaddr = -1;
++  dynamic_addr = 0;
++  dynamic_size = 0;
++  program_interpreter = NULL;
++  for (i = 0, segment = elf_pheader;
++       i < elf_header->e_phnum; i++, segment++)
++    {
++      check_ptr (segment);
++
++      switch (segment->p_type)
+ 	{
+-	  if (elf_header->e_ident [EI_CLASS] == ELFCLASS32)
+-	    error (0, 0, _("%s is a 32 bit ELF file.\n"), file_name);
+-	  else if (elf_header->e_ident [EI_CLASS] == ELFCLASS64)
+-	    error (0, 0, _("%s is a 64 bit ELF file.\n"), file_name);
+-	  else
+-	    error (0, 0, _("Unknown ELFCLASS in file %s.\n"), file_name);
++	case PT_LOAD:
++	  if (loadaddr == (Elf32_Addr) -1)
++	    loadaddr = segment->p_vaddr - segment->p_offset;
++	  break;
++
++	case PT_DYNAMIC:
++	  if (dynamic_addr)
++	    error (0, 0, _("more than one dynamic segment\n"));
++
++	  dynamic_addr = segment->p_offset;
++	  dynamic_size = segment->p_filesz;
++	  break;
++
++	case PT_INTERP:
++	  program_interpreter = (char *) (file_contents + segment->p_offset);
++	  check_ptr (program_interpreter);
++
++	  /* Check if this is enough to classify the binary.  */
++	  for (j = 0; j < sizeof (interpreters) / sizeof (interpreters [0]);
++	       ++j)
++	    if (strcmp (program_interpreter, interpreters[j].soname) == 0)
++	      {
++		*flag = interpreters[j].flag;
++		break;
++	      }
++	  break;
++
++	case PT_NOTE:
++	  if (!*osversion && segment->p_filesz >= 32 && segment->p_align >= 4)
++	    {
++	      Elf32_Word *abi_note = (Elf32_Word *) (file_contents
++						     + segment->p_offset);
++	      Elf32_Addr size = segment->p_filesz;
++
++	      while (abi_note [0] != 4 || abi_note [1] != 16
++		     || abi_note [2] != 1
++		     || memcmp (abi_note + 3, "GNU", 4) != 0)
++		{
++#define ROUND(len) (((len) + sizeof (Elf32_Word)) - 1) & -sizeof (Elf32_Word)))
++		  Elf32_Addr) note_size = 3 * sizeof (Elf32_Word))
++					 + ROUND (abi_note[0])
++					 + ROUND (abi_note[1]);
++
++		  if (size - 32 < note_size || note_size == 0)
++		    {
++		      size = 0;
++		      break;
++		    }
++		  size -= note_size;
++		  abi_note = (void *) abi_note + note_size;
++		}
++
++	      if (size == 0)
++		break;
++
++	      *osversion = (abi_note [4] << 24) |
++			   ((abi_note [5] & 0xff) << 16) |
++			   ((abi_note [6] & 0xff) << 8) |
++			   (abi_note [7] & 0xff);
++	    }
++	  break;
++
++	default:
++	  break;
++	}
++
++    }
++  if (loadaddr == (Elf32_Addr) -1)
++    {
++      /* Very strange. */
++      loadaddr = 0;
++    }
++
++  /* Now we can read the dynamic sections.  */
++  if (dynamic_size == 0)
++    return 1;
++
++  dynamic_segment = (Elf32_Dyn *) (file_contents + dynamic_addr);
++  check_ptr (dynamic_segment);
++
++  /* Find the string table.  */
++  dynamic_strings = NULL;
++  for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL;
++       ++dyn_entry)
++    {
++      check_ptr (dyn_entry);
++      if (dyn_entry->d_tag == DT_STRTAB)
++	{
++	  dynamic_strings = (char *) (file_contents + dyn_entry->d_un.d_val - loadaddr);
++	  check_ptr (dynamic_strings);
++	  break;
+ 	}
+-      return 1;
+     }
+ 
++  if (dynamic_strings == NULL)
++    return 1;
++
++  /* Now read the DT_NEEDED and DT_SONAME entries.  */
++  for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL;
++       ++dyn_entry)
++    {
++      if (dyn_entry->d_tag == DT_NEEDED || dyn_entry->d_tag == DT_SONAME)
++	{
++	  char *name = dynamic_strings + dyn_entry->d_un.d_val;
++	  check_ptr (name);
++
++	  if (dyn_entry->d_tag == DT_NEEDED)
++	    {
++
++	      if (*flag == FLAG_ELF)
++		{
++		  /* Check if this is enough to classify the binary.  */
++		  for (j = 0;
++		       j < sizeof (known_libs) / sizeof (known_libs [0]);
++		       ++j)
++		    if (strcmp (name, known_libs [j].soname) == 0)
++		      {
++			*flag = known_libs [j].flag;
++			break;
++		      }
++		}
++	    }
++
++	  else if (dyn_entry->d_tag == DT_SONAME)
++	    *soname = xstrdup (name);
++
++	  /* Do we have everything we need?  */
++	  if (*soname && *flag != FLAG_ELF)
++	    return 0;
++	}
++    }
++
++  /* We reach this point only if the file doesn't contain a DT_SONAME
++     or if we can't classify the library.  If it doesn't have a
++     soname, return the name of the library.  */
++  if (*soname == NULL)
++    *soname = xstrdup (lib);
++
++  return 0;
++}
++
++int
++process_elf_file64 (const char *file_name, const char *lib, int *flag,
++		  unsigned int *osversion, char **soname, void *file_contents,
++		  size_t file_length)
++{
++  int i;
++  unsigned int j;
++  Elf64_Addr loadaddr;
++  unsigned int dynamic_addr;
++  size_t dynamic_size;
++  char *program_interpreter;
++
++  Elf64_Ehdr *elf_header;
++  Elf64_Phdr *elf_pheader, *segment;
++  Elf64_Dyn *dynamic_segment, *dyn_entry;
++  char *dynamic_strings;
++
++  elf_header = (Elf64_Ehdr *) file_contents;
++  *osversion = 0;
++
+   if (elf_header->e_type != ET_DYN)
+     {
+       error (0, 0, _("%s is not a shared object file (Type: %d).\n"), file_name,
+@@ -81,7 +254,7 @@ process_elf_file (const char *file_name,
+     }
+ 
+   /* Get information from elf program header.  */
+-  elf_pheader = (ElfW(Phdr) *) (elf_header->e_phoff + file_contents);
++  elf_pheader = (Elf64_Phdr *) (elf_header->e_phoff + file_contents);
+   check_ptr (elf_pheader);
+ 
+   /* The library is an elf library, now search for soname and
+@@ -100,7 +273,7 @@ process_elf_file (const char *file_name,
+       switch (segment->p_type)
+ 	{
+ 	case PT_LOAD:
+-	  if (loadaddr == (ElfW(Addr)) -1)
++	  if (loadaddr == (Elf64_Addr) -1)
+ 	    loadaddr = segment->p_vaddr - segment->p_offset;
+ 	  break;
+ 
+@@ -129,16 +302,16 @@ process_elf_file (const char *file_name,
+ 	case PT_NOTE:
+ 	  if (!*osversion && segment->p_filesz >= 32 && segment->p_align >= 4)
+ 	    {
+-	      ElfW(Word) *abi_note = (ElfW(Word) *) (file_contents
++	      Elf64_Word *abi_note = (Elf64_Word *) (file_contents
+ 						     + segment->p_offset);
+-	      ElfW(Addr) size = segment->p_filesz;
++	      Elf64_Addr size = segment->p_filesz;
+ 
+ 	      while (abi_note [0] != 4 || abi_note [1] != 16
+ 		     || abi_note [2] != 1
+ 		     || memcmp (abi_note + 3, "GNU", 4) != 0)
+ 		{
+-#define ROUND(len) (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word)))
+-		  ElfW(Addr) note_size = 3 * sizeof (ElfW(Word))
++#define ROUND(len) (((len) + sizeof (Elf64_Word) - 1) & -sizeof (Elf64_Word))
++		  Elf64_Addr note_size = 3 * sizeof (Elf64_Word)
+ 					 + ROUND (abi_note[0])
+ 					 + ROUND (abi_note[1]);
+ 
+@@ -166,7 +339,7 @@ process_elf_file (const char *file_name,
+ 	}
+ 
+     }
+-  if (loadaddr == (ElfW(Addr)) -1)
++  if (loadaddr == (Elf64_Addr) -1)
+     {
+       /* Very strange. */
+       loadaddr = 0;
+@@ -176,7 +349,7 @@ process_elf_file (const char *file_name,
+   if (dynamic_size == 0)
+     return 1;
+ 
+-  dynamic_segment = (ElfW(Dyn) *) (file_contents + dynamic_addr);
++  dynamic_segment = (Elf64_Dyn *) (file_contents + dynamic_addr);
+   check_ptr (dynamic_segment);
+ 
+   /* Find the string table.  */
+@@ -233,3 +406,33 @@ process_elf_file (const char *file_name,
+ 
+   return 0;
+ }
++/* Returns 0 if everything is ok, != 0 in case of error.  */
++int
++process_elf_file (const char *file_name, const char *lib, int *flag,
++		  unsigned int *osversion, char **soname, void *file_contents,
++		  size_t file_length)
++{
++  int i;
++  unsigned int j;
++  ElfW(Addr) loadaddr;
++  unsigned int dynamic_addr;
++  size_t dynamic_size;
++  char *program_interpreter;
++
++  ElfW(Ehdr) *elf_header;
++  ElfW(Phdr) *elf_pheader, *segment;
++  ElfW(Dyn) *dynamic_segment, *dyn_entry;
++  char *dynamic_strings;
++
++  elf_header = (ElfW(Ehdr) *) file_contents;
++  *osversion = 0;
++
++  if (elf_header->e_ident [EI_CLASS] == ELFCLASS32)
++    return process_elf_file32(file_name, lib,flag, osversion, soname, file_contents, file_length);
++  else if (elf_header->e_ident [EI_CLASS] == ELFCLASS64)
++    return process_elf_file64(file_name, lib,flag, osversion, soname, file_contents, file_length);
++  error (0, 0, _("Unknown ELFCLASS in file %s.\n"), file_name);
++  return 1;
++}
++
++

+ 8 - 0
recipes-core/glibc/ldconfig-native-2.12.1/README

@@ -0,0 +1,8 @@
+The files are pulled verbatim from glibc 2.5 and then patched to allow
+standalone compilation of ldconfig.
+
+Richard Purdie
+OpenedHand Ltd.
+
+Upgraded the ldconfig recipe to eglibc 2.12.1
+Nitin A Kamble <nitin.a.kamble@intel.com> 2011/03/29

+ 116 - 0
recipes-core/glibc/ldconfig-native-2.12.1/add-64-bit-flag-for-ELF64-entries.patch

@@ -0,0 +1,116 @@
+From 9d62544090b08849218cd1fc52a36cdd5d90363e Mon Sep 17 00:00:00 2001
+From: Yuanjie Huang <yuanjie.huang@windriver.com>
+Date: Fri, 24 Apr 2015 03:29:31 +0000
+Subject: [PATCH] Add 64-bit flag for ELF64 entries.
+
+ldconfig-native was grepped from an old version of glibc, and its output
+lacks neccessary 64bit flag in entries.
+Due to this defect, ctypes.util.find_library() python function fails to
+detect any library due to the old file format that ldconfig-native
+creates. This fix sets architecture-dependent 64bit flags for 64-bit ELF.
+
+Upstream-Status: Inappropriate [embedded specific]
+
+Signed-off-by: Yuanjie Huang <yuanjie.huang@windriver.com>
+---
+ cache.c      |  4 ++++
+ ldconfig.h   |  4 ++++
+ readelflib.c | 34 ++++++++++++++++++++++++++++++++++
+ 3 files changed, 42 insertions(+)
+
+diff --git a/cache.c b/cache.c
+index a904d44..c4f5411 100644
+--- a/cache.c
++++ b/cache.c
+@@ -121,6 +121,10 @@ print_entry (const char *lib, int flag, unsigned int osversion,
+       break;
+     case FLAG_MIPS64_LIBN64:
+       fputs (",64bit", stdout);
++      break;
++    case FLAG_AARCH64_LIB64:
++      fputs (",AArch64", stdout);
++      break;
+     case 0:
+       break;
+     default:
+diff --git a/ldconfig.h b/ldconfig.h
+index fadd5ec..6a8a750 100644
+--- a/ldconfig.h
++++ b/ldconfig.h
+@@ -34,6 +34,10 @@
+ #define FLAG_POWERPC_LIB64	0x0500
+ #define FLAG_MIPS64_LIBN32	0x0600
+ #define FLAG_MIPS64_LIBN64	0x0700
++#define FLAG_X8664_LIBX32		0x0800
++#define FLAG_ARM_LIBHF			0x0900
++#define FLAG_AARCH64_LIB64		0x0a00
++#define FLAG_ARM_LIBSF			0x0b00
+ 
+ /* Name of auxiliary cache.  */
+ #define _PATH_LDCONFIG_AUX_CACHE "/var/cache/ldconfig/aux-cache"
+diff --git a/readelflib.c b/readelflib.c
+index 0bf0de3..6e87afc 100644
+--- a/readelflib.c
++++ b/readelflib.c
+@@ -28,6 +28,11 @@
+ 
+ #include "endian_extra.h"
+ 
++/* Work-around for old host that does not have AArch64 defined in elf.h. */
++#ifndef EM_AARCH64
++#define EM_AARCH64	183		/* ARM AARCH64 */
++#endif
++
+ #undef check_ptr
+ #define check_ptr(ptr)						\
+ do								\
+@@ -290,6 +295,48 @@ process_elf_file64 (const char *file_name, const char *lib, int *flag,
+      libc5/libc6.  */
+   *flag = FLAG_ELF;
+ 
++  /* Set flags according to information in ELF header to align with target
++     ldconfig */
++  switch (elf_header->e_machine)
++    {
++    case EM_IA_64:
++      /* Intel 64bit libraries are always libc.so.6+. */
++      /* see sysdeps/unix/sysv/linux/ia64/readelflib.c */
++      *flag |= FLAG_IA64_LIB64|FLAG_ELF_LIBC6;
++      break;
++    case EM_X86_64:
++      /* X86-64 64bit libraries are always libc.so.6+. */
++      /* see sysdeps/unix/sysv/linux/i386/readelflib.c */
++      *flag |= FLAG_X8664_LIB64|FLAG_ELF_LIBC6;
++      break;
++    case EM_S390:
++      /* S/390 64bit libraries are always libc.so.6+. */
++      /* see sysdeps/unix/sysv/linux/s390/readelflib.c */
++      *flag |= FLAG_S390_LIB64|FLAG_ELF_LIBC6;
++      break;
++    case EM_PPC64:
++      /* PowerPC 64bit libraries are always libc.so.6+. */
++      /* see sysdeps/unix/sysv/linux/powerpc/readelflib.c */
++      *flag |= FLAG_POWERPC_LIB64|FLAG_ELF_LIBC6;
++      break;
++    case EM_MIPS:
++    case EM_MIPS_RS3_LE:
++      /* n64 libraries are always libc.so.6+. */
++      /* NOTE: This does not correctly distinguish NAN2008 binaries and is possibly broken */
++      /* see sysdeps/unix/sysv/linux/mips/readelflib.c */
++      *flag |= FLAG_MIPS64_LIBN64|FLAG_ELF_LIBC6;
++      break;
++    case EM_AARCH64:
++      /* AArch64 libraries are always libc.so.6+. */
++      /* see sysdeps/unix/sysv/linux/arm/readelflib.c */
++      *flag |= FLAG_AARCH64_LIB64|FLAG_ELF_LIBC6;
++      break;
++    default:
++      error(0, 0, "%s is a 64-bit ELF for unknown machine %lx\n",
++            file_name, (long)elf_header->e_machine);
++      break;
++    }
++
+   loadaddr = -1;
+   dynamic_addr = 0;
+   dynamic_size = 0;
+-- 

+ 79 - 0
recipes-core/glibc/ldconfig-native-2.12.1/add-riscv-support.patch

@@ -0,0 +1,79 @@
+From fd50228cc213d2d87f5e3cf1f123acb3fda9b04e Mon Sep 17 00:00:00 2001
+From: Christoph Muellner <cmuellner@linux.com>
+Date: Mon, 28 Jun 2021 00:34:12 +0200
+Subject: [PATCH] ldconfig: Add RISC-V support
+
+ldconfig-native does not support RISC-V at the moment.
+Let's pull the reqired constants from upstream and add
+the required parsing code.
+
+Upstream-Status: Backport
+
+Signed-off-by: Christoph Muellner <cmuellner@linux.com>
+---
+ cache.c      |  6 ++++++
+ ldconfig.h   |  2 ++
+ readelflib.c | 10 ++++++++++
+ 3 files changed, 18 insertions(+)
+
+diff --git a/cache.c b/cache.c
+index c4f5411..a3b9e70 100644
+--- a/cache.c
++++ b/cache.c
+@@ -125,6 +125,12 @@ print_entry (const char *lib, int flag, unsigned int osversion,
+     case FLAG_AARCH64_LIB64:
+       fputs (",AArch64", stdout);
+       break;
++    case FLAG_RISCV_FLOAT_ABI_SOFT:
++      fputs (",soft-float", stdout);
++      break;
++    case FLAG_RISCV_FLOAT_ABI_DOUBLE:
++      fputs (",double-float", stdout);
++      break;
+     case 0:
+       break;
+     default:
+diff --git a/ldconfig.h b/ldconfig.h
+index 6a8a750..2e5e379 100644
+--- a/ldconfig.h
++++ b/ldconfig.h
+@@ -38,6 +38,8 @@
+ #define FLAG_ARM_LIBHF			0x0900
+ #define FLAG_AARCH64_LIB64		0x0a00
+ #define FLAG_ARM_LIBSF			0x0b00
++#define FLAG_RISCV_FLOAT_ABI_SOFT	0x0f00
++#define FLAG_RISCV_FLOAT_ABI_DOUBLE	0x1000
+ 
+ /* Name of auxiliary cache.  */
+ #define _PATH_LDCONFIG_AUX_CACHE "/var/cache/ldconfig/aux-cache"
+diff --git a/readelflib.c b/readelflib.c
+index 9ec0a54..a01e1ce 100644
+--- a/readelflib.c
++++ b/readelflib.c
+@@ -33,6 +33,10 @@
+ #define EM_AARCH64	183		/* ARM AARCH64 */
+ #endif
+ 
++#ifndef EM_RISCV
++#define EM_RISCV	243		/* RISC-V */
++#endif
++
+ #undef check_ptr
+ #define check_ptr(ptr)						\
+ do								\
+@@ -331,6 +335,12 @@ process_elf_file64 (const char *file_name, const char *lib, int *flag,
+       /* see sysdeps/unix/sysv/linux/arm/readelflib.c */
+       *flag |= FLAG_AARCH64_LIB64|FLAG_ELF_LIBC6;
+       break;
++    case EM_RISCV:
++      /* RISC-V libraries are always libc.so.6+. */
++      /* NOTE: This does not correctly handle soft-float binaries */
++      /* see sysdeps/unix/sysv/linux/riscv/readelflib.c */
++      *flag |= FLAG_RISCV_FLOAT_ABI_DOUBLE|FLAG_ELF_LIBC6;
++      break;
+     default:
+       error(0, 0, "%s is a 64-bit ELF for unknown machine %lx\n",
+             file_name, (long)elf_header->e_machine);
+-- 
+2.25.1
+

+ 454 - 0
recipes-core/glibc/ldconfig-native-2.12.1/endian-ness_handling.patch

@@ -0,0 +1,454 @@
+Upstream-Status: Inappropriate [embedded specific]
+
+Do data input/output handling according to endien-ness of the library file. That 
+enables use of ldconfig in the cross fashion for any architecture.
+
+2011/04/04
+Richard Purdie <richard.purdie@linuxfoundation.org>
+Nitin Kamble <nitin.a.kamble@intel.com>
+
+Index: ldconfig-native-2.12.1/readelflib.c
+===================================================================
+--- ldconfig-native-2.12.1.orig/readelflib.c
++++ ldconfig-native-2.12.1/readelflib.c
+@@ -38,6 +38,28 @@ do								\
+   }								\
+  while (0);
+ 
++int be;
++static uint16_t read16(uint16_t x, int be)
++{
++  if (be)
++        return be16toh(x);
++  return le16toh(x);
++}
++
++static uint32_t read32(uint32_t x, int be)
++{
++  if (be)
++        return be32toh(x);
++  return le32toh(x);
++}
++
++static uint64_t read64(uint64_t x, int be)
++{
++  if (be)
++        return be64toh(x);
++  return le64toh(x);
++}
++
+ /* Returns 0 if everything is ok, != 0 in case of error.  */
+ int
+ process_elf_file32 (const char *file_name, const char *lib, int *flag,
+@@ -59,15 +81,17 @@ process_elf_file32 (const char *file_nam
+   elf_header = (Elf32_Ehdr *) file_contents;
+   *osversion = 0;
+ 
+-  if (elf_header->e_type != ET_DYN)
++  be = (elf_header->e_ident[EI_DATA] == ELFDATA2MSB);
++
++  if (read16(elf_header->e_type, be) != ET_DYN)
+     {
+       error (0, 0, _("%s is not a shared object file (Type: %d).\n"), file_name,
+-	     elf_header->e_type);
++	     read16(elf_header->e_type, be));
+       return 1;
+     }
+ 
+   /* Get information from elf program header.  */
+-  elf_pheader = (Elf32_Phdr *) (elf_header->e_phoff + file_contents);
++  elf_pheader = (Elf32_Phdr *) (read32(elf_header->e_phoff, be) + file_contents);
+   check_ptr (elf_pheader);
+ 
+   /* The library is an elf library, now search for soname and
+@@ -79,27 +103,27 @@ process_elf_file32 (const char *file_nam
+   dynamic_size = 0;
+   program_interpreter = NULL;
+   for (i = 0, segment = elf_pheader;
+-       i < elf_header->e_phnum; i++, segment++)
++       i < read16(elf_header->e_phnum, be); i++, segment++)
+     {
+       check_ptr (segment);
+ 
+-      switch (segment->p_type)
++      switch (read32(segment->p_type, be))
+ 	{
+ 	case PT_LOAD:
+ 	  if (loadaddr == (Elf32_Addr) -1)
+-	    loadaddr = segment->p_vaddr - segment->p_offset;
++	    loadaddr = read32(segment->p_vaddr, be) - read32(segment->p_offset, be);
+ 	  break;
+ 
+ 	case PT_DYNAMIC:
+ 	  if (dynamic_addr)
+ 	    error (0, 0, _("more than one dynamic segment\n"));
+ 
+-	  dynamic_addr = segment->p_offset;
+-	  dynamic_size = segment->p_filesz;
++	  dynamic_addr = read32(segment->p_offset, be);
++	  dynamic_size = read32(segment->p_filesz, be);
+ 	  break;
+ 
+ 	case PT_INTERP:
+-	  program_interpreter = (char *) (file_contents + segment->p_offset);
++	  program_interpreter = (char *) (file_contents + read32(segment->p_offset, be));
+ 	  check_ptr (program_interpreter);
+ 
+ 	  /* Check if this is enough to classify the binary.  */
+@@ -113,20 +137,20 @@ process_elf_file32 (const char *file_nam
+ 	  break;
+ 
+ 	case PT_NOTE:
+-	  if (!*osversion && segment->p_filesz >= 32 && segment->p_align >= 4)
++	  if (!*osversion && read32(segment->p_filesz, be) >= 32 && segment->p_align >= 4)
+ 	    {
+ 	      Elf32_Word *abi_note = (Elf32_Word *) (file_contents
+-						     + segment->p_offset);
+-	      Elf32_Addr size = segment->p_filesz;
++						     + read32(segment->p_offset, be));
++	      Elf32_Addr size = read32(segment->p_filesz, be);
+ 
+-	      while (abi_note [0] != 4 || abi_note [1] != 16
+-		     || abi_note [2] != 1
++	      while (read32(abi_note [0], be) != 4 || read32(abi_note [1], be) != 16
++		     || read32(abi_note [2], be) != 1
+ 		     || memcmp (abi_note + 3, "GNU", 4) != 0)
+ 		{
+-#define ROUND(len) (((len) + sizeof (Elf32_Word)) - 1) & -sizeof (Elf32_Word)))
+-		  Elf32_Addr) note_size = 3 * sizeof (Elf32_Word))
+-					 + ROUND (abi_note[0])
+-					 + ROUND (abi_note[1]);
++#define ROUND(len) (((len) + sizeof (Elf32_Word) - 1) & -sizeof (Elf32_Word))
++		  Elf32_Addr note_size = 3 * sizeof (Elf32_Word)
++					 + ROUND (read32(abi_note[0], be))
++					 + ROUND (read32(abi_note[1], be));
+ 
+ 		  if (size - 32 < note_size || note_size == 0)
+ 		    {
+@@ -140,10 +164,10 @@ process_elf_file32 (const char *file_nam
+ 	      if (size == 0)
+ 		break;
+ 
+-	      *osversion = (abi_note [4] << 24) |
+-			   ((abi_note [5] & 0xff) << 16) |
+-			   ((abi_note [6] & 0xff) << 8) |
+-			   (abi_note [7] & 0xff);
++	      *osversion = (read32(abi_note [4], be) << 24) |
++			   ((read32(abi_note [5], be) & 0xff) << 16) |
++			   ((read32(abi_note [6], be) & 0xff) << 8) |
++			   (read32(abi_note [7], be) & 0xff);
+ 	    }
+ 	  break;
+ 
+@@ -167,13 +191,13 @@ process_elf_file32 (const char *file_nam
+ 
+   /* Find the string table.  */
+   dynamic_strings = NULL;
+-  for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL;
++  for (dyn_entry = dynamic_segment; read32(dyn_entry->d_tag, be) != DT_NULL;
+        ++dyn_entry)
+     {
+       check_ptr (dyn_entry);
+-      if (dyn_entry->d_tag == DT_STRTAB)
++      if (read32(dyn_entry->d_tag, be) == DT_STRTAB)
+ 	{
+-	  dynamic_strings = (char *) (file_contents + dyn_entry->d_un.d_val - loadaddr);
++	  dynamic_strings = (char *) (file_contents + read32(dyn_entry->d_un.d_val, be) - loadaddr);
+ 	  check_ptr (dynamic_strings);
+ 	  break;
+ 	}
+@@ -183,15 +207,15 @@ process_elf_file32 (const char *file_nam
+     return 1;
+ 
+   /* Now read the DT_NEEDED and DT_SONAME entries.  */
+-  for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL;
++  for (dyn_entry = dynamic_segment; read32(dyn_entry->d_tag, be) != DT_NULL;
+        ++dyn_entry)
+     {
+-      if (dyn_entry->d_tag == DT_NEEDED || dyn_entry->d_tag == DT_SONAME)
++      if (read32(dyn_entry->d_tag, be) == DT_NEEDED || read32(dyn_entry->d_tag, be) == DT_SONAME)
+ 	{
+-	  char *name = dynamic_strings + dyn_entry->d_un.d_val;
++	  char *name = dynamic_strings + read32(dyn_entry->d_un.d_val, be);
+ 	  check_ptr (name);
+ 
+-	  if (dyn_entry->d_tag == DT_NEEDED)
++	  if (read32(dyn_entry->d_tag, be) == DT_NEEDED)
+ 	    {
+ 
+ 	      if (*flag == FLAG_ELF)
+@@ -208,7 +232,7 @@ process_elf_file32 (const char *file_nam
+ 		}
+ 	    }
+ 
+-	  else if (dyn_entry->d_tag == DT_SONAME)
++	  else if (read32(dyn_entry->d_tag, be) == DT_SONAME)
+ 	    *soname = xstrdup (name);
+ 
+ 	  /* Do we have everything we need?  */
+@@ -246,15 +270,17 @@ process_elf_file64 (const char *file_nam
+   elf_header = (Elf64_Ehdr *) file_contents;
+   *osversion = 0;
+ 
+-  if (elf_header->e_type != ET_DYN)
++  be = (elf_header->e_ident[EI_DATA] == ELFDATA2MSB);
++
++  if (read16(elf_header->e_type, be) != ET_DYN)
+     {
+       error (0, 0, _("%s is not a shared object file (Type: %d).\n"), file_name,
+-	     elf_header->e_type);
++	     read16(elf_header->e_type, be));
+       return 1;
+     }
+ 
+   /* Get information from elf program header.  */
+-  elf_pheader = (Elf64_Phdr *) (elf_header->e_phoff + file_contents);
++  elf_pheader = (Elf64_Phdr *) (read64(elf_header->e_phoff, be) + file_contents);
+   check_ptr (elf_pheader);
+ 
+   /* The library is an elf library, now search for soname and
+@@ -266,27 +292,27 @@ process_elf_file64 (const char *file_nam
+   dynamic_size = 0;
+   program_interpreter = NULL;
+   for (i = 0, segment = elf_pheader;
+-       i < elf_header->e_phnum; i++, segment++)
++       i < read16(elf_header->e_phnum, be); i++, segment++)
+     {
+       check_ptr (segment);
+ 
+-      switch (segment->p_type)
++      switch (read32(segment->p_type, be))
+ 	{
+ 	case PT_LOAD:
+ 	  if (loadaddr == (Elf64_Addr) -1)
+-	    loadaddr = segment->p_vaddr - segment->p_offset;
++	    loadaddr = read64(segment->p_vaddr, be) - read64(segment->p_offset, be);
+ 	  break;
+ 
+ 	case PT_DYNAMIC:
+ 	  if (dynamic_addr)
+ 	    error (0, 0, _("more than one dynamic segment\n"));
+ 
+-	  dynamic_addr = segment->p_offset;
+-	  dynamic_size = segment->p_filesz;
++	  dynamic_addr = read64(segment->p_offset, be);
++	  dynamic_size = read32(segment->p_filesz, be);
+ 	  break;
+ 
+ 	case PT_INTERP:
+-	  program_interpreter = (char *) (file_contents + segment->p_offset);
++	  program_interpreter = (char *) (file_contents + read64(segment->p_offset, be));
+ 	  check_ptr (program_interpreter);
+ 
+ 	  /* Check if this is enough to classify the binary.  */
+@@ -300,20 +326,21 @@ process_elf_file64 (const char *file_nam
+ 	  break;
+ 
+ 	case PT_NOTE:
+-	  if (!*osversion && segment->p_filesz >= 32 && segment->p_align >= 4)
++	  if (!*osversion && read32(segment->p_filesz, be) >= 32 && read32(segment->p_align, be) >= 4)
+ 	    {
+ 	      Elf64_Word *abi_note = (Elf64_Word *) (file_contents
+-						     + segment->p_offset);
+-	      Elf64_Addr size = segment->p_filesz;
++						     + read64(segment->p_offset, be));
++	      Elf64_Addr size = read32(segment->p_filesz, be);
+ 
+-	      while (abi_note [0] != 4 || abi_note [1] != 16
+-		     || abi_note [2] != 1
++	      while (read32(abi_note [0], be) != 4 || read32(abi_note [1], be) != 16
++		     || read32(abi_note [2], be) != 1
+ 		     || memcmp (abi_note + 3, "GNU", 4) != 0)
+ 		{
++#undef ROUND
+ #define ROUND(len) (((len) + sizeof (Elf64_Word) - 1) & -sizeof (Elf64_Word))
+ 		  Elf64_Addr note_size = 3 * sizeof (Elf64_Word)
+-					 + ROUND (abi_note[0])
+-					 + ROUND (abi_note[1]);
++					 + ROUND (read32(abi_note[0], be))
++					 + ROUND (read32(abi_note[1], be));
+ 
+ 		  if (size - 32 < note_size || note_size == 0)
+ 		    {
+@@ -327,10 +354,10 @@ process_elf_file64 (const char *file_nam
+ 	      if (size == 0)
+ 		break;
+ 
+-	      *osversion = (abi_note [4] << 24) |
+-			   ((abi_note [5] & 0xff) << 16) |
+-			   ((abi_note [6] & 0xff) << 8) |
+-			   (abi_note [7] & 0xff);
++	      *osversion = (read32(abi_note [4], be) << 24) |
++			   ((read32(abi_note [5], be) & 0xff) << 16) |
++			   ((read32(abi_note [6], be) & 0xff) << 8) |
++			   (read32(abi_note [7], be) & 0xff);
+ 	    }
+ 	  break;
+ 
+@@ -354,13 +381,13 @@ process_elf_file64 (const char *file_nam
+ 
+   /* Find the string table.  */
+   dynamic_strings = NULL;
+-  for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL;
++  for (dyn_entry = dynamic_segment; read64(dyn_entry->d_tag, be) != DT_NULL;
+        ++dyn_entry)
+     {
+       check_ptr (dyn_entry);
+-      if (dyn_entry->d_tag == DT_STRTAB)
++      if (read64(dyn_entry->d_tag, be) == DT_STRTAB)
+ 	{
+-	  dynamic_strings = (char *) (file_contents + dyn_entry->d_un.d_val - loadaddr);
++	  dynamic_strings = (char *) (file_contents + read64(dyn_entry->d_un.d_val, be) - loadaddr);
+ 	  check_ptr (dynamic_strings);
+ 	  break;
+ 	}
+@@ -370,15 +397,15 @@ process_elf_file64 (const char *file_nam
+     return 1;
+ 
+   /* Now read the DT_NEEDED and DT_SONAME entries.  */
+-  for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL;
++  for (dyn_entry = dynamic_segment; read64(dyn_entry->d_tag, be) != DT_NULL;
+        ++dyn_entry)
+     {
+-      if (dyn_entry->d_tag == DT_NEEDED || dyn_entry->d_tag == DT_SONAME)
++      if (read64(dyn_entry->d_tag, be) == DT_NEEDED || read64(dyn_entry->d_tag, be) == DT_SONAME)
+ 	{
+-	  char *name = dynamic_strings + dyn_entry->d_un.d_val;
++	  char *name = dynamic_strings + read64(dyn_entry->d_un.d_val, be);
+ 	  check_ptr (name);
+ 
+-	  if (dyn_entry->d_tag == DT_NEEDED)
++	  if (read64(dyn_entry->d_tag, be) == DT_NEEDED)
+ 	    {
+ 
+ 	      if (*flag == FLAG_ELF)
+@@ -395,7 +422,7 @@ process_elf_file64 (const char *file_nam
+ 		}
+ 	    }
+ 
+-	  else if (dyn_entry->d_tag == DT_SONAME)
++	  else if (read64(dyn_entry->d_tag, be) == DT_SONAME)
+ 	    *soname = xstrdup (name);
+ 
+ 	  /* Do we have everything we need?  */
+Index: ldconfig-native-2.12.1/readlib.c
+===================================================================
+--- ldconfig-native-2.12.1.orig/readlib.c
++++ ldconfig-native-2.12.1/readlib.c
+@@ -169,7 +169,8 @@ process_file (const char *real_file_name
+       ret = 1;
+     }
+   /* Libraries have to be shared object files.  */
+-  else if (elf_header->e_type != ET_DYN)
++  else if ((elf_header->e_ident[EI_DATA] == ELFDATA2MSB && be16toh(elf_header->e_type) != ET_DYN) ||
++      (elf_header->e_ident[EI_DATA] == ELFDATA2LSB && le16toh(elf_header->e_type) != ET_DYN))
+     ret = 1;
+   else if (process_elf_file (file_name, lib, flag, osversion, soname,
+ 			     file_contents, statbuf.st_size))
+Index: ldconfig-native-2.12.1/cache.c
+===================================================================
+--- ldconfig-native-2.12.1.orig/cache.c
++++ ldconfig-native-2.12.1/cache.c
+@@ -39,6 +39,29 @@
+ # define N_(msgid)  msgid
+ #define _(msg) msg
+ 
++extern int be;
++
++static uint16_t write16(uint16_t x, int be)
++{
++  if (be)
++        return htobe16(x);
++  return htole16(x);
++}
++
++static uint32_t write32(uint32_t x, int be)
++{
++  if (be)
++        return htobe32(x);
++  return htole32(x);
++}
++
++static uint64_t write64(uint64_t x, int be)
++{
++  if (be)
++        return htobe64(x);
++  return htole64(x);
++}
++
+ struct cache_entry
+ {
+   char *lib;			/* Library name.  */
+@@ -279,7 +302,12 @@ save_cache (const char *cache_name)
+   /* Number of normal cache entries.  */
+   int cache_entry_old_count = 0;
+ 
+-  for (entry = entries; entry != NULL; entry = entry->next)
++    if (be)
++      printf("saving cache in big endian encoding\n");
++    else
++      printf("saving cache in little endian encoding\n");
++
++    for (entry = entries; entry != NULL; entry = entry->next)
+     {
+       /* Account the final NULs.  */
+       total_strlen += strlen (entry->lib) + strlen (entry->path) + 2;
+@@ -310,7 +338,7 @@ save_cache (const char *cache_name)
+       memset (file_entries, '\0', sizeof (struct cache_file));
+       memcpy (file_entries->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1);
+ 
+-      file_entries->nlibs = cache_entry_old_count;
++      file_entries->nlibs = write32(cache_entry_old_count, be);
+     }
+ 
+   struct cache_file_new *file_entries_new = NULL;
+@@ -330,8 +358,8 @@ save_cache (const char *cache_name)
+       memcpy (file_entries_new->version, CACHE_VERSION,
+ 	      sizeof CACHE_VERSION - 1);
+ 
+-      file_entries_new->nlibs = cache_entry_count;
+-      file_entries_new->len_strings = total_strlen;
++      file_entries_new->nlibs = write32(cache_entry_count, be);
++      file_entries_new->len_strings = write32(total_strlen, be);
+     }
+ 
+   /* Pad for alignment of cache_file_new.  */
+@@ -358,9 +386,9 @@ save_cache (const char *cache_name)
+       /* First the library.  */
+       if (opt_format != 2 && entry->hwcap == 0)
+ 	{
+-	  file_entries->libs[idx_old].flags = entry->flags;
++	  file_entries->libs[idx_old].flags = write32(entry->flags, be);
+ 	  /* XXX: Actually we can optimize here and remove duplicates.  */
+-	  file_entries->libs[idx_old].key = str_offset + pad;
++	  file_entries->libs[idx_old].key = write32(str_offset + pad, be);
+ 	}
+       if (opt_format != 0)
+ 	{
+@@ -368,10 +396,10 @@ save_cache (const char *cache_name)
+ 	     not doing so makes the code easier, the string table
+ 	     always begins at the beginning of the the new cache
+ 	     struct.  */
+-	  file_entries_new->libs[idx_new].flags = entry->flags;
+-	  file_entries_new->libs[idx_new].osversion = entry->osversion;
+-	  file_entries_new->libs[idx_new].hwcap = entry->hwcap;
+-	  file_entries_new->libs[idx_new].key = str_offset;
++	  file_entries_new->libs[idx_new].flags = write32(entry->flags, be);
++	  file_entries_new->libs[idx_new].osversion = write32(entry->osversion, be);
++	  file_entries_new->libs[idx_new].hwcap = write64(entry->hwcap, be);
++	  file_entries_new->libs[idx_new].key = write32(str_offset, be);
+ 	}
+ 
+       size_t len = strlen (entry->lib) + 1;
+@@ -379,9 +407,9 @@ save_cache (const char *cache_name)
+       str_offset += len;
+       /* Then the path.  */
+       if (opt_format != 2 && entry->hwcap == 0)
+-	file_entries->libs[idx_old].value = str_offset + pad;
++	file_entries->libs[idx_old].value = write32(str_offset + pad, be);
+       if (opt_format != 0)
+-	file_entries_new->libs[idx_new].value = str_offset;
++	file_entries_new->libs[idx_new].value = write32(str_offset, be);
+       len = strlen (entry->path) + 1;
+       str = mempcpy (str, entry->path, len);
+       str_offset += len;

+ 47 - 0
recipes-core/glibc/ldconfig-native-2.12.1/endian-ness_handling_fix.patch

@@ -0,0 +1,47 @@
+Upstream-Status: Inappropriate [embedded specific]
+
+Fix problem during parsing of ELF headers for 64bit on big-endian.
+Some header fields were read with wrong size.
+
+2014/10/24
+Par Olsson <Par.Olsson@windriver.com>
+Shan Hai <shan.hai@windriver.com>
+
+diff --git a/readelflib.c b/readelflib.c
+index 3f5b25b..0bf0de3 100644
+--- a/readelflib.c
++++ b/readelflib.c
+@@ -261,8 +261,8 @@ process_elf_file64 (const char *file_name, const char *lib, int *flag,
+   int i;
+   unsigned int j;
+   Elf64_Addr loadaddr;
+-  unsigned int dynamic_addr;
+-  size_t dynamic_size;
++  Elf64_Addr dynamic_addr;
++  Elf64_Xword dynamic_size;
+   char *program_interpreter;
+ 
+   Elf64_Ehdr *elf_header;
+@@ -311,7 +311,7 @@ process_elf_file64 (const char *file_name, const char *lib, int *flag,
+ 	    error (0, 0, _("more than one dynamic segment\n"));
+ 
+ 	  dynamic_addr = read64(segment->p_offset, be);
+-	  dynamic_size = read32(segment->p_filesz, be);
++	  dynamic_size = read64(segment->p_filesz, be);
+ 	  break;
+ 
+ 	case PT_INTERP:
+@@ -329,11 +329,11 @@ process_elf_file64 (const char *file_name, const char *lib, int *flag,
+ 	  break;
+ 
+ 	case PT_NOTE:
+-	  if (!*osversion && read32(segment->p_filesz, be) >= 32 && read32(segment->p_align, be) >= 4)
++	  if (!*osversion && read64(segment->p_filesz, be) >= 32 && read64(segment->p_align, be) >= 4)
+ 	    {
+ 	      Elf64_Word *abi_note = (Elf64_Word *) (file_contents
+ 						     + read64(segment->p_offset, be));
+-	      Elf64_Addr size = read32(segment->p_filesz, be);
++	      Elf64_Xword size = read64(segment->p_filesz, be);
+ 
+ 	      while (read32(abi_note [0], be) != 4 || read32(abi_note [1], be) != 16
+ 		     || read32(abi_note [2], be) != 1

+ 113 - 0
recipes-core/glibc/ldconfig-native-2.12.1/endianess-header.patch

@@ -0,0 +1,113 @@
+Upstream-Status: Inappropriate [fix poky patch]
+
+This patch fixes build issues with a previous endian-ness_handling.patch on
+distros that don't have macros referenced
+
+7/20/2011
+Matthew McClintock <msm@freescale.com>
+
+diff -purN ldconfig-native-2.12.1.orig/endian_extra.h ldconfig-native-2.12.1/endian_extra.h
+--- ldconfig-native-2.12.1.orig/endian_extra.h	1969-12-31 18:00:00.000000000 -0600
++++ ldconfig-native-2.12.1/endian_extra.h	2011-07-19 18:09:14.323048417 -0500
+@@ -0,0 +1,64 @@
++/* Copyright (C) 1992, 1996, 1997, 2000, 2008 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, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++#include <endian.h>
++
++#ifndef	_ENDIAN_EXTRA_H
++#define	_ENDIAN_EXTRA_H	1
++
++/* Don't redefine these macros if they already exist */
++#ifndef htobe16
++#ifdef __USE_BSD
++/* Conversion interfaces.  */
++# include <byteswap.h>
++
++# if __BYTE_ORDER == __LITTLE_ENDIAN
++#  define htobe16(x) __bswap_16 (x)
++#  define htole16(x) (x)
++#  define be16toh(x) __bswap_16 (x)
++#  define le16toh(x) (x)
++
++#  define htobe32(x) __bswap_32 (x)
++#  define htole32(x) (x)
++#  define be32toh(x) __bswap_32 (x)
++#  define le32toh(x) (x)
++
++#  define htobe64(x) __bswap_64 (x)
++#  define htole64(x) (x)
++#  define be64toh(x) __bswap_64 (x)
++#  define le64toh(x) (x)
++# else
++#  define htobe16(x) (x)
++#  define htole16(x) __bswap_16 (x)
++#  define be16toh(x) (x)
++#  define le16toh(x) __bswap_16 (x)
++
++#  define htobe32(x) (x)
++#  define htole32(x) __bswap_32 (x)
++#  define be32toh(x) (x)
++#  define le32toh(x) __bswap_32 (x)
++
++#  define htobe64(x) (x)
++#  define htole64(x) __bswap_64 (x)
++#  define be64toh(x) (x)
++#  define le64toh(x) __bswap_64 (x)
++# endif
++#endif
++#endif
++
++#endif	/* endian_extra.h */
+diff -purN ldconfig-native-2.12.1.orig/cache.c ldconfig-native-2.12.1/cache.c
+--- ldconfig-native-2.12.1.orig/cache.c	2011-07-19 18:21:28.347041301 -0500
++++ ldconfig-native-2.12.1/cache.c	2011-07-19 18:22:54.118048064 -0500
+@@ -39,6 +39,8 @@
+ # define N_(msgid)  msgid
+ #define _(msg) msg
+ 
++#include "endian_extra.h"
++
+ extern int be;
+ 
+ static uint16_t write16(uint16_t x, int be)
+diff -purN ldconfig-native-2.12.1.orig/readelflib.c ldconfig-native-2.12.1/readelflib.c
+--- ldconfig-native-2.12.1.orig/readelflib.c	2011-07-19 18:21:28.346041593 -0500
++++ ldconfig-native-2.12.1/readelflib.c	2011-07-19 18:23:05.324059875 -0500
+@@ -25,6 +25,9 @@
+ 
+ /* check_ptr checks that a pointer is in the mmaped file and doesn't
+    point outside it.  */
++
++#include "endian_extra.h"
++
+ #undef check_ptr
+ #define check_ptr(ptr)						\
+ do								\
+diff -purN ldconfig-native-2.12.1.orig/readlib.c ldconfig-native-2.12.1/readlib.c
+--- ldconfig-native-2.12.1.orig/readlib.c	2011-07-19 18:21:28.346041593 -0500
++++ ldconfig-native-2.12.1/readlib.c	2011-07-19 18:23:23.877046210 -0500
+@@ -40,6 +40,8 @@
+ 
+ #include "ldconfig.h"
+ 
++#include "endian_extra.h"
++
+ #define _(msg) msg
+ 
+ #define Elf32_CLASS ELFCLASS32

+ 24 - 0
recipes-core/glibc/ldconfig-native-2.12.1/flag_fix.patch

@@ -0,0 +1,24 @@
+Upstream-Status: Inappropriate [embedded specific]
+
+The native version of ldconfig was using native definition of LD_SO (i.e. 
+ld-linux-x86-64.so.2 ) which is not correct for doing the cross ldconfig.
+This was causing libc.so on the target marked as ELF lib rather than 
+FLAG_ELF_LIBC6 in the ld.so.cache.
+
+Nitin A Kamble <nitin.a.kamble@intel.com> 2011/04/4
+
+Index: ldconfig-native-2.12.1/readlib.c
+===================================================================
+--- ldconfig-native-2.12.1.orig/readlib.c
++++ ldconfig-native-2.12.1/readlib.c
+@@ -51,6 +51,10 @@ struct known_names
+   int flag;
+ };
+ 
++/* don't use host's definition of LD_SO */
++#undef LD_SO 
++#define LD_SO "ld.so.1"
++
+ static struct known_names interpreters[] =
+ {
+   { "/lib/" LD_SO, FLAG_ELF_LIBC6 },

+ 37 - 0
recipes-core/glibc/ldconfig-native-2.12.1/ldconfig-default-to-all-multilib-dirs.patch

@@ -0,0 +1,37 @@
+Upstream-Status: Inappropriate [embedded specific]
+
+make ldconfig default to both /lib+/usr/lib, /lib32+/usr/lib32 and
+/lib64+/usr/lib64 on bi-ABI architectures.
+
+---
+ ldconfig.c |   10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff -urpN a/ldconfig.c b/ldconfig.c
+--- a/ldconfig.c
++++ b/ldconfig.c
+@@ -52,7 +52,11 @@
+ 
+ #define SYSCONFDIR "/etc"
+ #define LIBDIR "/usr/lib"
++#define LIBDIR32 "/usr/lib32"
++#define LIBDIR64 "/usr/lib64"
+ #define SLIBDIR "/lib"
++#define SLIBDIR32 "/lib32"
++#define SLIBDIR64 "/lib64"
+ # define N_(msgid)  msgid
+ #define _(msg) msg
+ 
+@@ -1373,6 +1377,12 @@ main (int argc, char **argv)
+       add_system_dir (SLIBDIR);
+       if (strcmp (SLIBDIR, LIBDIR))
+ 	add_system_dir (LIBDIR);
++      add_system_dir (SLIBDIR32);
++      if (strcmp (SLIBDIR32, LIBDIR32))
++	add_system_dir (LIBDIR32);
++      add_system_dir (SLIBDIR64);
++      if (strcmp (SLIBDIR64, LIBDIR64))
++	add_system_dir (LIBDIR64);
+     }
+ 
+   const char *aux_cache_file = _PATH_LDCONFIG_AUX_CACHE;

BIN
recipes-core/glibc/ldconfig-native-2.12.1/ldconfig-native-2.12.1.tar.bz2


+ 471 - 0
recipes-core/glibc/ldconfig-native-2.12.1/ldconfig.patch

@@ -0,0 +1,471 @@
+Upstream-Status: Inappropriate [embedded specific]
+
+enable standalone building of ldconfig
+
+---
+ cache.c        |   11 +-
+ chroot_canon.c |    7 +
+ dl-cache.c     |  235 ---------------------------------------------------------
+ dl-cache.h     |    3 
+ ldconfig.c     |   27 ++++--
+ readlib.c      |    7 +
+ xstrdup.c      |   11 --
+ 7 files changed, 45 insertions(+), 256 deletions(-)
+
+Index: ldconfig-native-2.12.1/cache.c
+===================================================================
+--- ldconfig-native-2.12.1.orig/cache.c
++++ ldconfig-native-2.12.1/cache.c
+@@ -16,6 +16,9 @@
+    along with this program; if not, write to the Free Software Foundation,
+    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+ 
++#define _LARGEFILE64_SOURCE
++#define _GNU_SOURCE
++
+ #include <errno.h>
+ #include <error.h>
+ #include <dirent.h>
+@@ -31,8 +34,10 @@
+ #include <sys/stat.h>
+ #include <sys/types.h>
+ 
+-#include <ldconfig.h>
+-#include <dl-cache.h>
++#include "ldconfig.h"
++#include "dl-cache.h"
++# define N_(msgid)  msgid
++#define _(msg) msg
+ 
+ struct cache_entry
+ {
+Index: ldconfig-native-2.12.1/chroot_canon.c
+===================================================================
+--- ldconfig-native-2.12.1.orig/chroot_canon.c
++++ ldconfig-native-2.12.1/chroot_canon.c
+@@ -17,6 +17,9 @@
+    along with this program; if not, write to the Free Software Foundation,
+    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+ 
++#define _LARGEFILE64_SOURCE
++#define _GNU_SOURCE
++
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+@@ -27,7 +30,9 @@
+ #include <stddef.h>
+ #include <stdint.h>
+ 
+-#include <ldconfig.h>
++#include "ldconfig.h"
++
++#define __set_errno(Val) errno = (Val)
+ 
+ #ifndef PATH_MAX
+ #define PATH_MAX 1024
+Index: ldconfig-native-2.12.1/dl-cache.c
+===================================================================
+--- ldconfig-native-2.12.1.orig/dl-cache.c
++++ ldconfig-native-2.12.1/dl-cache.c
+@@ -20,12 +20,12 @@
+ 
+ #include <assert.h>
+ #include <unistd.h>
+-#include <ldsodefs.h>
++//#include "ldsodefs.h"
+ #include <sys/mman.h>
+ #include <dl-cache.h>
+ #include <dl-procinfo.h>
+ 
+-#include <stdio-common/_itoa.h>
++//#include "_itoa.h"
+ 
+ #ifndef _DL_PLATFORMS_COUNT
+ # define _DL_PLATFORMS_COUNT 0
+@@ -39,103 +39,7 @@ static size_t cachesize;
+ /* 1 if cache_data + PTR points into the cache.  */
+ #define _dl_cache_verify_ptr(ptr) (ptr < cache_data_size)
+ 
+-#define SEARCH_CACHE(cache) \
+-/* We use binary search since the table is sorted in the cache file.	      \
+-   The first matching entry in the table is returned.			      \
+-   It is important to use the same algorithm as used while generating	      \
+-   the cache file.  */							      \
+-do									      \
+-  {									      \
+-    left = 0;								      \
+-    right = cache->nlibs - 1;						      \
+-									      \
+-    while (left <= right)						      \
+-      {									      \
+-	__typeof__ (cache->libs[0].key) key;				      \
+-									      \
+-	middle = (left + right) / 2;					      \
+-									      \
+-	key = cache->libs[middle].key;					      \
+-									      \
+-	/* Make sure string table indices are not bogus before using	      \
+-	   them.  */							      \
+-	if (! _dl_cache_verify_ptr (key))				      \
+-	  {								      \
+-	    cmpres = 1;							      \
+-	    break;							      \
+-	  }								      \
+-									      \
+-	/* Actually compare the entry with the key.  */			      \
+-	cmpres = _dl_cache_libcmp (name, cache_data + key);		      \
+-	if (__builtin_expect (cmpres == 0, 0))				      \
+-	  {								      \
+-	    /* Found it.  LEFT now marks the last entry for which we	      \
+-	       know the name is correct.  */				      \
+-	    left = middle;						      \
+-									      \
+-	    /* There might be entries with this name before the one we	      \
+-	       found.  So we have to find the beginning.  */		      \
+-	    while (middle > 0)						      \
+-	      {								      \
+-		__typeof__ (cache->libs[0].key) key;			      \
+-									      \
+-		key = cache->libs[middle - 1].key;			      \
+-		/* Make sure string table indices are not bogus before	      \
+-		   using them.  */					      \
+-		if (! _dl_cache_verify_ptr (key)			      \
+-		    /* Actually compare the entry.  */			      \
+-		    || _dl_cache_libcmp (name, cache_data + key) != 0)	      \
+-		  break;						      \
+-		--middle;						      \
+-	      }								      \
+-									      \
+-	    do								      \
+-	      {								      \
+-		int flags;						      \
+-		__typeof__ (cache->libs[0]) *lib = &cache->libs[middle];      \
+-									      \
+-		/* Only perform the name test if necessary.  */		      \
+-		if (middle > left					      \
+-		    /* We haven't seen this string so far.  Test whether the  \
+-		       index is ok and whether the name matches.  Otherwise   \
+-		       we are done.  */					      \
+-		    && (! _dl_cache_verify_ptr (lib->key)		      \
+-			|| (_dl_cache_libcmp (name, cache_data + lib->key)    \
+-			    != 0)))					      \
+-		  break;						      \
+-									      \
+-		flags = lib->flags;					      \
+-		if (_dl_cache_check_flags (flags)			      \
+-		    && _dl_cache_verify_ptr (lib->value))		      \
+-		  {							      \
+-		    if (best == NULL || flags == GLRO(dl_correct_cache_id))   \
+-		      {							      \
+-			HWCAP_CHECK;					      \
+-			best = cache_data + lib->value;			      \
+-									      \
+-			if (flags == GLRO(dl_correct_cache_id))		      \
+-			  /* We've found an exact match for the shared	      \
+-			     object and no general `ELF' release.  Stop	      \
+-			     searching.  */				      \
+-			  break;					      \
+-		      }							      \
+-		  }							      \
+-	      }								      \
+-	    while (++middle <= right);					      \
+-	    break;							      \
+-	}								      \
+-									      \
+-	if (cmpres < 0)							      \
+-	  left = middle + 1;						      \
+-	else								      \
+-	  right = middle - 1;						      \
+-      }									      \
+-  }									      \
+-while (0)
+-
+-
+ int
+-internal_function
+ _dl_cache_libcmp (const char *p1, const char *p2)
+ {
+   while (*p1 != '\0')
+@@ -172,139 +76,3 @@ _dl_cache_libcmp (const char *p1, const 
+     }
+   return *p1 - *p2;
+ }
+-
+-
+-/* Look up NAME in ld.so.cache and return the file name stored there,
+-   or null if none is found.  */
+-
+-const char *
+-internal_function
+-_dl_load_cache_lookup (const char *name)
+-{
+-  int left, right, middle;
+-  int cmpres;
+-  const char *cache_data;
+-  uint32_t cache_data_size;
+-  const char *best;
+-
+-  /* Print a message if the loading of libs is traced.  */
+-  if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_LIBS, 0))
+-    _dl_debug_printf (" search cache=%s\n", LD_SO_CACHE);
+-
+-  if (cache == NULL)
+-    {
+-      /* Read the contents of the file.  */
+-      void *file = _dl_sysdep_read_whole_file (LD_SO_CACHE, &cachesize,
+-					       PROT_READ);
+-
+-      /* We can handle three different cache file formats here:
+-	 - the old libc5/glibc2.0/2.1 format
+-	 - the old format with the new format in it
+-	 - only the new format
+-	 The following checks if the cache contains any of these formats.  */
+-      if (file != MAP_FAILED && cachesize > sizeof *cache
+-	  && memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0)
+-	{
+-	  size_t offset;
+-	  /* Looks ok.  */
+-	  cache = file;
+-
+-	  /* Check for new version.  */
+-	  offset = ALIGN_CACHE (sizeof (struct cache_file)
+-				+ cache->nlibs * sizeof (struct file_entry));
+-
+-	  cache_new = (struct cache_file_new *) ((void *) cache + offset);
+-	  if (cachesize < (offset + sizeof (struct cache_file_new))
+-	      || memcmp (cache_new->magic, CACHEMAGIC_VERSION_NEW,
+-			 sizeof CACHEMAGIC_VERSION_NEW - 1) != 0)
+-	    cache_new = (void *) -1;
+-	}
+-      else if (file != MAP_FAILED && cachesize > sizeof *cache_new
+-	       && memcmp (file, CACHEMAGIC_VERSION_NEW,
+-			  sizeof CACHEMAGIC_VERSION_NEW - 1) == 0)
+-	{
+-	  cache_new = file;
+-	  cache = file;
+-	}
+-      else
+-	{
+-	  if (file != MAP_FAILED)
+-	    __munmap (file, cachesize);
+-	  cache = (void *) -1;
+-	}
+-
+-      assert (cache != NULL);
+-    }
+-
+-  if (cache == (void *) -1)
+-    /* Previously looked for the cache file and didn't find it.  */
+-    return NULL;
+-
+-  best = NULL;
+-
+-  if (cache_new != (void *) -1)
+-    {
+-      uint64_t platform;
+-
+-      /* This is where the strings start.  */
+-      cache_data = (const char *) cache_new;
+-
+-      /* Now we can compute how large the string table is.  */
+-      cache_data_size = (const char *) cache + cachesize - cache_data;
+-
+-      platform = _dl_string_platform (GLRO(dl_platform));
+-      if (platform != (uint64_t) -1)
+-	platform = 1ULL << platform;
+-
+-#define _DL_HWCAP_TLS_MASK (1LL << 63)
+-      uint64_t hwcap_exclude = ~((GLRO(dl_hwcap) & GLRO(dl_hwcap_mask))
+-				 | _DL_HWCAP_PLATFORM | _DL_HWCAP_TLS_MASK);
+-
+-      /* Only accept hwcap if it's for the right platform.  */
+-#define HWCAP_CHECK \
+-      if (lib->hwcap & hwcap_exclude)					      \
+-	continue;							      \
+-      if (GLRO(dl_osversion) && lib->osversion > GLRO(dl_osversion))	      \
+-	continue;							      \
+-      if (_DL_PLATFORMS_COUNT						      \
+-	  && (lib->hwcap & _DL_HWCAP_PLATFORM) != 0			      \
+-	  && (lib->hwcap & _DL_HWCAP_PLATFORM) != platform)		      \
+-	continue
+-      SEARCH_CACHE (cache_new);
+-    }
+-  else
+-    {
+-      /* This is where the strings start.  */
+-      cache_data = (const char *) &cache->libs[cache->nlibs];
+-
+-      /* Now we can compute how large the string table is.  */
+-      cache_data_size = (const char *) cache + cachesize - cache_data;
+-
+-#undef HWCAP_CHECK
+-#define HWCAP_CHECK do {} while (0)
+-      SEARCH_CACHE (cache);
+-    }
+-
+-  /* Print our result if wanted.  */
+-  if (__builtin_expect (GLRO_dl_debug_mask & DL_DEBUG_LIBS, 0)
+-      && best != NULL)
+-    _dl_debug_printf ("  trying file=%s\n", best);
+-
+-  return best;
+-}
+-
+-#ifndef MAP_COPY
+-/* If the system does not support MAP_COPY we cannot leave the file open
+-   all the time since this would create problems when the file is replaced.
+-   Therefore we provide this function to close the file and open it again
+-   once needed.  */
+-void
+-_dl_unload_cache (void)
+-{
+-  if (cache != NULL && cache != (struct cache_file *) -1)
+-    {
+-      __munmap (cache, cachesize);
+-      cache = NULL;
+-    }
+-}
+-#endif
+Index: ldconfig-native-2.12.1/dl-cache.h
+===================================================================
+--- ldconfig-native-2.12.1.orig/dl-cache.h
++++ ldconfig-native-2.12.1/dl-cache.h
+@@ -101,5 +101,4 @@ struct cache_file_new
+ (((addr) + __alignof__ (struct cache_file_new) -1)	\
+  & (~(__alignof__ (struct cache_file_new) - 1)))
+ 
+-extern int _dl_cache_libcmp (const char *p1, const char *p2)
+-     internal_function;
++extern int _dl_cache_libcmp (const char *p1, const char *p2);
+Index: ldconfig-native-2.12.1/ldconfig.c
+===================================================================
+--- ldconfig-native-2.12.1.orig/ldconfig.c
++++ ldconfig-native-2.12.1/ldconfig.c
+@@ -16,6 +16,9 @@
+    along with this program; if not, write to the Free Software Foundation,
+    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+ 
++#define _LARGEFILE64_SOURCE
++#define _GNU_SOURCE
++
+ #define PROCINFO_CLASS static
+ #include <alloca.h>
+ #include <argp.h>
+@@ -39,10 +42,20 @@
+ #include <glob.h>
+ #include <libgen.h>
+ 
+-#include <ldconfig.h>
+-#include <dl-cache.h>
++#include "ldconfig.h"
++#include "dl-cache.h"
++
++#include "dl-procinfo.h"
++
++#include "argp.h"
++
++
++#define SYSCONFDIR "/etc"
++#define LIBDIR "/usr/lib"
++#define SLIBDIR "/lib"
++# define N_(msgid)  msgid
++#define _(msg) msg
+ 
+-#include <dl-procinfo.h>
+ 
+ #ifdef _DL_FIRST_PLATFORM
+ # define _DL_FIRST_EXTRA (_DL_FIRST_PLATFORM + _DL_PLATFORMS_COUNT)
+@@ -55,7 +68,7 @@
+ #endif
+ 
+ /* Get libc version number.  */
+-#include <version.h>
++#include "version.h"
+ 
+ #define PACKAGE _libc_intl_domainname
+ 
+@@ -152,8 +165,8 @@ static const struct argp_option options[
+   { NULL, 0, NULL, 0, NULL, 0 }
+ };
+ 
+-#define PROCINFO_CLASS static
+-#include <dl-procinfo.c>
++//#define PROCINFO_CLASS static
++//#include <dl-procinfo.c>
+ 
+ /* Short description of program.  */
+ static const char doc[] = N_("Configure Dynamic Linker Run Time Bindings.");
+@@ -291,6 +304,7 @@ parse_opt (int key, char *arg, struct ar
+   return 0;
+ }
+ 
++#define REPORT_BUGS_TO "mailing list : poky@lists.yoctoproject.org"
+ /* Print bug-reporting information in the help message.  */
+ static char *
+ more_help (int key, const char *text, void *input)
+@@ -315,7 +329,7 @@ For bug reporting instructions, please s
+ static void
+ print_version (FILE *stream, struct argp_state *state)
+ {
+-  fprintf (stream, "ldconfig %s%s\n", PKGVERSION, VERSION);
++  fprintf (stream, "ldconfig (Hacked Poky Version)\n");
+   fprintf (stream, gettext ("\
+ Copyright (C) %s Free Software Foundation, Inc.\n\
+ This is free software; see the source for copying conditions.  There is NO\n\
+@@ -1233,6 +1247,7 @@ set_hwcap (void)
+     hwcap_mask = strtoul (mask, NULL, 0);
+ }
+ 
++const char _libc_intl_domainname[] = "libc";
+ 
+ int
+ main (int argc, char **argv)
+Index: ldconfig-native-2.12.1/readlib.c
+===================================================================
+--- ldconfig-native-2.12.1.orig/readlib.c
++++ ldconfig-native-2.12.1/readlib.c
+@@ -22,6 +22,9 @@
+    development version.  Besides the simplification, it has also been
+    modified to read some other file formats.  */
+ 
++#define _LARGEFILE64_SOURCE
++#define _GNU_SOURCE
++
+ #include <a.out.h>
+ #include <elf.h>
+ #include <error.h>
+@@ -35,7 +38,9 @@
+ #include <sys/stat.h>
+ #include <gnu/lib-names.h>
+ 
+-#include <ldconfig.h>
++#include "ldconfig.h"
++
++#define _(msg) msg
+ 
+ #define Elf32_CLASS ELFCLASS32
+ #define Elf64_CLASS ELFCLASS64
+Index: ldconfig-native-2.12.1/xstrdup.c
+===================================================================
+--- ldconfig-native-2.12.1.orig/xstrdup.c
++++ ldconfig-native-2.12.1/xstrdup.c
+@@ -16,15 +16,10 @@
+    along with this program; if not, write to the Free Software Foundation,
+    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+ 
+-#ifdef HAVE_CONFIG_H
+-# include <config.h>
+-#endif
++#define _GNU_SOURCE
++
++#include <string.h>
+ 
+-#if defined STDC_HEADERS || defined HAVE_STRING_H || _LIBC
+-# include <string.h>
+-#else
+-# include <strings.h>
+-#endif
+ void *xmalloc (size_t n) __THROW;
+ char *xstrdup (char *string) __THROW;
+ 

+ 36 - 0
recipes-core/glibc/ldconfig-native-2.12.1/ldconfig_aux-cache_path_fix.patch

@@ -0,0 +1,36 @@
+Upstream-Status: Pending
+
+Coming from this bug: http://sourceware.org/bugzilla/show_bug.cgi?id=11149
+
+Nitin A Kamble <nitin.a.kamble@intel.com>2011/03/29
+
+--- ldconfig-native-2.12.1.orig/ldconfig.c	
++++ ldconfig-native-2.12.1/ldconfig.c	
+@@ -1359,14 +1359,9 @@ main (int argc, char **argv)
+ 
+   const char *aux_cache_file = _PATH_LDCONFIG_AUX_CACHE;
+   if (opt_chroot)
+-    {
+-      aux_cache_file = chroot_canon (opt_chroot, aux_cache_file);
+-      if (aux_cache_file == NULL)
+-	error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"),
+-	       _PATH_LDCONFIG_AUX_CACHE);
+-    }
++    aux_cache_file = chroot_canon (opt_chroot, aux_cache_file);
+ 
+-  if (! opt_ignore_aux_cache)
++  if (! opt_ignore_aux_cache && aux_cache_file)
+     load_aux_cache (aux_cache_file);
+   else
+     init_aux_cache ();
+@@ -1376,7 +1371,8 @@ main (int argc, char **argv)
+   if (opt_build_cache)
+     {
+       save_cache (cache_file);
+-      save_aux_cache (aux_cache_file);
++      if (aux_cache_file)
++        save_aux_cache (aux_cache_file);
+     }
+ 
+   return 0;
+

+ 19 - 0
recipes-core/glibc/ldconfig-native-2.12.1/no-aux-cache.patch

@@ -0,0 +1,19 @@
+The ldconfig auxiliary cache is a dictionary where the keys include inode, so
+there is no point in writing these files on the build host. 
+
+Upstream-Status: Inappropriate
+Signed-off-by: Ross Burton <ross.burton@arm.com>
+
+diff --git a/ldconfig.c b/ldconfig.c
+index 2c4eb57..2d6dc92 100644
+--- a/ldconfig.c
++++ b/ldconfig.c
+@@ -1399,8 +1399,6 @@ main (int argc, char **argv)
+   if (opt_build_cache)
+     {
+       save_cache (cache_file);
+-      if (aux_cache_file)
+-        save_aux_cache (aux_cache_file);
+     }
+ 
+   return 0;

+ 36 - 0
recipes-core/glibc/ldconfig-native_2.12.1.bb

@@ -0,0 +1,36 @@
+SUMMARY = "A standalone native ldconfig build"
+
+LICENSE = "GPLv2+"
+
+LIC_FILES_CHKSUM = "file://${S}/ldconfig.c;endline=17;md5=1d15f20937c055cb5de2329a4c054399"
+
+SRC_URI = "file://ldconfig-native-2.12.1.tar.bz2 \
+           file://ldconfig.patch \
+           file://ldconfig_aux-cache_path_fix.patch \
+           file://32and64bit.patch \
+           file://endian-ness_handling.patch \
+           file://flag_fix.patch \
+           file://endianess-header.patch \
+           file://ldconfig-default-to-all-multilib-dirs.patch \
+           file://endian-ness_handling_fix.patch \
+           file://add-64-bit-flag-for-ELF64-entries.patch \
+           file://no-aux-cache.patch \
+           file://add-riscv-support.patch \
+"
+
+PR = "r2"
+
+FILESEXTRAPATHS =. "${FILE_DIRNAME}/${P}:"
+
+inherit native
+
+S = "${WORKDIR}/${PN}-${PV}"
+
+do_compile () {
+	$CC ldconfig.c -std=gnu99 chroot_canon.c xmalloc.c xstrdup.c cache.c readlib.c  -I. dl-cache.c -o ldconfig
+}
+
+do_install () {
+	install -d ${D}/${bindir}/
+	install ldconfig ${D}/${bindir}/
+}

Some files were not shown because too many files changed in this diff